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