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