LCOV - code coverage report
Current view: top level - gcc - fold-const-call.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.9 % 1086 998
Test Date: 2026-06-20 15:32:29 Functions: 88.9 % 45 40
Legend: Lines:     hit not hit

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

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.