LCOV - code coverage report
Current view: top level - gcc - fold-const-call.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.5 % 1066 997
Test Date: 2026-02-28 14:20:25 Functions: 90.9 % 44 40
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.