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 41908770 : integer_cst_p (tree t)
40 : {
41 41908770 : return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
42 : }
43 :
44 : static inline bool
45 45743773 : real_cst_p (tree t)
46 : {
47 45743773 : return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
48 : }
49 :
50 : static inline bool
51 27878095 : complex_cst_p (tree t)
52 : {
53 27878095 : 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 2906135 : size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
61 : {
62 2906135 : if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 2905980 : && integer_cst_p (t)
64 4588750 : && tree_fits_uhwi_p (t))
65 : {
66 1682615 : *size_out = tree_to_uhwi (t);
67 1682615 : 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 66438 : build_cmp_result (tree type, int res)
78 : {
79 71056 : 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 244876 : 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 244876 : if (!mpfr_number_p (m)
95 229867 : || mpfr_overflow_p ()
96 229867 : || mpfr_underflow_p ()
97 471199 : || (flag_rounding_math && inexact))
98 : return false;
99 :
100 226238 : REAL_VALUE_TYPE tmp;
101 226238 : 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 226238 : if (!real_isfinite (&tmp)
107 226238 : || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
108 : return false;
109 :
110 226238 : real_convert (result, format, &tmp);
111 226238 : 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 109735 : 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 109735 : if (format->b != 2 || !real_isfinite (arg))
129 : return false;
130 :
131 106993 : int prec = format->p;
132 106993 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
133 :
134 106993 : auto_mpfr m (prec);
135 106993 : mpfr_from_real (m, arg, MPFR_RNDN);
136 106993 : mpfr_clear_flags ();
137 106993 : bool inexact = func (m, m, rnd);
138 106993 : bool ok = do_mpfr_ckconv (result, m, inexact, format);
139 :
140 106993 : return ok;
141 106993 : }
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 150 : 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 150 : if (format->b != 2 || !real_isfinite (arg))
157 : return false;
158 :
159 150 : int prec = format->p;
160 150 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
161 150 : mpfr_t m, ms, mc;
162 :
163 150 : mpfr_inits2 (prec, m, ms, mc, NULL);
164 150 : mpfr_from_real (m, arg, MPFR_RNDN);
165 150 : mpfr_clear_flags ();
166 150 : bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
167 150 : bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
168 150 : && do_mpfr_ckconv (result_cos, mc, inexact, format));
169 150 : mpfr_clears (m, ms, mc, NULL);
170 :
171 150 : 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 144338 : 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 144338 : if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
190 : return false;
191 :
192 133294 : int prec = format->p;
193 133294 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
194 133294 : mpfr_t m0, m1;
195 :
196 133294 : mpfr_inits2 (prec, m0, m1, NULL);
197 133294 : mpfr_from_real (m0, arg0, MPFR_RNDN);
198 133294 : mpfr_from_real (m1, arg1, MPFR_RNDN);
199 133294 : mpfr_clear_flags ();
200 133294 : bool inexact = func (m0, m0, m1, rnd);
201 133294 : bool ok = do_mpfr_ckconv (result, m0, inexact, format);
202 133294 : mpfr_clears (m0, m1, NULL);
203 :
204 133294 : 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 : 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 : 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 : 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 : 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 : 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 : 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 1652 : 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 1652 : if (!real_isfinite (arg))
478 : return false;
479 :
480 1652 : real_value rounded;
481 1652 : fn (&rounded, format, arg);
482 :
483 1652 : bool fail = false;
484 1652 : *result = real_to_integer (&rounded, &fail, precision);
485 1652 : 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 127345 : fold_const_pow (real_value *result, const real_value *arg0,
496 : const real_value *arg1, const real_format *format)
497 : {
498 127345 : if (flag_signaling_nans
499 127345 : && (REAL_VALUE_ISSIGNALING_NAN (*arg0)
500 0 : || REAL_VALUE_ISSIGNALING_NAN (*arg1)))
501 : return false;
502 :
503 127345 : if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
504 : {
505 117037 : if (flag_errno_math)
506 116674 : 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 117037 : 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 12450 : fold_const_nextafter (real_value *result, const real_value *arg0,
534 : const real_value *arg1, const real_format *format)
535 : {
536 12450 : if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
537 12450 : || REAL_VALUE_ISSIGNALING_NAN (*arg1))
538 : return false;
539 :
540 : /* Don't handle composite modes, nor decimal, nor modes without
541 : inf or denorm at least for now. */
542 12450 : if (format->pnan < format->p
543 12450 : || format->b == 10
544 12450 : || !format->has_inf
545 12450 : || !format->has_denorm)
546 : return false;
547 :
548 19278 : 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 12450 : && (flag_trapping_math || flag_errno_math))
552 : return false;
553 : /* Similarly for nextafter (0, 1) raising underflow. */
554 5622 : else if (flag_trapping_math
555 5115 : && arg0->cl == rvc_zero
556 4474 : && result->cl != rvc_zero)
557 : return false;
558 :
559 1328 : real_convert (result, format, result);
560 :
561 1328 : 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 25264 : 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 25264 : 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 42742 : if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
584 : return false;
585 :
586 : /* Don't perform operation if we honor signaling NaNs and
587 : operand is a signaling NaN. */
588 9824 : if (!flag_unsafe_math_optimizations
589 9819 : && flag_signaling_nans
590 9944 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
591 : return false;
592 :
593 9824 : REAL_VALUE_TYPE initial_result;
594 9824 : real_ldexp (&initial_result, arg0, arg1.to_shwi ());
595 :
596 : /* Ensure we didn't overflow. */
597 9824 : if (real_isinf (&initial_result))
598 : return false;
599 :
600 : /* Only proceed if the target mode can hold the
601 : resulting value. */
602 9804 : *result = real_value_truncate (format, initial_result);
603 9804 : 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 405103 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
612 : {
613 405103 : REAL_VALUE_TYPE real;
614 405103 : const char *str = c_getstr (arg);
615 405103 : if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
616 404634 : 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 2137 : fold_const_reduction (tree type, tree arg, tree_code code)
624 : {
625 2137 : if (TREE_CODE (arg) != VECTOR_CST)
626 : return NULL_TREE;
627 :
628 4274 : bool idempotent_p = (code == MAX_EXPR
629 2137 : || code == MIN_EXPR
630 2137 : || code == BIT_AND_EXPR
631 : || code == BIT_IOR_EXPR);
632 :
633 2137 : unsigned HOST_WIDE_INT nelts = vector_cst_encoded_nelts (arg);
634 : /* Fall back to the exact element count for singleton sNaN encodings, since
635 : a known single-element vector performs no operation and so cannot raise an
636 : exception. */
637 2137 : bool singleton_snan_p
638 : = (nelts == 1
639 2137 : && tree_expr_maybe_signaling_nan_p (VECTOR_CST_ELT (arg, 0)));
640 :
641 2137 : if (idempotent_p
642 407 : && !VECTOR_CST_STEPPED_P (arg)
643 1137 : && multiple_p (VECTOR_CST_NELTS (arg), nelts)
644 2516 : && !singleton_snan_p)
645 : /* Operating on the first NELTS elements is enough. */
646 : ;
647 1758 : else if (code == BIT_XOR_EXPR
648 5 : && !VECTOR_CST_STEPPED_P (arg)
649 1764 : && multiple_p (VECTOR_CST_NELTS (arg), nelts * 2))
650 : {
651 3 : if (VECTOR_CST_DUPLICATE_P (arg))
652 : {
653 : /* Process two copies of a one-element-per-pattern encoding. */
654 : nelts *= 2;
655 : }
656 : else
657 0 : gcc_checking_assert (VECTOR_CST_NELTS_PER_PATTERN (arg) == 2);
658 : }
659 :
660 1755 : else if (!VECTOR_CST_NELTS (arg).is_constant (&nelts))
661 : return NULL_TREE;
662 :
663 2137 : tree res = VECTOR_CST_ELT (arg, 0);
664 28331 : for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
665 : {
666 24057 : res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
667 24057 : if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
668 : return NULL_TREE;
669 : }
670 : return res;
671 : }
672 :
673 : /* Fold a call to IFN_VEC_CONVERT (ARG) returning TYPE. */
674 :
675 : static tree
676 6605 : fold_const_vec_convert (tree ret_type, tree arg)
677 : {
678 6605 : enum tree_code code = NOP_EXPR;
679 6605 : tree arg_type = TREE_TYPE (arg);
680 6605 : if (TREE_CODE (arg) != VECTOR_CST)
681 : return NULL_TREE;
682 :
683 6605 : gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
684 :
685 13210 : if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
686 13123 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
687 : code = FIX_TRUNC_EXPR;
688 13088 : else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
689 13088 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
690 : code = FLOAT_EXPR;
691 :
692 : /* We can't handle steps directly when extending, since the
693 : values need to wrap at the original precision first. */
694 6605 : bool step_ok_p
695 13210 : = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
696 6518 : && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
697 13062 : && (TYPE_PRECISION (TREE_TYPE (ret_type))
698 6457 : <= TYPE_PRECISION (TREE_TYPE (arg_type))));
699 6605 : tree_vector_builder elts;
700 6605 : if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
701 : return NULL_TREE;
702 :
703 6605 : unsigned int count = elts.encoded_nelts ();
704 18342 : for (unsigned int i = 0; i < count; ++i)
705 : {
706 11743 : tree elt = fold_unary (code, TREE_TYPE (ret_type),
707 : VECTOR_CST_ELT (arg, i));
708 11743 : if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
709 6 : return NULL_TREE;
710 11737 : elts.quick_push (elt);
711 : }
712 :
713 6599 : return elts.build ();
714 6605 : }
715 :
716 : /* Try to evaluate:
717 :
718 : IFN_WHILE_ULT (ARG0, ARG1, (TYPE) { ... })
719 :
720 : Return the value on success and null on failure. */
721 :
722 : static tree
723 0 : fold_while_ult (tree type, poly_uint64 arg0, poly_uint64 arg1)
724 : {
725 0 : if (known_ge (arg0, arg1))
726 0 : return build_zero_cst (type);
727 :
728 0 : if (maybe_ge (arg0, arg1))
729 : return NULL_TREE;
730 :
731 0 : poly_uint64 diff = arg1 - arg0;
732 0 : poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
733 0 : if (known_ge (diff, nelts))
734 0 : return build_all_ones_cst (type);
735 :
736 0 : unsigned HOST_WIDE_INT const_diff;
737 0 : if (known_le (diff, nelts) && diff.is_constant (&const_diff))
738 : {
739 0 : tree minus_one = build_minus_one_cst (TREE_TYPE (type));
740 0 : tree zero = build_zero_cst (TREE_TYPE (type));
741 0 : return build_vector_a_then_b (type, const_diff, minus_one, zero);
742 : }
743 : return NULL_TREE;
744 : }
745 :
746 : /* Try to evaluate:
747 :
748 : *RESULT = FN (*ARG)
749 :
750 : in format FORMAT. Return true on success. */
751 :
752 : static bool
753 162541 : fold_const_call_ss (real_value *result, combined_fn fn,
754 : const real_value *arg, const real_format *format)
755 : {
756 162541 : switch (fn)
757 : {
758 23088 : CASE_CFN_SQRT:
759 23088 : CASE_CFN_SQRT_FN:
760 23088 : return (real_compare (GE_EXPR, arg, &dconst0)
761 23088 : && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
762 :
763 512 : CASE_CFN_CBRT:
764 512 : CASE_CFN_CBRT_FN:
765 512 : return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
766 :
767 1976 : CASE_CFN_ASIN:
768 1976 : CASE_CFN_ASIN_FN:
769 1976 : return (real_compare (GE_EXPR, arg, &dconstm1)
770 1202 : && real_compare (LE_EXPR, arg, &dconst1)
771 2396 : && do_mpfr_arg1 (result, mpfr_asin, arg, format));
772 :
773 2027 : CASE_CFN_ACOS:
774 2027 : CASE_CFN_ACOS_FN:
775 2027 : return (real_compare (GE_EXPR, arg, &dconstm1)
776 1253 : && real_compare (LE_EXPR, arg, &dconst1)
777 2506 : && do_mpfr_arg1 (result, mpfr_acos, arg, format));
778 :
779 552 : CASE_CFN_ATAN:
780 552 : CASE_CFN_ATAN_FN:
781 552 : return do_mpfr_arg1 (result, mpfr_atan, arg, format);
782 :
783 312 : CASE_CFN_ASINH:
784 312 : CASE_CFN_ASINH_FN:
785 312 : return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
786 :
787 1451 : CASE_CFN_ACOSH:
788 1451 : CASE_CFN_ACOSH_FN:
789 1451 : return (real_compare (GE_EXPR, arg, &dconst1)
790 1451 : && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
791 :
792 1906 : CASE_CFN_ATANH:
793 1906 : CASE_CFN_ATANH_FN:
794 1906 : return (real_compare (GE_EXPR, arg, &dconstm1)
795 1906 : && real_compare (LE_EXPR, arg, &dconst1)
796 3812 : && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
797 :
798 1010 : CASE_CFN_SIN:
799 1010 : CASE_CFN_SIN_FN:
800 1010 : return do_mpfr_arg1 (result, mpfr_sin, arg, format);
801 :
802 846 : CASE_CFN_COS:
803 846 : CASE_CFN_COS_FN:
804 846 : return do_mpfr_arg1 (result, mpfr_cos, arg, format);
805 :
806 553 : CASE_CFN_TAN:
807 553 : CASE_CFN_TAN_FN:
808 553 : return do_mpfr_arg1 (result, mpfr_tan, arg, format);
809 :
810 394 : CASE_CFN_SINH:
811 394 : CASE_CFN_SINH_FN:
812 394 : return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
813 :
814 399 : CASE_CFN_COSH:
815 399 : CASE_CFN_COSH_FN:
816 399 : return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
817 :
818 349 : CASE_CFN_TANH:
819 349 : CASE_CFN_TANH_FN:
820 349 : return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
821 :
822 : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
823 55 : CASE_CFN_ACOSPI:
824 55 : CASE_CFN_ACOSPI_FN:
825 55 : return (real_compare (GE_EXPR, arg, &dconstm1)
826 55 : && real_compare (LE_EXPR, arg, &dconst1)
827 110 : && do_mpfr_arg1 (result, mpfr_acospi, arg, format));
828 :
829 60 : CASE_CFN_ASINPI:
830 60 : CASE_CFN_ASINPI_FN:
831 60 : return (real_compare (GE_EXPR, arg, &dconstm1)
832 60 : && real_compare (LE_EXPR, arg, &dconst1)
833 120 : && do_mpfr_arg1 (result, mpfr_asinpi, arg, format));
834 :
835 36 : CASE_CFN_ATANPI:
836 36 : CASE_CFN_ATANPI_FN:
837 36 : return do_mpfr_arg1 (result, mpfr_atanpi, arg, format);
838 :
839 60 : CASE_CFN_COSPI:
840 60 : CASE_CFN_COSPI_FN:
841 60 : return do_mpfr_arg1 (result, mpfr_cospi, arg, format);
842 :
843 60 : CASE_CFN_SINPI:
844 60 : CASE_CFN_SINPI_FN:
845 60 : return do_mpfr_arg1 (result, mpfr_sinpi, arg, format);
846 :
847 72 : CASE_CFN_TANPI:
848 72 : CASE_CFN_TANPI_FN:
849 72 : return do_mpfr_arg1 (result, mpfr_tanpi, arg, format);
850 : #endif
851 :
852 511 : CASE_CFN_ERF:
853 511 : CASE_CFN_ERF_FN:
854 511 : return do_mpfr_arg1 (result, mpfr_erf, arg, format);
855 :
856 554 : CASE_CFN_ERFC:
857 554 : CASE_CFN_ERFC_FN:
858 554 : return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
859 :
860 4899 : CASE_CFN_TGAMMA:
861 4899 : CASE_CFN_TGAMMA_FN:
862 4899 : return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
863 :
864 870 : CASE_CFN_EXP:
865 870 : CASE_CFN_EXP_FN:
866 870 : return do_mpfr_arg1 (result, mpfr_exp, arg, format);
867 :
868 10784 : CASE_CFN_EXP2:
869 10784 : CASE_CFN_EXP2_FN:
870 10784 : return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
871 :
872 698 : CASE_CFN_EXP10:
873 698 : CASE_CFN_POW10:
874 698 : return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
875 :
876 327 : CASE_CFN_EXPM1:
877 327 : CASE_CFN_EXPM1_FN:
878 327 : return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
879 :
880 61445 : CASE_CFN_LOG:
881 61445 : CASE_CFN_LOG_FN:
882 61445 : return (real_compare (GT_EXPR, arg, &dconst0)
883 61445 : && do_mpfr_arg1 (result, mpfr_log, arg, format));
884 :
885 3136 : CASE_CFN_LOG2:
886 3136 : CASE_CFN_LOG2_FN:
887 3136 : return (real_compare (GT_EXPR, arg, &dconst0)
888 3136 : && do_mpfr_arg1 (result, mpfr_log2, arg, format));
889 :
890 3172 : CASE_CFN_LOG10:
891 3172 : CASE_CFN_LOG10_FN:
892 3172 : return (real_compare (GT_EXPR, arg, &dconst0)
893 3172 : && do_mpfr_arg1 (result, mpfr_log10, arg, format));
894 :
895 1921 : CASE_CFN_LOG1P:
896 1921 : CASE_CFN_LOG1P_FN:
897 1921 : return (real_compare (GT_EXPR, arg, &dconstm1)
898 1921 : && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
899 :
900 221 : CASE_CFN_J0:
901 221 : return do_mpfr_arg1 (result, mpfr_j0, arg, format);
902 :
903 221 : CASE_CFN_J1:
904 221 : return do_mpfr_arg1 (result, mpfr_j1, arg, format);
905 :
906 2447 : CASE_CFN_Y0:
907 2447 : return (real_compare (GT_EXPR, arg, &dconst0)
908 2447 : && do_mpfr_arg1 (result, mpfr_y0, arg, format));
909 :
910 2447 : CASE_CFN_Y1:
911 2447 : return (real_compare (GT_EXPR, arg, &dconst0)
912 2447 : && do_mpfr_arg1 (result, mpfr_y1, arg, format));
913 :
914 360 : CASE_CFN_FLOOR:
915 360 : CASE_CFN_FLOOR_FN:
916 360 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
917 : {
918 360 : real_floor (result, format, arg);
919 360 : return true;
920 : }
921 : return false;
922 :
923 323 : CASE_CFN_CEIL:
924 323 : CASE_CFN_CEIL_FN:
925 323 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
926 : {
927 323 : real_ceil (result, format, arg);
928 323 : return true;
929 : }
930 : return false;
931 :
932 544 : CASE_CFN_TRUNC:
933 544 : CASE_CFN_TRUNC_FN:
934 544 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
935 : {
936 544 : real_trunc (result, format, arg);
937 544 : return true;
938 : }
939 : return false;
940 :
941 264 : CASE_CFN_ROUND:
942 264 : CASE_CFN_ROUND_FN:
943 264 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
944 : {
945 264 : real_round (result, format, arg);
946 264 : return true;
947 : }
948 : return false;
949 :
950 189 : CASE_CFN_ROUNDEVEN:
951 189 : CASE_CFN_ROUNDEVEN_FN:
952 189 : if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
953 : {
954 189 : real_roundeven (result, format, arg);
955 189 : return true;
956 : }
957 : return false;
958 :
959 4463 : CASE_CFN_LOGB:
960 4463 : CASE_CFN_LOGB_FN:
961 4463 : return fold_const_logb (result, arg, format);
962 :
963 960 : CASE_CFN_SIGNIFICAND:
964 960 : return fold_const_significand (result, arg, format);
965 :
966 : default:
967 : return false;
968 : }
969 : }
970 :
971 : /* Try to evaluate:
972 :
973 : *RESULT = FN (*ARG)
974 :
975 : where FORMAT is the format of ARG and PRECISION is the number of
976 : significant bits in the result. Return true on success. */
977 :
978 : static bool
979 17501 : fold_const_call_ss (wide_int *result, combined_fn fn,
980 : const real_value *arg, unsigned int precision,
981 : const real_format *format)
982 : {
983 17501 : switch (fn)
984 : {
985 1863 : CASE_CFN_SIGNBIT:
986 1863 : if (real_isneg (arg))
987 996 : *result = wi::one (precision);
988 : else
989 867 : *result = wi::zero (precision);
990 : return true;
991 :
992 6485 : CASE_CFN_ILOGB:
993 6485 : CASE_CFN_ILOGB_FN:
994 : /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
995 : Proceed iff radix == 2. In GCC, normalized significands are in
996 : the range [0.5, 1.0). We want the exponent as if they were
997 : [1.0, 2.0) so get the exponent and subtract 1. */
998 6485 : if (arg->cl == rvc_normal && format->b == 2)
999 : {
1000 834 : *result = wi::shwi (REAL_EXP (arg) - 1, precision);
1001 834 : return true;
1002 : }
1003 : return false;
1004 :
1005 378 : CASE_CFN_ICEIL:
1006 378 : CASE_CFN_LCEIL:
1007 378 : CASE_CFN_LLCEIL:
1008 378 : return fold_const_conversion (result, real_ceil, arg,
1009 378 : precision, format);
1010 :
1011 378 : CASE_CFN_LFLOOR:
1012 378 : CASE_CFN_IFLOOR:
1013 378 : CASE_CFN_LLFLOOR:
1014 378 : return fold_const_conversion (result, real_floor, arg,
1015 378 : precision, format);
1016 :
1017 896 : CASE_CFN_IROUND:
1018 896 : CASE_CFN_LROUND:
1019 896 : CASE_CFN_LROUND_FN:
1020 896 : CASE_CFN_LLROUND:
1021 896 : CASE_CFN_LLROUND_FN:
1022 896 : return fold_const_conversion (result, real_round, arg,
1023 896 : precision, format);
1024 :
1025 : CASE_CFN_IRINT:
1026 : CASE_CFN_LRINT:
1027 : CASE_CFN_LRINT_FN:
1028 : CASE_CFN_LLRINT:
1029 : CASE_CFN_LLRINT_FN:
1030 : /* Not yet folded to a constant. */
1031 : return false;
1032 :
1033 1500 : CASE_CFN_FINITE:
1034 1500 : case CFN_BUILT_IN_FINITED32:
1035 1500 : case CFN_BUILT_IN_FINITED64:
1036 1500 : case CFN_BUILT_IN_FINITED128:
1037 1500 : case CFN_BUILT_IN_ISFINITE:
1038 1534 : *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
1039 1500 : return true;
1040 :
1041 3664 : case CFN_BUILT_IN_ISSIGNALING:
1042 7175 : *result = wi::shwi (real_issignaling_nan (arg) ? 1 : 0, precision);
1043 3664 : return true;
1044 :
1045 208 : CASE_CFN_ISINF:
1046 208 : case CFN_BUILT_IN_ISINFD32:
1047 208 : case CFN_BUILT_IN_ISINFD64:
1048 208 : case CFN_BUILT_IN_ISINFD128:
1049 208 : if (real_isinf (arg))
1050 299 : *result = wi::shwi (arg->sign ? -1 : 1, precision);
1051 : else
1052 42 : *result = wi::shwi (0, precision);
1053 : return true;
1054 :
1055 1341 : CASE_CFN_ISNAN:
1056 1341 : case CFN_BUILT_IN_ISNAND32:
1057 1341 : case CFN_BUILT_IN_ISNAND64:
1058 1341 : case CFN_BUILT_IN_ISNAND128:
1059 2456 : *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
1060 1341 : return true;
1061 :
1062 : default:
1063 : return false;
1064 : }
1065 : }
1066 :
1067 : /* Try to evaluate:
1068 :
1069 : *RESULT = FN (ARG)
1070 :
1071 : where ARG_TYPE is the type of ARG and PRECISION is the number of bits
1072 : in the result. Return true on success. */
1073 :
1074 : static bool
1075 5411225 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1076 : unsigned int precision, tree arg_type)
1077 : {
1078 5411225 : switch (fn)
1079 : {
1080 491 : CASE_CFN_FFS:
1081 491 : case CFN_BUILT_IN_FFSG:
1082 491 : *result = wi::shwi (wi::ffs (arg), precision);
1083 491 : return true;
1084 :
1085 2176 : CASE_CFN_CLZ:
1086 2176 : case CFN_BUILT_IN_CLZG:
1087 2176 : {
1088 2176 : int tmp;
1089 2176 : if (wi::ne_p (arg, 0))
1090 1691 : tmp = wi::clz (arg);
1091 485 : else if (BITINT_TYPE_P (arg_type))
1092 9 : tmp = TYPE_PRECISION (arg_type);
1093 952 : else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1094 : tmp))
1095 476 : tmp = TYPE_PRECISION (arg_type);
1096 2176 : *result = wi::shwi (tmp, precision);
1097 2176 : return true;
1098 : }
1099 :
1100 1542 : CASE_CFN_CTZ:
1101 1542 : case CFN_BUILT_IN_CTZG:
1102 1542 : {
1103 1542 : int tmp;
1104 1542 : if (wi::ne_p (arg, 0))
1105 1298 : tmp = wi::ctz (arg);
1106 244 : else if (BITINT_TYPE_P (arg_type))
1107 0 : tmp = TYPE_PRECISION (arg_type);
1108 488 : else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1109 : tmp))
1110 244 : tmp = TYPE_PRECISION (arg_type);
1111 1542 : *result = wi::shwi (tmp, precision);
1112 1542 : return true;
1113 : }
1114 :
1115 412 : CASE_CFN_CLRSB:
1116 412 : case CFN_BUILT_IN_CLRSBG:
1117 412 : *result = wi::shwi (wi::clrsb (arg), precision);
1118 412 : return true;
1119 :
1120 41706 : CASE_CFN_POPCOUNT:
1121 41706 : case CFN_BUILT_IN_POPCOUNTG:
1122 41706 : *result = wi::shwi (wi::popcount (arg), precision);
1123 41706 : return true;
1124 :
1125 553 : CASE_CFN_PARITY:
1126 553 : case CFN_BUILT_IN_PARITYG:
1127 553 : *result = wi::shwi (wi::parity (arg), precision);
1128 553 : return true;
1129 :
1130 738 : CASE_CFN_BSWAP:
1131 1476 : *result = wi::bswap (wide_int::from (arg, precision,
1132 1476 : TYPE_SIGN (arg_type)));
1133 738 : return true;
1134 :
1135 53 : CASE_CFN_BITREVERSE:
1136 106 : *result = wi::bitreverse (wide_int::from (arg, precision,
1137 106 : TYPE_SIGN (arg_type)));
1138 53 : return true;
1139 :
1140 : default:
1141 : return false;
1142 : }
1143 : }
1144 :
1145 : /* Try to evaluate:
1146 :
1147 : RESULT = FN (*ARG)
1148 :
1149 : where FORMAT is the format of ARG and of the real and imaginary parts
1150 : of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
1151 : true on success. */
1152 :
1153 : static bool
1154 150 : fold_const_call_cs (real_value *result_real, real_value *result_imag,
1155 : combined_fn fn, const real_value *arg,
1156 : const real_format *format)
1157 : {
1158 0 : switch (fn)
1159 : {
1160 150 : CASE_CFN_CEXPI:
1161 : /* cexpi(x+yi) = cos(x)+sin(y)*i. */
1162 150 : return do_mpfr_sincos (result_imag, result_real, arg, format);
1163 :
1164 : default:
1165 : return false;
1166 : }
1167 : }
1168 :
1169 : /* Try to evaluate:
1170 :
1171 : *RESULT = fn (ARG)
1172 :
1173 : where FORMAT is the format of RESULT and of the real and imaginary parts
1174 : of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
1175 : success. */
1176 :
1177 : static bool
1178 2296 : fold_const_call_sc (real_value *result, combined_fn fn,
1179 : const real_value *arg_real, const real_value *arg_imag,
1180 : const real_format *format)
1181 : {
1182 0 : switch (fn)
1183 : {
1184 1160 : CASE_CFN_CABS:
1185 1160 : CASE_CFN_CABS_FN:
1186 1160 : return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1187 :
1188 : default:
1189 : return false;
1190 : }
1191 : }
1192 :
1193 : /* Try to evaluate:
1194 :
1195 : RESULT = fn (ARG)
1196 :
1197 : where FORMAT is the format of the real and imaginary parts of RESULT
1198 : (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1199 : Return true on success. */
1200 :
1201 : static bool
1202 39622 : fold_const_call_cc (real_value *result_real, real_value *result_imag,
1203 : combined_fn fn, const real_value *arg_real,
1204 : const real_value *arg_imag, const real_format *format)
1205 : {
1206 39622 : switch (fn)
1207 : {
1208 686 : CASE_CFN_CCOS:
1209 686 : CASE_CFN_CCOS_FN:
1210 686 : return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1211 686 : arg_real, arg_imag, format);
1212 :
1213 676 : CASE_CFN_CCOSH:
1214 676 : CASE_CFN_CCOSH_FN:
1215 676 : return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1216 676 : arg_real, arg_imag, format);
1217 :
1218 683 : CASE_CFN_CPROJ:
1219 683 : CASE_CFN_CPROJ_FN:
1220 683 : if (real_isinf (arg_real) || real_isinf (arg_imag))
1221 : {
1222 436 : *result_real = dconstinf;
1223 436 : *result_imag = dconst0;
1224 436 : result_imag->sign = arg_imag->sign;
1225 : }
1226 : else
1227 : {
1228 247 : *result_real = *arg_real;
1229 247 : *result_imag = *arg_imag;
1230 : }
1231 : return true;
1232 :
1233 701 : CASE_CFN_CSIN:
1234 701 : CASE_CFN_CSIN_FN:
1235 701 : return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1236 701 : arg_real, arg_imag, format);
1237 :
1238 676 : CASE_CFN_CSINH:
1239 676 : CASE_CFN_CSINH_FN:
1240 676 : return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1241 676 : arg_real, arg_imag, format);
1242 :
1243 698 : CASE_CFN_CTAN:
1244 698 : CASE_CFN_CTAN_FN:
1245 698 : return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1246 698 : arg_real, arg_imag, format);
1247 :
1248 676 : CASE_CFN_CTANH:
1249 676 : CASE_CFN_CTANH_FN:
1250 676 : return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1251 676 : arg_real, arg_imag, format);
1252 :
1253 777 : CASE_CFN_CLOG:
1254 777 : CASE_CFN_CLOG_FN:
1255 777 : return do_mpc_arg1 (result_real, result_imag, mpc_log,
1256 777 : arg_real, arg_imag, format);
1257 :
1258 3053 : CASE_CFN_CSQRT:
1259 3053 : CASE_CFN_CSQRT_FN:
1260 3053 : return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1261 3053 : arg_real, arg_imag, format);
1262 :
1263 679 : CASE_CFN_CASIN:
1264 679 : CASE_CFN_CASIN_FN:
1265 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1266 679 : arg_real, arg_imag, format);
1267 :
1268 728 : CASE_CFN_CACOS:
1269 728 : CASE_CFN_CACOS_FN:
1270 728 : return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1271 728 : arg_real, arg_imag, format);
1272 :
1273 679 : CASE_CFN_CATAN:
1274 679 : CASE_CFN_CATAN_FN:
1275 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1276 679 : arg_real, arg_imag, format);
1277 :
1278 679 : CASE_CFN_CASINH:
1279 679 : CASE_CFN_CASINH_FN:
1280 679 : return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1281 679 : arg_real, arg_imag, format);
1282 :
1283 745 : CASE_CFN_CACOSH:
1284 745 : CASE_CFN_CACOSH_FN:
1285 745 : return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1286 745 : arg_real, arg_imag, format);
1287 :
1288 679 : CASE_CFN_CATANH:
1289 679 : CASE_CFN_CATANH_FN:
1290 679 : return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1291 679 : arg_real, arg_imag, format);
1292 :
1293 1583 : CASE_CFN_CEXP:
1294 1583 : CASE_CFN_CEXP_FN:
1295 1583 : return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1296 1583 : arg_real, arg_imag, format);
1297 :
1298 : default:
1299 : return false;
1300 : }
1301 : }
1302 :
1303 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1304 : where the arguments and result are numerical. */
1305 :
1306 : static tree
1307 20612693 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
1308 : {
1309 20612693 : machine_mode mode = TYPE_MODE (type);
1310 20612693 : machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1311 :
1312 20612693 : if (integer_cst_p (arg))
1313 : {
1314 5821691 : if (SCALAR_INT_MODE_P (mode))
1315 : {
1316 5411225 : wide_int result;
1317 5411225 : if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1318 5411225 : TYPE_PRECISION (type), TREE_TYPE (arg)))
1319 47671 : return wide_int_to_tree (type, result);
1320 5411225 : }
1321 : return NULL_TREE;
1322 : }
1323 :
1324 14791002 : if (real_cst_p (arg))
1325 : {
1326 180195 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1327 180195 : if (mode == arg_mode)
1328 : {
1329 : /* real -> real. */
1330 162541 : REAL_VALUE_TYPE result;
1331 162541 : if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1332 162541 : REAL_MODE_FORMAT (mode)))
1333 101140 : return build_real (type, result);
1334 : }
1335 17654 : else if (COMPLEX_MODE_P (mode)
1336 17804 : && GET_MODE_INNER (mode) == arg_mode)
1337 : {
1338 : /* real -> complex real. */
1339 150 : REAL_VALUE_TYPE result_real, result_imag;
1340 300 : if (fold_const_call_cs (&result_real, &result_imag, fn,
1341 150 : TREE_REAL_CST_PTR (arg),
1342 150 : REAL_MODE_FORMAT (arg_mode)))
1343 300 : return build_complex (type,
1344 150 : build_real (TREE_TYPE (type), result_real),
1345 300 : build_real (TREE_TYPE (type), result_imag));
1346 : }
1347 17504 : else if (INTEGRAL_TYPE_P (type))
1348 : {
1349 : /* real -> int. */
1350 17501 : wide_int result;
1351 17501 : if (fold_const_call_ss (&result, fn,
1352 17501 : TREE_REAL_CST_PTR (arg),
1353 17501 : TYPE_PRECISION (type),
1354 17501 : REAL_MODE_FORMAT (arg_mode)))
1355 11062 : return wide_int_to_tree (type, result);
1356 17501 : }
1357 : return NULL_TREE;
1358 : }
1359 :
1360 14610807 : if (complex_cst_p (arg))
1361 : {
1362 41918 : gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1363 41918 : machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1364 41918 : tree argr = TREE_REALPART (arg);
1365 41918 : tree argi = TREE_IMAGPART (arg);
1366 41918 : if (mode == arg_mode
1367 39622 : && real_cst_p (argr)
1368 81540 : && real_cst_p (argi))
1369 : {
1370 : /* complex real -> complex real. */
1371 39622 : REAL_VALUE_TYPE result_real, result_imag;
1372 79244 : if (fold_const_call_cc (&result_real, &result_imag, fn,
1373 39622 : TREE_REAL_CST_PTR (argr),
1374 39622 : TREE_REAL_CST_PTR (argi),
1375 39622 : REAL_MODE_FORMAT (inner_mode)))
1376 20972 : return build_complex (type,
1377 10486 : build_real (TREE_TYPE (type), result_real),
1378 20972 : build_real (TREE_TYPE (type), result_imag));
1379 : }
1380 31432 : if (mode == inner_mode
1381 2296 : && real_cst_p (argr)
1382 33728 : && real_cst_p (argi))
1383 : {
1384 : /* complex real -> real. */
1385 2296 : REAL_VALUE_TYPE result;
1386 4592 : if (fold_const_call_sc (&result, fn,
1387 2296 : TREE_REAL_CST_PTR (argr),
1388 2296 : TREE_REAL_CST_PTR (argi),
1389 2296 : REAL_MODE_FORMAT (inner_mode)))
1390 1160 : return build_real (type, result);
1391 : }
1392 : return NULL_TREE;
1393 : }
1394 :
1395 : return NULL_TREE;
1396 : }
1397 :
1398 : /* Try to fold FN (ARG) to a constant. Return the constant on success,
1399 : otherwise return null. TYPE is the type of the return value. */
1400 :
1401 : tree
1402 21613583 : fold_const_call (combined_fn fn, tree type, tree arg)
1403 : {
1404 21613583 : switch (fn)
1405 : {
1406 587045 : case CFN_BUILT_IN_STRLEN:
1407 587045 : if (const char *str = c_getstr (arg))
1408 97765 : return build_int_cst (type, strlen (str));
1409 : return NULL_TREE;
1410 :
1411 234390 : CASE_CFN_NAN:
1412 234390 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1413 234390 : case CFN_BUILT_IN_NAND32:
1414 234390 : case CFN_BUILT_IN_NAND64:
1415 234390 : case CFN_BUILT_IN_NAND128:
1416 234390 : case CFN_BUILT_IN_NAND64X:
1417 234390 : return fold_const_builtin_nan (type, arg, true);
1418 :
1419 170713 : CASE_CFN_NANS:
1420 170713 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1421 170713 : case CFN_BUILT_IN_NANSF16B:
1422 170713 : case CFN_BUILT_IN_NANSD32:
1423 170713 : case CFN_BUILT_IN_NANSD64:
1424 170713 : case CFN_BUILT_IN_NANSD128:
1425 170713 : case CFN_BUILT_IN_NANSD64X:
1426 170713 : return fold_const_builtin_nan (type, arg, false);
1427 :
1428 1725 : case CFN_REDUC_PLUS:
1429 1725 : return fold_const_reduction (type, arg, PLUS_EXPR);
1430 :
1431 47 : case CFN_REDUC_MAX:
1432 47 : return fold_const_reduction (type, arg, MAX_EXPR);
1433 :
1434 67 : case CFN_REDUC_MIN:
1435 67 : return fold_const_reduction (type, arg, MIN_EXPR);
1436 :
1437 34 : case CFN_REDUC_AND:
1438 34 : return fold_const_reduction (type, arg, BIT_AND_EXPR);
1439 :
1440 259 : case CFN_REDUC_IOR:
1441 259 : return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1442 :
1443 5 : case CFN_REDUC_XOR:
1444 5 : return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1445 :
1446 6605 : case CFN_VEC_CONVERT:
1447 6605 : return fold_const_vec_convert (type, arg);
1448 :
1449 20612693 : default:
1450 20612693 : return fold_const_call_1 (fn, type, arg);
1451 : }
1452 : }
1453 :
1454 : /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1455 : of type TYPE. */
1456 :
1457 : static tree
1458 0 : fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1459 : {
1460 0 : if (TREE_CODE (arg1) != VECTOR_CST)
1461 : return NULL_TREE;
1462 :
1463 0 : unsigned HOST_WIDE_INT nelts;
1464 0 : if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1465 : return NULL_TREE;
1466 :
1467 0 : for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1468 : {
1469 0 : arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1470 0 : if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1471 : return NULL_TREE;
1472 : }
1473 : return arg0;
1474 : }
1475 :
1476 : /* Fold a call to IFN_VEC_SHL_INSERT (ARG0, ARG1), returning a value
1477 : of type TYPE. */
1478 :
1479 : static tree
1480 0 : fold_const_vec_shl_insert (tree, tree arg0, tree arg1)
1481 : {
1482 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1483 : return NULL_TREE;
1484 :
1485 : /* vec_shl_insert ( dup(CST), CST) -> dup (CST). */
1486 0 : if (tree elem = uniform_vector_p (arg0))
1487 : {
1488 0 : if (operand_equal_p (elem, arg1))
1489 0 : return arg0;
1490 : }
1491 :
1492 : return NULL_TREE;
1493 : }
1494 :
1495 : /* Fold a call to IFN_VEC_EXTRACT (ARG0, ARG1), returning a value
1496 : of type TYPE.
1497 :
1498 : Right now this is only handling uniform vectors, so ARG1 is not
1499 : used. But it could be easily adjusted in the future to handle
1500 : non-uniform vectors by extracting the relevant element. */
1501 :
1502 : static tree
1503 0 : fold_const_vec_extract (tree, tree arg0, tree)
1504 : {
1505 0 : if (TREE_CODE (arg0) != VECTOR_CST)
1506 : return NULL_TREE;
1507 :
1508 : /* vec_extract ( dup(CST), CST) -> dup (CST). */
1509 0 : if (tree elem = uniform_vector_p (arg0))
1510 : return elem;
1511 :
1512 : return NULL_TREE;
1513 : }
1514 :
1515 : /* Try to fold scalar integer IFN_SAT_ADD with operands OP0 and OP1. */
1516 :
1517 : static tree
1518 36 : fold_internal_fn_sat_add (tree type, tree op0, tree op1)
1519 : {
1520 36 : if (!INTEGRAL_NB_TYPE_P (type))
1521 : return NULL_TREE;
1522 :
1523 0 : if (TREE_CODE (op0) != INTEGER_CST
1524 0 : || TREE_CODE (op1) != INTEGER_CST)
1525 : return NULL_TREE;
1526 :
1527 0 : wi::overflow_type overflow;
1528 0 : unsigned int prec = TYPE_PRECISION (type);
1529 0 : wide_int result = wi::add (wi::to_wide (op0), wi::to_wide (op1),
1530 0 : TYPE_SIGN (type), &overflow);
1531 :
1532 0 : if (overflow != wi::OVF_NONE)
1533 : {
1534 0 : if (TYPE_UNSIGNED (type))
1535 0 : result = wi::max_value (prec, UNSIGNED);
1536 0 : else if (overflow == wi::OVF_OVERFLOW)
1537 0 : result = wi::max_value (prec, SIGNED);
1538 0 : else if (overflow == wi::OVF_UNDERFLOW)
1539 0 : result = wi::min_value (prec, SIGNED);
1540 : else
1541 : return NULL_TREE;
1542 : }
1543 :
1544 0 : return wide_int_to_tree (type, result);
1545 0 : }
1546 :
1547 : /* Try to evaluate:
1548 :
1549 : *RESULT = FN (*ARG0, *ARG1)
1550 :
1551 : in format FORMAT. Return true on success. */
1552 :
1553 : static bool
1554 226256 : fold_const_call_sss (real_value *result, combined_fn fn,
1555 : const real_value *arg0, const real_value *arg1,
1556 : const real_format *format)
1557 : {
1558 226256 : switch (fn)
1559 : {
1560 6774 : CASE_CFN_DREM:
1561 6774 : CASE_CFN_REMAINDER:
1562 6774 : CASE_CFN_REMAINDER_FN:
1563 6774 : return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1564 :
1565 986 : CASE_CFN_ATAN2:
1566 986 : CASE_CFN_ATAN2_FN:
1567 986 : return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1568 :
1569 : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
1570 84 : CASE_CFN_ATAN2PI:
1571 84 : CASE_CFN_ATAN2PI_FN:
1572 84 : return do_mpfr_arg2 (result, mpfr_atan2pi, arg0, arg1, format);
1573 : #endif
1574 :
1575 572 : CASE_CFN_FDIM:
1576 572 : CASE_CFN_FDIM_FN:
1577 572 : return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1578 :
1579 517 : CASE_CFN_FMOD:
1580 517 : CASE_CFN_FMOD_FN:
1581 517 : return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
1582 :
1583 578 : CASE_CFN_HYPOT:
1584 578 : CASE_CFN_HYPOT_FN:
1585 578 : return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1586 :
1587 70628 : CASE_CFN_COPYSIGN:
1588 70628 : CASE_CFN_COPYSIGN_FN:
1589 70628 : *result = *arg0;
1590 70628 : real_copysign (result, arg1);
1591 70628 : return true;
1592 :
1593 3161 : CASE_CFN_FMIN:
1594 3161 : CASE_CFN_FMIN_FN:
1595 3161 : return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1596 :
1597 3161 : CASE_CFN_FMAX:
1598 3161 : CASE_CFN_FMAX_FN:
1599 3161 : return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1600 :
1601 127345 : CASE_CFN_POW:
1602 127345 : CASE_CFN_POW_FN:
1603 127345 : return fold_const_pow (result, arg0, arg1, format);
1604 :
1605 12450 : CASE_CFN_NEXTAFTER:
1606 12450 : CASE_CFN_NEXTAFTER_FN:
1607 12450 : case CFN_BUILT_IN_NEXTAFTERF16B:
1608 12450 : CASE_CFN_NEXTTOWARD:
1609 12450 : return fold_const_nextafter (result, arg0, arg1, format);
1610 :
1611 : default:
1612 : return false;
1613 : }
1614 : }
1615 :
1616 : /* Try to evaluate:
1617 :
1618 : *RESULT = FN (*ARG0, ARG1)
1619 :
1620 : where FORMAT is the format of *RESULT and *ARG0. Return true on
1621 : success. */
1622 :
1623 : static bool
1624 25662 : fold_const_call_sss (real_value *result, combined_fn fn,
1625 : const real_value *arg0, const wide_int_ref &arg1,
1626 : const real_format *format)
1627 : {
1628 25662 : switch (fn)
1629 : {
1630 7914 : CASE_CFN_LDEXP:
1631 7914 : CASE_CFN_LDEXP_FN:
1632 7914 : return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1633 :
1634 17350 : CASE_CFN_SCALBN:
1635 17350 : CASE_CFN_SCALBN_FN:
1636 17350 : CASE_CFN_SCALBLN:
1637 17350 : CASE_CFN_SCALBLN_FN:
1638 17350 : return (format->b == 2
1639 17350 : && fold_const_builtin_load_exponent (result, arg0, arg1,
1640 : format));
1641 :
1642 389 : CASE_CFN_POWI:
1643 : /* Avoid the folding if flag_signaling_nans is on and
1644 : operand is a signaling NaN. */
1645 389 : if (!flag_unsafe_math_optimizations
1646 376 : && flag_signaling_nans
1647 404 : && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1648 : return false;
1649 :
1650 389 : real_powi (result, format, arg0, arg1.to_shwi ());
1651 389 : return true;
1652 :
1653 : default:
1654 : return false;
1655 : }
1656 : }
1657 :
1658 : /* Try to evaluate:
1659 :
1660 : *RESULT = FN (ARG0, *ARG1)
1661 :
1662 : where FORMAT is the format of *RESULT and *ARG1. Return true on
1663 : success. */
1664 :
1665 : static bool
1666 6434 : fold_const_call_sss (real_value *result, combined_fn fn,
1667 : const wide_int_ref &arg0, const real_value *arg1,
1668 : const real_format *format)
1669 : {
1670 6434 : switch (fn)
1671 : {
1672 1220 : CASE_CFN_JN:
1673 1220 : return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1674 :
1675 5205 : CASE_CFN_YN:
1676 5205 : return (real_compare (GT_EXPR, arg1, &dconst0)
1677 5205 : && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1678 :
1679 : default:
1680 : return false;
1681 : }
1682 : }
1683 :
1684 : /* Try to evaluate:
1685 :
1686 : *RESULT = FN (ARG0, ARG1)
1687 :
1688 : where ARG_TYPE is the type of ARG0 and PRECISION is the number of bits in
1689 : the result. Return true on success. */
1690 :
1691 : static bool
1692 417717 : fold_const_call_sss (wide_int *result, combined_fn fn,
1693 : const wide_int_ref &arg0, const wide_int_ref &arg1,
1694 : unsigned int precision, tree arg_type ATTRIBUTE_UNUSED)
1695 : {
1696 417717 : switch (fn)
1697 : {
1698 17009 : case CFN_CLZ:
1699 17009 : case CFN_BUILT_IN_CLZG:
1700 17009 : {
1701 17009 : int tmp;
1702 17009 : if (wi::ne_p (arg0, 0))
1703 16892 : tmp = wi::clz (arg0);
1704 : else
1705 117 : tmp = arg1.to_shwi ();
1706 17009 : *result = wi::shwi (tmp, precision);
1707 17009 : return true;
1708 : }
1709 :
1710 11904 : case CFN_CTZ:
1711 11904 : case CFN_BUILT_IN_CTZG:
1712 11904 : {
1713 11904 : int tmp;
1714 11904 : if (wi::ne_p (arg0, 0))
1715 11812 : tmp = wi::ctz (arg0);
1716 : else
1717 92 : tmp = arg1.to_shwi ();
1718 11904 : *result = wi::shwi (tmp, precision);
1719 11904 : return true;
1720 : }
1721 :
1722 : default:
1723 : return false;
1724 : }
1725 : }
1726 :
1727 : /* Try to evaluate:
1728 :
1729 : RESULT = fn (ARG0, ARG1)
1730 :
1731 : where FORMAT is the format of the real and imaginary parts of RESULT
1732 : (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1733 : and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
1734 :
1735 : static bool
1736 32067 : fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1737 : combined_fn fn, const real_value *arg0_real,
1738 : const real_value *arg0_imag, const real_value *arg1_real,
1739 : const real_value *arg1_imag, const real_format *format)
1740 : {
1741 0 : switch (fn)
1742 : {
1743 32067 : CASE_CFN_CPOW:
1744 32067 : CASE_CFN_CPOW_FN:
1745 32067 : return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1746 0 : arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1747 :
1748 : default:
1749 : return false;
1750 : }
1751 : }
1752 :
1753 : /* Subroutine of fold_const_call, with the same interface. Handle cases
1754 : where the arguments and result are numerical. */
1755 :
1756 : static tree
1757 16825695 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1758 : {
1759 16825695 : machine_mode mode = TYPE_MODE (type);
1760 16825695 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1761 16825695 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1762 :
1763 16825695 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1764 : {
1765 426551 : if (SCALAR_INT_MODE_P (mode))
1766 : {
1767 417717 : wide_int result;
1768 417717 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1769 835434 : wi::to_wide (arg1), TYPE_PRECISION (type),
1770 417717 : TREE_TYPE (arg0)))
1771 28913 : return wide_int_to_tree (type, result);
1772 417717 : }
1773 : return NULL_TREE;
1774 : }
1775 :
1776 16399144 : if (mode == arg0_mode
1777 11217280 : && real_cst_p (arg0)
1778 17657052 : && real_cst_p (arg1))
1779 : {
1780 226256 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1781 226256 : REAL_VALUE_TYPE result;
1782 226256 : if (arg0_mode == arg1_mode)
1783 : {
1784 : /* real, real -> real. */
1785 451932 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1786 225966 : TREE_REAL_CST_PTR (arg1),
1787 225966 : REAL_MODE_FORMAT (mode)))
1788 194544 : return build_real (type, result);
1789 : }
1790 290 : else if (arg1_mode == TYPE_MODE (long_double_type_node))
1791 290 : switch (fn)
1792 : {
1793 290 : CASE_CFN_NEXTTOWARD:
1794 : /* real, long double -> real. */
1795 580 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1796 290 : TREE_REAL_CST_PTR (arg1),
1797 290 : REAL_MODE_FORMAT (mode)))
1798 228 : return build_real (type, result);
1799 : break;
1800 : default:
1801 : break;
1802 : }
1803 : return NULL_TREE;
1804 : }
1805 :
1806 16172888 : if (real_cst_p (arg0)
1807 16172888 : && integer_cst_p (arg1))
1808 : {
1809 25665 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1810 25665 : if (mode == arg0_mode)
1811 : {
1812 : /* real, int -> real. */
1813 25662 : REAL_VALUE_TYPE result;
1814 25662 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1815 51324 : wi::to_wide (arg1),
1816 25662 : REAL_MODE_FORMAT (mode)))
1817 5515 : return build_real (type, result);
1818 : }
1819 : return NULL_TREE;
1820 : }
1821 :
1822 16147223 : if (integer_cst_p (arg0)
1823 16147223 : && real_cst_p (arg1))
1824 : {
1825 6434 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1826 6434 : if (mode == arg1_mode)
1827 : {
1828 : /* int, real -> real. */
1829 6434 : REAL_VALUE_TYPE result;
1830 12868 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1831 6434 : TREE_REAL_CST_PTR (arg1),
1832 6434 : REAL_MODE_FORMAT (mode)))
1833 1755 : return build_real (type, result);
1834 : }
1835 : return NULL_TREE;
1836 : }
1837 :
1838 16140789 : if (arg0_mode == arg1_mode
1839 13235221 : && complex_cst_p (arg0)
1840 16172856 : && complex_cst_p (arg1))
1841 : {
1842 32067 : gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1843 32067 : machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1844 32067 : tree arg0r = TREE_REALPART (arg0);
1845 32067 : tree arg0i = TREE_IMAGPART (arg0);
1846 32067 : tree arg1r = TREE_REALPART (arg1);
1847 32067 : tree arg1i = TREE_IMAGPART (arg1);
1848 32067 : if (mode == arg0_mode
1849 32067 : && real_cst_p (arg0r)
1850 32067 : && real_cst_p (arg0i)
1851 32067 : && real_cst_p (arg1r)
1852 64134 : && real_cst_p (arg1i))
1853 : {
1854 : /* complex real, complex real -> complex real. */
1855 32067 : REAL_VALUE_TYPE result_real, result_imag;
1856 64134 : if (fold_const_call_ccc (&result_real, &result_imag, fn,
1857 32067 : TREE_REAL_CST_PTR (arg0r),
1858 32067 : TREE_REAL_CST_PTR (arg0i),
1859 32067 : TREE_REAL_CST_PTR (arg1r),
1860 32067 : TREE_REAL_CST_PTR (arg1i),
1861 32067 : REAL_MODE_FORMAT (inner_mode)))
1862 21470 : return build_complex (type,
1863 10735 : build_real (TREE_TYPE (type), result_real),
1864 21470 : build_real (TREE_TYPE (type), result_imag));
1865 : }
1866 : return NULL_TREE;
1867 : }
1868 :
1869 : return NULL_TREE;
1870 : }
1871 :
1872 : /* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
1873 : otherwise return null. TYPE is the type of the return value. */
1874 :
1875 : tree
1876 19620447 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1877 : {
1878 19620447 : const char *p0, *p1;
1879 19620447 : char c;
1880 19620447 : tree_code subcode;
1881 19620447 : switch (fn)
1882 : {
1883 2692 : case CFN_BUILT_IN_STRSPN:
1884 2692 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1885 123 : return build_int_cst (type, strspn (p0, p1));
1886 : return NULL_TREE;
1887 :
1888 2596 : case CFN_BUILT_IN_STRCSPN:
1889 2596 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1890 123 : return build_int_cst (type, strcspn (p0, p1));
1891 : return NULL_TREE;
1892 :
1893 2230019 : case CFN_BUILT_IN_STRCMP:
1894 2230019 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1895 24938 : return build_cmp_result (type, strcmp (p0, p1));
1896 : return NULL_TREE;
1897 :
1898 309 : case CFN_BUILT_IN_STRCASECMP:
1899 309 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1900 : {
1901 10 : int r = strcmp (p0, p1);
1902 10 : if (r == 0)
1903 1 : return build_cmp_result (type, r);
1904 : }
1905 : return NULL_TREE;
1906 :
1907 210966 : case CFN_BUILT_IN_INDEX:
1908 210966 : case CFN_BUILT_IN_STRCHR:
1909 210966 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1910 : {
1911 142 : const char *r = strchr (p0, c);
1912 142 : if (r == NULL)
1913 38 : return build_int_cst (type, 0);
1914 104 : return fold_convert (type,
1915 : fold_build_pointer_plus_hwi (arg0, r - p0));
1916 : }
1917 : return NULL_TREE;
1918 :
1919 201238 : case CFN_BUILT_IN_RINDEX:
1920 201238 : case CFN_BUILT_IN_STRRCHR:
1921 201238 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1922 : {
1923 103 : const char *r = strrchr (p0, c);
1924 103 : if (r == NULL)
1925 35 : return build_int_cst (type, 0);
1926 68 : return fold_convert (type,
1927 : fold_build_pointer_plus_hwi (arg0, r - p0));
1928 : }
1929 : return NULL_TREE;
1930 :
1931 108886 : case CFN_BUILT_IN_STRSTR:
1932 108886 : if ((p1 = c_getstr (arg1)))
1933 : {
1934 6023 : if ((p0 = c_getstr (arg0)))
1935 : {
1936 182 : const char *r = strstr (p0, p1);
1937 182 : if (r == NULL)
1938 38 : return build_int_cst (type, 0);
1939 144 : return fold_convert (type,
1940 : fold_build_pointer_plus_hwi (arg0, r - p0));
1941 : }
1942 5841 : if (*p1 == '\0')
1943 13 : return fold_convert (type, arg0);
1944 : }
1945 : return NULL_TREE;
1946 :
1947 19599 : case CFN_BUILT_IN_STRNLEN:
1948 19599 : if ((p0 = c_getstr (arg0)))
1949 : {
1950 3178 : unsigned HOST_WIDE_INT s1 = 0;
1951 3178 : if (!size_t_cst_p (arg1, &s1))
1952 : return NULL_TREE;
1953 :
1954 442 : return build_int_cst (type, strnlen (p0, s1));
1955 : }
1956 : return NULL_TREE;
1957 :
1958 0 : case CFN_FOLD_LEFT_PLUS:
1959 0 : return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1960 :
1961 0 : case CFN_VEC_SHL_INSERT:
1962 0 : return fold_const_vec_shl_insert (type, arg0, arg1);
1963 :
1964 0 : case CFN_VEC_EXTRACT:
1965 0 : return fold_const_vec_extract (type, arg0, arg1);
1966 :
1967 36 : case CFN_SAT_ADD:
1968 36 : return fold_internal_fn_sat_add (type, arg0, arg1);
1969 :
1970 6554 : case CFN_UBSAN_CHECK_ADD:
1971 6554 : case CFN_ADD_OVERFLOW:
1972 6554 : subcode = PLUS_EXPR;
1973 6554 : goto arith_overflow;
1974 :
1975 6366 : case CFN_UBSAN_CHECK_SUB:
1976 6366 : case CFN_SUB_OVERFLOW:
1977 6366 : subcode = MINUS_EXPR;
1978 6366 : goto arith_overflow;
1979 :
1980 5491 : case CFN_UBSAN_CHECK_MUL:
1981 5491 : case CFN_MUL_OVERFLOW:
1982 5491 : subcode = MULT_EXPR;
1983 5491 : goto arith_overflow;
1984 :
1985 18411 : arith_overflow:
1986 18411 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1987 : {
1988 17549 : tree itype
1989 17549 : = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
1990 17549 : bool ovf = false;
1991 17549 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
1992 17549 : fold_convert (itype, arg1));
1993 17549 : if (!r || TREE_CODE (r) != INTEGER_CST)
1994 : return NULL_TREE;
1995 17549 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
1996 : ovf = true;
1997 17549 : if (TREE_OVERFLOW (r))
1998 3443 : r = drop_tree_overflow (r);
1999 17549 : if (itype == type)
2000 : {
2001 2803 : if (ovf)
2002 : return NULL_TREE;
2003 1780 : return r;
2004 : }
2005 : else
2006 14746 : return build_complex (type, r, build_int_cst (itype, ovf));
2007 : }
2008 : return NULL_TREE;
2009 :
2010 16825695 : default:
2011 16825695 : return fold_const_call_1 (fn, type, arg0, arg1);
2012 : }
2013 : }
2014 :
2015 : /* Try to evaluate:
2016 :
2017 : *RESULT = FN (*ARG0, *ARG1, *ARG2)
2018 :
2019 : in format FORMAT. Return true on success. */
2020 :
2021 : static bool
2022 2534 : fold_const_call_ssss (real_value *result, combined_fn fn,
2023 : const real_value *arg0, const real_value *arg1,
2024 : const real_value *arg2, const real_format *format)
2025 : {
2026 2534 : switch (fn)
2027 : {
2028 2534 : CASE_CFN_FMA:
2029 2534 : CASE_CFN_FMA_FN:
2030 2534 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
2031 :
2032 0 : case CFN_FMS:
2033 0 : {
2034 0 : real_value new_arg2 = real_value_negate (arg2);
2035 0 : return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
2036 : }
2037 :
2038 0 : case CFN_FNMA:
2039 0 : {
2040 0 : real_value new_arg0 = real_value_negate (arg0);
2041 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
2042 : }
2043 :
2044 0 : case CFN_FNMS:
2045 0 : {
2046 0 : real_value new_arg0 = real_value_negate (arg0);
2047 0 : real_value new_arg2 = real_value_negate (arg2);
2048 0 : return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
2049 : &new_arg2, format);
2050 : }
2051 :
2052 : default:
2053 : return false;
2054 : }
2055 : }
2056 :
2057 : /* Subroutine of fold_const_call, with the same interface. Handle cases
2058 : where the arguments and result are numerical. */
2059 :
2060 : static tree
2061 4553175 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2062 : {
2063 4553175 : machine_mode mode = TYPE_MODE (type);
2064 4553175 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
2065 4553175 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
2066 4553175 : machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
2067 :
2068 4553175 : if (arg0_mode == arg1_mode
2069 4553175 : && arg0_mode == arg2_mode
2070 2020088 : && real_cst_p (arg0)
2071 2712 : && real_cst_p (arg1)
2072 4555815 : && real_cst_p (arg2))
2073 : {
2074 2534 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
2075 2534 : if (mode == arg0_mode)
2076 : {
2077 : /* real, real, real -> real. */
2078 2534 : REAL_VALUE_TYPE result;
2079 5068 : if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
2080 2534 : TREE_REAL_CST_PTR (arg1),
2081 2534 : TREE_REAL_CST_PTR (arg2),
2082 2534 : REAL_MODE_FORMAT (mode)))
2083 1060 : return build_real (type, result);
2084 : }
2085 : return NULL_TREE;
2086 : }
2087 :
2088 : return NULL_TREE;
2089 : }
2090 :
2091 : /* Given a CRC polynomial POLYNOMIAL_ARG, the current CRC value in CRC_ARG and
2092 : new data item DATA_ARG. Compute the updated CRC result value in type TYPE.
2093 : The CRC direction is inferred from FN (forward vs reversed). */
2094 :
2095 : static tree
2096 627 : fold_const_crc (internal_fn fn, tree type, tree crc_arg, tree data_arg,
2097 : tree polynomial_arg)
2098 : {
2099 627 : if (!integer_cst_p (crc_arg)
2100 109 : || !integer_cst_p (data_arg)
2101 664 : || !integer_cst_p (polynomial_arg))
2102 : return NULL_TREE;
2103 :
2104 37 : unsigned int crc_bits = TYPE_PRECISION (type);
2105 37 : unsigned int data_bits = TYPE_PRECISION (TREE_TYPE (data_arg));
2106 :
2107 37 : if ((data_bits != 8 && data_bits != 16 && data_bits != 32 && data_bits != 64)
2108 37 : || (crc_bits != 8 && crc_bits != 16 && crc_bits != 32 && crc_bits != 64)
2109 37 : || data_bits > crc_bits)
2110 : return NULL_TREE;
2111 :
2112 37 : if (!tree_fits_uhwi_p (crc_arg)
2113 37 : || !tree_fits_uhwi_p (data_arg)
2114 37 : || !tree_fits_uhwi_p (polynomial_arg))
2115 : return NULL_TREE;
2116 :
2117 37 : unsigned HOST_WIDE_INT crc = tree_to_uhwi (crc_arg);
2118 37 : unsigned HOST_WIDE_INT data = tree_to_uhwi (data_arg);
2119 37 : unsigned HOST_WIDE_INT polynomial = tree_to_uhwi (polynomial_arg);
2120 :
2121 37 : if (fn == IFN_CRC_REV)
2122 18 : crc = calculate_reversed_crc (crc, data, polynomial, crc_bits, data_bits);
2123 : else
2124 19 : crc = calculate_crc (crc, data, polynomial, crc_bits, data_bits);
2125 :
2126 37 : return build_int_cstu (type, crc);
2127 : }
2128 :
2129 : /* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
2130 : success, otherwise return null. TYPE is the type of the return value. */
2131 :
2132 : tree
2133 7456851 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2134 : {
2135 7456851 : const char *p0, *p1;
2136 7456851 : char c;
2137 7456851 : unsigned HOST_WIDE_INT s0, s1, s2 = 0;
2138 7456851 : switch (fn)
2139 : {
2140 45132 : case CFN_BUILT_IN_STRNCMP:
2141 45132 : if (!size_t_cst_p (arg2, &s2))
2142 : return NULL_TREE;
2143 29117 : if (s2 == 0
2144 237 : && !TREE_SIDE_EFFECTS (arg0)
2145 29326 : && !TREE_SIDE_EFFECTS (arg1))
2146 209 : return build_int_cst (type, 0);
2147 28908 : else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
2148 573 : return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
2149 : return NULL_TREE;
2150 :
2151 8207 : case CFN_BUILT_IN_STRNCASECMP:
2152 8207 : if (!size_t_cst_p (arg2, &s2))
2153 : return NULL_TREE;
2154 7886 : if (s2 == 0
2155 9 : && !TREE_SIDE_EFFECTS (arg0)
2156 7891 : && !TREE_SIDE_EFFECTS (arg1))
2157 5 : return build_int_cst (type, 0);
2158 7881 : else if ((p0 = c_getstr (arg0))
2159 724 : && (p1 = c_getstr (arg1))
2160 8021 : && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
2161 3 : return build_int_cst (type, 0);
2162 : return NULL_TREE;
2163 :
2164 2586146 : case CFN_BUILT_IN_BCMP:
2165 2586146 : case CFN_BUILT_IN_MEMCMP:
2166 2586146 : if (!size_t_cst_p (arg2, &s2))
2167 : return NULL_TREE;
2168 1637606 : if (s2 == 0
2169 13060 : && !TREE_SIDE_EFFECTS (arg0)
2170 1650666 : && !TREE_SIDE_EFFECTS (arg1))
2171 13060 : return build_int_cst (type, 0);
2172 1624546 : if ((p0 = getbyterep (arg0, &s0))
2173 12666 : && (p1 = getbyterep (arg1, &s1))
2174 3765 : && s2 <= s0
2175 1627865 : && s2 <= s1)
2176 3317 : return build_cmp_result (type, memcmp (p0, p1, s2));
2177 : return NULL_TREE;
2178 :
2179 263472 : case CFN_BUILT_IN_MEMCHR:
2180 263472 : if (!size_t_cst_p (arg2, &s2))
2181 : return NULL_TREE;
2182 7564 : if (s2 == 0
2183 151 : && !TREE_SIDE_EFFECTS (arg0)
2184 7698 : && !TREE_SIDE_EFFECTS (arg1))
2185 131 : return build_int_cst (type, 0);
2186 7433 : if ((p0 = getbyterep (arg0, &s0))
2187 2615 : && s2 <= s0
2188 9929 : && target_char_cst_p (arg1, &c))
2189 : {
2190 913 : const char *r = (const char *) memchr (p0, c, s2);
2191 913 : if (r == NULL)
2192 284 : return build_int_cst (type, 0);
2193 629 : return fold_convert (type,
2194 : fold_build_pointer_plus_hwi (arg0, r - p0));
2195 : }
2196 : return NULL_TREE;
2197 :
2198 0 : case CFN_WHILE_ULT:
2199 0 : {
2200 0 : poly_uint64 parg0, parg1;
2201 0 : if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
2202 0 : return fold_while_ult (type, parg0, parg1);
2203 : return NULL_TREE;
2204 : }
2205 :
2206 92 : case CFN_UADDC:
2207 92 : case CFN_USUBC:
2208 92 : if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
2209 : {
2210 92 : tree itype = TREE_TYPE (type);
2211 92 : bool ovf = false;
2212 92 : tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
2213 92 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
2214 92 : fold_convert (itype, arg1));
2215 92 : if (!r)
2216 : return NULL_TREE;
2217 92 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
2218 : ovf = true;
2219 92 : tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
2220 92 : if (!r2 || TREE_CODE (r2) != INTEGER_CST)
2221 : return NULL_TREE;
2222 92 : if (arith_overflowed_p (subcode, itype, r, arg2))
2223 0 : ovf = true;
2224 92 : if (TREE_OVERFLOW (r2))
2225 0 : r2 = drop_tree_overflow (r2);
2226 92 : return build_complex (type, r2, build_int_cst (itype, ovf));
2227 : }
2228 : return NULL_TREE;
2229 :
2230 627 : case CFN_BUILT_IN_CRC8_DATA8:
2231 627 : case CFN_BUILT_IN_CRC16_DATA8:
2232 627 : case CFN_BUILT_IN_CRC16_DATA16:
2233 627 : case CFN_BUILT_IN_CRC32_DATA8:
2234 627 : case CFN_BUILT_IN_CRC32_DATA16:
2235 627 : case CFN_BUILT_IN_CRC32_DATA32:
2236 627 : case CFN_BUILT_IN_CRC64_DATA8:
2237 627 : case CFN_BUILT_IN_CRC64_DATA16:
2238 627 : case CFN_BUILT_IN_CRC64_DATA32:
2239 627 : case CFN_BUILT_IN_CRC64_DATA64:
2240 627 : case CFN_BUILT_IN_REV_CRC8_DATA8:
2241 627 : case CFN_BUILT_IN_REV_CRC16_DATA8:
2242 627 : case CFN_BUILT_IN_REV_CRC16_DATA16:
2243 627 : case CFN_BUILT_IN_REV_CRC32_DATA8:
2244 627 : case CFN_BUILT_IN_REV_CRC32_DATA16:
2245 627 : case CFN_BUILT_IN_REV_CRC32_DATA32:
2246 627 : case CFN_BUILT_IN_REV_CRC64_DATA8:
2247 627 : case CFN_BUILT_IN_REV_CRC64_DATA16:
2248 627 : case CFN_BUILT_IN_REV_CRC64_DATA32:
2249 627 : case CFN_BUILT_IN_REV_CRC64_DATA64:
2250 627 : return fold_const_crc (associated_internal_fn (fn, type),
2251 627 : type, arg0, arg1, arg2);
2252 :
2253 4553175 : default:
2254 4553175 : return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2255 : }
2256 : }
|