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