]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fold-const-call.c
PR 83097 Use __BYTE_ORDER__ predefined macro instead of runtime check
[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)
8e6cdc90
RS
63 && (wi::min_precision (wi::to_wide (t), UNSIGNED)
64 <= sizeof (size_t) * CHAR_BIT))
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;
101 real_from_mpfr (&tmp, m, format, GMP_RNDN);
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;
132 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
133 mpfr_t m;
134
135 mpfr_init2 (m, prec);
136 mpfr_from_real (m, arg, GMP_RNDN);
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;
162 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
163 mpfr_t m, ms, mc;
164
165 mpfr_inits2 (prec, m, ms, mc, NULL);
166 mpfr_from_real (m, arg, GMP_RNDN);
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;
195 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
196 mpfr_t m0, m1;
197
198 mpfr_inits2 (prec, m0, m1, NULL);
199 mpfr_from_real (m0, arg0, GMP_RNDN);
200 mpfr_from_real (m1, arg1, GMP_RNDN);
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,
218 int (*func) (mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
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;
226 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
227 mpfr_t m;
228
229 mpfr_init2 (m, prec);
230 mpfr_from_real (m, arg1, GMP_RNDN);
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;
262 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
263 mpfr_t m0, m1, m2;
264
265 mpfr_inits2 (prec, m0, m1, m2, NULL);
266 mpfr_from_real (m0, arg0, GMP_RNDN);
267 mpfr_from_real (m1, arg1, GMP_RNDN);
268 mpfr_from_real (m2, arg2, GMP_RNDN);
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;
298 real_from_mpfr (&tmp_real, mpc_realref (m), format, GMP_RNDN);
299 real_from_mpfr (&tmp_imag, mpc_imagref (m), format, GMP_RNDN);
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);
343 mpfr_from_real (mpc_realref (m), arg_real, GMP_RNDN);
344 mpfr_from_real (mpc_imagref (m), arg_imag, GMP_RNDN);
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);
380 mpfr_from_real (mpc_realref (m0), arg0_real, GMP_RNDN);
381 mpfr_from_real (mpc_imagref (m0), arg0_imag, GMP_RNDN);
382 mpfr_from_real (mpc_realref (m1), arg1_real, GMP_RNDN);
383 mpfr_from_real (mpc_imagref (m1), arg1_imag, GMP_RNDN);
384 mpfr_clear_flags ();
385 bool inexact = func (m0, m0, m1, crnd);
386 bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
387 mpc_clear (m0);
388 mpc_clear (m1);
389
390 return ok;
391}
392
393/* Try to evaluate:
394
395 *RESULT = logb (*ARG)
396
397 in format FORMAT. Return true on success. */
398
399static bool
400fold_const_logb (real_value *result, const real_value *arg,
401 const real_format *format)
402{
403 switch (arg->cl)
404 {
405 case rvc_nan:
406 /* If arg is +-NaN, then return it. */
407 *result = *arg;
408 return true;
409
410 case rvc_inf:
411 /* If arg is +-Inf, then return +Inf. */
412 *result = *arg;
413 result->sign = 0;
414 return true;
415
416 case rvc_zero:
417 /* Zero may set errno and/or raise an exception. */
418 return false;
419
420 case rvc_normal:
421 /* For normal numbers, proceed iff radix == 2. In GCC,
422 normalized significands are in the range [0.5, 1.0). We
423 want the exponent as if they were [1.0, 2.0) so get the
424 exponent and subtract 1. */
425 if (format->b == 2)
426 {
427 real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED);
428 return true;
429 }
430 return false;
431 }
432 gcc_unreachable ();
433}
434
435/* Try to evaluate:
436
437 *RESULT = significand (*ARG)
438
439 in format FORMAT. Return true on success. */
440
441static bool
442fold_const_significand (real_value *result, const real_value *arg,
443 const real_format *format)
444{
445 switch (arg->cl)
446 {
447 case rvc_zero:
448 case rvc_nan:
449 case rvc_inf:
450 /* If arg is +-0, +-Inf or +-NaN, then return it. */
451 *result = *arg;
452 return true;
453
454 case rvc_normal:
455 /* For normal numbers, proceed iff radix == 2. */
456 if (format->b == 2)
457 {
458 *result = *arg;
459 /* In GCC, normalized significands are in the range [0.5, 1.0).
460 We want them to be [1.0, 2.0) so set the exponent to 1. */
461 SET_REAL_EXP (result, 1);
462 return true;
463 }
464 return false;
465 }
466 gcc_unreachable ();
467}
468
469/* Try to evaluate:
470
471 *RESULT = f (*ARG)
472
473 where FORMAT is the format of *ARG and PRECISION is the number of
474 significant bits in the result. Return true on success. */
475
476static bool
477fold_const_conversion (wide_int *result,
478 void (*fn) (real_value *, format_helper,
479 const real_value *),
480 const real_value *arg, unsigned int precision,
481 const real_format *format)
482{
483 if (!real_isfinite (arg))
484 return false;
485
486 real_value rounded;
487 fn (&rounded, format, arg);
488
489 bool fail = false;
490 *result = real_to_integer (&rounded, &fail, precision);
491 return !fail;
492}
493
494/* Try to evaluate:
495
496 *RESULT = pow (*ARG0, *ARG1)
497
498 in format FORMAT. Return true on success. */
499
500static bool
501fold_const_pow (real_value *result, const real_value *arg0,
502 const real_value *arg1, const real_format *format)
503{
504 if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
505 return true;
506
507 /* Check for an integer exponent. */
508 REAL_VALUE_TYPE cint1;
509 HOST_WIDE_INT n1 = real_to_integer (arg1);
510 real_from_integer (&cint1, VOIDmode, n1, SIGNED);
511 /* Attempt to evaluate pow at compile-time, unless this should
512 raise an exception. */
513 if (real_identical (arg1, &cint1)
514 && (n1 > 0
515 || (!flag_trapping_math && !flag_errno_math)
516 || !real_equal (arg0, &dconst0)))
517 {
518 bool inexact = real_powi (result, format, arg0, n1);
5a00b0aa
SS
519 /* Avoid the folding if flag_signaling_nans is on. */
520 if (flag_unsafe_math_optimizations
521 || (!inexact
522 && !(flag_signaling_nans
523 && REAL_VALUE_ISSIGNALING_NAN (*arg0))))
5c1a2e63
RS
524 return true;
525 }
526
527 return false;
528}
529
530/* Try to evaluate:
531
532 *RESULT = ldexp (*ARG0, ARG1)
533
534 in format FORMAT. Return true on success. */
535
536static bool
537fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
538 const wide_int_ref &arg1,
539 const real_format *format)
540{
541 /* Bound the maximum adjustment to twice the range of the
542 mode's valid exponents. Use abs to ensure the range is
543 positive as a sanity check. */
544 int max_exp_adj = 2 * labs (format->emax - format->emin);
545
546 /* The requested adjustment must be inside this range. This
547 is a preliminary cap to avoid things like overflow, we
548 may still fail to compute the result for other reasons. */
549 if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
550 return false;
551
5a00b0aa
SS
552 /* Don't perform operation if we honor signaling NaNs and
553 operand is a signaling NaN. */
554 if (!flag_unsafe_math_optimizations
555 && flag_signaling_nans
556 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
557 return false;
558
5c1a2e63
RS
559 REAL_VALUE_TYPE initial_result;
560 real_ldexp (&initial_result, arg0, arg1.to_shwi ());
561
562 /* Ensure we didn't overflow. */
563 if (real_isinf (&initial_result))
564 return false;
565
566 /* Only proceed if the target mode can hold the
567 resulting value. */
568 *result = real_value_truncate (format, initial_result);
569 return real_equal (&initial_result, result);
570}
571
df838ef0
RS
572/* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
573 return type TYPE. QUIET is true if a quiet rather than signalling
574 NaN is required. */
575
576static tree
577fold_const_builtin_nan (tree type, tree arg, bool quiet)
578{
579 REAL_VALUE_TYPE real;
580 const char *str = c_getstr (arg);
581 if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
582 return build_real (type, real);
583 return NULL_TREE;
584}
585
5c1a2e63
RS
586/* Try to evaluate:
587
588 *RESULT = FN (*ARG)
589
590 in format FORMAT. Return true on success. */
591
592static bool
d7ebef06 593fold_const_call_ss (real_value *result, combined_fn fn,
5c1a2e63
RS
594 const real_value *arg, const real_format *format)
595{
596 switch (fn)
597 {
d7ebef06 598 CASE_CFN_SQRT:
ee5fd23a 599 CASE_CFN_SQRT_FN:
5c1a2e63
RS
600 return (real_compare (GE_EXPR, arg, &dconst0)
601 && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
602
d7ebef06 603 CASE_CFN_CBRT:
5c1a2e63
RS
604 return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
605
d7ebef06 606 CASE_CFN_ASIN:
5c1a2e63
RS
607 return (real_compare (GE_EXPR, arg, &dconstm1)
608 && real_compare (LE_EXPR, arg, &dconst1)
609 && do_mpfr_arg1 (result, mpfr_asin, arg, format));
610
d7ebef06 611 CASE_CFN_ACOS:
5c1a2e63
RS
612 return (real_compare (GE_EXPR, arg, &dconstm1)
613 && real_compare (LE_EXPR, arg, &dconst1)
614 && do_mpfr_arg1 (result, mpfr_acos, arg, format));
615
d7ebef06 616 CASE_CFN_ATAN:
5c1a2e63
RS
617 return do_mpfr_arg1 (result, mpfr_atan, arg, format);
618
d7ebef06 619 CASE_CFN_ASINH:
5c1a2e63
RS
620 return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
621
d7ebef06 622 CASE_CFN_ACOSH:
5c1a2e63
RS
623 return (real_compare (GE_EXPR, arg, &dconst1)
624 && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
625
d7ebef06 626 CASE_CFN_ATANH:
5c1a2e63
RS
627 return (real_compare (GE_EXPR, arg, &dconstm1)
628 && real_compare (LE_EXPR, arg, &dconst1)
629 && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
630
d7ebef06 631 CASE_CFN_SIN:
5c1a2e63
RS
632 return do_mpfr_arg1 (result, mpfr_sin, arg, format);
633
d7ebef06 634 CASE_CFN_COS:
5c1a2e63
RS
635 return do_mpfr_arg1 (result, mpfr_cos, arg, format);
636
d7ebef06 637 CASE_CFN_TAN:
5c1a2e63
RS
638 return do_mpfr_arg1 (result, mpfr_tan, arg, format);
639
d7ebef06 640 CASE_CFN_SINH:
5c1a2e63
RS
641 return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
642
d7ebef06 643 CASE_CFN_COSH:
5c1a2e63
RS
644 return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
645
d7ebef06 646 CASE_CFN_TANH:
5c1a2e63
RS
647 return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
648
d7ebef06 649 CASE_CFN_ERF:
5c1a2e63
RS
650 return do_mpfr_arg1 (result, mpfr_erf, arg, format);
651
d7ebef06 652 CASE_CFN_ERFC:
5c1a2e63
RS
653 return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
654
d7ebef06 655 CASE_CFN_TGAMMA:
5c1a2e63
RS
656 return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
657
d7ebef06 658 CASE_CFN_EXP:
5c1a2e63
RS
659 return do_mpfr_arg1 (result, mpfr_exp, arg, format);
660
d7ebef06 661 CASE_CFN_EXP2:
5c1a2e63
RS
662 return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
663
d7ebef06
RS
664 CASE_CFN_EXP10:
665 CASE_CFN_POW10:
5c1a2e63
RS
666 return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
667
d7ebef06 668 CASE_CFN_EXPM1:
5c1a2e63
RS
669 return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
670
d7ebef06 671 CASE_CFN_LOG:
5c1a2e63
RS
672 return (real_compare (GT_EXPR, arg, &dconst0)
673 && do_mpfr_arg1 (result, mpfr_log, arg, format));
674
d7ebef06 675 CASE_CFN_LOG2:
5c1a2e63
RS
676 return (real_compare (GT_EXPR, arg, &dconst0)
677 && do_mpfr_arg1 (result, mpfr_log2, arg, format));
678
d7ebef06 679 CASE_CFN_LOG10:
5c1a2e63
RS
680 return (real_compare (GT_EXPR, arg, &dconst0)
681 && do_mpfr_arg1 (result, mpfr_log10, arg, format));
682
d7ebef06 683 CASE_CFN_LOG1P:
5c1a2e63
RS
684 return (real_compare (GT_EXPR, arg, &dconstm1)
685 && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
686
d7ebef06 687 CASE_CFN_J0:
5c1a2e63
RS
688 return do_mpfr_arg1 (result, mpfr_j0, arg, format);
689
d7ebef06 690 CASE_CFN_J1:
5c1a2e63
RS
691 return do_mpfr_arg1 (result, mpfr_j1, arg, format);
692
d7ebef06 693 CASE_CFN_Y0:
5c1a2e63
RS
694 return (real_compare (GT_EXPR, arg, &dconst0)
695 && do_mpfr_arg1 (result, mpfr_y0, arg, format));
696
d7ebef06 697 CASE_CFN_Y1:
5c1a2e63
RS
698 return (real_compare (GT_EXPR, arg, &dconst0)
699 && do_mpfr_arg1 (result, mpfr_y1, arg, format));
700
d7ebef06 701 CASE_CFN_FLOOR:
5c1a2e63
RS
702 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
703 {
704 real_floor (result, format, arg);
705 return true;
706 }
707 return false;
708
d7ebef06 709 CASE_CFN_CEIL:
5c1a2e63
RS
710 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
711 {
712 real_ceil (result, format, arg);
713 return true;
714 }
715 return false;
716
d7ebef06 717 CASE_CFN_TRUNC:
5c1a2e63
RS
718 real_trunc (result, format, arg);
719 return true;
720
d7ebef06 721 CASE_CFN_ROUND:
5c1a2e63
RS
722 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
723 {
724 real_round (result, format, arg);
725 return true;
726 }
727 return false;
728
d7ebef06 729 CASE_CFN_LOGB:
5c1a2e63
RS
730 return fold_const_logb (result, arg, format);
731
d7ebef06 732 CASE_CFN_SIGNIFICAND:
5c1a2e63
RS
733 return fold_const_significand (result, arg, format);
734
735 default:
736 return false;
737 }
738}
739
740/* Try to evaluate:
741
742 *RESULT = FN (*ARG)
743
744 where FORMAT is the format of ARG and PRECISION is the number of
745 significant bits in the result. Return true on success. */
746
747static bool
d7ebef06 748fold_const_call_ss (wide_int *result, combined_fn fn,
5c1a2e63
RS
749 const real_value *arg, unsigned int precision,
750 const real_format *format)
751{
752 switch (fn)
753 {
d7ebef06 754 CASE_CFN_SIGNBIT:
5c1a2e63
RS
755 if (real_isneg (arg))
756 *result = wi::one (precision);
757 else
758 *result = wi::zero (precision);
759 return true;
760
d7ebef06 761 CASE_CFN_ILOGB:
5c1a2e63
RS
762 /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
763 Proceed iff radix == 2. In GCC, normalized significands are in
764 the range [0.5, 1.0). We want the exponent as if they were
765 [1.0, 2.0) so get the exponent and subtract 1. */
766 if (arg->cl == rvc_normal && format->b == 2)
767 {
768 *result = wi::shwi (REAL_EXP (arg) - 1, precision);
769 return true;
770 }
771 return false;
772
d7ebef06
RS
773 CASE_CFN_ICEIL:
774 CASE_CFN_LCEIL:
775 CASE_CFN_LLCEIL:
5c1a2e63
RS
776 return fold_const_conversion (result, real_ceil, arg,
777 precision, format);
778
d7ebef06
RS
779 CASE_CFN_LFLOOR:
780 CASE_CFN_IFLOOR:
781 CASE_CFN_LLFLOOR:
5c1a2e63
RS
782 return fold_const_conversion (result, real_floor, arg,
783 precision, format);
784
d7ebef06
RS
785 CASE_CFN_IROUND:
786 CASE_CFN_LROUND:
787 CASE_CFN_LLROUND:
5c1a2e63
RS
788 return fold_const_conversion (result, real_round, arg,
789 precision, format);
790
d7ebef06
RS
791 CASE_CFN_IRINT:
792 CASE_CFN_LRINT:
793 CASE_CFN_LLRINT:
5c1a2e63
RS
794 /* Not yet folded to a constant. */
795 return false;
796
d7ebef06
RS
797 CASE_CFN_FINITE:
798 case CFN_BUILT_IN_FINITED32:
799 case CFN_BUILT_IN_FINITED64:
800 case CFN_BUILT_IN_FINITED128:
801 case CFN_BUILT_IN_ISFINITE:
2556a032
RS
802 *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
803 return true;
804
d7ebef06
RS
805 CASE_CFN_ISINF:
806 case CFN_BUILT_IN_ISINFD32:
807 case CFN_BUILT_IN_ISINFD64:
808 case CFN_BUILT_IN_ISINFD128:
2556a032
RS
809 if (real_isinf (arg))
810 *result = wi::shwi (arg->sign ? -1 : 1, precision);
811 else
812 *result = wi::shwi (0, precision);
813 return true;
814
d7ebef06
RS
815 CASE_CFN_ISNAN:
816 case CFN_BUILT_IN_ISNAND32:
817 case CFN_BUILT_IN_ISNAND64:
818 case CFN_BUILT_IN_ISNAND128:
2556a032
RS
819 *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
820 return true;
821
5c1a2e63
RS
822 default:
823 return false;
824 }
825}
826
db9bd5d5
RS
827/* Try to evaluate:
828
829 *RESULT = FN (ARG)
830
831 where ARG_TYPE is the type of ARG and PRECISION is the number of bits
832 in the result. Return true on success. */
833
834static bool
d7ebef06
RS
835fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
836 unsigned int precision, tree arg_type)
db9bd5d5
RS
837{
838 switch (fn)
839 {
d7ebef06 840 CASE_CFN_FFS:
db9bd5d5
RS
841 *result = wi::shwi (wi::ffs (arg), precision);
842 return true;
843
d7ebef06 844 CASE_CFN_CLZ:
db9bd5d5
RS
845 {
846 int tmp;
847 if (wi::ne_p (arg, 0))
848 tmp = wi::clz (arg);
7a504f33
RS
849 else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
850 tmp))
db9bd5d5
RS
851 tmp = TYPE_PRECISION (arg_type);
852 *result = wi::shwi (tmp, precision);
853 return true;
854 }
855
d7ebef06 856 CASE_CFN_CTZ:
db9bd5d5
RS
857 {
858 int tmp;
859 if (wi::ne_p (arg, 0))
860 tmp = wi::ctz (arg);
7a504f33
RS
861 else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
862 tmp))
db9bd5d5
RS
863 tmp = TYPE_PRECISION (arg_type);
864 *result = wi::shwi (tmp, precision);
865 return true;
866 }
867
d7ebef06 868 CASE_CFN_CLRSB:
db9bd5d5
RS
869 *result = wi::shwi (wi::clrsb (arg), precision);
870 return true;
871
d7ebef06 872 CASE_CFN_POPCOUNT:
db9bd5d5
RS
873 *result = wi::shwi (wi::popcount (arg), precision);
874 return true;
875
d7ebef06 876 CASE_CFN_PARITY:
db9bd5d5
RS
877 *result = wi::shwi (wi::parity (arg), precision);
878 return true;
879
d7ebef06
RS
880 case CFN_BUILT_IN_BSWAP16:
881 case CFN_BUILT_IN_BSWAP32:
882 case CFN_BUILT_IN_BSWAP64:
db9bd5d5
RS
883 *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
884 return true;
885
886 default:
887 return false;
888 }
889}
890
5c1a2e63
RS
891/* Try to evaluate:
892
893 RESULT = FN (*ARG)
894
895 where FORMAT is the format of ARG and of the real and imaginary parts
896 of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
897 true on success. */
898
899static bool
900fold_const_call_cs (real_value *result_real, real_value *result_imag,
d7ebef06 901 combined_fn fn, const real_value *arg,
5c1a2e63
RS
902 const real_format *format)
903{
904 switch (fn)
905 {
d7ebef06 906 CASE_CFN_CEXPI:
5c1a2e63
RS
907 /* cexpi(x+yi) = cos(x)+sin(y)*i. */
908 return do_mpfr_sincos (result_imag, result_real, arg, format);
909
910 default:
911 return false;
912 }
913}
914
915/* Try to evaluate:
916
917 *RESULT = fn (ARG)
918
919 where FORMAT is the format of RESULT and of the real and imaginary parts
920 of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
921 success. */
922
923static bool
d7ebef06 924fold_const_call_sc (real_value *result, combined_fn fn,
5c1a2e63
RS
925 const real_value *arg_real, const real_value *arg_imag,
926 const real_format *format)
927{
928 switch (fn)
929 {
d7ebef06 930 CASE_CFN_CABS:
5c1a2e63
RS
931 return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
932
933 default:
934 return false;
935 }
936}
937
938/* Try to evaluate:
939
940 RESULT = fn (ARG)
941
942 where FORMAT is the format of the real and imaginary parts of RESULT
943 (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
944 Return true on success. */
945
946static bool
947fold_const_call_cc (real_value *result_real, real_value *result_imag,
d7ebef06 948 combined_fn fn, const real_value *arg_real,
5c1a2e63
RS
949 const real_value *arg_imag, const real_format *format)
950{
951 switch (fn)
952 {
d7ebef06 953 CASE_CFN_CCOS:
5c1a2e63
RS
954 return do_mpc_arg1 (result_real, result_imag, mpc_cos,
955 arg_real, arg_imag, format);
956
d7ebef06 957 CASE_CFN_CCOSH:
5c1a2e63
RS
958 return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
959 arg_real, arg_imag, format);
960
d7ebef06 961 CASE_CFN_CPROJ:
5c1a2e63
RS
962 if (real_isinf (arg_real) || real_isinf (arg_imag))
963 {
964 real_inf (result_real);
965 *result_imag = dconst0;
966 result_imag->sign = arg_imag->sign;
967 }
968 else
969 {
970 *result_real = *arg_real;
971 *result_imag = *arg_imag;
972 }
973 return true;
974
d7ebef06 975 CASE_CFN_CSIN:
5c1a2e63
RS
976 return do_mpc_arg1 (result_real, result_imag, mpc_sin,
977 arg_real, arg_imag, format);
978
d7ebef06 979 CASE_CFN_CSINH:
5c1a2e63
RS
980 return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
981 arg_real, arg_imag, format);
982
d7ebef06 983 CASE_CFN_CTAN:
5c1a2e63
RS
984 return do_mpc_arg1 (result_real, result_imag, mpc_tan,
985 arg_real, arg_imag, format);
986
d7ebef06 987 CASE_CFN_CTANH:
5c1a2e63
RS
988 return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
989 arg_real, arg_imag, format);
990
d7ebef06 991 CASE_CFN_CLOG:
5c1a2e63
RS
992 return do_mpc_arg1 (result_real, result_imag, mpc_log,
993 arg_real, arg_imag, format);
994
d7ebef06 995 CASE_CFN_CSQRT:
5c1a2e63
RS
996 return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
997 arg_real, arg_imag, format);
998
d7ebef06 999 CASE_CFN_CASIN:
5c1a2e63
RS
1000 return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1001 arg_real, arg_imag, format);
1002
d7ebef06 1003 CASE_CFN_CACOS:
5c1a2e63
RS
1004 return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1005 arg_real, arg_imag, format);
1006
d7ebef06 1007 CASE_CFN_CATAN:
5c1a2e63
RS
1008 return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1009 arg_real, arg_imag, format);
1010
d7ebef06 1011 CASE_CFN_CASINH:
5c1a2e63
RS
1012 return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1013 arg_real, arg_imag, format);
1014
d7ebef06 1015 CASE_CFN_CACOSH:
5c1a2e63
RS
1016 return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1017 arg_real, arg_imag, format);
1018
d7ebef06 1019 CASE_CFN_CATANH:
5c1a2e63
RS
1020 return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1021 arg_real, arg_imag, format);
1022
d7ebef06 1023 CASE_CFN_CEXP:
5c1a2e63
RS
1024 return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1025 arg_real, arg_imag, format);
1026
1027 default:
1028 return false;
1029 }
1030}
1031
df838ef0
RS
1032/* Subroutine of fold_const_call, with the same interface. Handle cases
1033 where the arguments and result are numerical. */
5c1a2e63 1034
df838ef0 1035static tree
d7ebef06 1036fold_const_call_1 (combined_fn fn, tree type, tree arg)
5c1a2e63
RS
1037{
1038 machine_mode mode = TYPE_MODE (type);
1039 machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1040
db9bd5d5
RS
1041 if (integer_cst_p (arg))
1042 {
1043 if (SCALAR_INT_MODE_P (mode))
1044 {
1045 wide_int result;
8e6cdc90
RS
1046 if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1047 TYPE_PRECISION (type), TREE_TYPE (arg)))
db9bd5d5
RS
1048 return wide_int_to_tree (type, result);
1049 }
1050 return NULL_TREE;
1051 }
1052
5c1a2e63
RS
1053 if (real_cst_p (arg))
1054 {
1055 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1056 if (mode == arg_mode)
1057 {
1058 /* real -> real. */
1059 REAL_VALUE_TYPE result;
1060 if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1061 REAL_MODE_FORMAT (mode)))
1062 return build_real (type, result);
1063 }
1064 else if (COMPLEX_MODE_P (mode)
1065 && GET_MODE_INNER (mode) == arg_mode)
1066 {
1067 /* real -> complex real. */
1068 REAL_VALUE_TYPE result_real, result_imag;
1069 if (fold_const_call_cs (&result_real, &result_imag, fn,
1070 TREE_REAL_CST_PTR (arg),
1071 REAL_MODE_FORMAT (arg_mode)))
1072 return build_complex (type,
1073 build_real (TREE_TYPE (type), result_real),
1074 build_real (TREE_TYPE (type), result_imag));
1075 }
1076 else if (INTEGRAL_TYPE_P (type))
1077 {
1078 /* real -> int. */
1079 wide_int result;
1080 if (fold_const_call_ss (&result, fn,
1081 TREE_REAL_CST_PTR (arg),
1082 TYPE_PRECISION (type),
1083 REAL_MODE_FORMAT (arg_mode)))
1084 return wide_int_to_tree (type, result);
1085 }
1086 return NULL_TREE;
1087 }
1088
1089 if (complex_cst_p (arg))
1090 {
1091 gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1092 machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1093 tree argr = TREE_REALPART (arg);
1094 tree argi = TREE_IMAGPART (arg);
1095 if (mode == arg_mode
1096 && real_cst_p (argr)
1097 && real_cst_p (argi))
1098 {
1099 /* complex real -> complex real. */
1100 REAL_VALUE_TYPE result_real, result_imag;
1101 if (fold_const_call_cc (&result_real, &result_imag, fn,
1102 TREE_REAL_CST_PTR (argr),
1103 TREE_REAL_CST_PTR (argi),
1104 REAL_MODE_FORMAT (inner_mode)))
1105 return build_complex (type,
1106 build_real (TREE_TYPE (type), result_real),
1107 build_real (TREE_TYPE (type), result_imag));
1108 }
1109 if (mode == inner_mode
1110 && real_cst_p (argr)
1111 && real_cst_p (argi))
1112 {
1113 /* complex real -> real. */
1114 REAL_VALUE_TYPE result;
1115 if (fold_const_call_sc (&result, fn,
1116 TREE_REAL_CST_PTR (argr),
1117 TREE_REAL_CST_PTR (argi),
1118 REAL_MODE_FORMAT (inner_mode)))
1119 return build_real (type, result);
1120 }
1121 return NULL_TREE;
1122 }
1123
1124 return NULL_TREE;
1125}
1126
df838ef0
RS
1127/* Try to fold FN (ARG) to a constant. Return the constant on success,
1128 otherwise return null. TYPE is the type of the return value. */
1129
1130tree
d7ebef06 1131fold_const_call (combined_fn fn, tree type, tree arg)
df838ef0
RS
1132{
1133 switch (fn)
1134 {
d7ebef06 1135 case CFN_BUILT_IN_STRLEN:
df838ef0
RS
1136 if (const char *str = c_getstr (arg))
1137 return build_int_cst (type, strlen (str));
1138 return NULL_TREE;
1139
d7ebef06 1140 CASE_CFN_NAN:
6dc198e3 1141 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
d7ebef06
RS
1142 case CFN_BUILT_IN_NAND32:
1143 case CFN_BUILT_IN_NAND64:
1144 case CFN_BUILT_IN_NAND128:
df838ef0
RS
1145 return fold_const_builtin_nan (type, arg, true);
1146
d7ebef06 1147 CASE_CFN_NANS:
6dc198e3 1148 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
df838ef0
RS
1149 return fold_const_builtin_nan (type, arg, false);
1150
1151 default:
1152 return fold_const_call_1 (fn, type, arg);
1153 }
1154}
1155
5c1a2e63
RS
1156/* Try to evaluate:
1157
1158 *RESULT = FN (*ARG0, *ARG1)
1159
1160 in format FORMAT. Return true on success. */
1161
1162static bool
d7ebef06 1163fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1164 const real_value *arg0, const real_value *arg1,
1165 const real_format *format)
1166{
1167 switch (fn)
1168 {
d7ebef06
RS
1169 CASE_CFN_DREM:
1170 CASE_CFN_REMAINDER:
5c1a2e63
RS
1171 return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1172
d7ebef06 1173 CASE_CFN_ATAN2:
5c1a2e63
RS
1174 return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1175
d7ebef06 1176 CASE_CFN_FDIM:
5c1a2e63
RS
1177 return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1178
d7ebef06 1179 CASE_CFN_HYPOT:
5c1a2e63
RS
1180 return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1181
d7ebef06 1182 CASE_CFN_COPYSIGN:
ee5fd23a 1183 CASE_CFN_COPYSIGN_FN:
5c1a2e63
RS
1184 *result = *arg0;
1185 real_copysign (result, arg1);
1186 return true;
1187
d7ebef06 1188 CASE_CFN_FMIN:
ee5fd23a 1189 CASE_CFN_FMIN_FN:
5c1a2e63
RS
1190 return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1191
d7ebef06 1192 CASE_CFN_FMAX:
ee5fd23a 1193 CASE_CFN_FMAX_FN:
5c1a2e63
RS
1194 return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1195
d7ebef06 1196 CASE_CFN_POW:
5c1a2e63
RS
1197 return fold_const_pow (result, arg0, arg1, format);
1198
1199 default:
1200 return false;
1201 }
1202}
1203
1204/* Try to evaluate:
1205
1206 *RESULT = FN (*ARG0, ARG1)
1207
1208 where FORMAT is the format of *RESULT and *ARG0. Return true on
1209 success. */
1210
1211static bool
d7ebef06 1212fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1213 const real_value *arg0, const wide_int_ref &arg1,
1214 const real_format *format)
1215{
1216 switch (fn)
1217 {
d7ebef06 1218 CASE_CFN_LDEXP:
5c1a2e63
RS
1219 return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1220
d7ebef06
RS
1221 CASE_CFN_SCALBN:
1222 CASE_CFN_SCALBLN:
5c1a2e63
RS
1223 return (format->b == 2
1224 && fold_const_builtin_load_exponent (result, arg0, arg1,
1225 format));
1226
d7ebef06 1227 CASE_CFN_POWI:
5a00b0aa
SS
1228 /* Avoid the folding if flag_signaling_nans is on and
1229 operand is a signaling NaN. */
1230 if (!flag_unsafe_math_optimizations
1231 && flag_signaling_nans
1232 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1233 return false;
1234
5c1a2e63
RS
1235 real_powi (result, format, arg0, arg1.to_shwi ());
1236 return true;
1237
1238 default:
1239 return false;
1240 }
1241}
1242
1243/* Try to evaluate:
1244
1245 *RESULT = FN (ARG0, *ARG1)
1246
1247 where FORMAT is the format of *RESULT and *ARG1. Return true on
1248 success. */
1249
1250static bool
d7ebef06 1251fold_const_call_sss (real_value *result, combined_fn fn,
5c1a2e63
RS
1252 const wide_int_ref &arg0, const real_value *arg1,
1253 const real_format *format)
1254{
1255 switch (fn)
1256 {
d7ebef06 1257 CASE_CFN_JN:
5c1a2e63
RS
1258 return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1259
d7ebef06 1260 CASE_CFN_YN:
5c1a2e63
RS
1261 return (real_compare (GT_EXPR, arg1, &dconst0)
1262 && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1263
1264 default:
1265 return false;
1266 }
1267}
1268
1269/* Try to evaluate:
1270
1271 RESULT = fn (ARG0, ARG1)
1272
1273 where FORMAT is the format of the real and imaginary parts of RESULT
1274 (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1275 and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1276
1277static bool
1278fold_const_call_ccc (real_value *result_real, real_value *result_imag,
d7ebef06 1279 combined_fn fn, const real_value *arg0_real,
5c1a2e63
RS
1280 const real_value *arg0_imag, const real_value *arg1_real,
1281 const real_value *arg1_imag, const real_format *format)
1282{
1283 switch (fn)
1284 {
d7ebef06 1285 CASE_CFN_CPOW:
5c1a2e63
RS
1286 return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1287 arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1288
1289 default:
1290 return false;
1291 }
1292}
1293
df838ef0
RS
1294/* Subroutine of fold_const_call, with the same interface. Handle cases
1295 where the arguments and result are numerical. */
5c1a2e63 1296
df838ef0 1297static tree
d7ebef06 1298fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
5c1a2e63
RS
1299{
1300 machine_mode mode = TYPE_MODE (type);
1301 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1302 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1303
1304 if (arg0_mode == arg1_mode
1305 && real_cst_p (arg0)
1306 && real_cst_p (arg1))
1307 {
1308 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1309 if (mode == arg0_mode)
1310 {
1311 /* real, real -> real. */
1312 REAL_VALUE_TYPE result;
1313 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1314 TREE_REAL_CST_PTR (arg1),
1315 REAL_MODE_FORMAT (mode)))
1316 return build_real (type, result);
1317 }
1318 return NULL_TREE;
1319 }
1320
1321 if (real_cst_p (arg0)
1322 && integer_cst_p (arg1))
1323 {
1324 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1325 if (mode == arg0_mode)
1326 {
1327 /* real, int -> real. */
1328 REAL_VALUE_TYPE result;
1329 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
8e6cdc90
RS
1330 wi::to_wide (arg1),
1331 REAL_MODE_FORMAT (mode)))
5c1a2e63
RS
1332 return build_real (type, result);
1333 }
1334 return NULL_TREE;
1335 }
1336
1337 if (integer_cst_p (arg0)
1338 && real_cst_p (arg1))
1339 {
1340 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1341 if (mode == arg1_mode)
1342 {
1343 /* int, real -> real. */
1344 REAL_VALUE_TYPE result;
8e6cdc90 1345 if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
5c1a2e63
RS
1346 TREE_REAL_CST_PTR (arg1),
1347 REAL_MODE_FORMAT (mode)))
1348 return build_real (type, result);
1349 }
1350 return NULL_TREE;
1351 }
1352
1353 if (arg0_mode == arg1_mode
1354 && complex_cst_p (arg0)
1355 && complex_cst_p (arg1))
1356 {
1357 gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1358 machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1359 tree arg0r = TREE_REALPART (arg0);
1360 tree arg0i = TREE_IMAGPART (arg0);
1361 tree arg1r = TREE_REALPART (arg1);
1362 tree arg1i = TREE_IMAGPART (arg1);
1363 if (mode == arg0_mode
1364 && real_cst_p (arg0r)
1365 && real_cst_p (arg0i)
1366 && real_cst_p (arg1r)
1367 && real_cst_p (arg1i))
1368 {
1369 /* complex real, complex real -> complex real. */
1370 REAL_VALUE_TYPE result_real, result_imag;
1371 if (fold_const_call_ccc (&result_real, &result_imag, fn,
1372 TREE_REAL_CST_PTR (arg0r),
1373 TREE_REAL_CST_PTR (arg0i),
1374 TREE_REAL_CST_PTR (arg1r),
1375 TREE_REAL_CST_PTR (arg1i),
1376 REAL_MODE_FORMAT (inner_mode)))
1377 return build_complex (type,
1378 build_real (TREE_TYPE (type), result_real),
1379 build_real (TREE_TYPE (type), result_imag));
1380 }
1381 return NULL_TREE;
1382 }
1383
1384 return NULL_TREE;
1385}
1386
df838ef0
RS
1387/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1388 otherwise return null. TYPE is the type of the return value. */
1389
1390tree
d7ebef06 1391fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
df838ef0
RS
1392{
1393 const char *p0, *p1;
bf2d0849 1394 char c;
df838ef0
RS
1395 switch (fn)
1396 {
d7ebef06 1397 case CFN_BUILT_IN_STRSPN:
df838ef0
RS
1398 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1399 return build_int_cst (type, strspn (p0, p1));
1400 return NULL_TREE;
1401
d7ebef06 1402 case CFN_BUILT_IN_STRCSPN:
df838ef0
RS
1403 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1404 return build_int_cst (type, strcspn (p0, p1));
1405 return NULL_TREE;
1406
d7ebef06 1407 case CFN_BUILT_IN_STRCMP:
df838ef0
RS
1408 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1409 return build_cmp_result (type, strcmp (p0, p1));
1410 return NULL_TREE;
1411
a918bfbf
ML
1412 case CFN_BUILT_IN_STRCASECMP:
1413 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1414 {
1415 int r = strcmp (p0, p1);
1416 if (r == 0)
1417 return build_cmp_result (type, r);
1418 }
1419 return NULL_TREE;
1420
bf2d0849
JJ
1421 case CFN_BUILT_IN_INDEX:
1422 case CFN_BUILT_IN_STRCHR:
1423 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1424 {
1425 const char *r = strchr (p0, c);
1426 if (r == NULL)
1427 return build_int_cst (type, 0);
1428 return fold_convert (type,
1429 fold_build_pointer_plus_hwi (arg0, r - p0));
1430 }
1431 return NULL_TREE;
1432
1433 case CFN_BUILT_IN_RINDEX:
1434 case CFN_BUILT_IN_STRRCHR:
1435 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1436 {
1437 const char *r = strrchr (p0, c);
1438 if (r == NULL)
1439 return build_int_cst (type, 0);
1440 return fold_convert (type,
1441 fold_build_pointer_plus_hwi (arg0, r - p0));
1442 }
1443 return NULL_TREE;
1444
c8952930
JJ
1445 case CFN_BUILT_IN_STRSTR:
1446 if ((p1 = c_getstr (arg1)))
1447 {
1448 if ((p0 = c_getstr (arg0)))
1449 {
1450 const char *r = strstr (p0, p1);
1451 if (r == NULL)
1452 return build_int_cst (type, 0);
1453 return fold_convert (type,
1454 fold_build_pointer_plus_hwi (arg0, r - p0));
1455 }
1456 if (*p1 == '\0')
1457 return fold_convert (type, arg0);
1458 }
1459 return NULL_TREE;
1460
df838ef0
RS
1461 default:
1462 return fold_const_call_1 (fn, type, arg0, arg1);
1463 }
1464}
1465
5c1a2e63
RS
1466/* Try to evaluate:
1467
1468 *RESULT = FN (*ARG0, *ARG1, *ARG2)
1469
1470 in format FORMAT. Return true on success. */
1471
1472static bool
d7ebef06 1473fold_const_call_ssss (real_value *result, combined_fn fn,
5c1a2e63
RS
1474 const real_value *arg0, const real_value *arg1,
1475 const real_value *arg2, const real_format *format)
1476{
1477 switch (fn)
1478 {
d7ebef06 1479 CASE_CFN_FMA:
ee5fd23a 1480 CASE_CFN_FMA_FN:
5c1a2e63
RS
1481 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1482
1483 default:
1484 return false;
1485 }
1486}
1487
df838ef0
RS
1488/* Subroutine of fold_const_call, with the same interface. Handle cases
1489 where the arguments and result are numerical. */
5c1a2e63 1490
df838ef0 1491static tree
d7ebef06 1492fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
5c1a2e63
RS
1493{
1494 machine_mode mode = TYPE_MODE (type);
1495 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1496 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1497 machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1498
1499 if (arg0_mode == arg1_mode
1500 && arg0_mode == arg2_mode
1501 && real_cst_p (arg0)
1502 && real_cst_p (arg1)
1503 && real_cst_p (arg2))
1504 {
1505 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1506 if (mode == arg0_mode)
1507 {
1508 /* real, real, real -> real. */
1509 REAL_VALUE_TYPE result;
1510 if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1511 TREE_REAL_CST_PTR (arg1),
1512 TREE_REAL_CST_PTR (arg2),
1513 REAL_MODE_FORMAT (mode)))
1514 return build_real (type, result);
1515 }
1516 return NULL_TREE;
1517 }
1518
1519 return NULL_TREE;
1520}
1521
df838ef0
RS
1522/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
1523 success, otherwise return null. TYPE is the type of the return value. */
1524
1525tree
d7ebef06 1526fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
df838ef0
RS
1527{
1528 const char *p0, *p1;
66972191 1529 char c;
302356da
ML
1530 unsigned HOST_WIDE_INT s0, s1;
1531 size_t s2 = 0;
df838ef0
RS
1532 switch (fn)
1533 {
d7ebef06 1534 case CFN_BUILT_IN_STRNCMP:
66972191 1535 if (!host_size_t_cst_p (arg2, &s2))
a918bfbf 1536 return NULL_TREE;
66972191
JJ
1537 if (s2 == 0
1538 && !TREE_SIDE_EFFECTS (arg0)
1539 && !TREE_SIDE_EFFECTS (arg1))
1540 return build_int_cst (type, 0);
1541 else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1542 return build_int_cst (type, strncmp (p0, p1, s2));
1543 return NULL_TREE;
1544
a918bfbf 1545 case CFN_BUILT_IN_STRNCASECMP:
66972191 1546 if (!host_size_t_cst_p (arg2, &s2))
a918bfbf 1547 return NULL_TREE;
66972191
JJ
1548 if (s2 == 0
1549 && !TREE_SIDE_EFFECTS (arg0)
1550 && !TREE_SIDE_EFFECTS (arg1))
1551 return build_int_cst (type, 0);
1552 else if ((p0 = c_getstr (arg0))
1553 && (p1 = c_getstr (arg1))
1554 && strncmp (p0, p1, s2) == 0)
1555 return build_int_cst (type, 0);
1556 return NULL_TREE;
1557
d7ebef06
RS
1558 case CFN_BUILT_IN_BCMP:
1559 case CFN_BUILT_IN_MEMCMP:
66972191
JJ
1560 if (!host_size_t_cst_p (arg2, &s2))
1561 return NULL_TREE;
1562 if (s2 == 0
1563 && !TREE_SIDE_EFFECTS (arg0)
1564 && !TREE_SIDE_EFFECTS (arg1))
1565 return build_int_cst (type, 0);
68c93708
ML
1566 if ((p0 = c_getstr (arg0, &s0))
1567 && (p1 = c_getstr (arg1, &s1))
68c93708
ML
1568 && s2 <= s0
1569 && s2 <= s1)
df838ef0
RS
1570 return build_cmp_result (type, memcmp (p0, p1, s2));
1571 return NULL_TREE;
1572
66972191
JJ
1573 case CFN_BUILT_IN_MEMCHR:
1574 if (!host_size_t_cst_p (arg2, &s2))
1575 return NULL_TREE;
1576 if (s2 == 0
1577 && !TREE_SIDE_EFFECTS (arg0)
1578 && !TREE_SIDE_EFFECTS (arg1))
1579 return build_int_cst (type, 0);
1580 if ((p0 = c_getstr (arg0, &s0))
1581 && s2 <= s0
1582 && target_char_cst_p (arg1, &c))
1583 {
1584 const char *r = (const char *) memchr (p0, c, s2);
1585 if (r == NULL)
1586 return build_int_cst (type, 0);
1587 return fold_convert (type,
1588 fold_build_pointer_plus_hwi (arg0, r - p0));
1589 }
1590 return NULL_TREE;
1591
df838ef0
RS
1592 default:
1593 return fold_const_call_1 (fn, type, arg0, arg1, arg2);
1594 }
1595}
1596
5c1a2e63
RS
1597/* Fold a fma operation with arguments ARG[012]. */
1598
1599tree
1600fold_fma (location_t, tree type, tree arg0, tree arg1, tree arg2)
1601{
1602 REAL_VALUE_TYPE result;
1603 if (real_cst_p (arg0)
1604 && real_cst_p (arg1)
1605 && real_cst_p (arg2)
1606 && do_mpfr_arg3 (&result, mpfr_fma, TREE_REAL_CST_PTR (arg0),
1607 TREE_REAL_CST_PTR (arg1), TREE_REAL_CST_PTR (arg2),
1608 REAL_MODE_FORMAT (TYPE_MODE (type))))
1609 return build_real (type, result);
1610
1611 return NULL_TREE;
1612}