]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fold-const-call.c
Move c_getstr to fold-const.c
[thirdparty/gcc.git] / gcc / fold-const-call.c
CommitLineData
6c21be92 1/* Constant folding for calls to built-in and internal functions.
2 Copyright (C) 1988-2015 Free Software Foundation, Inc.
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"
27#include "fold-const-call.h"
28
29/* Functions that test for certain constant types, abstracting away the
30 decision about whether to check for overflow. */
31
32static inline bool
33integer_cst_p (tree t)
34{
35 return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
36}
37
38static inline bool
39real_cst_p (tree t)
40{
41 return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
42}
43
44static inline bool
45complex_cst_p (tree t)
46{
47 return TREE_CODE (t) == COMPLEX_CST;
48}
49
50/* M is the result of trying to constant-fold an expression (starting
51 with clear MPFR flags) and INEXACT says whether the result in M is
52 exact or inexact. Return true if M can be used as a constant-folded
53 result in format FORMAT, storing the value in *RESULT if so. */
54
55static bool
56do_mpfr_ckconv (real_value *result, mpfr_srcptr m, bool inexact,
57 const real_format *format)
58{
59 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
60 overflow/underflow occurred. If -frounding-math, proceed iff the
61 result of calling FUNC was exact. */
62 if (!mpfr_number_p (m)
63 || mpfr_overflow_p ()
64 || mpfr_underflow_p ()
65 || (flag_rounding_math && inexact))
66 return false;
67
68 REAL_VALUE_TYPE tmp;
69 real_from_mpfr (&tmp, m, format, GMP_RNDN);
70
71 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
72 If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
73 underflowed in the conversion. */
74 if (!real_isfinite (&tmp)
75 || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
76 return false;
77
78 real_convert (result, format, &tmp);
79 return real_identical (result, &tmp);
80}
81
82/* Try to evaluate:
83
84 *RESULT = f (*ARG)
85
86 in format FORMAT, given that FUNC is the MPFR implementation of f.
87 Return true on success. */
88
89static bool
90do_mpfr_arg1 (real_value *result,
91 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
92 const real_value *arg, const real_format *format)
93{
94 /* To proceed, MPFR must exactly represent the target floating point
95 format, which only happens when the target base equals two. */
96 if (format->b != 2 || !real_isfinite (arg))
97 return false;
98
99 int prec = format->p;
100 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
101 mpfr_t m;
102
103 mpfr_init2 (m, prec);
104 mpfr_from_real (m, arg, GMP_RNDN);
105 mpfr_clear_flags ();
106 bool inexact = func (m, m, rnd);
107 bool ok = do_mpfr_ckconv (result, m, inexact, format);
108 mpfr_clear (m);
109
110 return ok;
111}
112
113/* Try to evaluate:
114
115 *RESULT_SIN = sin (*ARG);
116 *RESULT_COS = cos (*ARG);
117
118 for format FORMAT. Return true on success. */
119
120static bool
121do_mpfr_sincos (real_value *result_sin, real_value *result_cos,
122 const real_value *arg, const real_format *format)
123{
124 /* To proceed, MPFR must exactly represent the target floating point
125 format, which only happens when the target base equals two. */
126 if (format->b != 2 || !real_isfinite (arg))
127 return false;
128
129 int prec = format->p;
130 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
131 mpfr_t m, ms, mc;
132
133 mpfr_inits2 (prec, m, ms, mc, NULL);
134 mpfr_from_real (m, arg, GMP_RNDN);
135 mpfr_clear_flags ();
136 bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
137 bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
138 && do_mpfr_ckconv (result_cos, mc, inexact, format));
139 mpfr_clears (m, ms, mc, NULL);
140
141 return ok;
142}
143
144/* Try to evaluate:
145
146 *RESULT = f (*ARG0, *ARG1)
147
148 in format FORMAT, given that FUNC is the MPFR implementation of f.
149 Return true on success. */
150
151static bool
152do_mpfr_arg2 (real_value *result,
153 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t),
154 const real_value *arg0, const real_value *arg1,
155 const real_format *format)
156{
157 /* To proceed, MPFR must exactly represent the target floating point
158 format, which only happens when the target base equals two. */
159 if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
160 return false;
161
162 int prec = format->p;
163 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
164 mpfr_t m0, m1;
165
166 mpfr_inits2 (prec, m0, m1, NULL);
167 mpfr_from_real (m0, arg0, GMP_RNDN);
168 mpfr_from_real (m1, arg1, GMP_RNDN);
169 mpfr_clear_flags ();
170 bool inexact = func (m0, m0, m1, rnd);
171 bool ok = do_mpfr_ckconv (result, m0, inexact, format);
172 mpfr_clears (m0, m1, NULL);
173
174 return ok;
175}
176
177/* Try to evaluate:
178
179 *RESULT = f (ARG0, *ARG1)
180
181 in format FORMAT, given that FUNC is the MPFR implementation of f.
182 Return true on success. */
183
184static bool
185do_mpfr_arg2 (real_value *result,
186 int (*func) (mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
187 const wide_int_ref &arg0, const real_value *arg1,
188 const real_format *format)
189{
190 if (format->b != 2 || !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 m;
196
197 mpfr_init2 (m, prec);
198 mpfr_from_real (m, arg1, GMP_RNDN);
199 mpfr_clear_flags ();
200 bool inexact = func (m, arg0.to_shwi (), m, rnd);
201 bool ok = do_mpfr_ckconv (result, m, inexact, format);
202 mpfr_clear (m);
203
204 return ok;
205}
206
207/* Try to evaluate:
208
209 *RESULT = f (*ARG0, *ARG1, *ARG2)
210
211 in format FORMAT, given that FUNC is the MPFR implementation of f.
212 Return true on success. */
213
214static bool
215do_mpfr_arg3 (real_value *result,
216 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
217 mpfr_srcptr, mpfr_rnd_t),
218 const real_value *arg0, const real_value *arg1,
219 const real_value *arg2, const real_format *format)
220{
221 /* To proceed, MPFR must exactly represent the target floating point
222 format, which only happens when the target base equals two. */
223 if (format->b != 2
224 || !real_isfinite (arg0)
225 || !real_isfinite (arg1)
226 || !real_isfinite (arg2))
227 return false;
228
229 int prec = format->p;
230 mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
231 mpfr_t m0, m1, m2;
232
233 mpfr_inits2 (prec, m0, m1, m2, NULL);
234 mpfr_from_real (m0, arg0, GMP_RNDN);
235 mpfr_from_real (m1, arg1, GMP_RNDN);
236 mpfr_from_real (m2, arg2, GMP_RNDN);
237 mpfr_clear_flags ();
238 bool inexact = func (m0, m0, m1, m2, rnd);
239 bool ok = do_mpfr_ckconv (result, m0, inexact, format);
240 mpfr_clears (m0, m1, m2, NULL);
241
242 return ok;
243}
244
245/* M is the result of trying to constant-fold an expression (starting
246 with clear MPFR flags) and INEXACT says whether the result in M is
247 exact or inexact. Return true if M can be used as a constant-folded
248 result in which the real and imaginary parts have format FORMAT.
249 Store those parts in *RESULT_REAL and *RESULT_IMAG if so. */
250
251static bool
252do_mpc_ckconv (real_value *result_real, real_value *result_imag,
253 mpc_srcptr m, bool inexact, const real_format *format)
254{
255 /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
256 overflow/underflow occurred. If -frounding-math, proceed iff the
257 result of calling FUNC was exact. */
258 if (!mpfr_number_p (mpc_realref (m))
259 || !mpfr_number_p (mpc_imagref (m))
260 || mpfr_overflow_p ()
261 || mpfr_underflow_p ()
262 || (flag_rounding_math && inexact))
263 return false;
264
265 REAL_VALUE_TYPE tmp_real, tmp_imag;
266 real_from_mpfr (&tmp_real, mpc_realref (m), format, GMP_RNDN);
267 real_from_mpfr (&tmp_imag, mpc_imagref (m), format, GMP_RNDN);
268
269 /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
270 If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
271 underflowed in the conversion. */
272 if (!real_isfinite (&tmp_real)
273 || !real_isfinite (&tmp_imag)
274 || (tmp_real.cl == rvc_zero) != (mpfr_zero_p (mpc_realref (m)) != 0)
275 || (tmp_imag.cl == rvc_zero) != (mpfr_zero_p (mpc_imagref (m)) != 0))
276 return false;
277
278 real_convert (result_real, format, &tmp_real);
279 real_convert (result_imag, format, &tmp_imag);
280
281 return (real_identical (result_real, &tmp_real)
282 && real_identical (result_imag, &tmp_imag));
283}
284
285/* Try to evaluate:
286
287 RESULT = f (ARG)
288
289 in format FORMAT, given that FUNC is the mpc implementation of f.
290 Return true on success. Both RESULT and ARG are represented as
291 real and imaginary pairs. */
292
293static bool
294do_mpc_arg1 (real_value *result_real, real_value *result_imag,
295 int (*func) (mpc_ptr, mpc_srcptr, mpc_rnd_t),
296 const real_value *arg_real, const real_value *arg_imag,
297 const real_format *format)
298{
299 /* To proceed, MPFR must exactly represent the target floating point
300 format, which only happens when the target base equals two. */
301 if (format->b != 2
302 || !real_isfinite (arg_real)
303 || !real_isfinite (arg_imag))
304 return false;
305
306 int prec = format->p;
307 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
308 mpc_t m;
309
310 mpc_init2 (m, prec);
311 mpfr_from_real (mpc_realref (m), arg_real, GMP_RNDN);
312 mpfr_from_real (mpc_imagref (m), arg_imag, GMP_RNDN);
313 mpfr_clear_flags ();
314 bool inexact = func (m, m, crnd);
315 bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
316 mpc_clear (m);
317
318 return ok;
319}
320
321/* Try to evaluate:
322
323 RESULT = f (ARG0, ARG1)
324
325 in format FORMAT, given that FUNC is the mpc implementation of f.
326 Return true on success. RESULT, ARG0 and ARG1 are represented as
327 real and imaginary pairs. */
328
329static bool
330do_mpc_arg2 (real_value *result_real, real_value *result_imag,
331 int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t),
332 const real_value *arg0_real, const real_value *arg0_imag,
333 const real_value *arg1_real, const real_value *arg1_imag,
334 const real_format *format)
335{
336 if (!real_isfinite (arg0_real)
337 || !real_isfinite (arg0_imag)
338 || !real_isfinite (arg1_real)
339 || !real_isfinite (arg1_imag))
340 return false;
341
342 int prec = format->p;
343 mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
344 mpc_t m0, m1;
345
346 mpc_init2 (m0, prec);
347 mpc_init2 (m1, prec);
348 mpfr_from_real (mpc_realref (m0), arg0_real, GMP_RNDN);
349 mpfr_from_real (mpc_imagref (m0), arg0_imag, GMP_RNDN);
350 mpfr_from_real (mpc_realref (m1), arg1_real, GMP_RNDN);
351 mpfr_from_real (mpc_imagref (m1), arg1_imag, GMP_RNDN);
352 mpfr_clear_flags ();
353 bool inexact = func (m0, m0, m1, crnd);
354 bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
355 mpc_clear (m0);
356 mpc_clear (m1);
357
358 return ok;
359}
360
361/* Try to evaluate:
362
363 *RESULT = logb (*ARG)
364
365 in format FORMAT. Return true on success. */
366
367static bool
368fold_const_logb (real_value *result, const real_value *arg,
369 const real_format *format)
370{
371 switch (arg->cl)
372 {
373 case rvc_nan:
374 /* If arg is +-NaN, then return it. */
375 *result = *arg;
376 return true;
377
378 case rvc_inf:
379 /* If arg is +-Inf, then return +Inf. */
380 *result = *arg;
381 result->sign = 0;
382 return true;
383
384 case rvc_zero:
385 /* Zero may set errno and/or raise an exception. */
386 return false;
387
388 case rvc_normal:
389 /* For normal numbers, proceed iff radix == 2. In GCC,
390 normalized significands are in the range [0.5, 1.0). We
391 want the exponent as if they were [1.0, 2.0) so get the
392 exponent and subtract 1. */
393 if (format->b == 2)
394 {
395 real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED);
396 return true;
397 }
398 return false;
399 }
400 gcc_unreachable ();
401}
402
403/* Try to evaluate:
404
405 *RESULT = significand (*ARG)
406
407 in format FORMAT. Return true on success. */
408
409static bool
410fold_const_significand (real_value *result, const real_value *arg,
411 const real_format *format)
412{
413 switch (arg->cl)
414 {
415 case rvc_zero:
416 case rvc_nan:
417 case rvc_inf:
418 /* If arg is +-0, +-Inf or +-NaN, then return it. */
419 *result = *arg;
420 return true;
421
422 case rvc_normal:
423 /* For normal numbers, proceed iff radix == 2. */
424 if (format->b == 2)
425 {
426 *result = *arg;
427 /* In GCC, normalized significands are in the range [0.5, 1.0).
428 We want them to be [1.0, 2.0) so set the exponent to 1. */
429 SET_REAL_EXP (result, 1);
430 return true;
431 }
432 return false;
433 }
434 gcc_unreachable ();
435}
436
437/* Try to evaluate:
438
439 *RESULT = f (*ARG)
440
441 where FORMAT is the format of *ARG and PRECISION is the number of
442 significant bits in the result. Return true on success. */
443
444static bool
445fold_const_conversion (wide_int *result,
446 void (*fn) (real_value *, format_helper,
447 const real_value *),
448 const real_value *arg, unsigned int precision,
449 const real_format *format)
450{
451 if (!real_isfinite (arg))
452 return false;
453
454 real_value rounded;
455 fn (&rounded, format, arg);
456
457 bool fail = false;
458 *result = real_to_integer (&rounded, &fail, precision);
459 return !fail;
460}
461
462/* Try to evaluate:
463
464 *RESULT = pow (*ARG0, *ARG1)
465
466 in format FORMAT. Return true on success. */
467
468static bool
469fold_const_pow (real_value *result, const real_value *arg0,
470 const real_value *arg1, const real_format *format)
471{
472 if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
473 return true;
474
475 /* Check for an integer exponent. */
476 REAL_VALUE_TYPE cint1;
477 HOST_WIDE_INT n1 = real_to_integer (arg1);
478 real_from_integer (&cint1, VOIDmode, n1, SIGNED);
479 /* Attempt to evaluate pow at compile-time, unless this should
480 raise an exception. */
481 if (real_identical (arg1, &cint1)
482 && (n1 > 0
483 || (!flag_trapping_math && !flag_errno_math)
484 || !real_equal (arg0, &dconst0)))
485 {
486 bool inexact = real_powi (result, format, arg0, n1);
487 if (flag_unsafe_math_optimizations || !inexact)
488 return true;
489 }
490
491 return false;
492}
493
494/* Try to evaluate:
495
496 *RESULT = ldexp (*ARG0, ARG1)
497
498 in format FORMAT. Return true on success. */
499
500static bool
501fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
502 const wide_int_ref &arg1,
503 const real_format *format)
504{
505 /* Bound the maximum adjustment to twice the range of the
506 mode's valid exponents. Use abs to ensure the range is
507 positive as a sanity check. */
508 int max_exp_adj = 2 * labs (format->emax - format->emin);
509
510 /* The requested adjustment must be inside this range. This
511 is a preliminary cap to avoid things like overflow, we
512 may still fail to compute the result for other reasons. */
513 if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
514 return false;
515
516 REAL_VALUE_TYPE initial_result;
517 real_ldexp (&initial_result, arg0, arg1.to_shwi ());
518
519 /* Ensure we didn't overflow. */
520 if (real_isinf (&initial_result))
521 return false;
522
523 /* Only proceed if the target mode can hold the
524 resulting value. */
525 *result = real_value_truncate (format, initial_result);
526 return real_equal (&initial_result, result);
527}
528
529/* Try to evaluate:
530
531 *RESULT = FN (*ARG)
532
533 in format FORMAT. Return true on success. */
534
535static bool
536fold_const_call_ss (real_value *result, built_in_function fn,
537 const real_value *arg, const real_format *format)
538{
539 switch (fn)
540 {
541 CASE_FLT_FN (BUILT_IN_SQRT):
542 return (real_compare (GE_EXPR, arg, &dconst0)
543 && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
544
545 CASE_FLT_FN (BUILT_IN_CBRT):
546 return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
547
548 CASE_FLT_FN (BUILT_IN_ASIN):
549 return (real_compare (GE_EXPR, arg, &dconstm1)
550 && real_compare (LE_EXPR, arg, &dconst1)
551 && do_mpfr_arg1 (result, mpfr_asin, arg, format));
552
553 CASE_FLT_FN (BUILT_IN_ACOS):
554 return (real_compare (GE_EXPR, arg, &dconstm1)
555 && real_compare (LE_EXPR, arg, &dconst1)
556 && do_mpfr_arg1 (result, mpfr_acos, arg, format));
557
558 CASE_FLT_FN (BUILT_IN_ATAN):
559 return do_mpfr_arg1 (result, mpfr_atan, arg, format);
560
561 CASE_FLT_FN (BUILT_IN_ASINH):
562 return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
563
564 CASE_FLT_FN (BUILT_IN_ACOSH):
565 return (real_compare (GE_EXPR, arg, &dconst1)
566 && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
567
568 CASE_FLT_FN (BUILT_IN_ATANH):
569 return (real_compare (GE_EXPR, arg, &dconstm1)
570 && real_compare (LE_EXPR, arg, &dconst1)
571 && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
572
573 CASE_FLT_FN (BUILT_IN_SIN):
574 return do_mpfr_arg1 (result, mpfr_sin, arg, format);
575
576 CASE_FLT_FN (BUILT_IN_COS):
577 return do_mpfr_arg1 (result, mpfr_cos, arg, format);
578
579 CASE_FLT_FN (BUILT_IN_TAN):
580 return do_mpfr_arg1 (result, mpfr_tan, arg, format);
581
582 CASE_FLT_FN (BUILT_IN_SINH):
583 return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
584
585 CASE_FLT_FN (BUILT_IN_COSH):
586 return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
587
588 CASE_FLT_FN (BUILT_IN_TANH):
589 return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
590
591 CASE_FLT_FN (BUILT_IN_ERF):
592 return do_mpfr_arg1 (result, mpfr_erf, arg, format);
593
594 CASE_FLT_FN (BUILT_IN_ERFC):
595 return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
596
597 CASE_FLT_FN (BUILT_IN_TGAMMA):
598 return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
599
600 CASE_FLT_FN (BUILT_IN_EXP):
601 return do_mpfr_arg1 (result, mpfr_exp, arg, format);
602
603 CASE_FLT_FN (BUILT_IN_EXP2):
604 return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
605
606 CASE_FLT_FN (BUILT_IN_EXP10):
607 CASE_FLT_FN (BUILT_IN_POW10):
608 return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
609
610 CASE_FLT_FN (BUILT_IN_EXPM1):
611 return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
612
613 CASE_FLT_FN (BUILT_IN_LOG):
614 return (real_compare (GT_EXPR, arg, &dconst0)
615 && do_mpfr_arg1 (result, mpfr_log, arg, format));
616
617 CASE_FLT_FN (BUILT_IN_LOG2):
618 return (real_compare (GT_EXPR, arg, &dconst0)
619 && do_mpfr_arg1 (result, mpfr_log2, arg, format));
620
621 CASE_FLT_FN (BUILT_IN_LOG10):
622 return (real_compare (GT_EXPR, arg, &dconst0)
623 && do_mpfr_arg1 (result, mpfr_log10, arg, format));
624
625 CASE_FLT_FN (BUILT_IN_LOG1P):
626 return (real_compare (GT_EXPR, arg, &dconstm1)
627 && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
628
629 CASE_FLT_FN (BUILT_IN_J0):
630 return do_mpfr_arg1 (result, mpfr_j0, arg, format);
631
632 CASE_FLT_FN (BUILT_IN_J1):
633 return do_mpfr_arg1 (result, mpfr_j1, arg, format);
634
635 CASE_FLT_FN (BUILT_IN_Y0):
636 return (real_compare (GT_EXPR, arg, &dconst0)
637 && do_mpfr_arg1 (result, mpfr_y0, arg, format));
638
639 CASE_FLT_FN (BUILT_IN_Y1):
640 return (real_compare (GT_EXPR, arg, &dconst0)
641 && do_mpfr_arg1 (result, mpfr_y1, arg, format));
642
643 CASE_FLT_FN (BUILT_IN_FLOOR):
644 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
645 {
646 real_floor (result, format, arg);
647 return true;
648 }
649 return false;
650
651 CASE_FLT_FN (BUILT_IN_CEIL):
652 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
653 {
654 real_ceil (result, format, arg);
655 return true;
656 }
657 return false;
658
659 CASE_FLT_FN (BUILT_IN_TRUNC):
660 real_trunc (result, format, arg);
661 return true;
662
663 CASE_FLT_FN (BUILT_IN_ROUND):
664 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
665 {
666 real_round (result, format, arg);
667 return true;
668 }
669 return false;
670
671 CASE_FLT_FN (BUILT_IN_LOGB):
672 return fold_const_logb (result, arg, format);
673
674 CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
675 return fold_const_significand (result, arg, format);
676
677 default:
678 return false;
679 }
680}
681
682/* Try to evaluate:
683
684 *RESULT = FN (*ARG)
685
686 where FORMAT is the format of ARG and PRECISION is the number of
687 significant bits in the result. Return true on success. */
688
689static bool
690fold_const_call_ss (wide_int *result, built_in_function fn,
691 const real_value *arg, unsigned int precision,
692 const real_format *format)
693{
694 switch (fn)
695 {
696 CASE_FLT_FN (BUILT_IN_SIGNBIT):
697 if (real_isneg (arg))
698 *result = wi::one (precision);
699 else
700 *result = wi::zero (precision);
701 return true;
702
703 CASE_FLT_FN (BUILT_IN_ILOGB):
704 /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
705 Proceed iff radix == 2. In GCC, normalized significands are in
706 the range [0.5, 1.0). We want the exponent as if they were
707 [1.0, 2.0) so get the exponent and subtract 1. */
708 if (arg->cl == rvc_normal && format->b == 2)
709 {
710 *result = wi::shwi (REAL_EXP (arg) - 1, precision);
711 return true;
712 }
713 return false;
714
715 CASE_FLT_FN (BUILT_IN_ICEIL):
716 CASE_FLT_FN (BUILT_IN_LCEIL):
717 CASE_FLT_FN (BUILT_IN_LLCEIL):
718 return fold_const_conversion (result, real_ceil, arg,
719 precision, format);
720
721 CASE_FLT_FN (BUILT_IN_LFLOOR):
722 CASE_FLT_FN (BUILT_IN_IFLOOR):
723 CASE_FLT_FN (BUILT_IN_LLFLOOR):
724 return fold_const_conversion (result, real_floor, arg,
725 precision, format);
726
727 CASE_FLT_FN (BUILT_IN_IROUND):
728 CASE_FLT_FN (BUILT_IN_LROUND):
729 CASE_FLT_FN (BUILT_IN_LLROUND):
730 return fold_const_conversion (result, real_round, arg,
731 precision, format);
732
733 CASE_FLT_FN (BUILT_IN_IRINT):
734 CASE_FLT_FN (BUILT_IN_LRINT):
735 CASE_FLT_FN (BUILT_IN_LLRINT):
736 /* Not yet folded to a constant. */
737 return false;
738
739 default:
740 return false;
741 }
742}
743
744/* Try to evaluate:
745
746 RESULT = FN (*ARG)
747
748 where FORMAT is the format of ARG and of the real and imaginary parts
749 of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
750 true on success. */
751
752static bool
753fold_const_call_cs (real_value *result_real, real_value *result_imag,
754 built_in_function fn, const real_value *arg,
755 const real_format *format)
756{
757 switch (fn)
758 {
759 CASE_FLT_FN (BUILT_IN_CEXPI):
760 /* cexpi(x+yi) = cos(x)+sin(y)*i. */
761 return do_mpfr_sincos (result_imag, result_real, arg, format);
762
763 default:
764 return false;
765 }
766}
767
768/* Try to evaluate:
769
770 *RESULT = fn (ARG)
771
772 where FORMAT is the format of RESULT and of the real and imaginary parts
773 of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
774 success. */
775
776static bool
777fold_const_call_sc (real_value *result, built_in_function fn,
778 const real_value *arg_real, const real_value *arg_imag,
779 const real_format *format)
780{
781 switch (fn)
782 {
783 CASE_FLT_FN (BUILT_IN_CABS):
784 return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
785
786 default:
787 return false;
788 }
789}
790
791/* Try to evaluate:
792
793 RESULT = fn (ARG)
794
795 where FORMAT is the format of the real and imaginary parts of RESULT
796 (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
797 Return true on success. */
798
799static bool
800fold_const_call_cc (real_value *result_real, real_value *result_imag,
801 built_in_function fn, const real_value *arg_real,
802 const real_value *arg_imag, const real_format *format)
803{
804 switch (fn)
805 {
806 CASE_FLT_FN (BUILT_IN_CCOS):
807 return do_mpc_arg1 (result_real, result_imag, mpc_cos,
808 arg_real, arg_imag, format);
809
810 CASE_FLT_FN (BUILT_IN_CCOSH):
811 return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
812 arg_real, arg_imag, format);
813
814 CASE_FLT_FN (BUILT_IN_CPROJ):
815 if (real_isinf (arg_real) || real_isinf (arg_imag))
816 {
817 real_inf (result_real);
818 *result_imag = dconst0;
819 result_imag->sign = arg_imag->sign;
820 }
821 else
822 {
823 *result_real = *arg_real;
824 *result_imag = *arg_imag;
825 }
826 return true;
827
828 CASE_FLT_FN (BUILT_IN_CSIN):
829 return do_mpc_arg1 (result_real, result_imag, mpc_sin,
830 arg_real, arg_imag, format);
831
832 CASE_FLT_FN (BUILT_IN_CSINH):
833 return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
834 arg_real, arg_imag, format);
835
836 CASE_FLT_FN (BUILT_IN_CTAN):
837 return do_mpc_arg1 (result_real, result_imag, mpc_tan,
838 arg_real, arg_imag, format);
839
840 CASE_FLT_FN (BUILT_IN_CTANH):
841 return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
842 arg_real, arg_imag, format);
843
844 CASE_FLT_FN (BUILT_IN_CLOG):
845 return do_mpc_arg1 (result_real, result_imag, mpc_log,
846 arg_real, arg_imag, format);
847
848 CASE_FLT_FN (BUILT_IN_CSQRT):
849 return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
850 arg_real, arg_imag, format);
851
852 CASE_FLT_FN (BUILT_IN_CASIN):
853 return do_mpc_arg1 (result_real, result_imag, mpc_asin,
854 arg_real, arg_imag, format);
855
856 CASE_FLT_FN (BUILT_IN_CACOS):
857 return do_mpc_arg1 (result_real, result_imag, mpc_acos,
858 arg_real, arg_imag, format);
859
860 CASE_FLT_FN (BUILT_IN_CATAN):
861 return do_mpc_arg1 (result_real, result_imag, mpc_atan,
862 arg_real, arg_imag, format);
863
864 CASE_FLT_FN (BUILT_IN_CASINH):
865 return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
866 arg_real, arg_imag, format);
867
868 CASE_FLT_FN (BUILT_IN_CACOSH):
869 return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
870 arg_real, arg_imag, format);
871
872 CASE_FLT_FN (BUILT_IN_CATANH):
873 return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
874 arg_real, arg_imag, format);
875
876 CASE_FLT_FN (BUILT_IN_CEXP):
877 return do_mpc_arg1 (result_real, result_imag, mpc_exp,
878 arg_real, arg_imag, format);
879
880 default:
881 return false;
882 }
883}
884
885/* Try to fold FN (ARG) to a constant. Return the constant on success,
886 otherwise return null. TYPE is the type of the return value. */
887
888tree
889fold_const_call (built_in_function fn, tree type, tree arg)
890{
891 machine_mode mode = TYPE_MODE (type);
892 machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
893
894 if (real_cst_p (arg))
895 {
896 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
897 if (mode == arg_mode)
898 {
899 /* real -> real. */
900 REAL_VALUE_TYPE result;
901 if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
902 REAL_MODE_FORMAT (mode)))
903 return build_real (type, result);
904 }
905 else if (COMPLEX_MODE_P (mode)
906 && GET_MODE_INNER (mode) == arg_mode)
907 {
908 /* real -> complex real. */
909 REAL_VALUE_TYPE result_real, result_imag;
910 if (fold_const_call_cs (&result_real, &result_imag, fn,
911 TREE_REAL_CST_PTR (arg),
912 REAL_MODE_FORMAT (arg_mode)))
913 return build_complex (type,
914 build_real (TREE_TYPE (type), result_real),
915 build_real (TREE_TYPE (type), result_imag));
916 }
917 else if (INTEGRAL_TYPE_P (type))
918 {
919 /* real -> int. */
920 wide_int result;
921 if (fold_const_call_ss (&result, fn,
922 TREE_REAL_CST_PTR (arg),
923 TYPE_PRECISION (type),
924 REAL_MODE_FORMAT (arg_mode)))
925 return wide_int_to_tree (type, result);
926 }
927 return NULL_TREE;
928 }
929
930 if (complex_cst_p (arg))
931 {
932 gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
933 machine_mode inner_mode = GET_MODE_INNER (arg_mode);
934 tree argr = TREE_REALPART (arg);
935 tree argi = TREE_IMAGPART (arg);
936 if (mode == arg_mode
937 && real_cst_p (argr)
938 && real_cst_p (argi))
939 {
940 /* complex real -> complex real. */
941 REAL_VALUE_TYPE result_real, result_imag;
942 if (fold_const_call_cc (&result_real, &result_imag, fn,
943 TREE_REAL_CST_PTR (argr),
944 TREE_REAL_CST_PTR (argi),
945 REAL_MODE_FORMAT (inner_mode)))
946 return build_complex (type,
947 build_real (TREE_TYPE (type), result_real),
948 build_real (TREE_TYPE (type), result_imag));
949 }
950 if (mode == inner_mode
951 && real_cst_p (argr)
952 && real_cst_p (argi))
953 {
954 /* complex real -> real. */
955 REAL_VALUE_TYPE result;
956 if (fold_const_call_sc (&result, fn,
957 TREE_REAL_CST_PTR (argr),
958 TREE_REAL_CST_PTR (argi),
959 REAL_MODE_FORMAT (inner_mode)))
960 return build_real (type, result);
961 }
962 return NULL_TREE;
963 }
964
965 return NULL_TREE;
966}
967
968/* Try to evaluate:
969
970 *RESULT = FN (*ARG0, *ARG1)
971
972 in format FORMAT. Return true on success. */
973
974static bool
975fold_const_call_sss (real_value *result, built_in_function fn,
976 const real_value *arg0, const real_value *arg1,
977 const real_format *format)
978{
979 switch (fn)
980 {
981 CASE_FLT_FN (BUILT_IN_DREM):
982 CASE_FLT_FN (BUILT_IN_REMAINDER):
983 return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
984
985 CASE_FLT_FN (BUILT_IN_ATAN2):
986 return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
987
988 CASE_FLT_FN (BUILT_IN_FDIM):
989 return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
990
991 CASE_FLT_FN (BUILT_IN_HYPOT):
992 return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
993
994 CASE_FLT_FN (BUILT_IN_COPYSIGN):
995 *result = *arg0;
996 real_copysign (result, arg1);
997 return true;
998
999 CASE_FLT_FN (BUILT_IN_FMIN):
1000 return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1001
1002 CASE_FLT_FN (BUILT_IN_FMAX):
1003 return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1004
1005 CASE_FLT_FN (BUILT_IN_POW):
1006 return fold_const_pow (result, arg0, arg1, format);
1007
1008 default:
1009 return false;
1010 }
1011}
1012
1013/* Try to evaluate:
1014
1015 *RESULT = FN (*ARG0, ARG1)
1016
1017 where FORMAT is the format of *RESULT and *ARG0. Return true on
1018 success. */
1019
1020static bool
1021fold_const_call_sss (real_value *result, built_in_function fn,
1022 const real_value *arg0, const wide_int_ref &arg1,
1023 const real_format *format)
1024{
1025 switch (fn)
1026 {
1027 CASE_FLT_FN (BUILT_IN_LDEXP):
1028 return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1029
1030 CASE_FLT_FN (BUILT_IN_SCALBN):
1031 CASE_FLT_FN (BUILT_IN_SCALBLN):
1032 return (format->b == 2
1033 && fold_const_builtin_load_exponent (result, arg0, arg1,
1034 format));
1035
1036 CASE_FLT_FN (BUILT_IN_POWI):
1037 real_powi (result, format, arg0, arg1.to_shwi ());
1038 return true;
1039
1040 default:
1041 return false;
1042 }
1043}
1044
1045/* Try to evaluate:
1046
1047 *RESULT = FN (ARG0, *ARG1)
1048
1049 where FORMAT is the format of *RESULT and *ARG1. Return true on
1050 success. */
1051
1052static bool
1053fold_const_call_sss (real_value *result, built_in_function fn,
1054 const wide_int_ref &arg0, const real_value *arg1,
1055 const real_format *format)
1056{
1057 switch (fn)
1058 {
1059 CASE_FLT_FN (BUILT_IN_JN):
1060 return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1061
1062 CASE_FLT_FN (BUILT_IN_YN):
1063 return (real_compare (GT_EXPR, arg1, &dconst0)
1064 && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1065
1066 default:
1067 return false;
1068 }
1069}
1070
1071/* Try to evaluate:
1072
1073 RESULT = fn (ARG0, ARG1)
1074
1075 where FORMAT is the format of the real and imaginary parts of RESULT
1076 (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1077 and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1078
1079static bool
1080fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1081 built_in_function fn, const real_value *arg0_real,
1082 const real_value *arg0_imag, const real_value *arg1_real,
1083 const real_value *arg1_imag, const real_format *format)
1084{
1085 switch (fn)
1086 {
1087 CASE_FLT_FN (BUILT_IN_CPOW):
1088 return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1089 arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1090
1091 default:
1092 return false;
1093 }
1094}
1095
1096/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1097 otherwise return null. TYPE is the type of the return value. */
1098
1099tree
1100fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1)
1101{
1102 machine_mode mode = TYPE_MODE (type);
1103 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1104 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1105
1106 if (arg0_mode == arg1_mode
1107 && real_cst_p (arg0)
1108 && real_cst_p (arg1))
1109 {
1110 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1111 if (mode == arg0_mode)
1112 {
1113 /* real, real -> real. */
1114 REAL_VALUE_TYPE result;
1115 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1116 TREE_REAL_CST_PTR (arg1),
1117 REAL_MODE_FORMAT (mode)))
1118 return build_real (type, result);
1119 }
1120 return NULL_TREE;
1121 }
1122
1123 if (real_cst_p (arg0)
1124 && integer_cst_p (arg1))
1125 {
1126 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1127 if (mode == arg0_mode)
1128 {
1129 /* real, int -> real. */
1130 REAL_VALUE_TYPE result;
1131 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1132 arg1, REAL_MODE_FORMAT (mode)))
1133 return build_real (type, result);
1134 }
1135 return NULL_TREE;
1136 }
1137
1138 if (integer_cst_p (arg0)
1139 && real_cst_p (arg1))
1140 {
1141 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1142 if (mode == arg1_mode)
1143 {
1144 /* int, real -> real. */
1145 REAL_VALUE_TYPE result;
1146 if (fold_const_call_sss (&result, fn, arg0,
1147 TREE_REAL_CST_PTR (arg1),
1148 REAL_MODE_FORMAT (mode)))
1149 return build_real (type, result);
1150 }
1151 return NULL_TREE;
1152 }
1153
1154 if (arg0_mode == arg1_mode
1155 && complex_cst_p (arg0)
1156 && complex_cst_p (arg1))
1157 {
1158 gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1159 machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1160 tree arg0r = TREE_REALPART (arg0);
1161 tree arg0i = TREE_IMAGPART (arg0);
1162 tree arg1r = TREE_REALPART (arg1);
1163 tree arg1i = TREE_IMAGPART (arg1);
1164 if (mode == arg0_mode
1165 && real_cst_p (arg0r)
1166 && real_cst_p (arg0i)
1167 && real_cst_p (arg1r)
1168 && real_cst_p (arg1i))
1169 {
1170 /* complex real, complex real -> complex real. */
1171 REAL_VALUE_TYPE result_real, result_imag;
1172 if (fold_const_call_ccc (&result_real, &result_imag, fn,
1173 TREE_REAL_CST_PTR (arg0r),
1174 TREE_REAL_CST_PTR (arg0i),
1175 TREE_REAL_CST_PTR (arg1r),
1176 TREE_REAL_CST_PTR (arg1i),
1177 REAL_MODE_FORMAT (inner_mode)))
1178 return build_complex (type,
1179 build_real (TREE_TYPE (type), result_real),
1180 build_real (TREE_TYPE (type), result_imag));
1181 }
1182 return NULL_TREE;
1183 }
1184
1185 return NULL_TREE;
1186}
1187
1188/* Try to evaluate:
1189
1190 *RESULT = FN (*ARG0, *ARG1, *ARG2)
1191
1192 in format FORMAT. Return true on success. */
1193
1194static bool
1195fold_const_call_ssss (real_value *result, built_in_function fn,
1196 const real_value *arg0, const real_value *arg1,
1197 const real_value *arg2, const real_format *format)
1198{
1199 switch (fn)
1200 {
1201 CASE_FLT_FN (BUILT_IN_FMA):
1202 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1203
1204 default:
1205 return false;
1206 }
1207}
1208
1209/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
1210 success, otherwise return null. TYPE is the type of the return value. */
1211
1212tree
1213fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1,
1214 tree arg2)
1215{
1216 machine_mode mode = TYPE_MODE (type);
1217 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1218 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1219 machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1220
1221 if (arg0_mode == arg1_mode
1222 && arg0_mode == arg2_mode
1223 && real_cst_p (arg0)
1224 && real_cst_p (arg1)
1225 && real_cst_p (arg2))
1226 {
1227 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1228 if (mode == arg0_mode)
1229 {
1230 /* real, real, real -> real. */
1231 REAL_VALUE_TYPE result;
1232 if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1233 TREE_REAL_CST_PTR (arg1),
1234 TREE_REAL_CST_PTR (arg2),
1235 REAL_MODE_FORMAT (mode)))
1236 return build_real (type, result);
1237 }
1238 return NULL_TREE;
1239 }
1240
1241 return NULL_TREE;
1242}
1243
1244/* Fold a fma operation with arguments ARG[012]. */
1245
1246tree
1247fold_fma (location_t, tree type, tree arg0, tree arg1, tree arg2)
1248{
1249 REAL_VALUE_TYPE result;
1250 if (real_cst_p (arg0)
1251 && real_cst_p (arg1)
1252 && real_cst_p (arg2)
1253 && do_mpfr_arg3 (&result, mpfr_fma, TREE_REAL_CST_PTR (arg0),
1254 TREE_REAL_CST_PTR (arg1), TREE_REAL_CST_PTR (arg2),
1255 REAL_MODE_FORMAT (TYPE_MODE (type))))
1256 return build_real (type, result);
1257
1258 return NULL_TREE;
1259}