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