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