]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fold-const-call.cc
Merge remote-tracking branch 'origin/master' into devel/c++-contracts
[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:
7f940822 737 CASE_CFN_CBRT_FN:
5c1a2e63
RS
738 return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
739
d7ebef06 740 CASE_CFN_ASIN:
7f940822 741 CASE_CFN_ASIN_FN:
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:
7f940822 747 CASE_CFN_ACOS_FN:
5c1a2e63
RS
748 return (real_compare (GE_EXPR, arg, &dconstm1)
749 && real_compare (LE_EXPR, arg, &dconst1)
750 && do_mpfr_arg1 (result, mpfr_acos, arg, format));
751
d7ebef06 752 CASE_CFN_ATAN:
7f940822 753 CASE_CFN_ATAN_FN:
5c1a2e63
RS
754 return do_mpfr_arg1 (result, mpfr_atan, arg, format);
755
d7ebef06 756 CASE_CFN_ASINH:
7f940822 757 CASE_CFN_ASINH_FN:
5c1a2e63
RS
758 return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
759
d7ebef06 760 CASE_CFN_ACOSH:
7f940822 761 CASE_CFN_ACOSH_FN:
5c1a2e63
RS
762 return (real_compare (GE_EXPR, arg, &dconst1)
763 && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
764
d7ebef06 765 CASE_CFN_ATANH:
7f940822 766 CASE_CFN_ATANH_FN:
5c1a2e63
RS
767 return (real_compare (GE_EXPR, arg, &dconstm1)
768 && real_compare (LE_EXPR, arg, &dconst1)
769 && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
770
d7ebef06 771 CASE_CFN_SIN:
7f940822 772 CASE_CFN_SIN_FN:
5c1a2e63
RS
773 return do_mpfr_arg1 (result, mpfr_sin, arg, format);
774
d7ebef06 775 CASE_CFN_COS:
7f940822 776 CASE_CFN_COS_FN:
5c1a2e63
RS
777 return do_mpfr_arg1 (result, mpfr_cos, arg, format);
778
d7ebef06 779 CASE_CFN_TAN:
7f940822 780 CASE_CFN_TAN_FN:
5c1a2e63
RS
781 return do_mpfr_arg1 (result, mpfr_tan, arg, format);
782
d7ebef06 783 CASE_CFN_SINH:
7f940822 784 CASE_CFN_SINH_FN:
5c1a2e63
RS
785 return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
786
d7ebef06 787 CASE_CFN_COSH:
7f940822 788 CASE_CFN_COSH_FN:
5c1a2e63
RS
789 return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
790
d7ebef06 791 CASE_CFN_TANH:
7f940822 792 CASE_CFN_TANH_FN:
5c1a2e63
RS
793 return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
794
d7ebef06 795 CASE_CFN_ERF:
7f940822 796 CASE_CFN_ERF_FN:
5c1a2e63
RS
797 return do_mpfr_arg1 (result, mpfr_erf, arg, format);
798
d7ebef06 799 CASE_CFN_ERFC:
7f940822 800 CASE_CFN_ERFC_FN:
5c1a2e63
RS
801 return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
802
d7ebef06 803 CASE_CFN_TGAMMA:
7f940822 804 CASE_CFN_TGAMMA_FN:
5c1a2e63
RS
805 return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
806
d7ebef06 807 CASE_CFN_EXP:
7f940822 808 CASE_CFN_EXP_FN:
5c1a2e63
RS
809 return do_mpfr_arg1 (result, mpfr_exp, arg, format);
810
d7ebef06 811 CASE_CFN_EXP2:
7f940822 812 CASE_CFN_EXP2_FN:
5c1a2e63
RS
813 return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
814
d7ebef06
RS
815 CASE_CFN_EXP10:
816 CASE_CFN_POW10:
5c1a2e63
RS
817 return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
818
d7ebef06 819 CASE_CFN_EXPM1:
7f940822 820 CASE_CFN_EXPM1_FN:
5c1a2e63
RS
821 return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
822
d7ebef06 823 CASE_CFN_LOG:
7f940822 824 CASE_CFN_LOG_FN:
5c1a2e63
RS
825 return (real_compare (GT_EXPR, arg, &dconst0)
826 && do_mpfr_arg1 (result, mpfr_log, arg, format));
827
d7ebef06 828 CASE_CFN_LOG2:
7f940822 829 CASE_CFN_LOG2_FN:
5c1a2e63
RS
830 return (real_compare (GT_EXPR, arg, &dconst0)
831 && do_mpfr_arg1 (result, mpfr_log2, arg, format));
832
d7ebef06 833 CASE_CFN_LOG10:
7f940822 834 CASE_CFN_LOG10_FN:
5c1a2e63
RS
835 return (real_compare (GT_EXPR, arg, &dconst0)
836 && do_mpfr_arg1 (result, mpfr_log10, arg, format));
837
d7ebef06 838 CASE_CFN_LOG1P:
7f940822 839 CASE_CFN_LOG1P_FN:
5c1a2e63
RS
840 return (real_compare (GT_EXPR, arg, &dconstm1)
841 && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
842
d7ebef06 843 CASE_CFN_J0:
5c1a2e63
RS
844 return do_mpfr_arg1 (result, mpfr_j0, arg, format);
845
d7ebef06 846 CASE_CFN_J1:
5c1a2e63
RS
847 return do_mpfr_arg1 (result, mpfr_j1, arg, format);
848
d7ebef06 849 CASE_CFN_Y0:
5c1a2e63
RS
850 return (real_compare (GT_EXPR, arg, &dconst0)
851 && do_mpfr_arg1 (result, mpfr_y0, arg, format));
852
d7ebef06 853 CASE_CFN_Y1:
5c1a2e63
RS
854 return (real_compare (GT_EXPR, arg, &dconst0)
855 && do_mpfr_arg1 (result, mpfr_y1, arg, format));
856
d7ebef06 857 CASE_CFN_FLOOR:
c6cfa2bf 858 CASE_CFN_FLOOR_FN:
7d7b99f9 859 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
5c1a2e63
RS
860 {
861 real_floor (result, format, arg);
862 return true;
863 }
864 return false;
865
d7ebef06 866 CASE_CFN_CEIL:
c6cfa2bf 867 CASE_CFN_CEIL_FN:
7d7b99f9 868 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
5c1a2e63
RS
869 {
870 real_ceil (result, format, arg);
871 return true;
872 }
873 return false;
874
d7ebef06 875 CASE_CFN_TRUNC:
c6cfa2bf 876 CASE_CFN_TRUNC_FN:
7d7b99f9
TJ
877 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
878 {
879 real_trunc (result, format, arg);
880 return true;
881 }
882 return false;
5c1a2e63 883
d7ebef06 884 CASE_CFN_ROUND:
c6cfa2bf 885 CASE_CFN_ROUND_FN:
7d7b99f9 886 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
5c1a2e63
RS
887 {
888 real_round (result, format, arg);
889 return true;
890 }
891 return false;
892
7d7b99f9
TJ
893 CASE_CFN_ROUNDEVEN:
894 CASE_CFN_ROUNDEVEN_FN:
895 if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
896 {
897 real_roundeven (result, format, arg);
898 return true;
899 }
900 return false;
901
d7ebef06 902 CASE_CFN_LOGB:
7f940822 903 CASE_CFN_LOGB_FN:
5c1a2e63
RS
904 return fold_const_logb (result, arg, format);
905
d7ebef06 906 CASE_CFN_SIGNIFICAND:
5c1a2e63
RS
907 return fold_const_significand (result, arg, format);
908
909 default:
910 return false;
911 }
912}
913
914/* Try to evaluate:
915
916 *RESULT = FN (*ARG)
917
918 where FORMAT is the format of ARG and PRECISION is the number of
919 significant bits in the result. Return true on success. */
920
921static bool
d7ebef06 922fold_const_call_ss (wide_int *result, combined_fn fn,
5c1a2e63
RS
923 const real_value *arg, unsigned int precision,
924 const real_format *format)
925{
926 switch (fn)
927 {
d7ebef06 928 CASE_CFN_SIGNBIT:
5c1a2e63
RS
929 if (real_isneg (arg))
930 *result = wi::one (precision);
931 else
932 *result = wi::zero (precision);
933 return true;
934
d7ebef06 935 CASE_CFN_ILOGB:
7f940822 936 CASE_CFN_ILOGB_FN:
5c1a2e63
RS
937 /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
938 Proceed iff radix == 2. In GCC, normalized significands are in
939 the range [0.5, 1.0). We want the exponent as if they were
940 [1.0, 2.0) so get the exponent and subtract 1. */
941 if (arg->cl == rvc_normal && format->b == 2)
942 {
943 *result = wi::shwi (REAL_EXP (arg) - 1, precision);
944 return true;
945 }
946 return false;
947
d7ebef06
RS
948 CASE_CFN_ICEIL:
949 CASE_CFN_LCEIL:
950 CASE_CFN_LLCEIL:
5c1a2e63
RS
951 return fold_const_conversion (result, real_ceil, arg,
952 precision, format);
953
d7ebef06
RS
954 CASE_CFN_LFLOOR:
955 CASE_CFN_IFLOOR:
956 CASE_CFN_LLFLOOR:
5c1a2e63
RS
957 return fold_const_conversion (result, real_floor, arg,
958 precision, format);
959
d7ebef06
RS
960 CASE_CFN_IROUND:
961 CASE_CFN_LROUND:
7f940822 962 CASE_CFN_LROUND_FN:
d7ebef06 963 CASE_CFN_LLROUND:
7f940822 964 CASE_CFN_LLROUND_FN:
5c1a2e63
RS
965 return fold_const_conversion (result, real_round, arg,
966 precision, format);
967
d7ebef06
RS
968 CASE_CFN_IRINT:
969 CASE_CFN_LRINT:
7f940822 970 CASE_CFN_LRINT_FN:
d7ebef06 971 CASE_CFN_LLRINT:
7f940822 972 CASE_CFN_LLRINT_FN:
5c1a2e63
RS
973 /* Not yet folded to a constant. */
974 return false;
975
d7ebef06
RS
976 CASE_CFN_FINITE:
977 case CFN_BUILT_IN_FINITED32:
978 case CFN_BUILT_IN_FINITED64:
979 case CFN_BUILT_IN_FINITED128:
980 case CFN_BUILT_IN_ISFINITE:
2556a032
RS
981 *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
982 return true;
983
0982edd3
JJ
984 case CFN_BUILT_IN_ISSIGNALING:
985 *result = wi::shwi (real_issignaling_nan (arg) ? 1 : 0, precision);
986 return true;
987
d7ebef06
RS
988 CASE_CFN_ISINF:
989 case CFN_BUILT_IN_ISINFD32:
990 case CFN_BUILT_IN_ISINFD64:
991 case CFN_BUILT_IN_ISINFD128:
2556a032
RS
992 if (real_isinf (arg))
993 *result = wi::shwi (arg->sign ? -1 : 1, precision);
994 else
995 *result = wi::shwi (0, precision);
996 return true;
997
d7ebef06
RS
998 CASE_CFN_ISNAN:
999 case CFN_BUILT_IN_ISNAND32:
1000 case CFN_BUILT_IN_ISNAND64:
1001 case CFN_BUILT_IN_ISNAND128:
2556a032
RS
1002 *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
1003 return true;
1004
5c1a2e63
RS
1005 default:
1006 return false;
1007 }
1008}
1009
db9bd5d5
RS
1010/* Try to evaluate:
1011
1012 *RESULT = FN (ARG)
1013
1014 where ARG_TYPE is the type of ARG and PRECISION is the number of bits
1015 in the result. Return true on success. */
1016
1017static bool
d7ebef06
RS
1018fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1019 unsigned int precision, tree arg_type)
db9bd5d5
RS
1020{
1021 switch (fn)
1022 {
d7ebef06 1023 CASE_CFN_FFS:
db9bd5d5
RS
1024 *result = wi::shwi (wi::ffs (arg), precision);
1025 return true;
1026
d7ebef06 1027 CASE_CFN_CLZ:
db9bd5d5
RS
1028 {
1029 int tmp;
1030 if (wi::ne_p (arg, 0))
1031 tmp = wi::clz (arg);
7a504f33
RS
1032 else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1033 tmp))
db9bd5d5
RS
1034 tmp = TYPE_PRECISION (arg_type);
1035 *result = wi::shwi (tmp, precision);
1036 return true;
1037 }
1038
d7ebef06 1039 CASE_CFN_CTZ:
db9bd5d5
RS
1040 {
1041 int tmp;
1042 if (wi::ne_p (arg, 0))
1043 tmp = wi::ctz (arg);
7a504f33
RS
1044 else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1045 tmp))
db9bd5d5
RS
1046 tmp = TYPE_PRECISION (arg_type);
1047 *result = wi::shwi (tmp, precision);
1048 return true;
1049 }
1050
d7ebef06 1051 CASE_CFN_CLRSB:
db9bd5d5
RS
1052 *result = wi::shwi (wi::clrsb (arg), precision);
1053 return true;
1054
d7ebef06 1055 CASE_CFN_POPCOUNT:
db9bd5d5
RS
1056 *result = wi::shwi (wi::popcount (arg), precision);
1057 return true;
1058
d7ebef06 1059 CASE_CFN_PARITY:
db9bd5d5
RS
1060 *result = wi::shwi (wi::parity (arg), precision);
1061 return true;
1062
d7ebef06
RS
1063 case CFN_BUILT_IN_BSWAP16:
1064 case CFN_BUILT_IN_BSWAP32:
1065 case CFN_BUILT_IN_BSWAP64:
fe7ebef7 1066 case CFN_BUILT_IN_BSWAP128:
db9bd5d5
RS
1067 *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
1068 return true;
1069
1070 default:
1071 return false;
1072 }
1073}
1074
5c1a2e63
RS
1075/* Try to evaluate:
1076
1077 RESULT = FN (*ARG)
1078
1079 where FORMAT is the format of ARG and of the real and imaginary parts
1080 of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
1081 true on success. */
1082
1083static bool
1084fold_const_call_cs (real_value *result_real, real_value *result_imag,
d7ebef06 1085 combined_fn fn, const real_value *arg,
5c1a2e63
RS
1086 const real_format *format)
1087{
1088 switch (fn)
1089 {
d7ebef06 1090 CASE_CFN_CEXPI:
5c1a2e63
RS
1091 /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1092 return do_mpfr_sincos (result_imag, result_real, arg, format);
1093
1094 default:
1095 return false;
1096 }
1097}
1098
1099/* Try to evaluate:
1100
1101 *RESULT = fn (ARG)
1102
1103 where FORMAT is the format of RESULT and of the real and imaginary parts
1104 of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
1105 success. */
1106
1107static bool
d7ebef06 1108fold_const_call_sc (real_value *result, combined_fn fn,
5c1a2e63
RS
1109 const real_value *arg_real, const real_value *arg_imag,
1110 const real_format *format)
1111{
1112 switch (fn)
1113 {
d7ebef06 1114 CASE_CFN_CABS:
259a1155 1115 CASE_CFN_CABS_FN:
5c1a2e63
RS
1116 return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1117
1118 default:
1119 return false;
1120 }
1121}
1122
1123/* Try to evaluate:
1124
1125 RESULT = fn (ARG)
1126
1127 where FORMAT is the format of the real and imaginary parts of RESULT
1128 (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1129 Return true on success. */
1130
1131static bool
1132fold_const_call_cc (real_value *result_real, real_value *result_imag,
d7ebef06 1133 combined_fn fn, const real_value *arg_real,
5c1a2e63
RS
1134 const real_value *arg_imag, const real_format *format)
1135{
1136 switch (fn)
1137 {
d7ebef06 1138 CASE_CFN_CCOS:
259a1155 1139 CASE_CFN_CCOS_FN:
5c1a2e63
RS
1140 return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1141 arg_real, arg_imag, format);
1142
d7ebef06 1143 CASE_CFN_CCOSH:
259a1155 1144 CASE_CFN_CCOSH_FN:
5c1a2e63
RS
1145 return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1146 arg_real, arg_imag, format);
1147
d7ebef06 1148 CASE_CFN_CPROJ:
259a1155 1149 CASE_CFN_CPROJ_FN:
5c1a2e63
RS
1150 if (real_isinf (arg_real) || real_isinf (arg_imag))
1151 {
bb9d4344 1152 *result_real = dconstinf;
5c1a2e63
RS
1153 *result_imag = dconst0;
1154 result_imag->sign = arg_imag->sign;
1155 }
1156 else
1157 {
1158 *result_real = *arg_real;
1159 *result_imag = *arg_imag;
1160 }
1161 return true;
1162
d7ebef06 1163 CASE_CFN_CSIN:
259a1155 1164 CASE_CFN_CSIN_FN:
5c1a2e63
RS
1165 return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1166 arg_real, arg_imag, format);
1167
d7ebef06 1168 CASE_CFN_CSINH:
259a1155 1169 CASE_CFN_CSINH_FN:
5c1a2e63
RS
1170 return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1171 arg_real, arg_imag, format);
1172
d7ebef06 1173 CASE_CFN_CTAN:
259a1155 1174 CASE_CFN_CTAN_FN:
5c1a2e63
RS
1175 return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1176 arg_real, arg_imag, format);
1177
d7ebef06 1178 CASE_CFN_CTANH:
259a1155 1179 CASE_CFN_CTANH_FN:
5c1a2e63
RS
1180 return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1181 arg_real, arg_imag, format);
1182
d7ebef06 1183 CASE_CFN_CLOG:
259a1155 1184 CASE_CFN_CLOG_FN:
5c1a2e63
RS
1185 return do_mpc_arg1 (result_real, result_imag, mpc_log,
1186 arg_real, arg_imag, format);
1187
d7ebef06 1188 CASE_CFN_CSQRT:
259a1155 1189 CASE_CFN_CSQRT_FN:
5c1a2e63
RS
1190 return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1191 arg_real, arg_imag, format);
1192
d7ebef06 1193 CASE_CFN_CASIN:
259a1155 1194 CASE_CFN_CASIN_FN:
5c1a2e63
RS
1195 return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1196 arg_real, arg_imag, format);
1197
d7ebef06 1198 CASE_CFN_CACOS:
259a1155 1199 CASE_CFN_CACOS_FN:
5c1a2e63
RS
1200 return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1201 arg_real, arg_imag, format);
1202
d7ebef06 1203 CASE_CFN_CATAN:
259a1155 1204 CASE_CFN_CATAN_FN:
5c1a2e63
RS
1205 return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1206 arg_real, arg_imag, format);
1207
d7ebef06 1208 CASE_CFN_CASINH:
259a1155 1209 CASE_CFN_CASINH_FN:
5c1a2e63
RS
1210 return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1211 arg_real, arg_imag, format);
1212
d7ebef06 1213 CASE_CFN_CACOSH:
259a1155 1214 CASE_CFN_CACOSH_FN:
5c1a2e63
RS
1215 return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1216 arg_real, arg_imag, format);
1217
d7ebef06 1218 CASE_CFN_CATANH:
259a1155 1219 CASE_CFN_CATANH_FN:
5c1a2e63
RS
1220 return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1221 arg_real, arg_imag, format);
1222
d7ebef06 1223 CASE_CFN_CEXP:
259a1155 1224 CASE_CFN_CEXP_FN:
5c1a2e63
RS
1225 return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1226 arg_real, arg_imag, format);
1227
1228 default:
1229 return false;
1230 }
1231}
1232
df838ef0
RS
1233/* Subroutine of fold_const_call, with the same interface. Handle cases
1234 where the arguments and result are numerical. */
5c1a2e63 1235
df838ef0 1236static tree
d7ebef06 1237fold_const_call_1 (combined_fn fn, tree type, tree arg)
5c1a2e63
RS
1238{
1239 machine_mode mode = TYPE_MODE (type);
1240 machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1241
db9bd5d5
RS
1242 if (integer_cst_p (arg))
1243 {
1244 if (SCALAR_INT_MODE_P (mode))
1245 {
1246 wide_int result;
8e6cdc90
RS
1247 if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1248 TYPE_PRECISION (type), TREE_TYPE (arg)))
db9bd5d5
RS
1249 return wide_int_to_tree (type, result);
1250 }
1251 return NULL_TREE;
1252 }
1253
5c1a2e63
RS
1254 if (real_cst_p (arg))
1255 {
1256 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1257 if (mode == arg_mode)
1258 {
1259 /* real -> real. */
1260 REAL_VALUE_TYPE result;
1261 if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1262 REAL_MODE_FORMAT (mode)))
1263 return build_real (type, result);
1264 }
1265 else if (COMPLEX_MODE_P (mode)
1266 && GET_MODE_INNER (mode) == arg_mode)
1267 {
1268 /* real -> complex real. */
1269 REAL_VALUE_TYPE result_real, result_imag;
1270 if (fold_const_call_cs (&result_real, &result_imag, fn,
1271 TREE_REAL_CST_PTR (arg),
1272 REAL_MODE_FORMAT (arg_mode)))
1273 return build_complex (type,
1274 build_real (TREE_TYPE (type), result_real),
1275 build_real (TREE_TYPE (type), result_imag));
1276 }
1277 else if (INTEGRAL_TYPE_P (type))
1278 {
1279 /* real -> int. */
1280 wide_int result;
1281 if (fold_const_call_ss (&result, fn,
1282 TREE_REAL_CST_PTR (arg),
1283 TYPE_PRECISION (type),
1284 REAL_MODE_FORMAT (arg_mode)))
1285 return wide_int_to_tree (type, result);
1286 }
1287 return NULL_TREE;
1288 }
1289
1290 if (complex_cst_p (arg))
1291 {
1292 gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1293 machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1294 tree argr = TREE_REALPART (arg);
1295 tree argi = TREE_IMAGPART (arg);
1296 if (mode == arg_mode
1297 && real_cst_p (argr)
1298 && real_cst_p (argi))
1299 {
1300 /* complex real -> complex real. */
1301 REAL_VALUE_TYPE result_real, result_imag;
1302 if (fold_const_call_cc (&result_real, &result_imag, fn,
1303 TREE_REAL_CST_PTR (argr),
1304 TREE_REAL_CST_PTR (argi),
1305 REAL_MODE_FORMAT (inner_mode)))
1306 return build_complex (type,
1307 build_real (TREE_TYPE (type), result_real),
1308 build_real (TREE_TYPE (type), result_imag));
1309 }
1310 if (mode == inner_mode
1311 && real_cst_p (argr)
1312 && real_cst_p (argi))
1313 {
1314 /* complex real -> real. */
1315 REAL_VALUE_TYPE result;
1316 if (fold_const_call_sc (&result, fn,
1317 TREE_REAL_CST_PTR (argr),
1318 TREE_REAL_CST_PTR (argi),
1319 REAL_MODE_FORMAT (inner_mode)))
1320 return build_real (type, result);
1321 }
1322 return NULL_TREE;
1323 }
1324
1325 return NULL_TREE;
1326}
1327
df838ef0
RS
1328/* Try to fold FN (ARG) to a constant. Return the constant on success,
1329 otherwise return null. TYPE is the type of the return value. */
1330
1331tree
d7ebef06 1332fold_const_call (combined_fn fn, tree type, tree arg)
df838ef0
RS
1333{
1334 switch (fn)
1335 {
d7ebef06 1336 case CFN_BUILT_IN_STRLEN:
df838ef0
RS
1337 if (const char *str = c_getstr (arg))
1338 return build_int_cst (type, strlen (str));
1339 return NULL_TREE;
1340
d7ebef06 1341 CASE_CFN_NAN:
6dc198e3 1342 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
d7ebef06
RS
1343 case CFN_BUILT_IN_NAND32:
1344 case CFN_BUILT_IN_NAND64:
1345 case CFN_BUILT_IN_NAND128:
df838ef0
RS
1346 return fold_const_builtin_nan (type, arg, true);
1347
d7ebef06 1348 CASE_CFN_NANS:
6dc198e3 1349 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
c2565a31 1350 case CFN_BUILT_IN_NANSF16B:
6c8e4f4d
JM
1351 case CFN_BUILT_IN_NANSD32:
1352 case CFN_BUILT_IN_NANSD64:
1353 case CFN_BUILT_IN_NANSD128:
df838ef0
RS
1354 return fold_const_builtin_nan (type, arg, false);
1355
16d24520
RS
1356 case CFN_REDUC_PLUS:
1357 return fold_const_reduction (type, arg, PLUS_EXPR);
1358
1359 case CFN_REDUC_MAX:
1360 return fold_const_reduction (type, arg, MAX_EXPR);
1361
1362 case CFN_REDUC_MIN:
1363 return fold_const_reduction (type, arg, MIN_EXPR);
1364
898f07b0
RS
1365 case CFN_REDUC_AND:
1366 return fold_const_reduction (type, arg, BIT_AND_EXPR);
1367
1368 case CFN_REDUC_IOR:
1369 return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1370
1371 case CFN_REDUC_XOR:
1372 return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1373
d8fcab68
JJ
1374 case CFN_VEC_CONVERT:
1375 return fold_const_vec_convert (type, arg);
1376
df838ef0
RS
1377 default:
1378 return fold_const_call_1 (fn, type, arg);
1379 }
1380}
1381
b781a135
RS
1382/* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1383 of type TYPE. */
1384
1385static tree
1386fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1387{
1388 if (TREE_CODE (arg1) != VECTOR_CST)
1389 return NULL_TREE;
1390
1391 unsigned HOST_WIDE_INT nelts;
1392 if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1393 return NULL_TREE;
1394
1395 for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1396 {
1397 arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1398 if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1399 return NULL_TREE;
1400 }
1401 return arg0;
1402}
1403
5c1a2e63
RS
1404/* Try to evaluate:
1405
1406 *RESULT = FN (*ARG0, *ARG1)
1407
1408 in format FORMAT. Return true on success. */
1409
1410static bool
d7ebef06 1411fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1412 const real_value *arg0, const real_value *arg1,
1413 const real_format *format)
1414{
1415 switch (fn)
1416 {
d7ebef06
RS
1417 CASE_CFN_DREM:
1418 CASE_CFN_REMAINDER:
7f940822 1419 CASE_CFN_REMAINDER_FN:
5c1a2e63
RS
1420 return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1421
d7ebef06 1422 CASE_CFN_ATAN2:
7f940822 1423 CASE_CFN_ATAN2_FN:
5c1a2e63
RS
1424 return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1425
d7ebef06 1426 CASE_CFN_FDIM:
7f940822 1427 CASE_CFN_FDIM_FN:
5c1a2e63
RS
1428 return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1429
2c17b5f8 1430 CASE_CFN_FMOD:
7f940822 1431 CASE_CFN_FMOD_FN:
2c17b5f8
RS
1432 return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
1433
d7ebef06 1434 CASE_CFN_HYPOT:
7f940822 1435 CASE_CFN_HYPOT_FN:
5c1a2e63
RS
1436 return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1437
d7ebef06 1438 CASE_CFN_COPYSIGN:
ee5fd23a 1439 CASE_CFN_COPYSIGN_FN:
5c1a2e63
RS
1440 *result = *arg0;
1441 real_copysign (result, arg1);
1442 return true;
1443
d7ebef06 1444 CASE_CFN_FMIN:
ee5fd23a 1445 CASE_CFN_FMIN_FN:
5c1a2e63
RS
1446 return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1447
d7ebef06 1448 CASE_CFN_FMAX:
ee5fd23a 1449 CASE_CFN_FMAX_FN:
5c1a2e63
RS
1450 return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1451
d7ebef06 1452 CASE_CFN_POW:
7f940822 1453 CASE_CFN_POW_FN:
5c1a2e63
RS
1454 return fold_const_pow (result, arg0, arg1, format);
1455
04782385 1456 CASE_CFN_NEXTAFTER:
7f940822 1457 CASE_CFN_NEXTAFTER_FN:
29490c2a 1458 case CFN_BUILT_IN_NEXTAFTERF16B:
04782385
JJ
1459 CASE_CFN_NEXTTOWARD:
1460 return fold_const_nextafter (result, arg0, arg1, format);
1461
5c1a2e63
RS
1462 default:
1463 return false;
1464 }
1465}
1466
1467/* Try to evaluate:
1468
1469 *RESULT = FN (*ARG0, ARG1)
1470
1471 where FORMAT is the format of *RESULT and *ARG0. Return true on
1472 success. */
1473
1474static bool
d7ebef06 1475fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1476 const real_value *arg0, const wide_int_ref &arg1,
1477 const real_format *format)
1478{
1479 switch (fn)
1480 {
d7ebef06 1481 CASE_CFN_LDEXP:
7f940822 1482 CASE_CFN_LDEXP_FN:
5c1a2e63
RS
1483 return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1484
d7ebef06 1485 CASE_CFN_SCALBN:
7f940822 1486 CASE_CFN_SCALBN_FN:
d7ebef06 1487 CASE_CFN_SCALBLN:
7f940822 1488 CASE_CFN_SCALBLN_FN:
5c1a2e63
RS
1489 return (format->b == 2
1490 && fold_const_builtin_load_exponent (result, arg0, arg1,
1491 format));
1492
d7ebef06 1493 CASE_CFN_POWI:
5a00b0aa
SS
1494 /* Avoid the folding if flag_signaling_nans is on and
1495 operand is a signaling NaN. */
1496 if (!flag_unsafe_math_optimizations
1497 && flag_signaling_nans
1498 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1499 return false;
1500
5c1a2e63
RS
1501 real_powi (result, format, arg0, arg1.to_shwi ());
1502 return true;
1503
1504 default:
1505 return false;
1506 }
1507}
1508
1509/* Try to evaluate:
1510
1511 *RESULT = FN (ARG0, *ARG1)
1512
1513 where FORMAT is the format of *RESULT and *ARG1. Return true on
1514 success. */
1515
1516static bool
d7ebef06 1517fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1518 const wide_int_ref &arg0, const real_value *arg1,
1519 const real_format *format)
1520{
1521 switch (fn)
1522 {
d7ebef06 1523 CASE_CFN_JN:
5c1a2e63
RS
1524 return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1525
d7ebef06 1526 CASE_CFN_YN:
5c1a2e63
RS
1527 return (real_compare (GT_EXPR, arg1, &dconst0)
1528 && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1529
1530 default:
1531 return false;
1532 }
1533}
1534
1535/* Try to evaluate:
1536
1537 RESULT = fn (ARG0, ARG1)
1538
1539 where FORMAT is the format of the real and imaginary parts of RESULT
1540 (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1541 and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1542
1543static bool
1544fold_const_call_ccc (real_value *result_real, real_value *result_imag,
d7ebef06 1545 combined_fn fn, const real_value *arg0_real,
5c1a2e63
RS
1546 const real_value *arg0_imag, const real_value *arg1_real,
1547 const real_value *arg1_imag, const real_format *format)
1548{
1549 switch (fn)
1550 {
d7ebef06 1551 CASE_CFN_CPOW:
259a1155 1552 CASE_CFN_CPOW_FN:
5c1a2e63
RS
1553 return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1554 arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1555
1556 default:
1557 return false;
1558 }
1559}
1560
df838ef0
RS
1561/* Subroutine of fold_const_call, with the same interface. Handle cases
1562 where the arguments and result are numerical. */
5c1a2e63 1563
df838ef0 1564static tree
d7ebef06 1565fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
5c1a2e63
RS
1566{
1567 machine_mode mode = TYPE_MODE (type);
1568 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1569 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1570
04782385 1571 if (mode == arg0_mode
5c1a2e63
RS
1572 && real_cst_p (arg0)
1573 && real_cst_p (arg1))
1574 {
1575 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
04782385
JJ
1576 REAL_VALUE_TYPE result;
1577 if (arg0_mode == arg1_mode)
5c1a2e63
RS
1578 {
1579 /* real, real -> real. */
5c1a2e63
RS
1580 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1581 TREE_REAL_CST_PTR (arg1),
1582 REAL_MODE_FORMAT (mode)))
1583 return build_real (type, result);
1584 }
04782385
JJ
1585 else if (arg1_mode == TYPE_MODE (long_double_type_node))
1586 switch (fn)
1587 {
1588 CASE_CFN_NEXTTOWARD:
1589 /* real, long double -> real. */
1590 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1591 TREE_REAL_CST_PTR (arg1),
1592 REAL_MODE_FORMAT (mode)))
1593 return build_real (type, result);
1594 break;
1595 default:
1596 break;
1597 }
5c1a2e63
RS
1598 return NULL_TREE;
1599 }
1600
1601 if (real_cst_p (arg0)
1602 && integer_cst_p (arg1))
1603 {
1604 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1605 if (mode == arg0_mode)
1606 {
1607 /* real, int -> real. */
1608 REAL_VALUE_TYPE result;
1609 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
8e6cdc90
RS
1610 wi::to_wide (arg1),
1611 REAL_MODE_FORMAT (mode)))
5c1a2e63
RS
1612 return build_real (type, result);
1613 }
1614 return NULL_TREE;
1615 }
1616
1617 if (integer_cst_p (arg0)
1618 && real_cst_p (arg1))
1619 {
1620 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1621 if (mode == arg1_mode)
1622 {
1623 /* int, real -> real. */
1624 REAL_VALUE_TYPE result;
8e6cdc90 1625 if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
5c1a2e63
RS
1626 TREE_REAL_CST_PTR (arg1),
1627 REAL_MODE_FORMAT (mode)))
1628 return build_real (type, result);
1629 }
1630 return NULL_TREE;
1631 }
1632
1633 if (arg0_mode == arg1_mode
1634 && complex_cst_p (arg0)
1635 && complex_cst_p (arg1))
1636 {
1637 gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1638 machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1639 tree arg0r = TREE_REALPART (arg0);
1640 tree arg0i = TREE_IMAGPART (arg0);
1641 tree arg1r = TREE_REALPART (arg1);
1642 tree arg1i = TREE_IMAGPART (arg1);
1643 if (mode == arg0_mode
1644 && real_cst_p (arg0r)
1645 && real_cst_p (arg0i)
1646 && real_cst_p (arg1r)
1647 && real_cst_p (arg1i))
1648 {
1649 /* complex real, complex real -> complex real. */
1650 REAL_VALUE_TYPE result_real, result_imag;
1651 if (fold_const_call_ccc (&result_real, &result_imag, fn,
1652 TREE_REAL_CST_PTR (arg0r),
1653 TREE_REAL_CST_PTR (arg0i),
1654 TREE_REAL_CST_PTR (arg1r),
1655 TREE_REAL_CST_PTR (arg1i),
1656 REAL_MODE_FORMAT (inner_mode)))
1657 return build_complex (type,
1658 build_real (TREE_TYPE (type), result_real),
1659 build_real (TREE_TYPE (type), result_imag));
1660 }
1661 return NULL_TREE;
1662 }
1663
1664 return NULL_TREE;
1665}
1666
df838ef0
RS
1667/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1668 otherwise return null. TYPE is the type of the return value. */
1669
1670tree
d7ebef06 1671fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
df838ef0
RS
1672{
1673 const char *p0, *p1;
bf2d0849 1674 char c;
df838ef0
RS
1675 switch (fn)
1676 {
d7ebef06 1677 case CFN_BUILT_IN_STRSPN:
df838ef0
RS
1678 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1679 return build_int_cst (type, strspn (p0, p1));
1680 return NULL_TREE;
1681
d7ebef06 1682 case CFN_BUILT_IN_STRCSPN:
df838ef0
RS
1683 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1684 return build_int_cst (type, strcspn (p0, p1));
1685 return NULL_TREE;
1686
d7ebef06 1687 case CFN_BUILT_IN_STRCMP:
df838ef0
RS
1688 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1689 return build_cmp_result (type, strcmp (p0, p1));
1690 return NULL_TREE;
1691
a918bfbf
ML
1692 case CFN_BUILT_IN_STRCASECMP:
1693 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1694 {
1695 int r = strcmp (p0, p1);
1696 if (r == 0)
1697 return build_cmp_result (type, r);
1698 }
1699 return NULL_TREE;
1700
bf2d0849
JJ
1701 case CFN_BUILT_IN_INDEX:
1702 case CFN_BUILT_IN_STRCHR:
1703 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1704 {
1705 const char *r = strchr (p0, c);
1706 if (r == NULL)
1707 return build_int_cst (type, 0);
1708 return fold_convert (type,
1709 fold_build_pointer_plus_hwi (arg0, r - p0));
1710 }
1711 return NULL_TREE;
1712
1713 case CFN_BUILT_IN_RINDEX:
1714 case CFN_BUILT_IN_STRRCHR:
1715 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1716 {
1717 const char *r = strrchr (p0, c);
1718 if (r == NULL)
1719 return build_int_cst (type, 0);
1720 return fold_convert (type,
1721 fold_build_pointer_plus_hwi (arg0, r - p0));
1722 }
1723 return NULL_TREE;
1724
c8952930
JJ
1725 case CFN_BUILT_IN_STRSTR:
1726 if ((p1 = c_getstr (arg1)))
1727 {
1728 if ((p0 = c_getstr (arg0)))
1729 {
1730 const char *r = strstr (p0, p1);
1731 if (r == NULL)
1732 return build_int_cst (type, 0);
1733 return fold_convert (type,
1734 fold_build_pointer_plus_hwi (arg0, r - p0));
1735 }
1736 if (*p1 == '\0')
1737 return fold_convert (type, arg0);
1738 }
1739 return NULL_TREE;
1740
b781a135
RS
1741 case CFN_FOLD_LEFT_PLUS:
1742 return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1743
df838ef0
RS
1744 default:
1745 return fold_const_call_1 (fn, type, arg0, arg1);
1746 }
1747}
1748
5c1a2e63
RS
1749/* Try to evaluate:
1750
1751 *RESULT = FN (*ARG0, *ARG1, *ARG2)
1752
1753 in format FORMAT. Return true on success. */
1754
1755static bool
d7ebef06 1756fold_const_call_ssss (real_value *result, combined_fn fn,
5c1a2e63
RS
1757 const real_value *arg0, const real_value *arg1,
1758 const real_value *arg2, const real_format *format)
1759{
1760 switch (fn)
1761 {
d7ebef06 1762 CASE_CFN_FMA:
ee5fd23a 1763 CASE_CFN_FMA_FN:
5c1a2e63
RS
1764 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1765
c566cc9f
RS
1766 case CFN_FMS:
1767 {
1768 real_value new_arg2 = real_value_negate (arg2);
1769 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
1770 }
1771
1772 case CFN_FNMA:
1773 {
1774 real_value new_arg0 = real_value_negate (arg0);
1775 return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
1776 }
1777
1778 case CFN_FNMS:
1779 {
1780 real_value new_arg0 = real_value_negate (arg0);
1781 real_value new_arg2 = real_value_negate (arg2);
1782 return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
1783 &new_arg2, format);
1784 }
1785
5c1a2e63
RS
1786 default:
1787 return false;
1788 }
1789}
1790
df838ef0
RS
1791/* Subroutine of fold_const_call, with the same interface. Handle cases
1792 where the arguments and result are numerical. */
5c1a2e63 1793
df838ef0 1794static tree
d7ebef06 1795fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
5c1a2e63
RS
1796{
1797 machine_mode mode = TYPE_MODE (type);
1798 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1799 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1800 machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1801
1802 if (arg0_mode == arg1_mode
1803 && arg0_mode == arg2_mode
1804 && real_cst_p (arg0)
1805 && real_cst_p (arg1)
1806 && real_cst_p (arg2))
1807 {
1808 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1809 if (mode == arg0_mode)
1810 {
1811 /* real, real, real -> real. */
1812 REAL_VALUE_TYPE result;
1813 if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1814 TREE_REAL_CST_PTR (arg1),
1815 TREE_REAL_CST_PTR (arg2),
1816 REAL_MODE_FORMAT (mode)))
1817 return build_real (type, result);
1818 }
1819 return NULL_TREE;
1820 }
1821
1822 return NULL_TREE;
1823}
1824
df838ef0
RS
1825/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
1826 success, otherwise return null. TYPE is the type of the return value. */
1827
1828tree
d7ebef06 1829fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
df838ef0
RS
1830{
1831 const char *p0, *p1;
66972191 1832 char c;
b7a0507a 1833 unsigned HOST_WIDE_INT s0, s1, s2 = 0;
df838ef0
RS
1834 switch (fn)
1835 {
d7ebef06 1836 case CFN_BUILT_IN_STRNCMP:
b7a0507a 1837 if (!size_t_cst_p (arg2, &s2))
a918bfbf 1838 return NULL_TREE;
66972191
JJ
1839 if (s2 == 0
1840 && !TREE_SIDE_EFFECTS (arg0)
1841 && !TREE_SIDE_EFFECTS (arg1))
1842 return build_int_cst (type, 0);
1843 else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
b7a0507a 1844 return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
66972191
JJ
1845 return NULL_TREE;
1846
a918bfbf 1847 case CFN_BUILT_IN_STRNCASECMP:
b7a0507a 1848 if (!size_t_cst_p (arg2, &s2))
a918bfbf 1849 return NULL_TREE;
66972191
JJ
1850 if (s2 == 0
1851 && !TREE_SIDE_EFFECTS (arg0)
1852 && !TREE_SIDE_EFFECTS (arg1))
1853 return build_int_cst (type, 0);
1854 else if ((p0 = c_getstr (arg0))
1855 && (p1 = c_getstr (arg1))
b7a0507a 1856 && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
66972191
JJ
1857 return build_int_cst (type, 0);
1858 return NULL_TREE;
1859
d7ebef06
RS
1860 case CFN_BUILT_IN_BCMP:
1861 case CFN_BUILT_IN_MEMCMP:
b7a0507a 1862 if (!size_t_cst_p (arg2, &s2))
66972191
JJ
1863 return NULL_TREE;
1864 if (s2 == 0
1865 && !TREE_SIDE_EFFECTS (arg0)
1866 && !TREE_SIDE_EFFECTS (arg1))
1867 return build_int_cst (type, 0);
866626ef
MS
1868 if ((p0 = getbyterep (arg0, &s0))
1869 && (p1 = getbyterep (arg1, &s1))
68c93708
ML
1870 && s2 <= s0
1871 && s2 <= s1)
df838ef0
RS
1872 return build_cmp_result (type, memcmp (p0, p1, s2));
1873 return NULL_TREE;
1874
66972191 1875 case CFN_BUILT_IN_MEMCHR:
b7a0507a 1876 if (!size_t_cst_p (arg2, &s2))
66972191
JJ
1877 return NULL_TREE;
1878 if (s2 == 0
1879 && !TREE_SIDE_EFFECTS (arg0)
1880 && !TREE_SIDE_EFFECTS (arg1))
1881 return build_int_cst (type, 0);
866626ef 1882 if ((p0 = getbyterep (arg0, &s0))
66972191
JJ
1883 && s2 <= s0
1884 && target_char_cst_p (arg1, &c))
1885 {
1886 const char *r = (const char *) memchr (p0, c, s2);
1887 if (r == NULL)
1888 return build_int_cst (type, 0);
1889 return fold_convert (type,
1890 fold_build_pointer_plus_hwi (arg0, r - p0));
1891 }
1892 return NULL_TREE;
1893
0b1fe8cf
RS
1894 case CFN_WHILE_ULT:
1895 {
1896 poly_uint64 parg0, parg1;
1897 if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
1898 return fold_while_ult (type, parg0, parg1);
1899 return NULL_TREE;
1900 }
1901
df838ef0
RS
1902 default:
1903 return fold_const_call_1 (fn, type, arg0, arg1, arg2);
1904 }
1905}