xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fold-const-call.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Constant folding for calls to built-in and internal functions.
2    Copyright (C) 1988-2020 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "realmpfr.h"
24 #include "tree.h"
25 #include "stor-layout.h"
26 #include "options.h"
27 #include "fold-const.h"
28 #include "fold-const-call.h"
29 #include "case-cfn-macros.h"
30 #include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO.  */
31 #include "builtins.h"
32 #include "gimple-expr.h"
33 #include "tree-vector-builder.h"
34 
35 /* Functions that test for certain constant types, abstracting away the
36    decision about whether to check for overflow.  */
37 
38 static inline bool
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       *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
1036       return true;
1037 
1038     default:
1039       return false;
1040     }
1041 }
1042 
1043 /* Try to evaluate:
1044 
1045       RESULT = FN (*ARG)
1046 
1047    where FORMAT is the format of ARG and of the real and imaginary parts
1048    of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively.  Return
1049    true on success.  */
1050 
1051 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)1052 fold_const_call_cs (real_value *result_real, real_value *result_imag,
1053 		    combined_fn fn, const real_value *arg,
1054 		    const real_format *format)
1055 {
1056   switch (fn)
1057     {
1058     CASE_CFN_CEXPI:
1059       /* cexpi(x+yi) = cos(x)+sin(y)*i.  */
1060       return do_mpfr_sincos (result_imag, result_real, arg, format);
1061 
1062     default:
1063       return false;
1064     }
1065 }
1066 
1067 /* Try to evaluate:
1068 
1069       *RESULT = fn (ARG)
1070 
1071    where FORMAT is the format of RESULT and of the real and imaginary parts
1072    of ARG, passed as ARG_REAL and ARG_IMAG respectively.  Return true on
1073    success.  */
1074 
1075 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)1076 fold_const_call_sc (real_value *result, combined_fn fn,
1077 		    const real_value *arg_real, const real_value *arg_imag,
1078 		    const real_format *format)
1079 {
1080   switch (fn)
1081     {
1082     CASE_CFN_CABS:
1083       return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
1084 
1085     default:
1086       return false;
1087     }
1088 }
1089 
1090 /* Try to evaluate:
1091 
1092       RESULT = fn (ARG)
1093 
1094    where FORMAT is the format of the real and imaginary parts of RESULT
1095    (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
1096    Return true on success.  */
1097 
1098 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)1099 fold_const_call_cc (real_value *result_real, real_value *result_imag,
1100 		    combined_fn fn, const real_value *arg_real,
1101 		    const real_value *arg_imag, const real_format *format)
1102 {
1103   switch (fn)
1104     {
1105     CASE_CFN_CCOS:
1106       return do_mpc_arg1 (result_real, result_imag, mpc_cos,
1107 			  arg_real, arg_imag, format);
1108 
1109     CASE_CFN_CCOSH:
1110       return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
1111 			  arg_real, arg_imag, format);
1112 
1113     CASE_CFN_CPROJ:
1114       if (real_isinf (arg_real) || real_isinf (arg_imag))
1115 	{
1116 	  real_inf (result_real);
1117 	  *result_imag = dconst0;
1118 	  result_imag->sign = arg_imag->sign;
1119 	}
1120       else
1121 	{
1122 	  *result_real = *arg_real;
1123 	  *result_imag = *arg_imag;
1124 	}
1125       return true;
1126 
1127     CASE_CFN_CSIN:
1128       return do_mpc_arg1 (result_real, result_imag, mpc_sin,
1129 			  arg_real, arg_imag, format);
1130 
1131     CASE_CFN_CSINH:
1132       return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
1133 			  arg_real, arg_imag, format);
1134 
1135     CASE_CFN_CTAN:
1136       return do_mpc_arg1 (result_real, result_imag, mpc_tan,
1137 			  arg_real, arg_imag, format);
1138 
1139     CASE_CFN_CTANH:
1140       return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
1141 			  arg_real, arg_imag, format);
1142 
1143     CASE_CFN_CLOG:
1144       return do_mpc_arg1 (result_real, result_imag, mpc_log,
1145 			  arg_real, arg_imag, format);
1146 
1147     CASE_CFN_CSQRT:
1148       return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
1149 			  arg_real, arg_imag, format);
1150 
1151     CASE_CFN_CASIN:
1152       return do_mpc_arg1 (result_real, result_imag, mpc_asin,
1153 			  arg_real, arg_imag, format);
1154 
1155     CASE_CFN_CACOS:
1156       return do_mpc_arg1 (result_real, result_imag, mpc_acos,
1157 			  arg_real, arg_imag, format);
1158 
1159     CASE_CFN_CATAN:
1160       return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1161 			  arg_real, arg_imag, format);
1162 
1163     CASE_CFN_CASINH:
1164       return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1165 			  arg_real, arg_imag, format);
1166 
1167     CASE_CFN_CACOSH:
1168       return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1169 			  arg_real, arg_imag, format);
1170 
1171     CASE_CFN_CATANH:
1172       return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1173 			  arg_real, arg_imag, format);
1174 
1175     CASE_CFN_CEXP:
1176       return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1177 			  arg_real, arg_imag, format);
1178 
1179     default:
1180       return false;
1181     }
1182 }
1183 
1184 /* Subroutine of fold_const_call, with the same interface.  Handle cases
1185    where the arguments and result are numerical.  */
1186 
1187 static tree
fold_const_call_1(combined_fn fn,tree type,tree arg)1188 fold_const_call_1 (combined_fn fn, tree type, tree arg)
1189 {
1190   machine_mode mode = TYPE_MODE (type);
1191   machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1192 
1193   if (integer_cst_p (arg))
1194     {
1195       if (SCALAR_INT_MODE_P (mode))
1196 	{
1197 	  wide_int result;
1198 	  if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
1199 				  TYPE_PRECISION (type), TREE_TYPE (arg)))
1200 	    return wide_int_to_tree (type, result);
1201 	}
1202       return NULL_TREE;
1203     }
1204 
1205   if (real_cst_p (arg))
1206     {
1207       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1208       if (mode == arg_mode)
1209 	{
1210 	  /* real -> real.  */
1211 	  REAL_VALUE_TYPE result;
1212 	  if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1213 				  REAL_MODE_FORMAT (mode)))
1214 	    return build_real (type, result);
1215 	}
1216       else if (COMPLEX_MODE_P (mode)
1217 	       && GET_MODE_INNER (mode) == arg_mode)
1218 	{
1219 	  /* real -> complex real.  */
1220 	  REAL_VALUE_TYPE result_real, result_imag;
1221 	  if (fold_const_call_cs (&result_real, &result_imag, fn,
1222 				  TREE_REAL_CST_PTR (arg),
1223 				  REAL_MODE_FORMAT (arg_mode)))
1224 	    return build_complex (type,
1225 				  build_real (TREE_TYPE (type), result_real),
1226 				  build_real (TREE_TYPE (type), result_imag));
1227 	}
1228       else if (INTEGRAL_TYPE_P (type))
1229 	{
1230 	  /* real -> int.  */
1231 	  wide_int result;
1232 	  if (fold_const_call_ss (&result, fn,
1233 				  TREE_REAL_CST_PTR (arg),
1234 				  TYPE_PRECISION (type),
1235 				  REAL_MODE_FORMAT (arg_mode)))
1236 	    return wide_int_to_tree (type, result);
1237 	}
1238       return NULL_TREE;
1239     }
1240 
1241   if (complex_cst_p (arg))
1242     {
1243       gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1244       machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1245       tree argr = TREE_REALPART (arg);
1246       tree argi = TREE_IMAGPART (arg);
1247       if (mode == arg_mode
1248 	  && real_cst_p (argr)
1249 	  && real_cst_p (argi))
1250 	{
1251 	  /* complex real -> complex real.  */
1252 	  REAL_VALUE_TYPE result_real, result_imag;
1253 	  if (fold_const_call_cc (&result_real, &result_imag, fn,
1254 				  TREE_REAL_CST_PTR (argr),
1255 				  TREE_REAL_CST_PTR (argi),
1256 				  REAL_MODE_FORMAT (inner_mode)))
1257 	    return build_complex (type,
1258 				  build_real (TREE_TYPE (type), result_real),
1259 				  build_real (TREE_TYPE (type), result_imag));
1260 	}
1261       if (mode == inner_mode
1262 	  && real_cst_p (argr)
1263 	  && real_cst_p (argi))
1264 	{
1265 	  /* complex real -> real.  */
1266 	  REAL_VALUE_TYPE result;
1267 	  if (fold_const_call_sc (&result, fn,
1268 				  TREE_REAL_CST_PTR (argr),
1269 				  TREE_REAL_CST_PTR (argi),
1270 				  REAL_MODE_FORMAT (inner_mode)))
1271 	    return build_real (type, result);
1272 	}
1273       return NULL_TREE;
1274     }
1275 
1276   return NULL_TREE;
1277 }
1278 
1279 /* Try to fold FN (ARG) to a constant.  Return the constant on success,
1280    otherwise return null.  TYPE is the type of the return value.  */
1281 
1282 tree
fold_const_call(combined_fn fn,tree type,tree arg)1283 fold_const_call (combined_fn fn, tree type, tree arg)
1284 {
1285   switch (fn)
1286     {
1287     case CFN_BUILT_IN_STRLEN:
1288       if (const char *str = c_getstr (arg))
1289 	return build_int_cst (type, strlen (str));
1290       return NULL_TREE;
1291 
1292     CASE_CFN_NAN:
1293     CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
1294     case CFN_BUILT_IN_NAND32:
1295     case CFN_BUILT_IN_NAND64:
1296     case CFN_BUILT_IN_NAND128:
1297       return fold_const_builtin_nan (type, arg, true);
1298 
1299     CASE_CFN_NANS:
1300     CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
1301       return fold_const_builtin_nan (type, arg, false);
1302 
1303     case CFN_REDUC_PLUS:
1304       return fold_const_reduction (type, arg, PLUS_EXPR);
1305 
1306     case CFN_REDUC_MAX:
1307       return fold_const_reduction (type, arg, MAX_EXPR);
1308 
1309     case CFN_REDUC_MIN:
1310       return fold_const_reduction (type, arg, MIN_EXPR);
1311 
1312     case CFN_REDUC_AND:
1313       return fold_const_reduction (type, arg, BIT_AND_EXPR);
1314 
1315     case CFN_REDUC_IOR:
1316       return fold_const_reduction (type, arg, BIT_IOR_EXPR);
1317 
1318     case CFN_REDUC_XOR:
1319       return fold_const_reduction (type, arg, BIT_XOR_EXPR);
1320 
1321     case CFN_VEC_CONVERT:
1322       return fold_const_vec_convert (type, arg);
1323 
1324     default:
1325       return fold_const_call_1 (fn, type, arg);
1326     }
1327 }
1328 
1329 /* Fold a call to IFN_FOLD_LEFT_<CODE> (ARG0, ARG1), returning a value
1330    of type TYPE.  */
1331 
1332 static tree
fold_const_fold_left(tree type,tree arg0,tree arg1,tree_code code)1333 fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code)
1334 {
1335   if (TREE_CODE (arg1) != VECTOR_CST)
1336     return NULL_TREE;
1337 
1338   unsigned HOST_WIDE_INT nelts;
1339   if (!VECTOR_CST_NELTS (arg1).is_constant (&nelts))
1340     return NULL_TREE;
1341 
1342   for (unsigned HOST_WIDE_INT i = 0; i < nelts; i++)
1343     {
1344       arg0 = const_binop (code, type, arg0, VECTOR_CST_ELT (arg1, i));
1345       if (arg0 == NULL_TREE || !CONSTANT_CLASS_P (arg0))
1346 	return NULL_TREE;
1347     }
1348   return arg0;
1349 }
1350 
1351 /* Try to evaluate:
1352 
1353       *RESULT = FN (*ARG0, *ARG1)
1354 
1355    in format FORMAT.  Return true on success.  */
1356 
1357 static bool
fold_const_call_sss(real_value * result,combined_fn fn,const real_value * arg0,const real_value * arg1,const real_format * format)1358 fold_const_call_sss (real_value *result, combined_fn fn,
1359 		     const real_value *arg0, const real_value *arg1,
1360 		     const real_format *format)
1361 {
1362   switch (fn)
1363     {
1364     CASE_CFN_DREM:
1365     CASE_CFN_REMAINDER:
1366       return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1367 
1368     CASE_CFN_ATAN2:
1369       return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1370 
1371     CASE_CFN_FDIM:
1372       return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1373 
1374     CASE_CFN_HYPOT:
1375       return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1376 
1377     CASE_CFN_COPYSIGN:
1378     CASE_CFN_COPYSIGN_FN:
1379       *result = *arg0;
1380       real_copysign (result, arg1);
1381       return true;
1382 
1383     CASE_CFN_FMIN:
1384     CASE_CFN_FMIN_FN:
1385       return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1386 
1387     CASE_CFN_FMAX:
1388     CASE_CFN_FMAX_FN:
1389       return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1390 
1391     CASE_CFN_POW:
1392       return fold_const_pow (result, arg0, arg1, format);
1393 
1394     CASE_CFN_NEXTAFTER:
1395     CASE_CFN_NEXTTOWARD:
1396       return fold_const_nextafter (result, arg0, arg1, format);
1397 
1398     default:
1399       return false;
1400     }
1401 }
1402 
1403 /* Try to evaluate:
1404 
1405       *RESULT = FN (*ARG0, ARG1)
1406 
1407    where FORMAT is the format of *RESULT and *ARG0.  Return true on
1408    success.  */
1409 
1410 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)1411 fold_const_call_sss (real_value *result, combined_fn fn,
1412 		     const real_value *arg0, const wide_int_ref &arg1,
1413 		     const real_format *format)
1414 {
1415   switch (fn)
1416     {
1417     CASE_CFN_LDEXP:
1418       return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1419 
1420     CASE_CFN_SCALBN:
1421     CASE_CFN_SCALBLN:
1422       return (format->b == 2
1423 	      && fold_const_builtin_load_exponent (result, arg0, arg1,
1424 						   format));
1425 
1426     CASE_CFN_POWI:
1427       /* Avoid the folding if flag_signaling_nans is on and
1428          operand is a signaling NaN.  */
1429       if (!flag_unsafe_math_optimizations
1430 	  && flag_signaling_nans
1431 	  && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1432         return false;
1433 
1434       real_powi (result, format, arg0, arg1.to_shwi ());
1435       return true;
1436 
1437     default:
1438       return false;
1439     }
1440 }
1441 
1442 /* Try to evaluate:
1443 
1444       *RESULT = FN (ARG0, *ARG1)
1445 
1446    where FORMAT is the format of *RESULT and *ARG1.  Return true on
1447    success.  */
1448 
1449 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)1450 fold_const_call_sss (real_value *result, combined_fn fn,
1451 		     const wide_int_ref &arg0, const real_value *arg1,
1452 		     const real_format *format)
1453 {
1454   switch (fn)
1455     {
1456     CASE_CFN_JN:
1457       return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1458 
1459     CASE_CFN_YN:
1460       return (real_compare (GT_EXPR, arg1, &dconst0)
1461 	      && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1462 
1463     default:
1464       return false;
1465     }
1466 }
1467 
1468 /* Try to evaluate:
1469 
1470       RESULT = fn (ARG0, ARG1)
1471 
1472    where FORMAT is the format of the real and imaginary parts of RESULT
1473    (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1474    and of ARG1 (ARG1_REAL and ARG1_IMAG).  Return true on success.  */
1475 
1476 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)1477 fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1478 		     combined_fn fn, const real_value *arg0_real,
1479 		     const real_value *arg0_imag, const real_value *arg1_real,
1480 		     const real_value *arg1_imag, const real_format *format)
1481 {
1482   switch (fn)
1483     {
1484     CASE_CFN_CPOW:
1485       return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1486 			  arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1487 
1488     default:
1489       return false;
1490     }
1491 }
1492 
1493 /* Subroutine of fold_const_call, with the same interface.  Handle cases
1494    where the arguments and result are numerical.  */
1495 
1496 static tree
fold_const_call_1(combined_fn fn,tree type,tree arg0,tree arg1)1497 fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1498 {
1499   machine_mode mode = TYPE_MODE (type);
1500   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1501   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1502 
1503   if (mode == arg0_mode
1504       && real_cst_p (arg0)
1505       && real_cst_p (arg1))
1506     {
1507       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1508       REAL_VALUE_TYPE result;
1509       if (arg0_mode == arg1_mode)
1510 	{
1511 	  /* real, real -> real.  */
1512 	  if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1513 				   TREE_REAL_CST_PTR (arg1),
1514 				   REAL_MODE_FORMAT (mode)))
1515 	    return build_real (type, result);
1516 	}
1517       else if (arg1_mode == TYPE_MODE (long_double_type_node))
1518 	switch (fn)
1519 	  {
1520 	  CASE_CFN_NEXTTOWARD:
1521 	    /* real, long double -> real.  */
1522 	    if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1523 				     TREE_REAL_CST_PTR (arg1),
1524 				     REAL_MODE_FORMAT (mode)))
1525 	      return build_real (type, result);
1526 	    break;
1527 	  default:
1528 	    break;
1529 	  }
1530       return NULL_TREE;
1531     }
1532 
1533   if (real_cst_p (arg0)
1534       && integer_cst_p (arg1))
1535     {
1536       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1537       if (mode == arg0_mode)
1538 	{
1539 	  /* real, int -> real.  */
1540 	  REAL_VALUE_TYPE result;
1541 	  if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1542 				   wi::to_wide (arg1),
1543 				   REAL_MODE_FORMAT (mode)))
1544 	    return build_real (type, result);
1545 	}
1546       return NULL_TREE;
1547     }
1548 
1549   if (integer_cst_p (arg0)
1550       && real_cst_p (arg1))
1551     {
1552       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1553       if (mode == arg1_mode)
1554 	{
1555 	  /* int, real -> real.  */
1556 	  REAL_VALUE_TYPE result;
1557 	  if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
1558 				   TREE_REAL_CST_PTR (arg1),
1559 				   REAL_MODE_FORMAT (mode)))
1560 	    return build_real (type, result);
1561 	}
1562       return NULL_TREE;
1563     }
1564 
1565   if (arg0_mode == arg1_mode
1566       && complex_cst_p (arg0)
1567       && complex_cst_p (arg1))
1568     {
1569       gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1570       machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1571       tree arg0r = TREE_REALPART (arg0);
1572       tree arg0i = TREE_IMAGPART (arg0);
1573       tree arg1r = TREE_REALPART (arg1);
1574       tree arg1i = TREE_IMAGPART (arg1);
1575       if (mode == arg0_mode
1576 	  && real_cst_p (arg0r)
1577 	  && real_cst_p (arg0i)
1578 	  && real_cst_p (arg1r)
1579 	  && real_cst_p (arg1i))
1580 	{
1581 	  /* complex real, complex real -> complex real.  */
1582 	  REAL_VALUE_TYPE result_real, result_imag;
1583 	  if (fold_const_call_ccc (&result_real, &result_imag, fn,
1584 				   TREE_REAL_CST_PTR (arg0r),
1585 				   TREE_REAL_CST_PTR (arg0i),
1586 				   TREE_REAL_CST_PTR (arg1r),
1587 				   TREE_REAL_CST_PTR (arg1i),
1588 				   REAL_MODE_FORMAT (inner_mode)))
1589 	    return build_complex (type,
1590 				  build_real (TREE_TYPE (type), result_real),
1591 				  build_real (TREE_TYPE (type), result_imag));
1592 	}
1593       return NULL_TREE;
1594     }
1595 
1596   return NULL_TREE;
1597 }
1598 
1599 /* Try to fold FN (ARG0, ARG1) to a constant.  Return the constant on success,
1600    otherwise return null.  TYPE is the type of the return value.  */
1601 
1602 tree
fold_const_call(combined_fn fn,tree type,tree arg0,tree arg1)1603 fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1604 {
1605   const char *p0, *p1;
1606   char c;
1607   switch (fn)
1608     {
1609     case CFN_BUILT_IN_STRSPN:
1610       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1611 	return build_int_cst (type, strspn (p0, p1));
1612       return NULL_TREE;
1613 
1614     case CFN_BUILT_IN_STRCSPN:
1615       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1616 	return build_int_cst (type, strcspn (p0, p1));
1617       return NULL_TREE;
1618 
1619     case CFN_BUILT_IN_STRCMP:
1620       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1621 	return build_cmp_result (type, strcmp (p0, p1));
1622       return NULL_TREE;
1623 
1624     case CFN_BUILT_IN_STRCASECMP:
1625       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1626 	{
1627 	  int r = strcmp (p0, p1);
1628 	  if (r == 0)
1629 	    return build_cmp_result (type, r);
1630 	}
1631       return NULL_TREE;
1632 
1633     case CFN_BUILT_IN_INDEX:
1634     case CFN_BUILT_IN_STRCHR:
1635       if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1636 	{
1637 	  const char *r = strchr (p0, c);
1638 	  if (r == NULL)
1639 	    return build_int_cst (type, 0);
1640 	  return fold_convert (type,
1641 			       fold_build_pointer_plus_hwi (arg0, r - p0));
1642 	}
1643       return NULL_TREE;
1644 
1645     case CFN_BUILT_IN_RINDEX:
1646     case CFN_BUILT_IN_STRRCHR:
1647       if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
1648 	{
1649 	  const char *r = strrchr (p0, c);
1650 	  if (r == NULL)
1651 	    return build_int_cst (type, 0);
1652 	  return fold_convert (type,
1653 			       fold_build_pointer_plus_hwi (arg0, r - p0));
1654 	}
1655       return NULL_TREE;
1656 
1657     case CFN_BUILT_IN_STRSTR:
1658       if ((p1 = c_getstr (arg1)))
1659 	{
1660 	  if ((p0 = c_getstr (arg0)))
1661 	    {
1662 	      const char *r = strstr (p0, p1);
1663 	      if (r == NULL)
1664 		return build_int_cst (type, 0);
1665 	      return fold_convert (type,
1666 				   fold_build_pointer_plus_hwi (arg0, r - p0));
1667 	    }
1668 	  if (*p1 == '\0')
1669 	    return fold_convert (type, arg0);
1670 	}
1671       return NULL_TREE;
1672 
1673     case CFN_FOLD_LEFT_PLUS:
1674       return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR);
1675 
1676     default:
1677       return fold_const_call_1 (fn, type, arg0, arg1);
1678     }
1679 }
1680 
1681 /* Try to evaluate:
1682 
1683       *RESULT = FN (*ARG0, *ARG1, *ARG2)
1684 
1685    in format FORMAT.  Return true on success.  */
1686 
1687 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)1688 fold_const_call_ssss (real_value *result, combined_fn fn,
1689 		      const real_value *arg0, const real_value *arg1,
1690 		      const real_value *arg2, const real_format *format)
1691 {
1692   switch (fn)
1693     {
1694     CASE_CFN_FMA:
1695     CASE_CFN_FMA_FN:
1696       return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1697 
1698     case CFN_FMS:
1699       {
1700 	real_value new_arg2 = real_value_negate (arg2);
1701 	return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, &new_arg2, format);
1702       }
1703 
1704     case CFN_FNMA:
1705       {
1706 	real_value new_arg0 = real_value_negate (arg0);
1707 	return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1, arg2, format);
1708       }
1709 
1710     case CFN_FNMS:
1711       {
1712 	real_value new_arg0 = real_value_negate (arg0);
1713 	real_value new_arg2 = real_value_negate (arg2);
1714 	return do_mpfr_arg3 (result, mpfr_fma, &new_arg0, arg1,
1715 			     &new_arg2, format);
1716       }
1717 
1718     default:
1719       return false;
1720     }
1721 }
1722 
1723 /* Subroutine of fold_const_call, with the same interface.  Handle cases
1724    where the arguments and result are numerical.  */
1725 
1726 static tree
fold_const_call_1(combined_fn fn,tree type,tree arg0,tree arg1,tree arg2)1727 fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
1728 {
1729   machine_mode mode = TYPE_MODE (type);
1730   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1731   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1732   machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1733 
1734   if (arg0_mode == arg1_mode
1735       && arg0_mode == arg2_mode
1736       && real_cst_p (arg0)
1737       && real_cst_p (arg1)
1738       && real_cst_p (arg2))
1739     {
1740       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1741       if (mode == arg0_mode)
1742 	{
1743 	  /* real, real, real -> real.  */
1744 	  REAL_VALUE_TYPE result;
1745 	  if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1746 				    TREE_REAL_CST_PTR (arg1),
1747 				    TREE_REAL_CST_PTR (arg2),
1748 				    REAL_MODE_FORMAT (mode)))
1749 	    return build_real (type, result);
1750 	}
1751       return NULL_TREE;
1752     }
1753 
1754   return NULL_TREE;
1755 }
1756 
1757 /* Try to fold FN (ARG0, ARG1, ARG2) to a constant.  Return the constant on
1758    success, otherwise return null.  TYPE is the type of the return value.  */
1759 
1760 tree
fold_const_call(combined_fn fn,tree type,tree arg0,tree arg1,tree arg2)1761 fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
1762 {
1763   const char *p0, *p1;
1764   char c;
1765   unsigned HOST_WIDE_INT s0, s1, s2 = 0;
1766   switch (fn)
1767     {
1768     case CFN_BUILT_IN_STRNCMP:
1769       if (!size_t_cst_p (arg2, &s2))
1770 	return NULL_TREE;
1771       if (s2 == 0
1772 	  && !TREE_SIDE_EFFECTS (arg0)
1773 	  && !TREE_SIDE_EFFECTS (arg1))
1774 	return build_int_cst (type, 0);
1775       else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1776 	return build_int_cst (type, strncmp (p0, p1, MIN (s2, SIZE_MAX)));
1777       return NULL_TREE;
1778 
1779     case CFN_BUILT_IN_STRNCASECMP:
1780       if (!size_t_cst_p (arg2, &s2))
1781 	return NULL_TREE;
1782       if (s2 == 0
1783 	  && !TREE_SIDE_EFFECTS (arg0)
1784 	  && !TREE_SIDE_EFFECTS (arg1))
1785 	return build_int_cst (type, 0);
1786       else if ((p0 = c_getstr (arg0))
1787 	       && (p1 = c_getstr (arg1))
1788 	       && strncmp (p0, p1, MIN (s2, SIZE_MAX)) == 0)
1789 	return build_int_cst (type, 0);
1790       return NULL_TREE;
1791 
1792     case CFN_BUILT_IN_BCMP:
1793     case CFN_BUILT_IN_MEMCMP:
1794       if (!size_t_cst_p (arg2, &s2))
1795 	return NULL_TREE;
1796       if (s2 == 0
1797 	  && !TREE_SIDE_EFFECTS (arg0)
1798 	  && !TREE_SIDE_EFFECTS (arg1))
1799 	return build_int_cst (type, 0);
1800       if ((p0 = c_getstr (arg0, &s0))
1801 	  && (p1 = c_getstr (arg1, &s1))
1802 	  && s2 <= s0
1803 	  && s2 <= s1)
1804 	return build_cmp_result (type, memcmp (p0, p1, s2));
1805       return NULL_TREE;
1806 
1807     case CFN_BUILT_IN_MEMCHR:
1808       if (!size_t_cst_p (arg2, &s2))
1809 	return NULL_TREE;
1810       if (s2 == 0
1811 	  && !TREE_SIDE_EFFECTS (arg0)
1812 	  && !TREE_SIDE_EFFECTS (arg1))
1813 	return build_int_cst (type, 0);
1814       if ((p0 = c_getstr (arg0, &s0))
1815 	  && s2 <= s0
1816 	  && target_char_cst_p (arg1, &c))
1817 	{
1818 	  const char *r = (const char *) memchr (p0, c, s2);
1819 	  if (r == NULL)
1820 	    return build_int_cst (type, 0);
1821 	  return fold_convert (type,
1822 			       fold_build_pointer_plus_hwi (arg0, r - p0));
1823 	}
1824       return NULL_TREE;
1825 
1826     case CFN_WHILE_ULT:
1827       {
1828 	poly_uint64 parg0, parg1;
1829 	if (poly_int_tree_p (arg0, &parg0) && poly_int_tree_p (arg1, &parg1))
1830 	  return fold_while_ult (type, parg0, parg1);
1831 	return NULL_TREE;
1832       }
1833 
1834     default:
1835       return fold_const_call_1 (fn, type, arg0, arg1, arg2);
1836     }
1837 }
1838