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