1 /* Constant folding for calls to built-in and internal functions.
2    Copyright (C) 1988-2016 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 
32 /* Functions that test for certain constant types, abstracting away the
33    decision about whether to check for overflow.  */
34 
35 static inline bool
integer_cst_p(tree t)36 integer_cst_p (tree t)
37 {
38   return TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t);
39 }
40 
41 static inline bool
real_cst_p(tree t)42 real_cst_p (tree t)
43 {
44   return TREE_CODE (t) == REAL_CST && !TREE_OVERFLOW (t);
45 }
46 
47 static inline bool
complex_cst_p(tree t)48 complex_cst_p (tree t)
49 {
50   return TREE_CODE (t) == COMPLEX_CST;
51 }
52 
53 /* Return true if ARG is a constant in the range of the host size_t.
54    Store it in *SIZE_OUT if so.  */
55 
56 static inline bool
host_size_t_cst_p(tree t,size_t * size_out)57 host_size_t_cst_p (tree t, size_t *size_out)
58 {
59   if (integer_cst_p (t)
60       && wi::min_precision (t, UNSIGNED) <= sizeof (size_t) * CHAR_BIT)
61     {
62       *size_out = tree_to_uhwi (t);
63       return true;
64     }
65   return false;
66 }
67 
68 /* RES is the result of a comparison in which < 0 means "less", 0 means
69    "equal" and > 0 means "more".  Canonicalize it to -1, 0 or 1 and
70    return it in type TYPE.  */
71 
72 static inline tree
build_cmp_result(tree type,int res)73 build_cmp_result (tree type, int res)
74 {
75   return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0);
76 }
77 
78 /* M is the result of trying to constant-fold an expression (starting
79    with clear MPFR flags) and INEXACT says whether the result in M is
80    exact or inexact.  Return true if M can be used as a constant-folded
81    result in format FORMAT, storing the value in *RESULT if so.  */
82 
83 static bool
do_mpfr_ckconv(real_value * result,mpfr_srcptr m,bool inexact,const real_format * format)84 do_mpfr_ckconv (real_value *result, mpfr_srcptr m, bool inexact,
85 		const real_format *format)
86 {
87   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
88      overflow/underflow occurred.  If -frounding-math, proceed iff the
89      result of calling FUNC was exact.  */
90   if (!mpfr_number_p (m)
91       || mpfr_overflow_p ()
92       || mpfr_underflow_p ()
93       || (flag_rounding_math && inexact))
94     return false;
95 
96   REAL_VALUE_TYPE tmp;
97   real_from_mpfr (&tmp, m, format, GMP_RNDN);
98 
99   /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
100      If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
101      underflowed in the conversion.  */
102   if (!real_isfinite (&tmp)
103       || ((tmp.cl == rvc_zero) != (mpfr_zero_p (m) != 0)))
104     return false;
105 
106   real_convert (result, format, &tmp);
107   return real_identical (result, &tmp);
108 }
109 
110 /* Try to evaluate:
111 
112       *RESULT = f (*ARG)
113 
114    in format FORMAT, given that FUNC is the MPFR implementation of f.
115    Return true on success.  */
116 
117 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)118 do_mpfr_arg1 (real_value *result,
119 	      int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
120 	      const real_value *arg, const real_format *format)
121 {
122   /* To proceed, MPFR must exactly represent the target floating point
123      format, which only happens when the target base equals two.  */
124   if (format->b != 2 || !real_isfinite (arg))
125     return false;
126 
127   int prec = format->p;
128   mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
129   mpfr_t m;
130 
131   mpfr_init2 (m, prec);
132   mpfr_from_real (m, arg, GMP_RNDN);
133   mpfr_clear_flags ();
134   bool inexact = func (m, m, rnd);
135   bool ok = do_mpfr_ckconv (result, m, inexact, format);
136   mpfr_clear (m);
137 
138   return ok;
139 }
140 
141 /* Try to evaluate:
142 
143       *RESULT_SIN = sin (*ARG);
144       *RESULT_COS = cos (*ARG);
145 
146    for format FORMAT.  Return true on success.  */
147 
148 static bool
do_mpfr_sincos(real_value * result_sin,real_value * result_cos,const real_value * arg,const real_format * format)149 do_mpfr_sincos (real_value *result_sin, real_value *result_cos,
150 		const real_value *arg, const real_format *format)
151 {
152   /* To proceed, MPFR must exactly represent the target floating point
153      format, which only happens when the target base equals two.  */
154   if (format->b != 2 || !real_isfinite (arg))
155     return false;
156 
157   int prec = format->p;
158   mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
159   mpfr_t m, ms, mc;
160 
161   mpfr_inits2 (prec, m, ms, mc, NULL);
162   mpfr_from_real (m, arg, GMP_RNDN);
163   mpfr_clear_flags ();
164   bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
165   bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
166 	     && do_mpfr_ckconv (result_cos, mc, inexact, format));
167   mpfr_clears (m, ms, mc, NULL);
168 
169   return ok;
170 }
171 
172 /* Try to evaluate:
173 
174       *RESULT = f (*ARG0, *ARG1)
175 
176    in format FORMAT, given that FUNC is the MPFR implementation of f.
177    Return true on success.  */
178 
179 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)180 do_mpfr_arg2 (real_value *result,
181 	      int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t),
182 	      const real_value *arg0, const real_value *arg1,
183 	      const real_format *format)
184 {
185   /* To proceed, MPFR must exactly represent the target floating point
186      format, which only happens when the target base equals two.  */
187   if (format->b != 2 || !real_isfinite (arg0) || !real_isfinite (arg1))
188     return false;
189 
190   int prec = format->p;
191   mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
192   mpfr_t m0, m1;
193 
194   mpfr_inits2 (prec, m0, m1, NULL);
195   mpfr_from_real (m0, arg0, GMP_RNDN);
196   mpfr_from_real (m1, arg1, GMP_RNDN);
197   mpfr_clear_flags ();
198   bool inexact = func (m0, m0, m1, rnd);
199   bool ok = do_mpfr_ckconv (result, m0, inexact, format);
200   mpfr_clears (m0, m1, NULL);
201 
202   return ok;
203 }
204 
205 /* Try to evaluate:
206 
207       *RESULT = f (ARG0, *ARG1)
208 
209    in format FORMAT, given that FUNC is the MPFR implementation of f.
210    Return true on success.  */
211 
212 static bool
do_mpfr_arg2(real_value * result,int (* func)(mpfr_ptr,long,mpfr_srcptr,mp_rnd_t),const wide_int_ref & arg0,const real_value * arg1,const real_format * format)213 do_mpfr_arg2 (real_value *result,
214 	      int (*func) (mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
215 	      const wide_int_ref &arg0, const real_value *arg1,
216 	      const real_format *format)
217 {
218   if (format->b != 2 || !real_isfinite (arg1))
219     return false;
220 
221   int prec = format->p;
222   mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
223   mpfr_t m;
224 
225   mpfr_init2 (m, prec);
226   mpfr_from_real (m, arg1, GMP_RNDN);
227   mpfr_clear_flags ();
228   bool inexact = func (m, arg0.to_shwi (), m, rnd);
229   bool ok = do_mpfr_ckconv (result, m, inexact, format);
230   mpfr_clear (m);
231 
232   return ok;
233 }
234 
235 /* Try to evaluate:
236 
237       *RESULT = f (*ARG0, *ARG1, *ARG2)
238 
239    in format FORMAT, given that FUNC is the MPFR implementation of f.
240    Return true on success.  */
241 
242 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)243 do_mpfr_arg3 (real_value *result,
244 	      int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_srcptr,
245 			   mpfr_srcptr, mpfr_rnd_t),
246 	      const real_value *arg0, const real_value *arg1,
247 	      const real_value *arg2, const real_format *format)
248 {
249   /* To proceed, MPFR must exactly represent the target floating point
250      format, which only happens when the target base equals two.  */
251   if (format->b != 2
252       || !real_isfinite (arg0)
253       || !real_isfinite (arg1)
254       || !real_isfinite (arg2))
255     return false;
256 
257   int prec = format->p;
258   mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
259   mpfr_t m0, m1, m2;
260 
261   mpfr_inits2 (prec, m0, m1, m2, NULL);
262   mpfr_from_real (m0, arg0, GMP_RNDN);
263   mpfr_from_real (m1, arg1, GMP_RNDN);
264   mpfr_from_real (m2, arg2, GMP_RNDN);
265   mpfr_clear_flags ();
266   bool inexact = func (m0, m0, m1, m2, rnd);
267   bool ok = do_mpfr_ckconv (result, m0, inexact, format);
268   mpfr_clears (m0, m1, m2, NULL);
269 
270   return ok;
271 }
272 
273 /* M is the result of trying to constant-fold an expression (starting
274    with clear MPFR flags) and INEXACT says whether the result in M is
275    exact or inexact.  Return true if M can be used as a constant-folded
276    result in which the real and imaginary parts have format FORMAT.
277    Store those parts in *RESULT_REAL and *RESULT_IMAG if so.  */
278 
279 static bool
do_mpc_ckconv(real_value * result_real,real_value * result_imag,mpc_srcptr m,bool inexact,const real_format * format)280 do_mpc_ckconv (real_value *result_real, real_value *result_imag,
281 	       mpc_srcptr m, bool inexact, const real_format *format)
282 {
283   /* Proceed iff we get a normal number, i.e. not NaN or Inf and no
284      overflow/underflow occurred.  If -frounding-math, proceed iff the
285      result of calling FUNC was exact.  */
286   if (!mpfr_number_p (mpc_realref (m))
287       || !mpfr_number_p (mpc_imagref (m))
288       || mpfr_overflow_p ()
289       || mpfr_underflow_p ()
290       || (flag_rounding_math && inexact))
291     return false;
292 
293   REAL_VALUE_TYPE tmp_real, tmp_imag;
294   real_from_mpfr (&tmp_real, mpc_realref (m), format, GMP_RNDN);
295   real_from_mpfr (&tmp_imag, mpc_imagref (m), format, GMP_RNDN);
296 
297   /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
298      If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
299      underflowed in the conversion.  */
300   if (!real_isfinite (&tmp_real)
301       || !real_isfinite (&tmp_imag)
302       || (tmp_real.cl == rvc_zero) != (mpfr_zero_p (mpc_realref (m)) != 0)
303       || (tmp_imag.cl == rvc_zero) != (mpfr_zero_p (mpc_imagref (m)) != 0))
304     return false;
305 
306   real_convert (result_real, format, &tmp_real);
307   real_convert (result_imag, format, &tmp_imag);
308 
309   return (real_identical (result_real, &tmp_real)
310 	  && real_identical (result_imag, &tmp_imag));
311 }
312 
313 /* Try to evaluate:
314 
315       RESULT = f (ARG)
316 
317    in format FORMAT, given that FUNC is the mpc implementation of f.
318    Return true on success.  Both RESULT and ARG are represented as
319    real and imaginary pairs.  */
320 
321 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)322 do_mpc_arg1 (real_value *result_real, real_value *result_imag,
323 	     int (*func) (mpc_ptr, mpc_srcptr, mpc_rnd_t),
324 	     const real_value *arg_real, const real_value *arg_imag,
325 	     const real_format *format)
326 {
327   /* To proceed, MPFR must exactly represent the target floating point
328      format, which only happens when the target base equals two.  */
329   if (format->b != 2
330       || !real_isfinite (arg_real)
331       || !real_isfinite (arg_imag))
332     return false;
333 
334   int prec = format->p;
335   mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
336   mpc_t m;
337 
338   mpc_init2 (m, prec);
339   mpfr_from_real (mpc_realref (m), arg_real, GMP_RNDN);
340   mpfr_from_real (mpc_imagref (m), arg_imag, GMP_RNDN);
341   mpfr_clear_flags ();
342   bool inexact = func (m, m, crnd);
343   bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
344   mpc_clear (m);
345 
346   return ok;
347 }
348 
349 /* Try to evaluate:
350 
351       RESULT = f (ARG0, ARG1)
352 
353    in format FORMAT, given that FUNC is the mpc implementation of f.
354    Return true on success.  RESULT, ARG0 and ARG1 are represented as
355    real and imaginary pairs.  */
356 
357 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)358 do_mpc_arg2 (real_value *result_real, real_value *result_imag,
359 	     int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t),
360 	     const real_value *arg0_real, const real_value *arg0_imag,
361 	     const real_value *arg1_real, const real_value *arg1_imag,
362 	     const real_format *format)
363 {
364   if (!real_isfinite (arg0_real)
365       || !real_isfinite (arg0_imag)
366       || !real_isfinite (arg1_real)
367       || !real_isfinite (arg1_imag))
368     return false;
369 
370   int prec = format->p;
371   mpc_rnd_t crnd = format->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
372   mpc_t m0, m1;
373 
374   mpc_init2 (m0, prec);
375   mpc_init2 (m1, prec);
376   mpfr_from_real (mpc_realref (m0), arg0_real, GMP_RNDN);
377   mpfr_from_real (mpc_imagref (m0), arg0_imag, GMP_RNDN);
378   mpfr_from_real (mpc_realref (m1), arg1_real, GMP_RNDN);
379   mpfr_from_real (mpc_imagref (m1), arg1_imag, GMP_RNDN);
380   mpfr_clear_flags ();
381   bool inexact = func (m0, m0, m1, crnd);
382   bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
383   mpc_clear (m0);
384   mpc_clear (m1);
385 
386   return ok;
387 }
388 
389 /* Try to evaluate:
390 
391       *RESULT = logb (*ARG)
392 
393    in format FORMAT.  Return true on success.  */
394 
395 static bool
fold_const_logb(real_value * result,const real_value * arg,const real_format * format)396 fold_const_logb (real_value *result, const real_value *arg,
397 		 const real_format *format)
398 {
399   switch (arg->cl)
400     {
401     case rvc_nan:
402       /* If arg is +-NaN, then return it.  */
403       *result = *arg;
404       return true;
405 
406     case rvc_inf:
407       /* If arg is +-Inf, then return +Inf.  */
408       *result = *arg;
409       result->sign = 0;
410       return true;
411 
412     case rvc_zero:
413       /* Zero may set errno and/or raise an exception.  */
414       return false;
415 
416     case rvc_normal:
417       /* For normal numbers, proceed iff radix == 2.  In GCC,
418 	 normalized significands are in the range [0.5, 1.0).  We
419 	 want the exponent as if they were [1.0, 2.0) so get the
420 	 exponent and subtract 1.  */
421       if (format->b == 2)
422 	{
423 	  real_from_integer (result, format, REAL_EXP (arg) - 1, SIGNED);
424 	  return true;
425 	}
426       return false;
427     }
428   gcc_unreachable ();
429 }
430 
431 /* Try to evaluate:
432 
433       *RESULT = significand (*ARG)
434 
435    in format FORMAT.  Return true on success.  */
436 
437 static bool
fold_const_significand(real_value * result,const real_value * arg,const real_format * format)438 fold_const_significand (real_value *result, const real_value *arg,
439 			const real_format *format)
440 {
441   switch (arg->cl)
442     {
443     case rvc_zero:
444     case rvc_nan:
445     case rvc_inf:
446       /* If arg is +-0, +-Inf or +-NaN, then return it.  */
447       *result = *arg;
448       return true;
449 
450     case rvc_normal:
451       /* For normal numbers, proceed iff radix == 2.  */
452       if (format->b == 2)
453 	{
454 	  *result = *arg;
455 	  /* In GCC, normalized significands are in the range [0.5, 1.0).
456 	     We want them to be [1.0, 2.0) so set the exponent to 1.  */
457 	  SET_REAL_EXP (result, 1);
458 	  return true;
459 	}
460       return false;
461     }
462   gcc_unreachable ();
463 }
464 
465 /* Try to evaluate:
466 
467       *RESULT = f (*ARG)
468 
469    where FORMAT is the format of *ARG and PRECISION is the number of
470    significant bits in the result.  Return true on success.  */
471 
472 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)473 fold_const_conversion (wide_int *result,
474 		       void (*fn) (real_value *, format_helper,
475 				   const real_value *),
476 		       const real_value *arg, unsigned int precision,
477 		       const real_format *format)
478 {
479   if (!real_isfinite (arg))
480     return false;
481 
482   real_value rounded;
483   fn (&rounded, format, arg);
484 
485   bool fail = false;
486   *result = real_to_integer (&rounded, &fail, precision);
487   return !fail;
488 }
489 
490 /* Try to evaluate:
491 
492       *RESULT = pow (*ARG0, *ARG1)
493 
494    in format FORMAT.  Return true on success.  */
495 
496 static bool
fold_const_pow(real_value * result,const real_value * arg0,const real_value * arg1,const real_format * format)497 fold_const_pow (real_value *result, const real_value *arg0,
498 		const real_value *arg1, const real_format *format)
499 {
500   if (do_mpfr_arg2 (result, mpfr_pow, arg0, arg1, format))
501     return true;
502 
503   /* Check for an integer exponent.  */
504   REAL_VALUE_TYPE cint1;
505   HOST_WIDE_INT n1 = real_to_integer (arg1);
506   real_from_integer (&cint1, VOIDmode, n1, SIGNED);
507   /* Attempt to evaluate pow at compile-time, unless this should
508      raise an exception.  */
509   if (real_identical (arg1, &cint1)
510       && (n1 > 0
511 	  || (!flag_trapping_math && !flag_errno_math)
512 	  || !real_equal (arg0, &dconst0)))
513     {
514       bool inexact = real_powi (result, format, arg0, n1);
515       /* Avoid the folding if flag_signaling_nans is on.  */
516       if (flag_unsafe_math_optimizations
517 	  || (!inexact
518 	      && !(flag_signaling_nans
519 	           && REAL_VALUE_ISSIGNALING_NAN (*arg0))))
520 	return true;
521     }
522 
523   return false;
524 }
525 
526 /* Try to evaluate:
527 
528       *RESULT = ldexp (*ARG0, ARG1)
529 
530    in format FORMAT.  Return true on success.  */
531 
532 static bool
fold_const_builtin_load_exponent(real_value * result,const real_value * arg0,const wide_int_ref & arg1,const real_format * format)533 fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
534 				  const wide_int_ref &arg1,
535 				  const real_format *format)
536 {
537   /* Bound the maximum adjustment to twice the range of the
538      mode's valid exponents.  Use abs to ensure the range is
539      positive as a sanity check.  */
540   int max_exp_adj = 2 * labs (format->emax - format->emin);
541 
542   /* The requested adjustment must be inside this range.  This
543      is a preliminary cap to avoid things like overflow, we
544      may still fail to compute the result for other reasons.  */
545   if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
546     return false;
547 
548   /* Don't perform operation if we honor signaling NaNs and
549      operand is a signaling NaN.  */
550   if (!flag_unsafe_math_optimizations
551       && flag_signaling_nans
552       && REAL_VALUE_ISSIGNALING_NAN (*arg0))
553     return false;
554 
555   REAL_VALUE_TYPE initial_result;
556   real_ldexp (&initial_result, arg0, arg1.to_shwi ());
557 
558   /* Ensure we didn't overflow.  */
559   if (real_isinf (&initial_result))
560     return false;
561 
562   /* Only proceed if the target mode can hold the
563      resulting value.  */
564   *result = real_value_truncate (format, initial_result);
565   return real_equal (&initial_result, result);
566 }
567 
568 /* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
569    return type TYPE.  QUIET is true if a quiet rather than signalling
570    NaN is required.  */
571 
572 static tree
fold_const_builtin_nan(tree type,tree arg,bool quiet)573 fold_const_builtin_nan (tree type, tree arg, bool quiet)
574 {
575   REAL_VALUE_TYPE real;
576   const char *str = c_getstr (arg);
577   if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
578     return build_real (type, real);
579   return NULL_TREE;
580 }
581 
582 /* Try to evaluate:
583 
584       *RESULT = FN (*ARG)
585 
586    in format FORMAT.  Return true on success.  */
587 
588 static bool
fold_const_call_ss(real_value * result,combined_fn fn,const real_value * arg,const real_format * format)589 fold_const_call_ss (real_value *result, combined_fn fn,
590 		    const real_value *arg, const real_format *format)
591 {
592   switch (fn)
593     {
594     CASE_CFN_SQRT:
595       return (real_compare (GE_EXPR, arg, &dconst0)
596 	      && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
597 
598     CASE_CFN_CBRT:
599       return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
600 
601     CASE_CFN_ASIN:
602       return (real_compare (GE_EXPR, arg, &dconstm1)
603 	      && real_compare (LE_EXPR, arg, &dconst1)
604 	      && do_mpfr_arg1 (result, mpfr_asin, arg, format));
605 
606     CASE_CFN_ACOS:
607       return (real_compare (GE_EXPR, arg, &dconstm1)
608 	      && real_compare (LE_EXPR, arg, &dconst1)
609 	      && do_mpfr_arg1 (result, mpfr_acos, arg, format));
610 
611     CASE_CFN_ATAN:
612       return do_mpfr_arg1 (result, mpfr_atan, arg, format);
613 
614     CASE_CFN_ASINH:
615       return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
616 
617     CASE_CFN_ACOSH:
618       return (real_compare (GE_EXPR, arg, &dconst1)
619 	      && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
620 
621     CASE_CFN_ATANH:
622       return (real_compare (GE_EXPR, arg, &dconstm1)
623 	      && real_compare (LE_EXPR, arg, &dconst1)
624 	      && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
625 
626     CASE_CFN_SIN:
627       return do_mpfr_arg1 (result, mpfr_sin, arg, format);
628 
629     CASE_CFN_COS:
630       return do_mpfr_arg1 (result, mpfr_cos, arg, format);
631 
632     CASE_CFN_TAN:
633       return do_mpfr_arg1 (result, mpfr_tan, arg, format);
634 
635     CASE_CFN_SINH:
636       return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
637 
638     CASE_CFN_COSH:
639       return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
640 
641     CASE_CFN_TANH:
642       return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
643 
644     CASE_CFN_ERF:
645       return do_mpfr_arg1 (result, mpfr_erf, arg, format);
646 
647     CASE_CFN_ERFC:
648       return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
649 
650     CASE_CFN_TGAMMA:
651       return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
652 
653     CASE_CFN_EXP:
654       return do_mpfr_arg1 (result, mpfr_exp, arg, format);
655 
656     CASE_CFN_EXP2:
657       return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
658 
659     CASE_CFN_EXP10:
660     CASE_CFN_POW10:
661       return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
662 
663     CASE_CFN_EXPM1:
664       return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
665 
666     CASE_CFN_LOG:
667       return (real_compare (GT_EXPR, arg, &dconst0)
668 	      && do_mpfr_arg1 (result, mpfr_log, arg, format));
669 
670     CASE_CFN_LOG2:
671       return (real_compare (GT_EXPR, arg, &dconst0)
672 	      && do_mpfr_arg1 (result, mpfr_log2, arg, format));
673 
674     CASE_CFN_LOG10:
675       return (real_compare (GT_EXPR, arg, &dconst0)
676 	      && do_mpfr_arg1 (result, mpfr_log10, arg, format));
677 
678     CASE_CFN_LOG1P:
679       return (real_compare (GT_EXPR, arg, &dconstm1)
680 	      && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
681 
682     CASE_CFN_J0:
683       return do_mpfr_arg1 (result, mpfr_j0, arg, format);
684 
685     CASE_CFN_J1:
686       return do_mpfr_arg1 (result, mpfr_j1, arg, format);
687 
688     CASE_CFN_Y0:
689       return (real_compare (GT_EXPR, arg, &dconst0)
690 	      && do_mpfr_arg1 (result, mpfr_y0, arg, format));
691 
692     CASE_CFN_Y1:
693       return (real_compare (GT_EXPR, arg, &dconst0)
694 	      && do_mpfr_arg1 (result, mpfr_y1, arg, format));
695 
696     CASE_CFN_FLOOR:
697       if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
698 	{
699 	  real_floor (result, format, arg);
700 	  return true;
701 	}
702       return false;
703 
704     CASE_CFN_CEIL:
705       if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
706 	{
707 	  real_ceil (result, format, arg);
708 	  return true;
709 	}
710       return false;
711 
712     CASE_CFN_TRUNC:
713       real_trunc (result, format, arg);
714       return true;
715 
716     CASE_CFN_ROUND:
717       if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
718 	{
719 	  real_round (result, format, arg);
720 	  return true;
721 	}
722       return false;
723 
724     CASE_CFN_LOGB:
725       return fold_const_logb (result, arg, format);
726 
727     CASE_CFN_SIGNIFICAND:
728       return fold_const_significand (result, arg, format);
729 
730     default:
731       return false;
732     }
733 }
734 
735 /* Try to evaluate:
736 
737       *RESULT = FN (*ARG)
738 
739    where FORMAT is the format of ARG and PRECISION is the number of
740    significant bits in the result.  Return true on success.  */
741 
742 static bool
fold_const_call_ss(wide_int * result,combined_fn fn,const real_value * arg,unsigned int precision,const real_format * format)743 fold_const_call_ss (wide_int *result, combined_fn fn,
744 		    const real_value *arg, unsigned int precision,
745 		    const real_format *format)
746 {
747   switch (fn)
748     {
749     CASE_CFN_SIGNBIT:
750       if (real_isneg (arg))
751 	*result = wi::one (precision);
752       else
753 	*result = wi::zero (precision);
754       return true;
755 
756     CASE_CFN_ILOGB:
757       /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
758 	 Proceed iff radix == 2.  In GCC, normalized significands are in
759 	 the range [0.5, 1.0).  We want the exponent as if they were
760 	 [1.0, 2.0) so get the exponent and subtract 1.  */
761       if (arg->cl == rvc_normal && format->b == 2)
762 	{
763 	  *result = wi::shwi (REAL_EXP (arg) - 1, precision);
764 	  return true;
765 	}
766       return false;
767 
768     CASE_CFN_ICEIL:
769     CASE_CFN_LCEIL:
770     CASE_CFN_LLCEIL:
771       return fold_const_conversion (result, real_ceil, arg,
772 				    precision, format);
773 
774     CASE_CFN_LFLOOR:
775     CASE_CFN_IFLOOR:
776     CASE_CFN_LLFLOOR:
777       return fold_const_conversion (result, real_floor, arg,
778 				    precision, format);
779 
780     CASE_CFN_IROUND:
781     CASE_CFN_LROUND:
782     CASE_CFN_LLROUND:
783       return fold_const_conversion (result, real_round, arg,
784 				    precision, format);
785 
786     CASE_CFN_IRINT:
787     CASE_CFN_LRINT:
788     CASE_CFN_LLRINT:
789       /* Not yet folded to a constant.  */
790       return false;
791 
792     CASE_CFN_FINITE:
793     case CFN_BUILT_IN_FINITED32:
794     case CFN_BUILT_IN_FINITED64:
795     case CFN_BUILT_IN_FINITED128:
796     case CFN_BUILT_IN_ISFINITE:
797       *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
798       return true;
799 
800     CASE_CFN_ISINF:
801     case CFN_BUILT_IN_ISINFD32:
802     case CFN_BUILT_IN_ISINFD64:
803     case CFN_BUILT_IN_ISINFD128:
804       if (real_isinf (arg))
805 	*result = wi::shwi (arg->sign ? -1 : 1, precision);
806       else
807 	*result = wi::shwi (0, precision);
808       return true;
809 
810     CASE_CFN_ISNAN:
811     case CFN_BUILT_IN_ISNAND32:
812     case CFN_BUILT_IN_ISNAND64:
813     case CFN_BUILT_IN_ISNAND128:
814       *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
815       return true;
816 
817     default:
818       return false;
819     }
820 }
821 
822 /* Try to evaluate:
823 
824       *RESULT = FN (ARG)
825 
826    where ARG_TYPE is the type of ARG and PRECISION is the number of bits
827    in the result.  Return true on success.  */
828 
829 static bool
fold_const_call_ss(wide_int * result,combined_fn fn,const wide_int_ref & arg,unsigned int precision,tree arg_type)830 fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
831 		    unsigned int precision, tree arg_type)
832 {
833   switch (fn)
834     {
835     CASE_CFN_FFS:
836       *result = wi::shwi (wi::ffs (arg), precision);
837       return true;
838 
839     CASE_CFN_CLZ:
840       {
841 	int tmp;
842 	if (wi::ne_p (arg, 0))
843 	  tmp = wi::clz (arg);
844 	else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp))
845 	  tmp = TYPE_PRECISION (arg_type);
846 	*result = wi::shwi (tmp, precision);
847 	return true;
848       }
849 
850     CASE_CFN_CTZ:
851       {
852 	int tmp;
853 	if (wi::ne_p (arg, 0))
854 	  tmp = wi::ctz (arg);
855 	else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp))
856 	  tmp = TYPE_PRECISION (arg_type);
857 	*result = wi::shwi (tmp, precision);
858 	return true;
859       }
860 
861     CASE_CFN_CLRSB:
862       *result = wi::shwi (wi::clrsb (arg), precision);
863       return true;
864 
865     CASE_CFN_POPCOUNT:
866       *result = wi::shwi (wi::popcount (arg), precision);
867       return true;
868 
869     CASE_CFN_PARITY:
870       *result = wi::shwi (wi::parity (arg), precision);
871       return true;
872 
873     case CFN_BUILT_IN_BSWAP16:
874     case CFN_BUILT_IN_BSWAP32:
875     case CFN_BUILT_IN_BSWAP64:
876       *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
877       return true;
878 
879     default:
880       return false;
881     }
882 }
883 
884 /* Try to evaluate:
885 
886       RESULT = FN (*ARG)
887 
888    where FORMAT is the format of ARG and of the real and imaginary parts
889    of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively.  Return
890    true on success.  */
891 
892 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)893 fold_const_call_cs (real_value *result_real, real_value *result_imag,
894 		    combined_fn fn, const real_value *arg,
895 		    const real_format *format)
896 {
897   switch (fn)
898     {
899     CASE_CFN_CEXPI:
900       /* cexpi(x+yi) = cos(x)+sin(y)*i.  */
901       return do_mpfr_sincos (result_imag, result_real, arg, format);
902 
903     default:
904       return false;
905     }
906 }
907 
908 /* Try to evaluate:
909 
910       *RESULT = fn (ARG)
911 
912    where FORMAT is the format of RESULT and of the real and imaginary parts
913    of ARG, passed as ARG_REAL and ARG_IMAG respectively.  Return true on
914    success.  */
915 
916 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)917 fold_const_call_sc (real_value *result, combined_fn fn,
918 		    const real_value *arg_real, const real_value *arg_imag,
919 		    const real_format *format)
920 {
921   switch (fn)
922     {
923     CASE_CFN_CABS:
924       return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
925 
926     default:
927       return false;
928     }
929 }
930 
931 /* Try to evaluate:
932 
933       RESULT = fn (ARG)
934 
935    where FORMAT is the format of the real and imaginary parts of RESULT
936    (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
937    Return true on success.  */
938 
939 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)940 fold_const_call_cc (real_value *result_real, real_value *result_imag,
941 		    combined_fn fn, const real_value *arg_real,
942 		    const real_value *arg_imag, const real_format *format)
943 {
944   switch (fn)
945     {
946     CASE_CFN_CCOS:
947       return do_mpc_arg1 (result_real, result_imag, mpc_cos,
948 			  arg_real, arg_imag, format);
949 
950     CASE_CFN_CCOSH:
951       return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
952 			  arg_real, arg_imag, format);
953 
954     CASE_CFN_CPROJ:
955       if (real_isinf (arg_real) || real_isinf (arg_imag))
956 	{
957 	  real_inf (result_real);
958 	  *result_imag = dconst0;
959 	  result_imag->sign = arg_imag->sign;
960 	}
961       else
962 	{
963 	  *result_real = *arg_real;
964 	  *result_imag = *arg_imag;
965 	}
966       return true;
967 
968     CASE_CFN_CSIN:
969       return do_mpc_arg1 (result_real, result_imag, mpc_sin,
970 			  arg_real, arg_imag, format);
971 
972     CASE_CFN_CSINH:
973       return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
974 			  arg_real, arg_imag, format);
975 
976     CASE_CFN_CTAN:
977       return do_mpc_arg1 (result_real, result_imag, mpc_tan,
978 			  arg_real, arg_imag, format);
979 
980     CASE_CFN_CTANH:
981       return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
982 			  arg_real, arg_imag, format);
983 
984     CASE_CFN_CLOG:
985       return do_mpc_arg1 (result_real, result_imag, mpc_log,
986 			  arg_real, arg_imag, format);
987 
988     CASE_CFN_CSQRT:
989       return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
990 			  arg_real, arg_imag, format);
991 
992     CASE_CFN_CASIN:
993       return do_mpc_arg1 (result_real, result_imag, mpc_asin,
994 			  arg_real, arg_imag, format);
995 
996     CASE_CFN_CACOS:
997       return do_mpc_arg1 (result_real, result_imag, mpc_acos,
998 			  arg_real, arg_imag, format);
999 
1000     CASE_CFN_CATAN:
1001       return do_mpc_arg1 (result_real, result_imag, mpc_atan,
1002 			  arg_real, arg_imag, format);
1003 
1004     CASE_CFN_CASINH:
1005       return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
1006 			  arg_real, arg_imag, format);
1007 
1008     CASE_CFN_CACOSH:
1009       return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
1010 			  arg_real, arg_imag, format);
1011 
1012     CASE_CFN_CATANH:
1013       return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
1014 			  arg_real, arg_imag, format);
1015 
1016     CASE_CFN_CEXP:
1017       return do_mpc_arg1 (result_real, result_imag, mpc_exp,
1018 			  arg_real, arg_imag, format);
1019 
1020     default:
1021       return false;
1022     }
1023 }
1024 
1025 /* Subroutine of fold_const_call, with the same interface.  Handle cases
1026    where the arguments and result are numerical.  */
1027 
1028 static tree
fold_const_call_1(combined_fn fn,tree type,tree arg)1029 fold_const_call_1 (combined_fn fn, tree type, tree arg)
1030 {
1031   machine_mode mode = TYPE_MODE (type);
1032   machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
1033 
1034   if (integer_cst_p (arg))
1035     {
1036       if (SCALAR_INT_MODE_P (mode))
1037 	{
1038 	  wide_int result;
1039 	  if (fold_const_call_ss (&result, fn, arg, TYPE_PRECISION (type),
1040 				  TREE_TYPE (arg)))
1041 	    return wide_int_to_tree (type, result);
1042 	}
1043       return NULL_TREE;
1044     }
1045 
1046   if (real_cst_p (arg))
1047     {
1048       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
1049       if (mode == arg_mode)
1050 	{
1051 	  /* real -> real.  */
1052 	  REAL_VALUE_TYPE result;
1053 	  if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
1054 				  REAL_MODE_FORMAT (mode)))
1055 	    return build_real (type, result);
1056 	}
1057       else if (COMPLEX_MODE_P (mode)
1058 	       && GET_MODE_INNER (mode) == arg_mode)
1059 	{
1060 	  /* real -> complex real.  */
1061 	  REAL_VALUE_TYPE result_real, result_imag;
1062 	  if (fold_const_call_cs (&result_real, &result_imag, fn,
1063 				  TREE_REAL_CST_PTR (arg),
1064 				  REAL_MODE_FORMAT (arg_mode)))
1065 	    return build_complex (type,
1066 				  build_real (TREE_TYPE (type), result_real),
1067 				  build_real (TREE_TYPE (type), result_imag));
1068 	}
1069       else if (INTEGRAL_TYPE_P (type))
1070 	{
1071 	  /* real -> int.  */
1072 	  wide_int result;
1073 	  if (fold_const_call_ss (&result, fn,
1074 				  TREE_REAL_CST_PTR (arg),
1075 				  TYPE_PRECISION (type),
1076 				  REAL_MODE_FORMAT (arg_mode)))
1077 	    return wide_int_to_tree (type, result);
1078 	}
1079       return NULL_TREE;
1080     }
1081 
1082   if (complex_cst_p (arg))
1083     {
1084       gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
1085       machine_mode inner_mode = GET_MODE_INNER (arg_mode);
1086       tree argr = TREE_REALPART (arg);
1087       tree argi = TREE_IMAGPART (arg);
1088       if (mode == arg_mode
1089 	  && real_cst_p (argr)
1090 	  && real_cst_p (argi))
1091 	{
1092 	  /* complex real -> complex real.  */
1093 	  REAL_VALUE_TYPE result_real, result_imag;
1094 	  if (fold_const_call_cc (&result_real, &result_imag, fn,
1095 				  TREE_REAL_CST_PTR (argr),
1096 				  TREE_REAL_CST_PTR (argi),
1097 				  REAL_MODE_FORMAT (inner_mode)))
1098 	    return build_complex (type,
1099 				  build_real (TREE_TYPE (type), result_real),
1100 				  build_real (TREE_TYPE (type), result_imag));
1101 	}
1102       if (mode == inner_mode
1103 	  && real_cst_p (argr)
1104 	  && real_cst_p (argi))
1105 	{
1106 	  /* complex real -> real.  */
1107 	  REAL_VALUE_TYPE result;
1108 	  if (fold_const_call_sc (&result, fn,
1109 				  TREE_REAL_CST_PTR (argr),
1110 				  TREE_REAL_CST_PTR (argi),
1111 				  REAL_MODE_FORMAT (inner_mode)))
1112 	    return build_real (type, result);
1113 	}
1114       return NULL_TREE;
1115     }
1116 
1117   return NULL_TREE;
1118 }
1119 
1120 /* Try to fold FN (ARG) to a constant.  Return the constant on success,
1121    otherwise return null.  TYPE is the type of the return value.  */
1122 
1123 tree
fold_const_call(combined_fn fn,tree type,tree arg)1124 fold_const_call (combined_fn fn, tree type, tree arg)
1125 {
1126   switch (fn)
1127     {
1128     case CFN_BUILT_IN_STRLEN:
1129       if (const char *str = c_getstr (arg))
1130 	return build_int_cst (type, strlen (str));
1131       return NULL_TREE;
1132 
1133     CASE_CFN_NAN:
1134     case CFN_BUILT_IN_NAND32:
1135     case CFN_BUILT_IN_NAND64:
1136     case CFN_BUILT_IN_NAND128:
1137       return fold_const_builtin_nan (type, arg, true);
1138 
1139     CASE_CFN_NANS:
1140       return fold_const_builtin_nan (type, arg, false);
1141 
1142     default:
1143       return fold_const_call_1 (fn, type, arg);
1144     }
1145 }
1146 
1147 /* Try to evaluate:
1148 
1149       *RESULT = FN (*ARG0, *ARG1)
1150 
1151    in format FORMAT.  Return true on success.  */
1152 
1153 static bool
fold_const_call_sss(real_value * result,combined_fn fn,const real_value * arg0,const real_value * arg1,const real_format * format)1154 fold_const_call_sss (real_value *result, combined_fn fn,
1155 		     const real_value *arg0, const real_value *arg1,
1156 		     const real_format *format)
1157 {
1158   switch (fn)
1159     {
1160     CASE_CFN_DREM:
1161     CASE_CFN_REMAINDER:
1162       return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
1163 
1164     CASE_CFN_ATAN2:
1165       return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
1166 
1167     CASE_CFN_FDIM:
1168       return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
1169 
1170     CASE_CFN_HYPOT:
1171       return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
1172 
1173     CASE_CFN_COPYSIGN:
1174       *result = *arg0;
1175       real_copysign (result, arg1);
1176       return true;
1177 
1178     CASE_CFN_FMIN:
1179       return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
1180 
1181     CASE_CFN_FMAX:
1182       return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
1183 
1184     CASE_CFN_POW:
1185       return fold_const_pow (result, arg0, arg1, format);
1186 
1187     default:
1188       return false;
1189     }
1190 }
1191 
1192 /* Try to evaluate:
1193 
1194       *RESULT = FN (*ARG0, ARG1)
1195 
1196    where FORMAT is the format of *RESULT and *ARG0.  Return true on
1197    success.  */
1198 
1199 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)1200 fold_const_call_sss (real_value *result, combined_fn fn,
1201 		     const real_value *arg0, const wide_int_ref &arg1,
1202 		     const real_format *format)
1203 {
1204   switch (fn)
1205     {
1206     CASE_CFN_LDEXP:
1207       return fold_const_builtin_load_exponent (result, arg0, arg1, format);
1208 
1209     CASE_CFN_SCALBN:
1210     CASE_CFN_SCALBLN:
1211       return (format->b == 2
1212 	      && fold_const_builtin_load_exponent (result, arg0, arg1,
1213 						   format));
1214 
1215     CASE_CFN_POWI:
1216       /* Avoid the folding if flag_signaling_nans is on and
1217          operand is a signaling NaN.  */
1218       if (!flag_unsafe_math_optimizations
1219 	  && flag_signaling_nans
1220 	  && REAL_VALUE_ISSIGNALING_NAN (*arg0))
1221         return false;
1222 
1223       real_powi (result, format, arg0, arg1.to_shwi ());
1224       return true;
1225 
1226     default:
1227       return false;
1228     }
1229 }
1230 
1231 /* Try to evaluate:
1232 
1233       *RESULT = FN (ARG0, *ARG1)
1234 
1235    where FORMAT is the format of *RESULT and *ARG1.  Return true on
1236    success.  */
1237 
1238 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)1239 fold_const_call_sss (real_value *result, combined_fn fn,
1240 		     const wide_int_ref &arg0, const real_value *arg1,
1241 		     const real_format *format)
1242 {
1243   switch (fn)
1244     {
1245     CASE_CFN_JN:
1246       return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
1247 
1248     CASE_CFN_YN:
1249       return (real_compare (GT_EXPR, arg1, &dconst0)
1250 	      && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
1251 
1252     default:
1253       return false;
1254     }
1255 }
1256 
1257 /* Try to evaluate:
1258 
1259       RESULT = fn (ARG0, ARG1)
1260 
1261    where FORMAT is the format of the real and imaginary parts of RESULT
1262    (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
1263    and of ARG1 (ARG1_REAL and ARG1_IMAG).  Return true on success.  */
1264 
1265 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)1266 fold_const_call_ccc (real_value *result_real, real_value *result_imag,
1267 		     combined_fn fn, const real_value *arg0_real,
1268 		     const real_value *arg0_imag, const real_value *arg1_real,
1269 		     const real_value *arg1_imag, const real_format *format)
1270 {
1271   switch (fn)
1272     {
1273     CASE_CFN_CPOW:
1274       return do_mpc_arg2 (result_real, result_imag, mpc_pow,
1275 			  arg0_real, arg0_imag, arg1_real, arg1_imag, format);
1276 
1277     default:
1278       return false;
1279     }
1280 }
1281 
1282 /* Subroutine of fold_const_call, with the same interface.  Handle cases
1283    where the arguments and result are numerical.  */
1284 
1285 static tree
fold_const_call_1(combined_fn fn,tree type,tree arg0,tree arg1)1286 fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
1287 {
1288   machine_mode mode = TYPE_MODE (type);
1289   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1290   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1291 
1292   if (arg0_mode == arg1_mode
1293       && real_cst_p (arg0)
1294       && real_cst_p (arg1))
1295     {
1296       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1297       if (mode == arg0_mode)
1298 	{
1299 	  /* real, real -> real.  */
1300 	  REAL_VALUE_TYPE result;
1301 	  if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1302 				   TREE_REAL_CST_PTR (arg1),
1303 				   REAL_MODE_FORMAT (mode)))
1304 	    return build_real (type, result);
1305 	}
1306       return NULL_TREE;
1307     }
1308 
1309   if (real_cst_p (arg0)
1310       && integer_cst_p (arg1))
1311     {
1312       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1313       if (mode == arg0_mode)
1314 	{
1315 	  /* real, int -> real.  */
1316 	  REAL_VALUE_TYPE result;
1317 	  if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
1318 				   arg1, REAL_MODE_FORMAT (mode)))
1319 	    return build_real (type, result);
1320 	}
1321       return NULL_TREE;
1322     }
1323 
1324   if (integer_cst_p (arg0)
1325       && real_cst_p (arg1))
1326     {
1327       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
1328       if (mode == arg1_mode)
1329 	{
1330 	  /* int, real -> real.  */
1331 	  REAL_VALUE_TYPE result;
1332 	  if (fold_const_call_sss (&result, fn, arg0,
1333 				   TREE_REAL_CST_PTR (arg1),
1334 				   REAL_MODE_FORMAT (mode)))
1335 	    return build_real (type, result);
1336 	}
1337       return NULL_TREE;
1338     }
1339 
1340   if (arg0_mode == arg1_mode
1341       && complex_cst_p (arg0)
1342       && complex_cst_p (arg1))
1343     {
1344       gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
1345       machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
1346       tree arg0r = TREE_REALPART (arg0);
1347       tree arg0i = TREE_IMAGPART (arg0);
1348       tree arg1r = TREE_REALPART (arg1);
1349       tree arg1i = TREE_IMAGPART (arg1);
1350       if (mode == arg0_mode
1351 	  && real_cst_p (arg0r)
1352 	  && real_cst_p (arg0i)
1353 	  && real_cst_p (arg1r)
1354 	  && real_cst_p (arg1i))
1355 	{
1356 	  /* complex real, complex real -> complex real.  */
1357 	  REAL_VALUE_TYPE result_real, result_imag;
1358 	  if (fold_const_call_ccc (&result_real, &result_imag, fn,
1359 				   TREE_REAL_CST_PTR (arg0r),
1360 				   TREE_REAL_CST_PTR (arg0i),
1361 				   TREE_REAL_CST_PTR (arg1r),
1362 				   TREE_REAL_CST_PTR (arg1i),
1363 				   REAL_MODE_FORMAT (inner_mode)))
1364 	    return build_complex (type,
1365 				  build_real (TREE_TYPE (type), result_real),
1366 				  build_real (TREE_TYPE (type), result_imag));
1367 	}
1368       return NULL_TREE;
1369     }
1370 
1371   return NULL_TREE;
1372 }
1373 
1374 /* Try to fold FN (ARG0, ARG1) to a constant.  Return the constant on success,
1375    otherwise return null.  TYPE is the type of the return value.  */
1376 
1377 tree
fold_const_call(combined_fn fn,tree type,tree arg0,tree arg1)1378 fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
1379 {
1380   const char *p0, *p1;
1381   switch (fn)
1382     {
1383     case CFN_BUILT_IN_STRSPN:
1384       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1385 	return build_int_cst (type, strspn (p0, p1));
1386       return NULL_TREE;
1387 
1388     case CFN_BUILT_IN_STRCSPN:
1389       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1390 	return build_int_cst (type, strcspn (p0, p1));
1391       return NULL_TREE;
1392 
1393     case CFN_BUILT_IN_STRCMP:
1394       if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
1395 	return build_cmp_result (type, strcmp (p0, p1));
1396       return NULL_TREE;
1397 
1398     default:
1399       return fold_const_call_1 (fn, type, arg0, arg1);
1400     }
1401 }
1402 
1403 /* Try to evaluate:
1404 
1405       *RESULT = FN (*ARG0, *ARG1, *ARG2)
1406 
1407    in format FORMAT.  Return true on success.  */
1408 
1409 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)1410 fold_const_call_ssss (real_value *result, combined_fn fn,
1411 		      const real_value *arg0, const real_value *arg1,
1412 		      const real_value *arg2, const real_format *format)
1413 {
1414   switch (fn)
1415     {
1416     CASE_CFN_FMA:
1417       return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
1418 
1419     default:
1420       return false;
1421     }
1422 }
1423 
1424 /* Subroutine of fold_const_call, with the same interface.  Handle cases
1425    where the arguments and result are numerical.  */
1426 
1427 static tree
fold_const_call_1(combined_fn fn,tree type,tree arg0,tree arg1,tree arg2)1428 fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
1429 {
1430   machine_mode mode = TYPE_MODE (type);
1431   machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
1432   machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
1433   machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
1434 
1435   if (arg0_mode == arg1_mode
1436       && arg0_mode == arg2_mode
1437       && real_cst_p (arg0)
1438       && real_cst_p (arg1)
1439       && real_cst_p (arg2))
1440     {
1441       gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
1442       if (mode == arg0_mode)
1443 	{
1444 	  /* real, real, real -> real.  */
1445 	  REAL_VALUE_TYPE result;
1446 	  if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
1447 				    TREE_REAL_CST_PTR (arg1),
1448 				    TREE_REAL_CST_PTR (arg2),
1449 				    REAL_MODE_FORMAT (mode)))
1450 	    return build_real (type, result);
1451 	}
1452       return NULL_TREE;
1453     }
1454 
1455   return NULL_TREE;
1456 }
1457 
1458 /* Try to fold FN (ARG0, ARG1, ARG2) to a constant.  Return the constant on
1459    success, otherwise return null.  TYPE is the type of the return value.  */
1460 
1461 tree
fold_const_call(combined_fn fn,tree type,tree arg0,tree arg1,tree arg2)1462 fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
1463 {
1464   const char *p0, *p1;
1465   size_t s2;
1466   switch (fn)
1467     {
1468     case CFN_BUILT_IN_STRNCMP:
1469       if ((p0 = c_getstr (arg0))
1470 	  && (p1 = c_getstr (arg1))
1471 	  && host_size_t_cst_p (arg2, &s2))
1472 	return build_int_cst (type, strncmp (p0, p1, s2));
1473       return NULL_TREE;
1474 
1475     case CFN_BUILT_IN_BCMP:
1476     case CFN_BUILT_IN_MEMCMP:
1477       if ((p0 = c_getstr (arg0))
1478 	  && (p1 = c_getstr (arg1))
1479 	  && host_size_t_cst_p (arg2, &s2)
1480 	  && s2 <= strlen (p0)
1481 	  && s2 <= strlen (p1))
1482 	return build_cmp_result (type, memcmp (p0, p1, s2));
1483       return NULL_TREE;
1484 
1485     default:
1486       return fold_const_call_1 (fn, type, arg0, arg1, arg2);
1487     }
1488 }
1489 
1490 /* Fold a fma operation with arguments ARG[012].  */
1491 
1492 tree
fold_fma(location_t,tree type,tree arg0,tree arg1,tree arg2)1493 fold_fma (location_t, tree type, tree arg0, tree arg1, tree arg2)
1494 {
1495   REAL_VALUE_TYPE result;
1496   if (real_cst_p (arg0)
1497       && real_cst_p (arg1)
1498       && real_cst_p (arg2)
1499       && do_mpfr_arg3 (&result, mpfr_fma, TREE_REAL_CST_PTR (arg0),
1500 		       TREE_REAL_CST_PTR (arg1), TREE_REAL_CST_PTR (arg2),
1501 		       REAL_MODE_FORMAT (TYPE_MODE (type))))
1502     return build_real (type, result);
1503 
1504   return NULL_TREE;
1505 }
1506