LCOV - code coverage report
Current view: top level - gcc - fold-const-call.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 823 884 93.1 %
Date: 2020-05-30 12:51:24 Functions: 35 41 85.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Constant folding for calls to built-in and internal functions.
       2                 :            :    Copyright (C) 1988-2020 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_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                 :   16876500 : integer_cst_p (tree t)
      40                 :            : {
      41                 :   21884500 :   return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
      42                 :            : }
      43                 :            : 
      44                 :            : static inline bool
      45                 :   16260500 : real_cst_p (tree t)
      46                 :            : {
      47                 :   18754000 :   return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
      48                 :            : }
      49                 :            : 
      50                 :            : static inline bool
      51                 :    8501280 : complex_cst_p (tree t)
      52                 :            : {
      53                 :    8501280 :   return TREE_CODE (t) == COMPLEX_CST;
      54                 :            : }
      55                 :            : 
      56                 :            : /* Return true if ARG is a constant in the range of the host size_t.
      57                 :            :    Store it in *SIZE_OUT if so.  */
      58                 :            : 
      59                 :            : static inline bool
      60                 :    2075120 : host_size_t_cst_p (tree t, size_t *size_out)
      61                 :            : {
      62                 :    2075120 :   if (types_compatible_p (size_type_node, TREE_TYPE (t))
      63                 :    2074840 :       && integer_cst_p (t)
      64                 :    4149950 :       && (wi::min_precision (wi::to_wide (t), UNSIGNED)
      65                 :            :           <= sizeof (size_t) * CHAR_BIT))
      66                 :            :     {
      67                 :    1460770 :       *size_out = tree_to_uhwi (t);
      68                 :    1460770 :       return true;
      69                 :            :     }
      70                 :            :   return false;
      71                 :            : }
      72                 :            : 
      73                 :            : /* RES is the result of a comparison in which < 0 means "less", 0 means
      74                 :            :    "equal" and > 0 means "more".  Canonicalize it to -1, 0 or 1 and
      75                 :            :    return it in type TYPE.  */
      76                 :            : 
      77                 :            : tree
      78                 :       5494 : build_cmp_result (tree type, int res)
      79                 :            : {
      80                 :       9507 :   return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0);
      81                 :            : }
      82                 :            : 
      83                 :            : /* M is the result of trying to constant-fold an expression (starting
      84                 :            :    with clear MPFR flags) and INEXACT says whether the result in M is
      85                 :            :    exact or inexact.  Return true if M can be used as a constant-folded
      86                 :            :    result in format FORMAT, storing the value in *RESULT if so.  */
      87                 :            : 
      88                 :            : static bool
      89                 :      60309 : do_mpfr_ckconv (real_value *result, mpfr_srcptr m, bool inexact,
      90                 :            :                 const real_format *format)
      91                 :            : {
      92                 :            :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
      93                 :            :      overflow/underflow occurred.  If -frounding-math, proceed iff the
      94                 :            :      result of calling FUNC was exact.  */
      95                 :      60309 :   if (!mpfr_number_p (m)
      96                 :      45837 :       || mpfr_overflow_p ()
      97                 :      45837 :       || mpfr_underflow_p ()
      98                 :     102602 :       || (flag_rounding_math && inexact))
      99                 :      18060 :     return false;
     100                 :            : 
     101                 :      42249 :   REAL_VALUE_TYPE tmp;
     102                 :      42249 :   real_from_mpfr (&tmp, m, format, MPFR_RNDN);
     103                 :            : 
     104                 :            :   /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
     105                 :            :      If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
     106                 :            :      underflowed in the conversion.  */
     107                 :      42249 :   if (!real_isfinite (&tmp)
     108                 :      42249 :       || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
     109                 :            :     return false;
     110                 :            : 
     111                 :      42249 :   real_convert (result, format, &tmp);
     112                 :      42249 :   return real_identical (result, &tmp);
     113                 :            : }
     114                 :            : 
     115                 :            : /* Try to evaluate:
     116                 :            : 
     117                 :            :       *RESULT = f (*ARG)
     118                 :            : 
     119                 :            :    in format FORMAT, given that FUNC is the MPFR implementation of f.
     120                 :            :    Return true on success.  */
     121                 :            : 
     122                 :            : static bool
     123                 :      37624 : do_mpfr_arg1 (real_value *result,
     124                 :            :               int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
     125                 :            :               const real_value *arg, const real_format *format)
     126                 :            : {
     127                 :            :   /* To proceed, MPFR must exactly represent the target floating point
     128                 :            :      format, which only happens when the target base equals two.  */
     129                 :      37624 :   if (format->b != 2 || !real_isfinite (arg))
     130                 :       2322 :     return false;
     131                 :            : 
     132                 :      35302 :   int prec = format->p;
     133                 :      35302 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     134                 :      35302 :   mpfr_t m;
     135                 :            : 
     136                 :      35302 :   mpfr_init2 (m, prec);
     137                 :      35302 :   mpfr_from_real (m, arg, MPFR_RNDN);
     138                 :      35302 :   mpfr_clear_flags ();
     139                 :      35302 :   bool inexact = func (m, m, rnd);
     140                 :      35302 :   bool ok = do_mpfr_ckconv (result, m, inexact, format);
     141                 :      35302 :   mpfr_clear (m);
     142                 :            : 
     143                 :      35302 :   return ok;
     144                 :            : }
     145                 :            : 
     146                 :            : /* Try to evaluate:
     147                 :            : 
     148                 :            :       *RESULT_SIN = sin (*ARG);
     149                 :            :       *RESULT_COS = cos (*ARG);
     150                 :            : 
     151                 :            :    for format FORMAT.  Return true on success.  */
     152                 :            : 
     153                 :            : static bool
     154                 :        158 : do_mpfr_sincos (real_value *result_sin, real_value *result_cos,
     155                 :            :                 const real_value *arg, const real_format *format)
     156                 :            : {
     157                 :            :   /* To proceed, MPFR must exactly represent the target floating point
     158                 :            :      format, which only happens when the target base equals two.  */
     159                 :        158 :   if (format->b != 2 || !real_isfinite (arg))
     160                 :          0 :     return false;
     161                 :            : 
     162                 :        158 :   int prec = format->p;
     163                 :        158 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     164                 :        158 :   mpfr_t m, ms, mc;
     165                 :            : 
     166                 :        158 :   mpfr_inits2 (prec, m, ms, mc, NULL);
     167                 :        158 :   mpfr_from_real (m, arg, MPFR_RNDN);
     168                 :        158 :   mpfr_clear_flags ();
     169                 :        158 :   bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
     170                 :        158 :   bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
     171                 :        158 :              && do_mpfr_ckconv (result_cos, mc, inexact, format));
     172                 :        158 :   mpfr_clears (m, ms, mc, NULL);
     173                 :            : 
     174                 :        158 :   return ok;
     175                 :            : }
     176                 :            : 
     177                 :            : /* Try to evaluate:
     178                 :            : 
     179                 :            :       *RESULT = f (*ARG0, *ARG1)
     180                 :            : 
     181                 :            :    in format FORMAT, given that FUNC is the MPFR implementation of f.
     182                 :            :    Return true on success.  */
     183                 :            : 
     184                 :            : static bool
     185                 :      25009 : do_mpfr_arg2 (real_value *result,
     186                 :            :               int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t),
     187                 :            :               const real_value *arg0, const real_value *arg1,
     188                 :            :               const real_format *format)
     189                 :            : {
     190                 :            :   /* To proceed, MPFR must exactly represent the target floating point
     191                 :            :      format, which only happens when the target base equals two.  */
     192                 :      25009 :   if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
     193                 :       4658 :     return false;
     194                 :            : 
     195                 :      20351 :   int prec = format->p;
     196                 :      20351 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     197                 :      20351 :   mpfr_t m0, m1;
     198                 :            : 
     199                 :      20351 :   mpfr_inits2 (prec, m0, m1, NULL);
     200                 :      20351 :   mpfr_from_real (m0, arg0, MPFR_RNDN);
     201                 :      20351 :   mpfr_from_real (m1, arg1, MPFR_RNDN);
     202                 :      20351 :   mpfr_clear_flags ();
     203                 :      20351 :   bool inexact = func (m0, m0, m1, rnd);
     204                 :      20351 :   bool ok = do_mpfr_ckconv (result, m0, inexact, format);
     205                 :      20351 :   mpfr_clears (m0, m1, NULL);
     206                 :            : 
     207                 :      20351 :   return ok;
     208                 :            : }
     209                 :            : 
     210                 :            : /* Try to evaluate:
     211                 :            : 
     212                 :            :       *RESULT = f (ARG0, *ARG1)
     213                 :            : 
     214                 :            :    in format FORMAT, given that FUNC is the MPFR implementation of f.
     215                 :            :    Return true on success.  */
     216                 :            : 
     217                 :            : static bool
     218                 :       1745 : do_mpfr_arg2 (real_value *result,
     219                 :            :               int (*func) (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t),
     220                 :            :               const wide_int_ref &arg0, const real_value *arg1,
     221                 :            :               const real_format *format)
     222                 :            : {
     223                 :       1745 :   if (format->b != 2 || !real_isfinite (arg1))
     224                 :          0 :     return false;
     225                 :            : 
     226                 :       1745 :   int prec = format->p;
     227                 :       1745 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     228                 :       1745 :   mpfr_t m;
     229                 :            : 
     230                 :       1745 :   mpfr_init2 (m, prec);
     231                 :       1745 :   mpfr_from_real (m, arg1, MPFR_RNDN);
     232                 :       1745 :   mpfr_clear_flags ();
     233                 :       3490 :   bool inexact = func (m, arg0.to_shwi (), m, rnd);
     234                 :       1745 :   bool ok = do_mpfr_ckconv (result, m, inexact, format);
     235                 :       1745 :   mpfr_clear (m);
     236                 :            : 
     237                 :       1745 :   return ok;
     238                 :            : }
     239                 :            : 
     240                 :            : /* Try to evaluate:
     241                 :            : 
     242                 :            :       *RESULT = f (*ARG0, *ARG1, *ARG2)
     243                 :            : 
     244                 :            :    in format FORMAT, given that FUNC is the MPFR implementation of f.
     245                 :            :    Return true on success.  */
     246                 :            : 
     247                 :            : static bool
     248                 :       2595 : do_mpfr_arg3 (real_value *result,
     249                 :            :               int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
     250                 :            :                            mpfr_srcptr, mpfr_rnd_t),
     251                 :            :               const real_value *arg0, const real_value *arg1,
     252                 :            :               const real_value *arg2, const real_format *format)
     253                 :            : {
     254                 :            :   /* To proceed, MPFR must exactly represent the target floating point
     255                 :            :      format, which only happens when the target base equals two.  */
     256                 :       2595 :   if (format->b != 2
     257                 :       2595 :       || !real_isfinite (arg0)
     258                 :       2595 :       || !real_isfinite (arg1)
     259                 :       5190 :       || !real_isfinite (arg2))
     260                 :          0 :     return false;
     261                 :            : 
     262                 :       2595 :   int prec = format->p;
     263                 :       2595 :   mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
     264                 :       2595 :   mpfr_t m0, m1, m2;
     265                 :            : 
     266                 :       2595 :   mpfr_inits2 (prec, m0, m1, m2, NULL);
     267                 :       2595 :   mpfr_from_real (m0, arg0, MPFR_RNDN);
     268                 :       2595 :   mpfr_from_real (m1, arg1, MPFR_RNDN);
     269                 :       2595 :   mpfr_from_real (m2, arg2, MPFR_RNDN);
     270                 :       2595 :   mpfr_clear_flags ();
     271                 :       2595 :   bool inexact = func (m0, m0, m1, m2, rnd);
     272                 :       2595 :   bool ok = do_mpfr_ckconv (result, m0, inexact, format);
     273                 :       2595 :   mpfr_clears (m0, m1, m2, NULL);
     274                 :            : 
     275                 :       2595 :   return ok;
     276                 :            : }
     277                 :            : 
     278                 :            : /* M is the result of trying to constant-fold an expression (starting
     279                 :            :    with clear MPFR flags) and INEXACT says whether the result in M is
     280                 :            :    exact or inexact.  Return true if M can be used as a constant-folded
     281                 :            :    result in which the real and imaginary parts have format FORMAT.
     282                 :            :    Store those parts in *RESULT_REAL and *RESULT_IMAG if so.  */
     283                 :            : 
     284                 :            : static bool
     285                 :      39222 : do_mpc_ckconv (real_value *result_real, real_value *result_imag,
     286                 :            :                mpc_srcptr m, bool inexact, const real_format *format)
     287                 :            : {
     288                 :            :   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
     289                 :            :      overflow/underflow occurred.  If -frounding-math, proceed iff the
     290                 :            :      result of calling FUNC was exact.  */
     291                 :      39222 :   if (!mpfr_number_p (mpc_realref (m))
     292                 :      33682 :       || !mpfr_number_p (mpc_imagref (m))
     293                 :      33682 :       || mpfr_overflow_p ()
     294                 :      33660 :       || mpfr_underflow_p ()
     295                 :      69270 :       || (flag_rounding_math && inexact))
     296                 :       9174 :     return false;
     297                 :            : 
     298                 :      30048 :   REAL_VALUE_TYPE tmp_real, tmp_imag;
     299                 :      30048 :   real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN);
     300                 :      30048 :   real_from_mpfr (&tmp_imag, mpc_imagref (m), format, MPFR_RNDN);
     301                 :            : 
     302                 :            :   /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
     303                 :            :      If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
     304                 :            :      underflowed in the conversion.  */
     305                 :      30048 :   if (!real_isfinite (&tmp_real)
     306                 :      30048 :       || !real_isfinite (&tmp_imag)
     307                 :      30048 :       || (tmp_real.cl == rvc_zero) != (mpfr_zero_p (mpc_realref (m)) != 0)
     308                 :      60096 :       || (tmp_imag.cl == rvc_zero) != (mpfr_zero_p (mpc_imagref (m)) != 0))
     309                 :          0 :     return false;
     310                 :            : 
     311                 :      30048 :   real_convert (result_real, format, &tmp_real);
     312                 :      30048 :   real_convert (result_imag, format, &tmp_imag);
     313                 :            : 
     314                 :      30048 :   return (real_identical (result_real, &tmp_real)
     315                 :      30048 :           && real_identical (result_imag, &tmp_imag));
     316                 :            : }
     317                 :            : 
     318                 :            : /* Try to evaluate:
     319                 :            : 
     320                 :            :       RESULT = f (ARG)
     321                 :            : 
     322                 :            :    in format FORMAT, given that FUNC is the mpc implementation of f.
     323                 :            :    Return true on success.  Both RESULT and ARG are represented as
     324                 :            :    real and imaginary pairs.  */
     325                 :            : 
     326                 :            : static bool
     327                 :      13609 : do_mpc_arg1 (real_value *result_real, real_value *result_imag,
     328                 :            :              int (*func) (mpc_ptr, mpc_srcptr, mpc_rnd_t),
     329                 :            :              const real_value *arg_real, const real_value *arg_imag,
     330                 :            :              const real_format *format)
     331                 :            : {
     332                 :            :   /* To proceed, MPFR must exactly represent the target floating point
     333                 :            :      format, which only happens when the target base equals two.  */
     334                 :      13609 :   if (format->b != 2
     335                 :      13609 :       || !real_isfinite (arg_real)
     336                 :      24896 :       || !real_isfinite (arg_imag))
     337                 :       2322 :     return false;
     338                 :            : 
     339                 :      11287 :   int prec = format->p;
     340                 :      11287 :   mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
     341                 :      11287 :   mpc_t m;
     342                 :            : 
     343                 :      11287 :   mpc_init2 (m, prec);
     344                 :      11287 :   mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN);
     345                 :      11287 :   mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN);
     346                 :      11287 :   mpfr_clear_flags ();
     347                 :      11287 :   bool inexact = func (m, m, crnd);
     348                 :      11287 :   bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
     349                 :      11287 :   mpc_clear (m);
     350                 :            : 
     351                 :      11287 :   return ok;
     352                 :            : }
     353                 :            : 
     354                 :            : /* Try to evaluate:
     355                 :            : 
     356                 :            :       RESULT = f (ARG0, ARG1)
     357                 :            : 
     358                 :            :    in format FORMAT, given that FUNC is the mpc implementation of f.
     359                 :            :    Return true on success.  RESULT, ARG0 and ARG1 are represented as
     360                 :            :    real and imaginary pairs.  */
     361                 :            : 
     362                 :            : static bool
     363                 :      32579 : do_mpc_arg2 (real_value *result_real, real_value *result_imag,
     364                 :            :              int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t),
     365                 :            :              const real_value *arg0_real, const real_value *arg0_imag,
     366                 :            :              const real_value *arg1_real, const real_value *arg1_imag,
     367                 :            :              const real_format *format)
     368                 :            : {
     369                 :      32579 :   if (!real_isfinite (arg0_real)
     370                 :      30257 :       || !real_isfinite (arg0_imag)
     371                 :      30257 :       || !real_isfinite (arg1_real)
     372                 :      60514 :       || !real_isfinite (arg1_imag))
     373                 :       4644 :     return false;
     374                 :            : 
     375                 :      27935 :   int prec = format->p;
     376                 :      27935 :   mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
     377                 :      27935 :   mpc_t m0, m1;
     378                 :            : 
     379                 :      27935 :   mpc_init2 (m0, prec);
     380                 :      27935 :   mpc_init2 (m1, prec);
     381                 :      27935 :   mpfr_from_real (mpc_realref (m0), arg0_real, MPFR_RNDN);
     382                 :      27935 :   mpfr_from_real (mpc_imagref (m0), arg0_imag, MPFR_RNDN);
     383                 :      27935 :   mpfr_from_real (mpc_realref (m1), arg1_real, MPFR_RNDN);
     384                 :      27935 :   mpfr_from_real (mpc_imagref (m1), arg1_imag, MPFR_RNDN);
     385                 :      27935 :   mpfr_clear_flags ();
     386                 :      27935 :   bool inexact = func (m0, m0, m1, crnd);
     387                 :      27935 :   bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
     388                 :      27935 :   mpc_clear (m0);
     389                 :      27935 :   mpc_clear (m1);
     390                 :            : 
     391                 :      27935 :   return ok;
     392                 :            : }
     393                 :            : 
     394                 :            : /* Try to evaluate:
     395                 :            : 
     396                 :            :       *RESULT = logb (*ARG)
     397                 :            : 
     398                 :            :    in format FORMAT.  Return true on success.  */
     399                 :            : 
     400                 :            : static bool
     401                 :       4300 : fold_const_logb (real_value *result, const real_value *arg,
     402                 :            :                  const real_format *format)
     403                 :            : {
     404                 :       4300 :   switch (arg->cl)
     405                 :            :     {
     406                 :         96 :     case rvc_nan:
     407                 :            :       /* If arg is +-NaN, then return it.  */
     408                 :         96 :       *result = *arg;
     409                 :         96 :       return true;
     410                 :            : 
     411                 :         96 :     case rvc_inf:
     412                 :            :       /* If arg is +-Inf, then return +Inf.  */
     413                 :         96 :       *result = *arg;
     414                 :         96 :       result->sign = 0;
     415                 :         96 :       return true;
     416                 :            : 
     417                 :            :     case rvc_zero:
     418                 :            :       /* Zero may set errno and/or raise an exception.  */
     419                 :            :       return false;
     420                 :            : 
     421                 :       1614 :     case rvc_normal:
     422                 :            :       /* For normal numbers, proceed iff radix == 2.  In GCC,
     423                 :            :          normalized significands are in the range [0.5, 1.0).  We
     424                 :            :          want the exponent as if they were [1.0, 2.0) so get the
     425                 :            :          exponent and subtract 1.  */
     426                 :       1614 :       if (format->b == 2)
     427                 :            :         {
     428                 :       1614 :           real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED);
     429                 :       1614 :           return true;
     430                 :            :         }
     431                 :            :       return false;
     432                 :            :     }
     433                 :            :   gcc_unreachable ();
     434                 :            : }
     435                 :            : 
     436                 :            : /* Try to evaluate:
     437                 :            : 
     438                 :            :       *RESULT = significand (*ARG)
     439                 :            : 
     440                 :            :    in format FORMAT.  Return true on success.  */
     441                 :            : 
     442                 :            : static bool
     443                 :        960 : fold_const_significand (real_value *result, const real_value *arg,
     444                 :            :                         const real_format *format)
     445                 :            : {
     446                 :          0 :   switch (arg->cl)
     447                 :            :     {
     448                 :        288 :     case rvc_zero:
     449                 :        288 :     case rvc_nan:
     450                 :        288 :     case rvc_inf:
     451                 :            :       /* If arg is +-0, +-Inf or +-NaN, then return it.  */
     452                 :        288 :       *result = *arg;
     453                 :        288 :       return true;
     454                 :            : 
     455                 :        672 :     case rvc_normal:
     456                 :            :       /* For normal numbers, proceed iff radix == 2.  */
     457                 :        672 :       if (format->b == 2)
     458                 :            :         {
     459                 :        672 :           *result = *arg;
     460                 :            :           /* In GCC, normalized significands are in the range [0.5, 1.0).
     461                 :            :              We want them to be [1.0, 2.0) so set the exponent to 1.  */
     462                 :        672 :           SET_REAL_EXP (result, 1);
     463                 :        672 :           return true;
     464                 :            :         }
     465                 :            :       return false;
     466                 :            :     }
     467                 :            :   gcc_unreachable ();
     468                 :            : }
     469                 :            : 
     470                 :            : /* Try to evaluate:
     471                 :            : 
     472                 :            :       *RESULT = f (*ARG)
     473                 :            : 
     474                 :            :    where FORMAT is the format of *ARG and PRECISION is the number of
     475                 :            :    significant bits in the result.  Return true on success.  */
     476                 :            : 
     477                 :            : static bool
     478                 :       1265 : fold_const_conversion (wide_int *result,
     479                 :            :                        void (*fn) (real_value *, format_helper,
     480                 :            :                                    const real_value *),
     481                 :            :                        const real_value *arg, unsigned int precision,
     482                 :            :                        const real_format *format)
     483                 :            : {
     484                 :       1265 :   if (!real_isfinite (arg))
     485                 :            :     return false;
     486                 :            : 
     487                 :       1265 :   real_value rounded;
     488                 :       1265 :   fn (&rounded, format, arg);
     489                 :            : 
     490                 :       1265 :   bool fail = false;
     491                 :       1265 :   *result = real_to_integer (&rounded, &fail, precision);
     492                 :       1265 :   return !fail;
     493                 :            : }
     494                 :            : 
     495                 :            : /* Try to evaluate:
     496                 :            : 
     497                 :            :       *RESULT = pow (*ARG0, *ARG1)
     498                 :            : 
     499                 :            :    in format FORMAT.  Return true on success.  */
     500                 :            : 
     501                 :            : static bool
     502                 :      17109 : fold_const_pow (real_value *result, const real_value *arg0,
     503                 :            :                 const real_value *arg1, const real_format *format)
     504                 :            : {
     505                 :      17109 :   if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
     506                 :            :     return true;
     507                 :            : 
     508                 :            :   /* Check for an integer exponent.  */
     509                 :      10272 :   REAL_VALUE_TYPE cint1;
     510                 :      10272 :   HOST_WIDE_INT n1 = real_to_integer (arg1);
     511                 :      10272 :   real_from_integer (&cint1, VOIDmode, n1, SIGNED);
     512                 :            :   /* Attempt to evaluate pow at compile-time, unless this should
     513                 :            :      raise an exception.  */
     514                 :      10272 :   if (real_identical (arg1, &cint1)
     515                 :      10272 :       && (n1 > 0
     516                 :        774 :           || (!flag_trapping_math && !flag_errno_math)
     517                 :        774 :           || !real_equal (arg0, &dconst0)))
     518                 :            :     {
     519                 :       1548 :       bool inexact = real_powi (result, format, arg0, n1);
     520                 :            :       /* Avoid the folding if flag_signaling_nans is on.  */
     521                 :       1548 :       if (flag_unsafe_math_optimizations
     522                 :       1548 :           || (!inexact
     523                 :          0 :               && !(flag_signaling_nans
     524                 :          0 :                    && REAL_VALUE_ISSIGNALING_NAN (*arg0))))
     525                 :          0 :         return true;
     526                 :            :     }
     527                 :            : 
     528                 :            :   return false;
     529                 :            : }
     530                 :            : 
     531                 :            : /* Try to evaluate:
     532                 :            : 
     533                 :            :       *RESULT = nextafter (*ARG0, *ARG1)
     534                 :            : 
     535                 :            :    or
     536                 :            : 
     537                 :            :       *RESULT = nexttoward (*ARG0, *ARG1)
     538                 :            : 
     539                 :            :    in format FORMAT.  Return true on success.  */
     540                 :            : 
     541                 :            : static bool
     542                 :       2345 : fold_const_nextafter (real_value *result, const real_value *arg0,
     543                 :            :                       const real_value *arg1, const real_format *format)
     544                 :            : {
     545                 :       2345 :   if (REAL_VALUE_ISSIGNALING_NAN (*arg0)
     546                 :       2345 :       || REAL_VALUE_ISSIGNALING_NAN (*arg1))
     547                 :          0 :     return false;
     548                 :            : 
     549                 :            :   /* Don't handle composite modes, nor decimal, nor modes without
     550                 :            :      inf or denorm at least for now.  */
     551                 :       2345 :   if (format->pnan < format->p
     552                 :       2345 :       || format->b == 10
     553                 :       2345 :       || !format->has_inf
     554                 :       2345 :       || !format->has_denorm)
     555                 :            :     return false;
     556                 :            : 
     557                 :       2937 :   if (real_nextafter (result, format, arg0, arg1)
     558                 :            :       /* If raising underflow or overflow and setting errno to ERANGE,
     559                 :            :          fail if we care about those side-effects.  */
     560                 :       2345 :       && (flag_trapping_math || flag_errno_math))
     561                 :        592 :     return false;
     562                 :            :   /* Similarly for nextafter (0, 1) raising underflow.  */
     563                 :       1753 :   else if (flag_trapping_math
     564                 :       1288 :            && arg0->cl == rvc_zero
     565                 :        838 :            && result->cl != rvc_zero)
     566                 :            :     return false;
     567                 :            : 
     568                 :        971 :   real_convert (result, format, result);
     569                 :            : 
     570                 :        971 :   return true;
     571                 :            : }
     572                 :            : 
     573                 :            : /* Try to evaluate:
     574                 :            : 
     575                 :            :       *RESULT = ldexp (*ARG0, ARG1)
     576                 :            : 
     577                 :            :    in format FORMAT.  Return true on success.  */
     578                 :            : 
     579                 :            : static bool
     580                 :      24315 : fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
     581                 :            :                                   const wide_int_ref &arg1,
     582                 :            :                                   const real_format *format)
     583                 :            : {
     584                 :            :   /* Bound the maximum adjustment to twice the range of the
     585                 :            :      mode's valid exponents.  Use abs to ensure the range is
     586                 :            :      positive as a sanity check.  */
     587                 :      24315 :   int max_exp_adj = 2 * labs (format->emax - format->emin);
     588                 :            : 
     589                 :            :   /* The requested adjustment must be inside this range.  This
     590                 :            :      is a preliminary cap to avoid things like overflow, we
     591                 :            :      may still fail to compute the result for other reasons.  */
     592                 :      41144 :   if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
     593                 :      14972 :     return false;
     594                 :            : 
     595                 :            :   /* Don't perform operation if we honor signaling NaNs and
     596                 :            :      operand is a signaling NaN.  */
     597                 :       9343 :   if (!flag_unsafe_math_optimizations
     598                 :       9343 :       && flag_signaling_nans
     599                 :       9433 :       && REAL_VALUE_ISSIGNALING_NAN (*arg0))
     600                 :            :     return false;
     601                 :            : 
     602                 :       9343 :   REAL_VALUE_TYPE initial_result;
     603                 :      18686 :   real_ldexp (&initial_result, arg0, arg1.to_shwi ());
     604                 :            : 
     605                 :            :   /* Ensure we didn't overflow.  */
     606                 :       9343 :   if (real_isinf (&initial_result))
     607                 :            :     return false;
     608                 :            : 
     609                 :            :   /* Only proceed if the target mode can hold the
     610                 :            :      resulting value.  */
     611                 :       9343 :   *result = real_value_truncate (format, initial_result);
     612                 :       9343 :   return real_equal (&initial_result, result);
     613                 :            : }
     614                 :            : 
     615                 :            : /* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
     616                 :            :    return type TYPE.  QUIET is true if a quiet rather than signalling
     617                 :            :    NaN is required.  */
     618                 :            : 
     619                 :            : static tree
     620                 :      98987 : fold_const_builtin_nan (tree type, tree arg, bool quiet)
     621                 :            : {
     622                 :      98987 :   REAL_VALUE_TYPE real;
     623                 :      98987 :   const char *str = c_getstr (arg);
     624                 :     197680 :   if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
     625                 :      98663 :     return build_real (type, real);
     626                 :            :   return NULL_TREE;
     627                 :            : }
     628                 :            : 
     629                 :            : /* Fold a call to IFN_REDUC_<CODE> (ARG), returning a value of type TYPE.  */
     630                 :            : 
     631                 :            : static tree
     632                 :         52 : fold_const_reduction (tree type, tree arg, tree_code code)
     633                 :            : {
     634                 :         52 :   unsigned HOST_WIDE_INT nelts;
     635                 :         52 :   if (TREE_CODE (arg) != VECTOR_CST
     636                 :        104 :       || !VECTOR_CST_NELTS (arg).is_constant (&nelts))
     637                 :          0 :     return NULL_TREE;
     638                 :            : 
     639                 :         52 :   tree res = VECTOR_CST_ELT (arg, 0);
     640                 :        272 :   for (unsigned HOST_WIDE_INT i = 1; i < nelts; i++)
     641                 :            :     {
     642                 :        220 :       res = const_binop (code, type, res, VECTOR_CST_ELT (arg, i));
     643                 :        220 :       if (res == NULL_TREE || !CONSTANT_CLASS_P (res))
     644                 :            :         return NULL_TREE;
     645                 :            :     }
     646                 :            :   return res;
     647                 :            : }
     648                 :            : 
     649                 :            : /* Fold a call to IFN_VEC_CONVERT (ARG) returning TYPE.  */
     650                 :            : 
     651                 :            : static tree
     652                 :         65 : fold_const_vec_convert (tree ret_type, tree arg)
     653                 :            : {
     654                 :         65 :   enum tree_code code = NOP_EXPR;
     655                 :         65 :   tree arg_type = TREE_TYPE (arg);
     656                 :         65 :   if (TREE_CODE (arg) != VECTOR_CST)
     657                 :            :     return NULL_TREE;
     658                 :            : 
     659                 :         65 :   gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
     660                 :            : 
     661                 :        130 :   if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
     662                 :        100 :       && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
     663                 :            :     code = FIX_TRUNC_EXPR;
     664                 :         60 :   else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
     665                 :         60 :            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
     666                 :            :     code = FLOAT_EXPR;
     667                 :            : 
     668                 :            :   /* We can't handle steps directly when extending, since the
     669                 :            :      values need to wrap at the original precision first.  */
     670                 :         65 :   bool step_ok_p
     671                 :         65 :     = (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
     672                 :         35 :        && INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
     673                 :         65 :        && (TYPE_PRECISION (TREE_TYPE (ret_type))
     674                 :          0 :            <= TYPE_PRECISION (TREE_TYPE (arg_type))));
     675                 :         65 :   tree_vector_builder elts;
     676                 :         65 :   if (!elts.new_unary_operation (ret_type, arg, step_ok_p))
     677                 :            :     return NULL_TREE;
     678                 :            : 
     679                 :         65 :   unsigned int count = elts.encoded_nelts ();
     680                 :        325 :   for (unsigned int i = 0; i < count; ++i)
     681                 :            :     {
     682                 :        260 :       tree elt = fold_unary (code, TREE_TYPE (ret_type),
     683                 :            :                              VECTOR_CST_ELT (arg, i));
     684                 :        260 :       if (elt == NULL_TREE || !CONSTANT_CLASS_P (elt))
     685                 :         65 :         return NULL_TREE;
     686                 :        260 :       elts.quick_push (elt);
     687                 :            :     }
     688                 :            : 
     689                 :         65 :   return elts.build ();
     690                 :            : }
     691                 :            : 
     692                 :            : /* Try to evaluate:
     693                 :            : 
     694                 :            :       IFN_WHILE_ULT (ARG0, ARG1, (TYPE) { ... })
     695                 :            : 
     696                 :            :    Return the value on success and null on failure.  */
     697                 :            : 
     698                 :            : static tree
     699                 :          0 : fold_while_ult (tree type, poly_uint64 arg0, poly_uint64 arg1)
     700                 :            : {
     701                 :          0 :   if (known_ge (arg0, arg1))
     702                 :          0 :     return build_zero_cst (type);
     703                 :            : 
     704                 :          0 :   if (maybe_ge (arg0, arg1))
     705                 :            :     return NULL_TREE;
     706                 :            : 
     707                 :          0 :   poly_uint64 diff = arg1 - arg0;
     708                 :          0 :   poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
     709                 :          0 :   if (known_ge (diff, nelts))
     710                 :          0 :     return build_all_ones_cst (type);
     711                 :            : 
     712                 :          0 :   unsigned HOST_WIDE_INT const_diff;
     713                 :          0 :   if (known_le (diff, nelts) && diff.is_constant (&const_diff))
     714                 :            :     {
     715                 :          0 :       tree minus_one = build_minus_one_cst (TREE_TYPE (type));
     716                 :          0 :       tree zero = build_zero_cst (TREE_TYPE (type));
     717                 :          0 :       return build_vector_a_then_b (type, const_diff, minus_one, zero);
     718                 :            :     }
     719                 :            :   return NULL_TREE;
     720                 :            : }
     721                 :            : 
     722                 :            : /* Try to evaluate:
     723                 :            : 
     724                 :            :       *RESULT = FN (*ARG)
     725                 :            : 
     726                 :            :    in format FORMAT.  Return true on success.  */
     727                 :            : 
     728                 :            : static bool
     729                 :      89837 : fold_const_call_ss (real_value *result, combined_fn fn,
     730                 :            :                     const real_value *arg, const real_format *format)
     731                 :            : {
     732                 :      89837 :   switch (fn)
     733                 :            :     {
     734                 :       6123 :     CASE_CFN_SQRT:
     735                 :       6123 :     CASE_CFN_SQRT_FN:
     736                 :       6123 :       return (real_compare (GE_EXPR, arg, &dconst0)
     737                 :       6123 :               && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
     738                 :            : 
     739                 :        412 :     CASE_CFN_CBRT:
     740                 :        412 :       return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
     741                 :            : 
     742                 :       1814 :     CASE_CFN_ASIN:
     743                 :       1814 :       return (real_compare (GE_EXPR, arg, &dconstm1)
     744                 :       1040 :               && real_compare (LE_EXPR, arg, &dconst1)
     745                 :       2080 :               && do_mpfr_arg1 (result, mpfr_asin, arg, format));
     746                 :            : 
     747                 :       1885 :     CASE_CFN_ACOS:
     748                 :       1885 :       return (real_compare (GE_EXPR, arg, &dconstm1)
     749                 :       1111 :               && real_compare (LE_EXPR, arg, &dconst1)
     750                 :       2222 :               && do_mpfr_arg1 (result, mpfr_acos, arg, format));
     751                 :            : 
     752                 :        410 :     CASE_CFN_ATAN:
     753                 :        410 :       return do_mpfr_arg1 (result, mpfr_atan, arg, format);
     754                 :            : 
     755                 :        216 :     CASE_CFN_ASINH:
     756                 :        216 :       return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
     757                 :            : 
     758                 :       1306 :     CASE_CFN_ACOSH:
     759                 :       1306 :       return (real_compare (GE_EXPR, arg, &dconst1)
     760                 :       1306 :               && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
     761                 :            : 
     762                 :       1768 :     CASE_CFN_ATANH:
     763                 :       1768 :       return (real_compare (GE_EXPR, arg, &dconstm1)
     764                 :       1768 :               && real_compare (LE_EXPR, arg, &dconst1)
     765                 :       3536 :               && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
     766                 :            : 
     767                 :        655 :     CASE_CFN_SIN:
     768                 :        655 :       return do_mpfr_arg1 (result, mpfr_sin, arg, format);
     769                 :            : 
     770                 :        554 :     CASE_CFN_COS:
     771                 :        554 :       return do_mpfr_arg1 (result, mpfr_cos, arg, format);
     772                 :            : 
     773                 :        428 :     CASE_CFN_TAN:
     774                 :        428 :       return do_mpfr_arg1 (result, mpfr_tan, arg, format);
     775                 :            : 
     776                 :        232 :     CASE_CFN_SINH:
     777                 :        232 :       return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
     778                 :            : 
     779                 :        232 :     CASE_CFN_COSH:
     780                 :        232 :       return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
     781                 :            : 
     782                 :        223 :     CASE_CFN_TANH:
     783                 :        223 :       return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
     784                 :            : 
     785                 :        228 :     CASE_CFN_ERF:
     786                 :        228 :       return do_mpfr_arg1 (result, mpfr_erf, arg, format);
     787                 :            : 
     788                 :        265 :     CASE_CFN_ERFC:
     789                 :        265 :       return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
     790                 :            : 
     791                 :       4758 :     CASE_CFN_TGAMMA:
     792                 :       4758 :       return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
     793                 :            : 
     794                 :        683 :     CASE_CFN_EXP:
     795                 :        683 :       return do_mpfr_arg1 (result, mpfr_exp, arg, format);
     796                 :            : 
     797                 :      10644 :     CASE_CFN_EXP2:
     798                 :      10644 :       return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
     799                 :            : 
     800                 :        680 :     CASE_CFN_EXP10:
     801                 :        680 :     CASE_CFN_POW10:
     802                 :        680 :       return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
     803                 :            : 
     804                 :        219 :     CASE_CFN_EXPM1:
     805                 :        219 :       return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
     806                 :            : 
     807                 :      12185 :     CASE_CFN_LOG:
     808                 :      12185 :       return (real_compare (GT_EXPR, arg, &dconst0)
     809                 :      12185 :               && do_mpfr_arg1 (result, mpfr_log, arg, format));
     810                 :            : 
     811                 :       2918 :     CASE_CFN_LOG2:
     812                 :       2918 :       return (real_compare (GT_EXPR, arg, &dconst0)
     813                 :       2918 :               && do_mpfr_arg1 (result, mpfr_log2, arg, format));
     814                 :            : 
     815                 :       2865 :     CASE_CFN_LOG10:
     816                 :       2865 :       return (real_compare (GT_EXPR, arg, &dconst0)
     817                 :       2865 :               && do_mpfr_arg1 (result, mpfr_log10, arg, format));
     818                 :            : 
     819                 :       1817 :     CASE_CFN_LOG1P:
     820                 :       1817 :       return (real_compare (GT_EXPR, arg, &dconstm1)
     821                 :       1817 :               && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
     822                 :            : 
     823                 :        221 :     CASE_CFN_J0:
     824                 :        221 :       return do_mpfr_arg1 (result, mpfr_j0, arg, format);
     825                 :            : 
     826                 :        221 :     CASE_CFN_J1:
     827                 :        221 :       return do_mpfr_arg1 (result, mpfr_j1, arg, format);
     828                 :            : 
     829                 :       2447 :     CASE_CFN_Y0:
     830                 :       2447 :       return (real_compare (GT_EXPR, arg, &dconst0)
     831                 :       2447 :               && do_mpfr_arg1 (result, mpfr_y0, arg, format));
     832                 :            : 
     833                 :       2447 :     CASE_CFN_Y1:
     834                 :       2447 :       return (real_compare (GT_EXPR, arg, &dconst0)
     835                 :       2447 :               && do_mpfr_arg1 (result, mpfr_y1, arg, format));
     836                 :            : 
     837                 :        265 :     CASE_CFN_FLOOR:
     838                 :        265 :     CASE_CFN_FLOOR_FN:
     839                 :        265 :       if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
     840                 :            :         {
     841                 :        265 :           real_floor (result, format, arg);
     842                 :        265 :           return true;
     843                 :            :         }
     844                 :            :       return false;
     845                 :            : 
     846                 :        256 :     CASE_CFN_CEIL:
     847                 :        256 :     CASE_CFN_CEIL_FN:
     848                 :        256 :       if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
     849                 :            :         {
     850                 :        256 :           real_ceil (result, format, arg);
     851                 :        256 :           return true;
     852                 :            :         }
     853                 :            :       return false;
     854                 :            : 
     855                 :        325 :     CASE_CFN_TRUNC:
     856                 :        325 :     CASE_CFN_TRUNC_FN:
     857                 :        325 :       if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
     858                 :            :         {
     859                 :        325 :           real_trunc (result, format, arg);
     860                 :        325 :           return true;
     861                 :            :         }
     862                 :            :       return false;
     863                 :            : 
     864                 :        295 :     CASE_CFN_ROUND:
     865                 :        295 :     CASE_CFN_ROUND_FN:
     866                 :        295 :       if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
     867                 :            :         {
     868                 :        295 :           real_round (result, format, arg);
     869                 :        295 :           return true;
     870                 :            :         }
     871                 :            :       return false;
     872                 :            : 
     873                 :        189 :     CASE_CFN_ROUNDEVEN:
     874                 :        189 :     CASE_CFN_ROUNDEVEN_FN:
     875                 :        189 :       if (!REAL_VALUE_ISSIGNALING_NAN (*arg))
     876                 :            :         {
     877                 :        189 :           real_roundeven (result, format, arg);
     878                 :        189 :           return true;
     879                 :            :         }
     880                 :            :       return false;
     881                 :            : 
     882                 :       4300 :     CASE_CFN_LOGB:
     883                 :       4300 :       return fold_const_logb (result, arg, format);
     884                 :            : 
     885                 :        960 :     CASE_CFN_SIGNIFICAND:
     886                 :        960 :       return fold_const_significand (result, arg, format);
     887                 :            : 
     888                 :            :     default:
     889                 :            :       return false;
     890                 :            :     }
     891                 :            : }
     892                 :            : 
     893                 :            : /* Try to evaluate:
     894                 :            : 
     895                 :            :       *RESULT = FN (*ARG)
     896                 :            : 
     897                 :            :    where FORMAT is the format of ARG and PRECISION is the number of
     898                 :            :    significant bits in the result.  Return true on success.  */
     899                 :            : 
     900                 :            : static bool
     901                 :      10450 : fold_const_call_ss (wide_int *result, combined_fn fn,
     902                 :            :                     const real_value *arg, unsigned int precision,
     903                 :            :                     const real_format *format)
     904                 :            : {
     905                 :      10450 :   switch (fn)
     906                 :            :     {
     907                 :        725 :     CASE_CFN_SIGNBIT:
     908                 :        725 :       if (real_isneg (arg))
     909                 :        740 :         *result = wi::one (precision);
     910                 :            :       else
     911                 :        355 :         *result = wi::zero (precision);
     912                 :            :       return true;
     913                 :            : 
     914                 :       6768 :     CASE_CFN_ILOGB:
     915                 :            :       /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
     916                 :            :          Proceed iff radix == 2.  In GCC, normalized significands are in
     917                 :            :          the range [0.5, 1.0).  We want the exponent as if they were
     918                 :            :          [1.0, 2.0) so get the exponent and subtract 1.  */
     919                 :       6768 :       if (arg->cl == rvc_normal && format->b == 2)
     920                 :            :         {
     921                 :       1536 :           *result = wi::shwi (REAL_EXP (arg) - 1, precision);
     922                 :        768 :           return true;
     923                 :            :         }
     924                 :            :       return false;
     925                 :            : 
     926                 :        378 :     CASE_CFN_ICEIL:
     927                 :        378 :     CASE_CFN_LCEIL:
     928                 :        378 :     CASE_CFN_LLCEIL:
     929                 :        378 :       return fold_const_conversion (result, real_ceil, arg,
     930                 :        378 :                                     precision, format);
     931                 :            : 
     932                 :        378 :     CASE_CFN_LFLOOR:
     933                 :        378 :     CASE_CFN_IFLOOR:
     934                 :        378 :     CASE_CFN_LLFLOOR:
     935                 :        378 :       return fold_const_conversion (result, real_floor, arg,
     936                 :        378 :                                     precision, format);
     937                 :            : 
     938                 :        509 :     CASE_CFN_IROUND:
     939                 :        509 :     CASE_CFN_LROUND:
     940                 :        509 :     CASE_CFN_LLROUND:
     941                 :        509 :       return fold_const_conversion (result, real_round, arg,
     942                 :        509 :                                     precision, format);
     943                 :            : 
     944                 :            :     CASE_CFN_IRINT:
     945                 :            :     CASE_CFN_LRINT:
     946                 :            :     CASE_CFN_LLRINT:
     947                 :            :       /* Not yet folded to a constant.  */
     948                 :            :       return false;
     949                 :            : 
     950                 :        149 :     CASE_CFN_FINITE:
     951                 :        149 :     case CFN_BUILT_IN_FINITED32:
     952                 :        149 :     case CFN_BUILT_IN_FINITED64:
     953                 :        149 :     case CFN_BUILT_IN_FINITED128:
     954                 :        149 :     case CFN_BUILT_IN_ISFINITE:
     955                 :        298 :       *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
     956                 :        149 :       return true;
     957                 :            : 
     958                 :        250 :     CASE_CFN_ISINF:
     959                 :        250 :     case CFN_BUILT_IN_ISINFD32:
     960                 :        250 :     case CFN_BUILT_IN_ISINFD64:
     961                 :        250 :     case CFN_BUILT_IN_ISINFD128:
     962                 :        250 :       if (real_isinf (arg))
     963                 :        410 :         *result = wi::shwi (arg->sign ? -1 : 1, precision);
     964                 :            :       else
     965                 :         45 :         *result = wi::shwi (0, precision);
     966                 :            :       return true;
     967                 :            : 
     968                 :        605 :     CASE_CFN_ISNAN:
     969                 :        605 :     case CFN_BUILT_IN_ISNAND32:
     970                 :        605 :     case CFN_BUILT_IN_ISNAND64:
     971                 :        605 :     case CFN_BUILT_IN_ISNAND128:
     972                 :       1210 :       *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
     973                 :        605 :       return true;
     974                 :            : 
     975                 :            :     default:
     976                 :            :       return false;
     977                 :            :     }
     978                 :            : }
     979                 :            : 
     980                 :            : /* Try to evaluate:
     981                 :            : 
     982                 :            :       *RESULT = FN (ARG)
     983                 :            : 
     984                 :            :    where ARG_TYPE is the type of ARG and PRECISION is the number of bits
     985                 :            :    in the result.  Return true on success.  */
     986                 :            : 
     987                 :            : static bool
     988                 :    3224460 : fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
     989                 :            :                     unsigned int precision, tree arg_type)
     990                 :            : {
     991                 :    3224460 :   switch (fn)
     992                 :            :     {
     993                 :        370 :     CASE_CFN_FFS:
     994                 :        740 :       *result = wi::shwi (wi::ffs (arg), precision);
     995                 :        370 :       return true;
     996                 :            : 
     997                 :       1462 :     CASE_CFN_CLZ:
     998                 :       1462 :       {
     999                 :       1462 :         int tmp;
    1000                 :       1462 :         if (wi::ne_p (arg, 0))
    1001                 :       1321 :           tmp = wi::clz (arg);
    1002                 :        282 :         else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
    1003                 :            :                                              tmp))
    1004                 :        141 :           tmp = TYPE_PRECISION (arg_type);
    1005                 :       2903 :         *result = wi::shwi (tmp, precision);
    1006                 :       1462 :         return true;
    1007                 :            :       }
    1008                 :            : 
    1009                 :        993 :     CASE_CFN_CTZ:
    1010                 :        993 :       {
    1011                 :        993 :         int tmp;
    1012                 :        993 :         if (wi::ne_p (arg, 0))
    1013                 :        692 :           tmp = wi::ctz (arg);
    1014                 :        602 :         else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
    1015                 :            :                                              tmp))
    1016                 :        301 :           tmp = TYPE_PRECISION (arg_type);
    1017                 :       1963 :         *result = wi::shwi (tmp, precision);
    1018                 :        993 :         return true;
    1019                 :            :       }
    1020                 :            : 
    1021                 :        302 :     CASE_CFN_CLRSB:
    1022                 :        604 :       *result = wi::shwi (wi::clrsb (arg), precision);
    1023                 :        302 :       return true;
    1024                 :            : 
    1025                 :        894 :     CASE_CFN_POPCOUNT:
    1026                 :       1788 :       *result = wi::shwi (wi::popcount (arg), precision);
    1027                 :        894 :       return true;
    1028                 :            : 
    1029                 :        454 :     CASE_CFN_PARITY:
    1030                 :        908 :       *result = wi::shwi (wi::parity (arg), precision);
    1031                 :        454 :       return true;
    1032                 :            : 
    1033                 :        473 :     case CFN_BUILT_IN_BSWAP16:
    1034                 :        473 :     case CFN_BUILT_IN_BSWAP32:
    1035                 :        473 :     case CFN_BUILT_IN_BSWAP64:
    1036                 :        473 :     case CFN_BUILT_IN_BSWAP128:
    1037                 :        473 :       *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
    1038                 :        473 :       return true;
    1039                 :            : 
    1040                 :            :     default:
    1041                 :            :       return false;
    1042                 :            :     }
    1043                 :            : }
    1044                 :            : 
    1045                 :            : /* Try to evaluate:
    1046                 :            : 
    1047                 :            :       RESULT = FN (*ARG)
    1048                 :            : 
    1049                 :            :    where FORMAT is the format of ARG and of the real and imaginary parts
    1050                 :            :    of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively.  Return
    1051                 :            :    true on success.  */
    1052                 :            : 
    1053                 :            : static bool
    1054                 :        158 : fold_const_call_cs (real_value *result_real, real_value *result_imag,
    1055                 :            :                     combined_fn fn, const real_value *arg,
    1056                 :            :                     const real_format *format)
    1057                 :            : {
    1058                 :          0 :   switch (fn)
    1059                 :            :     {
    1060                 :        158 :     CASE_CFN_CEXPI:
    1061                 :            :       /* cexpi(x+yi) = cos(x)+sin(y)*i.  */
    1062                 :        158 :       return do_mpfr_sincos (result_imag, result_real, arg, format);
    1063                 :            : 
    1064                 :            :     default:
    1065                 :            :       return false;
    1066                 :            :     }
    1067                 :            : }
    1068                 :            : 
    1069                 :            : /* Try to evaluate:
    1070                 :            : 
    1071                 :            :       *RESULT = fn (ARG)
    1072                 :            : 
    1073                 :            :    where FORMAT is the format of RESULT and of the real and imaginary parts
    1074                 :            :    of ARG, passed as ARG_REAL and ARG_IMAG respectively.  Return true on
    1075                 :            :    success.  */
    1076                 :            : 
    1077                 :            : static bool
    1078                 :       1692 : fold_const_call_sc (real_value *result, combined_fn fn,
    1079                 :            :                     const real_value *arg_real, const real_value *arg_imag,
    1080                 :            :                     const real_format *format)
    1081                 :            : {
    1082                 :          0 :   switch (fn)
    1083                 :            :     {
    1084                 :        286 :     CASE_CFN_CABS:
    1085                 :        286 :       return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
    1086                 :            : 
    1087                 :            :     default:
    1088                 :            :       return false;
    1089                 :            :     }
    1090                 :            : }
    1091                 :            : 
    1092                 :            : /* Try to evaluate:
    1093                 :            : 
    1094                 :            :       RESULT = fn (ARG)
    1095                 :            : 
    1096                 :            :    where FORMAT is the format of the real and imaginary parts of RESULT
    1097                 :            :    (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
    1098                 :            :    Return true on success.  */
    1099                 :            : 
    1100                 :            : static bool
    1101                 :      39142 : fold_const_call_cc (real_value *result_real, real_value *result_imag,
    1102                 :            :                     combined_fn fn, const real_value *arg_real,
    1103                 :            :                     const real_value *arg_imag, const real_format *format)
    1104                 :            : {
    1105                 :      39142 :   switch (fn)
    1106                 :            :     {
    1107                 :        682 :     CASE_CFN_CCOS:
    1108                 :        682 :       return do_mpc_arg1 (result_real, result_imag, mpc_cos,
    1109                 :        682 :                           arg_real, arg_imag, format);
    1110                 :            : 
    1111                 :        672 :     CASE_CFN_CCOSH:
    1112                 :        672 :       return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
    1113                 :        672 :                           arg_real, arg_imag, format);
    1114                 :            : 
    1115                 :       1269 :     CASE_CFN_CPROJ:
    1116                 :       1269 :       if (real_isinf (arg_real) || real_isinf (arg_imag))
    1117                 :            :         {
    1118                 :       1020 :           real_inf (result_real);
    1119                 :       1020 :           *result_imag = dconst0;
    1120                 :       1020 :           result_imag->sign = arg_imag->sign;
    1121                 :            :         }
    1122                 :            :       else
    1123                 :            :         {
    1124                 :        249 :           *result_real = *arg_real;
    1125                 :        249 :           *result_imag = *arg_imag;
    1126                 :            :         }
    1127                 :            :       return true;
    1128                 :            : 
    1129                 :        682 :     CASE_CFN_CSIN:
    1130                 :        682 :       return do_mpc_arg1 (result_real, result_imag, mpc_sin,
    1131                 :        682 :                           arg_real, arg_imag, format);
    1132                 :            : 
    1133                 :        672 :     CASE_CFN_CSINH:
    1134                 :        672 :       return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
    1135                 :        672 :                           arg_real, arg_imag, format);
    1136                 :            : 
    1137                 :        694 :     CASE_CFN_CTAN:
    1138                 :        694 :       return do_mpc_arg1 (result_real, result_imag, mpc_tan,
    1139                 :        694 :                           arg_real, arg_imag, format);
    1140                 :            : 
    1141                 :        672 :     CASE_CFN_CTANH:
    1142                 :        672 :       return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
    1143                 :        672 :                           arg_real, arg_imag, format);
    1144                 :            : 
    1145                 :        751 :     CASE_CFN_CLOG:
    1146                 :        751 :       return do_mpc_arg1 (result_real, result_imag, mpc_log,
    1147                 :        751 :                           arg_real, arg_imag, format);
    1148                 :            : 
    1149                 :       3045 :     CASE_CFN_CSQRT:
    1150                 :       3045 :       return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
    1151                 :       3045 :                           arg_real, arg_imag, format);
    1152                 :            : 
    1153                 :        675 :     CASE_CFN_CASIN:
    1154                 :        675 :       return do_mpc_arg1 (result_real, result_imag, mpc_asin,
    1155                 :        675 :                           arg_real, arg_imag, format);
    1156                 :            : 
    1157                 :        724 :     CASE_CFN_CACOS:
    1158                 :        724 :       return do_mpc_arg1 (result_real, result_imag, mpc_acos,
    1159                 :        724 :                           arg_real, arg_imag, format);
    1160                 :            : 
    1161                 :        675 :     CASE_CFN_CATAN:
    1162                 :        675 :       return do_mpc_arg1 (result_real, result_imag, mpc_atan,
    1163                 :        675 :                           arg_real, arg_imag, format);
    1164                 :            : 
    1165                 :        675 :     CASE_CFN_CASINH:
    1166                 :        675 :       return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
    1167                 :        675 :                           arg_real, arg_imag, format);
    1168                 :            : 
    1169                 :        741 :     CASE_CFN_CACOSH:
    1170                 :        741 :       return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
    1171                 :        741 :                           arg_real, arg_imag, format);
    1172                 :            : 
    1173                 :        675 :     CASE_CFN_CATANH:
    1174                 :        675 :       return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
    1175                 :        675 :                           arg_real, arg_imag, format);
    1176                 :            : 
    1177                 :       1574 :     CASE_CFN_CEXP:
    1178                 :       1574 :       return do_mpc_arg1 (result_real, result_imag, mpc_exp,
    1179                 :       1574 :                           arg_real, arg_imag, format);
    1180                 :            : 
    1181                 :            :     default:
    1182                 :            :       return false;
    1183                 :            :     }
    1184                 :            : }
    1185                 :            : 
    1186                 :            : /* Subroutine of fold_const_call, with the same interface.  Handle cases
    1187                 :            :    where the arguments and result are numerical.  */
    1188                 :            : 
    1189                 :            : static tree
    1190                 :    8233100 : fold_const_call_1 (combined_fn fn, tree type, tree arg)
    1191                 :            : {
    1192                 :    8233100 :   machine_mode mode = TYPE_MODE (type);
    1193                 :    8233100 :   machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
    1194                 :            : 
    1195                 :    8233100 :   if (integer_cst_p (arg))
    1196                 :            :     {
    1197                 :    3381590 :       if (SCALAR_INT_MODE_P (mode))
    1198                 :            :         {
    1199                 :    3224460 :           wide_int result;
    1200                 :    6448920 :           if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
    1201                 :    3224460 :                                   TYPE_PRECISION (type), TREE_TYPE (arg)))
    1202                 :       4948 :             return wide_int_to_tree (type, result);
    1203                 :            :         }
    1204                 :    3376640 :       return NULL_TREE;
    1205                 :            :     }
    1206                 :            : 
    1207                 :    4851510 :   if (real_cst_p (arg))
    1208                 :            :     {
    1209                 :     100445 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
    1210                 :     100445 :       if (mode == arg_mode)
    1211                 :            :         {
    1212                 :            :           /* real -> real.  */
    1213                 :      89837 :           REAL_VALUE_TYPE result;
    1214                 :      89837 :           if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
    1215                 :      89837 :                                   REAL_MODE_FORMAT (mode)))
    1216                 :      29176 :             return build_real (type, result);
    1217                 :            :         }
    1218                 :      10608 :       else if (COMPLEX_MODE_P (mode)
    1219                 :      10766 :                && GET_MODE_INNER (mode) == arg_mode)
    1220                 :            :         {
    1221                 :            :           /* real -> complex real.  */
    1222                 :        158 :           REAL_VALUE_TYPE result_real, result_imag;
    1223                 :        316 :           if (fold_const_call_cs (&result_real, &result_imag, fn,
    1224                 :        158 :                                   TREE_REAL_CST_PTR (arg),
    1225                 :        158 :                                   REAL_MODE_FORMAT (arg_mode)))
    1226                 :        474 :             return build_complex (type,
    1227                 :        158 :                                   build_real (TREE_TYPE (type), result_real),
    1228                 :        316 :                                   build_real (TREE_TYPE (type), result_imag));
    1229                 :            :         }
    1230                 :      10450 :       else if (INTEGRAL_TYPE_P (type))
    1231                 :            :         {
    1232                 :            :           /* real -> int.  */
    1233                 :      10450 :           wide_int result;
    1234                 :      20900 :           if (fold_const_call_ss (&result, fn,
    1235                 :      10450 :                                   TREE_REAL_CST_PTR (arg),
    1236                 :      10450 :                                   TYPE_PRECISION (type),
    1237                 :      10450 :                                   REAL_MODE_FORMAT (arg_mode)))
    1238                 :       3762 :             return wide_int_to_tree (type, result);
    1239                 :            :         }
    1240                 :      67349 :       return NULL_TREE;
    1241                 :            :     }
    1242                 :            : 
    1243                 :    4751070 :   if (complex_cst_p (arg))
    1244                 :            :     {
    1245                 :      40834 :       gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
    1246                 :      81668 :       machine_mode inner_mode = GET_MODE_INNER (arg_mode);
    1247                 :      40834 :       tree argr = TREE_REALPART (arg);
    1248                 :      40834 :       tree argi = TREE_IMAGPART (arg);
    1249                 :      40834 :       if (mode == arg_mode
    1250                 :      39142 :           && real_cst_p (argr)
    1251                 :      79976 :           && real_cst_p (argi))
    1252                 :            :         {
    1253                 :            :           /* complex real -> complex real.  */
    1254                 :      39142 :           REAL_VALUE_TYPE result_real, result_imag;
    1255                 :      78284 :           if (fold_const_call_cc (&result_real, &result_imag, fn,
    1256                 :      39142 :                                   TREE_REAL_CST_PTR (argr),
    1257                 :      39142 :                                   TREE_REAL_CST_PTR (argi),
    1258                 :      39142 :                                   REAL_MODE_FORMAT (inner_mode)))
    1259                 :      32898 :             return build_complex (type,
    1260                 :      10966 :                                   build_real (TREE_TYPE (type), result_real),
    1261                 :      21932 :                                   build_real (TREE_TYPE (type), result_imag));
    1262                 :            :         }
    1263                 :      29868 :       if (mode == inner_mode
    1264                 :       1692 :           && real_cst_p (argr)
    1265                 :      31560 :           && real_cst_p (argi))
    1266                 :            :         {
    1267                 :            :           /* complex real -> real.  */
    1268                 :       1692 :           REAL_VALUE_TYPE result;
    1269                 :       3384 :           if (fold_const_call_sc (&result, fn,
    1270                 :       1692 :                                   TREE_REAL_CST_PTR (argr),
    1271                 :       1692 :                                   TREE_REAL_CST_PTR (argi),
    1272                 :       1692 :                                   REAL_MODE_FORMAT (inner_mode)))
    1273                 :        286 :             return build_real (type, result);
    1274                 :            :         }
    1275                 :      29582 :       return NULL_TREE;
    1276                 :            :     }
    1277                 :            : 
    1278                 :            :   return NULL_TREE;
    1279                 :            : }
    1280                 :            : 
    1281                 :            : /* Try to fold FN (ARG) to a constant.  Return the constant on success,
    1282                 :            :    otherwise return null.  TYPE is the type of the return value.  */
    1283                 :            : 
    1284                 :            : tree
    1285                 :    8777570 : fold_const_call (combined_fn fn, tree type, tree arg)
    1286                 :            : {
    1287                 :    8777570 :   switch (fn)
    1288                 :            :     {
    1289                 :     445363 :     case CFN_BUILT_IN_STRLEN:
    1290                 :     445363 :       if (const char *str = c_getstr (arg))
    1291                 :      16274 :         return build_int_cst (type, strlen (str));
    1292                 :            :       return NULL_TREE;
    1293                 :            : 
    1294                 :      51697 :     CASE_CFN_NAN:
    1295                 :      51697 :     CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
    1296                 :      51697 :     case CFN_BUILT_IN_NAND32:
    1297                 :      51697 :     case CFN_BUILT_IN_NAND64:
    1298                 :      51697 :     case CFN_BUILT_IN_NAND128:
    1299                 :      51697 :       return fold_const_builtin_nan (type, arg, true);
    1300                 :            : 
    1301                 :      47290 :     CASE_CFN_NANS:
    1302                 :      47290 :     CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
    1303                 :      47290 :       return fold_const_builtin_nan (type, arg, false);
    1304                 :            : 
    1305                 :          5 :     case CFN_REDUC_PLUS:
    1306                 :          5 :       return fold_const_reduction (type, arg, PLUS_EXPR);
    1307                 :            : 
    1308                 :          6 :     case CFN_REDUC_MAX:
    1309                 :          6 :       return fold_const_reduction (type, arg, MAX_EXPR);
    1310                 :            : 
    1311                 :         41 :     case CFN_REDUC_MIN:
    1312                 :         41 :       return fold_const_reduction (type, arg, MIN_EXPR);
    1313                 :            : 
    1314                 :          0 :     case CFN_REDUC_AND:
    1315                 :          0 :       return fold_const_reduction (type, arg, BIT_AND_EXPR);
    1316                 :            : 
    1317                 :          0 :     case CFN_REDUC_IOR:
    1318                 :          0 :       return fold_const_reduction (type, arg, BIT_IOR_EXPR);
    1319                 :            : 
    1320                 :          0 :     case CFN_REDUC_XOR:
    1321                 :          0 :       return fold_const_reduction (type, arg, BIT_XOR_EXPR);
    1322                 :            : 
    1323                 :         65 :     case CFN_VEC_CONVERT:
    1324                 :         65 :       return fold_const_vec_convert (type, arg);
    1325                 :            : 
    1326                 :    8233100 :     default:
    1327                 :    8233100 :       return fold_const_call_1 (fn, type, arg);
    1328                 :            :     }
    1329                 :            : }
    1330                 :            : 
    1331                 :            : /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
    1332                 :            :    of type TYPE.  */
    1333                 :            : 
    1334                 :            : static tree
    1335                 :          0 : fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
    1336                 :            : {
    1337                 :          0 :   if (TREE_CODE (arg1) != VECTOR_CST)
    1338                 :            :     return NULL_TREE;
    1339                 :            : 
    1340                 :          0 :   unsigned HOST_WIDE_INT nelts;
    1341                 :          0 :   if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
    1342                 :            :     return NULL_TREE;
    1343                 :            : 
    1344                 :          0 :   for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
    1345                 :            :     {
    1346                 :          0 :       arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
    1347                 :          0 :       if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
    1348                 :            :         return NULL_TREE;
    1349                 :            :     }
    1350                 :            :   return arg0;
    1351                 :            : }
    1352                 :            : 
    1353                 :            : /* Try to evaluate:
    1354                 :            : 
    1355                 :            :       *RESULT = FN (*ARG0, *ARG1)
    1356                 :            : 
    1357                 :            :    in format FORMAT.  Return true on success.  */
    1358                 :            : 
    1359                 :            : static bool
    1360                 :      99447 : fold_const_call_sss (real_value *result, combined_fn fn,
    1361                 :            :                      const real_value *arg0, const real_value *arg1,
    1362                 :            :                      const real_format *format)
    1363                 :            : {
    1364                 :      99447 :   switch (fn)
    1365                 :            :     {
    1366                 :       5314 :     CASE_CFN_DREM:
    1367                 :       5314 :     CASE_CFN_REMAINDER:
    1368                 :       5314 :       return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
    1369                 :            : 
    1370                 :        802 :     CASE_CFN_ATAN2:
    1371                 :        802 :       return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
    1372                 :            : 
    1373                 :        452 :     CASE_CFN_FDIM:
    1374                 :        452 :       return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
    1375                 :            : 
    1376                 :        462 :     CASE_CFN_HYPOT:
    1377                 :        462 :       return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
    1378                 :            : 
    1379                 :      70355 :     CASE_CFN_COPYSIGN:
    1380                 :      70355 :     CASE_CFN_COPYSIGN_FN:
    1381                 :      70355 :       *result = *arg0;
    1382                 :      70355 :       real_copysign (result, arg1);
    1383                 :      70355 :       return true;
    1384                 :            : 
    1385                 :        292 :     CASE_CFN_FMIN:
    1386                 :        292 :     CASE_CFN_FMIN_FN:
    1387                 :        292 :       return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
    1388                 :            : 
    1389                 :        292 :     CASE_CFN_FMAX:
    1390                 :        292 :     CASE_CFN_FMAX_FN:
    1391                 :        292 :       return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
    1392                 :            : 
    1393                 :      17109 :     CASE_CFN_POW:
    1394                 :      17109 :       return fold_const_pow (result, arg0, arg1, format);
    1395                 :            : 
    1396                 :       2345 :     CASE_CFN_NEXTAFTER:
    1397                 :       2345 :     CASE_CFN_NEXTTOWARD:
    1398                 :       2345 :       return fold_const_nextafter (result, arg0, arg1, format);
    1399                 :            : 
    1400                 :            :     default:
    1401                 :            :       return false;
    1402                 :            :     }
    1403                 :            : }
    1404                 :            : 
    1405                 :            : /* Try to evaluate:
    1406                 :            : 
    1407                 :            :       *RESULT = FN (*ARG0, ARG1)
    1408                 :            : 
    1409                 :            :    where FORMAT is the format of *RESULT and *ARG0.  Return true on
    1410                 :            :    success.  */
    1411                 :            : 
    1412                 :            : static bool
    1413                 :      24688 : fold_const_call_sss (real_value *result, combined_fn fn,
    1414                 :            :                      const real_value *arg0, const wide_int_ref &arg1,
    1415                 :            :                      const real_format *format)
    1416                 :            : {
    1417                 :      24688 :   switch (fn)
    1418                 :            :     {
    1419                 :       7776 :     CASE_CFN_LDEXP:
    1420                 :       7776 :       return fold_const_builtin_load_exponent (result, arg0, arg1, format);
    1421                 :            : 
    1422                 :      16539 :     CASE_CFN_SCALBN:
    1423                 :      16539 :     CASE_CFN_SCALBLN:
    1424                 :      16539 :       return (format->b == 2
    1425                 :      16539 :               && fold_const_builtin_load_exponent (result, arg0, arg1,
    1426                 :            :                                                    format));
    1427                 :            : 
    1428                 :        364 :     CASE_CFN_POWI:
    1429                 :            :       /* Avoid the folding if flag_signaling_nans is on and
    1430                 :            :          operand is a signaling NaN.  */
    1431                 :        364 :       if (!flag_unsafe_math_optimizations
    1432                 :        351 :           && flag_signaling_nans
    1433                 :        364 :           && REAL_VALUE_ISSIGNALING_NAN (*arg0))
    1434                 :            :         return false;
    1435                 :            : 
    1436                 :        728 :       real_powi (result, format, arg0, arg1.to_shwi ());
    1437                 :        364 :       return true;
    1438                 :            : 
    1439                 :            :     default:
    1440                 :            :       return false;
    1441                 :            :     }
    1442                 :            : }
    1443                 :            : 
    1444                 :            : /* Try to evaluate:
    1445                 :            : 
    1446                 :            :       *RESULT = FN (ARG0, *ARG1)
    1447                 :            : 
    1448                 :            :    where FORMAT is the format of *RESULT and *ARG1.  Return true on
    1449                 :            :    success.  */
    1450                 :            : 
    1451                 :            : static bool
    1452                 :       6428 : fold_const_call_sss (real_value *result, combined_fn fn,
    1453                 :            :                      const wide_int_ref &arg0, const real_value *arg1,
    1454                 :            :                      const real_format *format)
    1455                 :            : {
    1456                 :       6428 :   switch (fn)
    1457                 :            :     {
    1458                 :       1208 :     CASE_CFN_JN:
    1459                 :       1208 :       return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
    1460                 :            : 
    1461                 :       5211 :     CASE_CFN_YN:
    1462                 :       5211 :       return (real_compare (GT_EXPR, arg1, &dconst0)
    1463                 :       5211 :               && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
    1464                 :            : 
    1465                 :            :     default:
    1466                 :            :       return false;
    1467                 :            :     }
    1468                 :            : }
    1469                 :            : 
    1470                 :            : /* Try to evaluate:
    1471                 :            : 
    1472                 :            :       RESULT = fn (ARG0, ARG1)
    1473                 :            : 
    1474                 :            :    where FORMAT is the format of the real and imaginary parts of RESULT
    1475                 :            :    (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
    1476                 :            :    and of ARG1 (ARG1_REAL and ARG1_IMAG).  Return true on success.  */
    1477                 :            : 
    1478                 :            : static bool
    1479                 :      32579 : fold_const_call_ccc (real_value *result_real, real_value *result_imag,
    1480                 :            :                      combined_fn fn, const real_value *arg0_real,
    1481                 :            :                      const real_value *arg0_imag, const real_value *arg1_real,
    1482                 :            :                      const real_value *arg1_imag, const real_format *format)
    1483                 :            : {
    1484                 :          0 :   switch (fn)
    1485                 :            :     {
    1486                 :      32579 :     CASE_CFN_CPOW:
    1487                 :      32579 :       return do_mpc_arg2 (result_real, result_imag, mpc_pow,
    1488                 :          0 :                           arg0_real, arg0_imag, arg1_real, arg1_imag, format);
    1489                 :            : 
    1490                 :            :     default:
    1491                 :            :       return false;
    1492                 :            :     }
    1493                 :            : }
    1494                 :            : 
    1495                 :            : /* Subroutine of fold_const_call, with the same interface.  Handle cases
    1496                 :            :    where the arguments and result are numerical.  */
    1497                 :            : 
    1498                 :            : static tree
    1499                 :    5708670 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
    1500                 :            : {
    1501                 :    5708670 :   machine_mode mode = TYPE_MODE (type);
    1502                 :    5708670 :   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
    1503                 :    5708670 :   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
    1504                 :            : 
    1505                 :    5708670 :   if (mode == arg0_mode
    1506                 :    3549650 :       && real_cst_p (arg0)
    1507                 :    6791690 :       && real_cst_p (arg1))
    1508                 :            :     {
    1509                 :      99447 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
    1510                 :      99447 :       REAL_VALUE_TYPE result;
    1511                 :      99447 :       if (arg0_mode == arg1_mode)
    1512                 :            :         {
    1513                 :            :           /* real, real -> real.  */
    1514                 :     198322 :           if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1515                 :      99161 :                                    TREE_REAL_CST_PTR (arg1),
    1516                 :      99161 :                                    REAL_MODE_FORMAT (mode)))
    1517                 :      82297 :             return build_real (type, result);
    1518                 :            :         }
    1519                 :        286 :       else if (arg1_mode == TYPE_MODE (long_double_type_node))
    1520                 :        286 :         switch (fn)
    1521                 :            :           {
    1522                 :        286 :           CASE_CFN_NEXTTOWARD:
    1523                 :            :             /* real, long double -> real.  */
    1524                 :        572 :             if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1525                 :        286 :                                      TREE_REAL_CST_PTR (arg1),
    1526                 :        286 :                                      REAL_MODE_FORMAT (mode)))
    1527                 :        224 :               return build_real (type, result);
    1528                 :            :             break;
    1529                 :            :           default:
    1530                 :            :             break;
    1531                 :            :           }
    1532                 :      16926 :       return NULL_TREE;
    1533                 :            :     }
    1534                 :            : 
    1535                 :    5609230 :   if (real_cst_p (arg0)
    1536                 :    5609230 :       && integer_cst_p (arg1))
    1537                 :            :     {
    1538                 :      24691 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
    1539                 :      24691 :       if (mode == arg0_mode)
    1540                 :            :         {
    1541                 :            :           /* real, int -> real.  */
    1542                 :      24688 :           REAL_VALUE_TYPE result;
    1543                 :      24688 :           if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1544                 :      49376 :                                    wi::to_wide (arg1),
    1545                 :      24688 :                                    REAL_MODE_FORMAT (mode)))
    1546                 :       5057 :             return build_real (type, result);
    1547                 :            :         }
    1548                 :      19634 :       return NULL_TREE;
    1549                 :            :     }
    1550                 :            : 
    1551                 :    5584540 :   if (integer_cst_p (arg0)
    1552                 :    5584540 :       && real_cst_p (arg1))
    1553                 :            :     {
    1554                 :       6428 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
    1555                 :       6428 :       if (mode == arg1_mode)
    1556                 :            :         {
    1557                 :            :           /* int, real -> real.  */
    1558                 :       6428 :           REAL_VALUE_TYPE result;
    1559                 :      12856 :           if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
    1560                 :       6428 :                                    TREE_REAL_CST_PTR (arg1),
    1561                 :       6428 :                                    REAL_MODE_FORMAT (mode)))
    1562                 :       1745 :             return build_real (type, result);
    1563                 :            :         }
    1564                 :       4683 :       return NULL_TREE;
    1565                 :            :     }
    1566                 :            : 
    1567                 :    5578110 :   if (arg0_mode == arg1_mode
    1568                 :    3717620 :       && complex_cst_p (arg0)
    1569                 :    5610690 :       && complex_cst_p (arg1))
    1570                 :            :     {
    1571                 :      32579 :       gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
    1572                 :      65158 :       machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
    1573                 :      32579 :       tree arg0r = TREE_REALPART (arg0);
    1574                 :      32579 :       tree arg0i = TREE_IMAGPART (arg0);
    1575                 :      32579 :       tree arg1r = TREE_REALPART (arg1);
    1576                 :      32579 :       tree arg1i = TREE_IMAGPART (arg1);
    1577                 :      32579 :       if (mode == arg0_mode
    1578                 :      32579 :           && real_cst_p (arg0r)
    1579                 :      32579 :           && real_cst_p (arg0i)
    1580                 :      32579 :           && real_cst_p (arg1r)
    1581                 :      65158 :           && real_cst_p (arg1i))
    1582                 :            :         {
    1583                 :            :           /* complex real, complex real -> complex real.  */
    1584                 :      32579 :           REAL_VALUE_TYPE result_real, result_imag;
    1585                 :      65158 :           if (fold_const_call_ccc (&result_real, &result_imag, fn,
    1586                 :      32579 :                                    TREE_REAL_CST_PTR (arg0r),
    1587                 :      32579 :                                    TREE_REAL_CST_PTR (arg0i),
    1588                 :      32579 :                                    TREE_REAL_CST_PTR (arg1r),
    1589                 :      32579 :                                    TREE_REAL_CST_PTR (arg1i),
    1590                 :      32579 :                                    REAL_MODE_FORMAT (inner_mode)))
    1591                 :      32205 :             return build_complex (type,
    1592                 :      10735 :                                   build_real (TREE_TYPE (type), result_real),
    1593                 :      21470 :                                   build_real (TREE_TYPE (type), result_imag));
    1594                 :            :         }
    1595                 :      21844 :       return NULL_TREE;
    1596                 :            :     }
    1597                 :            : 
    1598                 :            :   return NULL_TREE;
    1599                 :            : }
    1600                 :            : 
    1601                 :            : /* Try to fold FN (ARG0, ARG1) to a constant.  Return the constant on success,
    1602                 :            :    otherwise return null.  TYPE is the type of the return value.  */
    1603                 :            : 
    1604                 :            : tree
    1605                 :    6281580 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
    1606                 :            : {
    1607                 :    6281580 :   const char *p0, *p1;
    1608                 :    6281580 :   char c;
    1609                 :    6281580 :   switch (fn)
    1610                 :            :     {
    1611                 :       1890 :     case CFN_BUILT_IN_STRSPN:
    1612                 :       1890 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1613                 :        127 :         return build_int_cst (type, strspn (p0, p1));
    1614                 :            :       return NULL_TREE;
    1615                 :            : 
    1616                 :       1604 :     case CFN_BUILT_IN_STRCSPN:
    1617                 :       1604 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1618                 :        127 :         return build_int_cst (type, strcspn (p0, p1));
    1619                 :            :       return NULL_TREE;
    1620                 :            : 
    1621                 :     381330 :     case CFN_BUILT_IN_STRCMP:
    1622                 :     381330 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1623                 :       2905 :         return build_cmp_result (type, strcmp (p0, p1));
    1624                 :            :       return NULL_TREE;
    1625                 :            : 
    1626                 :        341 :     case CFN_BUILT_IN_STRCASECMP:
    1627                 :        341 :       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1628                 :            :         {
    1629                 :          7 :           int r = strcmp (p0, p1);
    1630                 :          7 :           if (r == 0)
    1631                 :          1 :             return build_cmp_result (type, r);
    1632                 :            :         }
    1633                 :            :       return NULL_TREE;
    1634                 :            : 
    1635                 :      79268 :     case CFN_BUILT_IN_INDEX:
    1636                 :      79268 :     case CFN_BUILT_IN_STRCHR:
    1637                 :      79268 :       if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
    1638                 :            :         {
    1639                 :        173 :           const char *r = strchr (p0, c);
    1640                 :        173 :           if (r == NULL)
    1641                 :         44 :             return build_int_cst (type, 0);
    1642                 :        129 :           return fold_convert (type,
    1643                 :            :                                fold_build_pointer_plus_hwi (arg0, r - p0));
    1644                 :            :         }
    1645                 :            :       return NULL_TREE;
    1646                 :            : 
    1647                 :      67787 :     case CFN_BUILT_IN_RINDEX:
    1648                 :      67787 :     case CFN_BUILT_IN_STRRCHR:
    1649                 :      67787 :       if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
    1650                 :            :         {
    1651                 :        137 :           const char *r = strrchr (p0, c);
    1652                 :        137 :           if (r == NULL)
    1653                 :         47 :             return build_int_cst (type, 0);
    1654                 :         90 :           return fold_convert (type,
    1655                 :            :                                fold_build_pointer_plus_hwi (arg0, r - p0));
    1656                 :            :         }
    1657                 :            :       return NULL_TREE;
    1658                 :            : 
    1659                 :      40686 :     case CFN_BUILT_IN_STRSTR:
    1660                 :      40686 :       if ((p1 = c_getstr (arg1)))
    1661                 :            :         {
    1662                 :       5816 :           if ((p0 = c_getstr (arg0)))
    1663                 :            :             {
    1664                 :        142 :               const char *r = strstr (p0, p1);
    1665                 :        142 :               if (r == NULL)
    1666                 :         13 :                 return build_int_cst (type, 0);
    1667                 :        129 :               return fold_convert (type,
    1668                 :            :                                    fold_build_pointer_plus_hwi (arg0, r - p0));
    1669                 :            :             }
    1670                 :       5674 :           if (*p1 == '\0')
    1671                 :         13 :             return fold_convert (type, arg0);
    1672                 :            :         }
    1673                 :            :       return NULL_TREE;
    1674                 :            : 
    1675                 :          0 :     case CFN_FOLD_LEFT_PLUS:
    1676                 :          0 :       return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
    1677                 :            : 
    1678                 :    5708670 :     default:
    1679                 :    5708670 :       return fold_const_call_1 (fn, type, arg0, arg1);
    1680                 :            :     }
    1681                 :            : }
    1682                 :            : 
    1683                 :            : /* Try to evaluate:
    1684                 :            : 
    1685                 :            :       *RESULT = FN (*ARG0, *ARG1, *ARG2)
    1686                 :            : 
    1687                 :            :    in format FORMAT.  Return true on success.  */
    1688                 :            : 
    1689                 :            : static bool
    1690                 :       2595 : fold_const_call_ssss (real_value *result, combined_fn fn,
    1691                 :            :                       const real_value *arg0, const real_value *arg1,
    1692                 :            :                       const real_value *arg2, const real_format *format)
    1693                 :            : {
    1694                 :       2595 :   switch (fn)
    1695                 :            :     {
    1696                 :       2595 :     CASE_CFN_FMA:
    1697                 :       2595 :     CASE_CFN_FMA_FN:
    1698                 :       2595 :       return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
    1699                 :            : 
    1700                 :          0 :     case CFN_FMS:
    1701                 :          0 :       {
    1702                 :          0 :         real_value new_arg2 = real_value_negate (arg2);
    1703                 :          0 :         return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
    1704                 :            :       }
    1705                 :            : 
    1706                 :          0 :     case CFN_FNMA:
    1707                 :          0 :       {
    1708                 :          0 :         real_value new_arg0 = real_value_negate (arg0);
    1709                 :          0 :         return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
    1710                 :            :       }
    1711                 :            : 
    1712                 :          0 :     case CFN_FNMS:
    1713                 :          0 :       {
    1714                 :          0 :         real_value new_arg0 = real_value_negate (arg0);
    1715                 :          0 :         real_value new_arg2 = real_value_negate (arg2);
    1716                 :          0 :         return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
    1717                 :            :                              &new_arg2, format);
    1718                 :            :       }
    1719                 :            : 
    1720                 :            :     default:
    1721                 :            :       return false;
    1722                 :            :     }
    1723                 :            : }
    1724                 :            : 
    1725                 :            : /* Subroutine of fold_const_call, with the same interface.  Handle cases
    1726                 :            :    where the arguments and result are numerical.  */
    1727                 :            : 
    1728                 :            : static tree
    1729                 :    2296330 : fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
    1730                 :            : {
    1731                 :    2296330 :   machine_mode mode = TYPE_MODE (type);
    1732                 :    2296330 :   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
    1733                 :    2296330 :   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
    1734                 :    2296330 :   machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
    1735                 :            : 
    1736                 :    2296330 :   if (arg0_mode == arg1_mode
    1737                 :    2296330 :       && arg0_mode == arg2_mode
    1738                 :     808647 :       && real_cst_p (arg0)
    1739                 :       2905 :       && real_cst_p (arg1)
    1740                 :    2298980 :       && real_cst_p (arg2))
    1741                 :            :     {
    1742                 :       2595 :       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
    1743                 :       2595 :       if (mode == arg0_mode)
    1744                 :            :         {
    1745                 :            :           /* real, real, real -> real.  */
    1746                 :       2595 :           REAL_VALUE_TYPE result;
    1747                 :       5190 :           if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
    1748                 :       2595 :                                     TREE_REAL_CST_PTR (arg1),
    1749                 :       2595 :                                     TREE_REAL_CST_PTR (arg2),
    1750                 :       2595 :                                     REAL_MODE_FORMAT (mode)))
    1751                 :        929 :             return build_real (type, result);
    1752                 :            :         }
    1753                 :       1666 :       return NULL_TREE;
    1754                 :            :     }
    1755                 :            : 
    1756                 :            :   return NULL_TREE;
    1757                 :            : }
    1758                 :            : 
    1759                 :            : /* Try to fold FN (ARG0, ARG1, ARG2) to a constant.  Return the constant on
    1760                 :            :    success, otherwise return null.  TYPE is the type of the return value.  */
    1761                 :            : 
    1762                 :            : tree
    1763                 :    4371450 : fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
    1764                 :            : {
    1765                 :    4371450 :   const char *p0, *p1;
    1766                 :    4371450 :   char c;
    1767                 :    4371450 :   unsigned HOST_WIDE_INT s0, s1;
    1768                 :    4371450 :   size_t s2 = 0;
    1769                 :    4371450 :   switch (fn)
    1770                 :            :     {
    1771                 :      38799 :     case CFN_BUILT_IN_STRNCMP:
    1772                 :      38799 :       if (!host_size_t_cst_p (arg2, &s2))
    1773                 :            :         return NULL_TREE;
    1774                 :      20612 :       if (s2 == 0
    1775                 :        282 :           && !TREE_SIDE_EFFECTS (arg0)
    1776                 :      20866 :           && !TREE_SIDE_EFFECTS (arg1))
    1777                 :        254 :         return build_int_cst (type, 0);
    1778                 :      20358 :       else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
    1779                 :        557 :         return build_int_cst (type, strncmp (p0, p1, s2));
    1780                 :            :       return NULL_TREE;
    1781                 :            : 
    1782                 :       5831 :     case CFN_BUILT_IN_STRNCASECMP:
    1783                 :       5831 :       if (!host_size_t_cst_p (arg2, &s2))
    1784                 :            :         return NULL_TREE;
    1785                 :       5402 :       if (s2 == 0
    1786                 :          7 :           && !TREE_SIDE_EFFECTS (arg0)
    1787                 :       5405 :           && !TREE_SIDE_EFFECTS (arg1))
    1788                 :          3 :         return build_int_cst (type, 0);
    1789                 :       5399 :       else if ((p0 = c_getstr (arg0))
    1790                 :        694 :                && (p1 = c_getstr (arg1))
    1791                 :       5553 :                && strncmp (p0, p1, s2) == 0)
    1792                 :          3 :         return build_int_cst (type, 0);
    1793                 :            :       return NULL_TREE;
    1794                 :            : 
    1795                 :    1962250 :     case CFN_BUILT_IN_BCMP:
    1796                 :    1962250 :     case CFN_BUILT_IN_MEMCMP:
    1797                 :    1962250 :       if (!host_size_t_cst_p (arg2, &s2))
    1798                 :            :         return NULL_TREE;
    1799                 :    1428240 :       if (s2 == 0
    1800                 :       9662 :           && !TREE_SIDE_EFFECTS (arg0)
    1801                 :    1437910 :           && !TREE_SIDE_EFFECTS (arg1))
    1802                 :       9662 :         return build_int_cst (type, 0);
    1803                 :    1418580 :       if ((p0 = c_getstr (arg0, &s0))
    1804                 :       5932 :           && (p1 = c_getstr (arg1, &s1))
    1805                 :       2523 :           && s2 <= s0
    1806                 :    1421100 :           && s2 <= s1)
    1807                 :       2523 :         return build_cmp_result (type, memcmp (p0, p1, s2));
    1808                 :            :       return NULL_TREE;
    1809                 :            : 
    1810                 :      68237 :     case CFN_BUILT_IN_MEMCHR:
    1811                 :      68237 :       if (!host_size_t_cst_p (arg2, &s2))
    1812                 :            :         return NULL_TREE;
    1813                 :       6509 :       if (s2 == 0
    1814                 :        157 :           && !TREE_SIDE_EFFECTS (arg0)
    1815                 :       6649 :           && !TREE_SIDE_EFFECTS (arg1))
    1816                 :        137 :         return build_int_cst (type, 0);
    1817                 :       6372 :       if ((p0 = c_getstr (arg0, &s0))
    1818                 :       1631 :           && s2 <= s0
    1819                 :       7463 :           && target_char_cst_p (arg1, &c))
    1820                 :            :         {
    1821                 :        676 :           const char *r = (const char *) memchr (p0, c, s2);
    1822                 :        676 :           if (r == NULL)
    1823                 :        264 :             return build_int_cst (type, 0);
    1824                 :        412 :           return fold_convert (type,
    1825                 :            :                                fold_build_pointer_plus_hwi (arg0, r - p0));
    1826                 :            :         }
    1827                 :            :       return NULL_TREE;
    1828                 :            : 
    1829                 :          0 :     case CFN_WHILE_ULT:
    1830                 :          0 :       {
    1831                 :          0 :         poly_uint64 parg0, parg1;
    1832                 :          0 :         if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
    1833                 :          0 :           return fold_while_ult (type, parg0, parg1);
    1834                 :            :         return NULL_TREE;
    1835                 :            :       }
    1836                 :            : 
    1837                 :    2296330 :     default:
    1838                 :    2296330 :       return fold_const_call_1 (fn, type, arg0, arg1, arg2);
    1839                 :            :     }
    1840                 :            : }

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.