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 36717726 : integer_cst_p (tree t)
40 : {
41 36717726 : return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
42 : }
43 :
44 : static inline bool
45 42212087 : real_cst_p (tree t)
46 : {
47 42212087 : return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
48 : }
49 :
50 : static inline bool
51 25724362 : complex_cst_p (tree t)
52 : {
53 25724362 : 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 2760628 : size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
61 : {
62 2760628 : if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 2760473 : && integer_cst_p (t)
64 4405974 : && tree_fits_uhwi_p (t))
65 : {
66 1645346 : *size_out = tree_to_uhwi (t);
67 1645346 : 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 66468 : build_cmp_result (tree type, int res)
78 : {
79 71076 : 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 236538 : 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 236538 : if (!mpfr_number_p (m)
95 221529 : || mpfr_overflow_p ()
96 221529 : || mpfr_underflow_p ()
97 454523 : || (flag_rounding_math && inexact))
98 18638 : return false;
99 :
100 217900 : REAL_VALUE_TYPE tmp;
101 217900 : 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 217900 : if (!real_isfinite (&tmp)
107 217900 : || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
108 : return false;
109 :
110 217900 : real_convert (result, format, &tmp);
111 217900 : 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 106364 : 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 106364 : if (format->b != 2 || !real_isfinite (arg))
129 2742 : return false;
130 :
131 103622 : int prec = format->p;
132 103622 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
133 :
134 103622 : auto_mpfr m (prec);
135 103622 : mpfr_from_real (m, arg, MPFR_RNDN);
136 103622 : mpfr_clear_flags ();
137 103622 : bool inexact = func (m, m, rnd);
138 103622 : bool ok = do_mpfr_ckconv (result, m, inexact, format);
139 :
140 103622 : return ok;
141 103622 : }
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 147 : 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 147 : if (format->b != 2 || !real_isfinite (arg))
157 0 : return false;
158 :
159 147 : int prec = format->p;
160 147 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
161 147 : mpfr_t m, ms, mc;
162 :
163 147 : mpfr_inits2 (prec, m, ms, mc, NULL);
164 147 : mpfr_from_real (m, arg, MPFR_RNDN);
165 147 : mpfr_clear_flags ();
166 147 : bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
167 147 : bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
168 147 : && do_mpfr_ckconv (result_cos, mc, inexact, format));
169 147 : mpfr_clears (m, ms, mc, NULL);
170 :
171 147 : 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 139377 : 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 139377 : if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
190 11044 : return false;
191 :
192 128333 : int prec = format->p;
193 128333 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
194 128333 : mpfr_t m0, m1;
195 :
196 128333 : mpfr_inits2 (prec, m0, m1, NULL);
197 128333 : mpfr_from_real (m0, arg0, MPFR_RNDN);
198 128333 : mpfr_from_real (m1, arg1, MPFR_RNDN);
199 128333 : mpfr_clear_flags ();
200 128333 : bool inexact = func (m0, m0, m1, rnd);
201 128333 : bool ok = do_mpfr_ckconv (result, m0, inexact, format);
202 128333 : mpfr_clears (m0, m1, NULL);
203 :
204 128333 : 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 38801 : 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 38801 : if (!mpfr_number_p (mpc_realref (m))
287 33261 : || !mpfr_number_p (mpc_imagref (m))
288 33261 : || mpfr_overflow_p ()
289 33261 : || mpfr_underflow_p ()
290 68428 : || (flag_rounding_math && inexact))
291 9174 : return false;
292 :
293 29627 : REAL_VALUE_TYPE tmp_real, tmp_imag;
294 29627 : real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN);
295 29627 : 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 29627 : if (!real_isfinite (&tmp_real)
301 29627 : || !real_isfinite (&tmp_imag)
302 29627 : || (tmp_real.cl == rvc_zero) != (mpfr_zero_p (mpc_realref (m)) != 0)
303 59254 : || (tmp_imag.cl == rvc_zero) != (mpfr_zero_p (mpc_imagref (m)) != 0))
304 0 : return false;
305 :
306 29627 : real_convert (result_real, format, &tmp_real);
307 29627 : real_convert (result_imag, format, &tmp_imag);
308 :
309 29627 : return (real_identical (result_real, &tmp_real)
310 29627 : && 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 13700 : 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 13700 : if (format->b != 2
330 13700 : || !real_isfinite (arg_real)
331 25078 : || !real_isfinite (arg_imag))
332 2322 : return false;
333 :
334 11378 : int prec = format->p;
335 11378 : mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
336 11378 : mpc_t m;
337 :
338 11378 : mpc_init2 (m, prec);
339 11378 : mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN);
340 11378 : mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN);
341 11378 : mpfr_clear_flags ();
342 11378 : bool inexact = func (m, m, crnd);
343 11378 : bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
344 11378 : mpc_clear (m);
345 :
346 11378 : 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 122367 : fold_const_pow (real_value *result, const real_value *arg0,
496 : const real_value *arg1, const real_format *format)
497 : {
498 122367 : if (flag_signaling_nans
499 122367 : && (REAL_VALUE_ISSIGNALING_NAN (*arg0)
500 0 : || REAL_VALUE_ISSIGNALING_NAN (*arg1)))
501 0 : return false;
502 :
503 122367 : if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
504 : {
505 112059 : if (flag_errno_math)
506 111696 : 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 10494 : fold_const_nextafter (real_value *result, const real_value *arg0,
534 : const real_value *arg1, const real_format *format)
535 : {
536 10494 : if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
537 10494 : || 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 10494 : if (format->pnan < format->p
543 10494 : || format->b == 10
544 10494 : || !format->has_inf
545 10494 : || !format->has_denorm)
546 : return false;
547 :
548 16042 : 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 10494 : && (flag_trapping_math || flag_errno_math))
552 5548 : return false;
553 : /* Similarly for nextafter (0, 1) raising underflow. */
554 4946 : else if (flag_trapping_math
555 4439 : && arg0->cl == rvc_zero
556 3822 : && 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 25261 : 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 25261 : 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 42736 : 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 9821 : if (!flag_unsafe_math_optimizations
589 9818 : && flag_signaling_nans
590 9941 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
591 : return false;
592 :
593 9821 : REAL_VALUE_TYPE initial_result;
594 9821 : real_ldexp (&initial_result, arg0, arg1.to_shwi ());
595 :
596 : /* Ensure we didn't overflow. */
597 9821 : if (real_isinf (&initial_result))
598 : return false;
599 :
600 : /* Only proceed if the target mode can hold the
601 : resulting value. */
602 9801 : *result = real_value_truncate (format, initial_result);
603 9801 : 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 364780 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
612 : {
613 364780 : REAL_VALUE_TYPE real;
614 364780 : const char *str = c_getstr (arg);
615 364780 : if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
616 364311 : 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 2125 : fold_const_reduction (tree type, tree arg, tree_code code)
624 : {
625 2125 : unsigned HOST_WIDE_INT nelts;
626 2125 : if (TREE_CODE (arg) != VECTOR_CST
627 2125 : || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
628 0 : return NULL_TREE;
629 :
630 2125 : tree res = VECTOR_CST_ELT (arg, 0);
631 26526 : for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
632 : {
633 24401 : res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
634 24401 : 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 253 : fold_const_vec_convert (tree ret_type, tree arg)
644 : {
645 253 : enum tree_code code = NOP_EXPR;
646 253 : tree arg_type = TREE_TYPE (arg);
647 253 : if (TREE_CODE (arg) != VECTOR_CST)
648 : return NULL_TREE;
649 :
650 253 : gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
651 :
652 506 : if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
653 441 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
654 : code = FIX_TRUNC_EXPR;
655 400 : else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
656 400 : && 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 253 : bool step_ok_p
662 506 : = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
663 188 : && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
664 388 : && (TYPE_PRECISION (TREE_TYPE (ret_type))
665 135 : <= TYPE_PRECISION (TREE_TYPE (arg_type))));
666 253 : tree_vector_builder elts;
667 253 : if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
668 : return NULL_TREE;
669 :
670 253 : unsigned int count = elts.encoded_nelts ();
671 884 : for (unsigned int i = 0; i < count; ++i)
672 : {
673 637 : tree elt = fold_unary (code, TREE_TYPE (ret_type),
674 : VECTOR_CST_ELT (arg, i));
675 637 : if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
676 6 : return NULL_TREE;
677 631 : elts.quick_push (elt);
678 : }
679 :
680 247 : return elts.build ();
681 253 : }
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 159036 : fold_const_call_ss (real_value *result, combined_fn fn,
721 : const real_value *arg, const real_format *format)
722 : {
723 159036 : switch (fn)
724 : {
725 22225 : CASE_CFN_SQRT:
726 22225 : CASE_CFN_SQRT_FN:
727 22225 : return (real_compare (GE_EXPR, arg, &dconst0)
728 22225 : && 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 556 : CASE_CFN_ATAN:
747 556 : CASE_CFN_ATAN_FN:
748 556 : 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 1011 : CASE_CFN_SIN:
766 1011 : CASE_CFN_SIN_FN:
767 1011 : return do_mpfr_arg1 (result, mpfr_sin, arg, format);
768 :
769 843 : CASE_CFN_COS:
770 843 : CASE_CFN_COS_FN:
771 843 : return do_mpfr_arg1 (result, mpfr_cos, arg, format);
772 :
773 557 : CASE_CFN_TAN:
774 557 : CASE_CFN_TAN_FN:
775 557 : 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 870 : CASE_CFN_EXP:
832 870 : CASE_CFN_EXP_FN:
833 870 : 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 58932 : CASE_CFN_LOG:
848 58932 : CASE_CFN_LOG_FN:
849 58932 : return (real_compare (GT_EXPR, arg, &dconst0)
850 58932 : && 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 273 : CASE_CFN_ROUND:
909 273 : CASE_CFN_ROUND_FN:
910 273 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
911 : {
912 273 : real_round (result, format, arg);
913 273 : 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 17618 : 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 17618 : switch (fn)
951 : {
952 1872 : CASE_CFN_SIGNBIT:
953 1872 : if (real_isneg (arg))
954 1005 : *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 3808 : case CFN_BUILT_IN_ISSIGNALING:
1009 7445 : *result = wi::shwi (real_issignaling_nan (arg) ? 1 : 0, precision);
1010 3808 : 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 3412143 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1043 : unsigned int precision, tree arg_type)
1044 : {
1045 3412143 : 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 1917 : CASE_CFN_CLZ:
1053 1917 : case CFN_BUILT_IN_CLZG:
1054 1917 : {
1055 1917 : int tmp;
1056 1917 : if (wi::ne_p (arg, 0))
1057 1579 : tmp = wi::clz (arg);
1058 338 : else if (TREE_CODE (arg_type) == BITINT_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 1917 : *result = wi::shwi (tmp, precision);
1064 1917 : return true;
1065 : }
1066 :
1067 768 : CASE_CFN_CTZ:
1068 768 : case CFN_BUILT_IN_CTZG:
1069 768 : {
1070 768 : int tmp;
1071 768 : if (wi::ne_p (arg, 0))
1072 524 : tmp = wi::ctz (arg);
1073 244 : else if (TREE_CODE (arg_type) == BITINT_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 768 : *result = wi::shwi (tmp, precision);
1079 768 : 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 38274 : CASE_CFN_POPCOUNT:
1088 38274 : case CFN_BUILT_IN_POPCOUNTG:
1089 38274 : *result = wi::shwi (wi::popcount (arg), precision);
1090 38274 : 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 721 : case CFN_BUILT_IN_BSWAP16:
1098 721 : case CFN_BUILT_IN_BSWAP32:
1099 721 : case CFN_BUILT_IN_BSWAP64:
1100 721 : case CFN_BUILT_IN_BSWAP128:
1101 1442 : *result = wi::bswap (wide_int::from (arg, precision,
1102 1442 : TYPE_SIGN (arg_type)));
1103 721 : return true;
1104 :
1105 : default:
1106 : return false;
1107 : }
1108 : }
1109 :
1110 : /* Try to evaluate:
1111 :
1112 : RESULT = FN (*ARG)
1113 :
1114 : where FORMAT is the format of ARG and of the real and imaginary parts
1115 : of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
1116 : true on success. */
1117 :
1118 : static bool
1119 147 : fold_const_call_cs (real_value *result_real, real_value *result_imag,
1120 : combined_fn fn, const real_value *arg,
1121 : const real_format *format)
1122 : {
1123 0 : switch (fn)
1124 : {
1125 147 : CASE_CFN_CEXPI:
1126 : /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1127 147 : return do_mpfr_sincos (result_imag, result_real, arg, format);
1128 :
1129 : default:
1130 : return false;
1131 : }
1132 : }
1133 :
1134 : /* Try to evaluate:
1135 :
1136 : *RESULT = fn (ARG)
1137 :
1138 : where FORMAT is the format of RESULT and of the real and imaginary parts
1139 : of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
1140 : success. */
1141 :
1142 : static bool
1143 2316 : fold_const_call_sc (real_value *result, combined_fn fn,
1144 : const real_value *arg_real, const real_value *arg_imag,
1145 : const real_format *format)
1146 : {
1147 0 : switch (fn)
1148 : {
1149 1180 : CASE_CFN_CABS:
1150 1180 : CASE_CFN_CABS_FN:
1151 1180 : return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1152 :
1153 : default:
1154 : return false;
1155 : }
1156 : }
1157 :
1158 : /* Try to evaluate:
1159 :
1160 : RESULT = fn (ARG)
1161 :
1162 : where FORMAT is the format of the real and imaginary parts of RESULT
1163 : (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1164 : Return true on success. */
1165 :
1166 : static bool
1167 38647 : fold_const_call_cc (real_value *result_real, real_value *result_imag,
1168 : combined_fn fn, const real_value *arg_real,
1169 : const real_value *arg_imag, const real_format *format)
1170 : {
1171 38647 : switch (fn)
1172 : {
1173 686 : CASE_CFN_CCOS:
1174 686 : CASE_CFN_CCOS_FN:
1175 686 : return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1176 686 : arg_real, arg_imag, format);
1177 :
1178 676 : CASE_CFN_CCOSH:
1179 676 : CASE_CFN_CCOSH_FN:
1180 676 : return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1181 676 : arg_real, arg_imag, format);
1182 :
1183 683 : CASE_CFN_CPROJ:
1184 683 : CASE_CFN_CPROJ_FN:
1185 683 : if (real_isinf (arg_real) || real_isinf (arg_imag))
1186 : {
1187 436 : *result_real = dconstinf;
1188 436 : *result_imag = dconst0;
1189 436 : result_imag->sign = arg_imag->sign;
1190 : }
1191 : else
1192 : {
1193 247 : *result_real = *arg_real;
1194 247 : *result_imag = *arg_imag;
1195 : }
1196 : return true;
1197 :
1198 686 : CASE_CFN_CSIN:
1199 686 : CASE_CFN_CSIN_FN:
1200 686 : return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1201 686 : arg_real, arg_imag, format);
1202 :
1203 676 : CASE_CFN_CSINH:
1204 676 : CASE_CFN_CSINH_FN:
1205 676 : return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1206 676 : arg_real, arg_imag, format);
1207 :
1208 698 : CASE_CFN_CTAN:
1209 698 : CASE_CFN_CTAN_FN:
1210 698 : return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1211 698 : arg_real, arg_imag, format);
1212 :
1213 676 : CASE_CFN_CTANH:
1214 676 : CASE_CFN_CTANH_FN:
1215 676 : return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1216 676 : arg_real, arg_imag, format);
1217 :
1218 777 : CASE_CFN_CLOG:
1219 777 : CASE_CFN_CLOG_FN:
1220 777 : return do_mpc_arg1 (result_real, result_imag, mpc_log,
1221 777 : arg_real, arg_imag, format);
1222 :
1223 3053 : CASE_CFN_CSQRT:
1224 3053 : CASE_CFN_CSQRT_FN:
1225 3053 : return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1226 3053 : arg_real, arg_imag, format);
1227 :
1228 679 : CASE_CFN_CASIN:
1229 679 : CASE_CFN_CASIN_FN:
1230 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1231 679 : arg_real, arg_imag, format);
1232 :
1233 728 : CASE_CFN_CACOS:
1234 728 : CASE_CFN_CACOS_FN:
1235 728 : return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1236 728 : arg_real, arg_imag, format);
1237 :
1238 679 : CASE_CFN_CATAN:
1239 679 : CASE_CFN_CATAN_FN:
1240 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1241 679 : arg_real, arg_imag, format);
1242 :
1243 679 : CASE_CFN_CASINH:
1244 679 : CASE_CFN_CASINH_FN:
1245 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1246 679 : arg_real, arg_imag, format);
1247 :
1248 745 : CASE_CFN_CACOSH:
1249 745 : CASE_CFN_CACOSH_FN:
1250 745 : return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1251 745 : arg_real, arg_imag, format);
1252 :
1253 679 : CASE_CFN_CATANH:
1254 679 : CASE_CFN_CATANH_FN:
1255 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1256 679 : arg_real, arg_imag, format);
1257 :
1258 1583 : CASE_CFN_CEXP:
1259 1583 : CASE_CFN_CEXP_FN:
1260 1583 : return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1261 1583 : arg_real, arg_imag, format);
1262 :
1263 : default:
1264 : return false;
1265 : }
1266 : }
1267 :
1268 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1269 : where the arguments and result are numerical. */
1270 :
1271 : static tree
1272 17025499 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
1273 : {
1274 17025499 : machine_mode mode = TYPE_MODE (type);
1275 17025499 : machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1276 :
1277 17025499 : if (integer_cst_p (arg))
1278 : {
1279 3526407 : if (SCALAR_INT_MODE_P (mode))
1280 : {
1281 3412143 : wide_int result;
1282 3412143 : if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1283 3412143 : TYPE_PRECISION (type), TREE_TYPE (arg)))
1284 43128 : return wide_int_to_tree (type, result);
1285 3412143 : }
1286 3483279 : return NULL_TREE;
1287 : }
1288 :
1289 13499092 : if (real_cst_p (arg))
1290 : {
1291 176804 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1292 176804 : if (mode == arg_mode)
1293 : {
1294 : /* real -> real. */
1295 159036 : REAL_VALUE_TYPE result;
1296 159036 : if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1297 159036 : REAL_MODE_FORMAT (mode)))
1298 97763 : return build_real (type, result);
1299 : }
1300 17768 : else if (COMPLEX_MODE_P (mode)
1301 17915 : && GET_MODE_INNER (mode) == arg_mode)
1302 : {
1303 : /* real -> complex real. */
1304 147 : REAL_VALUE_TYPE result_real, result_imag;
1305 294 : if (fold_const_call_cs (&result_real, &result_imag, fn,
1306 147 : TREE_REAL_CST_PTR (arg),
1307 147 : REAL_MODE_FORMAT (arg_mode)))
1308 294 : return build_complex (type,
1309 147 : build_real (TREE_TYPE (type), result_real),
1310 294 : build_real (TREE_TYPE (type), result_imag));
1311 : }
1312 17621 : else if (INTEGRAL_TYPE_P (type))
1313 : {
1314 : /* real -> int. */
1315 17618 : wide_int result;
1316 17618 : if (fold_const_call_ss (&result, fn,
1317 17618 : TREE_REAL_CST_PTR (arg),
1318 17618 : TYPE_PRECISION (type),
1319 17618 : REAL_MODE_FORMAT (arg_mode)))
1320 11199 : return wide_int_to_tree (type, result);
1321 17618 : }
1322 67695 : return NULL_TREE;
1323 : }
1324 :
1325 13322288 : if (complex_cst_p (arg))
1326 : {
1327 40963 : gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1328 40963 : machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1329 40963 : tree argr = TREE_REALPART (arg);
1330 40963 : tree argi = TREE_IMAGPART (arg);
1331 40963 : if (mode == arg_mode
1332 38647 : && real_cst_p (argr)
1333 79610 : && real_cst_p (argi))
1334 : {
1335 : /* complex real -> complex real. */
1336 38647 : REAL_VALUE_TYPE result_real, result_imag;
1337 77294 : if (fold_const_call_cc (&result_real, &result_imag, fn,
1338 38647 : TREE_REAL_CST_PTR (argr),
1339 38647 : TREE_REAL_CST_PTR (argi),
1340 38647 : REAL_MODE_FORMAT (inner_mode)))
1341 20942 : return build_complex (type,
1342 10471 : build_real (TREE_TYPE (type), result_real),
1343 20942 : build_real (TREE_TYPE (type), result_imag));
1344 : }
1345 30492 : if (mode == inner_mode
1346 2316 : && real_cst_p (argr)
1347 32808 : && real_cst_p (argi))
1348 : {
1349 : /* complex real -> real. */
1350 2316 : REAL_VALUE_TYPE result;
1351 4632 : if (fold_const_call_sc (&result, fn,
1352 2316 : TREE_REAL_CST_PTR (argr),
1353 2316 : TREE_REAL_CST_PTR (argi),
1354 2316 : REAL_MODE_FORMAT (inner_mode)))
1355 1180 : return build_real (type, result);
1356 : }
1357 29312 : return NULL_TREE;
1358 : }
1359 :
1360 : return NULL_TREE;
1361 : }
1362 :
1363 : /* Try to fold FN (ARG) to a constant. Return the constant on success,
1364 : otherwise return null. TYPE is the type of the return value. */
1365 :
1366 : tree
1367 17931178 : fold_const_call (combined_fn fn, tree type, tree arg)
1368 : {
1369 17931178 : switch (fn)
1370 : {
1371 538521 : case CFN_BUILT_IN_STRLEN:
1372 538521 : if (const char *str = c_getstr (arg))
1373 96580 : return build_int_cst (type, strlen (str));
1374 : return NULL_TREE;
1375 :
1376 212003 : CASE_CFN_NAN:
1377 212003 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1378 212003 : case CFN_BUILT_IN_NAND32:
1379 212003 : case CFN_BUILT_IN_NAND64:
1380 212003 : case CFN_BUILT_IN_NAND128:
1381 212003 : case CFN_BUILT_IN_NAND64X:
1382 212003 : return fold_const_builtin_nan (type, arg, true);
1383 :
1384 152777 : CASE_CFN_NANS:
1385 152777 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1386 152777 : case CFN_BUILT_IN_NANSF16B:
1387 152777 : case CFN_BUILT_IN_NANSD32:
1388 152777 : case CFN_BUILT_IN_NANSD64:
1389 152777 : case CFN_BUILT_IN_NANSD128:
1390 152777 : case CFN_BUILT_IN_NANSD64X:
1391 152777 : return fold_const_builtin_nan (type, arg, false);
1392 :
1393 1720 : case CFN_REDUC_PLUS:
1394 1720 : return fold_const_reduction (type, arg, PLUS_EXPR);
1395 :
1396 47 : case CFN_REDUC_MAX:
1397 47 : return fold_const_reduction (type, arg, MAX_EXPR);
1398 :
1399 67 : case CFN_REDUC_MIN:
1400 67 : return fold_const_reduction (type, arg, MIN_EXPR);
1401 :
1402 34 : case CFN_REDUC_AND:
1403 34 : return fold_const_reduction (type, arg, BIT_AND_EXPR);
1404 :
1405 251 : case CFN_REDUC_IOR:
1406 251 : return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1407 :
1408 6 : case CFN_REDUC_XOR:
1409 6 : return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1410 :
1411 253 : case CFN_VEC_CONVERT:
1412 253 : return fold_const_vec_convert (type, arg);
1413 :
1414 17025499 : default:
1415 17025499 : return fold_const_call_1 (fn, type, arg);
1416 : }
1417 : }
1418 :
1419 : /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1420 : of type TYPE. */
1421 :
1422 : static tree
1423 0 : fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1424 : {
1425 0 : if (TREE_CODE (arg1) != VECTOR_CST)
1426 : return NULL_TREE;
1427 :
1428 0 : unsigned HOST_WIDE_INT nelts;
1429 0 : if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1430 : return NULL_TREE;
1431 :
1432 0 : for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1433 : {
1434 0 : arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1435 0 : if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1436 : return NULL_TREE;
1437 : }
1438 : return arg0;
1439 : }
1440 :
1441 : /* Fold a call to IFN_VEC_SHL_INSERT (ARG0, ARG1), returning a value
1442 : of type TYPE. */
1443 :
1444 : static tree
1445 0 : fold_const_vec_shl_insert (tree, tree arg0, tree arg1)
1446 : {
1447 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1448 : return NULL_TREE;
1449 :
1450 : /* vec_shl_insert ( dup(CST), CST) -> dup (CST). */
1451 0 : if (tree elem = uniform_vector_p (arg0))
1452 : {
1453 0 : if (operand_equal_p (elem, arg1))
1454 : return arg0;
1455 : }
1456 :
1457 : return NULL_TREE;
1458 : }
1459 :
1460 : /* Fold a call to IFN_VEC_EXTRACT (ARG0, ARG1), returning a value
1461 : of type TYPE.
1462 :
1463 : Right now this is only handling uniform vectors, so ARG1 is not
1464 : used. But it could be easily adjusted in the future to handle
1465 : non-uniform vectors by extracting the relevant element. */
1466 :
1467 : static tree
1468 0 : fold_const_vec_extract (tree, tree arg0, tree)
1469 : {
1470 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1471 : return NULL_TREE;
1472 :
1473 : /* vec_extract ( dup(CST), CST) -> dup (CST). */
1474 0 : if (tree elem = uniform_vector_p (arg0))
1475 : return elem;
1476 :
1477 : return NULL_TREE;
1478 : }
1479 :
1480 : /* Try to evaluate:
1481 :
1482 : *RESULT = FN (*ARG0, *ARG1)
1483 :
1484 : in format FORMAT. Return true on success. */
1485 :
1486 : static bool
1487 219343 : fold_const_call_sss (real_value *result, combined_fn fn,
1488 : const real_value *arg0, const real_value *arg1,
1489 : const real_format *format)
1490 : {
1491 219343 : switch (fn)
1492 : {
1493 6774 : CASE_CFN_DREM:
1494 6774 : CASE_CFN_REMAINDER:
1495 6774 : CASE_CFN_REMAINDER_FN:
1496 6774 : return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1497 :
1498 983 : CASE_CFN_ATAN2:
1499 983 : CASE_CFN_ATAN2_FN:
1500 983 : return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1501 :
1502 : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
1503 84 : CASE_CFN_ATAN2PI:
1504 84 : CASE_CFN_ATAN2PI_FN:
1505 84 : return do_mpfr_arg2 (result, mpfr_atan2pi, arg0, arg1, format);
1506 : #endif
1507 :
1508 572 : CASE_CFN_FDIM:
1509 572 : CASE_CFN_FDIM_FN:
1510 572 : return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1511 :
1512 517 : CASE_CFN_FMOD:
1513 517 : CASE_CFN_FMOD_FN:
1514 517 : return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
1515 :
1516 578 : CASE_CFN_HYPOT:
1517 578 : CASE_CFN_HYPOT_FN:
1518 578 : return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1519 :
1520 70652 : CASE_CFN_COPYSIGN:
1521 70652 : CASE_CFN_COPYSIGN_FN:
1522 70652 : *result = *arg0;
1523 70652 : real_copysign (result, arg1);
1524 70652 : return true;
1525 :
1526 3161 : CASE_CFN_FMIN:
1527 3161 : CASE_CFN_FMIN_FN:
1528 3161 : return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1529 :
1530 3161 : CASE_CFN_FMAX:
1531 3161 : CASE_CFN_FMAX_FN:
1532 3161 : return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1533 :
1534 122367 : CASE_CFN_POW:
1535 122367 : CASE_CFN_POW_FN:
1536 122367 : return fold_const_pow (result, arg0, arg1, format);
1537 :
1538 10494 : CASE_CFN_NEXTAFTER:
1539 10494 : CASE_CFN_NEXTAFTER_FN:
1540 10494 : case CFN_BUILT_IN_NEXTAFTERF16B:
1541 10494 : CASE_CFN_NEXTTOWARD:
1542 10494 : return fold_const_nextafter (result, arg0, arg1, format);
1543 :
1544 : default:
1545 : return false;
1546 : }
1547 : }
1548 :
1549 : /* Try to evaluate:
1550 :
1551 : *RESULT = FN (*ARG0, ARG1)
1552 :
1553 : where FORMAT is the format of *RESULT and *ARG0. Return true on
1554 : success. */
1555 :
1556 : static bool
1557 25700 : fold_const_call_sss (real_value *result, combined_fn fn,
1558 : const real_value *arg0, const wide_int_ref &arg1,
1559 : const real_format *format)
1560 : {
1561 25700 : switch (fn)
1562 : {
1563 7912 : CASE_CFN_LDEXP:
1564 7912 : CASE_CFN_LDEXP_FN:
1565 7912 : return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1566 :
1567 17349 : CASE_CFN_SCALBN:
1568 17349 : CASE_CFN_SCALBN_FN:
1569 17349 : CASE_CFN_SCALBLN:
1570 17349 : CASE_CFN_SCALBLN_FN:
1571 17349 : return (format->b == 2
1572 17349 : && fold_const_builtin_load_exponent (result, arg0, arg1,
1573 : format));
1574 :
1575 430 : CASE_CFN_POWI:
1576 : /* Avoid the folding if flag_signaling_nans is on and
1577 : operand is a signaling NaN. */
1578 430 : if (!flag_unsafe_math_optimizations
1579 417 : && flag_signaling_nans
1580 445 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1581 : return false;
1582 :
1583 430 : real_powi (result, format, arg0, arg1.to_shwi ());
1584 430 : return true;
1585 :
1586 : default:
1587 : return false;
1588 : }
1589 : }
1590 :
1591 : /* Try to evaluate:
1592 :
1593 : *RESULT = FN (ARG0, *ARG1)
1594 :
1595 : where FORMAT is the format of *RESULT and *ARG1. Return true on
1596 : success. */
1597 :
1598 : static bool
1599 6434 : fold_const_call_sss (real_value *result, combined_fn fn,
1600 : const wide_int_ref &arg0, const real_value *arg1,
1601 : const real_format *format)
1602 : {
1603 6434 : switch (fn)
1604 : {
1605 1220 : CASE_CFN_JN:
1606 1220 : return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1607 :
1608 5205 : CASE_CFN_YN:
1609 5205 : return (real_compare (GT_EXPR, arg1, &dconst0)
1610 5205 : && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1611 :
1612 : default:
1613 : return false;
1614 : }
1615 : }
1616 :
1617 : /* Try to evaluate:
1618 :
1619 : *RESULT = FN (ARG0, ARG1)
1620 :
1621 : where ARG_TYPE is the type of ARG0 and PRECISION is the number of bits in
1622 : the result. Return true on success. */
1623 :
1624 : static bool
1625 266650 : fold_const_call_sss (wide_int *result, combined_fn fn,
1626 : const wide_int_ref &arg0, const wide_int_ref &arg1,
1627 : unsigned int precision, tree arg_type ATTRIBUTE_UNUSED)
1628 : {
1629 266650 : switch (fn)
1630 : {
1631 15734 : case CFN_CLZ:
1632 15734 : case CFN_BUILT_IN_CLZG:
1633 15734 : {
1634 15734 : int tmp;
1635 15734 : if (wi::ne_p (arg0, 0))
1636 15610 : tmp = wi::clz (arg0);
1637 : else
1638 124 : tmp = arg1.to_shwi ();
1639 15734 : *result = wi::shwi (tmp, precision);
1640 15734 : return true;
1641 : }
1642 :
1643 11468 : case CFN_CTZ:
1644 11468 : case CFN_BUILT_IN_CTZG:
1645 11468 : {
1646 11468 : int tmp;
1647 11468 : if (wi::ne_p (arg0, 0))
1648 11376 : tmp = wi::ctz (arg0);
1649 : else
1650 92 : tmp = arg1.to_shwi ();
1651 11468 : *result = wi::shwi (tmp, precision);
1652 11468 : return true;
1653 : }
1654 :
1655 : default:
1656 : return false;
1657 : }
1658 : }
1659 :
1660 : /* Try to evaluate:
1661 :
1662 : RESULT = fn (ARG0, ARG1)
1663 :
1664 : where FORMAT is the format of the real and imaginary parts of RESULT
1665 : (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1666 : and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1667 :
1668 : static bool
1669 32067 : fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1670 : combined_fn fn, const real_value *arg0_real,
1671 : const real_value *arg0_imag, const real_value *arg1_real,
1672 : const real_value *arg1_imag, const real_format *format)
1673 : {
1674 0 : switch (fn)
1675 : {
1676 32067 : CASE_CFN_CPOW:
1677 32067 : CASE_CFN_CPOW_FN:
1678 32067 : return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1679 0 : arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1680 :
1681 : default:
1682 : return false;
1683 : }
1684 : }
1685 :
1686 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1687 : where the arguments and result are numerical. */
1688 :
1689 : static tree
1690 15525993 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1691 : {
1692 15525993 : machine_mode mode = TYPE_MODE (type);
1693 15525993 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1694 15525993 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1695 :
1696 15525993 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1697 : {
1698 272309 : if (SCALAR_INT_MODE_P (mode))
1699 : {
1700 266650 : wide_int result;
1701 266650 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1702 533300 : wi::to_wide (arg1), TYPE_PRECISION (type),
1703 266650 : TREE_TYPE (arg0)))
1704 27202 : return wide_int_to_tree (type, result);
1705 266650 : }
1706 245107 : return NULL_TREE;
1707 : }
1708 :
1709 15253684 : if (mode == arg0_mode
1710 10164897 : && real_cst_p (arg0)
1711 16505414 : && real_cst_p (arg1))
1712 : {
1713 219343 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1714 219343 : REAL_VALUE_TYPE result;
1715 219343 : if (arg0_mode == arg1_mode)
1716 : {
1717 : /* real, real -> real. */
1718 438106 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1719 219053 : TREE_REAL_CST_PTR (arg1),
1720 219053 : REAL_MODE_FORMAT (mode)))
1721 189563 : return build_real (type, result);
1722 : }
1723 290 : else if (arg1_mode == TYPE_MODE (long_double_type_node))
1724 290 : switch (fn)
1725 : {
1726 290 : CASE_CFN_NEXTTOWARD:
1727 : /* real, long double -> real. */
1728 580 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1729 290 : TREE_REAL_CST_PTR (arg1),
1730 290 : REAL_MODE_FORMAT (mode)))
1731 228 : return build_real (type, result);
1732 : break;
1733 : default:
1734 : break;
1735 : }
1736 29552 : return NULL_TREE;
1737 : }
1738 :
1739 15034341 : if (real_cst_p (arg0)
1740 15034341 : && integer_cst_p (arg1))
1741 : {
1742 25703 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1743 25703 : if (mode == arg0_mode)
1744 : {
1745 : /* real, int -> real. */
1746 25700 : REAL_VALUE_TYPE result;
1747 25700 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1748 51400 : wi::to_wide (arg1),
1749 25700 : REAL_MODE_FORMAT (mode)))
1750 5553 : return build_real (type, result);
1751 : }
1752 20150 : return NULL_TREE;
1753 : }
1754 :
1755 15008638 : if (integer_cst_p (arg0)
1756 15008638 : && real_cst_p (arg1))
1757 : {
1758 6434 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1759 6434 : if (mode == arg1_mode)
1760 : {
1761 : /* int, real -> real. */
1762 6434 : REAL_VALUE_TYPE result;
1763 12868 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1764 6434 : TREE_REAL_CST_PTR (arg1),
1765 6434 : REAL_MODE_FORMAT (mode)))
1766 1755 : return build_real (type, result);
1767 : }
1768 4679 : return NULL_TREE;
1769 : }
1770 :
1771 15002204 : if (arg0_mode == arg1_mode
1772 12370007 : && complex_cst_p (arg0)
1773 15034271 : && complex_cst_p (arg1))
1774 : {
1775 32067 : gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1776 32067 : machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1777 32067 : tree arg0r = TREE_REALPART (arg0);
1778 32067 : tree arg0i = TREE_IMAGPART (arg0);
1779 32067 : tree arg1r = TREE_REALPART (arg1);
1780 32067 : tree arg1i = TREE_IMAGPART (arg1);
1781 32067 : if (mode == arg0_mode
1782 32067 : && real_cst_p (arg0r)
1783 32067 : && real_cst_p (arg0i)
1784 32067 : && real_cst_p (arg1r)
1785 64134 : && real_cst_p (arg1i))
1786 : {
1787 : /* complex real, complex real -> complex real. */
1788 32067 : REAL_VALUE_TYPE result_real, result_imag;
1789 64134 : if (fold_const_call_ccc (&result_real, &result_imag, fn,
1790 32067 : TREE_REAL_CST_PTR (arg0r),
1791 32067 : TREE_REAL_CST_PTR (arg0i),
1792 32067 : TREE_REAL_CST_PTR (arg1r),
1793 32067 : TREE_REAL_CST_PTR (arg1i),
1794 32067 : REAL_MODE_FORMAT (inner_mode)))
1795 21470 : return build_complex (type,
1796 10735 : build_real (TREE_TYPE (type), result_real),
1797 21470 : build_real (TREE_TYPE (type), result_imag));
1798 : }
1799 21332 : return NULL_TREE;
1800 : }
1801 :
1802 : return NULL_TREE;
1803 : }
1804 :
1805 : /* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1806 : otherwise return null. TYPE is the type of the return value. */
1807 :
1808 : tree
1809 18160744 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1810 : {
1811 18160744 : const char *p0, *p1;
1812 18160744 : char c;
1813 18160744 : tree_code subcode;
1814 18160744 : switch (fn)
1815 : {
1816 2692 : case CFN_BUILT_IN_STRSPN:
1817 2692 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1818 123 : return build_int_cst (type, strspn (p0, p1));
1819 : return NULL_TREE;
1820 :
1821 2596 : case CFN_BUILT_IN_STRCSPN:
1822 2596 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1823 123 : return build_int_cst (type, strcspn (p0, p1));
1824 : return NULL_TREE;
1825 :
1826 2207035 : case CFN_BUILT_IN_STRCMP:
1827 2207035 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1828 24934 : return build_cmp_result (type, strcmp (p0, p1));
1829 : return NULL_TREE;
1830 :
1831 251 : case CFN_BUILT_IN_STRCASECMP:
1832 251 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1833 : {
1834 7 : int r = strcmp (p0, p1);
1835 7 : if (r == 0)
1836 1 : return build_cmp_result (type, r);
1837 : }
1838 : return NULL_TREE;
1839 :
1840 164003 : case CFN_BUILT_IN_INDEX:
1841 164003 : case CFN_BUILT_IN_STRCHR:
1842 164003 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1843 : {
1844 136 : const char *r = strchr (p0, c);
1845 136 : if (r == NULL)
1846 32 : return build_int_cst (type, 0);
1847 104 : return fold_convert (type,
1848 : fold_build_pointer_plus_hwi (arg0, r - p0));
1849 : }
1850 : return NULL_TREE;
1851 :
1852 154542 : case CFN_BUILT_IN_RINDEX:
1853 154542 : case CFN_BUILT_IN_STRRCHR:
1854 154542 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1855 : {
1856 103 : const char *r = strrchr (p0, c);
1857 103 : if (r == NULL)
1858 35 : return build_int_cst (type, 0);
1859 68 : return fold_convert (type,
1860 : fold_build_pointer_plus_hwi (arg0, r - p0));
1861 : }
1862 : return NULL_TREE;
1863 :
1864 85552 : case CFN_BUILT_IN_STRSTR:
1865 85552 : if ((p1 = c_getstr (arg1)))
1866 : {
1867 6039 : if ((p0 = c_getstr (arg0)))
1868 : {
1869 182 : const char *r = strstr (p0, p1);
1870 182 : if (r == NULL)
1871 38 : return build_int_cst (type, 0);
1872 144 : return fold_convert (type,
1873 : fold_build_pointer_plus_hwi (arg0, r - p0));
1874 : }
1875 5857 : if (*p1 == '\0')
1876 13 : return fold_convert (type, arg0);
1877 : }
1878 : return NULL_TREE;
1879 :
1880 0 : case CFN_FOLD_LEFT_PLUS:
1881 0 : return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1882 :
1883 0 : case CFN_VEC_SHL_INSERT:
1884 0 : return fold_const_vec_shl_insert (type, arg0, arg1);
1885 :
1886 0 : case CFN_VEC_EXTRACT:
1887 0 : return fold_const_vec_extract (type, arg0, arg1);
1888 :
1889 6402 : case CFN_UBSAN_CHECK_ADD:
1890 6402 : case CFN_ADD_OVERFLOW:
1891 6402 : subcode = PLUS_EXPR;
1892 6402 : goto arith_overflow;
1893 :
1894 6317 : case CFN_UBSAN_CHECK_SUB:
1895 6317 : case CFN_SUB_OVERFLOW:
1896 6317 : subcode = MINUS_EXPR;
1897 6317 : goto arith_overflow;
1898 :
1899 5361 : case CFN_UBSAN_CHECK_MUL:
1900 5361 : case CFN_MUL_OVERFLOW:
1901 5361 : subcode = MULT_EXPR;
1902 5361 : goto arith_overflow;
1903 :
1904 18080 : arith_overflow:
1905 18080 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1906 : {
1907 17217 : tree itype
1908 17217 : = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
1909 17217 : bool ovf = false;
1910 17217 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
1911 17217 : fold_convert (itype, arg1));
1912 17217 : if (!r || TREE_CODE (r) != INTEGER_CST)
1913 : return NULL_TREE;
1914 17217 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
1915 : ovf = true;
1916 17217 : if (TREE_OVERFLOW (r))
1917 3434 : r = drop_tree_overflow (r);
1918 17217 : if (itype == type)
1919 : {
1920 2725 : if (ovf)
1921 : return NULL_TREE;
1922 : return r;
1923 : }
1924 : else
1925 14492 : return build_complex (type, r, build_int_cst (itype, ovf));
1926 : }
1927 : return NULL_TREE;
1928 :
1929 15525993 : default:
1930 15525993 : return fold_const_call_1 (fn, type, arg0, arg1);
1931 : }
1932 : }
1933 :
1934 : /* Try to evaluate:
1935 :
1936 : *RESULT = FN (*ARG0, *ARG1, *ARG2)
1937 :
1938 : in format FORMAT. Return true on success. */
1939 :
1940 : static bool
1941 2534 : fold_const_call_ssss (real_value *result, combined_fn fn,
1942 : const real_value *arg0, const real_value *arg1,
1943 : const real_value *arg2, const real_format *format)
1944 : {
1945 2534 : switch (fn)
1946 : {
1947 2534 : CASE_CFN_FMA:
1948 2534 : CASE_CFN_FMA_FN:
1949 2534 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1950 :
1951 0 : case CFN_FMS:
1952 0 : {
1953 0 : real_value new_arg2 = real_value_negate (arg2);
1954 0 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
1955 : }
1956 :
1957 0 : case CFN_FNMA:
1958 0 : {
1959 0 : real_value new_arg0 = real_value_negate (arg0);
1960 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
1961 : }
1962 :
1963 0 : case CFN_FNMS:
1964 0 : {
1965 0 : real_value new_arg0 = real_value_negate (arg0);
1966 0 : real_value new_arg2 = real_value_negate (arg2);
1967 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
1968 : &new_arg2, format);
1969 : }
1970 :
1971 : default:
1972 : return false;
1973 : }
1974 : }
1975 :
1976 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1977 : where the arguments and result are numerical. */
1978 :
1979 : static tree
1980 4380771 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
1981 : {
1982 4380771 : machine_mode mode = TYPE_MODE (type);
1983 4380771 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1984 4380771 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1985 4380771 : machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1986 :
1987 4380771 : if (arg0_mode == arg1_mode
1988 4380771 : && arg0_mode == arg2_mode
1989 1983030 : && real_cst_p (arg0)
1990 2712 : && real_cst_p (arg1)
1991 4383411 : && real_cst_p (arg2))
1992 : {
1993 2534 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1994 2534 : if (mode == arg0_mode)
1995 : {
1996 : /* real, real, real -> real. */
1997 2534 : REAL_VALUE_TYPE result;
1998 5068 : if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1999 2534 : TREE_REAL_CST_PTR (arg1),
2000 2534 : TREE_REAL_CST_PTR (arg2),
2001 2534 : REAL_MODE_FORMAT (mode)))
2002 1060 : return build_real (type, result);
2003 : }
2004 1474 : return NULL_TREE;
2005 : }
2006 :
2007 : return NULL_TREE;
2008 : }
2009 :
2010 : /* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
2011 : success, otherwise return null. TYPE is the type of the return value. */
2012 :
2013 : tree
2014 7141491 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2015 : {
2016 7141491 : const char *p0, *p1;
2017 7141491 : char c;
2018 7141491 : unsigned HOST_WIDE_INT s0, s1, s2 = 0;
2019 7141491 : switch (fn)
2020 : {
2021 44945 : case CFN_BUILT_IN_STRNCMP:
2022 44945 : if (!size_t_cst_p (arg2, &s2))
2023 : return NULL_TREE;
2024 28939 : if (s2 == 0
2025 237 : && !TREE_SIDE_EFFECTS (arg0)
2026 29148 : && !TREE_SIDE_EFFECTS (arg1))
2027 209 : return build_int_cst (type, 0);
2028 28730 : else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
2029 573 : return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
2030 : return NULL_TREE;
2031 :
2032 7999 : case CFN_BUILT_IN_STRNCASECMP:
2033 7999 : if (!size_t_cst_p (arg2, &s2))
2034 : return NULL_TREE;
2035 7678 : if (s2 == 0
2036 9 : && !TREE_SIDE_EFFECTS (arg0)
2037 7683 : && !TREE_SIDE_EFFECTS (arg1))
2038 5 : return build_int_cst (type, 0);
2039 7673 : else if ((p0 = c_getstr (arg0))
2040 724 : && (p1 = c_getstr (arg1))
2041 7813 : && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
2042 3 : return build_int_cst (type, 0);
2043 : return NULL_TREE;
2044 :
2045 2500767 : case CFN_BUILT_IN_BCMP:
2046 2500767 : case CFN_BUILT_IN_MEMCMP:
2047 2500767 : if (!size_t_cst_p (arg2, &s2))
2048 : return NULL_TREE;
2049 1601600 : if (s2 == 0
2050 13066 : && !TREE_SIDE_EFFECTS (arg0)
2051 1614666 : && !TREE_SIDE_EFFECTS (arg1))
2052 13066 : return build_int_cst (type, 0);
2053 1588534 : if ((p0 = getbyterep (arg0, &s0))
2054 12240 : && (p1 = getbyterep (arg1, &s1))
2055 3784 : && s2 <= s0
2056 1591886 : && s2 <= s1)
2057 3351 : return build_cmp_result (type, memcmp (p0, p1, s2));
2058 : return NULL_TREE;
2059 :
2060 206917 : case CFN_BUILT_IN_MEMCHR:
2061 206917 : if (!size_t_cst_p (arg2, &s2))
2062 : return NULL_TREE;
2063 7129 : if (s2 == 0
2064 151 : && !TREE_SIDE_EFFECTS (arg0)
2065 7263 : && !TREE_SIDE_EFFECTS (arg1))
2066 131 : return build_int_cst (type, 0);
2067 6998 : if ((p0 = getbyterep (arg0, &s0))
2068 2024 : && s2 <= s0
2069 8903 : && target_char_cst_p (arg1, &c))
2070 : {
2071 641 : const char *r = (const char *) memchr (p0, c, s2);
2072 641 : if (r == NULL)
2073 251 : return build_int_cst (type, 0);
2074 390 : return fold_convert (type,
2075 : fold_build_pointer_plus_hwi (arg0, r - p0));
2076 : }
2077 : return NULL_TREE;
2078 :
2079 0 : case CFN_WHILE_ULT:
2080 0 : {
2081 0 : poly_uint64 parg0, parg1;
2082 0 : if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
2083 0 : return fold_while_ult (type, parg0, parg1);
2084 : return NULL_TREE;
2085 : }
2086 :
2087 92 : case CFN_UADDC:
2088 92 : case CFN_USUBC:
2089 92 : if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
2090 : {
2091 92 : tree itype = TREE_TYPE (type);
2092 92 : bool ovf = false;
2093 92 : tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
2094 92 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
2095 92 : fold_convert (itype, arg1));
2096 92 : if (!r)
2097 : return NULL_TREE;
2098 92 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
2099 : ovf = true;
2100 92 : tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
2101 92 : if (!r2 || TREE_CODE (r2) != INTEGER_CST)
2102 : return NULL_TREE;
2103 92 : if (arith_overflowed_p (subcode, itype, r, arg2))
2104 0 : ovf = true;
2105 92 : if (TREE_OVERFLOW (r2))
2106 0 : r2 = drop_tree_overflow (r2);
2107 92 : return build_complex (type, r2, build_int_cst (itype, ovf));
2108 : }
2109 : return NULL_TREE;
2110 :
2111 4380771 : default:
2112 4380771 : return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2113 : }
2114 : }
|