Line data Source code
1 : /* Constant folding for calls to built-in and internal functions.
2 : Copyright (C) 1988-2026 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_VALUE_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
39 35004458 : integer_cst_p (tree t)
40 : {
41 35004458 : return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
42 : }
43 :
44 : static inline bool
45 38376865 : real_cst_p (tree t)
46 : {
47 38376865 : return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
48 : }
49 :
50 : static inline bool
51 22332686 : complex_cst_p (tree t)
52 : {
53 22332686 : 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
60 2764215 : size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
61 : {
62 2764215 : if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 2764060 : && integer_cst_p (t)
64 4423653 : && tree_fits_uhwi_p (t))
65 : {
66 1659438 : *size_out = tree_to_uhwi (t);
67 1659438 : 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
77 66476 : build_cmp_result (tree type, int res)
78 : {
79 71094 : 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
88 236947 : 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 236947 : if (!mpfr_number_p (m)
95 221938 : || mpfr_overflow_p ()
96 221938 : || mpfr_underflow_p ()
97 455341 : || (flag_rounding_math && inexact))
98 18638 : return false;
99 :
100 218309 : REAL_VALUE_TYPE tmp;
101 218309 : 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 mpfr_t is not, then we
105 : underflowed in the conversion. */
106 218309 : if (!real_isfinite (&tmp)
107 218309 : || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
108 : return false;
109 :
110 218309 : real_convert (result, format, &tmp);
111 218309 : 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
122 106557 : 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 106557 : if (format->b != 2 || !real_isfinite (arg))
129 2742 : return false;
130 :
131 103815 : int prec = format->p;
132 103815 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
133 :
134 103815 : auto_mpfr m (prec);
135 103815 : mpfr_from_real (m, arg, MPFR_RNDN);
136 103815 : mpfr_clear_flags ();
137 103815 : bool inexact = func (m, m, rnd);
138 103815 : bool ok = do_mpfr_ckconv (result, m, inexact, format);
139 :
140 103815 : return ok;
141 103815 : }
142 :
143 : /* Try to evaluate:
144 :
145 : *RESULT_SIN = sin (*ARG);
146 : *RESULT_COS = cos (*ARG);
147 :
148 : for format FORMAT. Return true on success. */
149 :
150 : static bool
151 146 : do_mpfr_sincos (real_value *result_sin, real_value *result_cos,
152 : const real_value *arg, const real_format *format)
153 : {
154 : /* To proceed, MPFR must exactly represent the target floating point
155 : format, which only happens when the target base equals two. */
156 146 : if (format->b != 2 || !real_isfinite (arg))
157 0 : return false;
158 :
159 146 : int prec = format->p;
160 146 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
161 146 : mpfr_t m, ms, mc;
162 :
163 146 : mpfr_inits2 (prec, m, ms, mc, NULL);
164 146 : mpfr_from_real (m, arg, MPFR_RNDN);
165 146 : mpfr_clear_flags ();
166 146 : bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
167 146 : bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
168 146 : && do_mpfr_ckconv (result_cos, mc, inexact, format));
169 146 : mpfr_clears (m, ms, mc, NULL);
170 :
171 146 : return ok;
172 : }
173 :
174 : /* Try to evaluate:
175 :
176 : *RESULT = f (*ARG0, *ARG1)
177 :
178 : in format FORMAT, given that FUNC is the MPFR implementation of f.
179 : Return true on success. */
180 :
181 : static bool
182 139595 : do_mpfr_arg2 (real_value *result,
183 : int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t),
184 : const real_value *arg0, const real_value *arg1,
185 : const real_format *format)
186 : {
187 : /* To proceed, MPFR must exactly represent the target floating point
188 : format, which only happens when the target base equals two. */
189 139595 : if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
190 11044 : return false;
191 :
192 128551 : int prec = format->p;
193 128551 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
194 128551 : mpfr_t m0, m1;
195 :
196 128551 : mpfr_inits2 (prec, m0, m1, NULL);
197 128551 : mpfr_from_real (m0, arg0, MPFR_RNDN);
198 128551 : mpfr_from_real (m1, arg1, MPFR_RNDN);
199 128551 : mpfr_clear_flags ();
200 128551 : bool inexact = func (m0, m0, m1, rnd);
201 128551 : bool ok = do_mpfr_ckconv (result, m0, inexact, format);
202 128551 : mpfr_clears (m0, m1, NULL);
203 :
204 128551 : return ok;
205 : }
206 :
207 : /* Try to evaluate:
208 :
209 : *RESULT = f (ARG0, *ARG1)
210 :
211 : in format FORMAT, given that FUNC is the MPFR implementation of f.
212 : Return true on success. */
213 :
214 : static bool
215 1755 : do_mpfr_arg2 (real_value *result,
216 : int (*func) (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t),
217 : const wide_int_ref &arg0, const real_value *arg1,
218 : const real_format *format)
219 : {
220 1755 : if (format->b != 2 || !real_isfinite (arg1))
221 0 : return false;
222 :
223 1755 : int prec = format->p;
224 1755 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
225 :
226 1755 : auto_mpfr m (prec);
227 1755 : mpfr_from_real (m, arg1, MPFR_RNDN);
228 1755 : mpfr_clear_flags ();
229 1755 : bool inexact = func (m, arg0.to_shwi (), m, rnd);
230 1755 : bool ok = do_mpfr_ckconv (result, m, inexact, format);
231 :
232 1755 : return ok;
233 1755 : }
234 :
235 : /* Try to evaluate:
236 :
237 : *RESULT = f (*ARG0, *ARG1, *ARG2)
238 :
239 : in format FORMAT, given that FUNC is the MPFR implementation of f.
240 : Return true on success. */
241 :
242 : static bool
243 2534 : do_mpfr_arg3 (real_value *result,
244 : int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
245 : mpfr_srcptr, mpfr_rnd_t),
246 : const real_value *arg0, const real_value *arg1,
247 : const real_value *arg2, const real_format *format)
248 : {
249 : /* To proceed, MPFR must exactly represent the target floating point
250 : format, which only happens when the target base equals two. */
251 2534 : if (format->b != 2
252 2534 : || !real_isfinite (arg0)
253 2534 : || !real_isfinite (arg1)
254 5068 : || !real_isfinite (arg2))
255 0 : return false;
256 :
257 2534 : int prec = format->p;
258 2534 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
259 2534 : mpfr_t m0, m1, m2;
260 :
261 2534 : mpfr_inits2 (prec, m0, m1, m2, NULL);
262 2534 : mpfr_from_real (m0, arg0, MPFR_RNDN);
263 2534 : mpfr_from_real (m1, arg1, MPFR_RNDN);
264 2534 : mpfr_from_real (m2, arg2, MPFR_RNDN);
265 2534 : mpfr_clear_flags ();
266 2534 : bool inexact = func (m0, m0, m1, m2, rnd);
267 2534 : bool ok = do_mpfr_ckconv (result, m0, inexact, format);
268 2534 : mpfr_clears (m0, m1, m2, NULL);
269 :
270 2534 : return ok;
271 : }
272 :
273 : /* M is the result of trying to constant-fold an expression (starting
274 : with clear MPFR flags) and INEXACT says whether the result in M is
275 : exact or inexact. Return true if M can be used as a constant-folded
276 : result in which the real and imaginary parts have format FORMAT.
277 : Store those parts in *RESULT_REAL and *RESULT_IMAG if so. */
278 :
279 : static bool
280 38816 : do_mpc_ckconv (real_value *result_real, real_value *result_imag,
281 : mpc_srcptr m, bool inexact, const real_format *format)
282 : {
283 : /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
284 : overflow/underflow occurred. If -frounding-math, proceed iff the
285 : result of calling FUNC was exact. */
286 38816 : if (!mpfr_number_p (mpc_realref (m))
287 33276 : || !mpfr_number_p (mpc_imagref (m))
288 33276 : || mpfr_overflow_p ()
289 33276 : || mpfr_underflow_p ()
290 68458 : || (flag_rounding_math && inexact))
291 9174 : return false;
292 :
293 29642 : REAL_VALUE_TYPE tmp_real, tmp_imag;
294 29642 : real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN);
295 29642 : real_from_mpfr (&tmp_imag, mpc_imagref (m), format, MPFR_RNDN);
296 :
297 : /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
298 : If the REAL_VALUE_TYPE is zero but the mpfr_t is not, then we
299 : underflowed in the conversion. */
300 29642 : if (!real_isfinite (&tmp_real)
301 29642 : || !real_isfinite (&tmp_imag)
302 29642 : || (tmp_real.cl == rvc_zero) != (mpfr_zero_p (mpc_realref (m)) != 0)
303 59284 : || (tmp_imag.cl == rvc_zero) != (mpfr_zero_p (mpc_imagref (m)) != 0))
304 0 : return false;
305 :
306 29642 : real_convert (result_real, format, &tmp_real);
307 29642 : real_convert (result_imag, format, &tmp_imag);
308 :
309 29642 : return (real_identical (result_real, &tmp_real)
310 29642 : && real_identical (result_imag, &tmp_imag));
311 : }
312 :
313 : /* Try to evaluate:
314 :
315 : RESULT = f (ARG)
316 :
317 : in format FORMAT, given that FUNC is the mpc implementation of f.
318 : Return true on success. Both RESULT and ARG are represented as
319 : real and imaginary pairs. */
320 :
321 : static bool
322 13715 : do_mpc_arg1 (real_value *result_real, real_value *result_imag,
323 : int (*func) (mpc_ptr, mpc_srcptr, mpc_rnd_t),
324 : const real_value *arg_real, const real_value *arg_imag,
325 : const real_format *format)
326 : {
327 : /* To proceed, MPFR must exactly represent the target floating point
328 : format, which only happens when the target base equals two. */
329 13715 : if (format->b != 2
330 13715 : || !real_isfinite (arg_real)
331 25108 : || !real_isfinite (arg_imag))
332 2322 : return false;
333 :
334 11393 : int prec = format->p;
335 11393 : mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
336 11393 : mpc_t m;
337 :
338 11393 : mpc_init2 (m, prec);
339 11393 : mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN);
340 11393 : mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN);
341 11393 : mpfr_clear_flags ();
342 11393 : bool inexact = func (m, m, crnd);
343 11393 : bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
344 11393 : mpc_clear (m);
345 :
346 11393 : return ok;
347 : }
348 :
349 : /* Try to evaluate:
350 :
351 : RESULT = f (ARG0, ARG1)
352 :
353 : in format FORMAT, given that FUNC is the mpc implementation of f.
354 : Return true on success. RESULT, ARG0 and ARG1 are represented as
355 : real and imaginary pairs. */
356 :
357 : static bool
358 32067 : do_mpc_arg2 (real_value *result_real, real_value *result_imag,
359 : int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t),
360 : const real_value *arg0_real, const real_value *arg0_imag,
361 : const real_value *arg1_real, const real_value *arg1_imag,
362 : const real_format *format)
363 : {
364 32067 : if (!real_isfinite (arg0_real)
365 29745 : || !real_isfinite (arg0_imag)
366 29745 : || !real_isfinite (arg1_real)
367 59490 : || !real_isfinite (arg1_imag))
368 4644 : return false;
369 :
370 27423 : int prec = format->p;
371 27423 : mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
372 27423 : mpc_t m0, m1;
373 :
374 27423 : mpc_init2 (m0, prec);
375 27423 : mpc_init2 (m1, prec);
376 27423 : mpfr_from_real (mpc_realref (m0), arg0_real, MPFR_RNDN);
377 27423 : mpfr_from_real (mpc_imagref (m0), arg0_imag, MPFR_RNDN);
378 27423 : mpfr_from_real (mpc_realref (m1), arg1_real, MPFR_RNDN);
379 27423 : mpfr_from_real (mpc_imagref (m1), arg1_imag, MPFR_RNDN);
380 27423 : mpfr_clear_flags ();
381 27423 : bool inexact = func (m0, m0, m1, crnd);
382 27423 : bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
383 27423 : mpc_clear (m0);
384 27423 : mpc_clear (m1);
385 :
386 27423 : return ok;
387 : }
388 :
389 : /* Try to evaluate:
390 :
391 : *RESULT = logb (*ARG)
392 :
393 : in format FORMAT. Return true on success. */
394 :
395 : static bool
396 4463 : fold_const_logb (real_value *result, const real_value *arg,
397 : const real_format *format)
398 : {
399 4463 : switch (arg->cl)
400 : {
401 106 : case rvc_nan:
402 : /* If arg is +-NaN, then return it. */
403 106 : *result = *arg;
404 106 : return true;
405 :
406 116 : case rvc_inf:
407 : /* If arg is +-Inf, then return +Inf. */
408 116 : *result = *arg;
409 116 : result->sign = 0;
410 116 : return true;
411 :
412 : case rvc_zero:
413 : /* Zero may set errno and/or raise an exception. */
414 : return false;
415 :
416 1670 : case rvc_normal:
417 : /* For normal numbers, proceed iff radix == 2. In GCC,
418 : normalized significands are in the range [0.5, 1.0). We
419 : want the exponent as if they were [1.0, 2.0) so get the
420 : exponent and subtract 1. */
421 1670 : if (format->b == 2)
422 : {
423 1670 : real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED);
424 1670 : return true;
425 : }
426 : return false;
427 : }
428 : }
429 :
430 : /* Try to evaluate:
431 :
432 : *RESULT = significand (*ARG)
433 :
434 : in format FORMAT. Return true on success. */
435 :
436 : static bool
437 960 : fold_const_significand (real_value *result, const real_value *arg,
438 : const real_format *format)
439 : {
440 0 : switch (arg->cl)
441 : {
442 288 : case rvc_zero:
443 288 : case rvc_nan:
444 288 : case rvc_inf:
445 : /* If arg is +-0, +-Inf or +-NaN, then return it. */
446 288 : *result = *arg;
447 288 : return true;
448 :
449 672 : case rvc_normal:
450 : /* For normal numbers, proceed iff radix == 2. */
451 672 : if (format->b == 2)
452 : {
453 672 : *result = *arg;
454 : /* In GCC, normalized significands are in the range [0.5, 1.0).
455 : We want them to be [1.0, 2.0) so set the exponent to 1. */
456 672 : SET_REAL_EXP (result, 1);
457 672 : return true;
458 : }
459 : return false;
460 : }
461 : }
462 :
463 : /* Try to evaluate:
464 :
465 : *RESULT = f (*ARG)
466 :
467 : where FORMAT is the format of *ARG and PRECISION is the number of
468 : significant bits in the result. Return true on success. */
469 :
470 : static bool
471 1640 : fold_const_conversion (wide_int *result,
472 : void (*fn) (real_value *, format_helper,
473 : const real_value *),
474 : const real_value *arg, unsigned int precision,
475 : const real_format *format)
476 : {
477 1640 : if (!real_isfinite (arg))
478 : return false;
479 :
480 1640 : real_value rounded;
481 1640 : fn (&rounded, format, arg);
482 :
483 1640 : bool fail = false;
484 1640 : *result = real_to_integer (&rounded, &fail, precision);
485 1640 : return !fail;
486 : }
487 :
488 : /* Try to evaluate:
489 :
490 : *RESULT = pow (*ARG0, *ARG1)
491 :
492 : in format FORMAT. Return true on success. */
493 :
494 : static bool
495 122609 : fold_const_pow (real_value *result, const real_value *arg0,
496 : const real_value *arg1, const real_format *format)
497 : {
498 122609 : if (flag_signaling_nans
499 122609 : && (REAL_VALUE_ISSIGNALING_NAN (*arg0)
500 0 : || REAL_VALUE_ISSIGNALING_NAN (*arg1)))
501 0 : return false;
502 :
503 122609 : if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
504 : {
505 112301 : if (flag_errno_math)
506 111938 : switch (result->cl)
507 : {
508 : case rvc_inf:
509 : case rvc_nan:
510 : return false;
511 0 : case rvc_zero:
512 0 : return arg0->cl == rvc_zero;
513 : default:
514 : break;
515 : }
516 : return true;
517 : }
518 :
519 : return false;
520 : }
521 :
522 : /* Try to evaluate:
523 :
524 : *RESULT = nextafter (*ARG0, *ARG1)
525 :
526 : or
527 :
528 : *RESULT = nexttoward (*ARG0, *ARG1)
529 :
530 : in format FORMAT. Return true on success. */
531 :
532 : static bool
533 10842 : fold_const_nextafter (real_value *result, const real_value *arg0,
534 : const real_value *arg1, const real_format *format)
535 : {
536 10842 : if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
537 10842 : || REAL_VALUE_ISSIGNALING_NAN (*arg1))
538 0 : return false;
539 :
540 : /* Don't handle composite modes, nor decimal, nor modes without
541 : inf or denorm at least for now. */
542 10842 : if (format->pnan < format->p
543 10842 : || format->b == 10
544 10842 : || !format->has_inf
545 10842 : || !format->has_denorm)
546 : return false;
547 :
548 16622 : if (real_nextafter (result, format, arg0, arg1)
549 : /* If raising underflow or overflow and setting errno to ERANGE,
550 : fail if we care about those side-effects. */
551 10842 : && (flag_trapping_math || flag_errno_math))
552 5780 : return false;
553 : /* Similarly for nextafter (0, 1) raising underflow. */
554 5062 : else if (flag_trapping_math
555 4555 : && arg0->cl == rvc_zero
556 3938 : && result->cl != rvc_zero)
557 : return false;
558 :
559 1304 : real_convert (result, format, result);
560 :
561 1304 : return true;
562 : }
563 :
564 : /* Try to evaluate:
565 :
566 : *RESULT = ldexp (*ARG0, ARG1)
567 :
568 : in format FORMAT. Return true on success. */
569 :
570 : static bool
571 25262 : fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
572 : const wide_int_ref &arg1,
573 : const real_format *format)
574 : {
575 : /* Bound the maximum adjustment to twice the range of the
576 : mode's valid exponents. Use abs to ensure the range is
577 : positive as a sanity check. */
578 25262 : int max_exp_adj = 2 * labs (format->emax - format->emin);
579 :
580 : /* The requested adjustment must be inside this range. This
581 : is a preliminary cap to avoid things like overflow, we
582 : may still fail to compute the result for other reasons. */
583 42738 : if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
584 15440 : return false;
585 :
586 : /* Don't perform operation if we honor signaling NaNs and
587 : operand is a signaling NaN. */
588 9822 : if (!flag_unsafe_math_optimizations
589 9819 : && flag_signaling_nans
590 9942 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
591 : return false;
592 :
593 9822 : REAL_VALUE_TYPE initial_result;
594 9822 : real_ldexp (&initial_result, arg0, arg1.to_shwi ());
595 :
596 : /* Ensure we didn't overflow. */
597 9822 : if (real_isinf (&initial_result))
598 : return false;
599 :
600 : /* Only proceed if the target mode can hold the
601 : resulting value. */
602 9802 : *result = real_value_truncate (format, initial_result);
603 9802 : return real_equal (&initial_result, result);
604 : }
605 :
606 : /* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
607 : return type TYPE. QUIET is true if a quiet rather than signalling
608 : NaN is required. */
609 :
610 : static tree
611 380285 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
612 : {
613 380285 : REAL_VALUE_TYPE real;
614 380285 : const char *str = c_getstr (arg);
615 380285 : if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
616 379816 : return build_real (type, real);
617 : return NULL_TREE;
618 : }
619 :
620 : /* Fold a call to IFN_REDUC_<CODE> (ARG), returning a value of type TYPE. */
621 :
622 : static tree
623 2123 : fold_const_reduction (tree type, tree arg, tree_code code)
624 : {
625 2123 : unsigned HOST_WIDE_INT nelts;
626 2123 : if (TREE_CODE (arg) != VECTOR_CST
627 2123 : || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
628 0 : return NULL_TREE;
629 :
630 2123 : tree res = VECTOR_CST_ELT (arg, 0);
631 26514 : for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
632 : {
633 24391 : res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
634 24391 : if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
635 : return NULL_TREE;
636 : }
637 : return res;
638 : }
639 :
640 : /* Fold a call to IFN_VEC_CONVERT (ARG) returning TYPE. */
641 :
642 : static tree
643 2188 : fold_const_vec_convert (tree ret_type, tree arg)
644 : {
645 2188 : enum tree_code code = NOP_EXPR;
646 2188 : tree arg_type = TREE_TYPE (arg);
647 2188 : if (TREE_CODE (arg) != VECTOR_CST)
648 : return NULL_TREE;
649 :
650 2188 : gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
651 :
652 4376 : if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
653 4301 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
654 : code = FIX_TRUNC_EXPR;
655 4262 : else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
656 4262 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
657 : code = FLOAT_EXPR;
658 :
659 : /* We can't handle steps directly when extending, since the
660 : values need to wrap at the original precision first. */
661 2188 : bool step_ok_p
662 4376 : = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
663 2113 : && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
664 4244 : && (TYPE_PRECISION (TREE_TYPE (ret_type))
665 2056 : <= TYPE_PRECISION (TREE_TYPE (arg_type))));
666 2188 : tree_vector_builder elts;
667 2188 : if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
668 : return NULL_TREE;
669 :
670 2188 : unsigned int count = elts.encoded_nelts ();
671 6491 : for (unsigned int i = 0; i < count; ++i)
672 : {
673 4309 : tree elt = fold_unary (code, TREE_TYPE (ret_type),
674 : VECTOR_CST_ELT (arg, i));
675 4309 : if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
676 6 : return NULL_TREE;
677 4303 : elts.quick_push (elt);
678 : }
679 :
680 2182 : return elts.build ();
681 2188 : }
682 :
683 : /* Try to evaluate:
684 :
685 : IFN_WHILE_ULT (ARG0, ARG1, (TYPE) { ... })
686 :
687 : Return the value on success and null on failure. */
688 :
689 : static tree
690 0 : fold_while_ult (tree type, poly_uint64 arg0, poly_uint64 arg1)
691 : {
692 0 : if (known_ge (arg0, arg1))
693 0 : return build_zero_cst (type);
694 :
695 0 : if (maybe_ge (arg0, arg1))
696 : return NULL_TREE;
697 :
698 0 : poly_uint64 diff = arg1 - arg0;
699 0 : poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
700 0 : if (known_ge (diff, nelts))
701 0 : return build_all_ones_cst (type);
702 :
703 0 : unsigned HOST_WIDE_INT const_diff;
704 0 : if (known_le (diff, nelts) && diff.is_constant (&const_diff))
705 : {
706 0 : tree minus_one = build_minus_one_cst (TREE_TYPE (type));
707 0 : tree zero = build_zero_cst (TREE_TYPE (type));
708 0 : return build_vector_a_then_b (type, const_diff, minus_one, zero);
709 : }
710 : return NULL_TREE;
711 : }
712 :
713 : /* Try to evaluate:
714 :
715 : *RESULT = FN (*ARG)
716 :
717 : in format FORMAT. Return true on success. */
718 :
719 : static bool
720 159200 : fold_const_call_ss (real_value *result, combined_fn fn,
721 : const real_value *arg, const real_format *format)
722 : {
723 159200 : switch (fn)
724 : {
725 22285 : CASE_CFN_SQRT:
726 22285 : CASE_CFN_SQRT_FN:
727 22285 : return (real_compare (GE_EXPR, arg, &dconst0)
728 22285 : && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
729 :
730 512 : CASE_CFN_CBRT:
731 512 : CASE_CFN_CBRT_FN:
732 512 : return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
733 :
734 1976 : CASE_CFN_ASIN:
735 1976 : CASE_CFN_ASIN_FN:
736 1976 : return (real_compare (GE_EXPR, arg, &dconstm1)
737 1202 : && real_compare (LE_EXPR, arg, &dconst1)
738 2396 : && do_mpfr_arg1 (result, mpfr_asin, arg, format));
739 :
740 2027 : CASE_CFN_ACOS:
741 2027 : CASE_CFN_ACOS_FN:
742 2027 : return (real_compare (GE_EXPR, arg, &dconstm1)
743 1253 : && real_compare (LE_EXPR, arg, &dconst1)
744 2506 : && do_mpfr_arg1 (result, mpfr_acos, arg, format));
745 :
746 552 : CASE_CFN_ATAN:
747 552 : CASE_CFN_ATAN_FN:
748 552 : return do_mpfr_arg1 (result, mpfr_atan, arg, format);
749 :
750 312 : CASE_CFN_ASINH:
751 312 : CASE_CFN_ASINH_FN:
752 312 : return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
753 :
754 1451 : CASE_CFN_ACOSH:
755 1451 : CASE_CFN_ACOSH_FN:
756 1451 : return (real_compare (GE_EXPR, arg, &dconst1)
757 1451 : && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
758 :
759 1906 : CASE_CFN_ATANH:
760 1906 : CASE_CFN_ATANH_FN:
761 1906 : return (real_compare (GE_EXPR, arg, &dconstm1)
762 1906 : && real_compare (LE_EXPR, arg, &dconst1)
763 3812 : && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
764 :
765 1010 : CASE_CFN_SIN:
766 1010 : CASE_CFN_SIN_FN:
767 1010 : return do_mpfr_arg1 (result, mpfr_sin, arg, format);
768 :
769 846 : CASE_CFN_COS:
770 846 : CASE_CFN_COS_FN:
771 846 : return do_mpfr_arg1 (result, mpfr_cos, arg, format);
772 :
773 553 : CASE_CFN_TAN:
774 553 : CASE_CFN_TAN_FN:
775 553 : return do_mpfr_arg1 (result, mpfr_tan, arg, format);
776 :
777 394 : CASE_CFN_SINH:
778 394 : CASE_CFN_SINH_FN:
779 394 : return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
780 :
781 399 : CASE_CFN_COSH:
782 399 : CASE_CFN_COSH_FN:
783 399 : return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
784 :
785 349 : CASE_CFN_TANH:
786 349 : CASE_CFN_TANH_FN:
787 349 : return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
788 :
789 : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
790 55 : CASE_CFN_ACOSPI:
791 55 : CASE_CFN_ACOSPI_FN:
792 55 : return (real_compare (GE_EXPR, arg, &dconstm1)
793 55 : && real_compare (LE_EXPR, arg, &dconst1)
794 110 : && do_mpfr_arg1 (result, mpfr_acospi, arg, format));
795 :
796 60 : CASE_CFN_ASINPI:
797 60 : CASE_CFN_ASINPI_FN:
798 60 : return (real_compare (GE_EXPR, arg, &dconstm1)
799 60 : && real_compare (LE_EXPR, arg, &dconst1)
800 120 : && do_mpfr_arg1 (result, mpfr_asinpi, arg, format));
801 :
802 36 : CASE_CFN_ATANPI:
803 36 : CASE_CFN_ATANPI_FN:
804 36 : return do_mpfr_arg1 (result, mpfr_atanpi, arg, format);
805 :
806 60 : CASE_CFN_COSPI:
807 60 : CASE_CFN_COSPI_FN:
808 60 : return do_mpfr_arg1 (result, mpfr_cospi, arg, format);
809 :
810 60 : CASE_CFN_SINPI:
811 60 : CASE_CFN_SINPI_FN:
812 60 : return do_mpfr_arg1 (result, mpfr_sinpi, arg, format);
813 :
814 72 : CASE_CFN_TANPI:
815 72 : CASE_CFN_TANPI_FN:
816 72 : return do_mpfr_arg1 (result, mpfr_tanpi, arg, format);
817 : #endif
818 :
819 511 : CASE_CFN_ERF:
820 511 : CASE_CFN_ERF_FN:
821 511 : return do_mpfr_arg1 (result, mpfr_erf, arg, format);
822 :
823 554 : CASE_CFN_ERFC:
824 554 : CASE_CFN_ERFC_FN:
825 554 : return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
826 :
827 4899 : CASE_CFN_TGAMMA:
828 4899 : CASE_CFN_TGAMMA_FN:
829 4899 : return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
830 :
831 868 : CASE_CFN_EXP:
832 868 : CASE_CFN_EXP_FN:
833 868 : return do_mpfr_arg1 (result, mpfr_exp, arg, format);
834 :
835 10784 : CASE_CFN_EXP2:
836 10784 : CASE_CFN_EXP2_FN:
837 10784 : return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
838 :
839 698 : CASE_CFN_EXP10:
840 698 : CASE_CFN_POW10:
841 698 : return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
842 :
843 327 : CASE_CFN_EXPM1:
844 327 : CASE_CFN_EXPM1_FN:
845 327 : return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
846 :
847 59073 : CASE_CFN_LOG:
848 59073 : CASE_CFN_LOG_FN:
849 59073 : return (real_compare (GT_EXPR, arg, &dconst0)
850 59073 : && do_mpfr_arg1 (result, mpfr_log, arg, format));
851 :
852 3136 : CASE_CFN_LOG2:
853 3136 : CASE_CFN_LOG2_FN:
854 3136 : return (real_compare (GT_EXPR, arg, &dconst0)
855 3136 : && do_mpfr_arg1 (result, mpfr_log2, arg, format));
856 :
857 3171 : CASE_CFN_LOG10:
858 3171 : CASE_CFN_LOG10_FN:
859 3171 : return (real_compare (GT_EXPR, arg, &dconst0)
860 3171 : && do_mpfr_arg1 (result, mpfr_log10, arg, format));
861 :
862 1921 : CASE_CFN_LOG1P:
863 1921 : CASE_CFN_LOG1P_FN:
864 1921 : return (real_compare (GT_EXPR, arg, &dconstm1)
865 1921 : && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
866 :
867 221 : CASE_CFN_J0:
868 221 : return do_mpfr_arg1 (result, mpfr_j0, arg, format);
869 :
870 221 : CASE_CFN_J1:
871 221 : return do_mpfr_arg1 (result, mpfr_j1, arg, format);
872 :
873 2447 : CASE_CFN_Y0:
874 2447 : return (real_compare (GT_EXPR, arg, &dconst0)
875 2447 : && do_mpfr_arg1 (result, mpfr_y0, arg, format));
876 :
877 2447 : CASE_CFN_Y1:
878 2447 : return (real_compare (GT_EXPR, arg, &dconst0)
879 2447 : && do_mpfr_arg1 (result, mpfr_y1, arg, format));
880 :
881 359 : CASE_CFN_FLOOR:
882 359 : CASE_CFN_FLOOR_FN:
883 359 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
884 : {
885 359 : real_floor (result, format, arg);
886 359 : return true;
887 : }
888 : return false;
889 :
890 321 : CASE_CFN_CEIL:
891 321 : CASE_CFN_CEIL_FN:
892 321 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
893 : {
894 321 : real_ceil (result, format, arg);
895 321 : return true;
896 : }
897 : return false;
898 :
899 532 : CASE_CFN_TRUNC:
900 532 : CASE_CFN_TRUNC_FN:
901 532 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
902 : {
903 532 : real_trunc (result, format, arg);
904 532 : return true;
905 : }
906 : return false;
907 :
908 264 : CASE_CFN_ROUND:
909 264 : CASE_CFN_ROUND_FN:
910 264 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
911 : {
912 264 : real_round (result, format, arg);
913 264 : return true;
914 : }
915 : return false;
916 :
917 189 : CASE_CFN_ROUNDEVEN:
918 189 : CASE_CFN_ROUNDEVEN_FN:
919 189 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
920 : {
921 189 : real_roundeven (result, format, arg);
922 189 : return true;
923 : }
924 : return false;
925 :
926 4463 : CASE_CFN_LOGB:
927 4463 : CASE_CFN_LOGB_FN:
928 4463 : return fold_const_logb (result, arg, format);
929 :
930 960 : CASE_CFN_SIGNIFICAND:
931 960 : return fold_const_significand (result, arg, format);
932 :
933 : default:
934 : return false;
935 : }
936 : }
937 :
938 : /* Try to evaluate:
939 :
940 : *RESULT = FN (*ARG)
941 :
942 : where FORMAT is the format of ARG and PRECISION is the number of
943 : significant bits in the result. Return true on success. */
944 :
945 : static bool
946 17473 : fold_const_call_ss (wide_int *result, combined_fn fn,
947 : const real_value *arg, unsigned int precision,
948 : const real_format *format)
949 : {
950 17473 : switch (fn)
951 : {
952 1871 : CASE_CFN_SIGNBIT:
953 1871 : if (real_isneg (arg))
954 1004 : *result = wi::one (precision);
955 : else
956 867 : *result = wi::zero (precision);
957 : return true;
958 :
959 6465 : CASE_CFN_ILOGB:
960 6465 : CASE_CFN_ILOGB_FN:
961 : /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
962 : Proceed iff radix == 2. In GCC, normalized significands are in
963 : the range [0.5, 1.0). We want the exponent as if they were
964 : [1.0, 2.0) so get the exponent and subtract 1. */
965 6465 : if (arg->cl == rvc_normal && format->b == 2)
966 : {
967 834 : *result = wi::shwi (REAL_EXP (arg) - 1, precision);
968 834 : return true;
969 : }
970 : return false;
971 :
972 378 : CASE_CFN_ICEIL:
973 378 : CASE_CFN_LCEIL:
974 378 : CASE_CFN_LLCEIL:
975 378 : return fold_const_conversion (result, real_ceil, arg,
976 378 : precision, format);
977 :
978 378 : CASE_CFN_LFLOOR:
979 378 : CASE_CFN_IFLOOR:
980 378 : CASE_CFN_LLFLOOR:
981 378 : return fold_const_conversion (result, real_floor, arg,
982 378 : precision, format);
983 :
984 884 : CASE_CFN_IROUND:
985 884 : CASE_CFN_LROUND:
986 884 : CASE_CFN_LROUND_FN:
987 884 : CASE_CFN_LLROUND:
988 884 : CASE_CFN_LLROUND_FN:
989 884 : return fold_const_conversion (result, real_round, arg,
990 884 : precision, format);
991 :
992 : CASE_CFN_IRINT:
993 : CASE_CFN_LRINT:
994 : CASE_CFN_LRINT_FN:
995 : CASE_CFN_LLRINT:
996 : CASE_CFN_LLRINT_FN:
997 : /* Not yet folded to a constant. */
998 : return false;
999 :
1000 1500 : CASE_CFN_FINITE:
1001 1500 : case CFN_BUILT_IN_FINITED32:
1002 1500 : case CFN_BUILT_IN_FINITED64:
1003 1500 : case CFN_BUILT_IN_FINITED128:
1004 1500 : case CFN_BUILT_IN_ISFINITE:
1005 1534 : *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
1006 1500 : return true;
1007 :
1008 3664 : case CFN_BUILT_IN_ISSIGNALING:
1009 7175 : *result = wi::shwi (real_issignaling_nan (arg) ? 1 : 0, precision);
1010 3664 : return true;
1011 :
1012 204 : CASE_CFN_ISINF:
1013 204 : case CFN_BUILT_IN_ISINFD32:
1014 204 : case CFN_BUILT_IN_ISINFD64:
1015 204 : case CFN_BUILT_IN_ISINFD128:
1016 204 : if (real_isinf (arg))
1017 295 : *result = wi::shwi (arg->sign ? -1 : 1, precision);
1018 : else
1019 40 : *result = wi::shwi (0, precision);
1020 : return true;
1021 :
1022 1341 : CASE_CFN_ISNAN:
1023 1341 : case CFN_BUILT_IN_ISNAND32:
1024 1341 : case CFN_BUILT_IN_ISNAND64:
1025 1341 : case CFN_BUILT_IN_ISNAND128:
1026 2456 : *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
1027 1341 : return true;
1028 :
1029 : default:
1030 : return false;
1031 : }
1032 : }
1033 :
1034 : /* Try to evaluate:
1035 :
1036 : *RESULT = FN (ARG)
1037 :
1038 : where ARG_TYPE is the type of ARG and PRECISION is the number of bits
1039 : in the result. Return true on success. */
1040 :
1041 : static bool
1042 4989422 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1043 : unsigned int precision, tree arg_type)
1044 : {
1045 4989422 : switch (fn)
1046 : {
1047 491 : CASE_CFN_FFS:
1048 491 : case CFN_BUILT_IN_FFSG:
1049 491 : *result = wi::shwi (wi::ffs (arg), precision);
1050 491 : return true;
1051 :
1052 2154 : CASE_CFN_CLZ:
1053 2154 : case CFN_BUILT_IN_CLZG:
1054 2154 : {
1055 2154 : int tmp;
1056 2154 : if (wi::ne_p (arg, 0))
1057 1816 : tmp = wi::clz (arg);
1058 338 : else if (BITINT_TYPE_P (arg_type))
1059 9 : tmp = TYPE_PRECISION (arg_type);
1060 658 : else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1061 : tmp))
1062 329 : tmp = TYPE_PRECISION (arg_type);
1063 2154 : *result = wi::shwi (tmp, precision);
1064 2154 : return true;
1065 : }
1066 :
1067 1148 : CASE_CFN_CTZ:
1068 1148 : case CFN_BUILT_IN_CTZG:
1069 1148 : {
1070 1148 : int tmp;
1071 1148 : if (wi::ne_p (arg, 0))
1072 904 : tmp = wi::ctz (arg);
1073 244 : else if (BITINT_TYPE_P (arg_type))
1074 0 : tmp = TYPE_PRECISION (arg_type);
1075 488 : else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1076 : tmp))
1077 244 : tmp = TYPE_PRECISION (arg_type);
1078 1148 : *result = wi::shwi (tmp, precision);
1079 1148 : return true;
1080 : }
1081 :
1082 412 : CASE_CFN_CLRSB:
1083 412 : case CFN_BUILT_IN_CLRSBG:
1084 412 : *result = wi::shwi (wi::clrsb (arg), precision);
1085 412 : return true;
1086 :
1087 39204 : CASE_CFN_POPCOUNT:
1088 39204 : case CFN_BUILT_IN_POPCOUNTG:
1089 39204 : *result = wi::shwi (wi::popcount (arg), precision);
1090 39204 : return true;
1091 :
1092 545 : CASE_CFN_PARITY:
1093 545 : case CFN_BUILT_IN_PARITYG:
1094 545 : *result = wi::shwi (wi::parity (arg), precision);
1095 545 : return true;
1096 :
1097 738 : CASE_CFN_BSWAP:
1098 1476 : *result = wi::bswap (wide_int::from (arg, precision,
1099 1476 : TYPE_SIGN (arg_type)));
1100 738 : return true;
1101 :
1102 53 : CASE_CFN_BITREVERSE:
1103 106 : *result = wi::bitreverse (wide_int::from (arg, precision,
1104 106 : TYPE_SIGN (arg_type)));
1105 53 : return true;
1106 :
1107 : default:
1108 : return false;
1109 : }
1110 : }
1111 :
1112 : /* Try to evaluate:
1113 :
1114 : RESULT = FN (*ARG)
1115 :
1116 : where FORMAT is the format of ARG and of the real and imaginary parts
1117 : of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
1118 : true on success. */
1119 :
1120 : static bool
1121 146 : fold_const_call_cs (real_value *result_real, real_value *result_imag,
1122 : combined_fn fn, const real_value *arg,
1123 : const real_format *format)
1124 : {
1125 0 : switch (fn)
1126 : {
1127 146 : CASE_CFN_CEXPI:
1128 : /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1129 146 : return do_mpfr_sincos (result_imag, result_real, arg, format);
1130 :
1131 : default:
1132 : return false;
1133 : }
1134 : }
1135 :
1136 : /* Try to evaluate:
1137 :
1138 : *RESULT = fn (ARG)
1139 :
1140 : where FORMAT is the format of RESULT and of the real and imaginary parts
1141 : of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
1142 : success. */
1143 :
1144 : static bool
1145 2292 : fold_const_call_sc (real_value *result, combined_fn fn,
1146 : const real_value *arg_real, const real_value *arg_imag,
1147 : const real_format *format)
1148 : {
1149 0 : switch (fn)
1150 : {
1151 1156 : CASE_CFN_CABS:
1152 1156 : CASE_CFN_CABS_FN:
1153 1156 : return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1154 :
1155 : default:
1156 : return false;
1157 : }
1158 : }
1159 :
1160 : /* Try to evaluate:
1161 :
1162 : RESULT = fn (ARG)
1163 :
1164 : where FORMAT is the format of the real and imaginary parts of RESULT
1165 : (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1166 : Return true on success. */
1167 :
1168 : static bool
1169 39622 : fold_const_call_cc (real_value *result_real, real_value *result_imag,
1170 : combined_fn fn, const real_value *arg_real,
1171 : const real_value *arg_imag, const real_format *format)
1172 : {
1173 39622 : switch (fn)
1174 : {
1175 686 : CASE_CFN_CCOS:
1176 686 : CASE_CFN_CCOS_FN:
1177 686 : return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1178 686 : arg_real, arg_imag, format);
1179 :
1180 676 : CASE_CFN_CCOSH:
1181 676 : CASE_CFN_CCOSH_FN:
1182 676 : return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1183 676 : arg_real, arg_imag, format);
1184 :
1185 683 : CASE_CFN_CPROJ:
1186 683 : CASE_CFN_CPROJ_FN:
1187 683 : if (real_isinf (arg_real) || real_isinf (arg_imag))
1188 : {
1189 436 : *result_real = dconstinf;
1190 436 : *result_imag = dconst0;
1191 436 : result_imag->sign = arg_imag->sign;
1192 : }
1193 : else
1194 : {
1195 247 : *result_real = *arg_real;
1196 247 : *result_imag = *arg_imag;
1197 : }
1198 : return true;
1199 :
1200 701 : CASE_CFN_CSIN:
1201 701 : CASE_CFN_CSIN_FN:
1202 701 : return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1203 701 : arg_real, arg_imag, format);
1204 :
1205 676 : CASE_CFN_CSINH:
1206 676 : CASE_CFN_CSINH_FN:
1207 676 : return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1208 676 : arg_real, arg_imag, format);
1209 :
1210 698 : CASE_CFN_CTAN:
1211 698 : CASE_CFN_CTAN_FN:
1212 698 : return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1213 698 : arg_real, arg_imag, format);
1214 :
1215 676 : CASE_CFN_CTANH:
1216 676 : CASE_CFN_CTANH_FN:
1217 676 : return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1218 676 : arg_real, arg_imag, format);
1219 :
1220 777 : CASE_CFN_CLOG:
1221 777 : CASE_CFN_CLOG_FN:
1222 777 : return do_mpc_arg1 (result_real, result_imag, mpc_log,
1223 777 : arg_real, arg_imag, format);
1224 :
1225 3053 : CASE_CFN_CSQRT:
1226 3053 : CASE_CFN_CSQRT_FN:
1227 3053 : return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1228 3053 : arg_real, arg_imag, format);
1229 :
1230 679 : CASE_CFN_CASIN:
1231 679 : CASE_CFN_CASIN_FN:
1232 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1233 679 : arg_real, arg_imag, format);
1234 :
1235 728 : CASE_CFN_CACOS:
1236 728 : CASE_CFN_CACOS_FN:
1237 728 : return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1238 728 : arg_real, arg_imag, format);
1239 :
1240 679 : CASE_CFN_CATAN:
1241 679 : CASE_CFN_CATAN_FN:
1242 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1243 679 : arg_real, arg_imag, format);
1244 :
1245 679 : CASE_CFN_CASINH:
1246 679 : CASE_CFN_CASINH_FN:
1247 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1248 679 : arg_real, arg_imag, format);
1249 :
1250 745 : CASE_CFN_CACOSH:
1251 745 : CASE_CFN_CACOSH_FN:
1252 745 : return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1253 745 : arg_real, arg_imag, format);
1254 :
1255 679 : CASE_CFN_CATANH:
1256 679 : CASE_CFN_CATANH_FN:
1257 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1258 679 : arg_real, arg_imag, format);
1259 :
1260 1583 : CASE_CFN_CEXP:
1261 1583 : CASE_CFN_CEXP_FN:
1262 1583 : return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1263 1583 : arg_real, arg_imag, format);
1264 :
1265 : default:
1266 : return false;
1267 : }
1268 : }
1269 :
1270 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1271 : where the arguments and result are numerical. */
1272 :
1273 : static tree
1274 16328378 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
1275 : {
1276 16328378 : machine_mode mode = TYPE_MODE (type);
1277 16328378 : machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1278 :
1279 16328378 : if (integer_cst_p (arg))
1280 : {
1281 5104230 : if (SCALAR_INT_MODE_P (mode))
1282 : {
1283 4989422 : wide_int result;
1284 4989422 : if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1285 4989422 : TYPE_PRECISION (type), TREE_TYPE (arg)))
1286 44745 : return wide_int_to_tree (type, result);
1287 4989422 : }
1288 5059485 : return NULL_TREE;
1289 : }
1290 :
1291 11224148 : if (real_cst_p (arg))
1292 : {
1293 176822 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1294 176822 : if (mode == arg_mode)
1295 : {
1296 : /* real -> real. */
1297 159200 : REAL_VALUE_TYPE result;
1298 159200 : if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1299 159200 : REAL_MODE_FORMAT (mode)))
1300 97947 : return build_real (type, result);
1301 : }
1302 17622 : else if (COMPLEX_MODE_P (mode)
1303 17768 : && GET_MODE_INNER (mode) == arg_mode)
1304 : {
1305 : /* real -> complex real. */
1306 146 : REAL_VALUE_TYPE result_real, result_imag;
1307 292 : if (fold_const_call_cs (&result_real, &result_imag, fn,
1308 146 : TREE_REAL_CST_PTR (arg),
1309 146 : REAL_MODE_FORMAT (arg_mode)))
1310 292 : return build_complex (type,
1311 146 : build_real (TREE_TYPE (type), result_real),
1312 292 : build_real (TREE_TYPE (type), result_imag));
1313 : }
1314 17476 : else if (INTEGRAL_TYPE_P (type))
1315 : {
1316 : /* real -> int. */
1317 17473 : wide_int result;
1318 17473 : if (fold_const_call_ss (&result, fn,
1319 17473 : TREE_REAL_CST_PTR (arg),
1320 17473 : TYPE_PRECISION (type),
1321 17473 : REAL_MODE_FORMAT (arg_mode)))
1322 11054 : return wide_int_to_tree (type, result);
1323 17473 : }
1324 67675 : return NULL_TREE;
1325 : }
1326 :
1327 11047326 : if (complex_cst_p (arg))
1328 : {
1329 41914 : gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1330 41914 : machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1331 41914 : tree argr = TREE_REALPART (arg);
1332 41914 : tree argi = TREE_IMAGPART (arg);
1333 41914 : if (mode == arg_mode
1334 39622 : && real_cst_p (argr)
1335 81536 : && real_cst_p (argi))
1336 : {
1337 : /* complex real -> complex real. */
1338 39622 : REAL_VALUE_TYPE result_real, result_imag;
1339 79244 : if (fold_const_call_cc (&result_real, &result_imag, fn,
1340 39622 : TREE_REAL_CST_PTR (argr),
1341 39622 : TREE_REAL_CST_PTR (argi),
1342 39622 : REAL_MODE_FORMAT (inner_mode)))
1343 20972 : return build_complex (type,
1344 10486 : build_real (TREE_TYPE (type), result_real),
1345 20972 : build_real (TREE_TYPE (type), result_imag));
1346 : }
1347 31428 : if (mode == inner_mode
1348 2292 : && real_cst_p (argr)
1349 33720 : && real_cst_p (argi))
1350 : {
1351 : /* complex real -> real. */
1352 2292 : REAL_VALUE_TYPE result;
1353 4584 : if (fold_const_call_sc (&result, fn,
1354 2292 : TREE_REAL_CST_PTR (argr),
1355 2292 : TREE_REAL_CST_PTR (argi),
1356 2292 : REAL_MODE_FORMAT (inner_mode)))
1357 1156 : return build_real (type, result);
1358 : }
1359 30272 : return NULL_TREE;
1360 : }
1361 :
1362 : return NULL_TREE;
1363 : }
1364 :
1365 : /* Try to fold FN (ARG) to a constant. Return the constant on success,
1366 : otherwise return null. TYPE is the type of the return value. */
1367 :
1368 : tree
1369 17234858 : fold_const_call (combined_fn fn, tree type, tree arg)
1370 : {
1371 17234858 : switch (fn)
1372 : {
1373 521884 : case CFN_BUILT_IN_STRLEN:
1374 521884 : if (const char *str = c_getstr (arg))
1375 79643 : return build_int_cst (type, strlen (str));
1376 : return NULL_TREE;
1377 :
1378 220388 : CASE_CFN_NAN:
1379 220388 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1380 220388 : case CFN_BUILT_IN_NAND32:
1381 220388 : case CFN_BUILT_IN_NAND64:
1382 220388 : case CFN_BUILT_IN_NAND128:
1383 220388 : case CFN_BUILT_IN_NAND64X:
1384 220388 : return fold_const_builtin_nan (type, arg, true);
1385 :
1386 159897 : CASE_CFN_NANS:
1387 159897 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1388 159897 : case CFN_BUILT_IN_NANSF16B:
1389 159897 : case CFN_BUILT_IN_NANSD32:
1390 159897 : case CFN_BUILT_IN_NANSD64:
1391 159897 : case CFN_BUILT_IN_NANSD128:
1392 159897 : case CFN_BUILT_IN_NANSD64X:
1393 159897 : return fold_const_builtin_nan (type, arg, false);
1394 :
1395 1718 : case CFN_REDUC_PLUS:
1396 1718 : return fold_const_reduction (type, arg, PLUS_EXPR);
1397 :
1398 47 : case CFN_REDUC_MAX:
1399 47 : return fold_const_reduction (type, arg, MAX_EXPR);
1400 :
1401 67 : case CFN_REDUC_MIN:
1402 67 : return fold_const_reduction (type, arg, MIN_EXPR);
1403 :
1404 34 : case CFN_REDUC_AND:
1405 34 : return fold_const_reduction (type, arg, BIT_AND_EXPR);
1406 :
1407 251 : case CFN_REDUC_IOR:
1408 251 : return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1409 :
1410 6 : case CFN_REDUC_XOR:
1411 6 : return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1412 :
1413 2188 : case CFN_VEC_CONVERT:
1414 2188 : return fold_const_vec_convert (type, arg);
1415 :
1416 16328378 : default:
1417 16328378 : return fold_const_call_1 (fn, type, arg);
1418 : }
1419 : }
1420 :
1421 : /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1422 : of type TYPE. */
1423 :
1424 : static tree
1425 0 : fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1426 : {
1427 0 : if (TREE_CODE (arg1) != VECTOR_CST)
1428 : return NULL_TREE;
1429 :
1430 0 : unsigned HOST_WIDE_INT nelts;
1431 0 : if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1432 : return NULL_TREE;
1433 :
1434 0 : for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1435 : {
1436 0 : arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1437 0 : if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1438 : return NULL_TREE;
1439 : }
1440 : return arg0;
1441 : }
1442 :
1443 : /* Fold a call to IFN_VEC_SHL_INSERT (ARG0, ARG1), returning a value
1444 : of type TYPE. */
1445 :
1446 : static tree
1447 0 : fold_const_vec_shl_insert (tree, tree arg0, tree arg1)
1448 : {
1449 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1450 : return NULL_TREE;
1451 :
1452 : /* vec_shl_insert ( dup(CST), CST) -> dup (CST). */
1453 0 : if (tree elem = uniform_vector_p (arg0))
1454 : {
1455 0 : if (operand_equal_p (elem, arg1))
1456 : return arg0;
1457 : }
1458 :
1459 : return NULL_TREE;
1460 : }
1461 :
1462 : /* Fold a call to IFN_VEC_EXTRACT (ARG0, ARG1), returning a value
1463 : of type TYPE.
1464 :
1465 : Right now this is only handling uniform vectors, so ARG1 is not
1466 : used. But it could be easily adjusted in the future to handle
1467 : non-uniform vectors by extracting the relevant element. */
1468 :
1469 : static tree
1470 0 : fold_const_vec_extract (tree, tree arg0, tree)
1471 : {
1472 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1473 : return NULL_TREE;
1474 :
1475 : /* vec_extract ( dup(CST), CST) -> dup (CST). */
1476 0 : if (tree elem = uniform_vector_p (arg0))
1477 : return elem;
1478 :
1479 : return NULL_TREE;
1480 : }
1481 :
1482 : /* Try to fold scalar integer IFN_SAT_ADD with operands OP0 and OP1. */
1483 :
1484 : static tree
1485 0 : fold_internal_fn_sat_add (tree type, tree op0, tree op1)
1486 : {
1487 0 : if (!INTEGRAL_NB_TYPE_P (type))
1488 : return NULL_TREE;
1489 :
1490 0 : if (TREE_CODE (op0) != INTEGER_CST
1491 0 : || TREE_CODE (op1) != INTEGER_CST)
1492 : return NULL_TREE;
1493 :
1494 0 : wi::overflow_type overflow;
1495 0 : unsigned int prec = TYPE_PRECISION (type);
1496 0 : wide_int result = wi::add (wi::to_wide (op0), wi::to_wide (op1),
1497 0 : TYPE_SIGN (type), &overflow);
1498 :
1499 0 : if (overflow != wi::OVF_NONE)
1500 : {
1501 0 : if (TYPE_UNSIGNED (type))
1502 0 : result = wi::max_value (prec, UNSIGNED);
1503 0 : else if (overflow == wi::OVF_OVERFLOW)
1504 0 : result = wi::max_value (prec, SIGNED);
1505 0 : else if (overflow == wi::OVF_UNDERFLOW)
1506 0 : result = wi::min_value (prec, SIGNED);
1507 : else
1508 : return NULL_TREE;
1509 : }
1510 :
1511 0 : return wide_int_to_tree (type, result);
1512 0 : }
1513 :
1514 : /* Try to evaluate:
1515 :
1516 : *RESULT = FN (*ARG0, *ARG1)
1517 :
1518 : in format FORMAT. Return true on success. */
1519 :
1520 : static bool
1521 219909 : fold_const_call_sss (real_value *result, combined_fn fn,
1522 : const real_value *arg0, const real_value *arg1,
1523 : const real_format *format)
1524 : {
1525 219909 : switch (fn)
1526 : {
1527 6774 : CASE_CFN_DREM:
1528 6774 : CASE_CFN_REMAINDER:
1529 6774 : CASE_CFN_REMAINDER_FN:
1530 6774 : return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1531 :
1532 983 : CASE_CFN_ATAN2:
1533 983 : CASE_CFN_ATAN2_FN:
1534 983 : return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1535 :
1536 : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
1537 84 : CASE_CFN_ATAN2PI:
1538 84 : CASE_CFN_ATAN2PI_FN:
1539 84 : return do_mpfr_arg2 (result, mpfr_atan2pi, arg0, arg1, format);
1540 : #endif
1541 :
1542 572 : CASE_CFN_FDIM:
1543 572 : CASE_CFN_FDIM_FN:
1544 572 : return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1545 :
1546 517 : CASE_CFN_FMOD:
1547 517 : CASE_CFN_FMOD_FN:
1548 517 : return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
1549 :
1550 578 : CASE_CFN_HYPOT:
1551 578 : CASE_CFN_HYPOT_FN:
1552 578 : return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1553 :
1554 70628 : CASE_CFN_COPYSIGN:
1555 70628 : CASE_CFN_COPYSIGN_FN:
1556 70628 : *result = *arg0;
1557 70628 : real_copysign (result, arg1);
1558 70628 : return true;
1559 :
1560 3161 : CASE_CFN_FMIN:
1561 3161 : CASE_CFN_FMIN_FN:
1562 3161 : return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1563 :
1564 3161 : CASE_CFN_FMAX:
1565 3161 : CASE_CFN_FMAX_FN:
1566 3161 : return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1567 :
1568 122609 : CASE_CFN_POW:
1569 122609 : CASE_CFN_POW_FN:
1570 122609 : return fold_const_pow (result, arg0, arg1, format);
1571 :
1572 10842 : CASE_CFN_NEXTAFTER:
1573 10842 : CASE_CFN_NEXTAFTER_FN:
1574 10842 : case CFN_BUILT_IN_NEXTAFTERF16B:
1575 10842 : CASE_CFN_NEXTTOWARD:
1576 10842 : return fold_const_nextafter (result, arg0, arg1, format);
1577 :
1578 : default:
1579 : return false;
1580 : }
1581 : }
1582 :
1583 : /* Try to evaluate:
1584 :
1585 : *RESULT = FN (*ARG0, ARG1)
1586 :
1587 : where FORMAT is the format of *RESULT and *ARG0. Return true on
1588 : success. */
1589 :
1590 : static bool
1591 25701 : fold_const_call_sss (real_value *result, combined_fn fn,
1592 : const real_value *arg0, const wide_int_ref &arg1,
1593 : const real_format *format)
1594 : {
1595 25701 : switch (fn)
1596 : {
1597 7912 : CASE_CFN_LDEXP:
1598 7912 : CASE_CFN_LDEXP_FN:
1599 7912 : return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1600 :
1601 17350 : CASE_CFN_SCALBN:
1602 17350 : CASE_CFN_SCALBN_FN:
1603 17350 : CASE_CFN_SCALBLN:
1604 17350 : CASE_CFN_SCALBLN_FN:
1605 17350 : return (format->b == 2
1606 17350 : && fold_const_builtin_load_exponent (result, arg0, arg1,
1607 : format));
1608 :
1609 430 : CASE_CFN_POWI:
1610 : /* Avoid the folding if flag_signaling_nans is on and
1611 : operand is a signaling NaN. */
1612 430 : if (!flag_unsafe_math_optimizations
1613 417 : && flag_signaling_nans
1614 445 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1615 : return false;
1616 :
1617 430 : real_powi (result, format, arg0, arg1.to_shwi ());
1618 430 : return true;
1619 :
1620 : default:
1621 : return false;
1622 : }
1623 : }
1624 :
1625 : /* Try to evaluate:
1626 :
1627 : *RESULT = FN (ARG0, *ARG1)
1628 :
1629 : where FORMAT is the format of *RESULT and *ARG1. Return true on
1630 : success. */
1631 :
1632 : static bool
1633 6434 : fold_const_call_sss (real_value *result, combined_fn fn,
1634 : const wide_int_ref &arg0, const real_value *arg1,
1635 : const real_format *format)
1636 : {
1637 6434 : switch (fn)
1638 : {
1639 1220 : CASE_CFN_JN:
1640 1220 : return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1641 :
1642 5205 : CASE_CFN_YN:
1643 5205 : return (real_compare (GT_EXPR, arg1, &dconst0)
1644 5205 : && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1645 :
1646 : default:
1647 : return false;
1648 : }
1649 : }
1650 :
1651 : /* Try to evaluate:
1652 :
1653 : *RESULT = FN (ARG0, ARG1)
1654 :
1655 : where ARG_TYPE is the type of ARG0 and PRECISION is the number of bits in
1656 : the result. Return true on success. */
1657 :
1658 : static bool
1659 333272 : fold_const_call_sss (wide_int *result, combined_fn fn,
1660 : const wide_int_ref &arg0, const wide_int_ref &arg1,
1661 : unsigned int precision, tree arg_type ATTRIBUTE_UNUSED)
1662 : {
1663 333272 : switch (fn)
1664 : {
1665 16086 : case CFN_CLZ:
1666 16086 : case CFN_BUILT_IN_CLZG:
1667 16086 : {
1668 16086 : int tmp;
1669 16086 : if (wi::ne_p (arg0, 0))
1670 15962 : tmp = wi::clz (arg0);
1671 : else
1672 124 : tmp = arg1.to_shwi ();
1673 16086 : *result = wi::shwi (tmp, precision);
1674 16086 : return true;
1675 : }
1676 :
1677 11507 : case CFN_CTZ:
1678 11507 : case CFN_BUILT_IN_CTZG:
1679 11507 : {
1680 11507 : int tmp;
1681 11507 : if (wi::ne_p (arg0, 0))
1682 11415 : tmp = wi::ctz (arg0);
1683 : else
1684 92 : tmp = arg1.to_shwi ();
1685 11507 : *result = wi::shwi (tmp, precision);
1686 11507 : return true;
1687 : }
1688 :
1689 : default:
1690 : return false;
1691 : }
1692 : }
1693 :
1694 : /* Try to evaluate:
1695 :
1696 : RESULT = fn (ARG0, ARG1)
1697 :
1698 : where FORMAT is the format of the real and imaginary parts of RESULT
1699 : (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1700 : and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1701 :
1702 : static bool
1703 32067 : fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1704 : combined_fn fn, const real_value *arg0_real,
1705 : const real_value *arg0_imag, const real_value *arg1_real,
1706 : const real_value *arg1_imag, const real_format *format)
1707 : {
1708 0 : switch (fn)
1709 : {
1710 32067 : CASE_CFN_CPOW:
1711 32067 : CASE_CFN_CPOW_FN:
1712 32067 : return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1713 0 : arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1714 :
1715 : default:
1716 : return false;
1717 : }
1718 : }
1719 :
1720 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1721 : where the arguments and result are numerical. */
1722 :
1723 : static tree
1724 14439187 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1725 : {
1726 14439187 : machine_mode mode = TYPE_MODE (type);
1727 14439187 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1728 14439187 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1729 :
1730 14439187 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1731 : {
1732 338943 : if (SCALAR_INT_MODE_P (mode))
1733 : {
1734 333272 : wide_int result;
1735 333272 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1736 666544 : wi::to_wide (arg1), TYPE_PRECISION (type),
1737 333272 : TREE_TYPE (arg0)))
1738 27593 : return wide_int_to_tree (type, result);
1739 333272 : }
1740 311350 : return NULL_TREE;
1741 : }
1742 :
1743 14100244 : if (mode == arg0_mode
1744 9958007 : && real_cst_p (arg0)
1745 15352170 : && real_cst_p (arg1))
1746 : {
1747 219909 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1748 219909 : REAL_VALUE_TYPE result;
1749 219909 : if (arg0_mode == arg1_mode)
1750 : {
1751 : /* real, real -> real. */
1752 439238 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1753 219619 : TREE_REAL_CST_PTR (arg1),
1754 219619 : REAL_MODE_FORMAT (mode)))
1755 189781 : return build_real (type, result);
1756 : }
1757 290 : else if (arg1_mode == TYPE_MODE (long_double_type_node))
1758 290 : switch (fn)
1759 : {
1760 290 : CASE_CFN_NEXTTOWARD:
1761 : /* real, long double -> real. */
1762 580 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1763 290 : TREE_REAL_CST_PTR (arg1),
1764 290 : REAL_MODE_FORMAT (mode)))
1765 228 : return build_real (type, result);
1766 : break;
1767 : default:
1768 : break;
1769 : }
1770 29900 : return NULL_TREE;
1771 : }
1772 :
1773 13880335 : if (real_cst_p (arg0)
1774 13880335 : && integer_cst_p (arg1))
1775 : {
1776 25704 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1777 25704 : if (mode == arg0_mode)
1778 : {
1779 : /* real, int -> real. */
1780 25701 : REAL_VALUE_TYPE result;
1781 25701 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1782 51402 : wi::to_wide (arg1),
1783 25701 : REAL_MODE_FORMAT (mode)))
1784 5554 : return build_real (type, result);
1785 : }
1786 20150 : return NULL_TREE;
1787 : }
1788 :
1789 13854631 : if (integer_cst_p (arg0)
1790 13854631 : && real_cst_p (arg1))
1791 : {
1792 6434 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1793 6434 : if (mode == arg1_mode)
1794 : {
1795 : /* int, real -> real. */
1796 6434 : REAL_VALUE_TYPE result;
1797 12868 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1798 6434 : TREE_REAL_CST_PTR (arg1),
1799 6434 : REAL_MODE_FORMAT (mode)))
1800 1755 : return build_real (type, result);
1801 : }
1802 4679 : return NULL_TREE;
1803 : }
1804 :
1805 13848197 : if (arg0_mode == arg1_mode
1806 11253293 : && complex_cst_p (arg0)
1807 13880264 : && complex_cst_p (arg1))
1808 : {
1809 32067 : gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1810 32067 : machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1811 32067 : tree arg0r = TREE_REALPART (arg0);
1812 32067 : tree arg0i = TREE_IMAGPART (arg0);
1813 32067 : tree arg1r = TREE_REALPART (arg1);
1814 32067 : tree arg1i = TREE_IMAGPART (arg1);
1815 32067 : if (mode == arg0_mode
1816 32067 : && real_cst_p (arg0r)
1817 32067 : && real_cst_p (arg0i)
1818 32067 : && real_cst_p (arg1r)
1819 64134 : && real_cst_p (arg1i))
1820 : {
1821 : /* complex real, complex real -> complex real. */
1822 32067 : REAL_VALUE_TYPE result_real, result_imag;
1823 64134 : if (fold_const_call_ccc (&result_real, &result_imag, fn,
1824 32067 : TREE_REAL_CST_PTR (arg0r),
1825 32067 : TREE_REAL_CST_PTR (arg0i),
1826 32067 : TREE_REAL_CST_PTR (arg1r),
1827 32067 : TREE_REAL_CST_PTR (arg1i),
1828 32067 : REAL_MODE_FORMAT (inner_mode)))
1829 21470 : return build_complex (type,
1830 10735 : build_real (TREE_TYPE (type), result_real),
1831 21470 : build_real (TREE_TYPE (type), result_imag));
1832 : }
1833 21332 : return NULL_TREE;
1834 : }
1835 :
1836 : return NULL_TREE;
1837 : }
1838 :
1839 : /* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1840 : otherwise return null. TYPE is the type of the return value. */
1841 :
1842 : tree
1843 17076973 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1844 : {
1845 17076973 : const char *p0, *p1;
1846 17076973 : char c;
1847 17076973 : tree_code subcode;
1848 17076973 : switch (fn)
1849 : {
1850 2692 : case CFN_BUILT_IN_STRSPN:
1851 2692 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1852 123 : return build_int_cst (type, strspn (p0, p1));
1853 : return NULL_TREE;
1854 :
1855 2596 : case CFN_BUILT_IN_STRCSPN:
1856 2596 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1857 123 : return build_int_cst (type, strcspn (p0, p1));
1858 : return NULL_TREE;
1859 :
1860 2210194 : case CFN_BUILT_IN_STRCMP:
1861 2210194 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1862 24938 : return build_cmp_result (type, strcmp (p0, p1));
1863 : return NULL_TREE;
1864 :
1865 269 : case CFN_BUILT_IN_STRCASECMP:
1866 269 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1867 : {
1868 10 : int r = strcmp (p0, p1);
1869 10 : if (r == 0)
1870 1 : return build_cmp_result (type, r);
1871 : }
1872 : return NULL_TREE;
1873 :
1874 164174 : case CFN_BUILT_IN_INDEX:
1875 164174 : case CFN_BUILT_IN_STRCHR:
1876 164174 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1877 : {
1878 142 : const char *r = strchr (p0, c);
1879 142 : if (r == NULL)
1880 38 : return build_int_cst (type, 0);
1881 104 : return fold_convert (type,
1882 : fold_build_pointer_plus_hwi (arg0, r - p0));
1883 : }
1884 : return NULL_TREE;
1885 :
1886 154458 : case CFN_BUILT_IN_RINDEX:
1887 154458 : case CFN_BUILT_IN_STRRCHR:
1888 154458 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1889 : {
1890 103 : const char *r = strrchr (p0, c);
1891 103 : if (r == NULL)
1892 35 : return build_int_cst (type, 0);
1893 68 : return fold_convert (type,
1894 : fold_build_pointer_plus_hwi (arg0, r - p0));
1895 : }
1896 : return NULL_TREE;
1897 :
1898 85304 : case CFN_BUILT_IN_STRSTR:
1899 85304 : if ((p1 = c_getstr (arg1)))
1900 : {
1901 5895 : if ((p0 = c_getstr (arg0)))
1902 : {
1903 182 : const char *r = strstr (p0, p1);
1904 182 : if (r == NULL)
1905 38 : return build_int_cst (type, 0);
1906 144 : return fold_convert (type,
1907 : fold_build_pointer_plus_hwi (arg0, r - p0));
1908 : }
1909 5713 : if (*p1 == '\0')
1910 13 : return fold_convert (type, arg0);
1911 : }
1912 : return NULL_TREE;
1913 :
1914 0 : case CFN_FOLD_LEFT_PLUS:
1915 0 : return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1916 :
1917 0 : case CFN_VEC_SHL_INSERT:
1918 0 : return fold_const_vec_shl_insert (type, arg0, arg1);
1919 :
1920 0 : case CFN_VEC_EXTRACT:
1921 0 : return fold_const_vec_extract (type, arg0, arg1);
1922 :
1923 0 : case CFN_SAT_ADD:
1924 0 : return fold_internal_fn_sat_add (type, arg0, arg1);
1925 :
1926 6399 : case CFN_UBSAN_CHECK_ADD:
1927 6399 : case CFN_ADD_OVERFLOW:
1928 6399 : subcode = PLUS_EXPR;
1929 6399 : goto arith_overflow;
1930 :
1931 6317 : case CFN_UBSAN_CHECK_SUB:
1932 6317 : case CFN_SUB_OVERFLOW:
1933 6317 : subcode = MINUS_EXPR;
1934 6317 : goto arith_overflow;
1935 :
1936 5383 : case CFN_UBSAN_CHECK_MUL:
1937 5383 : case CFN_MUL_OVERFLOW:
1938 5383 : subcode = MULT_EXPR;
1939 5383 : goto arith_overflow;
1940 :
1941 18099 : arith_overflow:
1942 18099 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1943 : {
1944 17240 : tree itype
1945 17240 : = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
1946 17240 : bool ovf = false;
1947 17240 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
1948 17240 : fold_convert (itype, arg1));
1949 17240 : if (!r || TREE_CODE (r) != INTEGER_CST)
1950 : return NULL_TREE;
1951 17240 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
1952 : ovf = true;
1953 17240 : if (TREE_OVERFLOW (r))
1954 3434 : r = drop_tree_overflow (r);
1955 17240 : if (itype == type)
1956 : {
1957 2737 : if (ovf)
1958 : return NULL_TREE;
1959 : return r;
1960 : }
1961 : else
1962 14503 : return build_complex (type, r, build_int_cst (itype, ovf));
1963 : }
1964 : return NULL_TREE;
1965 :
1966 14439187 : default:
1967 14439187 : return fold_const_call_1 (fn, type, arg0, arg1);
1968 : }
1969 : }
1970 :
1971 : /* Try to evaluate:
1972 :
1973 : *RESULT = FN (*ARG0, *ARG1, *ARG2)
1974 :
1975 : in format FORMAT. Return true on success. */
1976 :
1977 : static bool
1978 2534 : fold_const_call_ssss (real_value *result, combined_fn fn,
1979 : const real_value *arg0, const real_value *arg1,
1980 : const real_value *arg2, const real_format *format)
1981 : {
1982 2534 : switch (fn)
1983 : {
1984 2534 : CASE_CFN_FMA:
1985 2534 : CASE_CFN_FMA_FN:
1986 2534 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1987 :
1988 0 : case CFN_FMS:
1989 0 : {
1990 0 : real_value new_arg2 = real_value_negate (arg2);
1991 0 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
1992 : }
1993 :
1994 0 : case CFN_FNMA:
1995 0 : {
1996 0 : real_value new_arg0 = real_value_negate (arg0);
1997 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
1998 : }
1999 :
2000 0 : case CFN_FNMS:
2001 0 : {
2002 0 : real_value new_arg0 = real_value_negate (arg0);
2003 0 : real_value new_arg2 = real_value_negate (arg2);
2004 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
2005 : &new_arg2, format);
2006 : }
2007 :
2008 : default:
2009 : return false;
2010 : }
2011 : }
2012 :
2013 : /* Subroutine of fold_const_call, with the same interface. Handle cases
2014 : where the arguments and result are numerical. */
2015 :
2016 : static tree
2017 4110248 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2018 : {
2019 4110248 : machine_mode mode = TYPE_MODE (type);
2020 4110248 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
2021 4110248 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
2022 4110248 : machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
2023 :
2024 4110248 : if (arg0_mode == arg1_mode
2025 4110248 : && arg0_mode == arg2_mode
2026 1780782 : && real_cst_p (arg0)
2027 2712 : && real_cst_p (arg1)
2028 4112888 : && real_cst_p (arg2))
2029 : {
2030 2534 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
2031 2534 : if (mode == arg0_mode)
2032 : {
2033 : /* real, real, real -> real. */
2034 2534 : REAL_VALUE_TYPE result;
2035 5068 : if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
2036 2534 : TREE_REAL_CST_PTR (arg1),
2037 2534 : TREE_REAL_CST_PTR (arg2),
2038 2534 : REAL_MODE_FORMAT (mode)))
2039 1060 : return build_real (type, result);
2040 : }
2041 1474 : return NULL_TREE;
2042 : }
2043 :
2044 : return NULL_TREE;
2045 : }
2046 :
2047 : /* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
2048 : success, otherwise return null. TYPE is the type of the return value. */
2049 :
2050 : tree
2051 6874555 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2052 : {
2053 6874555 : const char *p0, *p1;
2054 6874555 : char c;
2055 6874555 : unsigned HOST_WIDE_INT s0, s1, s2 = 0;
2056 6874555 : switch (fn)
2057 : {
2058 45132 : case CFN_BUILT_IN_STRNCMP:
2059 45132 : if (!size_t_cst_p (arg2, &s2))
2060 : return NULL_TREE;
2061 29117 : if (s2 == 0
2062 237 : && !TREE_SIDE_EFFECTS (arg0)
2063 29326 : && !TREE_SIDE_EFFECTS (arg1))
2064 209 : return build_int_cst (type, 0);
2065 28908 : else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
2066 573 : return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
2067 : return NULL_TREE;
2068 :
2069 7999 : case CFN_BUILT_IN_STRNCASECMP:
2070 7999 : if (!size_t_cst_p (arg2, &s2))
2071 : return NULL_TREE;
2072 7678 : if (s2 == 0
2073 9 : && !TREE_SIDE_EFFECTS (arg0)
2074 7683 : && !TREE_SIDE_EFFECTS (arg1))
2075 5 : return build_int_cst (type, 0);
2076 7673 : else if ((p0 = c_getstr (arg0))
2077 724 : && (p1 = c_getstr (arg1))
2078 7813 : && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
2079 3 : return build_int_cst (type, 0);
2080 : return NULL_TREE;
2081 :
2082 2512170 : case CFN_BUILT_IN_BCMP:
2083 2512170 : case CFN_BUILT_IN_MEMCMP:
2084 2512170 : if (!size_t_cst_p (arg2, &s2))
2085 : return NULL_TREE;
2086 1615272 : if (s2 == 0
2087 13066 : && !TREE_SIDE_EFFECTS (arg0)
2088 1628338 : && !TREE_SIDE_EFFECTS (arg1))
2089 13066 : return build_int_cst (type, 0);
2090 1602206 : if ((p0 = getbyterep (arg0, &s0))
2091 12254 : && (p1 = getbyterep (arg1, &s1))
2092 3792 : && s2 <= s0
2093 1605562 : && s2 <= s1)
2094 3355 : return build_cmp_result (type, memcmp (p0, p1, s2));
2095 : return NULL_TREE;
2096 :
2097 198914 : case CFN_BUILT_IN_MEMCHR:
2098 198914 : if (!size_t_cst_p (arg2, &s2))
2099 : return NULL_TREE;
2100 7371 : if (s2 == 0
2101 151 : && !TREE_SIDE_EFFECTS (arg0)
2102 7505 : && !TREE_SIDE_EFFECTS (arg1))
2103 131 : return build_int_cst (type, 0);
2104 7240 : if ((p0 = getbyterep (arg0, &s0))
2105 2528 : && s2 <= s0
2106 9649 : && target_char_cst_p (arg1, &c))
2107 : {
2108 910 : const char *r = (const char *) memchr (p0, c, s2);
2109 910 : if (r == NULL)
2110 284 : return build_int_cst (type, 0);
2111 626 : return fold_convert (type,
2112 : fold_build_pointer_plus_hwi (arg0, r - p0));
2113 : }
2114 : return NULL_TREE;
2115 :
2116 0 : case CFN_WHILE_ULT:
2117 0 : {
2118 0 : poly_uint64 parg0, parg1;
2119 0 : if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
2120 0 : return fold_while_ult (type, parg0, parg1);
2121 : return NULL_TREE;
2122 : }
2123 :
2124 92 : case CFN_UADDC:
2125 92 : case CFN_USUBC:
2126 92 : if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
2127 : {
2128 92 : tree itype = TREE_TYPE (type);
2129 92 : bool ovf = false;
2130 92 : tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
2131 92 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
2132 92 : fold_convert (itype, arg1));
2133 92 : if (!r)
2134 : return NULL_TREE;
2135 92 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
2136 : ovf = true;
2137 92 : tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
2138 92 : if (!r2 || TREE_CODE (r2) != INTEGER_CST)
2139 : return NULL_TREE;
2140 92 : if (arith_overflowed_p (subcode, itype, r, arg2))
2141 0 : ovf = true;
2142 92 : if (TREE_OVERFLOW (r2))
2143 0 : r2 = drop_tree_overflow (r2);
2144 92 : return build_complex (type, r2, build_int_cst (itype, ovf));
2145 : }
2146 : return NULL_TREE;
2147 :
2148 4110248 : default:
2149 4110248 : return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2150 : }
2151 : }
|