LCOV - code coverage report
Current view: top level - gcc - fold-const-call.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.9 % 1093 1005
Test Date: 2026-05-30 15:37:04 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     33423949 : integer_cst_p (tree t)
      40              : {
      41     33423949 :   return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
      42              : }
      43              : 
      44              : static inline bool
      45     38078921 : real_cst_p (tree t)
      46              : {
      47     38078921 :   return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
      48              : }
      49              : 
      50              : static inline bool
      51     22212045 : complex_cst_p (tree t)
      52              : {
      53     22212045 :   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      2780772 : size_t_cst_p (tree t, unsigned HOST_WIDE_INT *size_out)
      61              : {
      62      2780772 :   if (types_compatible_p (size_type_node, TREE_TYPE (t))
      63      2780617 :       && integer_cst_p (t)
      64      4440009 :       && tree_fits_uhwi_p (t))
      65              :     {
      66      1659237 :       *size_out = tree_to_uhwi (t);
      67      1659237 :       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        66466 : build_cmp_result (tree type, int res)
      78              : {
      79        71072 :   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       238201 : 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       238201 :   if (!mpfr_number_p (m)
      95       223192 :       || mpfr_overflow_p ()
      96       223192 :       || mpfr_underflow_p ()
      97       457849 :       || (flag_rounding_math && inexact))
      98        18638 :     return false;
      99              : 
     100       219563 :   REAL_VALUE_TYPE tmp;
     101       219563 :   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       219563 :   if (!real_isfinite (&tmp)
     107       219563 :       || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
     108              :     return false;
     109              : 
     110       219563 :   real_convert (result, format, &tmp);
     111       219563 :   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       107057 : 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       107057 :   if (format->b != 2 || !real_isfinite (arg))
     129         2742 :     return false;
     130              : 
     131       104315 :   int prec = format->p;
     132       104315 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     133              : 
     134       104315 :   auto_mpfr m (prec);
     135       104315 :   mpfr_from_real (m, arg, MPFR_RNDN);
     136       104315 :   mpfr_clear_flags ();
     137       104315 :   bool inexact = func (m, m, rnd);
     138       104315 :   bool ok = do_mpfr_ckconv (result, m, inexact, format);
     139              : 
     140       104315 :   return ok;
     141       104315 : }
     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       140349 : 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       140349 :   if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
     190        11044 :     return false;
     191              : 
     192       129305 :   int prec = format->p;
     193       129305 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     194       129305 :   mpfr_t m0, m1;
     195              : 
     196       129305 :   mpfr_inits2 (prec, m0, m1, NULL);
     197       129305 :   mpfr_from_real (m0, arg0, MPFR_RNDN);
     198       129305 :   mpfr_from_real (m1, arg1, MPFR_RNDN);
     199       129305 :   mpfr_clear_flags ();
     200       129305 :   bool inexact = func (m0, m0, m1, rnd);
     201       129305 :   bool ok = do_mpfr_ckconv (result, m0, inexact, format);
     202       129305 :   mpfr_clears (m0, m1, NULL);
     203              : 
     204       129305 :   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       123363 : fold_const_pow (real_value *result, const real_value *arg0,
     496              :                 const real_value *arg1, const real_format *format)
     497              : {
     498       123363 :   if (flag_signaling_nans
     499       123363 :       && (REAL_VALUE_ISSIGNALING_NAN (*arg0)
     500            0 :           || REAL_VALUE_ISSIGNALING_NAN (*arg1)))
     501            0 :     return false;
     502              : 
     503       123363 :   if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
     504              :     {
     505       113055 :       if (flag_errno_math)
     506       112692 :         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        10776 : fold_const_nextafter (real_value *result, const real_value *arg0,
     534              :                       const real_value *arg1, const real_format *format)
     535              : {
     536        10776 :   if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
     537        10776 :       || 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        10776 :   if (format->pnan < format->p
     543        10776 :       || format->b == 10
     544        10776 :       || !format->has_inf
     545        10776 :       || !format->has_denorm)
     546              :     return false;
     547              : 
     548        16512 :   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        10776 :       && (flag_trapping_math || flag_errno_math))
     552         5736 :     return false;
     553              :   /* Similarly for nextafter (0, 1) raising underflow.  */
     554         5040 :   else if (flag_trapping_math
     555         4533 :            && arg0->cl == rvc_zero
     556         3916 :            && result->cl != rvc_zero)
     557              :     return false;
     558              : 
     559         1304 :   real_convert (result, format, result);
     560              : 
     561         1304 :   return true;
     562              : }
     563              : 
     564              : /* Try to evaluate:
     565              : 
     566              :       *RESULT = ldexp (*ARG0, ARG1)
     567              : 
     568              :    in format FORMAT.  Return true on success.  */
     569              : 
     570              : static bool
     571        25261 : fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
     572              :                                   const wide_int_ref &arg1,
     573              :                                   const real_format *format)
     574              : {
     575              :   /* Bound the maximum adjustment to twice the range of the
     576              :      mode's valid exponents.  Use abs to ensure the range is
     577              :      positive as a sanity check.  */
     578        25261 :   int max_exp_adj = 2 * labs (format->emax - format->emin);
     579              : 
     580              :   /* The requested adjustment must be inside this range.  This
     581              :      is a preliminary cap to avoid things like overflow, we
     582              :      may still fail to compute the result for other reasons.  */
     583        42736 :   if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
     584        15440 :     return false;
     585              : 
     586              :   /* Don't perform operation if we honor signaling NaNs and
     587              :      operand is a signaling NaN.  */
     588         9821 :   if (!flag_unsafe_math_optimizations
     589         9818 :       && flag_signaling_nans
     590         9941 :       && REAL_VALUE_ISSIGNALING_NAN (*arg0))
     591              :     return false;
     592              : 
     593         9821 :   REAL_VALUE_TYPE initial_result;
     594         9821 :   real_ldexp (&initial_result, arg0, arg1.to_shwi ());
     595              : 
     596              :   /* Ensure we didn't overflow.  */
     597         9821 :   if (real_isinf (&initial_result))
     598              :     return false;
     599              : 
     600              :   /* Only proceed if the target mode can hold the
     601              :      resulting value.  */
     602         9801 :   *result = real_value_truncate (format, initial_result);
     603         9801 :   return real_equal (&initial_result, result);
     604              : }
     605              : 
     606              : /* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
     607              :    return type TYPE.  QUIET is true if a quiet rather than signalling
     608              :    NaN is required.  */
     609              : 
     610              : static tree
     611       373260 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
     612              : {
     613       373260 :   REAL_VALUE_TYPE real;
     614       373260 :   const char *str = c_getstr (arg);
     615       373260 :   if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
     616       372791 :     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         2118 : fold_const_reduction (tree type, tree arg, tree_code code)
     624              : {
     625         2118 :   unsigned HOST_WIDE_INT nelts;
     626         2118 :   if (TREE_CODE (arg) != VECTOR_CST
     627         2118 :       || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
     628            0 :     return NULL_TREE;
     629              : 
     630         2118 :   tree res = VECTOR_CST_ELT (arg, 0);
     631        26494 :   for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
     632              :     {
     633        24376 :       res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
     634        24376 :       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       159700 : fold_const_call_ss (real_value *result, combined_fn fn,
     721              :                     const real_value *arg, const real_format *format)
     722              : {
     723       159700 :   switch (fn)
     724              :     {
     725        22407 :     CASE_CFN_SQRT:
     726        22407 :     CASE_CFN_SQRT_FN:
     727        22407 :       return (real_compare (GE_EXPR, arg, &dconst0)
     728        22407 :               && 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         1012 :     CASE_CFN_SIN:
     766         1012 :     CASE_CFN_SIN_FN:
     767         1012 :       return do_mpfr_arg1 (result, mpfr_sin, arg, format);
     768              : 
     769          848 :     CASE_CFN_COS:
     770          848 :     CASE_CFN_COS_FN:
     771          848 :       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          870 :     CASE_CFN_EXP:
     832          870 :     CASE_CFN_EXP_FN:
     833          870 :       return do_mpfr_arg1 (result, mpfr_exp, arg, format);
     834              : 
     835        10784 :     CASE_CFN_EXP2:
     836        10784 :     CASE_CFN_EXP2_FN:
     837        10784 :       return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
     838              : 
     839          698 :     CASE_CFN_EXP10:
     840          698 :     CASE_CFN_POW10:
     841          698 :       return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
     842              : 
     843          327 :     CASE_CFN_EXPM1:
     844          327 :     CASE_CFN_EXPM1_FN:
     845          327 :       return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
     846              : 
     847        59445 :     CASE_CFN_LOG:
     848        59445 :     CASE_CFN_LOG_FN:
     849        59445 :       return (real_compare (GT_EXPR, arg, &dconst0)
     850        59445 :               && 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      3548266 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
    1043              :                     unsigned int precision, tree arg_type)
    1044              : {
    1045      3548266 :   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         2151 :     CASE_CFN_CLZ:
    1053         2151 :     case CFN_BUILT_IN_CLZG:
    1054         2151 :       {
    1055         2151 :         int tmp;
    1056         2151 :         if (wi::ne_p (arg, 0))
    1057         1813 :           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         2151 :         *result = wi::shwi (tmp, precision);
    1064         2151 :         return true;
    1065              :       }
    1066              : 
    1067         1145 :     CASE_CFN_CTZ:
    1068         1145 :     case CFN_BUILT_IN_CTZG:
    1069         1145 :       {
    1070         1145 :         int tmp;
    1071         1145 :         if (wi::ne_p (arg, 0))
    1072          901 :           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         1145 :         *result = wi::shwi (tmp, precision);
    1079         1145 :         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        39436 :     CASE_CFN_POPCOUNT:
    1088        39436 :     case CFN_BUILT_IN_POPCOUNTG:
    1089        39436 :       *result = wi::shwi (wi::popcount (arg), precision);
    1090        39436 :       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_BUILT_IN_BSWAP16:
    1098          738 :     case CFN_BUILT_IN_BSWAP32:
    1099          738 :     case CFN_BUILT_IN_BSWAP64:
    1100          738 :     case CFN_BUILT_IN_BSWAP128:
    1101         1476 :       *result = wi::bswap (wide_int::from (arg, precision,
    1102         1476 :                                            TYPE_SIGN (arg_type)));
    1103          738 :       return true;
    1104              : 
    1105           47 :     case CFN_BUILT_IN_BITREVERSE8:
    1106           47 :     case CFN_BUILT_IN_BITREVERSE16:
    1107           47 :     case CFN_BUILT_IN_BITREVERSE32:
    1108           47 :     case CFN_BUILT_IN_BITREVERSE64:
    1109           47 :     case CFN_BUILT_IN_BITREVERSE128:
    1110           94 :       *result = wi::bitreverse (wide_int::from (arg, precision,
    1111           94 :                                                 TYPE_SIGN (arg_type)));
    1112           47 :       return true;
    1113              : 
    1114              :     default:
    1115              :       return false;
    1116              :     }
    1117              : }
    1118              : 
    1119              : /* Try to evaluate:
    1120              : 
    1121              :       RESULT = FN (*ARG)
    1122              : 
    1123              :    where FORMAT is the format of ARG and of the real and imaginary parts
    1124              :    of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively.  Return
    1125              :    true on success.  */
    1126              : 
    1127              : static bool
    1128          146 : fold_const_call_cs (real_value *result_real, real_value *result_imag,
    1129              :                     combined_fn fn, const real_value *arg,
    1130              :                     const real_format *format)
    1131              : {
    1132            0 :   switch (fn)
    1133              :     {
    1134          146 :     CASE_CFN_CEXPI:
    1135              :       /* cexpi(x+yi) = cos(x)+sin(y)*i.  */
    1136          146 :       return do_mpfr_sincos (result_imag, result_real, arg, format);
    1137              : 
    1138              :     default:
    1139              :       return false;
    1140              :     }
    1141              : }
    1142              : 
    1143              : /* Try to evaluate:
    1144              : 
    1145              :       *RESULT = fn (ARG)
    1146              : 
    1147              :    where FORMAT is the format of RESULT and of the real and imaginary parts
    1148              :    of ARG, passed as ARG_REAL and ARG_IMAG respectively.  Return true on
    1149              :    success.  */
    1150              : 
    1151              : static bool
    1152         2292 : fold_const_call_sc (real_value *result, combined_fn fn,
    1153              :                     const real_value *arg_real, const real_value *arg_imag,
    1154              :                     const real_format *format)
    1155              : {
    1156            0 :   switch (fn)
    1157              :     {
    1158         1156 :     CASE_CFN_CABS:
    1159         1156 :     CASE_CFN_CABS_FN:
    1160         1156 :       return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
    1161              : 
    1162              :     default:
    1163              :       return false;
    1164              :     }
    1165              : }
    1166              : 
    1167              : /* Try to evaluate:
    1168              : 
    1169              :       RESULT = fn (ARG)
    1170              : 
    1171              :    where FORMAT is the format of the real and imaginary parts of RESULT
    1172              :    (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
    1173              :    Return true on success.  */
    1174              : 
    1175              : static bool
    1176        39622 : fold_const_call_cc (real_value *result_real, real_value *result_imag,
    1177              :                     combined_fn fn, const real_value *arg_real,
    1178              :                     const real_value *arg_imag, const real_format *format)
    1179              : {
    1180        39622 :   switch (fn)
    1181              :     {
    1182          686 :     CASE_CFN_CCOS:
    1183          686 :     CASE_CFN_CCOS_FN:
    1184          686 :       return do_mpc_arg1 (result_real, result_imag, mpc_cos,
    1185          686 :                           arg_real, arg_imag, format);
    1186              : 
    1187          676 :     CASE_CFN_CCOSH:
    1188          676 :     CASE_CFN_CCOSH_FN:
    1189          676 :       return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
    1190          676 :                           arg_real, arg_imag, format);
    1191              : 
    1192          683 :     CASE_CFN_CPROJ:
    1193          683 :     CASE_CFN_CPROJ_FN:
    1194          683 :       if (real_isinf (arg_real) || real_isinf (arg_imag))
    1195              :         {
    1196          436 :           *result_real = dconstinf;
    1197          436 :           *result_imag = dconst0;
    1198          436 :           result_imag->sign = arg_imag->sign;
    1199              :         }
    1200              :       else
    1201              :         {
    1202          247 :           *result_real = *arg_real;
    1203          247 :           *result_imag = *arg_imag;
    1204              :         }
    1205              :       return true;
    1206              : 
    1207          701 :     CASE_CFN_CSIN:
    1208          701 :     CASE_CFN_CSIN_FN:
    1209          701 :       return do_mpc_arg1 (result_real, result_imag, mpc_sin,
    1210          701 :                           arg_real, arg_imag, format);
    1211              : 
    1212          676 :     CASE_CFN_CSINH:
    1213          676 :     CASE_CFN_CSINH_FN:
    1214          676 :       return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
    1215          676 :                           arg_real, arg_imag, format);
    1216              : 
    1217          698 :     CASE_CFN_CTAN:
    1218          698 :     CASE_CFN_CTAN_FN:
    1219          698 :       return do_mpc_arg1 (result_real, result_imag, mpc_tan,
    1220          698 :                           arg_real, arg_imag, format);
    1221              : 
    1222          676 :     CASE_CFN_CTANH:
    1223          676 :     CASE_CFN_CTANH_FN:
    1224          676 :       return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
    1225          676 :                           arg_real, arg_imag, format);
    1226              : 
    1227          777 :     CASE_CFN_CLOG:
    1228          777 :     CASE_CFN_CLOG_FN:
    1229          777 :       return do_mpc_arg1 (result_real, result_imag, mpc_log,
    1230          777 :                           arg_real, arg_imag, format);
    1231              : 
    1232         3053 :     CASE_CFN_CSQRT:
    1233         3053 :     CASE_CFN_CSQRT_FN:
    1234         3053 :       return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
    1235         3053 :                           arg_real, arg_imag, format);
    1236              : 
    1237          679 :     CASE_CFN_CASIN:
    1238          679 :     CASE_CFN_CASIN_FN:
    1239          679 :       return do_mpc_arg1 (result_real, result_imag, mpc_asin,
    1240          679 :                           arg_real, arg_imag, format);
    1241              : 
    1242          728 :     CASE_CFN_CACOS:
    1243          728 :     CASE_CFN_CACOS_FN:
    1244          728 :       return do_mpc_arg1 (result_real, result_imag, mpc_acos,
    1245          728 :                           arg_real, arg_imag, format);
    1246              : 
    1247          679 :     CASE_CFN_CATAN:
    1248          679 :     CASE_CFN_CATAN_FN:
    1249          679 :       return do_mpc_arg1 (result_real, result_imag, mpc_atan,
    1250          679 :                           arg_real, arg_imag, format);
    1251              : 
    1252          679 :     CASE_CFN_CASINH:
    1253          679 :     CASE_CFN_CASINH_FN:
    1254          679 :       return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
    1255          679 :                           arg_real, arg_imag, format);
    1256              : 
    1257          745 :     CASE_CFN_CACOSH:
    1258          745 :     CASE_CFN_CACOSH_FN:
    1259          745 :       return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
    1260          745 :                           arg_real, arg_imag, format);
    1261              : 
    1262          679 :     CASE_CFN_CATANH:
    1263          679 :     CASE_CFN_CATANH_FN:
    1264          679 :       return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
    1265          679 :                           arg_real, arg_imag, format);
    1266              : 
    1267         1583 :     CASE_CFN_CEXP:
    1268         1583 :     CASE_CFN_CEXP_FN:
    1269         1583 :       return do_mpc_arg1 (result_real, result_imag, mpc_exp,
    1270         1583 :                           arg_real, arg_imag, format);
    1271              : 
    1272              :     default:
    1273              :       return false;
    1274              :     }
    1275              : }
    1276              : 
    1277              : /* Subroutine of fold_const_call, with the same interface.  Handle cases
    1278              :    where the arguments and result are numerical.  */
    1279              : 
    1280              : static tree
    1281     14960554 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
    1282              : {
    1283     14960554 :   machine_mode mode = TYPE_MODE (type);
    1284     14960554 :   machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
    1285              : 
    1286     14960554 :   if (integer_cst_p (arg))
    1287              :     {
    1288      3663079 :       if (SCALAR_INT_MODE_P (mode))
    1289              :         {
    1290      3548266 :           wide_int result;
    1291      3548266 :           if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
    1292      3548266 :                                   TYPE_PRECISION (type), TREE_TYPE (arg)))
    1293        44965 :             return wide_int_to_tree (type, result);
    1294      3548266 :         }
    1295      3618114 :       return NULL_TREE;
    1296              :     }
    1297              : 
    1298     11297475 :   if (real_cst_p (arg))
    1299              :     {
    1300       177322 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
    1301       177322 :       if (mode == arg_mode)
    1302              :         {
    1303              :           /* real -> real.  */
    1304       159700 :           REAL_VALUE_TYPE result;
    1305       159700 :           if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
    1306       159700 :                                   REAL_MODE_FORMAT (mode)))
    1307        98447 :             return build_real (type, result);
    1308              :         }
    1309        17622 :       else if (COMPLEX_MODE_P (mode)
    1310        17768 :                && GET_MODE_INNER (mode) == arg_mode)
    1311              :         {
    1312              :           /* real -> complex real.  */
    1313          146 :           REAL_VALUE_TYPE result_real, result_imag;
    1314          292 :           if (fold_const_call_cs (&result_real, &result_imag, fn,
    1315          146 :                                   TREE_REAL_CST_PTR (arg),
    1316          146 :                                   REAL_MODE_FORMAT (arg_mode)))
    1317          292 :             return build_complex (type,
    1318          146 :                                   build_real (TREE_TYPE (type), result_real),
    1319          292 :                                   build_real (TREE_TYPE (type), result_imag));
    1320              :         }
    1321        17476 :       else if (INTEGRAL_TYPE_P (type))
    1322              :         {
    1323              :           /* real -> int.  */
    1324        17473 :           wide_int result;
    1325        17473 :           if (fold_const_call_ss (&result, fn,
    1326        17473 :                                   TREE_REAL_CST_PTR (arg),
    1327        17473 :                                   TYPE_PRECISION (type),
    1328        17473 :                                   REAL_MODE_FORMAT (arg_mode)))
    1329        11054 :             return wide_int_to_tree (type, result);
    1330        17473 :         }
    1331        67675 :       return NULL_TREE;
    1332              :     }
    1333              : 
    1334     11120153 :   if (complex_cst_p (arg))
    1335              :     {
    1336        41914 :       gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
    1337        41914 :       machine_mode inner_mode = GET_MODE_INNER (arg_mode);
    1338        41914 :       tree argr = TREE_REALPART (arg);
    1339        41914 :       tree argi = TREE_IMAGPART (arg);
    1340        41914 :       if (mode == arg_mode
    1341        39622 :           && real_cst_p (argr)
    1342        81536 :           && real_cst_p (argi))
    1343              :         {
    1344              :           /* complex real -> complex real.  */
    1345        39622 :           REAL_VALUE_TYPE result_real, result_imag;
    1346        79244 :           if (fold_const_call_cc (&result_real, &result_imag, fn,
    1347        39622 :                                   TREE_REAL_CST_PTR (argr),
    1348        39622 :                                   TREE_REAL_CST_PTR (argi),
    1349        39622 :                                   REAL_MODE_FORMAT (inner_mode)))
    1350        20972 :             return build_complex (type,
    1351        10486 :                                   build_real (TREE_TYPE (type), result_real),
    1352        20972 :                                   build_real (TREE_TYPE (type), result_imag));
    1353              :         }
    1354        31428 :       if (mode == inner_mode
    1355         2292 :           && real_cst_p (argr)
    1356        33720 :           && real_cst_p (argi))
    1357              :         {
    1358              :           /* complex real -> real.  */
    1359         2292 :           REAL_VALUE_TYPE result;
    1360         4584 :           if (fold_const_call_sc (&result, fn,
    1361         2292 :                                   TREE_REAL_CST_PTR (argr),
    1362         2292 :                                   TREE_REAL_CST_PTR (argi),
    1363         2292 :                                   REAL_MODE_FORMAT (inner_mode)))
    1364         1156 :             return build_real (type, result);
    1365              :         }
    1366        30272 :       return NULL_TREE;
    1367              :     }
    1368              : 
    1369              :   return NULL_TREE;
    1370              : }
    1371              : 
    1372              : /* Try to fold FN (ARG) to a constant.  Return the constant on success,
    1373              :    otherwise return null.  TYPE is the type of the return value.  */
    1374              : 
    1375              : tree
    1376     15877759 : fold_const_call (combined_fn fn, tree type, tree arg)
    1377              : {
    1378     15877759 :   switch (fn)
    1379              :     {
    1380       539639 :     case CFN_BUILT_IN_STRLEN:
    1381       539639 :       if (const char *str = c_getstr (arg))
    1382        90983 :         return build_int_cst (type, strlen (str));
    1383              :       return NULL_TREE;
    1384              : 
    1385       216731 :     CASE_CFN_NAN:
    1386       216731 :     CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
    1387       216731 :     case CFN_BUILT_IN_NAND32:
    1388       216731 :     case CFN_BUILT_IN_NAND64:
    1389       216731 :     case CFN_BUILT_IN_NAND128:
    1390       216731 :     case CFN_BUILT_IN_NAND64X:
    1391       216731 :       return fold_const_builtin_nan (type, arg, true);
    1392              : 
    1393       156529 :     CASE_CFN_NANS:
    1394       156529 :     CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
    1395       156529 :     case CFN_BUILT_IN_NANSF16B:
    1396       156529 :     case CFN_BUILT_IN_NANSD32:
    1397       156529 :     case CFN_BUILT_IN_NANSD64:
    1398       156529 :     case CFN_BUILT_IN_NANSD128:
    1399       156529 :     case CFN_BUILT_IN_NANSD64X:
    1400       156529 :       return fold_const_builtin_nan (type, arg, false);
    1401              : 
    1402         1713 :     case CFN_REDUC_PLUS:
    1403         1713 :       return fold_const_reduction (type, arg, PLUS_EXPR);
    1404              : 
    1405           47 :     case CFN_REDUC_MAX:
    1406           47 :       return fold_const_reduction (type, arg, MAX_EXPR);
    1407              : 
    1408           67 :     case CFN_REDUC_MIN:
    1409           67 :       return fold_const_reduction (type, arg, MIN_EXPR);
    1410              : 
    1411           34 :     case CFN_REDUC_AND:
    1412           34 :       return fold_const_reduction (type, arg, BIT_AND_EXPR);
    1413              : 
    1414          251 :     case CFN_REDUC_IOR:
    1415          251 :       return fold_const_reduction (type, arg, BIT_IOR_EXPR);
    1416              : 
    1417            6 :     case CFN_REDUC_XOR:
    1418            6 :       return fold_const_reduction (type, arg, BIT_XOR_EXPR);
    1419              : 
    1420         2188 :     case CFN_VEC_CONVERT:
    1421         2188 :       return fold_const_vec_convert (type, arg);
    1422              : 
    1423     14960554 :     default:
    1424     14960554 :       return fold_const_call_1 (fn, type, arg);
    1425              :     }
    1426              : }
    1427              : 
    1428              : /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
    1429              :    of type TYPE.  */
    1430              : 
    1431              : static tree
    1432            0 : fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
    1433              : {
    1434            0 :   if (TREE_CODE (arg1) != VECTOR_CST)
    1435              :     return NULL_TREE;
    1436              : 
    1437            0 :   unsigned HOST_WIDE_INT nelts;
    1438            0 :   if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
    1439              :     return NULL_TREE;
    1440              : 
    1441            0 :   for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
    1442              :     {
    1443            0 :       arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
    1444            0 :       if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
    1445              :         return NULL_TREE;
    1446              :     }
    1447              :   return arg0;
    1448              : }
    1449              : 
    1450              : /* Fold a call to IFN_VEC_SHL_INSERT (ARG0, ARG1), returning a value
    1451              :    of type TYPE.  */
    1452              : 
    1453              : static tree
    1454            0 : fold_const_vec_shl_insert (tree, tree arg0, tree arg1)
    1455              : {
    1456            0 :   if (TREE_CODE (arg0) != VECTOR_CST)
    1457              :     return NULL_TREE;
    1458              : 
    1459              :   /* vec_shl_insert ( dup(CST), CST) -> dup (CST). */
    1460            0 :   if (tree elem = uniform_vector_p (arg0))
    1461              :     {
    1462            0 :       if (operand_equal_p (elem, arg1))
    1463              :         return arg0;
    1464              :     }
    1465              : 
    1466              :   return NULL_TREE;
    1467              : }
    1468              : 
    1469              : /* Fold a call to IFN_VEC_EXTRACT (ARG0, ARG1), returning a value
    1470              :    of type TYPE.
    1471              : 
    1472              :    Right now this is only handling uniform vectors, so ARG1 is not
    1473              :    used.  But it could be easily adjusted in the future to handle
    1474              :    non-uniform vectors by extracting the relevant element.  */
    1475              : 
    1476              : static tree
    1477            0 : fold_const_vec_extract (tree, tree arg0, tree)
    1478              : {
    1479            0 :   if (TREE_CODE (arg0) != VECTOR_CST)
    1480              :     return NULL_TREE;
    1481              : 
    1482              :   /* vec_extract ( dup(CST), CST) -> dup (CST). */
    1483            0 :   if (tree elem = uniform_vector_p (arg0))
    1484              :     return elem;
    1485              : 
    1486              :   return NULL_TREE;
    1487              : }
    1488              : 
    1489              : /* Try to fold scalar integer IFN_SAT_ADD with operands OP0 and OP1.  */
    1490              : 
    1491              : static tree
    1492            0 : fold_internal_fn_sat_add (tree type, tree op0, tree op1)
    1493              : {
    1494            0 :   if (!INTEGRAL_NB_TYPE_P (type))
    1495              :     return NULL_TREE;
    1496              : 
    1497            0 :   if (TREE_CODE (op0) != INTEGER_CST
    1498            0 :       || TREE_CODE (op1) != INTEGER_CST)
    1499              :     return NULL_TREE;
    1500              : 
    1501            0 :   wi::overflow_type overflow;
    1502            0 :   unsigned int prec = TYPE_PRECISION (type);
    1503            0 :   wide_int result = wi::add (wi::to_wide (op0), wi::to_wide (op1),
    1504            0 :                              TYPE_SIGN (type), &overflow);
    1505              : 
    1506            0 :   if (overflow != wi::OVF_NONE)
    1507              :     {
    1508            0 :       if (TYPE_UNSIGNED (type))
    1509            0 :         result = wi::max_value (prec, UNSIGNED);
    1510            0 :       else if (overflow == wi::OVF_OVERFLOW)
    1511            0 :         result = wi::max_value (prec, SIGNED);
    1512            0 :       else if (overflow == wi::OVF_UNDERFLOW)
    1513            0 :         result = wi::min_value (prec, SIGNED);
    1514              :       else
    1515              :         return NULL_TREE;
    1516              :     }
    1517              : 
    1518            0 :   return wide_int_to_tree (type, result);
    1519            0 : }
    1520              : 
    1521              : /* Try to evaluate:
    1522              : 
    1523              :       *RESULT = FN (*ARG0, *ARG1)
    1524              : 
    1525              :    in format FORMAT.  Return true on success.  */
    1526              : 
    1527              : static bool
    1528       220597 : fold_const_call_sss (real_value *result, combined_fn fn,
    1529              :                      const real_value *arg0, const real_value *arg1,
    1530              :                      const real_format *format)
    1531              : {
    1532       220597 :   switch (fn)
    1533              :     {
    1534         6774 :     CASE_CFN_DREM:
    1535         6774 :     CASE_CFN_REMAINDER:
    1536         6774 :     CASE_CFN_REMAINDER_FN:
    1537         6774 :       return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
    1538              : 
    1539          983 :     CASE_CFN_ATAN2:
    1540          983 :     CASE_CFN_ATAN2_FN:
    1541          983 :       return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
    1542              : 
    1543              : #if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0)
    1544           84 :     CASE_CFN_ATAN2PI:
    1545           84 :     CASE_CFN_ATAN2PI_FN:
    1546           84 :       return do_mpfr_arg2 (result, mpfr_atan2pi, arg0, arg1, format);
    1547              : #endif
    1548              : 
    1549          572 :     CASE_CFN_FDIM:
    1550          572 :     CASE_CFN_FDIM_FN:
    1551          572 :       return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
    1552              : 
    1553          517 :     CASE_CFN_FMOD:
    1554          517 :     CASE_CFN_FMOD_FN:
    1555          517 :       return do_mpfr_arg2 (result, mpfr_fmod, arg0, arg1, format);
    1556              : 
    1557          578 :     CASE_CFN_HYPOT:
    1558          578 :     CASE_CFN_HYPOT_FN:
    1559          578 :       return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
    1560              : 
    1561        70628 :     CASE_CFN_COPYSIGN:
    1562        70628 :     CASE_CFN_COPYSIGN_FN:
    1563        70628 :       *result = *arg0;
    1564        70628 :       real_copysign (result, arg1);
    1565        70628 :       return true;
    1566              : 
    1567         3161 :     CASE_CFN_FMIN:
    1568         3161 :     CASE_CFN_FMIN_FN:
    1569         3161 :       return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
    1570              : 
    1571         3161 :     CASE_CFN_FMAX:
    1572         3161 :     CASE_CFN_FMAX_FN:
    1573         3161 :       return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
    1574              : 
    1575       123363 :     CASE_CFN_POW:
    1576       123363 :     CASE_CFN_POW_FN:
    1577       123363 :       return fold_const_pow (result, arg0, arg1, format);
    1578              : 
    1579        10776 :     CASE_CFN_NEXTAFTER:
    1580        10776 :     CASE_CFN_NEXTAFTER_FN:
    1581        10776 :     case CFN_BUILT_IN_NEXTAFTERF16B:
    1582        10776 :     CASE_CFN_NEXTTOWARD:
    1583        10776 :       return fold_const_nextafter (result, arg0, arg1, format);
    1584              : 
    1585              :     default:
    1586              :       return false;
    1587              :     }
    1588              : }
    1589              : 
    1590              : /* Try to evaluate:
    1591              : 
    1592              :       *RESULT = FN (*ARG0, ARG1)
    1593              : 
    1594              :    where FORMAT is the format of *RESULT and *ARG0.  Return true on
    1595              :    success.  */
    1596              : 
    1597              : static bool
    1598        25700 : fold_const_call_sss (real_value *result, combined_fn fn,
    1599              :                      const real_value *arg0, const wide_int_ref &arg1,
    1600              :                      const real_format *format)
    1601              : {
    1602        25700 :   switch (fn)
    1603              :     {
    1604         7912 :     CASE_CFN_LDEXP:
    1605         7912 :     CASE_CFN_LDEXP_FN:
    1606         7912 :       return fold_const_builtin_load_exponent (result, arg0, arg1, format);
    1607              : 
    1608        17349 :     CASE_CFN_SCALBN:
    1609        17349 :     CASE_CFN_SCALBN_FN:
    1610        17349 :     CASE_CFN_SCALBLN:
    1611        17349 :     CASE_CFN_SCALBLN_FN:
    1612        17349 :       return (format->b == 2
    1613        17349 :               && fold_const_builtin_load_exponent (result, arg0, arg1,
    1614              :                                                    format));
    1615              : 
    1616          430 :     CASE_CFN_POWI:
    1617              :       /* Avoid the folding if flag_signaling_nans is on and
    1618              :          operand is a signaling NaN.  */
    1619          430 :       if (!flag_unsafe_math_optimizations
    1620          417 :           && flag_signaling_nans
    1621          445 :           && REAL_VALUE_ISSIGNALING_NAN (*arg0))
    1622              :         return false;
    1623              : 
    1624          430 :       real_powi (result, format, arg0, arg1.to_shwi ());
    1625          430 :       return true;
    1626              : 
    1627              :     default:
    1628              :       return false;
    1629              :     }
    1630              : }
    1631              : 
    1632              : /* Try to evaluate:
    1633              : 
    1634              :       *RESULT = FN (ARG0, *ARG1)
    1635              : 
    1636              :    where FORMAT is the format of *RESULT and *ARG1.  Return true on
    1637              :    success.  */
    1638              : 
    1639              : static bool
    1640         6434 : fold_const_call_sss (real_value *result, combined_fn fn,
    1641              :                      const wide_int_ref &arg0, const real_value *arg1,
    1642              :                      const real_format *format)
    1643              : {
    1644         6434 :   switch (fn)
    1645              :     {
    1646         1220 :     CASE_CFN_JN:
    1647         1220 :       return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
    1648              : 
    1649         5205 :     CASE_CFN_YN:
    1650         5205 :       return (real_compare (GT_EXPR, arg1, &dconst0)
    1651         5205 :               && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
    1652              : 
    1653              :     default:
    1654              :       return false;
    1655              :     }
    1656              : }
    1657              : 
    1658              : /* Try to evaluate:
    1659              : 
    1660              :       *RESULT = FN (ARG0, ARG1)
    1661              : 
    1662              :    where ARG_TYPE is the type of ARG0 and PRECISION is the number of bits in
    1663              :    the result.  Return true on success.  */
    1664              : 
    1665              : static bool
    1666       314972 : fold_const_call_sss (wide_int *result, combined_fn fn,
    1667              :                      const wide_int_ref &arg0, const wide_int_ref &arg1,
    1668              :                      unsigned int precision, tree arg_type ATTRIBUTE_UNUSED)
    1669              : {
    1670       314972 :   switch (fn)
    1671              :     {
    1672        14762 :     case CFN_CLZ:
    1673        14762 :     case CFN_BUILT_IN_CLZG:
    1674        14762 :       {
    1675        14762 :         int tmp;
    1676        14762 :         if (wi::ne_p (arg0, 0))
    1677        14638 :           tmp = wi::clz (arg0);
    1678              :         else
    1679          124 :           tmp = arg1.to_shwi ();
    1680        14762 :         *result = wi::shwi (tmp, precision);
    1681        14762 :         return true;
    1682              :       }
    1683              : 
    1684        11571 :     case CFN_CTZ:
    1685        11571 :     case CFN_BUILT_IN_CTZG:
    1686        11571 :       {
    1687        11571 :         int tmp;
    1688        11571 :         if (wi::ne_p (arg0, 0))
    1689        11479 :           tmp = wi::ctz (arg0);
    1690              :         else
    1691           92 :           tmp = arg1.to_shwi ();
    1692        11571 :         *result = wi::shwi (tmp, precision);
    1693        11571 :         return true;
    1694              :       }
    1695              : 
    1696              :     default:
    1697              :       return false;
    1698              :     }
    1699              : }
    1700              : 
    1701              : /* Try to evaluate:
    1702              : 
    1703              :       RESULT = fn (ARG0, ARG1)
    1704              : 
    1705              :    where FORMAT is the format of the real and imaginary parts of RESULT
    1706              :    (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
    1707              :    and of ARG1 (ARG1_REAL and ARG1_IMAG).  Return true on success.  */
    1708              : 
    1709              : static bool
    1710        32067 : fold_const_call_ccc (real_value *result_real, real_value *result_imag,
    1711              :                      combined_fn fn, const real_value *arg0_real,
    1712              :                      const real_value *arg0_imag, const real_value *arg1_real,
    1713              :                      const real_value *arg1_imag, const real_format *format)
    1714              : {
    1715            0 :   switch (fn)
    1716              :     {
    1717        32067 :     CASE_CFN_CPOW:
    1718        32067 :     CASE_CFN_CPOW_FN:
    1719        32067 :       return do_mpc_arg2 (result_real, result_imag, mpc_pow,
    1720            0 :                           arg0_real, arg0_imag, arg1_real, arg1_imag, format);
    1721              : 
    1722              :     default:
    1723              :       return false;
    1724              :     }
    1725              : }
    1726              : 
    1727              : /* Subroutine of fold_const_call, with the same interface.  Handle cases
    1728              :    where the arguments and result are numerical.  */
    1729              : 
    1730              : static tree
    1731     14228473 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
    1732              : {
    1733     14228473 :   machine_mode mode = TYPE_MODE (type);
    1734     14228473 :   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
    1735     14228473 :   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
    1736              : 
    1737     14228473 :   if (integer_cst_p (arg0) && integer_cst_p (arg1))
    1738              :     {
    1739       320641 :       if (SCALAR_INT_MODE_P (mode))
    1740              :         {
    1741       314972 :           wide_int result;
    1742       314972 :           if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
    1743       629944 :                                    wi::to_wide (arg1), TYPE_PRECISION (type),
    1744       314972 :                                    TREE_TYPE (arg0)))
    1745        26333 :             return wide_int_to_tree (type, result);
    1746       314972 :         }
    1747       294308 :       return NULL_TREE;
    1748              :     }
    1749              : 
    1750     13907832 :   if (mode == arg0_mode
    1751      9761963 :       && real_cst_p (arg0)
    1752     15160448 :       && real_cst_p (arg1))
    1753              :     {
    1754       220597 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
    1755       220597 :       REAL_VALUE_TYPE result;
    1756       220597 :       if (arg0_mode == arg1_mode)
    1757              :         {
    1758              :           /* real, real -> real.  */
    1759       440614 :           if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1760       220307 :                                    TREE_REAL_CST_PTR (arg1),
    1761       220307 :                                    REAL_MODE_FORMAT (mode)))
    1762       190535 :             return build_real (type, result);
    1763              :         }
    1764          290 :       else if (arg1_mode == TYPE_MODE (long_double_type_node))
    1765          290 :         switch (fn)
    1766              :           {
    1767          290 :           CASE_CFN_NEXTTOWARD:
    1768              :             /* real, long double -> real.  */
    1769          580 :             if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1770          290 :                                      TREE_REAL_CST_PTR (arg1),
    1771          290 :                                      REAL_MODE_FORMAT (mode)))
    1772          228 :               return build_real (type, result);
    1773              :             break;
    1774              :           default:
    1775              :             break;
    1776              :           }
    1777        29834 :       return NULL_TREE;
    1778              :     }
    1779              : 
    1780     13687235 :   if (real_cst_p (arg0)
    1781     13687235 :       && integer_cst_p (arg1))
    1782              :     {
    1783        25703 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
    1784        25703 :       if (mode == arg0_mode)
    1785              :         {
    1786              :           /* real, int -> real.  */
    1787        25700 :           REAL_VALUE_TYPE result;
    1788        25700 :           if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1789        51400 :                                    wi::to_wide (arg1),
    1790        25700 :                                    REAL_MODE_FORMAT (mode)))
    1791         5553 :             return build_real (type, result);
    1792              :         }
    1793        20150 :       return NULL_TREE;
    1794              :     }
    1795              : 
    1796     13661532 :   if (integer_cst_p (arg0)
    1797     13661532 :       && real_cst_p (arg1))
    1798              :     {
    1799         6434 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
    1800         6434 :       if (mode == arg1_mode)
    1801              :         {
    1802              :           /* int, real -> real.  */
    1803         6434 :           REAL_VALUE_TYPE result;
    1804        12868 :           if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
    1805         6434 :                                    TREE_REAL_CST_PTR (arg1),
    1806         6434 :                                    REAL_MODE_FORMAT (mode)))
    1807         1755 :             return build_real (type, result);
    1808              :         }
    1809         4679 :       return NULL_TREE;
    1810              :     }
    1811              : 
    1812     13655098 :   if (arg0_mode == arg1_mode
    1813     11059825 :       && complex_cst_p (arg0)
    1814     13687165 :       && complex_cst_p (arg1))
    1815              :     {
    1816        32067 :       gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
    1817        32067 :       machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
    1818        32067 :       tree arg0r = TREE_REALPART (arg0);
    1819        32067 :       tree arg0i = TREE_IMAGPART (arg0);
    1820        32067 :       tree arg1r = TREE_REALPART (arg1);
    1821        32067 :       tree arg1i = TREE_IMAGPART (arg1);
    1822        32067 :       if (mode == arg0_mode
    1823        32067 :           && real_cst_p (arg0r)
    1824        32067 :           && real_cst_p (arg0i)
    1825        32067 :           && real_cst_p (arg1r)
    1826        64134 :           && real_cst_p (arg1i))
    1827              :         {
    1828              :           /* complex real, complex real -> complex real.  */
    1829        32067 :           REAL_VALUE_TYPE result_real, result_imag;
    1830        64134 :           if (fold_const_call_ccc (&result_real, &result_imag, fn,
    1831        32067 :                                    TREE_REAL_CST_PTR (arg0r),
    1832        32067 :                                    TREE_REAL_CST_PTR (arg0i),
    1833        32067 :                                    TREE_REAL_CST_PTR (arg1r),
    1834        32067 :                                    TREE_REAL_CST_PTR (arg1i),
    1835        32067 :                                    REAL_MODE_FORMAT (inner_mode)))
    1836        21470 :             return build_complex (type,
    1837        10735 :                                   build_real (TREE_TYPE (type), result_real),
    1838        21470 :                                   build_real (TREE_TYPE (type), result_imag));
    1839              :         }
    1840        21332 :       return NULL_TREE;
    1841              :     }
    1842              : 
    1843              :   return NULL_TREE;
    1844              : }
    1845              : 
    1846              : /* Try to fold FN (ARG0, ARG1) to a constant.  Return the constant on success,
    1847              :    otherwise return null.  TYPE is the type of the return value.  */
    1848              : 
    1849              : tree
    1850     16869103 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
    1851              : {
    1852     16869103 :   const char *p0, *p1;
    1853     16869103 :   char c;
    1854     16869103 :   tree_code subcode;
    1855     16869103 :   switch (fn)
    1856              :     {
    1857         2692 :     case CFN_BUILT_IN_STRSPN:
    1858         2692 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1859          123 :         return build_int_cst (type, strspn (p0, p1));
    1860              :       return NULL_TREE;
    1861              : 
    1862         2596 :     case CFN_BUILT_IN_STRCSPN:
    1863         2596 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1864          123 :         return build_int_cst (type, strcspn (p0, p1));
    1865              :       return NULL_TREE;
    1866              : 
    1867      2209309 :     case CFN_BUILT_IN_STRCMP:
    1868      2209309 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1869        24934 :         return build_cmp_result (type, strcmp (p0, p1));
    1870              :       return NULL_TREE;
    1871              : 
    1872          269 :     case CFN_BUILT_IN_STRCASECMP:
    1873          269 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1874              :         {
    1875           10 :           int r = strcmp (p0, p1);
    1876           10 :           if (r == 0)
    1877            1 :             return build_cmp_result (type, r);
    1878              :         }
    1879              :       return NULL_TREE;
    1880              : 
    1881       165680 :     case CFN_BUILT_IN_INDEX:
    1882       165680 :     case CFN_BUILT_IN_STRCHR:
    1883       165680 :       if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
    1884              :         {
    1885          136 :           const char *r = strchr (p0, c);
    1886          136 :           if (r == NULL)
    1887           32 :             return build_int_cst (type, 0);
    1888          104 :           return fold_convert (type,
    1889              :                                fold_build_pointer_plus_hwi (arg0, r - p0));
    1890              :         }
    1891              :       return NULL_TREE;
    1892              : 
    1893       155891 :     case CFN_BUILT_IN_RINDEX:
    1894       155891 :     case CFN_BUILT_IN_STRRCHR:
    1895       155891 :       if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
    1896              :         {
    1897          103 :           const char *r = strrchr (p0, c);
    1898          103 :           if (r == NULL)
    1899           35 :             return build_int_cst (type, 0);
    1900           68 :           return fold_convert (type,
    1901              :                                fold_build_pointer_plus_hwi (arg0, r - p0));
    1902              :         }
    1903              :       return NULL_TREE;
    1904              : 
    1905        86100 :     case CFN_BUILT_IN_STRSTR:
    1906        86100 :       if ((p1 = c_getstr (arg1)))
    1907              :         {
    1908         5951 :           if ((p0 = c_getstr (arg0)))
    1909              :             {
    1910          182 :               const char *r = strstr (p0, p1);
    1911          182 :               if (r == NULL)
    1912           38 :                 return build_int_cst (type, 0);
    1913          144 :               return fold_convert (type,
    1914              :                                    fold_build_pointer_plus_hwi (arg0, r - p0));
    1915              :             }
    1916         5769 :           if (*p1 == '\0')
    1917           13 :             return fold_convert (type, arg0);
    1918              :         }
    1919              :       return NULL_TREE;
    1920              : 
    1921            0 :     case CFN_FOLD_LEFT_PLUS:
    1922            0 :       return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
    1923              : 
    1924            0 :     case CFN_VEC_SHL_INSERT:
    1925            0 :       return fold_const_vec_shl_insert (type, arg0, arg1);
    1926              : 
    1927            0 :     case CFN_VEC_EXTRACT:
    1928            0 :       return fold_const_vec_extract (type, arg0, arg1);
    1929              : 
    1930            0 :     case CFN_SAT_ADD:
    1931            0 :       return fold_internal_fn_sat_add (type, arg0, arg1);
    1932              : 
    1933         6398 :     case CFN_UBSAN_CHECK_ADD:
    1934         6398 :     case CFN_ADD_OVERFLOW:
    1935         6398 :       subcode = PLUS_EXPR;
    1936         6398 :       goto arith_overflow;
    1937              : 
    1938         6317 :     case CFN_UBSAN_CHECK_SUB:
    1939         6317 :     case CFN_SUB_OVERFLOW:
    1940         6317 :       subcode = MINUS_EXPR;
    1941         6317 :       goto arith_overflow;
    1942              : 
    1943         5378 :     case CFN_UBSAN_CHECK_MUL:
    1944         5378 :     case CFN_MUL_OVERFLOW:
    1945         5378 :       subcode = MULT_EXPR;
    1946         5378 :       goto arith_overflow;
    1947              : 
    1948        18093 :     arith_overflow:
    1949        18093 :       if (integer_cst_p (arg0) && integer_cst_p (arg1))
    1950              :         {
    1951        17234 :           tree itype
    1952        17234 :             = TREE_CODE (type) == COMPLEX_TYPE ? TREE_TYPE (type) : type;
    1953        17234 :           bool ovf = false;
    1954        17234 :           tree r = int_const_binop (subcode, fold_convert (itype, arg0),
    1955        17234 :                                     fold_convert (itype, arg1));
    1956        17234 :           if (!r || TREE_CODE (r) != INTEGER_CST)
    1957              :             return NULL_TREE;
    1958        17234 :           if (arith_overflowed_p (subcode, itype, arg0, arg1))
    1959              :             ovf = true;
    1960        17234 :           if (TREE_OVERFLOW (r))
    1961         3434 :             r = drop_tree_overflow (r);
    1962        17234 :           if (itype == type)
    1963              :             {
    1964         2737 :               if (ovf)
    1965              :                 return NULL_TREE;
    1966              :               return r;
    1967              :             }
    1968              :           else
    1969        14497 :             return build_complex (type, r, build_int_cst (itype, ovf));
    1970              :         }
    1971              :       return NULL_TREE;
    1972              : 
    1973     14228473 :     default:
    1974     14228473 :       return fold_const_call_1 (fn, type, arg0, arg1);
    1975              :     }
    1976              : }
    1977              : 
    1978              : /* Try to evaluate:
    1979              : 
    1980              :       *RESULT = FN (*ARG0, *ARG1, *ARG2)
    1981              : 
    1982              :    in format FORMAT.  Return true on success.  */
    1983              : 
    1984              : static bool
    1985         2534 : fold_const_call_ssss (real_value *result, combined_fn fn,
    1986              :                       const real_value *arg0, const real_value *arg1,
    1987              :                       const real_value *arg2, const real_format *format)
    1988              : {
    1989         2534 :   switch (fn)
    1990              :     {
    1991         2534 :     CASE_CFN_FMA:
    1992         2534 :     CASE_CFN_FMA_FN:
    1993         2534 :       return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
    1994              : 
    1995            0 :     case CFN_FMS:
    1996            0 :       {
    1997            0 :         real_value new_arg2 = real_value_negate (arg2);
    1998            0 :         return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
    1999              :       }
    2000              : 
    2001            0 :     case CFN_FNMA:
    2002            0 :       {
    2003            0 :         real_value new_arg0 = real_value_negate (arg0);
    2004            0 :         return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
    2005              :       }
    2006              : 
    2007            0 :     case CFN_FNMS:
    2008            0 :       {
    2009            0 :         real_value new_arg0 = real_value_negate (arg0);
    2010            0 :         real_value new_arg2 = real_value_negate (arg2);
    2011            0 :         return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
    2012              :                              &new_arg2, format);
    2013              :       }
    2014              : 
    2015              :     default:
    2016              :       return false;
    2017              :     }
    2018              : }
    2019              : 
    2020              : /* Subroutine of fold_const_call, with the same interface.  Handle cases
    2021              :    where the arguments and result are numerical.  */
    2022              : 
    2023              : static tree
    2024      4139183 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
    2025              : {
    2026      4139183 :   machine_mode mode = TYPE_MODE (type);
    2027      4139183 :   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
    2028      4139183 :   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
    2029      4139183 :   machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
    2030              : 
    2031      4139183 :   if (arg0_mode == arg1_mode
    2032      4139183 :       && arg0_mode == arg2_mode
    2033      1798179 :       && real_cst_p (arg0)
    2034         2712 :       && real_cst_p (arg1)
    2035      4141823 :       && real_cst_p (arg2))
    2036              :     {
    2037         2534 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
    2038         2534 :       if (mode == arg0_mode)
    2039              :         {
    2040              :           /* real, real, real -> real.  */
    2041         2534 :           REAL_VALUE_TYPE result;
    2042         5068 :           if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
    2043         2534 :                                     TREE_REAL_CST_PTR (arg1),
    2044         2534 :                                     TREE_REAL_CST_PTR (arg2),
    2045         2534 :                                     REAL_MODE_FORMAT (mode)))
    2046         1060 :             return build_real (type, result);
    2047              :         }
    2048         1474 :       return NULL_TREE;
    2049              :     }
    2050              : 
    2051              :   return NULL_TREE;
    2052              : }
    2053              : 
    2054              : /* Try to fold FN (ARG0, ARG1, ARG2) to a constant.  Return the constant on
    2055              :    success, otherwise return null.  TYPE is the type of the return value.  */
    2056              : 
    2057              : tree
    2058      6920047 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
    2059              : {
    2060      6920047 :   const char *p0, *p1;
    2061      6920047 :   char c;
    2062      6920047 :   unsigned HOST_WIDE_INT s0, s1, s2 = 0;
    2063      6920047 :   switch (fn)
    2064              :     {
    2065        45003 :     case CFN_BUILT_IN_STRNCMP:
    2066        45003 :       if (!size_t_cst_p (arg2, &s2))
    2067              :         return NULL_TREE;
    2068        28997 :       if (s2 == 0
    2069          237 :           && !TREE_SIDE_EFFECTS (arg0)
    2070        29206 :           && !TREE_SIDE_EFFECTS (arg1))
    2071          209 :         return build_int_cst (type, 0);
    2072        28788 :       else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    2073          573 :         return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
    2074              :       return NULL_TREE;
    2075              : 
    2076         7999 :     case CFN_BUILT_IN_STRNCASECMP:
    2077         7999 :       if (!size_t_cst_p (arg2, &s2))
    2078              :         return NULL_TREE;
    2079         7678 :       if (s2 == 0
    2080            9 :           && !TREE_SIDE_EFFECTS (arg0)
    2081         7683 :           && !TREE_SIDE_EFFECTS (arg1))
    2082            5 :         return build_int_cst (type, 0);
    2083         7673 :       else if ((p0 = c_getstr (arg0))
    2084          724 :                && (p1 = c_getstr (arg1))
    2085         7813 :                && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
    2086            3 :         return build_int_cst (type, 0);
    2087              :       return NULL_TREE;
    2088              : 
    2089      2520908 :     case CFN_BUILT_IN_BCMP:
    2090      2520908 :     case CFN_BUILT_IN_MEMCMP:
    2091      2520908 :       if (!size_t_cst_p (arg2, &s2))
    2092              :         return NULL_TREE;
    2093      1615317 :       if (s2 == 0
    2094        13066 :           && !TREE_SIDE_EFFECTS (arg0)
    2095      1628383 :           && !TREE_SIDE_EFFECTS (arg1))
    2096        13066 :         return build_int_cst (type, 0);
    2097      1602251 :       if ((p0 = getbyterep (arg0, &s0))
    2098        12242 :           && (p1 = getbyterep (arg1, &s1))
    2099         3782 :           && s2 <= s0
    2100      1605601 :           && s2 <= s1)
    2101         3349 :         return build_cmp_result (type, memcmp (p0, p1, s2));
    2102              :       return NULL_TREE;
    2103              : 
    2104       206862 :     case CFN_BUILT_IN_MEMCHR:
    2105       206862 :       if (!size_t_cst_p (arg2, &s2))
    2106              :         return NULL_TREE;
    2107         7245 :       if (s2 == 0
    2108          151 :           && !TREE_SIDE_EFFECTS (arg0)
    2109         7379 :           && !TREE_SIDE_EFFECTS (arg1))
    2110          131 :         return build_int_cst (type, 0);
    2111         7114 :       if ((p0 = getbyterep (arg0, &s0))
    2112         2390 :           && s2 <= s0
    2113         9385 :           && target_char_cst_p (arg1, &c))
    2114              :         {
    2115          740 :           const char *r = (const char *) memchr (p0, c, s2);
    2116          740 :           if (r == NULL)
    2117          284 :             return build_int_cst (type, 0);
    2118          456 :           return fold_convert (type,
    2119              :                                fold_build_pointer_plus_hwi (arg0, r - p0));
    2120              :         }
    2121              :       return NULL_TREE;
    2122              : 
    2123            0 :     case CFN_WHILE_ULT:
    2124            0 :       {
    2125            0 :         poly_uint64 parg0, parg1;
    2126            0 :         if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
    2127            0 :           return fold_while_ult (type, parg0, parg1);
    2128              :         return NULL_TREE;
    2129              :       }
    2130              : 
    2131           92 :     case CFN_UADDC:
    2132           92 :     case CFN_USUBC:
    2133           92 :       if (integer_cst_p (arg0) && integer_cst_p (arg1) && integer_cst_p (arg2))
    2134              :         {
    2135           92 :           tree itype = TREE_TYPE (type);
    2136           92 :           bool ovf = false;
    2137           92 :           tree_code subcode = fn == CFN_UADDC ? PLUS_EXPR : MINUS_EXPR;
    2138           92 :           tree r = int_const_binop (subcode, fold_convert (itype, arg0),
    2139           92 :                                     fold_convert (itype, arg1));
    2140           92 :           if (!r)
    2141              :             return NULL_TREE;
    2142           92 :           if (arith_overflowed_p (subcode, itype, arg0, arg1))
    2143              :             ovf = true;
    2144           92 :           tree r2 = int_const_binop (subcode, r, fold_convert (itype, arg2));
    2145           92 :           if (!r2 || TREE_CODE (r2) != INTEGER_CST)
    2146              :             return NULL_TREE;
    2147           92 :           if (arith_overflowed_p (subcode, itype, r, arg2))
    2148            0 :             ovf = true;
    2149           92 :           if (TREE_OVERFLOW (r2))
    2150            0 :             r2 = drop_tree_overflow (r2);
    2151           92 :           return build_complex (type, r2, build_int_cst (itype, ovf));
    2152              :         }
    2153              :       return NULL_TREE;
    2154              : 
    2155      4139183 :     default:
    2156      4139183 :       return fold_const_call_1 (fn, type, arg0, arg1, arg2);
    2157              :     }
    2158              : }
        

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.