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