1/* Code for GIMPLE range op related routines.
2 Copyright (C) 2019-2025 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
4 and Aldy Hernandez <aldyh@redhat.com>.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GCC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "backend.h"
26#include "insn-codes.h"
27#include "tree.h"
28#include "gimple.h"
29#include "ssa.h"
30#include "gimple-pretty-print.h"
31#include "optabs-tree.h"
32#include "gimple-iterator.h"
33#include "gimple-fold.h"
34#include "wide-int.h"
35#include "fold-const.h"
36#include "case-cfn-macros.h"
37#include "omp-general.h"
38#include "cfgloop.h"
39#include "tree-ssa-loop.h"
40#include "tree-scalar-evolution.h"
41#include "langhooks.h"
42#include "vr-values.h"
43#include "range.h"
44#include "value-query.h"
45#include "gimple-range.h"
46#include "attr-fnspec.h"
47#include "realmpfr.h"
48
49// Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
50// on the statement. For efficiency, it is an error to not pass in enough
51// elements for the vector. Return the number of ssa-names.
52
53unsigned
54gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt)
55{
56 tree ssa;
57 int count = 0;
58
59 gimple_range_op_handler handler (stmt);
60 if (handler)
61 {
62 gcc_checking_assert (vec_size >= 2);
63 if ((ssa = gimple_range_ssa_p (exp: handler.operand1 ())))
64 vec[count++] = ssa;
65 if ((ssa = gimple_range_ssa_p (exp: handler.operand2 ())))
66 vec[count++] = ssa;
67 }
68 else if (is_a<gassign *> (p: stmt)
69 && gimple_assign_rhs_code (gs: stmt) == COND_EXPR)
70 {
71 gcc_checking_assert (vec_size >= 3);
72 gassign *st = as_a<gassign *> (p: stmt);
73 if ((ssa = gimple_range_ssa_p (exp: gimple_assign_rhs1 (gs: st))))
74 vec[count++] = ssa;
75 if ((ssa = gimple_range_ssa_p (exp: gimple_assign_rhs2 (gs: st))))
76 vec[count++] = ssa;
77 if ((ssa = gimple_range_ssa_p (exp: gimple_assign_rhs3 (gs: st))))
78 vec[count++] = ssa;
79 }
80 return count;
81}
82
83// Return the base of the RHS of an assignment.
84
85static tree
86gimple_range_base_of_assignment (const gimple *stmt)
87{
88 gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
89 tree op1 = gimple_assign_rhs1 (gs: stmt);
90 if (gimple_assign_rhs_code (gs: stmt) == ADDR_EXPR)
91 return get_base_address (TREE_OPERAND (op1, 0));
92 return op1;
93}
94
95// If statement is supported by range-ops, set the CODE and return the TYPE.
96
97static inline enum tree_code
98get_code (gimple *s)
99{
100 if (const gassign *ass = dyn_cast<const gassign *> (p: s))
101 return gimple_assign_rhs_code (gs: ass);
102 if (const gcond *cond = dyn_cast<const gcond *> (p: s))
103 return gimple_cond_code (gs: cond);
104 return ERROR_MARK;
105}
106
107// If statement S has a supported range_op handler return TRUE.
108
109bool
110gimple_range_op_handler::supported_p (gimple *s)
111{
112 enum tree_code code = get_code (s);
113 if (range_op_handler (code))
114 return true;
115 if (is_a <gcall *> (p: s) && gimple_range_op_handler (s))
116 return true;
117 return false;
118}
119
120// Construct a handler object for statement S.
121
122gimple_range_op_handler::gimple_range_op_handler (gimple *s)
123{
124 range_op_handler oper (get_code (s));
125 m_stmt = s;
126 m_op1 = NULL_TREE;
127 m_op2 = NULL_TREE;
128
129 if (oper)
130 switch (gimple_code (g: m_stmt))
131 {
132 case GIMPLE_COND:
133 m_op1 = gimple_cond_lhs (gs: m_stmt);
134 m_op2 = gimple_cond_rhs (gs: m_stmt);
135 // Check that operands are supported types. One check is enough.
136 if (value_range::supports_type_p (TREE_TYPE (m_op1)))
137 m_operator = oper.range_op ();
138 gcc_checking_assert (m_operator);
139 return;
140 case GIMPLE_ASSIGN:
141 m_op1 = gimple_range_base_of_assignment (stmt: m_stmt);
142 if (m_op1 && TREE_CODE (m_op1) == MEM_REF)
143 {
144 // If the base address is an SSA_NAME, we return it
145 // here. This allows processing of the range of that
146 // name, while the rest of the expression is simply
147 // ignored. The code in range_ops will see the
148 // ADDR_EXPR and do the right thing.
149 tree ssa = TREE_OPERAND (m_op1, 0);
150 if (TREE_CODE (ssa) == SSA_NAME)
151 m_op1 = ssa;
152 }
153 if (gimple_num_ops (gs: m_stmt) >= 3)
154 m_op2 = gimple_assign_rhs2 (gs: m_stmt);
155 // Check that operands are supported types. One check is enough.
156 if ((m_op1 && !value_range::supports_type_p (TREE_TYPE (m_op1))))
157 return;
158 m_operator = oper.range_op ();
159 gcc_checking_assert (m_operator);
160 return;
161 default:
162 gcc_unreachable ();
163 return;
164 }
165 // If no range-op table entry handled this stmt, check for other supported
166 // statements.
167 if (is_a <gcall *> (p: m_stmt))
168 maybe_builtin_call ();
169 else
170 maybe_non_standard ();
171 gcc_checking_assert (m_operator);
172}
173
174// Calculate what we can determine of the range of this unary
175// statement's operand if the lhs of the expression has the range
176// LHS_RANGE. Return false if nothing can be determined.
177
178bool
179gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range)
180{
181 // Give up on empty ranges.
182 if (lhs_range.undefined_p ())
183 return false;
184
185 // Unary operations require the type of the first operand in the
186 // second range position.
187 tree type = TREE_TYPE (operand1 ());
188 value_range type_range (type);
189 type_range.set_varying (type);
190 return op1_range (r, type, lhs: lhs_range, op2: type_range);
191}
192
193// Calculate what we can determine of the range of this statement's
194// first operand if the lhs of the expression has the range LHS_RANGE
195// and the second operand has the range OP2_RANGE. Return false if
196// nothing can be determined.
197
198bool
199gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
200 const vrange &op2_range, relation_trio k)
201{
202 // Give up on empty ranges.
203 if (lhs_range.undefined_p ())
204 return false;
205
206 // Unary operation are allowed to pass a range in for second operand
207 // as there are often additional restrictions beyond the type which
208 // can be imposed. See operator_cast::op1_range().
209 tree type = TREE_TYPE (operand1 ());
210 // If op2 is undefined, solve as if it is varying.
211 if (op2_range.undefined_p ())
212 {
213 if (gimple_num_ops (gs: m_stmt) < 3)
214 return false;
215 tree op2_type;
216 // This is sometimes invoked on single operand stmts.
217 if (operand2 ())
218 op2_type = TREE_TYPE (operand2 ());
219 else
220 op2_type = TREE_TYPE (operand1 ());
221 value_range trange (op2_type);
222 trange.set_varying (op2_type);
223 return op1_range (r, type, lhs: lhs_range, op2: trange, k);
224 }
225 return op1_range (r, type, lhs: lhs_range, op2: op2_range, k);
226}
227
228// Calculate what we can determine of the range of this statement's
229// second operand if the lhs of the expression has the range LHS_RANGE
230// and the first operand has the range OP1_RANGE. Return false if
231// nothing can be determined.
232
233bool
234gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
235 const vrange &op1_range, relation_trio k)
236{
237 // Give up on empty ranges.
238 if (lhs_range.undefined_p ())
239 return false;
240
241 tree type = TREE_TYPE (operand2 ());
242 // If op1 is undefined, solve as if it is varying.
243 if (op1_range.undefined_p ())
244 {
245 tree op1_type = TREE_TYPE (operand1 ());
246 value_range trange (op1_type);
247 trange.set_varying (op1_type);
248 return op2_range (r, type, lhs: lhs_range, op1: trange, k);
249 }
250 return op2_range (r, type, lhs: lhs_range, op1: op1_range, k);
251}
252
253// --------------------------------------------------------------------
254
255// Implement range operator for float CFN_BUILT_IN_CONSTANT_P.
256class cfn_constant_float_p : public range_operator
257{
258public:
259 using range_operator::fold_range;
260 virtual bool fold_range (irange &r, tree type, const frange &lh,
261 const irange &, relation_trio) const
262 {
263 if (lh.singleton_p ())
264 {
265 wide_int one = wi::one (TYPE_PRECISION (type));
266 r.set (type, one, one);
267 return true;
268 }
269 if (cfun->after_inlining)
270 {
271 r.set_zero (type);
272 return true;
273 }
274 return false;
275 }
276} op_cfn_constant_float_p;
277
278// Implement range operator for integral CFN_BUILT_IN_CONSTANT_P.
279class cfn_constant_p : public range_operator
280{
281public:
282 using range_operator::fold_range;
283 virtual bool fold_range (irange &r, tree type, const irange &lh,
284 const irange &, relation_trio) const
285 {
286 if (lh.singleton_p ())
287 {
288 wide_int one = wi::one (TYPE_PRECISION (type));
289 r.set (type, one, one);
290 return true;
291 }
292 if (cfun->after_inlining)
293 {
294 r.set_zero (type);
295 return true;
296 }
297 return false;
298 }
299} op_cfn_constant_p;
300
301// Implement range operator for integral/pointer functions returning
302// the first argument.
303class cfn_pass_through_arg1 : public range_operator
304{
305public:
306 using range_operator::fold_range;
307 using range_operator::op1_range;
308 virtual bool fold_range (irange &r, tree, const irange &lh,
309 const irange &, relation_trio) const
310 {
311 r = lh;
312 return true;
313 }
314 virtual bool fold_range (prange &r, tree, const prange &lh,
315 const prange &, relation_trio) const
316 {
317 r = lh;
318 return true;
319 }
320 virtual bool op1_range (irange &r, tree, const irange &lhs,
321 const irange &, relation_trio) const
322 {
323 r = lhs;
324 return true;
325 }
326 virtual bool op1_range (prange &r, tree, const prange &lhs,
327 const prange &, relation_trio) const
328 {
329 r = lhs;
330 return true;
331 }
332} op_cfn_pass_through_arg1;
333
334// Implement range operator for CFN_BUILT_IN_SIGNBIT.
335class cfn_signbit : public range_operator
336{
337public:
338 using range_operator::fold_range;
339 using range_operator::op1_range;
340 virtual bool fold_range (irange &r, tree type, const frange &lh,
341 const irange &, relation_trio) const override
342 {
343 bool signbit;
344 if (lh.signbit_p (signbit))
345 {
346 if (signbit)
347 r.set_nonzero (type);
348 else
349 r.set_zero (type);
350 return true;
351 }
352 return false;
353 }
354 virtual bool op1_range (frange &r, tree type, const irange &lhs,
355 const frange &, relation_trio) const override
356 {
357 if (lhs.zero_p ())
358 {
359 r.set (type, dconst0, frange_val_max (type));
360 r.update_nan (sign: false);
361 return true;
362 }
363 if (!lhs.contains_p (wi::zero (TYPE_PRECISION (lhs.type ()))))
364 {
365 r.set (type, frange_val_min (type), dconstm0);
366 r.update_nan (sign: true);
367 return true;
368 }
369 return false;
370 }
371} op_cfn_signbit;
372
373// Implement range operator for CFN_BUILT_IN_COPYSIGN
374class cfn_copysign : public range_operator
375{
376public:
377 using range_operator::fold_range;
378 virtual bool fold_range (frange &r, tree type, const frange &lh,
379 const frange &rh, relation_trio) const override
380 {
381 frange neg;
382 if (!range_op_handler (ABS_EXPR).fold_range (r, type, lh, rh: frange (type)))
383 return false;
384 if (!range_op_handler (NEGATE_EXPR).fold_range (r&: neg, type, lh: r,
385 rh: frange (type)))
386 return false;
387
388 bool signbit;
389 if (rh.signbit_p (signbit))
390 {
391 // If the sign is negative, flip the result from ABS,
392 // otherwise leave things positive.
393 if (signbit)
394 r = neg;
395 }
396 else
397 // If the sign is unknown, keep the positive and negative
398 // alternatives.
399 r.union_ (neg);
400 return true;
401 }
402} op_cfn_copysign;
403
404/* Compute FUNC (ARG) where FUNC is a mpfr function. If RES_LOW is non-NULL,
405 set it to low bound of possible range if the function is expected to have
406 ULPS precision and similarly if RES_HIGH is non-NULL, set it to high bound.
407 If the function returns false, the results weren't set. */
408
409static bool
410frange_mpfr_arg1 (REAL_VALUE_TYPE *res_low, REAL_VALUE_TYPE *res_high,
411 int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
412 const REAL_VALUE_TYPE &arg, tree type, unsigned ulps)
413{
414 if (ulps == ~0U || !real_isfinite (&arg))
415 return false;
416 machine_mode mode = TYPE_MODE (type);
417 const real_format *format = REAL_MODE_FORMAT (mode);
418 auto_mpfr m (format->p);
419 mpfr_from_real (m, &arg, MPFR_RNDN);
420 mpfr_clear_flags ();
421 bool inexact = func (m, m, MPFR_RNDN);
422 if (!mpfr_number_p (m) || mpfr_overflow_p () || mpfr_underflow_p ())
423 return false;
424
425 REAL_VALUE_TYPE value, result;
426 real_from_mpfr (&value, m, format, MPFR_RNDN);
427 if (!real_isfinite (&value))
428 return false;
429 if ((value.cl == rvc_zero) != (mpfr_zero_p (m) != 0))
430 inexact = true;
431
432 real_convert (&result, format, &value);
433 if (!real_isfinite (&result))
434 return false;
435 bool round_low = false;
436 bool round_high = false;
437 if (!ulps && flag_rounding_math)
438 ++ulps;
439 if (inexact || !real_identical (&result, &value))
440 {
441 if (MODE_COMPOSITE_P (mode))
442 round_low = round_high = true;
443 else
444 {
445 round_low = !real_less (&result, &value);
446 round_high = !real_less (&value, &result);
447 }
448 }
449 if (res_low)
450 {
451 *res_low = result;
452 for (unsigned int i = 0; i < ulps + round_low; ++i)
453 frange_nextafter (mode, *res_low, dconstninf);
454 }
455 if (res_high)
456 {
457 *res_high = result;
458 for (unsigned int i = 0; i < ulps + round_high; ++i)
459 frange_nextafter (mode, *res_high, dconstinf);
460 }
461 return true;
462}
463
464class cfn_sqrt : public range_operator
465{
466public:
467 using range_operator::fold_range;
468 using range_operator::op1_range;
469 virtual bool fold_range (frange &r, tree type,
470 const frange &lh, const frange &,
471 relation_trio) const final override
472 {
473 if (lh.undefined_p ())
474 return false;
475 if (lh.known_isnan () || real_less (&lh.upper_bound (), &dconstm0))
476 {
477 r.set_nan (type);
478 return true;
479 }
480 unsigned bulps
481 = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true);
482 if (bulps == ~0U)
483 r.set_varying (type);
484 else if (bulps == 0)
485 r.set (type, dconstm0, dconstinf);
486 else
487 {
488 REAL_VALUE_TYPE boundmin = dconstm0;
489 while (bulps--)
490 frange_nextafter (TYPE_MODE (type), boundmin, dconstninf);
491 r.set (type, boundmin, dconstinf);
492 }
493 if (!lh.maybe_isnan () && !real_less (&lh.lower_bound (), &dconst0))
494 r.clear_nan ();
495
496 unsigned ulps
497 = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false);
498 if (ulps == ~0U)
499 return true;
500 REAL_VALUE_TYPE lb = lh.lower_bound ();
501 REAL_VALUE_TYPE ub = lh.upper_bound ();
502 if (!frange_mpfr_arg1 (res_low: &lb, NULL, func: mpfr_sqrt, arg: lb, type, ulps))
503 lb = dconstninf;
504 if (!frange_mpfr_arg1 (NULL, res_high: &ub, func: mpfr_sqrt, arg: ub, type, ulps))
505 ub = dconstinf;
506 frange r2;
507 r2.set (type, lb, ub);
508 r2.flush_denormals_to_zero ();
509 r.intersect (r2);
510 return true;
511 }
512 virtual bool op1_range (frange &r, tree type,
513 const frange &lhs, const frange &,
514 relation_trio) const final override
515 {
516 if (lhs.undefined_p ())
517 return false;
518
519 // A known NAN means the input is [-INF,-0.) U +-NAN.
520 if (lhs.known_isnan ())
521 {
522 known_nan:
523 REAL_VALUE_TYPE ub = dconstm0;
524 frange_nextafter (TYPE_MODE (type), ub, dconstninf);
525 r.set (type, dconstninf, ub);
526 // No r.flush_denormals_to_zero (); here - it is a reverse op.
527 return true;
528 }
529
530 // Results outside of [-0.0, +Inf] are impossible.
531 unsigned bulps
532 = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true);
533 if (bulps != ~0U)
534 {
535 const REAL_VALUE_TYPE &ub = lhs.upper_bound ();
536 REAL_VALUE_TYPE m0 = dconstm0;
537 while (bulps--)
538 frange_nextafter (TYPE_MODE (type), m0, dconstninf);
539 if (real_less (&ub, &m0))
540 {
541 if (!lhs.maybe_isnan ())
542 r.set_undefined ();
543 else
544 // If lhs could be NAN and finite result is impossible,
545 // the range is like lhs.known_isnan () above.
546 goto known_nan;
547 return true;
548 }
549 }
550
551 if (!lhs.maybe_isnan ())
552 // If NAN is not valid result, the input cannot include either
553 // a NAN nor values smaller than -0.
554 r.set (type, dconstm0, dconstinf, nan_state (false, false));
555 else
556 r.set_varying (type);
557
558 unsigned ulps
559 = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false);
560 if (ulps == ~0U)
561 return true;
562 REAL_VALUE_TYPE lb = lhs.lower_bound ();
563 REAL_VALUE_TYPE ub = lhs.upper_bound ();
564 if (!lhs.maybe_isnan () && real_less (&dconst0, &lb))
565 {
566 for (unsigned i = 0; i < ulps; ++i)
567 frange_nextafter (TYPE_MODE (type), lb, dconstninf);
568 if (real_less (&dconst0, &lb))
569 {
570 REAL_VALUE_TYPE op = lb;
571 frange_arithmetic (MULT_EXPR, type, lb, op, op, dconstninf);
572 }
573 else
574 lb = dconstninf;
575 }
576 else
577 lb = dconstninf;
578 if (real_isfinite (&ub) && real_less (&dconst0, &ub))
579 {
580 for (unsigned i = 0; i < ulps; ++i)
581 frange_nextafter (TYPE_MODE (type), ub, dconstinf);
582 if (real_isfinite (&ub))
583 {
584 REAL_VALUE_TYPE op = ub;
585 frange_arithmetic (MULT_EXPR, type, ub, op, op, dconstinf);
586 }
587 else
588 ub = dconstinf;
589 }
590 else
591 ub = dconstinf;
592 frange r2;
593 r2.set (type, lb, ub);
594 r.intersect (r2);
595 return true;
596 }
597} op_cfn_sqrt;
598
599class cfn_sincos : public range_operator
600{
601public:
602 using range_operator::fold_range;
603 using range_operator::op1_range;
604 cfn_sincos (combined_fn cfn) { m_cfn = cfn; }
605 virtual bool fold_range (frange &r, tree type,
606 const frange &lh, const frange &,
607 relation_trio) const final override
608 {
609 if (lh.undefined_p ())
610 return false;
611 if (lh.known_isnan () || lh.known_isinf ())
612 {
613 r.set_nan (type);
614 return true;
615 }
616 unsigned bulps = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type),
617 true);
618 if (bulps == ~0U)
619 r.set_varying (type);
620 else if (bulps == 0)
621 r.set (type, dconstm1, dconst1);
622 else
623 {
624 REAL_VALUE_TYPE boundmin, boundmax;
625 boundmax = dconst1;
626 while (bulps--)
627 frange_nextafter (TYPE_MODE (type), boundmax, dconstinf);
628 real_arithmetic (&boundmin, NEGATE_EXPR, &boundmax, NULL);
629 r.set (type, boundmin, boundmax);
630 }
631 if (!lh.maybe_isnan () && !lh.maybe_isinf ())
632 r.clear_nan ();
633
634 unsigned ulps
635 = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type), false);
636 if (ulps == ~0U)
637 return true;
638 REAL_VALUE_TYPE lb = lh.lower_bound ();
639 REAL_VALUE_TYPE ub = lh.upper_bound ();
640 REAL_VALUE_TYPE diff;
641 real_arithmetic (&diff, MINUS_EXPR, &ub, &lb);
642 if (!real_isfinite (&diff))
643 return true;
644 REAL_VALUE_TYPE pi = dconst_pi ();
645 REAL_VALUE_TYPE pix2;
646 real_arithmetic (&pix2, PLUS_EXPR, &pi, &pi);
647 // We can only try to narrow the range further if ub-lb < 2*pi.
648 if (!real_less (&diff, &pix2))
649 return true;
650 REAL_VALUE_TYPE lb_lo, lb_hi, ub_lo, ub_hi;
651 REAL_VALUE_TYPE lb_deriv_lo, lb_deriv_hi, ub_deriv_lo, ub_deriv_hi;
652 if (!frange_mpfr_arg1 (res_low: &lb_lo, res_high: &lb_hi,
653 func: m_cfn == CFN_SIN ? mpfr_sin : mpfr_cos, arg: lb,
654 type, ulps)
655 || !frange_mpfr_arg1 (res_low: &ub_lo, res_high: &ub_hi,
656 func: m_cfn == CFN_SIN ? mpfr_sin : mpfr_cos, arg: ub,
657 type, ulps)
658 || !frange_mpfr_arg1 (res_low: &lb_deriv_lo, res_high: &lb_deriv_hi,
659 func: m_cfn == CFN_SIN ? mpfr_cos : mpfr_sin, arg: lb,
660 type, ulps: 0)
661 || !frange_mpfr_arg1 (res_low: &ub_deriv_lo, res_high: &ub_deriv_hi,
662 func: m_cfn == CFN_SIN ? mpfr_cos : mpfr_sin, arg: ub,
663 type, ulps: 0))
664 return true;
665 if (m_cfn == CFN_COS)
666 {
667 // Derivative of cos is -sin, so negate.
668 lb_deriv_lo.sign ^= 1;
669 lb_deriv_hi.sign ^= 1;
670 ub_deriv_lo.sign ^= 1;
671 ub_deriv_hi.sign ^= 1;
672 }
673
674 if (real_less (&lb_lo, &ub_lo))
675 lb = lb_lo;
676 else
677 lb = ub_lo;
678 if (real_less (&lb_hi, &ub_hi))
679 ub = ub_hi;
680 else
681 ub = lb_hi;
682
683 // The range between the function result on the boundaries may need
684 // to be extended to +1 (+Inf) or -1 (-Inf) or both depending on the
685 // derivative or length of the argument range (diff).
686
687 // First handle special case, where the derivative has different signs,
688 // so the bound must be roughly -1 or +1.
689 if (real_isneg (&lb_deriv_lo) != real_isneg (&lb_deriv_hi))
690 {
691 if (real_isneg (&lb_lo))
692 lb = dconstninf;
693 else
694 ub = dconstinf;
695 }
696 if (real_isneg (&ub_deriv_lo) != real_isneg (&ub_deriv_hi))
697 {
698 if (real_isneg (&ub_lo))
699 lb = dconstninf;
700 else
701 ub = dconstinf;
702 }
703
704 // If derivative at lower_bound and upper_bound have the same sign,
705 // the function grows or declines on the whole range if diff < pi, so
706 // [lb, ub] is correct, and if diff >= pi the result range must include
707 // both the minimum and maximum.
708 if (real_isneg (&lb_deriv_lo) == real_isneg (&ub_deriv_lo))
709 {
710 if (!real_less (&diff, &pi))
711 return true;
712 }
713 // If function declines at lower_bound and grows at upper_bound,
714 // the result range must include the minimum, so set lb to -Inf.
715 else if (real_isneg (&lb_deriv_lo))
716 lb = dconstninf;
717 // If function grows at lower_bound and declines at upper_bound,
718 // the result range must include the maximum, so set ub to +Inf.
719 else
720 ub = dconstinf;
721 frange r2;
722 r2.set (type, lb, ub);
723 r2.flush_denormals_to_zero ();
724 r.intersect (r2);
725 return true;
726 }
727 virtual bool op1_range (frange &r, tree type,
728 const frange &lhs, const frange &,
729 relation_trio) const final override
730 {
731 if (lhs.undefined_p ())
732 return false;
733
734 // A known NAN means the input is [-INF,-INF][+INF,+INF] U +-NAN,
735 // which we can't currently represent.
736 if (lhs.known_isnan ())
737 {
738 r.set_varying (type);
739 return true;
740 }
741
742 // Results outside of [-1.0, +1.0] are impossible.
743 unsigned bulps
744 = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type), true);
745 if (bulps != ~0U)
746 {
747 const REAL_VALUE_TYPE &lb = lhs.lower_bound ();
748 const REAL_VALUE_TYPE &ub = lhs.upper_bound ();
749 REAL_VALUE_TYPE m1 = dconstm1;
750 REAL_VALUE_TYPE p1 = dconst1;
751 while (bulps--)
752 {
753 frange_nextafter (TYPE_MODE (type), m1, dconstninf);
754 frange_nextafter (TYPE_MODE (type), p1, dconstinf);
755 }
756 if (real_less (&ub, &m1) || real_less (&p1, &lb))
757 {
758 if (!lhs.maybe_isnan ())
759 r.set_undefined ();
760 else
761 /* If lhs could be NAN and finite result is impossible,
762 the range is like lhs.known_isnan () above,
763 [-INF,-INF][+INF,+INF] U +-NAN. */
764 r.set_varying (type);
765 return true;
766 }
767 }
768
769 if (!lhs.maybe_isnan ())
770 {
771 // If NAN is not valid result, the input cannot include either
772 // a NAN nor a +-INF.
773 REAL_VALUE_TYPE lb = real_min_representable (type);
774 REAL_VALUE_TYPE ub = real_max_representable (type);
775 r.set (type, lb, ub, nan_state (false, false));
776 }
777 else
778 r.set_varying (type);
779 return true;
780 }
781private:
782 combined_fn m_cfn;
783} op_cfn_sin (CFN_SIN), op_cfn_cos (CFN_COS);
784
785// Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
786class cfn_toupper_tolower : public range_operator
787{
788public:
789 using range_operator::fold_range;
790 cfn_toupper_tolower (bool toupper) { m_toupper = toupper; }
791 virtual bool fold_range (irange &r, tree type, const irange &lh,
792 const irange &, relation_trio) const;
793private:
794 bool get_letter_range (tree type, irange &lowers, irange &uppers) const;
795 bool m_toupper;
796} op_cfn_toupper (true), op_cfn_tolower (false);
797
798// Return TRUE if we recognize the target character set and return the
799// range for lower case and upper case letters.
800
801bool
802cfn_toupper_tolower::get_letter_range (tree type, irange &lowers,
803 irange &uppers) const
804{
805 // ASCII
806 int a = lang_hooks.to_target_charset ('a');
807 int z = lang_hooks.to_target_charset ('z');
808 int A = lang_hooks.to_target_charset ('A');
809 int Z = lang_hooks.to_target_charset ('Z');
810
811 if ((z - a == 25) && (Z - A == 25))
812 {
813 lowers = int_range<2> (type,
814 wi::shwi (val: a, TYPE_PRECISION (type)),
815 wi::shwi (val: z, TYPE_PRECISION (type)));
816 uppers = int_range<2> (type,
817 wi::shwi (val: A, TYPE_PRECISION (type)),
818 wi::shwi (val: Z, TYPE_PRECISION (type)));
819 return true;
820 }
821 // Unknown character set.
822 return false;
823}
824
825bool
826cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
827 const irange &, relation_trio) const
828{
829 int_range<3> lowers;
830 int_range<3> uppers;
831 if (!get_letter_range (type, lowers, uppers))
832 return false;
833
834 r = lh;
835 if (m_toupper)
836 {
837 // Return the range passed in without any lower case characters,
838 // but including all the upper case ones.
839 lowers.invert ();
840 r.intersect (lowers);
841 r.union_ (uppers);
842 }
843 else
844 {
845 // Return the range passed in without any lower case characters,
846 // but including all the upper case ones.
847 uppers.invert ();
848 r.intersect (uppers);
849 r.union_ (lowers);
850 }
851 return true;
852}
853
854// Implement range operator for CFN_BUILT_IN_FFS.
855class cfn_ffs : public range_operator
856{
857public:
858 using range_operator::fold_range;
859 virtual bool fold_range (irange &r, tree type, const irange &lh,
860 const irange &, relation_trio) const
861 {
862 if (lh.undefined_p ())
863 return false;
864 // __builtin_ffs* and __builtin_popcount* return [0, prec].
865 int prec = TYPE_PRECISION (lh.type ());
866 // If arg is non-zero, then ffs or popcount are non-zero.
867 int mini = range_includes_zero_p (vr: lh) ? 0 : 1;
868 int maxi = prec;
869
870 // If some high bits are known to be zero, decrease the maximum.
871 int_range_max tmp = lh;
872 if (TYPE_SIGN (tmp.type ()) == SIGNED)
873 range_cast (r&: tmp, type: unsigned_type_for (tmp.type ()));
874 wide_int max = tmp.upper_bound ();
875 maxi = wi::floor_log2 (max) + 1;
876 r.set (type,
877 wi::shwi (val: mini, TYPE_PRECISION (type)),
878 wi::shwi (val: maxi, TYPE_PRECISION (type)));
879 return true;
880 }
881} op_cfn_ffs;
882
883// Implement range operator for CFN_BUILT_IN_POPCOUNT.
884class cfn_popcount : public cfn_ffs
885{
886public:
887 using range_operator::fold_range;
888 virtual bool fold_range (irange &r, tree type, const irange &lh,
889 const irange &rh, relation_trio rel) const
890 {
891 if (lh.undefined_p ())
892 return false;
893 unsigned prec = TYPE_PRECISION (type);
894 irange_bitmask bm = lh.get_bitmask ();
895 wide_int nz = bm.get_nonzero_bits ();
896 wide_int high = wi::shwi (val: wi::popcount (nz), precision: prec);
897 // Calculating the popcount of a singleton is trivial.
898 if (lh.singleton_p ())
899 {
900 r.set (type, high, high);
901 return true;
902 }
903 if (cfn_ffs::fold_range (r, type, lh, rh, rel))
904 {
905 wide_int known_ones = ~bm.mask () & bm.value ();
906 wide_int low = wi::shwi (val: wi::popcount (known_ones), precision: prec);
907 int_range<2> tmp (type, low, high);
908 r.intersect (tmp);
909 return true;
910 }
911 return false;
912 }
913} op_cfn_popcount;
914
915// Implement range operator for CFN_BUILT_IN_CLZ
916class cfn_clz : public range_operator
917{
918public:
919 cfn_clz (bool internal) { m_gimple_call_internal_p = internal; }
920 using range_operator::fold_range;
921 virtual bool fold_range (irange &r, tree type, const irange &lh,
922 const irange &rh, relation_trio) const;
923private:
924 bool m_gimple_call_internal_p;
925} op_cfn_clz (false), op_cfn_clz_internal (true);
926
927bool
928cfn_clz::fold_range (irange &r, tree type, const irange &lh,
929 const irange &rh, relation_trio) const
930{
931 // __builtin_c[lt]z* return [0, prec-1], except when the
932 // argument is 0, but that is undefined behavior.
933 //
934 // For __builtin_c[lt]z* consider argument of 0 always undefined
935 // behavior, for internal fns likewise, unless it has 2 arguments,
936 // then the second argument is the value at zero.
937 if (lh.undefined_p ())
938 return false;
939 int prec = TYPE_PRECISION (lh.type ());
940 int mini = 0;
941 int maxi = prec - 1;
942 if (m_gimple_call_internal_p)
943 {
944 // Handle only the two common values.
945 if (rh.lower_bound () == -1)
946 mini = -1;
947 else if (rh.lower_bound () == prec)
948 maxi = prec;
949 else
950 // Magic value to give up, unless we can prove arg is non-zero.
951 mini = -2;
952 }
953
954 // From clz of minimum we can compute result maximum.
955 if (wi::gt_p (x: lh.lower_bound (), y: 0, TYPE_SIGN (lh.type ())))
956 {
957 maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ());
958 if (mini < 0)
959 mini = 0;
960 }
961 else if (!range_includes_zero_p (vr: lh))
962 {
963 mini = 0;
964 maxi = prec - 1;
965 }
966 if (mini == -2)
967 return false;
968 // From clz of maximum we can compute result minimum.
969 wide_int max = lh.upper_bound ();
970 int newmini = prec - 1 - wi::floor_log2 (max);
971 if (max == 0)
972 {
973 // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
974 // return [prec, prec] or [-1, -1], otherwise ignore the range.
975 if (maxi == prec)
976 mini = prec;
977 else if (mini == -1)
978 maxi = -1;
979 }
980 else if (mini >= 0)
981 mini = newmini;
982
983 if (mini == -2)
984 return false;
985 r.set (type,
986 wi::shwi (val: mini, TYPE_PRECISION (type)),
987 wi::shwi (val: maxi, TYPE_PRECISION (type)));
988 return true;
989}
990
991// Implement range operator for CFN_BUILT_IN_CTZ
992class cfn_ctz : public range_operator
993{
994public:
995 cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; }
996 using range_operator::fold_range;
997 virtual bool fold_range (irange &r, tree type, const irange &lh,
998 const irange &rh, relation_trio) const;
999private:
1000 bool m_gimple_call_internal_p;
1001} op_cfn_ctz (false), op_cfn_ctz_internal (true);
1002
1003bool
1004cfn_ctz::fold_range (irange &r, tree type, const irange &lh,
1005 const irange &rh, relation_trio) const
1006{
1007 if (lh.undefined_p ())
1008 return false;
1009 int prec = TYPE_PRECISION (lh.type ());
1010 int mini = 0;
1011 int maxi = prec - 1;
1012
1013 if (m_gimple_call_internal_p)
1014 {
1015 // Handle only the two common values.
1016 if (rh.lower_bound () == -1)
1017 mini = -1;
1018 else if (rh.lower_bound () == prec)
1019 maxi = prec;
1020 else
1021 // Magic value to give up, unless we can prove arg is non-zero.
1022 mini = -2;
1023 }
1024 // If arg is non-zero, then use [0, prec - 1].
1025 if (!range_includes_zero_p (vr: lh))
1026 {
1027 mini = 0;
1028 maxi = prec - 1;
1029 }
1030 // If some high bits are known to be zero, we can decrease
1031 // the maximum.
1032 wide_int max = lh.upper_bound ();
1033 if (max == 0)
1034 {
1035 // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO
1036 // is 2 with value -1 or prec, return [-1, -1] or [prec, prec].
1037 // Otherwise ignore the range.
1038 if (mini == -1)
1039 maxi = -1;
1040 else if (maxi == prec)
1041 mini = prec;
1042 }
1043 // If value at zero is prec and 0 is in the range, we can't lower
1044 // the upper bound. We could create two separate ranges though,
1045 // [0,floor_log2(max)][prec,prec] though.
1046 else if (maxi != prec)
1047 maxi = wi::floor_log2 (max);
1048
1049 if (mini == -2)
1050 return false;
1051 r.set (type,
1052 wi::shwi (val: mini, TYPE_PRECISION (type)),
1053 wi::shwi (val: maxi, TYPE_PRECISION (type)));
1054 return true;
1055}
1056
1057
1058// Implement range operator for CFN_BUILT_IN_
1059class cfn_clrsb : public range_operator
1060{
1061public:
1062 using range_operator::fold_range;
1063 virtual bool fold_range (irange &r, tree type, const irange &lh,
1064 const irange &, relation_trio) const
1065 {
1066 if (lh.undefined_p ())
1067 return false;
1068 int prec = TYPE_PRECISION (lh.type ());
1069 r.set (type,
1070 wi::zero (TYPE_PRECISION (type)),
1071 wi::shwi (val: prec - 1, TYPE_PRECISION (type)));
1072 return true;
1073 }
1074} op_cfn_clrsb;
1075
1076
1077// Implement range operator for CFN_BUILT_IN_
1078class cfn_ubsan : public range_operator
1079{
1080public:
1081 cfn_ubsan (enum tree_code code) { m_code = code; }
1082 using range_operator::fold_range;
1083 virtual bool fold_range (irange &r, tree type, const irange &lh,
1084 const irange &rh, relation_trio rel) const
1085 {
1086 bool saved_flag_wrapv = flag_wrapv;
1087 // Pretend the arithmetic is wrapping. If there is any overflow,
1088 // we'll complain, but will actually do wrapping operation.
1089 flag_wrapv = 1;
1090 bool result = range_op_handler (m_code).fold_range (r, type, lh, rh, rel);
1091 flag_wrapv = saved_flag_wrapv;
1092
1093 // If for both arguments vrp_valueize returned non-NULL, this should
1094 // have been already folded and if not, it wasn't folded because of
1095 // overflow. Avoid removing the UBSAN_CHECK_* calls in that case.
1096 if (result && r.singleton_p ())
1097 r.set_varying (type);
1098 return result;
1099 }
1100private:
1101 enum tree_code m_code;
1102};
1103
1104cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
1105cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
1106cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
1107
1108
1109// Implement range operator for CFN_BUILT_IN_STRLEN
1110class cfn_strlen : public range_operator
1111{
1112public:
1113 using range_operator::fold_range;
1114 virtual bool fold_range (irange &r, tree type, const prange &,
1115 const irange &, relation_trio) const
1116 {
1117 wide_int max = irange_val_max (ptrdiff_type_node);
1118 // To account for the terminating NULL, the maximum length
1119 // is one less than the maximum array size, which in turn
1120 // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
1121 // smaller than the former type).
1122 // FIXME: Use max_object_size() - 1 here.
1123 r.set (type, wi::zero (TYPE_PRECISION (type)), max - 2);
1124 return true;
1125 }
1126} op_cfn_strlen;
1127
1128
1129// Implement range operator for CFN_BUILT_IN_GOACC_DIM
1130class cfn_goacc_dim : public range_operator
1131{
1132public:
1133 cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; }
1134 using range_operator::fold_range;
1135 virtual bool fold_range (irange &r, tree type, const irange &lh,
1136 const irange &, relation_trio) const
1137 {
1138 tree axis_tree;
1139 if (!lh.singleton_p (result: &axis_tree))
1140 return false;
1141 HOST_WIDE_INT axis = TREE_INT_CST_LOW (axis_tree);
1142 int size = oacc_get_fn_dim_size (fn: current_function_decl, axis);
1143 if (!size)
1144 // If it's dynamic, the backend might know a hardware limitation.
1145 size = targetm.goacc.dim_limit (axis);
1146
1147 r.set (type,
1148 wi::shwi (val: m_is_pos ? 0 : 1, TYPE_PRECISION (type)),
1149 size
1150 ? wi::shwi (val: size - m_is_pos, TYPE_PRECISION (type))
1151 : irange_val_max (type));
1152 return true;
1153 }
1154private:
1155 bool m_is_pos;
1156} op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
1157
1158// Implement range operator for CFN_BUILT_IN_ISINF
1159class cfn_isinf : public range_operator
1160{
1161public:
1162 using range_operator::fold_range;
1163 using range_operator::op1_range;
1164 virtual bool fold_range (irange &r, tree type, const frange &op1,
1165 const irange &, relation_trio) const override
1166 {
1167 if (op1.undefined_p ())
1168 return false;
1169
1170 if (op1.known_isinf ())
1171 {
1172 wide_int one = wi::one (TYPE_PRECISION (type));
1173 r.set (type, one, one);
1174 return true;
1175 }
1176
1177 if (op1.known_isnan ()
1178 || (!real_isinf (&op1.lower_bound ())
1179 && !real_isinf (&op1.upper_bound ())))
1180 {
1181 r.set_zero (type);
1182 return true;
1183 }
1184
1185 r.set_varying (type);
1186 return true;
1187 }
1188 virtual bool op1_range (frange &r, tree type, const irange &lhs,
1189 const frange &, relation_trio) const override
1190 {
1191 if (lhs.undefined_p ())
1192 return false;
1193
1194 if (lhs.zero_p ())
1195 {
1196 nan_state nan (true);
1197 r.set (type, real_min_representable (type),
1198 real_max_representable (type), nan);
1199 return true;
1200 }
1201
1202 if (!range_includes_zero_p (vr: lhs))
1203 {
1204 // The range is [-INF,-INF][+INF,+INF], but it can't be represented.
1205 // Set range to [-INF,+INF]
1206 r.set_varying (type);
1207 r.clear_nan ();
1208 return true;
1209 }
1210
1211 r.set_varying (type);
1212 return true;
1213 }
1214} op_cfn_isinf;
1215
1216//Implement range operator for CFN_BUILT_IN_ISFINITE
1217class cfn_isfinite : public range_operator
1218{
1219public:
1220 using range_operator::fold_range;
1221 using range_operator::op1_range;
1222 virtual bool fold_range (irange &r, tree type, const frange &op1,
1223 const irange &, relation_trio) const override
1224 {
1225 if (op1.undefined_p ())
1226 return false;
1227
1228 if (op1.known_isfinite ())
1229 {
1230 wide_int one = wi::one (TYPE_PRECISION (type));
1231 r.set (type, one, one);
1232 return true;
1233 }
1234
1235 if (op1.known_isnan ()
1236 || op1.known_isinf ())
1237 {
1238 r.set_zero (type);
1239 return true;
1240 }
1241
1242 r.set_varying (type);
1243 return true;
1244 }
1245 virtual bool op1_range (frange &r, tree type, const irange &lhs,
1246 const frange &, relation_trio) const override
1247 {
1248 if (lhs.undefined_p ())
1249 return false;
1250
1251 if (lhs.zero_p ())
1252 {
1253 // The range is [-INF,-INF][+INF,+INF] NAN, but it can't be represented.
1254 // Set range to varying
1255 r.set_varying (type);
1256 return true;
1257 }
1258
1259 if (!range_includes_zero_p (vr: lhs))
1260 {
1261 nan_state nan (false);
1262 r.set (type, real_min_representable (type),
1263 real_max_representable (type), nan);
1264 return true;
1265 }
1266
1267 r.set_varying (type);
1268 return true;
1269 }
1270} op_cfn_isfinite;
1271
1272//Implement range operator for CFN_BUILT_IN_ISNORMAL
1273class cfn_isnormal : public range_operator
1274{
1275public:
1276 using range_operator::fold_range;
1277 using range_operator::op1_range;
1278 virtual bool fold_range (irange &r, tree type, const frange &op1,
1279 const irange &, relation_trio) const override
1280 {
1281 if (op1.undefined_p ())
1282 return false;
1283
1284 if (op1.known_isnormal ())
1285 {
1286 wide_int one = wi::one (TYPE_PRECISION (type));
1287 r.set (type, one, one);
1288 return true;
1289 }
1290
1291 if (op1.known_isnan ()
1292 || op1.known_isinf ()
1293 || op1.known_isdenormal_or_zero ())
1294 {
1295 r.set_zero (type);
1296 return true;
1297 }
1298
1299 r.set_varying (type);
1300 return true;
1301 }
1302 virtual bool op1_range (frange &r, tree type, const irange &lhs,
1303 const frange &, relation_trio) const override
1304 {
1305 if (lhs.undefined_p ())
1306 return false;
1307
1308 if (lhs.zero_p ())
1309 {
1310 r.set_varying (type);
1311 return true;
1312 }
1313
1314 if (!range_includes_zero_p (vr: lhs))
1315 {
1316 nan_state nan (false);
1317 r.set (type, real_min_representable (type),
1318 real_max_representable (type), nan);
1319 return true;
1320 }
1321
1322 r.set_varying (type);
1323 return true;
1324 }
1325} op_cfn_isnormal;
1326
1327// Implement range operator for CFN_BUILT_IN_
1328class cfn_parity : public range_operator
1329{
1330public:
1331 using range_operator::fold_range;
1332 virtual bool fold_range (irange &r, tree type, const irange &,
1333 const irange &, relation_trio) const
1334 {
1335 r = range_true_and_false (type);
1336 return true;
1337 }
1338} op_cfn_parity;
1339
1340// Set up a gimple_range_op_handler for any nonstandard function which can be
1341// supported via range-ops.
1342
1343void
1344gimple_range_op_handler::maybe_non_standard ()
1345{
1346 range_op_handler signed_op (OP_WIDEN_MULT_SIGNED);
1347 gcc_checking_assert (signed_op);
1348 range_op_handler unsigned_op (OP_WIDEN_MULT_UNSIGNED);
1349 gcc_checking_assert (unsigned_op);
1350
1351 if (gimple_code (g: m_stmt) == GIMPLE_ASSIGN)
1352 switch (gimple_assign_rhs_code (gs: m_stmt))
1353 {
1354 case WIDEN_MULT_EXPR:
1355 {
1356 m_op1 = gimple_assign_rhs1 (gs: m_stmt);
1357 m_op2 = gimple_assign_rhs2 (gs: m_stmt);
1358 tree ret = gimple_assign_lhs (gs: m_stmt);
1359 bool signed1 = TYPE_SIGN (TREE_TYPE (m_op1)) == SIGNED;
1360 bool signed2 = TYPE_SIGN (TREE_TYPE (m_op2)) == SIGNED;
1361 bool signed_ret = TYPE_SIGN (TREE_TYPE (ret)) == SIGNED;
1362
1363 /* Normally these operands should all have the same sign, but
1364 some passes and violate this by taking mismatched sign args. At
1365 the moment the only one that's possible is mismatch inputs and
1366 unsigned output. Once ranger supports signs for the operands we
1367 can properly fix it, for now only accept the case we can do
1368 correctly. */
1369 if ((signed1 ^ signed2) && signed_ret)
1370 return;
1371
1372 if (signed2 && !signed1)
1373 std::swap (a&: m_op1, b&: m_op2);
1374
1375 if (signed1 || signed2)
1376 m_operator = signed_op.range_op ();
1377 else
1378 m_operator = unsigned_op.range_op ();
1379 break;
1380 }
1381 default:
1382 break;
1383 }
1384}
1385
1386// Set up a gimple_range_op_handler for any built in function which can be
1387// supported via range-ops.
1388
1389void
1390gimple_range_op_handler::maybe_builtin_call ()
1391{
1392 gcc_checking_assert (is_a <gcall *> (m_stmt));
1393
1394 gcall *call = as_a <gcall *> (p: m_stmt);
1395 combined_fn func = gimple_call_combined_fn (call);
1396 if (func == CFN_LAST)
1397 return;
1398 tree type = gimple_range_type (s: call);
1399 if (!type)
1400 return;
1401 if (!value_range::supports_type_p (type))
1402 return;
1403
1404 switch (func)
1405 {
1406 case CFN_BUILT_IN_CONSTANT_P:
1407 m_op1 = gimple_call_arg (gs: call, index: 0);
1408 if (irange::supports_p (TREE_TYPE (m_op1)))
1409 m_operator = &op_cfn_constant_p;
1410 else if (frange::supports_p (TREE_TYPE (m_op1)))
1411 m_operator = &op_cfn_constant_float_p;
1412 break;
1413
1414 CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
1415 m_op1 = gimple_call_arg (gs: call, index: 0);
1416 m_operator = &op_cfn_signbit;
1417 break;
1418
1419 CASE_FLT_FN (BUILT_IN_ISINF):
1420 m_op1 = gimple_call_arg (gs: call, index: 0);
1421 m_operator = &op_cfn_isinf;
1422 break;
1423
1424 case CFN_BUILT_IN_ISFINITE:
1425 m_op1 = gimple_call_arg (gs: call, index: 0);
1426 m_operator = &op_cfn_isfinite;
1427 break;
1428
1429 case CFN_BUILT_IN_ISNORMAL:
1430 m_op1 = gimple_call_arg (gs: call, index: 0);
1431 m_operator = &op_cfn_isnormal;
1432 break;
1433
1434 CASE_CFN_COPYSIGN_ALL:
1435 m_op1 = gimple_call_arg (gs: call, index: 0);
1436 m_op2 = gimple_call_arg (gs: call, index: 1);
1437 m_operator = &op_cfn_copysign;
1438 break;
1439
1440 CASE_CFN_SQRT:
1441 CASE_CFN_SQRT_FN:
1442 m_op1 = gimple_call_arg (gs: call, index: 0);
1443 m_operator = &op_cfn_sqrt;
1444 break;
1445
1446 CASE_CFN_SIN:
1447 CASE_CFN_SIN_FN:
1448 m_op1 = gimple_call_arg (gs: call, index: 0);
1449 m_operator = &op_cfn_sin;
1450 break;
1451
1452 CASE_CFN_COS:
1453 CASE_CFN_COS_FN:
1454 m_op1 = gimple_call_arg (gs: call, index: 0);
1455 m_operator = &op_cfn_cos;
1456 break;
1457
1458 case CFN_BUILT_IN_TOUPPER:
1459 case CFN_BUILT_IN_TOLOWER:
1460 // Only proceed If the argument is compatible with the LHS.
1461 m_op1 = gimple_call_arg (gs: call, index: 0);
1462 if (range_compatible_p (type1: type, TREE_TYPE (m_op1)))
1463 m_operator = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower
1464 : &op_cfn_toupper;
1465 break;
1466
1467 CASE_CFN_FFS:
1468 m_op1 = gimple_call_arg (gs: call, index: 0);
1469 m_operator = &op_cfn_ffs;
1470 break;
1471
1472 CASE_CFN_POPCOUNT:
1473 m_op1 = gimple_call_arg (gs: call, index: 0);
1474 m_operator = &op_cfn_popcount;
1475 break;
1476
1477 CASE_CFN_CLZ:
1478 m_op1 = gimple_call_arg (gs: call, index: 0);
1479 if (gimple_call_internal_p (gs: call)
1480 && gimple_call_num_args (gs: call) == 2)
1481 {
1482 m_op2 = gimple_call_arg (gs: call, index: 1);
1483 m_operator = &op_cfn_clz_internal;
1484 }
1485 else
1486 m_operator = &op_cfn_clz;
1487 break;
1488
1489 CASE_CFN_CTZ:
1490 m_op1 = gimple_call_arg (gs: call, index: 0);
1491 if (gimple_call_internal_p (gs: call)
1492 && gimple_call_num_args (gs: call) == 2)
1493 {
1494 m_op2 = gimple_call_arg (gs: call, index: 1);
1495 m_operator = &op_cfn_ctz_internal;
1496 }
1497 else
1498 m_operator = &op_cfn_ctz;
1499 break;
1500
1501 CASE_CFN_CLRSB:
1502 m_op1 = gimple_call_arg (gs: call, index: 0);
1503 m_operator = &op_cfn_clrsb;
1504 break;
1505
1506 case CFN_UBSAN_CHECK_ADD:
1507 m_op1 = gimple_call_arg (gs: call, index: 0);
1508 m_op2 = gimple_call_arg (gs: call, index: 1);
1509 m_operator = &op_cfn_ubsan_add;
1510 break;
1511
1512 case CFN_UBSAN_CHECK_SUB:
1513 m_op1 = gimple_call_arg (gs: call, index: 0);
1514 m_op2 = gimple_call_arg (gs: call, index: 1);
1515 m_operator = &op_cfn_ubsan_sub;
1516 break;
1517
1518 case CFN_UBSAN_CHECK_MUL:
1519 m_op1 = gimple_call_arg (gs: call, index: 0);
1520 m_op2 = gimple_call_arg (gs: call, index: 1);
1521 m_operator = &op_cfn_ubsan_mul;
1522 break;
1523
1524 case CFN_BUILT_IN_STRLEN:
1525 {
1526 tree lhs = gimple_call_lhs (gs: call);
1527 if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node)
1528 == TYPE_PRECISION (TREE_TYPE (lhs))))
1529 {
1530 m_op1 = gimple_call_arg (gs: call, index: 0);
1531 m_operator = &op_cfn_strlen;
1532 }
1533 break;
1534 }
1535
1536 // Optimizing these two internal functions helps the loop
1537 // optimizer eliminate outer comparisons. Size is [1,N]
1538 // and pos is [0,N-1].
1539 case CFN_GOACC_DIM_SIZE:
1540 // This call will ensure all the asserts are triggered.
1541 oacc_get_ifn_dim_arg (stmt: call);
1542 m_op1 = gimple_call_arg (gs: call, index: 0);
1543 m_operator = &op_cfn_goacc_dim_size;
1544 break;
1545
1546 case CFN_GOACC_DIM_POS:
1547 // This call will ensure all the asserts are triggered.
1548 oacc_get_ifn_dim_arg (stmt: call);
1549 m_op1 = gimple_call_arg (gs: call, index: 0);
1550 m_operator = &op_cfn_goacc_dim_pos;
1551 break;
1552
1553 CASE_CFN_PARITY:
1554 m_operator = &op_cfn_parity;
1555 break;
1556
1557 default:
1558 {
1559 unsigned arg;
1560 if (gimple_call_fnspec (stmt: call).returns_arg (arg_no: &arg) && arg == 0)
1561 {
1562 m_op1 = gimple_call_arg (gs: call, index: 0);
1563 m_operator = &op_cfn_pass_through_arg1;
1564 }
1565 break;
1566 }
1567 }
1568}
1569

source code of gcc/gimple-range-op.cc