1/* Constant folding for calls to built-in and internal functions.
2 Copyright (C) 1988-2024 Free Software Foundation, Inc.
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"
27#include "fold-const.h"
28#include "fold-const-call.h"
29#include "case-cfn-macros.h"
30#include "tm.h" /* For C[LT]Z_DEFINED_VALUE_AT_ZERO. */
31#include "builtins.h"
32#include "gimple-expr.h"
33#include "tree-vector-builder.h"
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
56/* Return true if ARG is a size_type_node constant.
57 Store it in *SIZE_OUT if so. */
58
59static inline bool
60size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
61{
62 if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 && integer_cst_p (t)
64 && tree_fits_uhwi_p (t))
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
76tree
77build_cmp_result (tree type, int res)
78{
79 return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0);
80}
81
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;
101 real_from_mpfr (&tmp, m, format, MPFR_RNDN);
102
103 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
104 If the REAL_VALUE_TYPE is zero but the mpfr_t is not, then we
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;
132 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
133
134 auto_mpfr m (prec);
135 mpfr_from_real (m, arg, MPFR_RNDN);
136 mpfr_clear_flags ();
137 bool inexact = func (m, m, rnd);
138 bool ok = do_mpfr_ckconv (result, m, inexact, format);
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;
160 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
161 mpfr_t m, ms, mc;
162
163 mpfr_inits2 (prec, m, ms, mc, NULL);
164 mpfr_from_real (m, arg, MPFR_RNDN);
165 mpfr_clear_flags ();
166 bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
167 bool ok = (do_mpfr_ckconv (result: result_sin, m: ms, inexact, format)
168 && do_mpfr_ckconv (result: result_cos, m: 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;
193 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
194 mpfr_t m0, m1;
195
196 mpfr_inits2 (prec, m0, m1, NULL);
197 mpfr_from_real (m0, arg0, MPFR_RNDN);
198 mpfr_from_real (m1, arg1, MPFR_RNDN);
199 mpfr_clear_flags ();
200 bool inexact = func (m0, m0, m1, rnd);
201 bool ok = do_mpfr_ckconv (result, m: 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,
216 int (*func) (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t),
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;
224 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
225
226 auto_mpfr m (prec);
227 mpfr_from_real (m, arg1, MPFR_RNDN);
228 mpfr_clear_flags ();
229 bool inexact = func (m, arg0.to_shwi (), m, rnd);
230 bool ok = do_mpfr_ckconv (result, m, inexact, format);
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;
258 mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
259 mpfr_t m0, m1, m2;
260
261 mpfr_inits2 (prec, m0, m1, m2, NULL);
262 mpfr_from_real (m0, arg0, MPFR_RNDN);
263 mpfr_from_real (m1, arg1, MPFR_RNDN);
264 mpfr_from_real (m2, arg2, MPFR_RNDN);
265 mpfr_clear_flags ();
266 bool inexact = func (m0, m0, m1, m2, rnd);
267 bool ok = do_mpfr_ckconv (result, m: 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;
294 real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN);
295 real_from_mpfr (&tmp_imag, mpc_imagref (m), format, MPFR_RNDN);
296
297 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
298 If the REAL_VALUE_TYPE is zero but the mpfr_t is not, then we
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);
339 mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN);
340 mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN);
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);
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);
380 mpfr_clear_flags ();
381 bool inexact = func (m0, m0, m1, crnd);
382 bool ok = do_mpc_ckconv (result_real, result_imag, m: 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 }
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 }
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, func: 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);
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))))
518 return true;
519 }
520
521 return false;
522}
523
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
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 (x: 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 (x: arg1, y: -max_exp_adj) || wi::ges_p (x: arg1, y: max_exp_adj))
586 return false;
587
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
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
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
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{
627 unsigned HOST_WIDE_INT nelts;
628 if (TREE_CODE (arg) != VECTOR_CST
629 || !VECTOR_CST_NELTS (arg).is_constant (const_value: &nelts))
630 return NULL_TREE;
631
632 tree res = VECTOR_CST_ELT (arg, 0);
633 for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
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
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
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))));
668 tree_vector_builder elts;
669 if (!elts.new_unary_operation (shape: ret_type, vec: arg, allow_stepped_p: step_ok_p))
670 return NULL_TREE;
671
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 (obj: elt);
680 }
681
682 return elts.build ();
683}
684
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 (node: 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_value: &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
715/* Try to evaluate:
716
717 *RESULT = FN (*ARG)
718
719 in format FORMAT. Return true on success. */
720
721static bool
722fold_const_call_ss (real_value *result, combined_fn fn,
723 const real_value *arg, const real_format *format)
724{
725 switch (fn)
726 {
727 CASE_CFN_SQRT:
728 CASE_CFN_SQRT_FN:
729 return (real_compare (GE_EXPR, arg, &dconst0)
730 && do_mpfr_arg1 (result, func: mpfr_sqrt, arg, format));
731
732 CASE_CFN_CBRT:
733 CASE_CFN_CBRT_FN:
734 return do_mpfr_arg1 (result, func: mpfr_cbrt, arg, format);
735
736 CASE_CFN_ASIN:
737 CASE_CFN_ASIN_FN:
738 return (real_compare (GE_EXPR, arg, &dconstm1)
739 && real_compare (LE_EXPR, arg, &dconst1)
740 && do_mpfr_arg1 (result, func: mpfr_asin, arg, format));
741
742 CASE_CFN_ACOS:
743 CASE_CFN_ACOS_FN:
744 return (real_compare (GE_EXPR, arg, &dconstm1)
745 && real_compare (LE_EXPR, arg, &dconst1)
746 && do_mpfr_arg1 (result, func: mpfr_acos, arg, format));
747
748 CASE_CFN_ATAN:
749 CASE_CFN_ATAN_FN:
750 return do_mpfr_arg1 (result, func: mpfr_atan, arg, format);
751
752 CASE_CFN_ASINH:
753 CASE_CFN_ASINH_FN:
754 return do_mpfr_arg1 (result, func: mpfr_asinh, arg, format);
755
756 CASE_CFN_ACOSH:
757 CASE_CFN_ACOSH_FN:
758 return (real_compare (GE_EXPR, arg, &dconst1)
759 && do_mpfr_arg1 (result, func: mpfr_acosh, arg, format));
760
761 CASE_CFN_ATANH:
762 CASE_CFN_ATANH_FN:
763 return (real_compare (GE_EXPR, arg, &dconstm1)
764 && real_compare (LE_EXPR, arg, &dconst1)
765 && do_mpfr_arg1 (result, func: mpfr_atanh, arg, format));
766
767 CASE_CFN_SIN:
768 CASE_CFN_SIN_FN:
769 return do_mpfr_arg1 (result, func: mpfr_sin, arg, format);
770
771 CASE_CFN_COS:
772 CASE_CFN_COS_FN:
773 return do_mpfr_arg1 (result, func: mpfr_cos, arg, format);
774
775 CASE_CFN_TAN:
776 CASE_CFN_TAN_FN:
777 return do_mpfr_arg1 (result, func: mpfr_tan, arg, format);
778
779 CASE_CFN_SINH:
780 CASE_CFN_SINH_FN:
781 return do_mpfr_arg1 (result, func: mpfr_sinh, arg, format);
782
783 CASE_CFN_COSH:
784 CASE_CFN_COSH_FN:
785 return do_mpfr_arg1 (result, func: mpfr_cosh, arg, format);
786
787 CASE_CFN_TANH:
788 CASE_CFN_TANH_FN:
789 return do_mpfr_arg1 (result, func: mpfr_tanh, arg, format);
790
791 CASE_CFN_ERF:
792 CASE_CFN_ERF_FN:
793 return do_mpfr_arg1 (result, func: mpfr_erf, arg, format);
794
795 CASE_CFN_ERFC:
796 CASE_CFN_ERFC_FN:
797 return do_mpfr_arg1 (result, func: mpfr_erfc, arg, format);
798
799 CASE_CFN_TGAMMA:
800 CASE_CFN_TGAMMA_FN:
801 return do_mpfr_arg1 (result, func: mpfr_gamma, arg, format);
802
803 CASE_CFN_EXP:
804 CASE_CFN_EXP_FN:
805 return do_mpfr_arg1 (result, func: mpfr_exp, arg, format);
806
807 CASE_CFN_EXP2:
808 CASE_CFN_EXP2_FN:
809 return do_mpfr_arg1 (result, func: mpfr_exp2, arg, format);
810
811 CASE_CFN_EXP10:
812 CASE_CFN_POW10:
813 return do_mpfr_arg1 (result, func: mpfr_exp10, arg, format);
814
815 CASE_CFN_EXPM1:
816 CASE_CFN_EXPM1_FN:
817 return do_mpfr_arg1 (result, func: mpfr_expm1, arg, format);
818
819 CASE_CFN_LOG:
820 CASE_CFN_LOG_FN:
821 return (real_compare (GT_EXPR, arg, &dconst0)
822 && do_mpfr_arg1 (result, func: mpfr_log, arg, format));
823
824 CASE_CFN_LOG2:
825 CASE_CFN_LOG2_FN:
826 return (real_compare (GT_EXPR, arg, &dconst0)
827 && do_mpfr_arg1 (result, func: mpfr_log2, arg, format));
828
829 CASE_CFN_LOG10:
830 CASE_CFN_LOG10_FN:
831 return (real_compare (GT_EXPR, arg, &dconst0)
832 && do_mpfr_arg1 (result, func: mpfr_log10, arg, format));
833
834 CASE_CFN_LOG1P:
835 CASE_CFN_LOG1P_FN:
836 return (real_compare (GT_EXPR, arg, &dconstm1)
837 && do_mpfr_arg1 (result, func: mpfr_log1p, arg, format));
838
839 CASE_CFN_J0:
840 return do_mpfr_arg1 (result, func: mpfr_j0, arg, format);
841
842 CASE_CFN_J1:
843 return do_mpfr_arg1 (result, func: mpfr_j1, arg, format);
844
845 CASE_CFN_Y0:
846 return (real_compare (GT_EXPR, arg, &dconst0)
847 && do_mpfr_arg1 (result, func: mpfr_y0, arg, format));
848
849 CASE_CFN_Y1:
850 return (real_compare (GT_EXPR, arg, &dconst0)
851 && do_mpfr_arg1 (result, func: mpfr_y1, arg, format));
852
853 CASE_CFN_FLOOR:
854 CASE_CFN_FLOOR_FN:
855 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
856 {
857 real_floor (result, format, arg);
858 return true;
859 }
860 return false;
861
862 CASE_CFN_CEIL:
863 CASE_CFN_CEIL_FN:
864 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
865 {
866 real_ceil (result, format, arg);
867 return true;
868 }
869 return false;
870
871 CASE_CFN_TRUNC:
872 CASE_CFN_TRUNC_FN:
873 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
874 {
875 real_trunc (result, format, arg);
876 return true;
877 }
878 return false;
879
880 CASE_CFN_ROUND:
881 CASE_CFN_ROUND_FN:
882 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
883 {
884 real_round (result, format, arg);
885 return true;
886 }
887 return false;
888
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
898 CASE_CFN_LOGB:
899 CASE_CFN_LOGB_FN:
900 return fold_const_logb (result, arg, format);
901
902 CASE_CFN_SIGNIFICAND:
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
918fold_const_call_ss (wide_int *result, combined_fn fn,
919 const real_value *arg, unsigned int precision,
920 const real_format *format)
921{
922 switch (fn)
923 {
924 CASE_CFN_SIGNBIT:
925 if (real_isneg (arg))
926 *result = wi::one (precision);
927 else
928 *result = wi::zero (precision);
929 return true;
930
931 CASE_CFN_ILOGB:
932 CASE_CFN_ILOGB_FN:
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
944 CASE_CFN_ICEIL:
945 CASE_CFN_LCEIL:
946 CASE_CFN_LLCEIL:
947 return fold_const_conversion (result, fn: real_ceil, arg,
948 precision, format);
949
950 CASE_CFN_LFLOOR:
951 CASE_CFN_IFLOOR:
952 CASE_CFN_LLFLOOR:
953 return fold_const_conversion (result, fn: real_floor, arg,
954 precision, format);
955
956 CASE_CFN_IROUND:
957 CASE_CFN_LROUND:
958 CASE_CFN_LROUND_FN:
959 CASE_CFN_LLROUND:
960 CASE_CFN_LLROUND_FN:
961 return fold_const_conversion (result, fn: real_round, arg,
962 precision, format);
963
964 CASE_CFN_IRINT:
965 CASE_CFN_LRINT:
966 CASE_CFN_LRINT_FN:
967 CASE_CFN_LLRINT:
968 CASE_CFN_LLRINT_FN:
969 /* Not yet folded to a constant. */
970 return false;
971
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:
977 *result = wi::shwi (val: real_isfinite (arg) ? 1 : 0, precision);
978 return true;
979
980 case CFN_BUILT_IN_ISSIGNALING:
981 *result = wi::shwi (val: real_issignaling_nan (arg) ? 1 : 0, precision);
982 return true;
983
984 CASE_CFN_ISINF:
985 case CFN_BUILT_IN_ISINFD32:
986 case CFN_BUILT_IN_ISINFD64:
987 case CFN_BUILT_IN_ISINFD128:
988 if (real_isinf (arg))
989 *result = wi::shwi (val: arg->sign ? -1 : 1, precision);
990 else
991 *result = wi::shwi (val: 0, precision);
992 return true;
993
994 CASE_CFN_ISNAN:
995 case CFN_BUILT_IN_ISNAND32:
996 case CFN_BUILT_IN_ISNAND64:
997 case CFN_BUILT_IN_ISNAND128:
998 *result = wi::shwi (val: real_isnan (arg) ? 1 : 0, precision);
999 return true;
1000
1001 default:
1002 return false;
1003 }
1004}
1005
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
1014fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1015 unsigned int precision, tree arg_type)
1016{
1017 switch (fn)
1018 {
1019 CASE_CFN_FFS:
1020 case CFN_BUILT_IN_FFSG:
1021 *result = wi::shwi (val: wi::ffs (arg), precision);
1022 return true;
1023
1024 CASE_CFN_CLZ:
1025 case CFN_BUILT_IN_CLZG:
1026 {
1027 int tmp;
1028 if (wi::ne_p (x: arg, y: 0))
1029 tmp = wi::clz (arg);
1030 else if (TREE_CODE (arg_type) == BITINT_TYPE)
1031 tmp = TYPE_PRECISION (arg_type);
1032 else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1033 tmp))
1034 tmp = TYPE_PRECISION (arg_type);
1035 *result = wi::shwi (val: tmp, precision);
1036 return true;
1037 }
1038
1039 CASE_CFN_CTZ:
1040 case CFN_BUILT_IN_CTZG:
1041 {
1042 int tmp;
1043 if (wi::ne_p (x: arg, y: 0))
1044 tmp = wi::ctz (arg);
1045 else if (TREE_CODE (arg_type) == BITINT_TYPE)
1046 tmp = TYPE_PRECISION (arg_type);
1047 else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1048 tmp))
1049 tmp = TYPE_PRECISION (arg_type);
1050 *result = wi::shwi (val: tmp, precision);
1051 return true;
1052 }
1053
1054 CASE_CFN_CLRSB:
1055 case CFN_BUILT_IN_CLRSBG:
1056 *result = wi::shwi (val: wi::clrsb (arg), precision);
1057 return true;
1058
1059 CASE_CFN_POPCOUNT:
1060 case CFN_BUILT_IN_POPCOUNTG:
1061 *result = wi::shwi (val: wi::popcount (arg), precision);
1062 return true;
1063
1064 CASE_CFN_PARITY:
1065 case CFN_BUILT_IN_PARITYG:
1066 *result = wi::shwi (val: wi::parity (x: arg), precision);
1067 return true;
1068
1069 case CFN_BUILT_IN_BSWAP16:
1070 case CFN_BUILT_IN_BSWAP32:
1071 case CFN_BUILT_IN_BSWAP64:
1072 case CFN_BUILT_IN_BSWAP128:
1073 *result = wi::bswap (x: wide_int::from (x: arg, precision,
1074 TYPE_SIGN (arg_type)));
1075 return true;
1076
1077 default:
1078 return false;
1079 }
1080}
1081
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,
1092 combined_fn fn, const real_value *arg,
1093 const real_format *format)
1094{
1095 switch (fn)
1096 {
1097 CASE_CFN_CEXPI:
1098 /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1099 return do_mpfr_sincos (result_sin: result_imag, result_cos: 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
1115fold_const_call_sc (real_value *result, combined_fn fn,
1116 const real_value *arg_real, const real_value *arg_imag,
1117 const real_format *format)
1118{
1119 switch (fn)
1120 {
1121 CASE_CFN_CABS:
1122 CASE_CFN_CABS_FN:
1123 return do_mpfr_arg2 (result, func: mpfr_hypot, arg0: arg_real, arg1: 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,
1140 combined_fn fn, const real_value *arg_real,
1141 const real_value *arg_imag, const real_format *format)
1142{
1143 switch (fn)
1144 {
1145 CASE_CFN_CCOS:
1146 CASE_CFN_CCOS_FN:
1147 return do_mpc_arg1 (result_real, result_imag, func: mpc_cos,
1148 arg_real, arg_imag, format);
1149
1150 CASE_CFN_CCOSH:
1151 CASE_CFN_CCOSH_FN:
1152 return do_mpc_arg1 (result_real, result_imag, func: mpc_cosh,
1153 arg_real, arg_imag, format);
1154
1155 CASE_CFN_CPROJ:
1156 CASE_CFN_CPROJ_FN:
1157 if (real_isinf (arg_real) || real_isinf (arg_imag))
1158 {
1159 *result_real = dconstinf;
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
1170 CASE_CFN_CSIN:
1171 CASE_CFN_CSIN_FN:
1172 return do_mpc_arg1 (result_real, result_imag, func: mpc_sin,
1173 arg_real, arg_imag, format);
1174
1175 CASE_CFN_CSINH:
1176 CASE_CFN_CSINH_FN:
1177 return do_mpc_arg1 (result_real, result_imag, func: mpc_sinh,
1178 arg_real, arg_imag, format);
1179
1180 CASE_CFN_CTAN:
1181 CASE_CFN_CTAN_FN:
1182 return do_mpc_arg1 (result_real, result_imag, func: mpc_tan,
1183 arg_real, arg_imag, format);
1184
1185 CASE_CFN_CTANH:
1186 CASE_CFN_CTANH_FN:
1187 return do_mpc_arg1 (result_real, result_imag, func: mpc_tanh,
1188 arg_real, arg_imag, format);
1189
1190 CASE_CFN_CLOG:
1191 CASE_CFN_CLOG_FN:
1192 return do_mpc_arg1 (result_real, result_imag, func: mpc_log,
1193 arg_real, arg_imag, format);
1194
1195 CASE_CFN_CSQRT:
1196 CASE_CFN_CSQRT_FN:
1197 return do_mpc_arg1 (result_real, result_imag, func: mpc_sqrt,
1198 arg_real, arg_imag, format);
1199
1200 CASE_CFN_CASIN:
1201 CASE_CFN_CASIN_FN:
1202 return do_mpc_arg1 (result_real, result_imag, func: mpc_asin,
1203 arg_real, arg_imag, format);
1204
1205 CASE_CFN_CACOS:
1206 CASE_CFN_CACOS_FN:
1207 return do_mpc_arg1 (result_real, result_imag, func: mpc_acos,
1208 arg_real, arg_imag, format);
1209
1210 CASE_CFN_CATAN:
1211 CASE_CFN_CATAN_FN:
1212 return do_mpc_arg1 (result_real, result_imag, func: mpc_atan,
1213 arg_real, arg_imag, format);
1214
1215 CASE_CFN_CASINH:
1216 CASE_CFN_CASINH_FN:
1217 return do_mpc_arg1 (result_real, result_imag, func: mpc_asinh,
1218 arg_real, arg_imag, format);
1219
1220 CASE_CFN_CACOSH:
1221 CASE_CFN_CACOSH_FN:
1222 return do_mpc_arg1 (result_real, result_imag, func: mpc_acosh,
1223 arg_real, arg_imag, format);
1224
1225 CASE_CFN_CATANH:
1226 CASE_CFN_CATANH_FN:
1227 return do_mpc_arg1 (result_real, result_imag, func: mpc_atanh,
1228 arg_real, arg_imag, format);
1229
1230 CASE_CFN_CEXP:
1231 CASE_CFN_CEXP_FN:
1232 return do_mpc_arg1 (result_real, result_imag, func: mpc_exp,
1233 arg_real, arg_imag, format);
1234
1235 default:
1236 return false;
1237 }
1238}
1239
1240/* Subroutine of fold_const_call, with the same interface. Handle cases
1241 where the arguments and result are numerical. */
1242
1243static tree
1244fold_const_call_1 (combined_fn fn, tree type, tree arg)
1245{
1246 machine_mode mode = TYPE_MODE (type);
1247 machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1248
1249 if (integer_cst_p (t: arg))
1250 {
1251 if (SCALAR_INT_MODE_P (mode))
1252 {
1253 wide_int result;
1254 if (fold_const_call_ss (result: &result, fn, arg: wi::to_wide (t: arg),
1255 TYPE_PRECISION (type), TREE_TYPE (arg)))
1256 return wide_int_to_tree (type, cst: result);
1257 }
1258 return NULL_TREE;
1259 }
1260
1261 if (real_cst_p (t: 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: &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_real, result_imag: &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: &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, cst: result);
1293 }
1294 return NULL_TREE;
1295 }
1296
1297 if (complex_cst_p (t: 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 (t: argr)
1305 && real_cst_p (t: argi))
1306 {
1307 /* complex real -> complex real. */
1308 REAL_VALUE_TYPE result_real, result_imag;
1309 if (fold_const_call_cc (result_real: &result_real, result_imag: &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 (t: argr)
1319 && real_cst_p (t: argi))
1320 {
1321 /* complex real -> real. */
1322 REAL_VALUE_TYPE result;
1323 if (fold_const_call_sc (result: &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
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
1339fold_const_call (combined_fn fn, tree type, tree arg)
1340{
1341 switch (fn)
1342 {
1343 case CFN_BUILT_IN_STRLEN:
1344 if (const char *str = c_getstr (arg))
1345 return build_int_cst (type, strlen (s: str));
1346 return NULL_TREE;
1347
1348 CASE_CFN_NAN:
1349 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1350 case CFN_BUILT_IN_NAND32:
1351 case CFN_BUILT_IN_NAND64:
1352 case CFN_BUILT_IN_NAND128:
1353 return fold_const_builtin_nan (type, arg, quiet: true);
1354
1355 CASE_CFN_NANS:
1356 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1357 case CFN_BUILT_IN_NANSF16B:
1358 case CFN_BUILT_IN_NANSD32:
1359 case CFN_BUILT_IN_NANSD64:
1360 case CFN_BUILT_IN_NANSD128:
1361 return fold_const_builtin_nan (type, arg, quiet: false);
1362
1363 case CFN_REDUC_PLUS:
1364 return fold_const_reduction (type, arg, code: PLUS_EXPR);
1365
1366 case CFN_REDUC_MAX:
1367 return fold_const_reduction (type, arg, code: MAX_EXPR);
1368
1369 case CFN_REDUC_MIN:
1370 return fold_const_reduction (type, arg, code: MIN_EXPR);
1371
1372 case CFN_REDUC_AND:
1373 return fold_const_reduction (type, arg, code: BIT_AND_EXPR);
1374
1375 case CFN_REDUC_IOR:
1376 return fold_const_reduction (type, arg, code: BIT_IOR_EXPR);
1377
1378 case CFN_REDUC_XOR:
1379 return fold_const_reduction (type, arg, code: BIT_XOR_EXPR);
1380
1381 case CFN_VEC_CONVERT:
1382 return fold_const_vec_convert (ret_type: type, arg);
1383
1384 default:
1385 return fold_const_call_1 (fn, type, arg);
1386 }
1387}
1388
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 (const_value: &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
1411/* Try to evaluate:
1412
1413 *RESULT = FN (*ARG0, *ARG1)
1414
1415 in format FORMAT. Return true on success. */
1416
1417static bool
1418fold_const_call_sss (real_value *result, combined_fn fn,
1419 const real_value *arg0, const real_value *arg1,
1420 const real_format *format)
1421{
1422 switch (fn)
1423 {
1424 CASE_CFN_DREM:
1425 CASE_CFN_REMAINDER:
1426 CASE_CFN_REMAINDER_FN:
1427 return do_mpfr_arg2 (result, func: mpfr_remainder, arg0, arg1, format);
1428
1429 CASE_CFN_ATAN2:
1430 CASE_CFN_ATAN2_FN:
1431 return do_mpfr_arg2 (result, func: mpfr_atan2, arg0, arg1, format);
1432
1433 CASE_CFN_FDIM:
1434 CASE_CFN_FDIM_FN:
1435 return do_mpfr_arg2 (result, func: mpfr_dim, arg0, arg1, format);
1436
1437 CASE_CFN_FMOD:
1438 CASE_CFN_FMOD_FN:
1439 return do_mpfr_arg2 (result, func: mpfr_fmod, arg0, arg1, format);
1440
1441 CASE_CFN_HYPOT:
1442 CASE_CFN_HYPOT_FN:
1443 return do_mpfr_arg2 (result, func: mpfr_hypot, arg0, arg1, format);
1444
1445 CASE_CFN_COPYSIGN:
1446 CASE_CFN_COPYSIGN_FN:
1447 *result = *arg0;
1448 real_copysign (result, arg1);
1449 return true;
1450
1451 CASE_CFN_FMIN:
1452 CASE_CFN_FMIN_FN:
1453 return do_mpfr_arg2 (result, func: mpfr_min, arg0, arg1, format);
1454
1455 CASE_CFN_FMAX:
1456 CASE_CFN_FMAX_FN:
1457 return do_mpfr_arg2 (result, func: mpfr_max, arg0, arg1, format);
1458
1459 CASE_CFN_POW:
1460 CASE_CFN_POW_FN:
1461 return fold_const_pow (result, arg0, arg1, format);
1462
1463 CASE_CFN_NEXTAFTER:
1464 CASE_CFN_NEXTAFTER_FN:
1465 case CFN_BUILT_IN_NEXTAFTERF16B:
1466 CASE_CFN_NEXTTOWARD:
1467 return fold_const_nextafter (result, arg0, arg1, format);
1468
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
1482fold_const_call_sss (real_value *result, combined_fn fn,
1483 const real_value *arg0, const wide_int_ref &arg1,
1484 const real_format *format)
1485{
1486 switch (fn)
1487 {
1488 CASE_CFN_LDEXP:
1489 CASE_CFN_LDEXP_FN:
1490 return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1491
1492 CASE_CFN_SCALBN:
1493 CASE_CFN_SCALBN_FN:
1494 CASE_CFN_SCALBLN:
1495 CASE_CFN_SCALBLN_FN:
1496 return (format->b == 2
1497 && fold_const_builtin_load_exponent (result, arg0, arg1,
1498 format));
1499
1500 CASE_CFN_POWI:
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
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
1524fold_const_call_sss (real_value *result, combined_fn fn,
1525 const wide_int_ref &arg0, const real_value *arg1,
1526 const real_format *format)
1527{
1528 switch (fn)
1529 {
1530 CASE_CFN_JN:
1531 return do_mpfr_arg2 (result, func: mpfr_jn, arg0, arg1, format);
1532
1533 CASE_CFN_YN:
1534 return (real_compare (GT_EXPR, arg1, &dconst0)
1535 && do_mpfr_arg2 (result, func: mpfr_yn, arg0, arg1, format));
1536
1537 default:
1538 return false;
1539 }
1540}
1541
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 (x: arg0, y: 0))
1561 tmp = wi::clz (arg0);
1562 else
1563 tmp = arg1.to_shwi ();
1564 *result = wi::shwi (val: 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 (x: arg0, y: 0))
1573 tmp = wi::ctz (arg0);
1574 else
1575 tmp = arg1.to_shwi ();
1576 *result = wi::shwi (val: tmp, precision);
1577 return true;
1578 }
1579
1580 default:
1581 return false;
1582 }
1583}
1584
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,
1595 combined_fn fn, const real_value *arg0_real,
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 {
1601 CASE_CFN_CPOW:
1602 CASE_CFN_CPOW_FN:
1603 return do_mpc_arg2 (result_real, result_imag, func: mpc_pow,
1604 arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1605
1606 default:
1607 return false;
1608 }
1609}
1610
1611/* Subroutine of fold_const_call, with the same interface. Handle cases
1612 where the arguments and result are numerical. */
1613
1614static tree
1615fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
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
1621 if (integer_cst_p (t: arg0) && integer_cst_p (t: arg1))
1622 {
1623 if (SCALAR_INT_MODE_P (mode))
1624 {
1625 wide_int result;
1626 if (fold_const_call_sss (result: &result, fn, arg0: wi::to_wide (t: arg0),
1627 arg1: wi::to_wide (t: arg1), TYPE_PRECISION (type),
1628 TREE_TYPE (arg0)))
1629 return wide_int_to_tree (type, cst: result);
1630 }
1631 return NULL_TREE;
1632 }
1633
1634 if (mode == arg0_mode
1635 && real_cst_p (t: arg0)
1636 && real_cst_p (t: arg1))
1637 {
1638 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1639 REAL_VALUE_TYPE result;
1640 if (arg0_mode == arg1_mode)
1641 {
1642 /* real, real -> real. */
1643 if (fold_const_call_sss (result: &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 }
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: &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 }
1661 return NULL_TREE;
1662 }
1663
1664 if (real_cst_p (t: arg0)
1665 && integer_cst_p (t: 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: &result, fn, TREE_REAL_CST_PTR (arg0),
1673 arg1: wi::to_wide (t: arg1),
1674 REAL_MODE_FORMAT (mode)))
1675 return build_real (type, result);
1676 }
1677 return NULL_TREE;
1678 }
1679
1680 if (integer_cst_p (t: arg0)
1681 && real_cst_p (t: 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;
1688 if (fold_const_call_sss (result: &result, fn, arg0: wi::to_wide (t: arg0),
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 (t: arg0)
1698 && complex_cst_p (t: 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 (t: arg0r)
1708 && real_cst_p (t: arg0i)
1709 && real_cst_p (t: arg1r)
1710 && real_cst_p (t: 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_real, result_imag: &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
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
1734fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1735{
1736 const char *p0, *p1;
1737 char c;
1738 tree_code subcode;
1739 switch (fn)
1740 {
1741 case CFN_BUILT_IN_STRSPN:
1742 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1743 return build_int_cst (type, strspn (s: p0, accept: p1));
1744 return NULL_TREE;
1745
1746 case CFN_BUILT_IN_STRCSPN:
1747 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1748 return build_int_cst (type, strcspn (s: p0, reject: p1));
1749 return NULL_TREE;
1750
1751 case CFN_BUILT_IN_STRCMP:
1752 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1753 return build_cmp_result (type, res: strcmp (s1: p0, s2: p1));
1754 return NULL_TREE;
1755
1756 case CFN_BUILT_IN_STRCASECMP:
1757 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1758 {
1759 int r = strcmp (s1: p0, s2: p1);
1760 if (r == 0)
1761 return build_cmp_result (type, res: r);
1762 }
1763 return NULL_TREE;
1764
1765 case CFN_BUILT_IN_INDEX:
1766 case CFN_BUILT_IN_STRCHR:
1767 if ((p0 = c_getstr (arg0)) && target_char_cst_p (t: arg1, p: &c))
1768 {
1769 const char *r = strchr (s: p0, c: 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 (t: arg1, p: &c))
1780 {
1781 const char *r = strrchr (s: p0, c: 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
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 (haystack: p0, needle: 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
1805 case CFN_FOLD_LEFT_PLUS:
1806 return fold_const_fold_left (type, arg0, arg1, code: PLUS_EXPR);
1807
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 (t: arg0) && integer_cst_p (t: 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
1848 default:
1849 return fold_const_call_1 (fn, type, arg0, arg1);
1850 }
1851}
1852
1853/* Try to evaluate:
1854
1855 *RESULT = FN (*ARG0, *ARG1, *ARG2)
1856
1857 in format FORMAT. Return true on success. */
1858
1859static bool
1860fold_const_call_ssss (real_value *result, combined_fn fn,
1861 const real_value *arg0, const real_value *arg1,
1862 const real_value *arg2, const real_format *format)
1863{
1864 switch (fn)
1865 {
1866 CASE_CFN_FMA:
1867 CASE_CFN_FMA_FN:
1868 return do_mpfr_arg3 (result, func: mpfr_fma, arg0, arg1, arg2, format);
1869
1870 case CFN_FMS:
1871 {
1872 real_value new_arg2 = real_value_negate (arg2);
1873 return do_mpfr_arg3 (result, func: mpfr_fma, arg0, arg1, arg2: &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, func: mpfr_fma, arg0: &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, func: mpfr_fma, arg0: &new_arg0, arg1,
1887 arg2: &new_arg2, format);
1888 }
1889
1890 default:
1891 return false;
1892 }
1893}
1894
1895/* Subroutine of fold_const_call, with the same interface. Handle cases
1896 where the arguments and result are numerical. */
1897
1898static tree
1899fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
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 (t: arg0)
1909 && real_cst_p (t: arg1)
1910 && real_cst_p (t: 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: &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
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
1933fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
1934{
1935 const char *p0, *p1;
1936 char c;
1937 unsigned HOST_WIDE_INT s0, s1, s2 = 0;
1938 switch (fn)
1939 {
1940 case CFN_BUILT_IN_STRNCMP:
1941 if (!size_t_cst_p (t: arg2, size_out: &s2))
1942 return NULL_TREE;
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)))
1948 return build_int_cst (type, strncmp (s1: p0, s2: p1, MIN (s2, SIZE_MAX)));
1949 return NULL_TREE;
1950
1951 case CFN_BUILT_IN_STRNCASECMP:
1952 if (!size_t_cst_p (t: arg2, size_out: &s2))
1953 return NULL_TREE;
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))
1960 && strncmp (s1: p0, s2: p1, MIN (s2, SIZE_MAX)) == 0)
1961 return build_int_cst (type, 0);
1962 return NULL_TREE;
1963
1964 case CFN_BUILT_IN_BCMP:
1965 case CFN_BUILT_IN_MEMCMP:
1966 if (!size_t_cst_p (t: arg2, size_out: &s2))
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);
1972 if ((p0 = getbyterep (arg0, &s0))
1973 && (p1 = getbyterep (arg1, &s1))
1974 && s2 <= s0
1975 && s2 <= s1)
1976 return build_cmp_result (type, res: memcmp (s1: p0, s2: p1, n: s2));
1977 return NULL_TREE;
1978
1979 case CFN_BUILT_IN_MEMCHR:
1980 if (!size_t_cst_p (t: arg2, size_out: &s2))
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);
1986 if ((p0 = getbyterep (arg0, &s0))
1987 && s2 <= s0
1988 && target_char_cst_p (t: arg1, p: &c))
1989 {
1990 const char *r = (const char *) memchr (s: p0, c: c, n: 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
1998 case CFN_WHILE_ULT:
1999 {
2000 poly_uint64 parg0, parg1;
2001 if (poly_int_tree_p (t: arg0, value: &parg0) && poly_int_tree_p (t: arg1, value: &parg1))
2002 return fold_while_ult (type, arg0: parg0, arg1: parg1);
2003 return NULL_TREE;
2004 }
2005
2006 case CFN_UADDC:
2007 case CFN_USUBC:
2008 if (integer_cst_p (t: arg0) && integer_cst_p (t: arg1) && integer_cst_p (t: 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
2030 default:
2031 return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2032 }
2033}
2034

source code of gcc/fold-const-call.cc