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 33423949 : integer_cst_p (tree t)
40 : {
41 33423949 : return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
42 : }
43 :
44 : static inline bool
45 38078921 : real_cst_p (tree t)
46 : {
47 38078921 : return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
48 : }
49 :
50 : static inline bool
51 22212045 : complex_cst_p (tree t)
52 : {
53 22212045 : 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 2780772 : size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
61 : {
62 2780772 : if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 2780617 : && integer_cst_p (t)
64 4440009 : && tree_fits_uhwi_p (t))
65 : {
66 1659237 : *size_out = tree_to_uhwi (t);
67 1659237 : 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 66466 : build_cmp_result (tree type, int res)
78 : {
79 71072 : 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 238201 : 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 238201 : if (!mpfr_number_p (m)
95 223192 : || mpfr_overflow_p ()
96 223192 : || mpfr_underflow_p ()
97 457849 : || (flag_rounding_math && inexact))
98 18638 : return false;
99 :
100 219563 : REAL_VALUE_TYPE tmp;
101 219563 : 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 219563 : if (!real_isfinite (&tmp)
107 219563 : || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
108 : return false;
109 :
110 219563 : real_convert (result, format, &tmp);
111 219563 : 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 107057 : 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 107057 : if (format->b != 2 || !real_isfinite (arg))
129 2742 : return false;
130 :
131 104315 : int prec = format->p;
132 104315 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
133 :
134 104315 : auto_mpfr m (prec);
135 104315 : mpfr_from_real (m, arg, MPFR_RNDN);
136 104315 : mpfr_clear_flags ();
137 104315 : bool inexact = func (m, m, rnd);
138 104315 : bool ok = do_mpfr_ckconv (result, m, inexact, format);
139 :
140 104315 : return ok;
141 104315 : }
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 140349 : 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 140349 : if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
190 11044 : return false;
191 :
192 129305 : int prec = format->p;
193 129305 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
194 129305 : mpfr_t m0, m1;
195 :
196 129305 : mpfr_inits2 (prec, m0, m1, NULL);
197 129305 : mpfr_from_real (m0, arg0, MPFR_RNDN);
198 129305 : mpfr_from_real (m1, arg1, MPFR_RNDN);
199 129305 : mpfr_clear_flags ();
200 129305 : bool inexact = func (m0, m0, m1, rnd);
201 129305 : bool ok = do_mpfr_ckconv (result, m0, inexact, format);
202 129305 : mpfr_clears (m0, m1, NULL);
203 :
204 129305 : 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 123363 : fold_const_pow (real_value *result, const real_value *arg0,
496 : const real_value *arg1, const real_format *format)
497 : {
498 123363 : if (flag_signaling_nans
499 123363 : && (REAL_VALUE_ISSIGNALING_NAN (*arg0)
500 0 : || REAL_VALUE_ISSIGNALING_NAN (*arg1)))
501 0 : return false;
502 :
503 123363 : if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
504 : {
505 113055 : if (flag_errno_math)
506 112692 : 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 10776 : fold_const_nextafter (real_value *result, const real_value *arg0,
534 : const real_value *arg1, const real_format *format)
535 : {
536 10776 : if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
537 10776 : || 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 10776 : if (format->pnan < format->p
543 10776 : || format->b == 10
544 10776 : || !format->has_inf
545 10776 : || !format->has_denorm)
546 : return false;
547 :
548 16512 : 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 10776 : && (flag_trapping_math || flag_errno_math))
552 5736 : return false;
553 : /* Similarly for nextafter (0, 1) raising underflow. */
554 5040 : else if (flag_trapping_math
555 4533 : && arg0->cl == rvc_zero
556 3916 : && 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 373260 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
612 : {
613 373260 : REAL_VALUE_TYPE real;
614 373260 : const char *str = c_getstr (arg);
615 373260 : if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
616 372791 : 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 2118 : fold_const_reduction (tree type, tree arg, tree_code code)
624 : {
625 2118 : unsigned HOST_WIDE_INT nelts;
626 2118 : if (TREE_CODE (arg) != VECTOR_CST
627 2118 : || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
628 0 : return NULL_TREE;
629 :
630 2118 : tree res = VECTOR_CST_ELT (arg, 0);
631 26494 : for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
632 : {
633 24376 : res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
634 24376 : 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 159700 : fold_const_call_ss (real_value *result, combined_fn fn,
721 : const real_value *arg, const real_format *format)
722 : {
723 159700 : switch (fn)
724 : {
725 22407 : CASE_CFN_SQRT:
726 22407 : CASE_CFN_SQRT_FN:
727 22407 : return (real_compare (GE_EXPR, arg, &dconst0)
728 22407 : && 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 1012 : CASE_CFN_SIN:
766 1012 : CASE_CFN_SIN_FN:
767 1012 : return do_mpfr_arg1 (result, mpfr_sin, arg, format);
768 :
769 848 : CASE_CFN_COS:
770 848 : CASE_CFN_COS_FN:
771 848 : 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 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 59445 : CASE_CFN_LOG:
848 59445 : CASE_CFN_LOG_FN:
849 59445 : return (real_compare (GT_EXPR, arg, &dconst0)
850 59445 : && 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 3548266 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1043 : unsigned int precision, tree arg_type)
1044 : {
1045 3548266 : 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 2151 : CASE_CFN_CLZ:
1053 2151 : case CFN_BUILT_IN_CLZG:
1054 2151 : {
1055 2151 : int tmp;
1056 2151 : if (wi::ne_p (arg, 0))
1057 1813 : 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 2151 : *result = wi::shwi (tmp, precision);
1064 2151 : return true;
1065 : }
1066 :
1067 1145 : CASE_CFN_CTZ:
1068 1145 : case CFN_BUILT_IN_CTZG:
1069 1145 : {
1070 1145 : int tmp;
1071 1145 : if (wi::ne_p (arg, 0))
1072 901 : 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 1145 : *result = wi::shwi (tmp, precision);
1079 1145 : 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 39436 : CASE_CFN_POPCOUNT:
1088 39436 : case CFN_BUILT_IN_POPCOUNTG:
1089 39436 : *result = wi::shwi (wi::popcount (arg), precision);
1090 39436 : 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_BUILT_IN_BSWAP16:
1098 738 : case CFN_BUILT_IN_BSWAP32:
1099 738 : case CFN_BUILT_IN_BSWAP64:
1100 738 : case CFN_BUILT_IN_BSWAP128:
1101 1476 : *result = wi::bswap (wide_int::from (arg, precision,
1102 1476 : TYPE_SIGN (arg_type)));
1103 738 : return true;
1104 :
1105 47 : case CFN_BUILT_IN_BITREVERSE8:
1106 47 : case CFN_BUILT_IN_BITREVERSE16:
1107 47 : case CFN_BUILT_IN_BITREVERSE32:
1108 47 : case CFN_BUILT_IN_BITREVERSE64:
1109 47 : case CFN_BUILT_IN_BITREVERSE128:
1110 94 : *result = wi::bitreverse (wide_int::from (arg, precision,
1111 94 : TYPE_SIGN (arg_type)));
1112 47 : return true;
1113 :
1114 : default:
1115 : return false;
1116 : }
1117 : }
1118 :
1119 : /* Try to evaluate:
1120 :
1121 : RESULT = FN (*ARG)
1122 :
1123 : where FORMAT is the format of ARG and of the real and imaginary parts
1124 : of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
1125 : true on success. */
1126 :
1127 : static bool
1128 146 : fold_const_call_cs (real_value *result_real, real_value *result_imag,
1129 : combined_fn fn, const real_value *arg,
1130 : const real_format *format)
1131 : {
1132 0 : switch (fn)
1133 : {
1134 146 : CASE_CFN_CEXPI:
1135 : /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1136 146 : return do_mpfr_sincos (result_imag, result_real, arg, format);
1137 :
1138 : default:
1139 : return false;
1140 : }
1141 : }
1142 :
1143 : /* Try to evaluate:
1144 :
1145 : *RESULT = fn (ARG)
1146 :
1147 : where FORMAT is the format of RESULT and of the real and imaginary parts
1148 : of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
1149 : success. */
1150 :
1151 : static bool
1152 2292 : fold_const_call_sc (real_value *result, combined_fn fn,
1153 : const real_value *arg_real, const real_value *arg_imag,
1154 : const real_format *format)
1155 : {
1156 0 : switch (fn)
1157 : {
1158 1156 : CASE_CFN_CABS:
1159 1156 : CASE_CFN_CABS_FN:
1160 1156 : return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1161 :
1162 : default:
1163 : return false;
1164 : }
1165 : }
1166 :
1167 : /* Try to evaluate:
1168 :
1169 : RESULT = fn (ARG)
1170 :
1171 : where FORMAT is the format of the real and imaginary parts of RESULT
1172 : (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1173 : Return true on success. */
1174 :
1175 : static bool
1176 39622 : fold_const_call_cc (real_value *result_real, real_value *result_imag,
1177 : combined_fn fn, const real_value *arg_real,
1178 : const real_value *arg_imag, const real_format *format)
1179 : {
1180 39622 : switch (fn)
1181 : {
1182 686 : CASE_CFN_CCOS:
1183 686 : CASE_CFN_CCOS_FN:
1184 686 : return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1185 686 : arg_real, arg_imag, format);
1186 :
1187 676 : CASE_CFN_CCOSH:
1188 676 : CASE_CFN_CCOSH_FN:
1189 676 : return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1190 676 : arg_real, arg_imag, format);
1191 :
1192 683 : CASE_CFN_CPROJ:
1193 683 : CASE_CFN_CPROJ_FN:
1194 683 : if (real_isinf (arg_real) || real_isinf (arg_imag))
1195 : {
1196 436 : *result_real = dconstinf;
1197 436 : *result_imag = dconst0;
1198 436 : result_imag->sign = arg_imag->sign;
1199 : }
1200 : else
1201 : {
1202 247 : *result_real = *arg_real;
1203 247 : *result_imag = *arg_imag;
1204 : }
1205 : return true;
1206 :
1207 701 : CASE_CFN_CSIN:
1208 701 : CASE_CFN_CSIN_FN:
1209 701 : return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1210 701 : arg_real, arg_imag, format);
1211 :
1212 676 : CASE_CFN_CSINH:
1213 676 : CASE_CFN_CSINH_FN:
1214 676 : return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1215 676 : arg_real, arg_imag, format);
1216 :
1217 698 : CASE_CFN_CTAN:
1218 698 : CASE_CFN_CTAN_FN:
1219 698 : return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1220 698 : arg_real, arg_imag, format);
1221 :
1222 676 : CASE_CFN_CTANH:
1223 676 : CASE_CFN_CTANH_FN:
1224 676 : return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1225 676 : arg_real, arg_imag, format);
1226 :
1227 777 : CASE_CFN_CLOG:
1228 777 : CASE_CFN_CLOG_FN:
1229 777 : return do_mpc_arg1 (result_real, result_imag, mpc_log,
1230 777 : arg_real, arg_imag, format);
1231 :
1232 3053 : CASE_CFN_CSQRT:
1233 3053 : CASE_CFN_CSQRT_FN:
1234 3053 : return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1235 3053 : arg_real, arg_imag, format);
1236 :
1237 679 : CASE_CFN_CASIN:
1238 679 : CASE_CFN_CASIN_FN:
1239 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1240 679 : arg_real, arg_imag, format);
1241 :
1242 728 : CASE_CFN_CACOS:
1243 728 : CASE_CFN_CACOS_FN:
1244 728 : return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1245 728 : arg_real, arg_imag, format);
1246 :
1247 679 : CASE_CFN_CATAN:
1248 679 : CASE_CFN_CATAN_FN:
1249 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1250 679 : arg_real, arg_imag, format);
1251 :
1252 679 : CASE_CFN_CASINH:
1253 679 : CASE_CFN_CASINH_FN:
1254 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1255 679 : arg_real, arg_imag, format);
1256 :
1257 745 : CASE_CFN_CACOSH:
1258 745 : CASE_CFN_CACOSH_FN:
1259 745 : return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1260 745 : arg_real, arg_imag, format);
1261 :
1262 679 : CASE_CFN_CATANH:
1263 679 : CASE_CFN_CATANH_FN:
1264 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1265 679 : arg_real, arg_imag, format);
1266 :
1267 1583 : CASE_CFN_CEXP:
1268 1583 : CASE_CFN_CEXP_FN:
1269 1583 : return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1270 1583 : arg_real, arg_imag, format);
1271 :
1272 : default:
1273 : return false;
1274 : }
1275 : }
1276 :
1277 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1278 : where the arguments and result are numerical. */
1279 :
1280 : static tree
1281 14960554 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
1282 : {
1283 14960554 : machine_mode mode = TYPE_MODE (type);
1284 14960554 : machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1285 :
1286 14960554 : if (integer_cst_p (arg))
1287 : {
1288 3663079 : if (SCALAR_INT_MODE_P (mode))
1289 : {
1290 3548266 : wide_int result;
1291 3548266 : if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1292 3548266 : TYPE_PRECISION (type), TREE_TYPE (arg)))
1293 44965 : return wide_int_to_tree (type, result);
1294 3548266 : }
1295 3618114 : return NULL_TREE;
1296 : }
1297 :
1298 11297475 : if (real_cst_p (arg))
1299 : {
1300 177322 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1301 177322 : if (mode == arg_mode)
1302 : {
1303 : /* real -> real. */
1304 159700 : REAL_VALUE_TYPE result;
1305 159700 : if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1306 159700 : REAL_MODE_FORMAT (mode)))
1307 98447 : return build_real (type, result);
1308 : }
1309 17622 : else if (COMPLEX_MODE_P (mode)
1310 17768 : && GET_MODE_INNER (mode) == arg_mode)
1311 : {
1312 : /* real -> complex real. */
1313 146 : REAL_VALUE_TYPE result_real, result_imag;
1314 292 : if (fold_const_call_cs (&result_real, &result_imag, fn,
1315 146 : TREE_REAL_CST_PTR (arg),
1316 146 : REAL_MODE_FORMAT (arg_mode)))
1317 292 : return build_complex (type,
1318 146 : build_real (TREE_TYPE (type), result_real),
1319 292 : build_real (TREE_TYPE (type), result_imag));
1320 : }
1321 17476 : else if (INTEGRAL_TYPE_P (type))
1322 : {
1323 : /* real -> int. */
1324 17473 : wide_int result;
1325 17473 : if (fold_const_call_ss (&result, fn,
1326 17473 : TREE_REAL_CST_PTR (arg),
1327 17473 : TYPE_PRECISION (type),
1328 17473 : REAL_MODE_FORMAT (arg_mode)))
1329 11054 : return wide_int_to_tree (type, result);
1330 17473 : }
1331 67675 : return NULL_TREE;
1332 : }
1333 :
1334 11120153 : if (complex_cst_p (arg))
1335 : {
1336 41914 : gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1337 41914 : machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1338 41914 : tree argr = TREE_REALPART (arg);
1339 41914 : tree argi = TREE_IMAGPART (arg);
1340 41914 : if (mode == arg_mode
1341 39622 : && real_cst_p (argr)
1342 81536 : && real_cst_p (argi))
1343 : {
1344 : /* complex real -> complex real. */
1345 39622 : REAL_VALUE_TYPE result_real, result_imag;
1346 79244 : if (fold_const_call_cc (&result_real, &result_imag, fn,
1347 39622 : TREE_REAL_CST_PTR (argr),
1348 39622 : TREE_REAL_CST_PTR (argi),
1349 39622 : REAL_MODE_FORMAT (inner_mode)))
1350 20972 : return build_complex (type,
1351 10486 : build_real (TREE_TYPE (type), result_real),
1352 20972 : build_real (TREE_TYPE (type), result_imag));
1353 : }
1354 31428 : if (mode == inner_mode
1355 2292 : && real_cst_p (argr)
1356 33720 : && real_cst_p (argi))
1357 : {
1358 : /* complex real -> real. */
1359 2292 : REAL_VALUE_TYPE result;
1360 4584 : if (fold_const_call_sc (&result, fn,
1361 2292 : TREE_REAL_CST_PTR (argr),
1362 2292 : TREE_REAL_CST_PTR (argi),
1363 2292 : REAL_MODE_FORMAT (inner_mode)))
1364 1156 : return build_real (type, result);
1365 : }
1366 30272 : return NULL_TREE;
1367 : }
1368 :
1369 : return NULL_TREE;
1370 : }
1371 :
1372 : /* Try to fold FN (ARG) to a constant. Return the constant on success,
1373 : otherwise return null. TYPE is the type of the return value. */
1374 :
1375 : tree
1376 15877759 : fold_const_call (combined_fn fn, tree type, tree arg)
1377 : {
1378 15877759 : switch (fn)
1379 : {
1380 539639 : case CFN_BUILT_IN_STRLEN:
1381 539639 : if (const char *str = c_getstr (arg))
1382 90983 : return build_int_cst (type, strlen (str));
1383 : return NULL_TREE;
1384 :
1385 216731 : CASE_CFN_NAN:
1386 216731 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1387 216731 : case CFN_BUILT_IN_NAND32:
1388 216731 : case CFN_BUILT_IN_NAND64:
1389 216731 : case CFN_BUILT_IN_NAND128:
1390 216731 : case CFN_BUILT_IN_NAND64X:
1391 216731 : return fold_const_builtin_nan (type, arg, true);
1392 :
1393 156529 : CASE_CFN_NANS:
1394 156529 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1395 156529 : case CFN_BUILT_IN_NANSF16B:
1396 156529 : case CFN_BUILT_IN_NANSD32:
1397 156529 : case CFN_BUILT_IN_NANSD64:
1398 156529 : case CFN_BUILT_IN_NANSD128:
1399 156529 : case CFN_BUILT_IN_NANSD64X:
1400 156529 : return fold_const_builtin_nan (type, arg, false);
1401 :
1402 1713 : case CFN_REDUC_PLUS:
1403 1713 : return fold_const_reduction (type, arg, PLUS_EXPR);
1404 :
1405 47 : case CFN_REDUC_MAX:
1406 47 : return fold_const_reduction (type, arg, MAX_EXPR);
1407 :
1408 67 : case CFN_REDUC_MIN:
1409 67 : return fold_const_reduction (type, arg, MIN_EXPR);
1410 :
1411 34 : case CFN_REDUC_AND:
1412 34 : return fold_const_reduction (type, arg, BIT_AND_EXPR);
1413 :
1414 251 : case CFN_REDUC_IOR:
1415 251 : return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1416 :
1417 6 : case CFN_REDUC_XOR:
1418 6 : return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1419 :
1420 2188 : case CFN_VEC_CONVERT:
1421 2188 : return fold_const_vec_convert (type, arg);
1422 :
1423 14960554 : default:
1424 14960554 : return fold_const_call_1 (fn, type, arg);
1425 : }
1426 : }
1427 :
1428 : /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1429 : of type TYPE. */
1430 :
1431 : static tree
1432 0 : fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1433 : {
1434 0 : if (TREE_CODE (arg1) != VECTOR_CST)
1435 : return NULL_TREE;
1436 :
1437 0 : unsigned HOST_WIDE_INT nelts;
1438 0 : if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1439 : return NULL_TREE;
1440 :
1441 0 : for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1442 : {
1443 0 : arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1444 0 : if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1445 : return NULL_TREE;
1446 : }
1447 : return arg0;
1448 : }
1449 :
1450 : /* Fold a call to IFN_VEC_SHL_INSERT (ARG0, ARG1), returning a value
1451 : of type TYPE. */
1452 :
1453 : static tree
1454 0 : fold_const_vec_shl_insert (tree, tree arg0, tree arg1)
1455 : {
1456 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1457 : return NULL_TREE;
1458 :
1459 : /* vec_shl_insert ( dup(CST), CST) -> dup (CST). */
1460 0 : if (tree elem = uniform_vector_p (arg0))
1461 : {
1462 0 : if (operand_equal_p (elem, arg1))
1463 : return arg0;
1464 : }
1465 :
1466 : return NULL_TREE;
1467 : }
1468 :
1469 : /* Fold a call to IFN_VEC_EXTRACT (ARG0, ARG1), returning a value
1470 : of type TYPE.
1471 :
1472 : Right now this is only handling uniform vectors, so ARG1 is not
1473 : used. But it could be easily adjusted in the future to handle
1474 : non-uniform vectors by extracting the relevant element. */
1475 :
1476 : static tree
1477 0 : fold_const_vec_extract (tree, tree arg0, tree)
1478 : {
1479 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1480 : return NULL_TREE;
1481 :
1482 : /* vec_extract ( dup(CST), CST) -> dup (CST). */
1483 0 : if (tree elem = uniform_vector_p (arg0))
1484 : return elem;
1485 :
1486 : return NULL_TREE;
1487 : }
1488 :
1489 : /* Try to fold scalar integer IFN_SAT_ADD with operands OP0 and OP1. */
1490 :
1491 : static tree
1492 0 : fold_internal_fn_sat_add (tree type, tree op0, tree op1)
1493 : {
1494 0 : if (!INTEGRAL_NB_TYPE_P (type))
1495 : return NULL_TREE;
1496 :
1497 0 : if (TREE_CODE (op0) != INTEGER_CST
1498 0 : || TREE_CODE (op1) != INTEGER_CST)
1499 : return NULL_TREE;
1500 :
1501 0 : wi::overflow_type overflow;
1502 0 : unsigned int prec = TYPE_PRECISION (type);
1503 0 : wide_int result = wi::add (wi::to_wide (op0), wi::to_wide (op1),
1504 0 : TYPE_SIGN (type), &overflow);
1505 :
1506 0 : if (overflow != wi::OVF_NONE)
1507 : {
1508 0 : if (TYPE_UNSIGNED (type))
1509 0 : result = wi::max_value (prec, UNSIGNED);
1510 0 : else if (overflow == wi::OVF_OVERFLOW)
1511 0 : result = wi::max_value (prec, SIGNED);
1512 0 : else if (overflow == wi::OVF_UNDERFLOW)
1513 0 : result = wi::min_value (prec, SIGNED);
1514 : else
1515 : return NULL_TREE;
1516 : }
1517 :
1518 0 : return wide_int_to_tree (type, result);
1519 0 : }
1520 :
1521 : /* Try to evaluate:
1522 :
1523 : *RESULT = FN (*ARG0, *ARG1)
1524 :
1525 : in format FORMAT. Return true on success. */
1526 :
1527 : static bool
1528 220597 : fold_const_call_sss (real_value *result, combined_fn fn,
1529 : const real_value *arg0, const real_value *arg1,
1530 : const real_format *format)
1531 : {
1532 220597 : switch (fn)
1533 : {
1534 6774 : CASE_CFN_DREM:
1535 6774 : CASE_CFN_REMAINDER:
1536 6774 : CASE_CFN_REMAINDER_FN:
1537 6774 : return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1538 :
1539 983 : CASE_CFN_ATAN2:
1540 983 : CASE_CFN_ATAN2_FN:
1541 983 : return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1542 :
1543 : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
1544 84 : CASE_CFN_ATAN2PI:
1545 84 : CASE_CFN_ATAN2PI_FN:
1546 84 : return do_mpfr_arg2 (result, mpfr_atan2pi, arg0, arg1, format);
1547 : #endif
1548 :
1549 572 : CASE_CFN_FDIM:
1550 572 : CASE_CFN_FDIM_FN:
1551 572 : return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1552 :
1553 517 : CASE_CFN_FMOD:
1554 517 : CASE_CFN_FMOD_FN:
1555 517 : return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
1556 :
1557 578 : CASE_CFN_HYPOT:
1558 578 : CASE_CFN_HYPOT_FN:
1559 578 : return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1560 :
1561 70628 : CASE_CFN_COPYSIGN:
1562 70628 : CASE_CFN_COPYSIGN_FN:
1563 70628 : *result = *arg0;
1564 70628 : real_copysign (result, arg1);
1565 70628 : return true;
1566 :
1567 3161 : CASE_CFN_FMIN:
1568 3161 : CASE_CFN_FMIN_FN:
1569 3161 : return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1570 :
1571 3161 : CASE_CFN_FMAX:
1572 3161 : CASE_CFN_FMAX_FN:
1573 3161 : return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1574 :
1575 123363 : CASE_CFN_POW:
1576 123363 : CASE_CFN_POW_FN:
1577 123363 : return fold_const_pow (result, arg0, arg1, format);
1578 :
1579 10776 : CASE_CFN_NEXTAFTER:
1580 10776 : CASE_CFN_NEXTAFTER_FN:
1581 10776 : case CFN_BUILT_IN_NEXTAFTERF16B:
1582 10776 : CASE_CFN_NEXTTOWARD:
1583 10776 : return fold_const_nextafter (result, arg0, arg1, format);
1584 :
1585 : default:
1586 : return false;
1587 : }
1588 : }
1589 :
1590 : /* Try to evaluate:
1591 :
1592 : *RESULT = FN (*ARG0, ARG1)
1593 :
1594 : where FORMAT is the format of *RESULT and *ARG0. Return true on
1595 : success. */
1596 :
1597 : static bool
1598 25700 : fold_const_call_sss (real_value *result, combined_fn fn,
1599 : const real_value *arg0, const wide_int_ref &arg1,
1600 : const real_format *format)
1601 : {
1602 25700 : switch (fn)
1603 : {
1604 7912 : CASE_CFN_LDEXP:
1605 7912 : CASE_CFN_LDEXP_FN:
1606 7912 : return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1607 :
1608 17349 : CASE_CFN_SCALBN:
1609 17349 : CASE_CFN_SCALBN_FN:
1610 17349 : CASE_CFN_SCALBLN:
1611 17349 : CASE_CFN_SCALBLN_FN:
1612 17349 : return (format->b == 2
1613 17349 : && fold_const_builtin_load_exponent (result, arg0, arg1,
1614 : format));
1615 :
1616 430 : CASE_CFN_POWI:
1617 : /* Avoid the folding if flag_signaling_nans is on and
1618 : operand is a signaling NaN. */
1619 430 : if (!flag_unsafe_math_optimizations
1620 417 : && flag_signaling_nans
1621 445 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1622 : return false;
1623 :
1624 430 : real_powi (result, format, arg0, arg1.to_shwi ());
1625 430 : return true;
1626 :
1627 : default:
1628 : return false;
1629 : }
1630 : }
1631 :
1632 : /* Try to evaluate:
1633 :
1634 : *RESULT = FN (ARG0, *ARG1)
1635 :
1636 : where FORMAT is the format of *RESULT and *ARG1. Return true on
1637 : success. */
1638 :
1639 : static bool
1640 6434 : fold_const_call_sss (real_value *result, combined_fn fn,
1641 : const wide_int_ref &arg0, const real_value *arg1,
1642 : const real_format *format)
1643 : {
1644 6434 : switch (fn)
1645 : {
1646 1220 : CASE_CFN_JN:
1647 1220 : return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1648 :
1649 5205 : CASE_CFN_YN:
1650 5205 : return (real_compare (GT_EXPR, arg1, &dconst0)
1651 5205 : && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1652 :
1653 : default:
1654 : return false;
1655 : }
1656 : }
1657 :
1658 : /* Try to evaluate:
1659 :
1660 : *RESULT = FN (ARG0, ARG1)
1661 :
1662 : where ARG_TYPE is the type of ARG0 and PRECISION is the number of bits in
1663 : the result. Return true on success. */
1664 :
1665 : static bool
1666 314972 : fold_const_call_sss (wide_int *result, combined_fn fn,
1667 : const wide_int_ref &arg0, const wide_int_ref &arg1,
1668 : unsigned int precision, tree arg_type ATTRIBUTE_UNUSED)
1669 : {
1670 314972 : switch (fn)
1671 : {
1672 14762 : case CFN_CLZ:
1673 14762 : case CFN_BUILT_IN_CLZG:
1674 14762 : {
1675 14762 : int tmp;
1676 14762 : if (wi::ne_p (arg0, 0))
1677 14638 : tmp = wi::clz (arg0);
1678 : else
1679 124 : tmp = arg1.to_shwi ();
1680 14762 : *result = wi::shwi (tmp, precision);
1681 14762 : return true;
1682 : }
1683 :
1684 11571 : case CFN_CTZ:
1685 11571 : case CFN_BUILT_IN_CTZG:
1686 11571 : {
1687 11571 : int tmp;
1688 11571 : if (wi::ne_p (arg0, 0))
1689 11479 : tmp = wi::ctz (arg0);
1690 : else
1691 92 : tmp = arg1.to_shwi ();
1692 11571 : *result = wi::shwi (tmp, precision);
1693 11571 : return true;
1694 : }
1695 :
1696 : default:
1697 : return false;
1698 : }
1699 : }
1700 :
1701 : /* Try to evaluate:
1702 :
1703 : RESULT = fn (ARG0, ARG1)
1704 :
1705 : where FORMAT is the format of the real and imaginary parts of RESULT
1706 : (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1707 : and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1708 :
1709 : static bool
1710 32067 : fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1711 : combined_fn fn, const real_value *arg0_real,
1712 : const real_value *arg0_imag, const real_value *arg1_real,
1713 : const real_value *arg1_imag, const real_format *format)
1714 : {
1715 0 : switch (fn)
1716 : {
1717 32067 : CASE_CFN_CPOW:
1718 32067 : CASE_CFN_CPOW_FN:
1719 32067 : return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1720 0 : arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1721 :
1722 : default:
1723 : return false;
1724 : }
1725 : }
1726 :
1727 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1728 : where the arguments and result are numerical. */
1729 :
1730 : static tree
1731 14228473 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1732 : {
1733 14228473 : machine_mode mode = TYPE_MODE (type);
1734 14228473 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1735 14228473 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1736 :
1737 14228473 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1738 : {
1739 320641 : if (SCALAR_INT_MODE_P (mode))
1740 : {
1741 314972 : wide_int result;
1742 314972 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1743 629944 : wi::to_wide (arg1), TYPE_PRECISION (type),
1744 314972 : TREE_TYPE (arg0)))
1745 26333 : return wide_int_to_tree (type, result);
1746 314972 : }
1747 294308 : return NULL_TREE;
1748 : }
1749 :
1750 13907832 : if (mode == arg0_mode
1751 9761963 : && real_cst_p (arg0)
1752 15160448 : && real_cst_p (arg1))
1753 : {
1754 220597 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1755 220597 : REAL_VALUE_TYPE result;
1756 220597 : if (arg0_mode == arg1_mode)
1757 : {
1758 : /* real, real -> real. */
1759 440614 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1760 220307 : TREE_REAL_CST_PTR (arg1),
1761 220307 : REAL_MODE_FORMAT (mode)))
1762 190535 : return build_real (type, result);
1763 : }
1764 290 : else if (arg1_mode == TYPE_MODE (long_double_type_node))
1765 290 : switch (fn)
1766 : {
1767 290 : CASE_CFN_NEXTTOWARD:
1768 : /* real, long double -> real. */
1769 580 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1770 290 : TREE_REAL_CST_PTR (arg1),
1771 290 : REAL_MODE_FORMAT (mode)))
1772 228 : return build_real (type, result);
1773 : break;
1774 : default:
1775 : break;
1776 : }
1777 29834 : return NULL_TREE;
1778 : }
1779 :
1780 13687235 : if (real_cst_p (arg0)
1781 13687235 : && integer_cst_p (arg1))
1782 : {
1783 25703 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1784 25703 : if (mode == arg0_mode)
1785 : {
1786 : /* real, int -> real. */
1787 25700 : REAL_VALUE_TYPE result;
1788 25700 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1789 51400 : wi::to_wide (arg1),
1790 25700 : REAL_MODE_FORMAT (mode)))
1791 5553 : return build_real (type, result);
1792 : }
1793 20150 : return NULL_TREE;
1794 : }
1795 :
1796 13661532 : if (integer_cst_p (arg0)
1797 13661532 : && real_cst_p (arg1))
1798 : {
1799 6434 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1800 6434 : if (mode == arg1_mode)
1801 : {
1802 : /* int, real -> real. */
1803 6434 : REAL_VALUE_TYPE result;
1804 12868 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1805 6434 : TREE_REAL_CST_PTR (arg1),
1806 6434 : REAL_MODE_FORMAT (mode)))
1807 1755 : return build_real (type, result);
1808 : }
1809 4679 : return NULL_TREE;
1810 : }
1811 :
1812 13655098 : if (arg0_mode == arg1_mode
1813 11059825 : && complex_cst_p (arg0)
1814 13687165 : && complex_cst_p (arg1))
1815 : {
1816 32067 : gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1817 32067 : machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1818 32067 : tree arg0r = TREE_REALPART (arg0);
1819 32067 : tree arg0i = TREE_IMAGPART (arg0);
1820 32067 : tree arg1r = TREE_REALPART (arg1);
1821 32067 : tree arg1i = TREE_IMAGPART (arg1);
1822 32067 : if (mode == arg0_mode
1823 32067 : && real_cst_p (arg0r)
1824 32067 : && real_cst_p (arg0i)
1825 32067 : && real_cst_p (arg1r)
1826 64134 : && real_cst_p (arg1i))
1827 : {
1828 : /* complex real, complex real -> complex real. */
1829 32067 : REAL_VALUE_TYPE result_real, result_imag;
1830 64134 : if (fold_const_call_ccc (&result_real, &result_imag, fn,
1831 32067 : TREE_REAL_CST_PTR (arg0r),
1832 32067 : TREE_REAL_CST_PTR (arg0i),
1833 32067 : TREE_REAL_CST_PTR (arg1r),
1834 32067 : TREE_REAL_CST_PTR (arg1i),
1835 32067 : REAL_MODE_FORMAT (inner_mode)))
1836 21470 : return build_complex (type,
1837 10735 : build_real (TREE_TYPE (type), result_real),
1838 21470 : build_real (TREE_TYPE (type), result_imag));
1839 : }
1840 21332 : return NULL_TREE;
1841 : }
1842 :
1843 : return NULL_TREE;
1844 : }
1845 :
1846 : /* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1847 : otherwise return null. TYPE is the type of the return value. */
1848 :
1849 : tree
1850 16869103 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1851 : {
1852 16869103 : const char *p0, *p1;
1853 16869103 : char c;
1854 16869103 : tree_code subcode;
1855 16869103 : switch (fn)
1856 : {
1857 2692 : case CFN_BUILT_IN_STRSPN:
1858 2692 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1859 123 : return build_int_cst (type, strspn (p0, p1));
1860 : return NULL_TREE;
1861 :
1862 2596 : case CFN_BUILT_IN_STRCSPN:
1863 2596 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1864 123 : return build_int_cst (type, strcspn (p0, p1));
1865 : return NULL_TREE;
1866 :
1867 2209309 : case CFN_BUILT_IN_STRCMP:
1868 2209309 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1869 24934 : return build_cmp_result (type, strcmp (p0, p1));
1870 : return NULL_TREE;
1871 :
1872 269 : case CFN_BUILT_IN_STRCASECMP:
1873 269 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1874 : {
1875 10 : int r = strcmp (p0, p1);
1876 10 : if (r == 0)
1877 1 : return build_cmp_result (type, r);
1878 : }
1879 : return NULL_TREE;
1880 :
1881 165680 : case CFN_BUILT_IN_INDEX:
1882 165680 : case CFN_BUILT_IN_STRCHR:
1883 165680 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1884 : {
1885 136 : const char *r = strchr (p0, c);
1886 136 : if (r == NULL)
1887 32 : return build_int_cst (type, 0);
1888 104 : return fold_convert (type,
1889 : fold_build_pointer_plus_hwi (arg0, r - p0));
1890 : }
1891 : return NULL_TREE;
1892 :
1893 155891 : case CFN_BUILT_IN_RINDEX:
1894 155891 : case CFN_BUILT_IN_STRRCHR:
1895 155891 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1896 : {
1897 103 : const char *r = strrchr (p0, c);
1898 103 : if (r == NULL)
1899 35 : return build_int_cst (type, 0);
1900 68 : return fold_convert (type,
1901 : fold_build_pointer_plus_hwi (arg0, r - p0));
1902 : }
1903 : return NULL_TREE;
1904 :
1905 86100 : case CFN_BUILT_IN_STRSTR:
1906 86100 : if ((p1 = c_getstr (arg1)))
1907 : {
1908 5951 : if ((p0 = c_getstr (arg0)))
1909 : {
1910 182 : const char *r = strstr (p0, p1);
1911 182 : if (r == NULL)
1912 38 : return build_int_cst (type, 0);
1913 144 : return fold_convert (type,
1914 : fold_build_pointer_plus_hwi (arg0, r - p0));
1915 : }
1916 5769 : if (*p1 == '\0')
1917 13 : return fold_convert (type, arg0);
1918 : }
1919 : return NULL_TREE;
1920 :
1921 0 : case CFN_FOLD_LEFT_PLUS:
1922 0 : return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1923 :
1924 0 : case CFN_VEC_SHL_INSERT:
1925 0 : return fold_const_vec_shl_insert (type, arg0, arg1);
1926 :
1927 0 : case CFN_VEC_EXTRACT:
1928 0 : return fold_const_vec_extract (type, arg0, arg1);
1929 :
1930 0 : case CFN_SAT_ADD:
1931 0 : return fold_internal_fn_sat_add (type, arg0, arg1);
1932 :
1933 6398 : case CFN_UBSAN_CHECK_ADD:
1934 6398 : case CFN_ADD_OVERFLOW:
1935 6398 : subcode = PLUS_EXPR;
1936 6398 : goto arith_overflow;
1937 :
1938 6317 : case CFN_UBSAN_CHECK_SUB:
1939 6317 : case CFN_SUB_OVERFLOW:
1940 6317 : subcode = MINUS_EXPR;
1941 6317 : goto arith_overflow;
1942 :
1943 5378 : case CFN_UBSAN_CHECK_MUL:
1944 5378 : case CFN_MUL_OVERFLOW:
1945 5378 : subcode = MULT_EXPR;
1946 5378 : goto arith_overflow;
1947 :
1948 18093 : arith_overflow:
1949 18093 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1950 : {
1951 17234 : tree itype
1952 17234 : = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
1953 17234 : bool ovf = false;
1954 17234 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
1955 17234 : fold_convert (itype, arg1));
1956 17234 : if (!r || TREE_CODE (r) != INTEGER_CST)
1957 : return NULL_TREE;
1958 17234 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
1959 : ovf = true;
1960 17234 : if (TREE_OVERFLOW (r))
1961 3434 : r = drop_tree_overflow (r);
1962 17234 : if (itype == type)
1963 : {
1964 2737 : if (ovf)
1965 : return NULL_TREE;
1966 : return r;
1967 : }
1968 : else
1969 14497 : return build_complex (type, r, build_int_cst (itype, ovf));
1970 : }
1971 : return NULL_TREE;
1972 :
1973 14228473 : default:
1974 14228473 : return fold_const_call_1 (fn, type, arg0, arg1);
1975 : }
1976 : }
1977 :
1978 : /* Try to evaluate:
1979 :
1980 : *RESULT = FN (*ARG0, *ARG1, *ARG2)
1981 :
1982 : in format FORMAT. Return true on success. */
1983 :
1984 : static bool
1985 2534 : fold_const_call_ssss (real_value *result, combined_fn fn,
1986 : const real_value *arg0, const real_value *arg1,
1987 : const real_value *arg2, const real_format *format)
1988 : {
1989 2534 : switch (fn)
1990 : {
1991 2534 : CASE_CFN_FMA:
1992 2534 : CASE_CFN_FMA_FN:
1993 2534 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1994 :
1995 0 : case CFN_FMS:
1996 0 : {
1997 0 : real_value new_arg2 = real_value_negate (arg2);
1998 0 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
1999 : }
2000 :
2001 0 : case CFN_FNMA:
2002 0 : {
2003 0 : real_value new_arg0 = real_value_negate (arg0);
2004 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
2005 : }
2006 :
2007 0 : case CFN_FNMS:
2008 0 : {
2009 0 : real_value new_arg0 = real_value_negate (arg0);
2010 0 : real_value new_arg2 = real_value_negate (arg2);
2011 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
2012 : &new_arg2, format);
2013 : }
2014 :
2015 : default:
2016 : return false;
2017 : }
2018 : }
2019 :
2020 : /* Subroutine of fold_const_call, with the same interface. Handle cases
2021 : where the arguments and result are numerical. */
2022 :
2023 : static tree
2024 4139183 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2025 : {
2026 4139183 : machine_mode mode = TYPE_MODE (type);
2027 4139183 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
2028 4139183 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
2029 4139183 : machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
2030 :
2031 4139183 : if (arg0_mode == arg1_mode
2032 4139183 : && arg0_mode == arg2_mode
2033 1798179 : && real_cst_p (arg0)
2034 2712 : && real_cst_p (arg1)
2035 4141823 : && real_cst_p (arg2))
2036 : {
2037 2534 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
2038 2534 : if (mode == arg0_mode)
2039 : {
2040 : /* real, real, real -> real. */
2041 2534 : REAL_VALUE_TYPE result;
2042 5068 : if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
2043 2534 : TREE_REAL_CST_PTR (arg1),
2044 2534 : TREE_REAL_CST_PTR (arg2),
2045 2534 : REAL_MODE_FORMAT (mode)))
2046 1060 : return build_real (type, result);
2047 : }
2048 1474 : return NULL_TREE;
2049 : }
2050 :
2051 : return NULL_TREE;
2052 : }
2053 :
2054 : /* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
2055 : success, otherwise return null. TYPE is the type of the return value. */
2056 :
2057 : tree
2058 6920047 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2059 : {
2060 6920047 : const char *p0, *p1;
2061 6920047 : char c;
2062 6920047 : unsigned HOST_WIDE_INT s0, s1, s2 = 0;
2063 6920047 : switch (fn)
2064 : {
2065 45003 : case CFN_BUILT_IN_STRNCMP:
2066 45003 : if (!size_t_cst_p (arg2, &s2))
2067 : return NULL_TREE;
2068 28997 : if (s2 == 0
2069 237 : && !TREE_SIDE_EFFECTS (arg0)
2070 29206 : && !TREE_SIDE_EFFECTS (arg1))
2071 209 : return build_int_cst (type, 0);
2072 28788 : else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
2073 573 : return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
2074 : return NULL_TREE;
2075 :
2076 7999 : case CFN_BUILT_IN_STRNCASECMP:
2077 7999 : if (!size_t_cst_p (arg2, &s2))
2078 : return NULL_TREE;
2079 7678 : if (s2 == 0
2080 9 : && !TREE_SIDE_EFFECTS (arg0)
2081 7683 : && !TREE_SIDE_EFFECTS (arg1))
2082 5 : return build_int_cst (type, 0);
2083 7673 : else if ((p0 = c_getstr (arg0))
2084 724 : && (p1 = c_getstr (arg1))
2085 7813 : && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
2086 3 : return build_int_cst (type, 0);
2087 : return NULL_TREE;
2088 :
2089 2520908 : case CFN_BUILT_IN_BCMP:
2090 2520908 : case CFN_BUILT_IN_MEMCMP:
2091 2520908 : if (!size_t_cst_p (arg2, &s2))
2092 : return NULL_TREE;
2093 1615317 : if (s2 == 0
2094 13066 : && !TREE_SIDE_EFFECTS (arg0)
2095 1628383 : && !TREE_SIDE_EFFECTS (arg1))
2096 13066 : return build_int_cst (type, 0);
2097 1602251 : if ((p0 = getbyterep (arg0, &s0))
2098 12242 : && (p1 = getbyterep (arg1, &s1))
2099 3782 : && s2 <= s0
2100 1605601 : && s2 <= s1)
2101 3349 : return build_cmp_result (type, memcmp (p0, p1, s2));
2102 : return NULL_TREE;
2103 :
2104 206862 : case CFN_BUILT_IN_MEMCHR:
2105 206862 : if (!size_t_cst_p (arg2, &s2))
2106 : return NULL_TREE;
2107 7245 : if (s2 == 0
2108 151 : && !TREE_SIDE_EFFECTS (arg0)
2109 7379 : && !TREE_SIDE_EFFECTS (arg1))
2110 131 : return build_int_cst (type, 0);
2111 7114 : if ((p0 = getbyterep (arg0, &s0))
2112 2390 : && s2 <= s0
2113 9385 : && target_char_cst_p (arg1, &c))
2114 : {
2115 740 : const char *r = (const char *) memchr (p0, c, s2);
2116 740 : if (r == NULL)
2117 284 : return build_int_cst (type, 0);
2118 456 : return fold_convert (type,
2119 : fold_build_pointer_plus_hwi (arg0, r - p0));
2120 : }
2121 : return NULL_TREE;
2122 :
2123 0 : case CFN_WHILE_ULT:
2124 0 : {
2125 0 : poly_uint64 parg0, parg1;
2126 0 : if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
2127 0 : return fold_while_ult (type, parg0, parg1);
2128 : return NULL_TREE;
2129 : }
2130 :
2131 92 : case CFN_UADDC:
2132 92 : case CFN_USUBC:
2133 92 : if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
2134 : {
2135 92 : tree itype = TREE_TYPE (type);
2136 92 : bool ovf = false;
2137 92 : tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
2138 92 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
2139 92 : fold_convert (itype, arg1));
2140 92 : if (!r)
2141 : return NULL_TREE;
2142 92 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
2143 : ovf = true;
2144 92 : tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
2145 92 : if (!r2 || TREE_CODE (r2) != INTEGER_CST)
2146 : return NULL_TREE;
2147 92 : if (arith_overflowed_p (subcode, itype, r, arg2))
2148 0 : ovf = true;
2149 92 : if (TREE_OVERFLOW (r2))
2150 0 : r2 = drop_tree_overflow (r2);
2151 92 : return build_complex (type, r2, build_int_cst (itype, ovf));
2152 : }
2153 : return NULL_TREE;
2154 :
2155 4139183 : default:
2156 4139183 : return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2157 : }
2158 : }
|