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