]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fold-const-call.cc
inter-procedural value range propagation
[thirdparty/gcc.git] / gcc / fold-const-call.cc
CommitLineData
5c1a2e63 1/* Constant folding for calls to built-in and internal functions.
aeee4812 2 Copyright (C) 1988-2023 Free Software Foundation, Inc.
5c1a2e63
RS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "realmpfr.h"
24#include "tree.h"
25#include "stor-layout.h"
26#include "options.h"
df838ef0 27#include "fold-const.h"
5c1a2e63 28#include "fold-const-call.h"
d7ebef06 29#include "case-cfn-macros.h"
7383cb56 30#include "tm.h" /* For C[LT]Z_DEFINED_VALUE_AT_ZERO. */
488c6247 31#include "builtins.h"
4adbcdb4 32#include "gimple-expr.h"
d8fcab68 33#include "tree-vector-builder.h"
5c1a2e63
RS
34
35/* Functions that test for certain constant types, abstracting away the
36 decision about whether to check for overflow. */
37
38static inline bool
39integer_cst_p (tree t)
40{
41 return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
42}
43
44static inline bool
45real_cst_p (tree t)
46{
47 return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
48}
49
50static inline bool
51complex_cst_p (tree t)
52{
53 return TREE_CODE (t) == COMPLEX_CST;
54}
55
b7a0507a 56/* Return true if ARG is a size_type_node constant.
df838ef0
RS
57 Store it in *SIZE_OUT if so. */
58
59static inline bool
b7a0507a 60size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
df838ef0 61{
4adbcdb4
ML
62 if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 && integer_cst_p (t)
b7a0507a 64 && tree_fits_uhwi_p (t))
df838ef0
RS
65 {
66 *size_out = tree_to_uhwi (t);
67 return true;
68 }
69 return false;
70}
71
72/* RES is the result of a comparison in which < 0 means "less", 0 means
73 "equal" and > 0 means "more". Canonicalize it to -1, 0 or 1 and
74 return it in type TYPE. */
75
a918bfbf 76tree
df838ef0
RS
77build_cmp_result (tree type, int res)
78{
79 return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0);
80}
81
5c1a2e63
RS
82/* M is the result of trying to constant-fold an expression (starting
83 with clear MPFR flags) and INEXACT says whether the result in M is
84 exact or inexact. Return true if M can be used as a constant-folded
85 result in format FORMAT, storing the value in *RESULT if so. */
86
87static bool
88do_mpfr_ckconv (real_value *result, mpfr_srcptr m, bool inexact,
89 const real_format *format)
90{
91 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
92 overflow/underflow occurred. If -frounding-math, proceed iff the
93 result of calling FUNC was exact. */
94 if (!mpfr_number_p (m)
95 || mpfr_overflow_p ()
96 || mpfr_underflow_p ()
97 || (flag_rounding_math && inexact))
98 return false;
99
100 REAL_VALUE_TYPE tmp;
90ca6847 101 real_from_mpfr (&tmp, m, format, MPFR_RNDN);
5c1a2e63
RS
102
103 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
21cf5ec1 104 If the REAL_VALUE_TYPE is zero but the mpfr_t is not, then we
5c1a2e63
RS
105 underflowed in the conversion. */
106 if (!real_isfinite (&tmp)
107 || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
108 return false;
109
110 real_convert (result, format, &tmp);
111 return real_identical (result, &tmp);
112}
113
114/* Try to evaluate:
115
116 *RESULT = f (*ARG)
117
118 in format FORMAT, given that FUNC is the MPFR implementation of f.
119 Return true on success. */
120
121static bool
122do_mpfr_arg1 (real_value *result,
123 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
124 const real_value *arg, const real_format *format)
125{
126 /* To proceed, MPFR must exactly represent the target floating point
127 format, which only happens when the target base equals two. */
128 if (format->b != 2 || !real_isfinite (arg))
129 return false;
130
131 int prec = format->p;
90ca6847 132 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
5c1a2e63 133
278f8f56 134 auto_mpfr m (prec);
90ca6847 135 mpfr_from_real (m, arg, MPFR_RNDN);
5c1a2e63
RS
136 mpfr_clear_flags ();
137 bool inexact = func (m, m, rnd);
138 bool ok = do_mpfr_ckconv (result, m, inexact, format);
5c1a2e63
RS
139
140 return ok;
141}
142
143/* Try to evaluate:
144
145 *RESULT_SIN = sin (*ARG);
146 *RESULT_COS = cos (*ARG);
147
148 for format FORMAT. Return true on success. */
149
150static bool
151do_mpfr_sincos (real_value *result_sin, real_value *result_cos,
152 const real_value *arg, const real_format *format)
153{
154 /* To proceed, MPFR must exactly represent the target floating point
155 format, which only happens when the target base equals two. */
156 if (format->b != 2 || !real_isfinite (arg))
157 return false;
158
159 int prec = format->p;
90ca6847 160 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
5c1a2e63
RS
161 mpfr_t m, ms, mc;
162
163 mpfr_inits2 (prec, m, ms, mc, NULL);
90ca6847 164 mpfr_from_real (m, arg, MPFR_RNDN);
5c1a2e63
RS
165 mpfr_clear_flags ();
166 bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
167 bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
168 && do_mpfr_ckconv (result_cos, mc, inexact, format));
169 mpfr_clears (m, ms, mc, NULL);
170
171 return ok;
172}
173
174/* Try to evaluate:
175
176 *RESULT = f (*ARG0, *ARG1)
177
178 in format FORMAT, given that FUNC is the MPFR implementation of f.
179 Return true on success. */
180
181static bool
182do_mpfr_arg2 (real_value *result,
183 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t),
184 const real_value *arg0, const real_value *arg1,
185 const real_format *format)
186{
187 /* To proceed, MPFR must exactly represent the target floating point
188 format, which only happens when the target base equals two. */
189 if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
190 return false;
191
192 int prec = format->p;
90ca6847 193 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
5c1a2e63
RS
194 mpfr_t m0, m1;
195
196 mpfr_inits2 (prec, m0, m1, NULL);
90ca6847
TB
197 mpfr_from_real (m0, arg0, MPFR_RNDN);
198 mpfr_from_real (m1, arg1, MPFR_RNDN);
5c1a2e63
RS
199 mpfr_clear_flags ();
200 bool inexact = func (m0, m0, m1, rnd);
201 bool ok = do_mpfr_ckconv (result, m0, inexact, format);
202 mpfr_clears (m0, m1, NULL);
203
204 return ok;
205}
206
207/* Try to evaluate:
208
209 *RESULT = f (ARG0, *ARG1)
210
211 in format FORMAT, given that FUNC is the MPFR implementation of f.
212 Return true on success. */
213
214static bool
215do_mpfr_arg2 (real_value *result,
90ca6847 216 int (*func) (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t),
5c1a2e63
RS
217 const wide_int_ref &arg0, const real_value *arg1,
218 const real_format *format)
219{
220 if (format->b != 2 || !real_isfinite (arg1))
221 return false;
222
223 int prec = format->p;
90ca6847 224 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
5c1a2e63 225
278f8f56 226 auto_mpfr m (prec);
90ca6847 227 mpfr_from_real (m, arg1, MPFR_RNDN);
5c1a2e63
RS
228 mpfr_clear_flags ();
229 bool inexact = func (m, arg0.to_shwi (), m, rnd);
230 bool ok = do_mpfr_ckconv (result, m, inexact, format);
5c1a2e63
RS
231
232 return ok;
233}
234
235/* Try to evaluate:
236
237 *RESULT = f (*ARG0, *ARG1, *ARG2)
238
239 in format FORMAT, given that FUNC is the MPFR implementation of f.
240 Return true on success. */
241
242static bool
243do_mpfr_arg3 (real_value *result,
244 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
245 mpfr_srcptr, mpfr_rnd_t),
246 const real_value *arg0, const real_value *arg1,
247 const real_value *arg2, const real_format *format)
248{
249 /* To proceed, MPFR must exactly represent the target floating point
250 format, which only happens when the target base equals two. */
251 if (format->b != 2
252 || !real_isfinite (arg0)
253 || !real_isfinite (arg1)
254 || !real_isfinite (arg2))
255 return false;
256
257 int prec = format->p;
90ca6847 258 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
5c1a2e63
RS
259 mpfr_t m0, m1, m2;
260
261 mpfr_inits2 (prec, m0, m1, m2, NULL);
90ca6847
TB
262 mpfr_from_real (m0, arg0, MPFR_RNDN);
263 mpfr_from_real (m1, arg1, MPFR_RNDN);
264 mpfr_from_real (m2, arg2, MPFR_RNDN);
5c1a2e63
RS
265 mpfr_clear_flags ();
266 bool inexact = func (m0, m0, m1, m2, rnd);
267 bool ok = do_mpfr_ckconv (result, m0, inexact, format);
268 mpfr_clears (m0, m1, m2, NULL);
269
270 return ok;
271}
272
273/* M is the result of trying to constant-fold an expression (starting
274 with clear MPFR flags) and INEXACT says whether the result in M is
275 exact or inexact. Return true if M can be used as a constant-folded
276 result in which the real and imaginary parts have format FORMAT.
277 Store those parts in *RESULT_REAL and *RESULT_IMAG if so. */
278
279static bool
280do_mpc_ckconv (real_value *result_real, real_value *result_imag,
281 mpc_srcptr m, bool inexact, const real_format *format)
282{
283 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
284 overflow/underflow occurred. If -frounding-math, proceed iff the
285 result of calling FUNC was exact. */
286 if (!mpfr_number_p (mpc_realref (m))
287 || !mpfr_number_p (mpc_imagref (m))
288 || mpfr_overflow_p ()
289 || mpfr_underflow_p ()
290 || (flag_rounding_math && inexact))
291 return false;
292
293 REAL_VALUE_TYPE tmp_real, tmp_imag;
90ca6847
TB
294 real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN);
295 real_from_mpfr (&tmp_imag, mpc_imagref (m), format, MPFR_RNDN);
5c1a2e63
RS
296
297 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
21cf5ec1 298 If the REAL_VALUE_TYPE is zero but the mpfr_t is not, then we
5c1a2e63
RS
299 underflowed in the conversion. */
300 if (!real_isfinite (&tmp_real)
301 || !real_isfinite (&tmp_imag)
302 || (tmp_real.cl == rvc_zero) != (mpfr_zero_p (mpc_realref (m)) != 0)
303 || (tmp_imag.cl == rvc_zero) != (mpfr_zero_p (mpc_imagref (m)) != 0))
304 return false;
305
306 real_convert (result_real, format, &tmp_real);
307 real_convert (result_imag, format, &tmp_imag);
308
309 return (real_identical (result_real, &tmp_real)
310 && real_identical (result_imag, &tmp_imag));
311}
312
313/* Try to evaluate:
314
315 RESULT = f (ARG)
316
317 in format FORMAT, given that FUNC is the mpc implementation of f.
318 Return true on success. Both RESULT and ARG are represented as
319 real and imaginary pairs. */
320
321static bool
322do_mpc_arg1 (real_value *result_real, real_value *result_imag,
323 int (*func) (mpc_ptr, mpc_srcptr, mpc_rnd_t),
324 const real_value *arg_real, const real_value *arg_imag,
325 const real_format *format)
326{
327 /* To proceed, MPFR must exactly represent the target floating point
328 format, which only happens when the target base equals two. */
329 if (format->b != 2
330 || !real_isfinite (arg_real)
331 || !real_isfinite (arg_imag))
332 return false;
333
334 int prec = format->p;
335 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
336 mpc_t m;
337
338 mpc_init2 (m, prec);
90ca6847
TB
339 mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN);
340 mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN);
5c1a2e63
RS
341 mpfr_clear_flags ();
342 bool inexact = func (m, m, crnd);
343 bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
344 mpc_clear (m);
345
346 return ok;
347}
348
349/* Try to evaluate:
350
351 RESULT = f (ARG0, ARG1)
352
353 in format FORMAT, given that FUNC is the mpc implementation of f.
354 Return true on success. RESULT, ARG0 and ARG1 are represented as
355 real and imaginary pairs. */
356
357static bool
358do_mpc_arg2 (real_value *result_real, real_value *result_imag,
359 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t),
360 const real_value *arg0_real, const real_value *arg0_imag,
361 const real_value *arg1_real, const real_value *arg1_imag,
362 const real_format *format)
363{
364 if (!real_isfinite (arg0_real)
365 || !real_isfinite (arg0_imag)
366 || !real_isfinite (arg1_real)
367 || !real_isfinite (arg1_imag))
368 return false;
369
370 int prec = format->p;
371 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
372 mpc_t m0, m1;
373
374 mpc_init2 (m0, prec);
375 mpc_init2 (m1, prec);
90ca6847
TB
376 mpfr_from_real (mpc_realref (m0), arg0_real, MPFR_RNDN);
377 mpfr_from_real (mpc_imagref (m0), arg0_imag, MPFR_RNDN);
378 mpfr_from_real (mpc_realref (m1), arg1_real, MPFR_RNDN);
379 mpfr_from_real (mpc_imagref (m1), arg1_imag, MPFR_RNDN);
5c1a2e63
RS
380 mpfr_clear_flags ();
381 bool inexact = func (m0, m0, m1, crnd);
382 bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
383 mpc_clear (m0);
384 mpc_clear (m1);
385
386 return ok;
387}
388
389/* Try to evaluate:
390
391 *RESULT = logb (*ARG)
392
393 in format FORMAT. Return true on success. */
394
395static bool
396fold_const_logb (real_value *result, const real_value *arg,
397 const real_format *format)
398{
399 switch (arg->cl)
400 {
401 case rvc_nan:
402 /* If arg is +-NaN, then return it. */
403 *result = *arg;
404 return true;
405
406 case rvc_inf:
407 /* If arg is +-Inf, then return +Inf. */
408 *result = *arg;
409 result->sign = 0;
410 return true;
411
412 case rvc_zero:
413 /* Zero may set errno and/or raise an exception. */
414 return false;
415
416 case rvc_normal:
417 /* For normal numbers, proceed iff radix == 2. In GCC,
418 normalized significands are in the range [0.5, 1.0). We
419 want the exponent as if they were [1.0, 2.0) so get the
420 exponent and subtract 1. */
421 if (format->b == 2)
422 {
423 real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED);
424 return true;
425 }
426 return false;
427 }
5c1a2e63
RS
428}
429
430/* Try to evaluate:
431
432 *RESULT = significand (*ARG)
433
434 in format FORMAT. Return true on success. */
435
436static bool
437fold_const_significand (real_value *result, const real_value *arg,
438 const real_format *format)
439{
440 switch (arg->cl)
441 {
442 case rvc_zero:
443 case rvc_nan:
444 case rvc_inf:
445 /* If arg is +-0, +-Inf or +-NaN, then return it. */
446 *result = *arg;
447 return true;
448
449 case rvc_normal:
450 /* For normal numbers, proceed iff radix == 2. */
451 if (format->b == 2)
452 {
453 *result = *arg;
454 /* In GCC, normalized significands are in the range [0.5, 1.0).
455 We want them to be [1.0, 2.0) so set the exponent to 1. */
456 SET_REAL_EXP (result, 1);
457 return true;
458 }
459 return false;
460 }
5c1a2e63
RS
461}
462
463/* Try to evaluate:
464
465 *RESULT = f (*ARG)
466
467 where FORMAT is the format of *ARG and PRECISION is the number of
468 significant bits in the result. Return true on success. */
469
470static bool
471fold_const_conversion (wide_int *result,
472 void (*fn) (real_value *, format_helper,
473 const real_value *),
474 const real_value *arg, unsigned int precision,
475 const real_format *format)
476{
477 if (!real_isfinite (arg))
478 return false;
479
480 real_value rounded;
481 fn (&rounded, format, arg);
482
483 bool fail = false;
484 *result = real_to_integer (&rounded, &fail, precision);
485 return !fail;
486}
487
488/* Try to evaluate:
489
490 *RESULT = pow (*ARG0, *ARG1)
491
492 in format FORMAT. Return true on success. */
493
494static bool
495fold_const_pow (real_value *result, const real_value *arg0,
496 const real_value *arg1, const real_format *format)
497{
498 if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
499 return true;
500
501 /* Check for an integer exponent. */
502 REAL_VALUE_TYPE cint1;
503 HOST_WIDE_INT n1 = real_to_integer (arg1);
504 real_from_integer (&cint1, VOIDmode, n1, SIGNED);
505 /* Attempt to evaluate pow at compile-time, unless this should
506 raise an exception. */
507 if (real_identical (arg1, &cint1)
508 && (n1 > 0
509 || (!flag_trapping_math && !flag_errno_math)
510 || !real_equal (arg0, &dconst0)))
511 {
512 bool inexact = real_powi (result, format, arg0, n1);
5a00b0aa
SS
513 /* Avoid the folding if flag_signaling_nans is on. */
514 if (flag_unsafe_math_optimizations
515 || (!inexact
516 && !(flag_signaling_nans
517 && REAL_VALUE_ISSIGNALING_NAN (*arg0))))
5c1a2e63
RS
518 return true;
519 }
520
521 return false;
522}
523
04782385
JJ
524/* Try to evaluate:
525
526 *RESULT = nextafter (*ARG0, *ARG1)
527
528 or
529
530 *RESULT = nexttoward (*ARG0, *ARG1)
531
532 in format FORMAT. Return true on success. */
533
534static bool
535fold_const_nextafter (real_value *result, const real_value *arg0,
536 const real_value *arg1, const real_format *format)
537{
538 if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
539 || REAL_VALUE_ISSIGNALING_NAN (*arg1))
540 return false;
541
542 /* Don't handle composite modes, nor decimal, nor modes without
543 inf or denorm at least for now. */
544 if (format->pnan < format->p
545 || format->b == 10
546 || !format->has_inf
547 || !format->has_denorm)
548 return false;
549
550 if (real_nextafter (result, format, arg0, arg1)
551 /* If raising underflow or overflow and setting errno to ERANGE,
552 fail if we care about those side-effects. */
553 && (flag_trapping_math || flag_errno_math))
554 return false;
555 /* Similarly for nextafter (0, 1) raising underflow. */
556 else if (flag_trapping_math
557 && arg0->cl == rvc_zero
558 && result->cl != rvc_zero)
559 return false;
560
561 real_convert (result, format, result);
562
563 return true;
564}
565
5c1a2e63
RS
566/* Try to evaluate:
567
568 *RESULT = ldexp (*ARG0, ARG1)
569
570 in format FORMAT. Return true on success. */
571
572static bool
573fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
574 const wide_int_ref &arg1,
575 const real_format *format)
576{
577 /* Bound the maximum adjustment to twice the range of the
578 mode's valid exponents. Use abs to ensure the range is
579 positive as a sanity check. */
580 int max_exp_adj = 2 * labs (format->emax - format->emin);
581
582 /* The requested adjustment must be inside this range. This
583 is a preliminary cap to avoid things like overflow, we
584 may still fail to compute the result for other reasons. */
585 if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
586 return false;
587
5a00b0aa
SS
588 /* Don't perform operation if we honor signaling NaNs and
589 operand is a signaling NaN. */
590 if (!flag_unsafe_math_optimizations
591 && flag_signaling_nans
592 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
593 return false;
594
5c1a2e63
RS
595 REAL_VALUE_TYPE initial_result;
596 real_ldexp (&initial_result, arg0, arg1.to_shwi ());
597
598 /* Ensure we didn't overflow. */
599 if (real_isinf (&initial_result))
600 return false;
601
602 /* Only proceed if the target mode can hold the
603 resulting value. */
604 *result = real_value_truncate (format, initial_result);
605 return real_equal (&initial_result, result);
606}
607
df838ef0
RS
608/* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
609 return type TYPE. QUIET is true if a quiet rather than signalling
610 NaN is required. */
611
612static tree
613fold_const_builtin_nan (tree type, tree arg, bool quiet)
614{
615 REAL_VALUE_TYPE real;
616 const char *str = c_getstr (arg);
617 if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
618 return build_real (type, real);
619 return NULL_TREE;
620}
621
16d24520
RS
622/* Fold a call to IFN_REDUC_<CODE> (ARG), returning a value of type TYPE. */
623
624static tree
625fold_const_reduction (tree type, tree arg, tree_code code)
626{
928686b1
RS
627 unsigned HOST_WIDE_INT nelts;
628 if (TREE_CODE (arg) != VECTOR_CST
629 || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
16d24520
RS
630 return NULL_TREE;
631
632 tree res = VECTOR_CST_ELT (arg, 0);
928686b1 633 for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
16d24520
RS
634 {
635 res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
636 if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
637 return NULL_TREE;
638 }
639 return res;
640}
641
d8fcab68
JJ
642/* Fold a call to IFN_VEC_CONVERT (ARG) returning TYPE. */
643
644static tree
645fold_const_vec_convert (tree ret_type, tree arg)
646{
647 enum tree_code code = NOP_EXPR;
648 tree arg_type = TREE_TYPE (arg);
649 if (TREE_CODE (arg) != VECTOR_CST)
650 return NULL_TREE;
651
652 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
653
654 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
655 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
656 code = FIX_TRUNC_EXPR;
657 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
658 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
659 code = FLOAT_EXPR;
660
47635817
JJ
661 /* We can't handle steps directly when extending, since the
662 values need to wrap at the original precision first. */
663 bool step_ok_p
664 = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
665 && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
666 && (TYPE_PRECISION (TREE_TYPE (ret_type))
667 <= TYPE_PRECISION (TREE_TYPE (arg_type))));
d8fcab68 668 tree_vector_builder elts;
47635817
JJ
669 if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
670 return NULL_TREE;
671
d8fcab68
JJ
672 unsigned int count = elts.encoded_nelts ();
673 for (unsigned int i = 0; i < count; ++i)
674 {
675 tree elt = fold_unary (code, TREE_TYPE (ret_type),
676 VECTOR_CST_ELT (arg, i));
677 if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
678 return NULL_TREE;
679 elts.quick_push (elt);
680 }
681
682 return elts.build ();
683}
684
0b1fe8cf
RS
685/* Try to evaluate:
686
687 IFN_WHILE_ULT (ARG0, ARG1, (TYPE) { ... })
688
689 Return the value on success and null on failure. */
690
691static tree
692fold_while_ult (tree type, poly_uint64 arg0, poly_uint64 arg1)
693{
694 if (known_ge (arg0, arg1))
695 return build_zero_cst (type);
696
697 if (maybe_ge (arg0, arg1))
698 return NULL_TREE;
699
700 poly_uint64 diff = arg1 - arg0;
701 poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
702 if (known_ge (diff, nelts))
703 return build_all_ones_cst (type);
704
705 unsigned HOST_WIDE_INT const_diff;
706 if (known_le (diff, nelts) && diff.is_constant (&const_diff))
707 {
708 tree minus_one = build_minus_one_cst (TREE_TYPE (type));
709 tree zero = build_zero_cst (TREE_TYPE (type));
710 return build_vector_a_then_b (type, const_diff, minus_one, zero);
711 }
712 return NULL_TREE;
713}
714
5c1a2e63
RS
715/* Try to evaluate:
716
717 *RESULT = FN (*ARG)
718
719 in format FORMAT. Return true on success. */
720
721static bool
d7ebef06 722fold_const_call_ss (real_value *result, combined_fn fn,
5c1a2e63
RS
723 const real_value *arg, const real_format *format)
724{
725 switch (fn)
726 {
d7ebef06 727 CASE_CFN_SQRT:
ee5fd23a 728 CASE_CFN_SQRT_FN:
5c1a2e63
RS
729 return (real_compare (GE_EXPR, arg, &dconst0)
730 && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
731
d7ebef06 732 CASE_CFN_CBRT:
7f940822 733 CASE_CFN_CBRT_FN:
5c1a2e63
RS
734 return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
735
d7ebef06 736 CASE_CFN_ASIN:
7f940822 737 CASE_CFN_ASIN_FN:
5c1a2e63
RS
738 return (real_compare (GE_EXPR, arg, &dconstm1)
739 && real_compare (LE_EXPR, arg, &dconst1)
740 && do_mpfr_arg1 (result, mpfr_asin, arg, format));
741
d7ebef06 742 CASE_CFN_ACOS:
7f940822 743 CASE_CFN_ACOS_FN:
5c1a2e63
RS
744 return (real_compare (GE_EXPR, arg, &dconstm1)
745 && real_compare (LE_EXPR, arg, &dconst1)
746 && do_mpfr_arg1 (result, mpfr_acos, arg, format));
747
d7ebef06 748 CASE_CFN_ATAN:
7f940822 749 CASE_CFN_ATAN_FN:
5c1a2e63
RS
750 return do_mpfr_arg1 (result, mpfr_atan, arg, format);
751
d7ebef06 752 CASE_CFN_ASINH:
7f940822 753 CASE_CFN_ASINH_FN:
5c1a2e63
RS
754 return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
755
d7ebef06 756 CASE_CFN_ACOSH:
7f940822 757 CASE_CFN_ACOSH_FN:
5c1a2e63
RS
758 return (real_compare (GE_EXPR, arg, &dconst1)
759 && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
760
d7ebef06 761 CASE_CFN_ATANH:
7f940822 762 CASE_CFN_ATANH_FN:
5c1a2e63
RS
763 return (real_compare (GE_EXPR, arg, &dconstm1)
764 && real_compare (LE_EXPR, arg, &dconst1)
765 && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
766
d7ebef06 767 CASE_CFN_SIN:
7f940822 768 CASE_CFN_SIN_FN:
5c1a2e63
RS
769 return do_mpfr_arg1 (result, mpfr_sin, arg, format);
770
d7ebef06 771 CASE_CFN_COS:
7f940822 772 CASE_CFN_COS_FN:
5c1a2e63
RS
773 return do_mpfr_arg1 (result, mpfr_cos, arg, format);
774
d7ebef06 775 CASE_CFN_TAN:
7f940822 776 CASE_CFN_TAN_FN:
5c1a2e63
RS
777 return do_mpfr_arg1 (result, mpfr_tan, arg, format);
778
d7ebef06 779 CASE_CFN_SINH:
7f940822 780 CASE_CFN_SINH_FN:
5c1a2e63
RS
781 return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
782
d7ebef06 783 CASE_CFN_COSH:
7f940822 784 CASE_CFN_COSH_FN:
5c1a2e63
RS
785 return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
786
d7ebef06 787 CASE_CFN_TANH:
7f940822 788 CASE_CFN_TANH_FN:
5c1a2e63
RS
789 return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
790
d7ebef06 791 CASE_CFN_ERF:
7f940822 792 CASE_CFN_ERF_FN:
5c1a2e63
RS
793 return do_mpfr_arg1 (result, mpfr_erf, arg, format);
794
d7ebef06 795 CASE_CFN_ERFC:
7f940822 796 CASE_CFN_ERFC_FN:
5c1a2e63
RS
797 return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
798
d7ebef06 799 CASE_CFN_TGAMMA:
7f940822 800 CASE_CFN_TGAMMA_FN:
5c1a2e63
RS
801 return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
802
d7ebef06 803 CASE_CFN_EXP:
7f940822 804 CASE_CFN_EXP_FN:
5c1a2e63
RS
805 return do_mpfr_arg1 (result, mpfr_exp, arg, format);
806
d7ebef06 807 CASE_CFN_EXP2:
7f940822 808 CASE_CFN_EXP2_FN:
5c1a2e63
RS
809 return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
810
d7ebef06
RS
811 CASE_CFN_EXP10:
812 CASE_CFN_POW10:
5c1a2e63
RS
813 return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
814
d7ebef06 815 CASE_CFN_EXPM1:
7f940822 816 CASE_CFN_EXPM1_FN:
5c1a2e63
RS
817 return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
818
d7ebef06 819 CASE_CFN_LOG:
7f940822 820 CASE_CFN_LOG_FN:
5c1a2e63
RS
821 return (real_compare (GT_EXPR, arg, &dconst0)
822 && do_mpfr_arg1 (result, mpfr_log, arg, format));
823
d7ebef06 824 CASE_CFN_LOG2:
7f940822 825 CASE_CFN_LOG2_FN:
5c1a2e63
RS
826 return (real_compare (GT_EXPR, arg, &dconst0)
827 && do_mpfr_arg1 (result, mpfr_log2, arg, format));
828
d7ebef06 829 CASE_CFN_LOG10:
7f940822 830 CASE_CFN_LOG10_FN:
5c1a2e63
RS
831 return (real_compare (GT_EXPR, arg, &dconst0)
832 && do_mpfr_arg1 (result, mpfr_log10, arg, format));
833
d7ebef06 834 CASE_CFN_LOG1P:
7f940822 835 CASE_CFN_LOG1P_FN:
5c1a2e63
RS
836 return (real_compare (GT_EXPR, arg, &dconstm1)
837 && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
838
d7ebef06 839 CASE_CFN_J0:
5c1a2e63
RS
840 return do_mpfr_arg1 (result, mpfr_j0, arg, format);
841
d7ebef06 842 CASE_CFN_J1:
5c1a2e63
RS
843 return do_mpfr_arg1 (result, mpfr_j1, arg, format);
844
d7ebef06 845 CASE_CFN_Y0:
5c1a2e63
RS
846 return (real_compare (GT_EXPR, arg, &dconst0)
847 && do_mpfr_arg1 (result, mpfr_y0, arg, format));
848
d7ebef06 849 CASE_CFN_Y1:
5c1a2e63
RS
850 return (real_compare (GT_EXPR, arg, &dconst0)
851 && do_mpfr_arg1 (result, mpfr_y1, arg, format));
852
d7ebef06 853 CASE_CFN_FLOOR:
c6cfa2bf 854 CASE_CFN_FLOOR_FN:
7d7b99f9 855 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
5c1a2e63
RS
856 {
857 real_floor (result, format, arg);
858 return true;
859 }
860 return false;
861
d7ebef06 862 CASE_CFN_CEIL:
c6cfa2bf 863 CASE_CFN_CEIL_FN:
7d7b99f9 864 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
5c1a2e63
RS
865 {
866 real_ceil (result, format, arg);
867 return true;
868 }
869 return false;
870
d7ebef06 871 CASE_CFN_TRUNC:
c6cfa2bf 872 CASE_CFN_TRUNC_FN:
7d7b99f9
TJ
873 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
874 {
875 real_trunc (result, format, arg);
876 return true;
877 }
878 return false;
5c1a2e63 879
d7ebef06 880 CASE_CFN_ROUND:
c6cfa2bf 881 CASE_CFN_ROUND_FN:
7d7b99f9 882 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
5c1a2e63
RS
883 {
884 real_round (result, format, arg);
885 return true;
886 }
887 return false;
888
7d7b99f9
TJ
889 CASE_CFN_ROUNDEVEN:
890 CASE_CFN_ROUNDEVEN_FN:
891 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
892 {
893 real_roundeven (result, format, arg);
894 return true;
895 }
896 return false;
897
d7ebef06 898 CASE_CFN_LOGB:
7f940822 899 CASE_CFN_LOGB_FN:
5c1a2e63
RS
900 return fold_const_logb (result, arg, format);
901
d7ebef06 902 CASE_CFN_SIGNIFICAND:
5c1a2e63
RS
903 return fold_const_significand (result, arg, format);
904
905 default:
906 return false;
907 }
908}
909
910/* Try to evaluate:
911
912 *RESULT = FN (*ARG)
913
914 where FORMAT is the format of ARG and PRECISION is the number of
915 significant bits in the result. Return true on success. */
916
917static bool
d7ebef06 918fold_const_call_ss (wide_int *result, combined_fn fn,
5c1a2e63
RS
919 const real_value *arg, unsigned int precision,
920 const real_format *format)
921{
922 switch (fn)
923 {
d7ebef06 924 CASE_CFN_SIGNBIT:
5c1a2e63
RS
925 if (real_isneg (arg))
926 *result = wi::one (precision);
927 else
928 *result = wi::zero (precision);
929 return true;
930
d7ebef06 931 CASE_CFN_ILOGB:
7f940822 932 CASE_CFN_ILOGB_FN:
5c1a2e63
RS
933 /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
934 Proceed iff radix == 2. In GCC, normalized significands are in
935 the range [0.5, 1.0). We want the exponent as if they were
936 [1.0, 2.0) so get the exponent and subtract 1. */
937 if (arg->cl == rvc_normal && format->b == 2)
938 {
939 *result = wi::shwi (REAL_EXP (arg) - 1, precision);
940 return true;
941 }
942 return false;
943
d7ebef06
RS
944 CASE_CFN_ICEIL:
945 CASE_CFN_LCEIL:
946 CASE_CFN_LLCEIL:
5c1a2e63
RS
947 return fold_const_conversion (result, real_ceil, arg,
948 precision, format);
949
d7ebef06
RS
950 CASE_CFN_LFLOOR:
951 CASE_CFN_IFLOOR:
952 CASE_CFN_LLFLOOR:
5c1a2e63
RS
953 return fold_const_conversion (result, real_floor, arg,
954 precision, format);
955
d7ebef06
RS
956 CASE_CFN_IROUND:
957 CASE_CFN_LROUND:
7f940822 958 CASE_CFN_LROUND_FN:
d7ebef06 959 CASE_CFN_LLROUND:
7f940822 960 CASE_CFN_LLROUND_FN:
5c1a2e63
RS
961 return fold_const_conversion (result, real_round, arg,
962 precision, format);
963
d7ebef06
RS
964 CASE_CFN_IRINT:
965 CASE_CFN_LRINT:
7f940822 966 CASE_CFN_LRINT_FN:
d7ebef06 967 CASE_CFN_LLRINT:
7f940822 968 CASE_CFN_LLRINT_FN:
5c1a2e63
RS
969 /* Not yet folded to a constant. */
970 return false;
971
d7ebef06
RS
972 CASE_CFN_FINITE:
973 case CFN_BUILT_IN_FINITED32:
974 case CFN_BUILT_IN_FINITED64:
975 case CFN_BUILT_IN_FINITED128:
976 case CFN_BUILT_IN_ISFINITE:
2556a032
RS
977 *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
978 return true;
979
0982edd3
JJ
980 case CFN_BUILT_IN_ISSIGNALING:
981 *result = wi::shwi (real_issignaling_nan (arg) ? 1 : 0, precision);
982 return true;
983
d7ebef06
RS
984 CASE_CFN_ISINF:
985 case CFN_BUILT_IN_ISINFD32:
986 case CFN_BUILT_IN_ISINFD64:
987 case CFN_BUILT_IN_ISINFD128:
2556a032
RS
988 if (real_isinf (arg))
989 *result = wi::shwi (arg->sign ? -1 : 1, precision);
990 else
991 *result = wi::shwi (0, precision);
992 return true;
993
d7ebef06
RS
994 CASE_CFN_ISNAN:
995 case CFN_BUILT_IN_ISNAND32:
996 case CFN_BUILT_IN_ISNAND64:
997 case CFN_BUILT_IN_ISNAND128:
2556a032
RS
998 *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
999 return true;
1000
5c1a2e63
RS
1001 default:
1002 return false;
1003 }
1004}
1005
db9bd5d5
RS
1006/* Try to evaluate:
1007
1008 *RESULT = FN (ARG)
1009
1010 where ARG_TYPE is the type of ARG and PRECISION is the number of bits
1011 in the result. Return true on success. */
1012
1013static bool
d7ebef06
RS
1014fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1015 unsigned int precision, tree arg_type)
db9bd5d5
RS
1016{
1017 switch (fn)
1018 {
d7ebef06 1019 CASE_CFN_FFS:
7383cb56 1020 case CFN_BUILT_IN_FFSG:
db9bd5d5
RS
1021 *result = wi::shwi (wi::ffs (arg), precision);
1022 return true;
1023
d7ebef06 1024 CASE_CFN_CLZ:
7383cb56 1025 case CFN_BUILT_IN_CLZG:
db9bd5d5
RS
1026 {
1027 int tmp;
1028 if (wi::ne_p (arg, 0))
1029 tmp = wi::clz (arg);
7383cb56
JJ
1030 else if (TREE_CODE (arg_type) == BITINT_TYPE)
1031 tmp = TYPE_PRECISION (arg_type);
7a504f33
RS
1032 else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1033 tmp))
db9bd5d5
RS
1034 tmp = TYPE_PRECISION (arg_type);
1035 *result = wi::shwi (tmp, precision);
1036 return true;
1037 }
1038
d7ebef06 1039 CASE_CFN_CTZ:
7383cb56 1040 case CFN_BUILT_IN_CTZG:
db9bd5d5
RS
1041 {
1042 int tmp;
1043 if (wi::ne_p (arg, 0))
1044 tmp = wi::ctz (arg);
7383cb56
JJ
1045 else if (TREE_CODE (arg_type) == BITINT_TYPE)
1046 tmp = TYPE_PRECISION (arg_type);
7a504f33
RS
1047 else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1048 tmp))
db9bd5d5
RS
1049 tmp = TYPE_PRECISION (arg_type);
1050 *result = wi::shwi (tmp, precision);
1051 return true;
1052 }
1053
d7ebef06 1054 CASE_CFN_CLRSB:
7383cb56 1055 case CFN_BUILT_IN_CLRSBG:
db9bd5d5
RS
1056 *result = wi::shwi (wi::clrsb (arg), precision);
1057 return true;
1058
d7ebef06 1059 CASE_CFN_POPCOUNT:
7383cb56 1060 case CFN_BUILT_IN_POPCOUNTG:
db9bd5d5
RS
1061 *result = wi::shwi (wi::popcount (arg), precision);
1062 return true;
1063
d7ebef06 1064 CASE_CFN_PARITY:
7383cb56 1065 case CFN_BUILT_IN_PARITYG:
db9bd5d5
RS
1066 *result = wi::shwi (wi::parity (arg), precision);
1067 return true;
1068
d7ebef06
RS
1069 case CFN_BUILT_IN_BSWAP16:
1070 case CFN_BUILT_IN_BSWAP32:
1071 case CFN_BUILT_IN_BSWAP64:
fe7ebef7 1072 case CFN_BUILT_IN_BSWAP128:
0ede6b5a
RS
1073 *result = wi::bswap (wide_int::from (arg, precision,
1074 TYPE_SIGN (arg_type)));
db9bd5d5
RS
1075 return true;
1076
1077 default:
1078 return false;
1079 }
1080}
1081
5c1a2e63
RS
1082/* Try to evaluate:
1083
1084 RESULT = FN (*ARG)
1085
1086 where FORMAT is the format of ARG and of the real and imaginary parts
1087 of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
1088 true on success. */
1089
1090static bool
1091fold_const_call_cs (real_value *result_real, real_value *result_imag,
d7ebef06 1092 combined_fn fn, const real_value *arg,
5c1a2e63
RS
1093 const real_format *format)
1094{
1095 switch (fn)
1096 {
d7ebef06 1097 CASE_CFN_CEXPI:
5c1a2e63
RS
1098 /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1099 return do_mpfr_sincos (result_imag, result_real, arg, format);
1100
1101 default:
1102 return false;
1103 }
1104}
1105
1106/* Try to evaluate:
1107
1108 *RESULT = fn (ARG)
1109
1110 where FORMAT is the format of RESULT and of the real and imaginary parts
1111 of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
1112 success. */
1113
1114static bool
d7ebef06 1115fold_const_call_sc (real_value *result, combined_fn fn,
5c1a2e63
RS
1116 const real_value *arg_real, const real_value *arg_imag,
1117 const real_format *format)
1118{
1119 switch (fn)
1120 {
d7ebef06 1121 CASE_CFN_CABS:
259a1155 1122 CASE_CFN_CABS_FN:
5c1a2e63
RS
1123 return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1124
1125 default:
1126 return false;
1127 }
1128}
1129
1130/* Try to evaluate:
1131
1132 RESULT = fn (ARG)
1133
1134 where FORMAT is the format of the real and imaginary parts of RESULT
1135 (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1136 Return true on success. */
1137
1138static bool
1139fold_const_call_cc (real_value *result_real, real_value *result_imag,
d7ebef06 1140 combined_fn fn, const real_value *arg_real,
5c1a2e63
RS
1141 const real_value *arg_imag, const real_format *format)
1142{
1143 switch (fn)
1144 {
d7ebef06 1145 CASE_CFN_CCOS:
259a1155 1146 CASE_CFN_CCOS_FN:
5c1a2e63
RS
1147 return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1148 arg_real, arg_imag, format);
1149
d7ebef06 1150 CASE_CFN_CCOSH:
259a1155 1151 CASE_CFN_CCOSH_FN:
5c1a2e63
RS
1152 return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1153 arg_real, arg_imag, format);
1154
d7ebef06 1155 CASE_CFN_CPROJ:
259a1155 1156 CASE_CFN_CPROJ_FN:
5c1a2e63
RS
1157 if (real_isinf (arg_real) || real_isinf (arg_imag))
1158 {
bb9d4344 1159 *result_real = dconstinf;
5c1a2e63
RS
1160 *result_imag = dconst0;
1161 result_imag->sign = arg_imag->sign;
1162 }
1163 else
1164 {
1165 *result_real = *arg_real;
1166 *result_imag = *arg_imag;
1167 }
1168 return true;
1169
d7ebef06 1170 CASE_CFN_CSIN:
259a1155 1171 CASE_CFN_CSIN_FN:
5c1a2e63
RS
1172 return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1173 arg_real, arg_imag, format);
1174
d7ebef06 1175 CASE_CFN_CSINH:
259a1155 1176 CASE_CFN_CSINH_FN:
5c1a2e63
RS
1177 return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1178 arg_real, arg_imag, format);
1179
d7ebef06 1180 CASE_CFN_CTAN:
259a1155 1181 CASE_CFN_CTAN_FN:
5c1a2e63
RS
1182 return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1183 arg_real, arg_imag, format);
1184
d7ebef06 1185 CASE_CFN_CTANH:
259a1155 1186 CASE_CFN_CTANH_FN:
5c1a2e63
RS
1187 return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1188 arg_real, arg_imag, format);
1189
d7ebef06 1190 CASE_CFN_CLOG:
259a1155 1191 CASE_CFN_CLOG_FN:
5c1a2e63
RS
1192 return do_mpc_arg1 (result_real, result_imag, mpc_log,
1193 arg_real, arg_imag, format);
1194
d7ebef06 1195 CASE_CFN_CSQRT:
259a1155 1196 CASE_CFN_CSQRT_FN:
5c1a2e63
RS
1197 return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1198 arg_real, arg_imag, format);
1199
d7ebef06 1200 CASE_CFN_CASIN:
259a1155 1201 CASE_CFN_CASIN_FN:
5c1a2e63
RS
1202 return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1203 arg_real, arg_imag, format);
1204
d7ebef06 1205 CASE_CFN_CACOS:
259a1155 1206 CASE_CFN_CACOS_FN:
5c1a2e63
RS
1207 return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1208 arg_real, arg_imag, format);
1209
d7ebef06 1210 CASE_CFN_CATAN:
259a1155 1211 CASE_CFN_CATAN_FN:
5c1a2e63
RS
1212 return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1213 arg_real, arg_imag, format);
1214
d7ebef06 1215 CASE_CFN_CASINH:
259a1155 1216 CASE_CFN_CASINH_FN:
5c1a2e63
RS
1217 return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1218 arg_real, arg_imag, format);
1219
d7ebef06 1220 CASE_CFN_CACOSH:
259a1155 1221 CASE_CFN_CACOSH_FN:
5c1a2e63
RS
1222 return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1223 arg_real, arg_imag, format);
1224
d7ebef06 1225 CASE_CFN_CATANH:
259a1155 1226 CASE_CFN_CATANH_FN:
5c1a2e63
RS
1227 return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1228 arg_real, arg_imag, format);
1229
d7ebef06 1230 CASE_CFN_CEXP:
259a1155 1231 CASE_CFN_CEXP_FN:
5c1a2e63
RS
1232 return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1233 arg_real, arg_imag, format);
1234
1235 default:
1236 return false;
1237 }
1238}
1239
df838ef0
RS
1240/* Subroutine of fold_const_call, with the same interface. Handle cases
1241 where the arguments and result are numerical. */
5c1a2e63 1242
df838ef0 1243static tree
d7ebef06 1244fold_const_call_1 (combined_fn fn, tree type, tree arg)
5c1a2e63
RS
1245{
1246 machine_mode mode = TYPE_MODE (type);
1247 machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1248
db9bd5d5
RS
1249 if (integer_cst_p (arg))
1250 {
1251 if (SCALAR_INT_MODE_P (mode))
1252 {
1253 wide_int result;
8e6cdc90
RS
1254 if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1255 TYPE_PRECISION (type), TREE_TYPE (arg)))
db9bd5d5
RS
1256 return wide_int_to_tree (type, result);
1257 }
1258 return NULL_TREE;
1259 }
1260
5c1a2e63
RS
1261 if (real_cst_p (arg))
1262 {
1263 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1264 if (mode == arg_mode)
1265 {
1266 /* real -> real. */
1267 REAL_VALUE_TYPE result;
1268 if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1269 REAL_MODE_FORMAT (mode)))
1270 return build_real (type, result);
1271 }
1272 else if (COMPLEX_MODE_P (mode)
1273 && GET_MODE_INNER (mode) == arg_mode)
1274 {
1275 /* real -> complex real. */
1276 REAL_VALUE_TYPE result_real, result_imag;
1277 if (fold_const_call_cs (&result_real, &result_imag, fn,
1278 TREE_REAL_CST_PTR (arg),
1279 REAL_MODE_FORMAT (arg_mode)))
1280 return build_complex (type,
1281 build_real (TREE_TYPE (type), result_real),
1282 build_real (TREE_TYPE (type), result_imag));
1283 }
1284 else if (INTEGRAL_TYPE_P (type))
1285 {
1286 /* real -> int. */
1287 wide_int result;
1288 if (fold_const_call_ss (&result, fn,
1289 TREE_REAL_CST_PTR (arg),
1290 TYPE_PRECISION (type),
1291 REAL_MODE_FORMAT (arg_mode)))
1292 return wide_int_to_tree (type, result);
1293 }
1294 return NULL_TREE;
1295 }
1296
1297 if (complex_cst_p (arg))
1298 {
1299 gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1300 machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1301 tree argr = TREE_REALPART (arg);
1302 tree argi = TREE_IMAGPART (arg);
1303 if (mode == arg_mode
1304 && real_cst_p (argr)
1305 && real_cst_p (argi))
1306 {
1307 /* complex real -> complex real. */
1308 REAL_VALUE_TYPE result_real, result_imag;
1309 if (fold_const_call_cc (&result_real, &result_imag, fn,
1310 TREE_REAL_CST_PTR (argr),
1311 TREE_REAL_CST_PTR (argi),
1312 REAL_MODE_FORMAT (inner_mode)))
1313 return build_complex (type,
1314 build_real (TREE_TYPE (type), result_real),
1315 build_real (TREE_TYPE (type), result_imag));
1316 }
1317 if (mode == inner_mode
1318 && real_cst_p (argr)
1319 && real_cst_p (argi))
1320 {
1321 /* complex real -> real. */
1322 REAL_VALUE_TYPE result;
1323 if (fold_const_call_sc (&result, fn,
1324 TREE_REAL_CST_PTR (argr),
1325 TREE_REAL_CST_PTR (argi),
1326 REAL_MODE_FORMAT (inner_mode)))
1327 return build_real (type, result);
1328 }
1329 return NULL_TREE;
1330 }
1331
1332 return NULL_TREE;
1333}
1334
df838ef0
RS
1335/* Try to fold FN (ARG) to a constant. Return the constant on success,
1336 otherwise return null. TYPE is the type of the return value. */
1337
1338tree
d7ebef06 1339fold_const_call (combined_fn fn, tree type, tree arg)
df838ef0
RS
1340{
1341 switch (fn)
1342 {
d7ebef06 1343 case CFN_BUILT_IN_STRLEN:
df838ef0
RS
1344 if (const char *str = c_getstr (arg))
1345 return build_int_cst (type, strlen (str));
1346 return NULL_TREE;
1347
d7ebef06 1348 CASE_CFN_NAN:
6dc198e3 1349 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
d7ebef06
RS
1350 case CFN_BUILT_IN_NAND32:
1351 case CFN_BUILT_IN_NAND64:
1352 case CFN_BUILT_IN_NAND128:
df838ef0
RS
1353 return fold_const_builtin_nan (type, arg, true);
1354
d7ebef06 1355 CASE_CFN_NANS:
6dc198e3 1356 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
c2565a31 1357 case CFN_BUILT_IN_NANSF16B:
6c8e4f4d
JM
1358 case CFN_BUILT_IN_NANSD32:
1359 case CFN_BUILT_IN_NANSD64:
1360 case CFN_BUILT_IN_NANSD128:
df838ef0
RS
1361 return fold_const_builtin_nan (type, arg, false);
1362
16d24520
RS
1363 case CFN_REDUC_PLUS:
1364 return fold_const_reduction (type, arg, PLUS_EXPR);
1365
1366 case CFN_REDUC_MAX:
1367 return fold_const_reduction (type, arg, MAX_EXPR);
1368
1369 case CFN_REDUC_MIN:
1370 return fold_const_reduction (type, arg, MIN_EXPR);
1371
898f07b0
RS
1372 case CFN_REDUC_AND:
1373 return fold_const_reduction (type, arg, BIT_AND_EXPR);
1374
1375 case CFN_REDUC_IOR:
1376 return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1377
1378 case CFN_REDUC_XOR:
1379 return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1380
d8fcab68
JJ
1381 case CFN_VEC_CONVERT:
1382 return fold_const_vec_convert (type, arg);
1383
df838ef0
RS
1384 default:
1385 return fold_const_call_1 (fn, type, arg);
1386 }
1387}
1388
b781a135
RS
1389/* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1390 of type TYPE. */
1391
1392static tree
1393fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1394{
1395 if (TREE_CODE (arg1) != VECTOR_CST)
1396 return NULL_TREE;
1397
1398 unsigned HOST_WIDE_INT nelts;
1399 if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1400 return NULL_TREE;
1401
1402 for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1403 {
1404 arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1405 if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1406 return NULL_TREE;
1407 }
1408 return arg0;
1409}
1410
5c1a2e63
RS
1411/* Try to evaluate:
1412
1413 *RESULT = FN (*ARG0, *ARG1)
1414
1415 in format FORMAT. Return true on success. */
1416
1417static bool
d7ebef06 1418fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1419 const real_value *arg0, const real_value *arg1,
1420 const real_format *format)
1421{
1422 switch (fn)
1423 {
d7ebef06
RS
1424 CASE_CFN_DREM:
1425 CASE_CFN_REMAINDER:
7f940822 1426 CASE_CFN_REMAINDER_FN:
5c1a2e63
RS
1427 return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1428
d7ebef06 1429 CASE_CFN_ATAN2:
7f940822 1430 CASE_CFN_ATAN2_FN:
5c1a2e63
RS
1431 return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1432
d7ebef06 1433 CASE_CFN_FDIM:
7f940822 1434 CASE_CFN_FDIM_FN:
5c1a2e63
RS
1435 return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1436
2c17b5f8 1437 CASE_CFN_FMOD:
7f940822 1438 CASE_CFN_FMOD_FN:
2c17b5f8
RS
1439 return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
1440
d7ebef06 1441 CASE_CFN_HYPOT:
7f940822 1442 CASE_CFN_HYPOT_FN:
5c1a2e63
RS
1443 return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1444
d7ebef06 1445 CASE_CFN_COPYSIGN:
ee5fd23a 1446 CASE_CFN_COPYSIGN_FN:
5c1a2e63
RS
1447 *result = *arg0;
1448 real_copysign (result, arg1);
1449 return true;
1450
d7ebef06 1451 CASE_CFN_FMIN:
ee5fd23a 1452 CASE_CFN_FMIN_FN:
5c1a2e63
RS
1453 return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1454
d7ebef06 1455 CASE_CFN_FMAX:
ee5fd23a 1456 CASE_CFN_FMAX_FN:
5c1a2e63
RS
1457 return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1458
d7ebef06 1459 CASE_CFN_POW:
7f940822 1460 CASE_CFN_POW_FN:
5c1a2e63
RS
1461 return fold_const_pow (result, arg0, arg1, format);
1462
04782385 1463 CASE_CFN_NEXTAFTER:
7f940822 1464 CASE_CFN_NEXTAFTER_FN:
29490c2a 1465 case CFN_BUILT_IN_NEXTAFTERF16B:
04782385
JJ
1466 CASE_CFN_NEXTTOWARD:
1467 return fold_const_nextafter (result, arg0, arg1, format);
1468
5c1a2e63
RS
1469 default:
1470 return false;
1471 }
1472}
1473
1474/* Try to evaluate:
1475
1476 *RESULT = FN (*ARG0, ARG1)
1477
1478 where FORMAT is the format of *RESULT and *ARG0. Return true on
1479 success. */
1480
1481static bool
d7ebef06 1482fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1483 const real_value *arg0, const wide_int_ref &arg1,
1484 const real_format *format)
1485{
1486 switch (fn)
1487 {
d7ebef06 1488 CASE_CFN_LDEXP:
7f940822 1489 CASE_CFN_LDEXP_FN:
5c1a2e63
RS
1490 return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1491
d7ebef06 1492 CASE_CFN_SCALBN:
7f940822 1493 CASE_CFN_SCALBN_FN:
d7ebef06 1494 CASE_CFN_SCALBLN:
7f940822 1495 CASE_CFN_SCALBLN_FN:
5c1a2e63
RS
1496 return (format->b == 2
1497 && fold_const_builtin_load_exponent (result, arg0, arg1,
1498 format));
1499
d7ebef06 1500 CASE_CFN_POWI:
5a00b0aa
SS
1501 /* Avoid the folding if flag_signaling_nans is on and
1502 operand is a signaling NaN. */
1503 if (!flag_unsafe_math_optimizations
1504 && flag_signaling_nans
1505 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1506 return false;
1507
5c1a2e63
RS
1508 real_powi (result, format, arg0, arg1.to_shwi ());
1509 return true;
1510
1511 default:
1512 return false;
1513 }
1514}
1515
1516/* Try to evaluate:
1517
1518 *RESULT = FN (ARG0, *ARG1)
1519
1520 where FORMAT is the format of *RESULT and *ARG1. Return true on
1521 success. */
1522
1523static bool
d7ebef06 1524fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1525 const wide_int_ref &arg0, const real_value *arg1,
1526 const real_format *format)
1527{
1528 switch (fn)
1529 {
d7ebef06 1530 CASE_CFN_JN:
5c1a2e63
RS
1531 return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1532
d7ebef06 1533 CASE_CFN_YN:
5c1a2e63
RS
1534 return (real_compare (GT_EXPR, arg1, &dconst0)
1535 && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1536
1537 default:
1538 return false;
1539 }
1540}
1541
7383cb56
JJ
1542/* Try to evaluate:
1543
1544 *RESULT = FN (ARG0, ARG1)
1545
1546 where ARG_TYPE is the type of ARG0 and PRECISION is the number of bits in
1547 the result. Return true on success. */
1548
1549static bool
1550fold_const_call_sss (wide_int *result, combined_fn fn,
1551 const wide_int_ref &arg0, const wide_int_ref &arg1,
1552 unsigned int precision, tree arg_type ATTRIBUTE_UNUSED)
1553{
1554 switch (fn)
1555 {
1556 case CFN_CLZ:
1557 case CFN_BUILT_IN_CLZG:
1558 {
1559 int tmp;
1560 if (wi::ne_p (arg0, 0))
1561 tmp = wi::clz (arg0);
1562 else
1563 tmp = arg1.to_shwi ();
1564 *result = wi::shwi (tmp, precision);
1565 return true;
1566 }
1567
1568 case CFN_CTZ:
1569 case CFN_BUILT_IN_CTZG:
1570 {
1571 int tmp;
1572 if (wi::ne_p (arg0, 0))
1573 tmp = wi::ctz (arg0);
1574 else
1575 tmp = arg1.to_shwi ();
1576 *result = wi::shwi (tmp, precision);
1577 return true;
1578 }
1579
1580 default:
1581 return false;
1582 }
1583}
1584
5c1a2e63
RS
1585/* Try to evaluate:
1586
1587 RESULT = fn (ARG0, ARG1)
1588
1589 where FORMAT is the format of the real and imaginary parts of RESULT
1590 (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1591 and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1592
1593static bool
1594fold_const_call_ccc (real_value *result_real, real_value *result_imag,
d7ebef06 1595 combined_fn fn, const real_value *arg0_real,
5c1a2e63
RS
1596 const real_value *arg0_imag, const real_value *arg1_real,
1597 const real_value *arg1_imag, const real_format *format)
1598{
1599 switch (fn)
1600 {
d7ebef06 1601 CASE_CFN_CPOW:
259a1155 1602 CASE_CFN_CPOW_FN:
5c1a2e63
RS
1603 return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1604 arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1605
1606 default:
1607 return false;
1608 }
1609}
1610
df838ef0
RS
1611/* Subroutine of fold_const_call, with the same interface. Handle cases
1612 where the arguments and result are numerical. */
5c1a2e63 1613
df838ef0 1614static tree
d7ebef06 1615fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
5c1a2e63
RS
1616{
1617 machine_mode mode = TYPE_MODE (type);
1618 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1619 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1620
7383cb56
JJ
1621 if (integer_cst_p (arg0) && integer_cst_p (arg1))
1622 {
1623 if (SCALAR_INT_MODE_P (mode))
1624 {
1625 wide_int result;
1626 if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1627 wi::to_wide (arg1), TYPE_PRECISION (type),
1628 TREE_TYPE (arg0)))
1629 return wide_int_to_tree (type, result);
1630 }
1631 return NULL_TREE;
1632 }
1633
04782385 1634 if (mode == arg0_mode
5c1a2e63
RS
1635 && real_cst_p (arg0)
1636 && real_cst_p (arg1))
1637 {
1638 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
04782385
JJ
1639 REAL_VALUE_TYPE result;
1640 if (arg0_mode == arg1_mode)
5c1a2e63
RS
1641 {
1642 /* real, real -> real. */
5c1a2e63
RS
1643 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1644 TREE_REAL_CST_PTR (arg1),
1645 REAL_MODE_FORMAT (mode)))
1646 return build_real (type, result);
1647 }
04782385
JJ
1648 else if (arg1_mode == TYPE_MODE (long_double_type_node))
1649 switch (fn)
1650 {
1651 CASE_CFN_NEXTTOWARD:
1652 /* real, long double -> real. */
1653 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1654 TREE_REAL_CST_PTR (arg1),
1655 REAL_MODE_FORMAT (mode)))
1656 return build_real (type, result);
1657 break;
1658 default:
1659 break;
1660 }
5c1a2e63
RS
1661 return NULL_TREE;
1662 }
1663
1664 if (real_cst_p (arg0)
1665 && integer_cst_p (arg1))
1666 {
1667 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1668 if (mode == arg0_mode)
1669 {
1670 /* real, int -> real. */
1671 REAL_VALUE_TYPE result;
1672 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
8e6cdc90
RS
1673 wi::to_wide (arg1),
1674 REAL_MODE_FORMAT (mode)))
5c1a2e63
RS
1675 return build_real (type, result);
1676 }
1677 return NULL_TREE;
1678 }
1679
1680 if (integer_cst_p (arg0)
1681 && real_cst_p (arg1))
1682 {
1683 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1684 if (mode == arg1_mode)
1685 {
1686 /* int, real -> real. */
1687 REAL_VALUE_TYPE result;
8e6cdc90 1688 if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
5c1a2e63
RS
1689 TREE_REAL_CST_PTR (arg1),
1690 REAL_MODE_FORMAT (mode)))
1691 return build_real (type, result);
1692 }
1693 return NULL_TREE;
1694 }
1695
1696 if (arg0_mode == arg1_mode
1697 && complex_cst_p (arg0)
1698 && complex_cst_p (arg1))
1699 {
1700 gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1701 machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1702 tree arg0r = TREE_REALPART (arg0);
1703 tree arg0i = TREE_IMAGPART (arg0);
1704 tree arg1r = TREE_REALPART (arg1);
1705 tree arg1i = TREE_IMAGPART (arg1);
1706 if (mode == arg0_mode
1707 && real_cst_p (arg0r)
1708 && real_cst_p (arg0i)
1709 && real_cst_p (arg1r)
1710 && real_cst_p (arg1i))
1711 {
1712 /* complex real, complex real -> complex real. */
1713 REAL_VALUE_TYPE result_real, result_imag;
1714 if (fold_const_call_ccc (&result_real, &result_imag, fn,
1715 TREE_REAL_CST_PTR (arg0r),
1716 TREE_REAL_CST_PTR (arg0i),
1717 TREE_REAL_CST_PTR (arg1r),
1718 TREE_REAL_CST_PTR (arg1i),
1719 REAL_MODE_FORMAT (inner_mode)))
1720 return build_complex (type,
1721 build_real (TREE_TYPE (type), result_real),
1722 build_real (TREE_TYPE (type), result_imag));
1723 }
1724 return NULL_TREE;
1725 }
1726
1727 return NULL_TREE;
1728}
1729
df838ef0
RS
1730/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1731 otherwise return null. TYPE is the type of the return value. */
1732
1733tree
d7ebef06 1734fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
df838ef0
RS
1735{
1736 const char *p0, *p1;
bf2d0849 1737 char c;
4e31e63e 1738 tree_code subcode;
df838ef0
RS
1739 switch (fn)
1740 {
d7ebef06 1741 case CFN_BUILT_IN_STRSPN:
df838ef0
RS
1742 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1743 return build_int_cst (type, strspn (p0, p1));
1744 return NULL_TREE;
1745
d7ebef06 1746 case CFN_BUILT_IN_STRCSPN:
df838ef0
RS
1747 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1748 return build_int_cst (type, strcspn (p0, p1));
1749 return NULL_TREE;
1750
d7ebef06 1751 case CFN_BUILT_IN_STRCMP:
df838ef0
RS
1752 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1753 return build_cmp_result (type, strcmp (p0, p1));
1754 return NULL_TREE;
1755
a918bfbf
ML
1756 case CFN_BUILT_IN_STRCASECMP:
1757 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1758 {
1759 int r = strcmp (p0, p1);
1760 if (r == 0)
1761 return build_cmp_result (type, r);
1762 }
1763 return NULL_TREE;
1764
bf2d0849
JJ
1765 case CFN_BUILT_IN_INDEX:
1766 case CFN_BUILT_IN_STRCHR:
1767 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1768 {
1769 const char *r = strchr (p0, c);
1770 if (r == NULL)
1771 return build_int_cst (type, 0);
1772 return fold_convert (type,
1773 fold_build_pointer_plus_hwi (arg0, r - p0));
1774 }
1775 return NULL_TREE;
1776
1777 case CFN_BUILT_IN_RINDEX:
1778 case CFN_BUILT_IN_STRRCHR:
1779 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1780 {
1781 const char *r = strrchr (p0, c);
1782 if (r == NULL)
1783 return build_int_cst (type, 0);
1784 return fold_convert (type,
1785 fold_build_pointer_plus_hwi (arg0, r - p0));
1786 }
1787 return NULL_TREE;
1788
c8952930
JJ
1789 case CFN_BUILT_IN_STRSTR:
1790 if ((p1 = c_getstr (arg1)))
1791 {
1792 if ((p0 = c_getstr (arg0)))
1793 {
1794 const char *r = strstr (p0, p1);
1795 if (r == NULL)
1796 return build_int_cst (type, 0);
1797 return fold_convert (type,
1798 fold_build_pointer_plus_hwi (arg0, r - p0));
1799 }
1800 if (*p1 == '\0')
1801 return fold_convert (type, arg0);
1802 }
1803 return NULL_TREE;
1804
b781a135
RS
1805 case CFN_FOLD_LEFT_PLUS:
1806 return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1807
4e31e63e
JJ
1808 case CFN_UBSAN_CHECK_ADD:
1809 case CFN_ADD_OVERFLOW:
1810 subcode = PLUS_EXPR;
1811 goto arith_overflow;
1812
1813 case CFN_UBSAN_CHECK_SUB:
1814 case CFN_SUB_OVERFLOW:
1815 subcode = MINUS_EXPR;
1816 goto arith_overflow;
1817
1818 case CFN_UBSAN_CHECK_MUL:
1819 case CFN_MUL_OVERFLOW:
1820 subcode = MULT_EXPR;
1821 goto arith_overflow;
1822
1823 arith_overflow:
1824 if (integer_cst_p (arg0) && integer_cst_p (arg1))
1825 {
1826 tree itype
1827 = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
1828 bool ovf = false;
1829 tree r = int_const_binop (subcode, fold_convert (itype, arg0),
1830 fold_convert (itype, arg1));
1831 if (!r || TREE_CODE (r) != INTEGER_CST)
1832 return NULL_TREE;
1833 if (arith_overflowed_p (subcode, itype, arg0, arg1))
1834 ovf = true;
1835 if (TREE_OVERFLOW (r))
1836 r = drop_tree_overflow (r);
1837 if (itype == type)
1838 {
1839 if (ovf)
1840 return NULL_TREE;
1841 return r;
1842 }
1843 else
1844 return build_complex (type, r, build_int_cst (itype, ovf));
1845 }
1846 return NULL_TREE;
1847
df838ef0
RS
1848 default:
1849 return fold_const_call_1 (fn, type, arg0, arg1);
1850 }
1851}
1852
5c1a2e63
RS
1853/* Try to evaluate:
1854
1855 *RESULT = FN (*ARG0, *ARG1, *ARG2)
1856
1857 in format FORMAT. Return true on success. */
1858
1859static bool
d7ebef06 1860fold_const_call_ssss (real_value *result, combined_fn fn,
5c1a2e63
RS
1861 const real_value *arg0, const real_value *arg1,
1862 const real_value *arg2, const real_format *format)
1863{
1864 switch (fn)
1865 {
d7ebef06 1866 CASE_CFN_FMA:
ee5fd23a 1867 CASE_CFN_FMA_FN:
5c1a2e63
RS
1868 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1869
c566cc9f
RS
1870 case CFN_FMS:
1871 {
1872 real_value new_arg2 = real_value_negate (arg2);
1873 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
1874 }
1875
1876 case CFN_FNMA:
1877 {
1878 real_value new_arg0 = real_value_negate (arg0);
1879 return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
1880 }
1881
1882 case CFN_FNMS:
1883 {
1884 real_value new_arg0 = real_value_negate (arg0);
1885 real_value new_arg2 = real_value_negate (arg2);
1886 return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
1887 &new_arg2, format);
1888 }
1889
5c1a2e63
RS
1890 default:
1891 return false;
1892 }
1893}
1894
df838ef0
RS
1895/* Subroutine of fold_const_call, with the same interface. Handle cases
1896 where the arguments and result are numerical. */
5c1a2e63 1897
df838ef0 1898static tree
d7ebef06 1899fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
5c1a2e63
RS
1900{
1901 machine_mode mode = TYPE_MODE (type);
1902 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1903 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1904 machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1905
1906 if (arg0_mode == arg1_mode
1907 && arg0_mode == arg2_mode
1908 && real_cst_p (arg0)
1909 && real_cst_p (arg1)
1910 && real_cst_p (arg2))
1911 {
1912 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1913 if (mode == arg0_mode)
1914 {
1915 /* real, real, real -> real. */
1916 REAL_VALUE_TYPE result;
1917 if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1918 TREE_REAL_CST_PTR (arg1),
1919 TREE_REAL_CST_PTR (arg2),
1920 REAL_MODE_FORMAT (mode)))
1921 return build_real (type, result);
1922 }
1923 return NULL_TREE;
1924 }
1925
1926 return NULL_TREE;
1927}
1928
df838ef0
RS
1929/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
1930 success, otherwise return null. TYPE is the type of the return value. */
1931
1932tree
d7ebef06 1933fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
df838ef0
RS
1934{
1935 const char *p0, *p1;
66972191 1936 char c;
b7a0507a 1937 unsigned HOST_WIDE_INT s0, s1, s2 = 0;
df838ef0
RS
1938 switch (fn)
1939 {
d7ebef06 1940 case CFN_BUILT_IN_STRNCMP:
b7a0507a 1941 if (!size_t_cst_p (arg2, &s2))
a918bfbf 1942 return NULL_TREE;
66972191
JJ
1943 if (s2 == 0
1944 && !TREE_SIDE_EFFECTS (arg0)
1945 && !TREE_SIDE_EFFECTS (arg1))
1946 return build_int_cst (type, 0);
1947 else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
b7a0507a 1948 return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
66972191
JJ
1949 return NULL_TREE;
1950
a918bfbf 1951 case CFN_BUILT_IN_STRNCASECMP:
b7a0507a 1952 if (!size_t_cst_p (arg2, &s2))
a918bfbf 1953 return NULL_TREE;
66972191
JJ
1954 if (s2 == 0
1955 && !TREE_SIDE_EFFECTS (arg0)
1956 && !TREE_SIDE_EFFECTS (arg1))
1957 return build_int_cst (type, 0);
1958 else if ((p0 = c_getstr (arg0))
1959 && (p1 = c_getstr (arg1))
b7a0507a 1960 && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
66972191
JJ
1961 return build_int_cst (type, 0);
1962 return NULL_TREE;
1963
d7ebef06
RS
1964 case CFN_BUILT_IN_BCMP:
1965 case CFN_BUILT_IN_MEMCMP:
b7a0507a 1966 if (!size_t_cst_p (arg2, &s2))
66972191
JJ
1967 return NULL_TREE;
1968 if (s2 == 0
1969 && !TREE_SIDE_EFFECTS (arg0)
1970 && !TREE_SIDE_EFFECTS (arg1))
1971 return build_int_cst (type, 0);
866626ef
MS
1972 if ((p0 = getbyterep (arg0, &s0))
1973 && (p1 = getbyterep (arg1, &s1))
68c93708
ML
1974 && s2 <= s0
1975 && s2 <= s1)
df838ef0
RS
1976 return build_cmp_result (type, memcmp (p0, p1, s2));
1977 return NULL_TREE;
1978
66972191 1979 case CFN_BUILT_IN_MEMCHR:
b7a0507a 1980 if (!size_t_cst_p (arg2, &s2))
66972191
JJ
1981 return NULL_TREE;
1982 if (s2 == 0
1983 && !TREE_SIDE_EFFECTS (arg0)
1984 && !TREE_SIDE_EFFECTS (arg1))
1985 return build_int_cst (type, 0);
866626ef 1986 if ((p0 = getbyterep (arg0, &s0))
66972191
JJ
1987 && s2 <= s0
1988 && target_char_cst_p (arg1, &c))
1989 {
1990 const char *r = (const char *) memchr (p0, c, s2);
1991 if (r == NULL)
1992 return build_int_cst (type, 0);
1993 return fold_convert (type,
1994 fold_build_pointer_plus_hwi (arg0, r - p0));
1995 }
1996 return NULL_TREE;
1997
0b1fe8cf
RS
1998 case CFN_WHILE_ULT:
1999 {
2000 poly_uint64 parg0, parg1;
2001 if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
2002 return fold_while_ult (type, parg0, parg1);
2003 return NULL_TREE;
2004 }
2005
43a3252c
JJ
2006 case CFN_UADDC:
2007 case CFN_USUBC:
2008 if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
2009 {
2010 tree itype = TREE_TYPE (type);
2011 bool ovf = false;
2012 tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
2013 tree r = int_const_binop (subcode, fold_convert (itype, arg0),
2014 fold_convert (itype, arg1));
2015 if (!r)
2016 return NULL_TREE;
2017 if (arith_overflowed_p (subcode, itype, arg0, arg1))
2018 ovf = true;
2019 tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
2020 if (!r2 || TREE_CODE (r2) != INTEGER_CST)
2021 return NULL_TREE;
2022 if (arith_overflowed_p (subcode, itype, r, arg2))
2023 ovf = true;
2024 if (TREE_OVERFLOW (r2))
2025 r2 = drop_tree_overflow (r2);
2026 return build_complex (type, r2, build_int_cst (itype, ovf));
2027 }
2028 return NULL_TREE;
2029
df838ef0
RS
2030 default:
2031 return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2032 }
2033}