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