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