111
|
1 /* Constant folding for calls to built-in and internal functions.
|
|
2 Copyright (C) 1988-2017 Free Software Foundation, Inc.
|
|
3
|
|
4 This file is part of GCC.
|
|
5
|
|
6 GCC is free software; you can redistribute it and/or modify it under
|
|
7 the terms of the GNU General Public License as published by the Free
|
|
8 Software Foundation; either version 3, or (at your option) any later
|
|
9 version.
|
|
10
|
|
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with GCC; see the file COPYING3. If not see
|
|
18 <http://www.gnu.org/licenses/>. */
|
|
19
|
|
20 #include "config.h"
|
|
21 #include "system.h"
|
|
22 #include "coretypes.h"
|
|
23 #include "realmpfr.h"
|
|
24 #include "tree.h"
|
|
25 #include "stor-layout.h"
|
|
26 #include "options.h"
|
|
27 #include "fold-const.h"
|
|
28 #include "fold-const-call.h"
|
|
29 #include "case-cfn-macros.h"
|
|
30 #include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */
|
|
31 #include "builtins.h"
|
|
32 #include "gimple-expr.h"
|
|
33
|
|
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
|
|
532 *RESULT = ldexp (*ARG0, ARG1)
|
|
533
|
|
534 in format FORMAT. Return true on success. */
|
|
535
|
|
536 static bool
|
|
537 fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
|
|
538 const wide_int_ref &arg1,
|
|
539 const real_format *format)
|
|
540 {
|
|
541 /* Bound the maximum adjustment to twice the range of the
|
|
542 mode's valid exponents. Use abs to ensure the range is
|
|
543 positive as a sanity check. */
|
|
544 int max_exp_adj = 2 * labs (format->emax - format->emin);
|
|
545
|
|
546 /* The requested adjustment must be inside this range. This
|
|
547 is a preliminary cap to avoid things like overflow, we
|
|
548 may still fail to compute the result for other reasons. */
|
|
549 if (wi::les_p (arg1, -max_exp_adj) || wi::ges_p (arg1, max_exp_adj))
|
|
550 return false;
|
|
551
|
|
552 /* Don't perform operation if we honor signaling NaNs and
|
|
553 operand is a signaling NaN. */
|
|
554 if (!flag_unsafe_math_optimizations
|
|
555 && flag_signaling_nans
|
|
556 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
|
|
557 return false;
|
|
558
|
|
559 REAL_VALUE_TYPE initial_result;
|
|
560 real_ldexp (&initial_result, arg0, arg1.to_shwi ());
|
|
561
|
|
562 /* Ensure we didn't overflow. */
|
|
563 if (real_isinf (&initial_result))
|
|
564 return false;
|
|
565
|
|
566 /* Only proceed if the target mode can hold the
|
|
567 resulting value. */
|
|
568 *result = real_value_truncate (format, initial_result);
|
|
569 return real_equal (&initial_result, result);
|
|
570 }
|
|
571
|
|
572 /* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
|
|
573 return type TYPE. QUIET is true if a quiet rather than signalling
|
|
574 NaN is required. */
|
|
575
|
|
576 static tree
|
|
577 fold_const_builtin_nan (tree type, tree arg, bool quiet)
|
|
578 {
|
|
579 REAL_VALUE_TYPE real;
|
|
580 const char *str = c_getstr (arg);
|
|
581 if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
|
|
582 return build_real (type, real);
|
|
583 return NULL_TREE;
|
|
584 }
|
|
585
|
|
586 /* Try to evaluate:
|
|
587
|
|
588 *RESULT = FN (*ARG)
|
|
589
|
|
590 in format FORMAT. Return true on success. */
|
|
591
|
|
592 static bool
|
|
593 fold_const_call_ss (real_value *result, combined_fn fn,
|
|
594 const real_value *arg, const real_format *format)
|
|
595 {
|
|
596 switch (fn)
|
|
597 {
|
|
598 CASE_CFN_SQRT:
|
|
599 return (real_compare (GE_EXPR, arg, &dconst0)
|
|
600 && do_mpfr_arg1 (result, mpfr_sqrt, arg, format));
|
|
601
|
|
602 CASE_CFN_CBRT:
|
|
603 return do_mpfr_arg1 (result, mpfr_cbrt, arg, format);
|
|
604
|
|
605 CASE_CFN_ASIN:
|
|
606 return (real_compare (GE_EXPR, arg, &dconstm1)
|
|
607 && real_compare (LE_EXPR, arg, &dconst1)
|
|
608 && do_mpfr_arg1 (result, mpfr_asin, arg, format));
|
|
609
|
|
610 CASE_CFN_ACOS:
|
|
611 return (real_compare (GE_EXPR, arg, &dconstm1)
|
|
612 && real_compare (LE_EXPR, arg, &dconst1)
|
|
613 && do_mpfr_arg1 (result, mpfr_acos, arg, format));
|
|
614
|
|
615 CASE_CFN_ATAN:
|
|
616 return do_mpfr_arg1 (result, mpfr_atan, arg, format);
|
|
617
|
|
618 CASE_CFN_ASINH:
|
|
619 return do_mpfr_arg1 (result, mpfr_asinh, arg, format);
|
|
620
|
|
621 CASE_CFN_ACOSH:
|
|
622 return (real_compare (GE_EXPR, arg, &dconst1)
|
|
623 && do_mpfr_arg1 (result, mpfr_acosh, arg, format));
|
|
624
|
|
625 CASE_CFN_ATANH:
|
|
626 return (real_compare (GE_EXPR, arg, &dconstm1)
|
|
627 && real_compare (LE_EXPR, arg, &dconst1)
|
|
628 && do_mpfr_arg1 (result, mpfr_atanh, arg, format));
|
|
629
|
|
630 CASE_CFN_SIN:
|
|
631 return do_mpfr_arg1 (result, mpfr_sin, arg, format);
|
|
632
|
|
633 CASE_CFN_COS:
|
|
634 return do_mpfr_arg1 (result, mpfr_cos, arg, format);
|
|
635
|
|
636 CASE_CFN_TAN:
|
|
637 return do_mpfr_arg1 (result, mpfr_tan, arg, format);
|
|
638
|
|
639 CASE_CFN_SINH:
|
|
640 return do_mpfr_arg1 (result, mpfr_sinh, arg, format);
|
|
641
|
|
642 CASE_CFN_COSH:
|
|
643 return do_mpfr_arg1 (result, mpfr_cosh, arg, format);
|
|
644
|
|
645 CASE_CFN_TANH:
|
|
646 return do_mpfr_arg1 (result, mpfr_tanh, arg, format);
|
|
647
|
|
648 CASE_CFN_ERF:
|
|
649 return do_mpfr_arg1 (result, mpfr_erf, arg, format);
|
|
650
|
|
651 CASE_CFN_ERFC:
|
|
652 return do_mpfr_arg1 (result, mpfr_erfc, arg, format);
|
|
653
|
|
654 CASE_CFN_TGAMMA:
|
|
655 return do_mpfr_arg1 (result, mpfr_gamma, arg, format);
|
|
656
|
|
657 CASE_CFN_EXP:
|
|
658 return do_mpfr_arg1 (result, mpfr_exp, arg, format);
|
|
659
|
|
660 CASE_CFN_EXP2:
|
|
661 return do_mpfr_arg1 (result, mpfr_exp2, arg, format);
|
|
662
|
|
663 CASE_CFN_EXP10:
|
|
664 CASE_CFN_POW10:
|
|
665 return do_mpfr_arg1 (result, mpfr_exp10, arg, format);
|
|
666
|
|
667 CASE_CFN_EXPM1:
|
|
668 return do_mpfr_arg1 (result, mpfr_expm1, arg, format);
|
|
669
|
|
670 CASE_CFN_LOG:
|
|
671 return (real_compare (GT_EXPR, arg, &dconst0)
|
|
672 && do_mpfr_arg1 (result, mpfr_log, arg, format));
|
|
673
|
|
674 CASE_CFN_LOG2:
|
|
675 return (real_compare (GT_EXPR, arg, &dconst0)
|
|
676 && do_mpfr_arg1 (result, mpfr_log2, arg, format));
|
|
677
|
|
678 CASE_CFN_LOG10:
|
|
679 return (real_compare (GT_EXPR, arg, &dconst0)
|
|
680 && do_mpfr_arg1 (result, mpfr_log10, arg, format));
|
|
681
|
|
682 CASE_CFN_LOG1P:
|
|
683 return (real_compare (GT_EXPR, arg, &dconstm1)
|
|
684 && do_mpfr_arg1 (result, mpfr_log1p, arg, format));
|
|
685
|
|
686 CASE_CFN_J0:
|
|
687 return do_mpfr_arg1 (result, mpfr_j0, arg, format);
|
|
688
|
|
689 CASE_CFN_J1:
|
|
690 return do_mpfr_arg1 (result, mpfr_j1, arg, format);
|
|
691
|
|
692 CASE_CFN_Y0:
|
|
693 return (real_compare (GT_EXPR, arg, &dconst0)
|
|
694 && do_mpfr_arg1 (result, mpfr_y0, arg, format));
|
|
695
|
|
696 CASE_CFN_Y1:
|
|
697 return (real_compare (GT_EXPR, arg, &dconst0)
|
|
698 && do_mpfr_arg1 (result, mpfr_y1, arg, format));
|
|
699
|
|
700 CASE_CFN_FLOOR:
|
|
701 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
|
|
702 {
|
|
703 real_floor (result, format, arg);
|
|
704 return true;
|
|
705 }
|
|
706 return false;
|
|
707
|
|
708 CASE_CFN_CEIL:
|
|
709 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
|
|
710 {
|
|
711 real_ceil (result, format, arg);
|
|
712 return true;
|
|
713 }
|
|
714 return false;
|
|
715
|
|
716 CASE_CFN_TRUNC:
|
|
717 real_trunc (result, format, arg);
|
|
718 return true;
|
|
719
|
|
720 CASE_CFN_ROUND:
|
|
721 if (!REAL_VALUE_ISNAN (*arg) || !flag_errno_math)
|
|
722 {
|
|
723 real_round (result, format, arg);
|
|
724 return true;
|
|
725 }
|
|
726 return false;
|
|
727
|
|
728 CASE_CFN_LOGB:
|
|
729 return fold_const_logb (result, arg, format);
|
|
730
|
|
731 CASE_CFN_SIGNIFICAND:
|
|
732 return fold_const_significand (result, arg, format);
|
|
733
|
|
734 default:
|
|
735 return false;
|
|
736 }
|
|
737 }
|
|
738
|
|
739 /* Try to evaluate:
|
|
740
|
|
741 *RESULT = FN (*ARG)
|
|
742
|
|
743 where FORMAT is the format of ARG and PRECISION is the number of
|
|
744 significant bits in the result. Return true on success. */
|
|
745
|
|
746 static bool
|
|
747 fold_const_call_ss (wide_int *result, combined_fn fn,
|
|
748 const real_value *arg, unsigned int precision,
|
|
749 const real_format *format)
|
|
750 {
|
|
751 switch (fn)
|
|
752 {
|
|
753 CASE_CFN_SIGNBIT:
|
|
754 if (real_isneg (arg))
|
|
755 *result = wi::one (precision);
|
|
756 else
|
|
757 *result = wi::zero (precision);
|
|
758 return true;
|
|
759
|
|
760 CASE_CFN_ILOGB:
|
|
761 /* For ilogb we don't know FP_ILOGB0, so only handle normal values.
|
|
762 Proceed iff radix == 2. In GCC, normalized significands are in
|
|
763 the range [0.5, 1.0). We want the exponent as if they were
|
|
764 [1.0, 2.0) so get the exponent and subtract 1. */
|
|
765 if (arg->cl == rvc_normal && format->b == 2)
|
|
766 {
|
|
767 *result = wi::shwi (REAL_EXP (arg) - 1, precision);
|
|
768 return true;
|
|
769 }
|
|
770 return false;
|
|
771
|
|
772 CASE_CFN_ICEIL:
|
|
773 CASE_CFN_LCEIL:
|
|
774 CASE_CFN_LLCEIL:
|
|
775 return fold_const_conversion (result, real_ceil, arg,
|
|
776 precision, format);
|
|
777
|
|
778 CASE_CFN_LFLOOR:
|
|
779 CASE_CFN_IFLOOR:
|
|
780 CASE_CFN_LLFLOOR:
|
|
781 return fold_const_conversion (result, real_floor, arg,
|
|
782 precision, format);
|
|
783
|
|
784 CASE_CFN_IROUND:
|
|
785 CASE_CFN_LROUND:
|
|
786 CASE_CFN_LLROUND:
|
|
787 return fold_const_conversion (result, real_round, arg,
|
|
788 precision, format);
|
|
789
|
|
790 CASE_CFN_IRINT:
|
|
791 CASE_CFN_LRINT:
|
|
792 CASE_CFN_LLRINT:
|
|
793 /* Not yet folded to a constant. */
|
|
794 return false;
|
|
795
|
|
796 CASE_CFN_FINITE:
|
|
797 case CFN_BUILT_IN_FINITED32:
|
|
798 case CFN_BUILT_IN_FINITED64:
|
|
799 case CFN_BUILT_IN_FINITED128:
|
|
800 case CFN_BUILT_IN_ISFINITE:
|
|
801 *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
|
|
802 return true;
|
|
803
|
|
804 CASE_CFN_ISINF:
|
|
805 case CFN_BUILT_IN_ISINFD32:
|
|
806 case CFN_BUILT_IN_ISINFD64:
|
|
807 case CFN_BUILT_IN_ISINFD128:
|
|
808 if (real_isinf (arg))
|
|
809 *result = wi::shwi (arg->sign ? -1 : 1, precision);
|
|
810 else
|
|
811 *result = wi::shwi (0, precision);
|
|
812 return true;
|
|
813
|
|
814 CASE_CFN_ISNAN:
|
|
815 case CFN_BUILT_IN_ISNAND32:
|
|
816 case CFN_BUILT_IN_ISNAND64:
|
|
817 case CFN_BUILT_IN_ISNAND128:
|
|
818 *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
|
|
819 return true;
|
|
820
|
|
821 default:
|
|
822 return false;
|
|
823 }
|
|
824 }
|
|
825
|
|
826 /* Try to evaluate:
|
|
827
|
|
828 *RESULT = FN (ARG)
|
|
829
|
|
830 where ARG_TYPE is the type of ARG and PRECISION is the number of bits
|
|
831 in the result. Return true on success. */
|
|
832
|
|
833 static bool
|
|
834 fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
|
|
835 unsigned int precision, tree arg_type)
|
|
836 {
|
|
837 switch (fn)
|
|
838 {
|
|
839 CASE_CFN_FFS:
|
|
840 *result = wi::shwi (wi::ffs (arg), precision);
|
|
841 return true;
|
|
842
|
|
843 CASE_CFN_CLZ:
|
|
844 {
|
|
845 int tmp;
|
|
846 if (wi::ne_p (arg, 0))
|
|
847 tmp = wi::clz (arg);
|
|
848 else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
|
|
849 tmp))
|
|
850 tmp = TYPE_PRECISION (arg_type);
|
|
851 *result = wi::shwi (tmp, precision);
|
|
852 return true;
|
|
853 }
|
|
854
|
|
855 CASE_CFN_CTZ:
|
|
856 {
|
|
857 int tmp;
|
|
858 if (wi::ne_p (arg, 0))
|
|
859 tmp = wi::ctz (arg);
|
|
860 else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
|
|
861 tmp))
|
|
862 tmp = TYPE_PRECISION (arg_type);
|
|
863 *result = wi::shwi (tmp, precision);
|
|
864 return true;
|
|
865 }
|
|
866
|
|
867 CASE_CFN_CLRSB:
|
|
868 *result = wi::shwi (wi::clrsb (arg), precision);
|
|
869 return true;
|
|
870
|
|
871 CASE_CFN_POPCOUNT:
|
|
872 *result = wi::shwi (wi::popcount (arg), precision);
|
|
873 return true;
|
|
874
|
|
875 CASE_CFN_PARITY:
|
|
876 *result = wi::shwi (wi::parity (arg), precision);
|
|
877 return true;
|
|
878
|
|
879 case CFN_BUILT_IN_BSWAP16:
|
|
880 case CFN_BUILT_IN_BSWAP32:
|
|
881 case CFN_BUILT_IN_BSWAP64:
|
|
882 *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
|
|
883 return true;
|
|
884
|
|
885 default:
|
|
886 return false;
|
|
887 }
|
|
888 }
|
|
889
|
|
890 /* Try to evaluate:
|
|
891
|
|
892 RESULT = FN (*ARG)
|
|
893
|
|
894 where FORMAT is the format of ARG and of the real and imaginary parts
|
|
895 of RESULT, passed as RESULT_REAL and RESULT_IMAG respectively. Return
|
|
896 true on success. */
|
|
897
|
|
898 static bool
|
|
899 fold_const_call_cs (real_value *result_real, real_value *result_imag,
|
|
900 combined_fn fn, const real_value *arg,
|
|
901 const real_format *format)
|
|
902 {
|
|
903 switch (fn)
|
|
904 {
|
|
905 CASE_CFN_CEXPI:
|
|
906 /* cexpi(x+yi) = cos(x)+sin(y)*i. */
|
|
907 return do_mpfr_sincos (result_imag, result_real, arg, format);
|
|
908
|
|
909 default:
|
|
910 return false;
|
|
911 }
|
|
912 }
|
|
913
|
|
914 /* Try to evaluate:
|
|
915
|
|
916 *RESULT = fn (ARG)
|
|
917
|
|
918 where FORMAT is the format of RESULT and of the real and imaginary parts
|
|
919 of ARG, passed as ARG_REAL and ARG_IMAG respectively. Return true on
|
|
920 success. */
|
|
921
|
|
922 static bool
|
|
923 fold_const_call_sc (real_value *result, combined_fn fn,
|
|
924 const real_value *arg_real, const real_value *arg_imag,
|
|
925 const real_format *format)
|
|
926 {
|
|
927 switch (fn)
|
|
928 {
|
|
929 CASE_CFN_CABS:
|
|
930 return do_mpfr_arg2 (result, mpfr_hypot, arg_real, arg_imag, format);
|
|
931
|
|
932 default:
|
|
933 return false;
|
|
934 }
|
|
935 }
|
|
936
|
|
937 /* Try to evaluate:
|
|
938
|
|
939 RESULT = fn (ARG)
|
|
940
|
|
941 where FORMAT is the format of the real and imaginary parts of RESULT
|
|
942 (RESULT_REAL and RESULT_IMAG) and of ARG (ARG_REAL and ARG_IMAG).
|
|
943 Return true on success. */
|
|
944
|
|
945 static bool
|
|
946 fold_const_call_cc (real_value *result_real, real_value *result_imag,
|
|
947 combined_fn fn, const real_value *arg_real,
|
|
948 const real_value *arg_imag, const real_format *format)
|
|
949 {
|
|
950 switch (fn)
|
|
951 {
|
|
952 CASE_CFN_CCOS:
|
|
953 return do_mpc_arg1 (result_real, result_imag, mpc_cos,
|
|
954 arg_real, arg_imag, format);
|
|
955
|
|
956 CASE_CFN_CCOSH:
|
|
957 return do_mpc_arg1 (result_real, result_imag, mpc_cosh,
|
|
958 arg_real, arg_imag, format);
|
|
959
|
|
960 CASE_CFN_CPROJ:
|
|
961 if (real_isinf (arg_real) || real_isinf (arg_imag))
|
|
962 {
|
|
963 real_inf (result_real);
|
|
964 *result_imag = dconst0;
|
|
965 result_imag->sign = arg_imag->sign;
|
|
966 }
|
|
967 else
|
|
968 {
|
|
969 *result_real = *arg_real;
|
|
970 *result_imag = *arg_imag;
|
|
971 }
|
|
972 return true;
|
|
973
|
|
974 CASE_CFN_CSIN:
|
|
975 return do_mpc_arg1 (result_real, result_imag, mpc_sin,
|
|
976 arg_real, arg_imag, format);
|
|
977
|
|
978 CASE_CFN_CSINH:
|
|
979 return do_mpc_arg1 (result_real, result_imag, mpc_sinh,
|
|
980 arg_real, arg_imag, format);
|
|
981
|
|
982 CASE_CFN_CTAN:
|
|
983 return do_mpc_arg1 (result_real, result_imag, mpc_tan,
|
|
984 arg_real, arg_imag, format);
|
|
985
|
|
986 CASE_CFN_CTANH:
|
|
987 return do_mpc_arg1 (result_real, result_imag, mpc_tanh,
|
|
988 arg_real, arg_imag, format);
|
|
989
|
|
990 CASE_CFN_CLOG:
|
|
991 return do_mpc_arg1 (result_real, result_imag, mpc_log,
|
|
992 arg_real, arg_imag, format);
|
|
993
|
|
994 CASE_CFN_CSQRT:
|
|
995 return do_mpc_arg1 (result_real, result_imag, mpc_sqrt,
|
|
996 arg_real, arg_imag, format);
|
|
997
|
|
998 CASE_CFN_CASIN:
|
|
999 return do_mpc_arg1 (result_real, result_imag, mpc_asin,
|
|
1000 arg_real, arg_imag, format);
|
|
1001
|
|
1002 CASE_CFN_CACOS:
|
|
1003 return do_mpc_arg1 (result_real, result_imag, mpc_acos,
|
|
1004 arg_real, arg_imag, format);
|
|
1005
|
|
1006 CASE_CFN_CATAN:
|
|
1007 return do_mpc_arg1 (result_real, result_imag, mpc_atan,
|
|
1008 arg_real, arg_imag, format);
|
|
1009
|
|
1010 CASE_CFN_CASINH:
|
|
1011 return do_mpc_arg1 (result_real, result_imag, mpc_asinh,
|
|
1012 arg_real, arg_imag, format);
|
|
1013
|
|
1014 CASE_CFN_CACOSH:
|
|
1015 return do_mpc_arg1 (result_real, result_imag, mpc_acosh,
|
|
1016 arg_real, arg_imag, format);
|
|
1017
|
|
1018 CASE_CFN_CATANH:
|
|
1019 return do_mpc_arg1 (result_real, result_imag, mpc_atanh,
|
|
1020 arg_real, arg_imag, format);
|
|
1021
|
|
1022 CASE_CFN_CEXP:
|
|
1023 return do_mpc_arg1 (result_real, result_imag, mpc_exp,
|
|
1024 arg_real, arg_imag, format);
|
|
1025
|
|
1026 default:
|
|
1027 return false;
|
|
1028 }
|
|
1029 }
|
|
1030
|
|
1031 /* Subroutine of fold_const_call, with the same interface. Handle cases
|
|
1032 where the arguments and result are numerical. */
|
|
1033
|
|
1034 static tree
|
|
1035 fold_const_call_1 (combined_fn fn, tree type, tree arg)
|
|
1036 {
|
|
1037 machine_mode mode = TYPE_MODE (type);
|
|
1038 machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
|
|
1039
|
|
1040 if (integer_cst_p (arg))
|
|
1041 {
|
|
1042 if (SCALAR_INT_MODE_P (mode))
|
|
1043 {
|
|
1044 wide_int result;
|
|
1045 if (fold_const_call_ss (&result, fn, wi::to_wide (arg),
|
|
1046 TYPE_PRECISION (type), TREE_TYPE (arg)))
|
|
1047 return wide_int_to_tree (type, result);
|
|
1048 }
|
|
1049 return NULL_TREE;
|
|
1050 }
|
|
1051
|
|
1052 if (real_cst_p (arg))
|
|
1053 {
|
|
1054 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
|
|
1055 if (mode == arg_mode)
|
|
1056 {
|
|
1057 /* real -> real. */
|
|
1058 REAL_VALUE_TYPE result;
|
|
1059 if (fold_const_call_ss (&result, fn, TREE_REAL_CST_PTR (arg),
|
|
1060 REAL_MODE_FORMAT (mode)))
|
|
1061 return build_real (type, result);
|
|
1062 }
|
|
1063 else if (COMPLEX_MODE_P (mode)
|
|
1064 && GET_MODE_INNER (mode) == arg_mode)
|
|
1065 {
|
|
1066 /* real -> complex real. */
|
|
1067 REAL_VALUE_TYPE result_real, result_imag;
|
|
1068 if (fold_const_call_cs (&result_real, &result_imag, fn,
|
|
1069 TREE_REAL_CST_PTR (arg),
|
|
1070 REAL_MODE_FORMAT (arg_mode)))
|
|
1071 return build_complex (type,
|
|
1072 build_real (TREE_TYPE (type), result_real),
|
|
1073 build_real (TREE_TYPE (type), result_imag));
|
|
1074 }
|
|
1075 else if (INTEGRAL_TYPE_P (type))
|
|
1076 {
|
|
1077 /* real -> int. */
|
|
1078 wide_int result;
|
|
1079 if (fold_const_call_ss (&result, fn,
|
|
1080 TREE_REAL_CST_PTR (arg),
|
|
1081 TYPE_PRECISION (type),
|
|
1082 REAL_MODE_FORMAT (arg_mode)))
|
|
1083 return wide_int_to_tree (type, result);
|
|
1084 }
|
|
1085 return NULL_TREE;
|
|
1086 }
|
|
1087
|
|
1088 if (complex_cst_p (arg))
|
|
1089 {
|
|
1090 gcc_checking_assert (COMPLEX_MODE_P (arg_mode));
|
|
1091 machine_mode inner_mode = GET_MODE_INNER (arg_mode);
|
|
1092 tree argr = TREE_REALPART (arg);
|
|
1093 tree argi = TREE_IMAGPART (arg);
|
|
1094 if (mode == arg_mode
|
|
1095 && real_cst_p (argr)
|
|
1096 && real_cst_p (argi))
|
|
1097 {
|
|
1098 /* complex real -> complex real. */
|
|
1099 REAL_VALUE_TYPE result_real, result_imag;
|
|
1100 if (fold_const_call_cc (&result_real, &result_imag, fn,
|
|
1101 TREE_REAL_CST_PTR (argr),
|
|
1102 TREE_REAL_CST_PTR (argi),
|
|
1103 REAL_MODE_FORMAT (inner_mode)))
|
|
1104 return build_complex (type,
|
|
1105 build_real (TREE_TYPE (type), result_real),
|
|
1106 build_real (TREE_TYPE (type), result_imag));
|
|
1107 }
|
|
1108 if (mode == inner_mode
|
|
1109 && real_cst_p (argr)
|
|
1110 && real_cst_p (argi))
|
|
1111 {
|
|
1112 /* complex real -> real. */
|
|
1113 REAL_VALUE_TYPE result;
|
|
1114 if (fold_const_call_sc (&result, fn,
|
|
1115 TREE_REAL_CST_PTR (argr),
|
|
1116 TREE_REAL_CST_PTR (argi),
|
|
1117 REAL_MODE_FORMAT (inner_mode)))
|
|
1118 return build_real (type, result);
|
|
1119 }
|
|
1120 return NULL_TREE;
|
|
1121 }
|
|
1122
|
|
1123 return NULL_TREE;
|
|
1124 }
|
|
1125
|
|
1126 /* Try to fold FN (ARG) to a constant. Return the constant on success,
|
|
1127 otherwise return null. TYPE is the type of the return value. */
|
|
1128
|
|
1129 tree
|
|
1130 fold_const_call (combined_fn fn, tree type, tree arg)
|
|
1131 {
|
|
1132 switch (fn)
|
|
1133 {
|
|
1134 case CFN_BUILT_IN_STRLEN:
|
|
1135 if (const char *str = c_getstr (arg))
|
|
1136 return build_int_cst (type, strlen (str));
|
|
1137 return NULL_TREE;
|
|
1138
|
|
1139 CASE_CFN_NAN:
|
|
1140 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
|
|
1141 case CFN_BUILT_IN_NAND32:
|
|
1142 case CFN_BUILT_IN_NAND64:
|
|
1143 case CFN_BUILT_IN_NAND128:
|
|
1144 return fold_const_builtin_nan (type, arg, true);
|
|
1145
|
|
1146 CASE_CFN_NANS:
|
|
1147 CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
|
|
1148 return fold_const_builtin_nan (type, arg, false);
|
|
1149
|
|
1150 default:
|
|
1151 return fold_const_call_1 (fn, type, arg);
|
|
1152 }
|
|
1153 }
|
|
1154
|
|
1155 /* Try to evaluate:
|
|
1156
|
|
1157 *RESULT = FN (*ARG0, *ARG1)
|
|
1158
|
|
1159 in format FORMAT. Return true on success. */
|
|
1160
|
|
1161 static bool
|
|
1162 fold_const_call_sss (real_value *result, combined_fn fn,
|
|
1163 const real_value *arg0, const real_value *arg1,
|
|
1164 const real_format *format)
|
|
1165 {
|
|
1166 switch (fn)
|
|
1167 {
|
|
1168 CASE_CFN_DREM:
|
|
1169 CASE_CFN_REMAINDER:
|
|
1170 return do_mpfr_arg2 (result, mpfr_remainder, arg0, arg1, format);
|
|
1171
|
|
1172 CASE_CFN_ATAN2:
|
|
1173 return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format);
|
|
1174
|
|
1175 CASE_CFN_FDIM:
|
|
1176 return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format);
|
|
1177
|
|
1178 CASE_CFN_HYPOT:
|
|
1179 return do_mpfr_arg2 (result, mpfr_hypot, arg0, arg1, format);
|
|
1180
|
|
1181 CASE_CFN_COPYSIGN:
|
|
1182 *result = *arg0;
|
|
1183 real_copysign (result, arg1);
|
|
1184 return true;
|
|
1185
|
|
1186 CASE_CFN_FMIN:
|
|
1187 return do_mpfr_arg2 (result, mpfr_min, arg0, arg1, format);
|
|
1188
|
|
1189 CASE_CFN_FMAX:
|
|
1190 return do_mpfr_arg2 (result, mpfr_max, arg0, arg1, format);
|
|
1191
|
|
1192 CASE_CFN_POW:
|
|
1193 return fold_const_pow (result, arg0, arg1, format);
|
|
1194
|
|
1195 default:
|
|
1196 return false;
|
|
1197 }
|
|
1198 }
|
|
1199
|
|
1200 /* Try to evaluate:
|
|
1201
|
|
1202 *RESULT = FN (*ARG0, ARG1)
|
|
1203
|
|
1204 where FORMAT is the format of *RESULT and *ARG0. Return true on
|
|
1205 success. */
|
|
1206
|
|
1207 static bool
|
|
1208 fold_const_call_sss (real_value *result, combined_fn fn,
|
|
1209 const real_value *arg0, const wide_int_ref &arg1,
|
|
1210 const real_format *format)
|
|
1211 {
|
|
1212 switch (fn)
|
|
1213 {
|
|
1214 CASE_CFN_LDEXP:
|
|
1215 return fold_const_builtin_load_exponent (result, arg0, arg1, format);
|
|
1216
|
|
1217 CASE_CFN_SCALBN:
|
|
1218 CASE_CFN_SCALBLN:
|
|
1219 return (format->b == 2
|
|
1220 && fold_const_builtin_load_exponent (result, arg0, arg1,
|
|
1221 format));
|
|
1222
|
|
1223 CASE_CFN_POWI:
|
|
1224 /* Avoid the folding if flag_signaling_nans is on and
|
|
1225 operand is a signaling NaN. */
|
|
1226 if (!flag_unsafe_math_optimizations
|
|
1227 && flag_signaling_nans
|
|
1228 && REAL_VALUE_ISSIGNALING_NAN (*arg0))
|
|
1229 return false;
|
|
1230
|
|
1231 real_powi (result, format, arg0, arg1.to_shwi ());
|
|
1232 return true;
|
|
1233
|
|
1234 default:
|
|
1235 return false;
|
|
1236 }
|
|
1237 }
|
|
1238
|
|
1239 /* Try to evaluate:
|
|
1240
|
|
1241 *RESULT = FN (ARG0, *ARG1)
|
|
1242
|
|
1243 where FORMAT is the format of *RESULT and *ARG1. Return true on
|
|
1244 success. */
|
|
1245
|
|
1246 static bool
|
|
1247 fold_const_call_sss (real_value *result, combined_fn fn,
|
|
1248 const wide_int_ref &arg0, const real_value *arg1,
|
|
1249 const real_format *format)
|
|
1250 {
|
|
1251 switch (fn)
|
|
1252 {
|
|
1253 CASE_CFN_JN:
|
|
1254 return do_mpfr_arg2 (result, mpfr_jn, arg0, arg1, format);
|
|
1255
|
|
1256 CASE_CFN_YN:
|
|
1257 return (real_compare (GT_EXPR, arg1, &dconst0)
|
|
1258 && do_mpfr_arg2 (result, mpfr_yn, arg0, arg1, format));
|
|
1259
|
|
1260 default:
|
|
1261 return false;
|
|
1262 }
|
|
1263 }
|
|
1264
|
|
1265 /* Try to evaluate:
|
|
1266
|
|
1267 RESULT = fn (ARG0, ARG1)
|
|
1268
|
|
1269 where FORMAT is the format of the real and imaginary parts of RESULT
|
|
1270 (RESULT_REAL and RESULT_IMAG), of ARG0 (ARG0_REAL and ARG0_IMAG)
|
|
1271 and of ARG1 (ARG1_REAL and ARG1_IMAG). Return true on success. */
|
|
1272
|
|
1273 static bool
|
|
1274 fold_const_call_ccc (real_value *result_real, real_value *result_imag,
|
|
1275 combined_fn fn, const real_value *arg0_real,
|
|
1276 const real_value *arg0_imag, const real_value *arg1_real,
|
|
1277 const real_value *arg1_imag, const real_format *format)
|
|
1278 {
|
|
1279 switch (fn)
|
|
1280 {
|
|
1281 CASE_CFN_CPOW:
|
|
1282 return do_mpc_arg2 (result_real, result_imag, mpc_pow,
|
|
1283 arg0_real, arg0_imag, arg1_real, arg1_imag, format);
|
|
1284
|
|
1285 default:
|
|
1286 return false;
|
|
1287 }
|
|
1288 }
|
|
1289
|
|
1290 /* Subroutine of fold_const_call, with the same interface. Handle cases
|
|
1291 where the arguments and result are numerical. */
|
|
1292
|
|
1293 static tree
|
|
1294 fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1)
|
|
1295 {
|
|
1296 machine_mode mode = TYPE_MODE (type);
|
|
1297 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
|
|
1298 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
|
|
1299
|
|
1300 if (arg0_mode == arg1_mode
|
|
1301 && real_cst_p (arg0)
|
|
1302 && real_cst_p (arg1))
|
|
1303 {
|
|
1304 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
|
|
1305 if (mode == arg0_mode)
|
|
1306 {
|
|
1307 /* real, real -> real. */
|
|
1308 REAL_VALUE_TYPE result;
|
|
1309 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
|
|
1310 TREE_REAL_CST_PTR (arg1),
|
|
1311 REAL_MODE_FORMAT (mode)))
|
|
1312 return build_real (type, result);
|
|
1313 }
|
|
1314 return NULL_TREE;
|
|
1315 }
|
|
1316
|
|
1317 if (real_cst_p (arg0)
|
|
1318 && integer_cst_p (arg1))
|
|
1319 {
|
|
1320 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
|
|
1321 if (mode == arg0_mode)
|
|
1322 {
|
|
1323 /* real, int -> real. */
|
|
1324 REAL_VALUE_TYPE result;
|
|
1325 if (fold_const_call_sss (&result, fn, TREE_REAL_CST_PTR (arg0),
|
|
1326 wi::to_wide (arg1),
|
|
1327 REAL_MODE_FORMAT (mode)))
|
|
1328 return build_real (type, result);
|
|
1329 }
|
|
1330 return NULL_TREE;
|
|
1331 }
|
|
1332
|
|
1333 if (integer_cst_p (arg0)
|
|
1334 && real_cst_p (arg1))
|
|
1335 {
|
|
1336 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg1_mode));
|
|
1337 if (mode == arg1_mode)
|
|
1338 {
|
|
1339 /* int, real -> real. */
|
|
1340 REAL_VALUE_TYPE result;
|
|
1341 if (fold_const_call_sss (&result, fn, wi::to_wide (arg0),
|
|
1342 TREE_REAL_CST_PTR (arg1),
|
|
1343 REAL_MODE_FORMAT (mode)))
|
|
1344 return build_real (type, result);
|
|
1345 }
|
|
1346 return NULL_TREE;
|
|
1347 }
|
|
1348
|
|
1349 if (arg0_mode == arg1_mode
|
|
1350 && complex_cst_p (arg0)
|
|
1351 && complex_cst_p (arg1))
|
|
1352 {
|
|
1353 gcc_checking_assert (COMPLEX_MODE_P (arg0_mode));
|
|
1354 machine_mode inner_mode = GET_MODE_INNER (arg0_mode);
|
|
1355 tree arg0r = TREE_REALPART (arg0);
|
|
1356 tree arg0i = TREE_IMAGPART (arg0);
|
|
1357 tree arg1r = TREE_REALPART (arg1);
|
|
1358 tree arg1i = TREE_IMAGPART (arg1);
|
|
1359 if (mode == arg0_mode
|
|
1360 && real_cst_p (arg0r)
|
|
1361 && real_cst_p (arg0i)
|
|
1362 && real_cst_p (arg1r)
|
|
1363 && real_cst_p (arg1i))
|
|
1364 {
|
|
1365 /* complex real, complex real -> complex real. */
|
|
1366 REAL_VALUE_TYPE result_real, result_imag;
|
|
1367 if (fold_const_call_ccc (&result_real, &result_imag, fn,
|
|
1368 TREE_REAL_CST_PTR (arg0r),
|
|
1369 TREE_REAL_CST_PTR (arg0i),
|
|
1370 TREE_REAL_CST_PTR (arg1r),
|
|
1371 TREE_REAL_CST_PTR (arg1i),
|
|
1372 REAL_MODE_FORMAT (inner_mode)))
|
|
1373 return build_complex (type,
|
|
1374 build_real (TREE_TYPE (type), result_real),
|
|
1375 build_real (TREE_TYPE (type), result_imag));
|
|
1376 }
|
|
1377 return NULL_TREE;
|
|
1378 }
|
|
1379
|
|
1380 return NULL_TREE;
|
|
1381 }
|
|
1382
|
|
1383 /* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
|
|
1384 otherwise return null. TYPE is the type of the return value. */
|
|
1385
|
|
1386 tree
|
|
1387 fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1)
|
|
1388 {
|
|
1389 const char *p0, *p1;
|
|
1390 char c;
|
|
1391 switch (fn)
|
|
1392 {
|
|
1393 case CFN_BUILT_IN_STRSPN:
|
|
1394 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
|
|
1395 return build_int_cst (type, strspn (p0, p1));
|
|
1396 return NULL_TREE;
|
|
1397
|
|
1398 case CFN_BUILT_IN_STRCSPN:
|
|
1399 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
|
|
1400 return build_int_cst (type, strcspn (p0, p1));
|
|
1401 return NULL_TREE;
|
|
1402
|
|
1403 case CFN_BUILT_IN_STRCMP:
|
|
1404 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
|
|
1405 return build_cmp_result (type, strcmp (p0, p1));
|
|
1406 return NULL_TREE;
|
|
1407
|
|
1408 case CFN_BUILT_IN_STRCASECMP:
|
|
1409 if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
|
|
1410 {
|
|
1411 int r = strcmp (p0, p1);
|
|
1412 if (r == 0)
|
|
1413 return build_cmp_result (type, r);
|
|
1414 }
|
|
1415 return NULL_TREE;
|
|
1416
|
|
1417 case CFN_BUILT_IN_INDEX:
|
|
1418 case CFN_BUILT_IN_STRCHR:
|
|
1419 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
|
|
1420 {
|
|
1421 const char *r = strchr (p0, c);
|
|
1422 if (r == NULL)
|
|
1423 return build_int_cst (type, 0);
|
|
1424 return fold_convert (type,
|
|
1425 fold_build_pointer_plus_hwi (arg0, r - p0));
|
|
1426 }
|
|
1427 return NULL_TREE;
|
|
1428
|
|
1429 case CFN_BUILT_IN_RINDEX:
|
|
1430 case CFN_BUILT_IN_STRRCHR:
|
|
1431 if ((p0 = c_getstr (arg0)) && target_char_cst_p (arg1, &c))
|
|
1432 {
|
|
1433 const char *r = strrchr (p0, c);
|
|
1434 if (r == NULL)
|
|
1435 return build_int_cst (type, 0);
|
|
1436 return fold_convert (type,
|
|
1437 fold_build_pointer_plus_hwi (arg0, r - p0));
|
|
1438 }
|
|
1439 return NULL_TREE;
|
|
1440
|
|
1441 case CFN_BUILT_IN_STRSTR:
|
|
1442 if ((p1 = c_getstr (arg1)))
|
|
1443 {
|
|
1444 if ((p0 = c_getstr (arg0)))
|
|
1445 {
|
|
1446 const char *r = strstr (p0, p1);
|
|
1447 if (r == NULL)
|
|
1448 return build_int_cst (type, 0);
|
|
1449 return fold_convert (type,
|
|
1450 fold_build_pointer_plus_hwi (arg0, r - p0));
|
|
1451 }
|
|
1452 if (*p1 == '\0')
|
|
1453 return fold_convert (type, arg0);
|
|
1454 }
|
|
1455 return NULL_TREE;
|
|
1456
|
|
1457 default:
|
|
1458 return fold_const_call_1 (fn, type, arg0, arg1);
|
|
1459 }
|
|
1460 }
|
|
1461
|
|
1462 /* Try to evaluate:
|
|
1463
|
|
1464 *RESULT = FN (*ARG0, *ARG1, *ARG2)
|
|
1465
|
|
1466 in format FORMAT. Return true on success. */
|
|
1467
|
|
1468 static bool
|
|
1469 fold_const_call_ssss (real_value *result, combined_fn fn,
|
|
1470 const real_value *arg0, const real_value *arg1,
|
|
1471 const real_value *arg2, const real_format *format)
|
|
1472 {
|
|
1473 switch (fn)
|
|
1474 {
|
|
1475 CASE_CFN_FMA:
|
|
1476 return do_mpfr_arg3 (result, mpfr_fma, arg0, arg1, arg2, format);
|
|
1477
|
|
1478 default:
|
|
1479 return false;
|
|
1480 }
|
|
1481 }
|
|
1482
|
|
1483 /* Subroutine of fold_const_call, with the same interface. Handle cases
|
|
1484 where the arguments and result are numerical. */
|
|
1485
|
|
1486 static tree
|
|
1487 fold_const_call_1 (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
|
|
1488 {
|
|
1489 machine_mode mode = TYPE_MODE (type);
|
|
1490 machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
|
|
1491 machine_mode arg1_mode = TYPE_MODE (TREE_TYPE (arg1));
|
|
1492 machine_mode arg2_mode = TYPE_MODE (TREE_TYPE (arg2));
|
|
1493
|
|
1494 if (arg0_mode == arg1_mode
|
|
1495 && arg0_mode == arg2_mode
|
|
1496 && real_cst_p (arg0)
|
|
1497 && real_cst_p (arg1)
|
|
1498 && real_cst_p (arg2))
|
|
1499 {
|
|
1500 gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg0_mode));
|
|
1501 if (mode == arg0_mode)
|
|
1502 {
|
|
1503 /* real, real, real -> real. */
|
|
1504 REAL_VALUE_TYPE result;
|
|
1505 if (fold_const_call_ssss (&result, fn, TREE_REAL_CST_PTR (arg0),
|
|
1506 TREE_REAL_CST_PTR (arg1),
|
|
1507 TREE_REAL_CST_PTR (arg2),
|
|
1508 REAL_MODE_FORMAT (mode)))
|
|
1509 return build_real (type, result);
|
|
1510 }
|
|
1511 return NULL_TREE;
|
|
1512 }
|
|
1513
|
|
1514 return NULL_TREE;
|
|
1515 }
|
|
1516
|
|
1517 /* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
|
|
1518 success, otherwise return null. TYPE is the type of the return value. */
|
|
1519
|
|
1520 tree
|
|
1521 fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1, tree arg2)
|
|
1522 {
|
|
1523 const char *p0, *p1;
|
|
1524 char c;
|
|
1525 unsigned HOST_WIDE_INT s0, s1;
|
|
1526 size_t s2 = 0;
|
|
1527 switch (fn)
|
|
1528 {
|
|
1529 case CFN_BUILT_IN_STRNCMP:
|
|
1530 if (!host_size_t_cst_p (arg2, &s2))
|
|
1531 return NULL_TREE;
|
|
1532 if (s2 == 0
|
|
1533 && !TREE_SIDE_EFFECTS (arg0)
|
|
1534 && !TREE_SIDE_EFFECTS (arg1))
|
|
1535 return build_int_cst (type, 0);
|
|
1536 else if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
|
|
1537 return build_int_cst (type, strncmp (p0, p1, s2));
|
|
1538 return NULL_TREE;
|
|
1539
|
|
1540 case CFN_BUILT_IN_STRNCASECMP:
|
|
1541 if (!host_size_t_cst_p (arg2, &s2))
|
|
1542 return NULL_TREE;
|
|
1543 if (s2 == 0
|
|
1544 && !TREE_SIDE_EFFECTS (arg0)
|
|
1545 && !TREE_SIDE_EFFECTS (arg1))
|
|
1546 return build_int_cst (type, 0);
|
|
1547 else if ((p0 = c_getstr (arg0))
|
|
1548 && (p1 = c_getstr (arg1))
|
|
1549 && strncmp (p0, p1, s2) == 0)
|
|
1550 return build_int_cst (type, 0);
|
|
1551 return NULL_TREE;
|
|
1552
|
|
1553 case CFN_BUILT_IN_BCMP:
|
|
1554 case CFN_BUILT_IN_MEMCMP:
|
|
1555 if (!host_size_t_cst_p (arg2, &s2))
|
|
1556 return NULL_TREE;
|
|
1557 if (s2 == 0
|
|
1558 && !TREE_SIDE_EFFECTS (arg0)
|
|
1559 && !TREE_SIDE_EFFECTS (arg1))
|
|
1560 return build_int_cst (type, 0);
|
|
1561 if ((p0 = c_getstr (arg0, &s0))
|
|
1562 && (p1 = c_getstr (arg1, &s1))
|
|
1563 && s2 <= s0
|
|
1564 && s2 <= s1)
|
|
1565 return build_cmp_result (type, memcmp (p0, p1, s2));
|
|
1566 return NULL_TREE;
|
|
1567
|
|
1568 case CFN_BUILT_IN_MEMCHR:
|
|
1569 if (!host_size_t_cst_p (arg2, &s2))
|
|
1570 return NULL_TREE;
|
|
1571 if (s2 == 0
|
|
1572 && !TREE_SIDE_EFFECTS (arg0)
|
|
1573 && !TREE_SIDE_EFFECTS (arg1))
|
|
1574 return build_int_cst (type, 0);
|
|
1575 if ((p0 = c_getstr (arg0, &s0))
|
|
1576 && s2 <= s0
|
|
1577 && target_char_cst_p (arg1, &c))
|
|
1578 {
|
|
1579 const char *r = (const char *) memchr (p0, c, s2);
|
|
1580 if (r == NULL)
|
|
1581 return build_int_cst (type, 0);
|
|
1582 return fold_convert (type,
|
|
1583 fold_build_pointer_plus_hwi (arg0, r - p0));
|
|
1584 }
|
|
1585 return NULL_TREE;
|
|
1586
|
|
1587 default:
|
|
1588 return fold_const_call_1 (fn, type, arg0, arg1, arg2);
|
|
1589 }
|
|
1590 }
|
|
1591
|
|
1592 /* Fold a fma operation with arguments ARG[012]. */
|
|
1593
|
|
1594 tree
|
|
1595 fold_fma (location_t, tree type, tree arg0, tree arg1, tree arg2)
|
|
1596 {
|
|
1597 REAL_VALUE_TYPE result;
|
|
1598 if (real_cst_p (arg0)
|
|
1599 && real_cst_p (arg1)
|
|
1600 && real_cst_p (arg2)
|
|
1601 && do_mpfr_arg3 (&result, mpfr_fma, TREE_REAL_CST_PTR (arg0),
|
|
1602 TREE_REAL_CST_PTR (arg1), TREE_REAL_CST_PTR (arg2),
|
|
1603 REAL_MODE_FORMAT (TYPE_MODE (type))))
|
|
1604 return build_real (type, result);
|
|
1605
|
|
1606 return NULL_TREE;
|
|
1607 }
|