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