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

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.