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