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 42121528 : integer_cst_p (tree t)
40 : {
41 42121528 : return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
42 : }
43 :
44 : static inline bool
45 45909567 : real_cst_p (tree t)
46 : {
47 45909567 : return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
48 : }
49 :
50 : static inline bool
51 27984745 : complex_cst_p (tree t)
52 : {
53 27984745 : 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 2920220 : size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
61 : {
62 2920220 : if (types_compatible_p (size_type_node, TREE_TYPE (t))
63 2920065 : && integer_cst_p (t)
64 4604773 : && tree_fits_uhwi_p (t))
65 : {
66 1684553 : *size_out = tree_to_uhwi (t);
67 1684553 : 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 66444 : build_cmp_result (tree type, int res)
78 : {
79 71074 : 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 245609 : 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 245609 : if (!mpfr_number_p (m)
95 230604 : || mpfr_overflow_p ()
96 230604 : || mpfr_underflow_p ()
97 472669 : || (flag_rounding_math && inexact))
98 : return false;
99 :
100 226975 : REAL_VALUE_TYPE tmp;
101 226975 : 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 226975 : if (!real_isfinite (&tmp)
107 226975 : || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
108 : return false;
109 :
110 226975 : real_convert (result, format, &tmp);
111 226975 : 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 110026 : 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 110026 : if (format->b != 2 || !real_isfinite (arg))
129 : return false;
130 :
131 107284 : int prec = format->p;
132 107284 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
133 :
134 107284 : auto_mpfr m (prec);
135 107284 : mpfr_from_real (m, arg, MPFR_RNDN);
136 107284 : mpfr_clear_flags ();
137 107284 : bool inexact = func (m, m, rnd);
138 107284 : bool ok = do_mpfr_ckconv (result, m, inexact, format);
139 :
140 107284 : return ok;
141 107284 : }
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 144816 : 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 144816 : if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
190 : return false;
191 :
192 133736 : int prec = format->p;
193 133736 : mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
194 133736 : mpfr_t m0, m1;
195 :
196 133736 : mpfr_inits2 (prec, m0, m1, NULL);
197 133736 : mpfr_from_real (m0, arg0, MPFR_RNDN);
198 133736 : mpfr_from_real (m1, arg1, MPFR_RNDN);
199 133736 : mpfr_clear_flags ();
200 133736 : bool inexact = func (m0, m0, m1, rnd);
201 133736 : bool ok = do_mpfr_ckconv (result, m0, inexact, format);
202 133736 : mpfr_clears (m0, m1, NULL);
203 :
204 133736 : 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 127823 : fold_const_pow (real_value *result, const real_value *arg0,
496 : const real_value *arg1, const real_format *format)
497 : {
498 127823 : if (flag_signaling_nans
499 127823 : && (REAL_VALUE_ISSIGNALING_NAN (*arg0)
500 0 : || REAL_VALUE_ISSIGNALING_NAN (*arg1)))
501 : return false;
502 :
503 127823 : if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
504 : {
505 117479 : if (flag_errno_math)
506 117116 : 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 117479 : 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 12504 : fold_const_nextafter (real_value *result, const real_value *arg0,
534 : const real_value *arg1, const real_format *format)
535 : {
536 12504 : if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
537 12504 : || 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 12504 : if (format->pnan < format->p
543 12504 : || format->b == 10
544 12504 : || !format->has_inf
545 12504 : || !format->has_denorm)
546 : return false;
547 :
548 19368 : 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 12504 : && (flag_trapping_math || flag_errno_math))
552 : return false;
553 : /* Similarly for nextafter (0, 1) raising underflow. */
554 5640 : else if (flag_trapping_math
555 5133 : && arg0->cl == rvc_zero
556 4492 : && 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 406661 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
612 : {
613 406661 : REAL_VALUE_TYPE real;
614 406661 : const char *str = c_getstr (arg);
615 406661 : if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
616 406192 : 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 2017 : fold_const_reduction (tree type, tree arg, tree_code code)
624 : {
625 2017 : if (TREE_CODE (arg) != VECTOR_CST)
626 : return NULL_TREE;
627 :
628 4034 : bool idempotent_p = (code == MAX_EXPR
629 2017 : || code == MIN_EXPR
630 2017 : || code == BIT_AND_EXPR
631 : || code == BIT_IOR_EXPR);
632 :
633 2017 : 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 2017 : bool singleton_snan_p
638 : = (nelts == 1
639 2017 : && tree_expr_maybe_signaling_nan_p (VECTOR_CST_ELT (arg, 0)));
640 :
641 2017 : if (idempotent_p
642 400 : && !VECTOR_CST_STEPPED_P (arg)
643 1116 : && multiple_p (VECTOR_CST_NELTS (arg), nelts)
644 2389 : && !singleton_snan_p)
645 : /* Operating on the first NELTS elements is enough. */
646 : ;
647 1645 : else if (code == BIT_XOR_EXPR
648 4 : && !VECTOR_CST_STEPPED_P (arg)
649 1649 : && multiple_p (VECTOR_CST_NELTS (arg), nelts * 2))
650 : {
651 2 : 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 1643 : else if (!VECTOR_CST_NELTS (arg).is_constant (&nelts))
661 : return NULL_TREE;
662 :
663 2017 : tree res = VECTOR_CST_ELT (arg, 0);
664 27732 : for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
665 : {
666 23698 : res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
667 23698 : 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 6601 : fold_const_vec_convert (tree ret_type, tree arg)
677 : {
678 6601 : enum tree_code code = NOP_EXPR;
679 6601 : tree arg_type = TREE_TYPE (arg);
680 6601 : if (TREE_CODE (arg) != VECTOR_CST)
681 : return NULL_TREE;
682 :
683 6601 : gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
684 :
685 13202 : if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
686 13115 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
687 : code = FIX_TRUNC_EXPR;
688 13080 : else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
689 13080 : && 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 6601 : bool step_ok_p
695 13202 : = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
696 6514 : && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
697 13054 : && (TYPE_PRECISION (TREE_TYPE (ret_type))
698 6453 : <= TYPE_PRECISION (TREE_TYPE (arg_type))));
699 6601 : tree_vector_builder elts;
700 6601 : if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
701 : return NULL_TREE;
702 :
703 6601 : unsigned int count = elts.encoded_nelts ();
704 18334 : for (unsigned int i = 0; i < count; ++i)
705 : {
706 11739 : tree elt = fold_unary (code, TREE_TYPE (ret_type),
707 : VECTOR_CST_ELT (arg, i));
708 11739 : if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
709 6 : return NULL_TREE;
710 11733 : elts.quick_push (elt);
711 : }
712 :
713 6595 : return elts.build ();
714 6601 : }
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 162817 : fold_const_call_ss (real_value *result, combined_fn fn,
754 : const real_value *arg, const real_format *format)
755 : {
756 162817 : switch (fn)
757 : {
758 23164 : CASE_CFN_SQRT:
759 23164 : CASE_CFN_SQRT_FN:
760 23164 : return (real_compare (GE_EXPR, arg, &dconst0)
761 23164 : && 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 1454 : CASE_CFN_ACOSH:
788 1454 : CASE_CFN_ACOSH_FN:
789 1454 : return (real_compare (GE_EXPR, arg, &dconst1)
790 1454 : && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
791 :
792 1901 : CASE_CFN_ATANH:
793 1901 : CASE_CFN_ATANH_FN:
794 1901 : return (real_compare (GE_EXPR, arg, &dconstm1)
795 1901 : && real_compare (LE_EXPR, arg, &dconst1)
796 3802 : && 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 61659 : CASE_CFN_LOG:
881 61659 : CASE_CFN_LOG_FN:
882 61659 : return (real_compare (GT_EXPR, arg, &dconst0)
883 61659 : && do_mpfr_arg1 (result, mpfr_log, arg, format));
884 :
885 3130 : CASE_CFN_LOG2:
886 3130 : CASE_CFN_LOG2_FN:
887 3130 : return (real_compare (GT_EXPR, arg, &dconst0)
888 3130 : && do_mpfr_arg1 (result, mpfr_log2, arg, format));
889 :
890 3166 : CASE_CFN_LOG10:
891 3166 : CASE_CFN_LOG10_FN:
892 3166 : return (real_compare (GT_EXPR, arg, &dconst0)
893 3166 : && 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 2220270 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
1076 : unsigned int precision, tree arg_type)
1077 : {
1078 2220270 : 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 2197 : CASE_CFN_CLZ:
1086 2197 : case CFN_BUILT_IN_CLZG:
1087 2197 : {
1088 2197 : int tmp;
1089 2197 : if (wi::ne_p (arg, 0))
1090 1699 : tmp = wi::clz (arg);
1091 498 : else if (BITINT_TYPE_P (arg_type))
1092 9 : tmp = TYPE_PRECISION (arg_type);
1093 978 : else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
1094 : tmp))
1095 489 : tmp = TYPE_PRECISION (arg_type);
1096 2197 : *result = wi::shwi (tmp, precision);
1097 2197 : return true;
1098 : }
1099 :
1100 1545 : CASE_CFN_CTZ:
1101 1545 : case CFN_BUILT_IN_CTZG:
1102 1545 : {
1103 1545 : int tmp;
1104 1545 : if (wi::ne_p (arg, 0))
1105 1301 : 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 1545 : *result = wi::shwi (tmp, precision);
1112 1545 : 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 41960 : CASE_CFN_POPCOUNT:
1121 41960 : case CFN_BUILT_IN_POPCOUNTG:
1122 41960 : *result = wi::shwi (wi::popcount (arg), precision);
1123 41960 : 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 78 : CASE_CFN_BITREVERSE:
1136 156 : *result = wi::bitreverse (wide_int::from (arg, precision,
1137 156 : TYPE_SIGN (arg_type)));
1138 78 : 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 20748612 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
1308 : {
1309 20748612 : machine_mode mode = TYPE_MODE (type);
1310 20748612 : machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1311 :
1312 20748612 : if (integer_cst_p (arg))
1313 : {
1314 5897927 : if (INTEGRAL_TYPE_P (type))
1315 : {
1316 2220270 : wide_int result;
1317 2220270 : if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1318 2220270 : TYPE_PRECISION (type), TREE_TYPE (arg)))
1319 47974 : return wide_int_to_tree (type, result);
1320 2220270 : }
1321 : return NULL_TREE;
1322 : }
1323 :
1324 14850685 : if (real_cst_p (arg))
1325 : {
1326 180471 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1327 180471 : if (mode == arg_mode)
1328 : {
1329 : /* real -> real. */
1330 162817 : REAL_VALUE_TYPE result;
1331 162817 : if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1332 162817 : REAL_MODE_FORMAT (mode)))
1333 101435 : 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 14670214 : 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 21754907 : fold_const_call (combined_fn fn, tree type, tree arg)
1403 : {
1404 21754907 : switch (fn)
1405 : {
1406 591016 : case CFN_BUILT_IN_STRLEN:
1407 591016 : if (const char *str = c_getstr (arg))
1408 99869 : return build_int_cst (type, strlen (str));
1409 : return NULL_TREE;
1410 :
1411 235284 : CASE_CFN_NAN:
1412 235284 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1413 235284 : case CFN_BUILT_IN_NAND32:
1414 235284 : case CFN_BUILT_IN_NAND64:
1415 235284 : case CFN_BUILT_IN_NAND128:
1416 235284 : case CFN_BUILT_IN_NAND64X:
1417 235284 : return fold_const_builtin_nan (type, arg, true);
1418 :
1419 171377 : CASE_CFN_NANS:
1420 171377 : CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1421 171377 : case CFN_BUILT_IN_NANSF16B:
1422 171377 : case CFN_BUILT_IN_NANSD32:
1423 171377 : case CFN_BUILT_IN_NANSD64:
1424 171377 : case CFN_BUILT_IN_NANSD128:
1425 171377 : case CFN_BUILT_IN_NANSD64X:
1426 171377 : return fold_const_builtin_nan (type, arg, false);
1427 :
1428 1613 : case CFN_REDUC_PLUS:
1429 1613 : return fold_const_reduction (type, arg, PLUS_EXPR);
1430 :
1431 44 : case CFN_REDUC_MAX:
1432 44 : 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 32 : case CFN_REDUC_AND:
1438 32 : return fold_const_reduction (type, arg, BIT_AND_EXPR);
1439 :
1440 257 : case CFN_REDUC_IOR:
1441 257 : return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1442 :
1443 4 : case CFN_REDUC_XOR:
1444 4 : return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1445 :
1446 6601 : case CFN_VEC_CONVERT:
1447 6601 : return fold_const_vec_convert (type, arg);
1448 :
1449 20748612 : default:
1450 20748612 : 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 72 : fold_internal_fn_sat_add (tree type, tree op0, tree op1)
1519 : {
1520 72 : 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 226788 : 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 226788 : 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 127823 : CASE_CFN_POW:
1602 127823 : CASE_CFN_POW_FN:
1603 127823 : return fold_const_pow (result, arg0, arg1, format);
1604 :
1605 12504 : CASE_CFN_NEXTAFTER:
1606 12504 : CASE_CFN_NEXTAFTER_FN:
1607 12504 : case CFN_BUILT_IN_NEXTAFTERF16B:
1608 12504 : CASE_CFN_NEXTTOWARD:
1609 12504 : 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 389859 : 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 389859 : switch (fn)
1697 : {
1698 17050 : case CFN_CLZ:
1699 17050 : case CFN_BUILT_IN_CLZG:
1700 17050 : {
1701 17050 : int tmp;
1702 17050 : if (wi::ne_p (arg0, 0))
1703 16933 : tmp = wi::clz (arg0);
1704 : else
1705 117 : tmp = arg1.to_shwi ();
1706 17050 : *result = wi::shwi (tmp, precision);
1707 17050 : return true;
1708 : }
1709 :
1710 11936 : case CFN_CTZ:
1711 11936 : case CFN_BUILT_IN_CTZG:
1712 11936 : {
1713 11936 : int tmp;
1714 11936 : if (wi::ne_p (arg0, 0))
1715 11844 : tmp = wi::ctz (arg0);
1716 : else
1717 92 : tmp = arg1.to_shwi ();
1718 11936 : *result = wi::shwi (tmp, precision);
1719 11936 : 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 16886924 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1758 : {
1759 16886924 : machine_mode mode = TYPE_MODE (type);
1760 16886924 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1761 16886924 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1762 :
1763 16886924 : if (integer_cst_p (arg0) && integer_cst_p (arg1))
1764 : {
1765 427789 : if (INTEGRAL_TYPE_P (type))
1766 : {
1767 389859 : wide_int result;
1768 389859 : if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1769 779718 : wi::to_wide (arg1), TYPE_PRECISION (type),
1770 389859 : TREE_TYPE (arg0)))
1771 28986 : return wide_int_to_tree (type, result);
1772 389859 : }
1773 : return NULL_TREE;
1774 : }
1775 :
1776 16459135 : if (mode == arg0_mode
1777 11253366 : && real_cst_p (arg0)
1778 17717721 : && real_cst_p (arg1))
1779 : {
1780 226788 : gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1781 226788 : REAL_VALUE_TYPE result;
1782 226788 : if (arg0_mode == arg1_mode)
1783 : {
1784 : /* real, real -> real. */
1785 452996 : if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1786 226498 : TREE_REAL_CST_PTR (arg1),
1787 226498 : REAL_MODE_FORMAT (mode)))
1788 194986 : 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 16232347 : if (real_cst_p (arg0)
1807 16232347 : && 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 16206682 : if (integer_cst_p (arg0)
1823 16206682 : && 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 16200248 : if (arg0_mode == arg1_mode
1839 13282464 : && complex_cst_p (arg0)
1840 16232315 : && 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 19683331 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1877 : {
1878 19683331 : const char *p0, *p1;
1879 19683331 : char c;
1880 19683331 : tree_code subcode;
1881 19683331 : 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 2230375 : case CFN_BUILT_IN_STRCMP:
1894 2230375 : if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1895 24950 : 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 211512 : case CFN_BUILT_IN_INDEX:
1908 211512 : case CFN_BUILT_IN_STRCHR:
1909 211512 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1910 : {
1911 163 : const char *r = strchr (p0, c);
1912 163 : if (r == NULL)
1913 38 : return build_int_cst (type, 0);
1914 125 : return fold_convert (type,
1915 : fold_build_pointer_plus_hwi (arg0, r - p0));
1916 : }
1917 : return NULL_TREE;
1918 :
1919 201763 : case CFN_BUILT_IN_RINDEX:
1920 201763 : case CFN_BUILT_IN_STRRCHR:
1921 201763 : if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1922 : {
1923 124 : const char *r = strrchr (p0, c);
1924 124 : if (r == NULL)
1925 35 : return build_int_cst (type, 0);
1926 89 : return fold_convert (type,
1927 : fold_build_pointer_plus_hwi (arg0, r - p0));
1928 : }
1929 : return NULL_TREE;
1930 :
1931 109070 : case CFN_BUILT_IN_STRSTR:
1932 109070 : if ((p1 = c_getstr (arg1)))
1933 : {
1934 5978 : if ((p0 = c_getstr (arg0)))
1935 : {
1936 209 : const char *r = strstr (p0, p1);
1937 209 : if (r == NULL)
1938 44 : return build_int_cst (type, 0);
1939 165 : return fold_convert (type,
1940 : fold_build_pointer_plus_hwi (arg0, r - p0));
1941 : }
1942 5769 : if (*p1 == '\0')
1943 13 : return fold_convert (type, arg0);
1944 : }
1945 : return NULL_TREE;
1946 :
1947 19607 : case CFN_BUILT_IN_STRNLEN:
1948 19607 : 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 72 : case CFN_SAT_ADD:
1968 72 : 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 16886924 : default:
2011 16886924 : 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 4568344 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2062 : {
2063 4568344 : machine_mode mode = TYPE_MODE (type);
2064 4568344 : machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
2065 4568344 : machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
2066 4568344 : machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
2067 :
2068 4568344 : if (arg0_mode == arg1_mode
2069 4568344 : && arg0_mode == arg2_mode
2070 2029853 : && real_cst_p (arg0)
2071 2712 : && real_cst_p (arg1)
2072 4570984 : && 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 7486111 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
2134 : {
2135 7486111 : const char *p0, *p1;
2136 7486111 : char c;
2137 7486111 : unsigned HOST_WIDE_INT s0, s1, s2 = 0;
2138 7486111 : switch (fn)
2139 : {
2140 45148 : case CFN_BUILT_IN_STRNCMP:
2141 45148 : if (!size_t_cst_p (arg2, &s2))
2142 : return NULL_TREE;
2143 29133 : if (s2 == 0
2144 237 : && !TREE_SIDE_EFFECTS (arg0)
2145 29342 : && !TREE_SIDE_EFFECTS (arg1))
2146 209 : return build_int_cst (type, 0);
2147 28924 : 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 2598550 : case CFN_BUILT_IN_BCMP:
2165 2598550 : case CFN_BUILT_IN_MEMCMP:
2166 2598550 : if (!size_t_cst_p (arg2, &s2))
2167 : return NULL_TREE;
2168 1639388 : if (s2 == 0
2169 13060 : && !TREE_SIDE_EFFECTS (arg0)
2170 1652448 : && !TREE_SIDE_EFFECTS (arg1))
2171 13060 : return build_int_cst (type, 0);
2172 1626328 : if ((p0 = getbyterep (arg0, &s0))
2173 12674 : && (p1 = getbyterep (arg1, &s1))
2174 3771 : && s2 <= s0
2175 1629641 : && s2 <= s1)
2176 3311 : return build_cmp_result (type, memcmp (p0, p1, s2));
2177 : return NULL_TREE;
2178 :
2179 265137 : case CFN_BUILT_IN_MEMCHR:
2180 265137 : if (!size_t_cst_p (arg2, &s2))
2181 : return NULL_TREE;
2182 7704 : if (s2 == 0
2183 151 : && !TREE_SIDE_EFFECTS (arg0)
2184 7838 : && !TREE_SIDE_EFFECTS (arg1))
2185 131 : return build_int_cst (type, 0);
2186 7573 : if ((p0 = getbyterep (arg0, &s0))
2187 2733 : && s2 <= s0
2188 10187 : && target_char_cst_p (arg1, &c))
2189 : {
2190 1009 : const char *r = (const char *) memchr (p0, c, s2);
2191 1009 : if (r == NULL)
2192 290 : return build_int_cst (type, 0);
2193 719 : 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 98 : case CFN_UADDC:
2207 98 : case CFN_USUBC:
2208 98 : if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
2209 : {
2210 98 : tree itype = TREE_TYPE (type);
2211 98 : bool ovf = false;
2212 98 : tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
2213 98 : tree r = int_const_binop (subcode, fold_convert (itype, arg0),
2214 98 : fold_convert (itype, arg1));
2215 98 : if (!r)
2216 : return NULL_TREE;
2217 98 : if (arith_overflowed_p (subcode, itype, arg0, arg1))
2218 : ovf = true;
2219 98 : tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
2220 98 : if (!r2 || TREE_CODE (r2) != INTEGER_CST)
2221 : return NULL_TREE;
2222 98 : if (arith_overflowed_p (subcode, itype, r, arg2))
2223 0 : ovf = true;
2224 98 : if (TREE_OVERFLOW (r2))
2225 0 : r2 = drop_tree_overflow (r2);
2226 98 : 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 4568344 : default:
2254 4568344 : return fold_const_call_1 (fn, type, arg0, arg1, arg2);
2255 : }
2256 : }
|