Branch data Line data Source code
1 : : /* Code for GIMPLE range op related routines.
2 : : Copyright (C) 2019-2024 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 : 239134385 : gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt)
55 : : {
56 : 239134385 : tree ssa;
57 : 239134385 : int count = 0;
58 : :
59 : 239134385 : gimple_range_op_handler handler (stmt);
60 : 239134385 : if (handler)
61 : : {
62 : 62101372 : gcc_checking_assert (vec_size >= 2);
63 : 62101372 : if ((ssa = gimple_range_ssa_p (handler.operand1 ())))
64 : 53609247 : vec[count++] = ssa;
65 : 62101372 : if ((ssa = gimple_range_ssa_p (handler.operand2 ())))
66 : 15051599 : vec[count++] = ssa;
67 : : }
68 : 177033013 : else if (is_a<gassign *> (stmt)
69 : 177033013 : && gimple_assign_rhs_code (stmt) == COND_EXPR)
70 : : {
71 : 41097 : gcc_checking_assert (vec_size >= 3);
72 : 41097 : gassign *st = as_a<gassign *> (stmt);
73 : 41097 : if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st))))
74 : 41097 : vec[count++] = ssa;
75 : 82194 : if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st))))
76 : 34563 : vec[count++] = ssa;
77 : 82194 : if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st))))
78 : 20886 : vec[count++] = ssa;
79 : : }
80 : 239134385 : return count;
81 : : }
82 : :
83 : : // Return the base of the RHS of an assignment.
84 : :
85 : : static tree
86 : 248374929 : gimple_range_base_of_assignment (const gimple *stmt)
87 : : {
88 : 248374929 : gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
89 : 248374929 : tree op1 = gimple_assign_rhs1 (stmt);
90 : 248374929 : if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
91 : 3273122 : 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 : 999389777 : get_code (gimple *s)
99 : : {
100 : 999389777 : if (const gassign *ass = dyn_cast<const gassign *> (s))
101 : 759085703 : return gimple_assign_rhs_code (ass);
102 : 471199330 : if (const gcond *cond = dyn_cast<const gcond *> (s))
103 : 305020158 : 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 : 302834964 : gimple_range_op_handler::supported_p (gimple *s)
111 : : {
112 : 302834964 : enum tree_code code = get_code (s);
113 : 302834964 : if (range_op_handler (code))
114 : : return true;
115 : 90511703 : if (is_a <gcall *> (s) && gimple_range_op_handler (s))
116 : 570490 : return true;
117 : : return false;
118 : : }
119 : :
120 : : // Construct a handler object for statement S.
121 : :
122 : 696554813 : gimple_range_op_handler::gimple_range_op_handler (gimple *s)
123 : : {
124 : 696554813 : range_op_handler oper (get_code (s));
125 : 696554813 : m_stmt = s;
126 : 696554813 : m_op1 = NULL_TREE;
127 : 696554813 : m_op2 = NULL_TREE;
128 : :
129 : 696554813 : if (oper)
130 : 407561897 : switch (gimple_code (m_stmt))
131 : : {
132 : 159186968 : case GIMPLE_COND:
133 : 159186968 : m_op1 = gimple_cond_lhs (m_stmt);
134 : 159186968 : m_op2 = gimple_cond_rhs (m_stmt);
135 : : // Check that operands are supported types. One check is enough.
136 : 159186968 : if (Value_Range::supports_type_p (TREE_TYPE (m_op1)))
137 : 159107359 : m_operator = oper.range_op ();
138 : 159186968 : gcc_checking_assert (m_operator);
139 : 407561897 : return;
140 : 248374929 : case GIMPLE_ASSIGN:
141 : 248374929 : m_op1 = gimple_range_base_of_assignment (m_stmt);
142 : 248374929 : 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 : 3081224 : tree ssa = TREE_OPERAND (m_op1, 0);
150 : 3081224 : if (TREE_CODE (ssa) == SSA_NAME)
151 : 3081202 : m_op1 = ssa;
152 : : }
153 : 248374929 : if (gimple_num_ops (m_stmt) >= 3)
154 : 175508321 : m_op2 = gimple_assign_rhs2 (m_stmt);
155 : : // Check that operands are supported types. One check is enough.
156 : 248374929 : if ((m_op1 && !Value_Range::supports_type_p (TREE_TYPE (m_op1))))
157 : : return;
158 : 248121642 : m_operator = oper.range_op ();
159 : 248121642 : gcc_checking_assert (m_operator);
160 : : return;
161 : 0 : default:
162 : 0 : gcc_unreachable ();
163 : : return;
164 : : }
165 : : // If no range-op table entry handled this stmt, check for other supported
166 : : // statements.
167 : 288992916 : if (is_a <gcall *> (m_stmt))
168 : 57057093 : maybe_builtin_call ();
169 : : else
170 : 231935823 : maybe_non_standard ();
171 : 288992916 : 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 : :
178 : : bool
179 : 0 : gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range)
180 : : {
181 : 0 : gcc_checking_assert (gimple_num_ops (m_stmt) < 3);
182 : : // Give up on empty ranges.
183 : 0 : if (lhs_range.undefined_p ())
184 : : return false;
185 : :
186 : : // Unary operations require the type of the first operand in the
187 : : // second range position.
188 : 0 : tree type = TREE_TYPE (operand1 ());
189 : 0 : Value_Range type_range (type);
190 : 0 : type_range.set_varying (type);
191 : 0 : return op1_range (r, type, lhs_range, type_range);
192 : 0 : }
193 : :
194 : : // Calculate what we can determine of the range of this statement's
195 : : // first operand if the lhs of the expression has the range LHS_RANGE
196 : : // and the second operand has the range OP2_RANGE. Return false if
197 : : // nothing can be determined.
198 : :
199 : : bool
200 : 61841092 : gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
201 : : const vrange &op2_range, relation_trio k)
202 : : {
203 : : // Give up on empty ranges.
204 : 61841092 : if (lhs_range.undefined_p ())
205 : : return false;
206 : :
207 : : // Unary operation are allowed to pass a range in for second operand
208 : : // as there are often additional restrictions beyond the type which
209 : : // can be imposed. See operator_cast::op1_range().
210 : 61841092 : tree type = TREE_TYPE (operand1 ());
211 : : // If op2 is undefined, solve as if it is varying.
212 : 61841092 : if (op2_range.undefined_p ())
213 : : {
214 : 7513 : if (gimple_num_ops (m_stmt) < 3)
215 : : return false;
216 : 6060 : tree op2_type;
217 : : // This is sometimes invoked on single operand stmts.
218 : 6060 : if (operand2 ())
219 : 6046 : op2_type = TREE_TYPE (operand2 ());
220 : : else
221 : 14 : op2_type = TREE_TYPE (operand1 ());
222 : 6060 : Value_Range trange (op2_type);
223 : 6060 : trange.set_varying (op2_type);
224 : 6060 : return op1_range (r, type, lhs_range, trange, k);
225 : 6060 : }
226 : 61833579 : return op1_range (r, type, lhs_range, op2_range, k);
227 : : }
228 : :
229 : : // Calculate what we can determine of the range of this statement's
230 : : // second operand if the lhs of the expression has the range LHS_RANGE
231 : : // and the first operand has the range OP1_RANGE. Return false if
232 : : // nothing can be determined.
233 : :
234 : : bool
235 : 17378467 : gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
236 : : const vrange &op1_range, relation_trio k)
237 : : {
238 : : // Give up on empty ranges.
239 : 17378467 : if (lhs_range.undefined_p ())
240 : : return false;
241 : :
242 : 17378467 : tree type = TREE_TYPE (operand2 ());
243 : : // If op1 is undefined, solve as if it is varying.
244 : 17378467 : if (op1_range.undefined_p ())
245 : : {
246 : 7169 : tree op1_type = TREE_TYPE (operand1 ());
247 : 7169 : Value_Range trange (op1_type);
248 : 7169 : trange.set_varying (op1_type);
249 : 7169 : return op2_range (r, type, lhs_range, trange, k);
250 : 7169 : }
251 : 17371298 : return op2_range (r, type, lhs_range, op1_range, k);
252 : : }
253 : :
254 : : // --------------------------------------------------------------------
255 : :
256 : : // Implement range operator for float CFN_BUILT_IN_CONSTANT_P.
257 : : class cfn_constant_float_p : public range_operator
258 : : {
259 : : public:
260 : : using range_operator::fold_range;
261 : 144 : virtual bool fold_range (irange &r, tree type, const frange &lh,
262 : : const irange &, relation_trio) const
263 : : {
264 : 144 : if (lh.singleton_p ())
265 : : {
266 : 0 : wide_int one = wi::one (TYPE_PRECISION (type));
267 : 0 : r.set (type, one, one);
268 : 0 : return true;
269 : 0 : }
270 : 144 : if (cfun->after_inlining)
271 : : {
272 : 54 : r.set_zero (type);
273 : 54 : return true;
274 : : }
275 : : return false;
276 : : }
277 : : } op_cfn_constant_float_p;
278 : :
279 : : // Implement range operator for integral CFN_BUILT_IN_CONSTANT_P.
280 : : class cfn_constant_p : public range_operator
281 : : {
282 : : public:
283 : : using range_operator::fold_range;
284 : 40550 : virtual bool fold_range (irange &r, tree type, const irange &lh,
285 : : const irange &, relation_trio) const
286 : : {
287 : 40550 : if (lh.singleton_p ())
288 : : {
289 : 61 : wide_int one = wi::one (TYPE_PRECISION (type));
290 : 61 : r.set (type, one, one);
291 : 61 : return true;
292 : 61 : }
293 : 40489 : if (cfun->after_inlining)
294 : : {
295 : 31560 : r.set_zero (type);
296 : 31560 : return true;
297 : : }
298 : : return false;
299 : : }
300 : : } op_cfn_constant_p;
301 : :
302 : : // Implement range operator for integral/pointer functions returning
303 : : // the first argument.
304 : : class cfn_pass_through_arg1 : public range_operator
305 : : {
306 : : public:
307 : : using range_operator::fold_range;
308 : : using range_operator::op1_range;
309 : 297785 : virtual bool fold_range (irange &r, tree, const irange &lh,
310 : : const irange &, relation_trio) const
311 : : {
312 : 297785 : r = lh;
313 : 297785 : return true;
314 : : }
315 : 226949 : virtual bool op1_range (irange &r, tree, const irange &lhs,
316 : : const irange &, relation_trio) const
317 : : {
318 : 226949 : r = lhs;
319 : 226949 : return true;
320 : : }
321 : : } op_cfn_pass_through_arg1;
322 : :
323 : : // Implement range operator for CFN_BUILT_IN_SIGNBIT.
324 : : class cfn_signbit : public range_operator
325 : : {
326 : : public:
327 : : using range_operator::fold_range;
328 : : using range_operator::op1_range;
329 : 40499 : virtual bool fold_range (irange &r, tree type, const frange &lh,
330 : : const irange &, relation_trio) const override
331 : : {
332 : 40499 : bool signbit;
333 : 40499 : if (lh.signbit_p (signbit))
334 : : {
335 : 251 : if (signbit)
336 : 158 : r.set_nonzero (type);
337 : : else
338 : 93 : r.set_zero (type);
339 : 251 : return true;
340 : : }
341 : : return false;
342 : : }
343 : 13291 : virtual bool op1_range (frange &r, tree type, const irange &lhs,
344 : : const frange &, relation_trio) const override
345 : : {
346 : 13291 : if (lhs.zero_p ())
347 : : {
348 : 8478 : r.set (type, dconst0, frange_val_max (type));
349 : 8478 : r.update_nan (false);
350 : 8478 : return true;
351 : : }
352 : 4813 : if (!lhs.contains_p (wi::zero (TYPE_PRECISION (lhs.type ()))))
353 : : {
354 : 4813 : r.set (type, frange_val_min (type), dconstm0);
355 : 4813 : r.update_nan (true);
356 : 4813 : return true;
357 : : }
358 : : return false;
359 : : }
360 : : } op_cfn_signbit;
361 : :
362 : : // Implement range operator for CFN_BUILT_IN_COPYSIGN
363 : : class cfn_copysign : public range_operator
364 : : {
365 : : public:
366 : : using range_operator::fold_range;
367 : 156456 : virtual bool fold_range (frange &r, tree type, const frange &lh,
368 : : const frange &rh, relation_trio) const override
369 : : {
370 : 156456 : frange neg;
371 : 156456 : if (!range_op_handler (ABS_EXPR).fold_range (r, type, lh, frange (type)))
372 : : return false;
373 : 156456 : if (!range_op_handler (NEGATE_EXPR).fold_range (neg, type, r,
374 : 156456 : frange (type)))
375 : : return false;
376 : :
377 : 156456 : bool signbit;
378 : 156456 : if (rh.signbit_p (signbit))
379 : : {
380 : : // If the sign is negative, flip the result from ABS,
381 : : // otherwise leave things positive.
382 : 363 : if (signbit)
383 : 359 : r = neg;
384 : : }
385 : : else
386 : : // If the sign is unknown, keep the positive and negative
387 : : // alternatives.
388 : 156093 : r.union_ (neg);
389 : : return true;
390 : : }
391 : : } op_cfn_copysign;
392 : :
393 : : /* Compute FUNC (ARG) where FUNC is a mpfr function. If RES_LOW is non-NULL,
394 : : set it to low bound of possible range if the function is expected to have
395 : : ULPS precision and similarly if RES_HIGH is non-NULL, set it to high bound.
396 : : If the function returns false, the results weren't set. */
397 : :
398 : : static bool
399 : 42546 : frange_mpfr_arg1 (REAL_VALUE_TYPE *res_low, REAL_VALUE_TYPE *res_high,
400 : : int (*func) (mpfr_ptr, mpfr_srcptr, mpfr_rnd_t),
401 : : const REAL_VALUE_TYPE &arg, tree type, unsigned ulps)
402 : : {
403 : 42546 : if (ulps == ~0U || !real_isfinite (&arg))
404 : 30385 : return false;
405 : 12161 : machine_mode mode = TYPE_MODE (type);
406 : 12161 : const real_format *format = REAL_MODE_FORMAT (mode);
407 : 12161 : auto_mpfr m (format->p);
408 : 12161 : mpfr_from_real (m, &arg, MPFR_RNDN);
409 : 12161 : mpfr_clear_flags ();
410 : 12161 : bool inexact = func (m, m, MPFR_RNDN);
411 : 12161 : if (!mpfr_number_p (m) || mpfr_overflow_p () || mpfr_underflow_p ())
412 : 668 : return false;
413 : :
414 : 11493 : REAL_VALUE_TYPE value, result;
415 : 11493 : real_from_mpfr (&value, m, format, MPFR_RNDN);
416 : 11493 : if (!real_isfinite (&value))
417 : : return false;
418 : 11493 : if ((value.cl == rvc_zero) != (mpfr_zero_p (m) != 0))
419 : 0 : inexact = true;
420 : :
421 : 11493 : real_convert (&result, format, &value);
422 : 11493 : if (!real_isfinite (&result))
423 : : return false;
424 : 11493 : bool round_low = false;
425 : 11493 : bool round_high = false;
426 : 11493 : if (!ulps && flag_rounding_math)
427 : 0 : ++ulps;
428 : 11493 : if (inexact || !real_identical (&result, &value))
429 : : {
430 : 14665 : if (MODE_COMPOSITE_P (mode))
431 : : round_low = round_high = true;
432 : : else
433 : : {
434 : 2095 : round_low = !real_less (&result, &value);
435 : 2095 : round_high = !real_less (&value, &result);
436 : : }
437 : : }
438 : 11493 : if (res_low)
439 : : {
440 : 9805 : *res_low = result;
441 : 10574 : for (unsigned int i = 0; i < ulps + round_low; ++i)
442 : 769 : frange_nextafter (mode, *res_low, dconstninf);
443 : : }
444 : 11493 : if (res_high)
445 : : {
446 : 2056 : *res_high = result;
447 : 4178 : for (unsigned int i = 0; i < ulps + round_high; ++i)
448 : 2122 : frange_nextafter (mode, *res_high, dconstinf);
449 : : }
450 : : return true;
451 : 12161 : }
452 : :
453 : : class cfn_sqrt : public range_operator
454 : : {
455 : : public:
456 : : using range_operator::fold_range;
457 : : using range_operator::op1_range;
458 : 28109 : virtual bool fold_range (frange &r, tree type,
459 : : const frange &lh, const frange &,
460 : : relation_trio) const final override
461 : : {
462 : 28109 : if (lh.undefined_p ())
463 : : return false;
464 : 27952 : if (lh.known_isnan () || real_less (&lh.upper_bound (), &dconstm0))
465 : : {
466 : 6729 : r.set_nan (type);
467 : 6729 : return true;
468 : : }
469 : 21223 : unsigned bulps
470 : 21223 : = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true);
471 : 21223 : if (bulps == ~0U)
472 : 0 : r.set_varying (type);
473 : 21223 : else if (bulps == 0)
474 : 21223 : r.set (type, dconstm0, dconstinf);
475 : : else
476 : : {
477 : 0 : REAL_VALUE_TYPE boundmin = dconstm0;
478 : 0 : while (bulps--)
479 : 0 : frange_nextafter (TYPE_MODE (type), boundmin, dconstninf);
480 : 0 : r.set (type, boundmin, dconstinf);
481 : : }
482 : 22856 : if (!lh.maybe_isnan () && !real_less (&lh.lower_bound (), &dconst0))
483 : 658 : r.clear_nan ();
484 : :
485 : 21223 : unsigned ulps
486 : 21223 : = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false);
487 : 21223 : if (ulps == ~0U)
488 : : return true;
489 : 21089 : REAL_VALUE_TYPE lb = lh.lower_bound ();
490 : 21089 : REAL_VALUE_TYPE ub = lh.upper_bound ();
491 : 21089 : if (!frange_mpfr_arg1 (&lb, NULL, mpfr_sqrt, lb, type, ulps))
492 : 11652 : lb = dconstninf;
493 : 21089 : if (!frange_mpfr_arg1 (NULL, &ub, mpfr_sqrt, ub, type, ulps))
494 : 19401 : ub = dconstinf;
495 : 21089 : frange r2;
496 : 21089 : r2.set (type, lb, ub);
497 : 21089 : r2.flush_denormals_to_zero ();
498 : 21089 : r.intersect (r2);
499 : 21089 : return true;
500 : : }
501 : 763 : virtual bool op1_range (frange &r, tree type,
502 : : const frange &lhs, const frange &,
503 : : relation_trio) const final override
504 : : {
505 : 763 : if (lhs.undefined_p ())
506 : : return false;
507 : :
508 : : // A known NAN means the input is [-INF,-0.) U +-NAN.
509 : 763 : if (lhs.known_isnan ())
510 : : {
511 : 0 : known_nan:
512 : 0 : REAL_VALUE_TYPE ub = dconstm0;
513 : 0 : frange_nextafter (TYPE_MODE (type), ub, dconstninf);
514 : 0 : r.set (type, dconstninf, ub);
515 : : // No r.flush_denormals_to_zero (); here - it is a reverse op.
516 : 0 : return true;
517 : : }
518 : :
519 : : // Results outside of [-0.0, +Inf] are impossible.
520 : 763 : unsigned bulps
521 : 763 : = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), true);
522 : 763 : if (bulps != ~0U)
523 : : {
524 : 763 : const REAL_VALUE_TYPE &ub = lhs.upper_bound ();
525 : 763 : REAL_VALUE_TYPE m0 = dconstm0;
526 : 763 : while (bulps--)
527 : 0 : frange_nextafter (TYPE_MODE (type), m0, dconstninf);
528 : 763 : if (real_less (&ub, &m0))
529 : : {
530 : 0 : if (!lhs.maybe_isnan ())
531 : 0 : r.set_undefined ();
532 : : else
533 : : // If lhs could be NAN and finite result is impossible,
534 : : // the range is like lhs.known_isnan () above.
535 : 0 : goto known_nan;
536 : 0 : return true;
537 : : }
538 : : }
539 : :
540 : 1013 : if (!lhs.maybe_isnan ())
541 : : // If NAN is not valid result, the input cannot include either
542 : : // a NAN nor values smaller than -0.
543 : 250 : r.set (type, dconstm0, dconstinf, nan_state (false, false));
544 : : else
545 : 513 : r.set_varying (type);
546 : :
547 : 763 : unsigned ulps
548 : 763 : = targetm.libm_function_max_error (CFN_SQRT, TYPE_MODE (type), false);
549 : 763 : if (ulps == ~0U)
550 : : return true;
551 : 763 : REAL_VALUE_TYPE lb = lhs.lower_bound ();
552 : 763 : REAL_VALUE_TYPE ub = lhs.upper_bound ();
553 : 1013 : if (!lhs.maybe_isnan () && real_less (&dconst0, &lb))
554 : : {
555 : 129 : for (unsigned i = 0; i < ulps; ++i)
556 : 0 : frange_nextafter (TYPE_MODE (type), lb, dconstninf);
557 : 129 : if (real_less (&dconst0, &lb))
558 : : {
559 : 129 : REAL_VALUE_TYPE op = lb;
560 : 129 : frange_arithmetic (MULT_EXPR, type, lb, op, op, dconstninf);
561 : : }
562 : : else
563 : 0 : lb = dconstninf;
564 : : }
565 : : else
566 : 634 : lb = dconstninf;
567 : 763 : if (real_isfinite (&ub) && real_less (&dconst0, &ub))
568 : : {
569 : 265 : for (unsigned i = 0; i < ulps; ++i)
570 : 0 : frange_nextafter (TYPE_MODE (type), ub, dconstinf);
571 : 265 : if (real_isfinite (&ub))
572 : : {
573 : 265 : REAL_VALUE_TYPE op = ub;
574 : 265 : frange_arithmetic (MULT_EXPR, type, ub, op, op, dconstinf);
575 : : }
576 : : else
577 : 0 : ub = dconstinf;
578 : : }
579 : : else
580 : 498 : ub = dconstinf;
581 : 763 : frange r2;
582 : 763 : r2.set (type, lb, ub);
583 : 763 : r.intersect (r2);
584 : 763 : return true;
585 : : }
586 : : } op_cfn_sqrt;
587 : :
588 : : class cfn_sincos : public range_operator
589 : : {
590 : : public:
591 : : using range_operator::fold_range;
592 : : using range_operator::op1_range;
593 : : cfn_sincos (combined_fn cfn) { m_cfn = cfn; }
594 : 12481 : virtual bool fold_range (frange &r, tree type,
595 : : const frange &lh, const frange &,
596 : : relation_trio) const final override
597 : : {
598 : 12481 : if (lh.undefined_p ())
599 : : return false;
600 : 12465 : if (lh.known_isnan () || lh.known_isinf ())
601 : : {
602 : 0 : r.set_nan (type);
603 : 0 : return true;
604 : : }
605 : 12465 : unsigned bulps = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type),
606 : : true);
607 : 12465 : if (bulps == ~0U)
608 : 0 : r.set_varying (type);
609 : 12465 : else if (bulps == 0)
610 : 12413 : r.set (type, dconstm1, dconst1);
611 : : else
612 : : {
613 : 52 : REAL_VALUE_TYPE boundmin, boundmax;
614 : 52 : boundmax = dconst1;
615 : 104 : while (bulps--)
616 : 52 : frange_nextafter (TYPE_MODE (type), boundmax, dconstinf);
617 : 52 : real_arithmetic (&boundmin, NEGATE_EXPR, &boundmax, NULL);
618 : 52 : r.set (type, boundmin, boundmax);
619 : : }
620 : 14032 : if (!lh.maybe_isnan () && !lh.maybe_isinf ())
621 : 135 : r.clear_nan ();
622 : :
623 : 12465 : unsigned ulps
624 : 12465 : = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type), false);
625 : 12465 : if (ulps == ~0U)
626 : : return true;
627 : 12465 : REAL_VALUE_TYPE lb = lh.lower_bound ();
628 : 12465 : REAL_VALUE_TYPE ub = lh.upper_bound ();
629 : 12465 : REAL_VALUE_TYPE diff;
630 : 12465 : real_arithmetic (&diff, MINUS_EXPR, &ub, &lb);
631 : 12465 : if (!real_isfinite (&diff))
632 : : return true;
633 : 719 : REAL_VALUE_TYPE pi = dconst_pi ();
634 : 719 : REAL_VALUE_TYPE pix2;
635 : 719 : real_arithmetic (&pix2, PLUS_EXPR, &pi, &pi);
636 : : // We can only try to narrow the range further if ub-lb < 2*pi.
637 : 719 : if (!real_less (&diff, &pix2))
638 : : return true;
639 : 92 : REAL_VALUE_TYPE lb_lo, lb_hi, ub_lo, ub_hi;
640 : 92 : REAL_VALUE_TYPE lb_deriv_lo, lb_deriv_hi, ub_deriv_lo, ub_deriv_hi;
641 : 92 : if (!frange_mpfr_arg1 (&lb_lo, &lb_hi,
642 : 92 : m_cfn == CFN_SIN ? mpfr_sin : mpfr_cos, lb,
643 : : type, ulps)
644 : 92 : || !frange_mpfr_arg1 (&ub_lo, &ub_hi,
645 : 92 : m_cfn == CFN_SIN ? mpfr_sin : mpfr_cos, ub,
646 : : type, ulps)
647 : 92 : || !frange_mpfr_arg1 (&lb_deriv_lo, &lb_deriv_hi,
648 : 92 : m_cfn == CFN_SIN ? mpfr_cos : mpfr_sin, lb,
649 : : type, 0)
650 : 184 : || !frange_mpfr_arg1 (&ub_deriv_lo, &ub_deriv_hi,
651 : 92 : m_cfn == CFN_SIN ? mpfr_cos : mpfr_sin, ub,
652 : : type, 0))
653 : 0 : return true;
654 : 92 : if (m_cfn == CFN_COS)
655 : : {
656 : : // Derivative of cos is -sin, so negate.
657 : 29 : lb_deriv_lo.sign ^= 1;
658 : 29 : lb_deriv_hi.sign ^= 1;
659 : 29 : ub_deriv_lo.sign ^= 1;
660 : 29 : ub_deriv_hi.sign ^= 1;
661 : : }
662 : :
663 : 92 : if (real_less (&lb_lo, &ub_lo))
664 : 26 : lb = lb_lo;
665 : : else
666 : 66 : lb = ub_lo;
667 : 92 : if (real_less (&lb_hi, &ub_hi))
668 : 26 : ub = ub_hi;
669 : : else
670 : 66 : ub = lb_hi;
671 : :
672 : : // The range between the function result on the boundaries may need
673 : : // to be extended to +1 (+Inf) or -1 (-Inf) or both depending on the
674 : : // derivative or length of the argument range (diff).
675 : :
676 : : // First handle special case, where the derivative has different signs,
677 : : // so the bound must be roughly -1 or +1.
678 : 92 : if (real_isneg (&lb_deriv_lo) != real_isneg (&lb_deriv_hi))
679 : : {
680 : 0 : if (real_isneg (&lb_lo))
681 : 0 : lb = dconstninf;
682 : : else
683 : 0 : ub = dconstinf;
684 : : }
685 : 92 : if (real_isneg (&ub_deriv_lo) != real_isneg (&ub_deriv_hi))
686 : : {
687 : 0 : if (real_isneg (&ub_lo))
688 : 0 : lb = dconstninf;
689 : : else
690 : 0 : ub = dconstinf;
691 : : }
692 : :
693 : : // If derivative at lower_bound and upper_bound have the same sign,
694 : : // the function grows or declines on the whole range if diff < pi, so
695 : : // [lb, ub] is correct, and if diff >= pi the result range must include
696 : : // both the minimum and maximum.
697 : 92 : if (real_isneg (&lb_deriv_lo) == real_isneg (&ub_deriv_lo))
698 : : {
699 : 58 : if (!real_less (&diff, &pi))
700 : : return true;
701 : : }
702 : : // If function declines at lower_bound and grows at upper_bound,
703 : : // the result range must include the minimum, so set lb to -Inf.
704 : 34 : else if (real_isneg (&lb_deriv_lo))
705 : 0 : lb = dconstninf;
706 : : // If function grows at lower_bound and declines at upper_bound,
707 : : // the result range must include the maximum, so set ub to +Inf.
708 : : else
709 : 34 : ub = dconstinf;
710 : 92 : frange r2;
711 : 92 : r2.set (type, lb, ub);
712 : 92 : r2.flush_denormals_to_zero ();
713 : 92 : r.intersect (r2);
714 : 92 : return true;
715 : : }
716 : 3177 : virtual bool op1_range (frange &r, tree type,
717 : : const frange &lhs, const frange &,
718 : : relation_trio) const final override
719 : : {
720 : 3177 : if (lhs.undefined_p ())
721 : : return false;
722 : :
723 : : // A known NAN means the input is [-INF,-INF][+INF,+INF] U +-NAN,
724 : : // which we can't currently represent.
725 : 3177 : if (lhs.known_isnan ())
726 : : {
727 : 0 : r.set_varying (type);
728 : 0 : return true;
729 : : }
730 : :
731 : : // Results outside of [-1.0, +1.0] are impossible.
732 : 3177 : unsigned bulps
733 : 3177 : = targetm.libm_function_max_error (m_cfn, TYPE_MODE (type), true);
734 : 3177 : if (bulps != ~0U)
735 : : {
736 : 3177 : const REAL_VALUE_TYPE &lb = lhs.lower_bound ();
737 : 3177 : const REAL_VALUE_TYPE &ub = lhs.upper_bound ();
738 : 3177 : REAL_VALUE_TYPE m1 = dconstm1;
739 : 3177 : REAL_VALUE_TYPE p1 = dconst1;
740 : 3177 : while (bulps--)
741 : : {
742 : 0 : frange_nextafter (TYPE_MODE (type), m1, dconstninf);
743 : 0 : frange_nextafter (TYPE_MODE (type), p1, dconstinf);
744 : : }
745 : 3177 : if (real_less (&ub, &m1) || real_less (&p1, &lb))
746 : : {
747 : 0 : if (!lhs.maybe_isnan ())
748 : 0 : r.set_undefined ();
749 : : else
750 : : /* If lhs could be NAN and finite result is impossible,
751 : : the range is like lhs.known_isnan () above,
752 : : [-INF,-INF][+INF,+INF] U +-NAN. */
753 : 0 : r.set_varying (type);
754 : 0 : return true;
755 : : }
756 : : }
757 : :
758 : 4411 : if (!lhs.maybe_isnan ())
759 : : {
760 : : // If NAN is not valid result, the input cannot include either
761 : : // a NAN nor a +-INF.
762 : 1234 : REAL_VALUE_TYPE lb = real_min_representable (type);
763 : 1234 : REAL_VALUE_TYPE ub = real_max_representable (type);
764 : 1234 : r.set (type, lb, ub, nan_state (false, false));
765 : : }
766 : : else
767 : 1943 : r.set_varying (type);
768 : : return true;
769 : : }
770 : : private:
771 : : combined_fn m_cfn;
772 : : } op_cfn_sin (CFN_SIN), op_cfn_cos (CFN_COS);
773 : :
774 : : // Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
775 : : class cfn_toupper_tolower : public range_operator
776 : : {
777 : : public:
778 : : using range_operator::fold_range;
779 : : cfn_toupper_tolower (bool toupper) { m_toupper = toupper; }
780 : : virtual bool fold_range (irange &r, tree type, const irange &lh,
781 : : const irange &, relation_trio) const;
782 : : private:
783 : : bool get_letter_range (tree type, irange &lowers, irange &uppers) const;
784 : : bool m_toupper;
785 : : } op_cfn_toupper (true), op_cfn_tolower (false);
786 : :
787 : : // Return TRUE if we recognize the target character set and return the
788 : : // range for lower case and upper case letters.
789 : :
790 : : bool
791 : 9286 : cfn_toupper_tolower::get_letter_range (tree type, irange &lowers,
792 : : irange &uppers) const
793 : : {
794 : : // ASCII
795 : 9286 : int a = lang_hooks.to_target_charset ('a');
796 : 9286 : int z = lang_hooks.to_target_charset ('z');
797 : 9286 : int A = lang_hooks.to_target_charset ('A');
798 : 9286 : int Z = lang_hooks.to_target_charset ('Z');
799 : :
800 : 9286 : if ((z - a == 25) && (Z - A == 25))
801 : : {
802 : 18572 : lowers = int_range<2> (type,
803 : 18572 : wi::shwi (a, TYPE_PRECISION (type)),
804 : 18572 : wi::shwi (z, TYPE_PRECISION (type)));
805 : 18572 : uppers = int_range<2> (type,
806 : 18572 : wi::shwi (A, TYPE_PRECISION (type)),
807 : 18572 : wi::shwi (Z, TYPE_PRECISION (type)));
808 : 9286 : return true;
809 : : }
810 : : // Unknown character set.
811 : : return false;
812 : : }
813 : :
814 : : bool
815 : 9286 : cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
816 : : const irange &, relation_trio) const
817 : : {
818 : 9286 : int_range<3> lowers;
819 : 9286 : int_range<3> uppers;
820 : 9286 : if (!get_letter_range (type, lowers, uppers))
821 : : return false;
822 : :
823 : 9286 : r = lh;
824 : 9286 : if (m_toupper)
825 : : {
826 : : // Return the range passed in without any lower case characters,
827 : : // but including all the upper case ones.
828 : 9182 : lowers.invert ();
829 : 9182 : r.intersect (lowers);
830 : 9182 : r.union_ (uppers);
831 : : }
832 : : else
833 : : {
834 : : // Return the range passed in without any lower case characters,
835 : : // but including all the upper case ones.
836 : 104 : uppers.invert ();
837 : 104 : r.intersect (uppers);
838 : 104 : r.union_ (lowers);
839 : : }
840 : : return true;
841 : 9286 : }
842 : :
843 : : // Implement range operator for CFN_BUILT_IN_FFS.
844 : : class cfn_ffs : public range_operator
845 : : {
846 : : public:
847 : : using range_operator::fold_range;
848 : 5171 : virtual bool fold_range (irange &r, tree type, const irange &lh,
849 : : const irange &, relation_trio) const
850 : : {
851 : 5171 : if (lh.undefined_p ())
852 : : return false;
853 : : // __builtin_ffs* and __builtin_popcount* return [0, prec].
854 : 5171 : int prec = TYPE_PRECISION (lh.type ());
855 : : // If arg is non-zero, then ffs or popcount are non-zero.
856 : 5171 : int mini = range_includes_zero_p (&lh) ? 0 : 1;
857 : 5171 : int maxi = prec;
858 : :
859 : : // If some high bits are known to be zero, decrease the maximum.
860 : 5171 : int_range_max tmp = lh;
861 : 5171 : if (TYPE_SIGN (tmp.type ()) == SIGNED)
862 : 1596 : range_cast (tmp, unsigned_type_for (tmp.type ()));
863 : 5171 : wide_int max = tmp.upper_bound ();
864 : 5171 : maxi = wi::floor_log2 (max) + 1;
865 : 5171 : r.set (type,
866 : 10342 : wi::shwi (mini, TYPE_PRECISION (type)),
867 : 5171 : wi::shwi (maxi, TYPE_PRECISION (type)));
868 : 5171 : return true;
869 : 5171 : }
870 : : } op_cfn_ffs;
871 : :
872 : : // Implement range operator for CFN_BUILT_IN_POPCOUNT.
873 : : class cfn_popcount : public cfn_ffs
874 : : {
875 : : public:
876 : : using range_operator::fold_range;
877 : 3614 : virtual bool fold_range (irange &r, tree type, const irange &lh,
878 : : const irange &rh, relation_trio rel) const
879 : : {
880 : 3614 : if (lh.undefined_p ())
881 : : return false;
882 : 3606 : unsigned prec = TYPE_PRECISION (type);
883 : 3606 : irange_bitmask bm = lh.get_bitmask ();
884 : 3606 : wide_int nz = bm.get_nonzero_bits ();
885 : 3606 : wide_int high = wi::shwi (wi::popcount (nz), prec);
886 : : // Calculating the popcount of a singleton is trivial.
887 : 3606 : if (lh.singleton_p ())
888 : : {
889 : 1 : r.set (type, high, high);
890 : 1 : return true;
891 : : }
892 : 3605 : if (cfn_ffs::fold_range (r, type, lh, rh, rel))
893 : : {
894 : 3605 : wide_int known_ones = ~bm.mask () & bm.value ();
895 : 3605 : wide_int low = wi::shwi (wi::popcount (known_ones), prec);
896 : 3605 : int_range<2> tmp (type, low, high);
897 : 3605 : r.intersect (tmp);
898 : 3605 : return true;
899 : 3605 : }
900 : : return false;
901 : 3606 : }
902 : : } op_cfn_popcount;
903 : :
904 : : // Implement range operator for CFN_BUILT_IN_CLZ
905 : : class cfn_clz : public range_operator
906 : : {
907 : : public:
908 : : cfn_clz (bool internal) { m_gimple_call_internal_p = internal; }
909 : : using range_operator::fold_range;
910 : : virtual bool fold_range (irange &r, tree type, const irange &lh,
911 : : const irange &rh, relation_trio) const;
912 : : private:
913 : : bool m_gimple_call_internal_p;
914 : : } op_cfn_clz (false), op_cfn_clz_internal (true);
915 : :
916 : : bool
917 : 104759 : cfn_clz::fold_range (irange &r, tree type, const irange &lh,
918 : : const irange &rh, relation_trio) const
919 : : {
920 : : // __builtin_c[lt]z* return [0, prec-1], except when the
921 : : // argument is 0, but that is undefined behavior.
922 : : //
923 : : // For __builtin_c[lt]z* consider argument of 0 always undefined
924 : : // behavior, for internal fns likewise, unless it has 2 arguments,
925 : : // then the second argument is the value at zero.
926 : 104759 : if (lh.undefined_p ())
927 : : return false;
928 : 104698 : int prec = TYPE_PRECISION (lh.type ());
929 : 104698 : int mini = 0;
930 : 104698 : int maxi = prec - 1;
931 : 104698 : if (m_gimple_call_internal_p)
932 : : {
933 : : // Only handle the single common value.
934 : 51 : if (rh.lower_bound () == prec)
935 : 51 : maxi = prec;
936 : : else
937 : : // Magic value to give up, unless we can prove arg is non-zero.
938 : : mini = -2;
939 : : }
940 : :
941 : : // From clz of minimum we can compute result maximum.
942 : 104698 : if (wi::gt_p (lh.lower_bound (), 0, TYPE_SIGN (lh.type ())))
943 : : {
944 : 87648 : maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ());
945 : 87648 : if (mini == -2)
946 : : mini = 0;
947 : : }
948 : 17050 : else if (!range_includes_zero_p (&lh))
949 : : {
950 : : mini = 0;
951 : : maxi = prec - 1;
952 : : }
953 : 17049 : if (mini == -2)
954 : : return false;
955 : : // From clz of maximum we can compute result minimum.
956 : 104698 : wide_int max = lh.upper_bound ();
957 : 104698 : int newmini = prec - 1 - wi::floor_log2 (max);
958 : 104698 : if (max == 0)
959 : : {
960 : : // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
961 : : // return [prec, prec], otherwise ignore the range.
962 : 10 : if (maxi == prec)
963 : 0 : mini = prec;
964 : : }
965 : : else
966 : : mini = newmini;
967 : :
968 : 104698 : if (mini == -2)
969 : : return false;
970 : 104698 : r.set (type,
971 : 209396 : wi::shwi (mini, TYPE_PRECISION (type)),
972 : 104698 : wi::shwi (maxi, TYPE_PRECISION (type)));
973 : 104698 : return true;
974 : 104698 : }
975 : :
976 : : // Implement range operator for CFN_BUILT_IN_CTZ
977 : : class cfn_ctz : public range_operator
978 : : {
979 : : public:
980 : : cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; }
981 : : using range_operator::fold_range;
982 : : virtual bool fold_range (irange &r, tree type, const irange &lh,
983 : : const irange &rh, relation_trio) const;
984 : : private:
985 : : bool m_gimple_call_internal_p;
986 : : } op_cfn_ctz (false), op_cfn_ctz_internal (true);
987 : :
988 : : bool
989 : 9729 : cfn_ctz::fold_range (irange &r, tree type, const irange &lh,
990 : : const irange &rh, relation_trio) const
991 : : {
992 : 9729 : if (lh.undefined_p ())
993 : : return false;
994 : 9702 : int prec = TYPE_PRECISION (lh.type ());
995 : 9702 : int mini = 0;
996 : 9702 : int maxi = prec - 1;
997 : :
998 : 9702 : if (m_gimple_call_internal_p)
999 : : {
1000 : : // Handle only the two common values.
1001 : 62 : if (rh.lower_bound () == -1)
1002 : : mini = -1;
1003 : 62 : else if (rh.lower_bound () == prec)
1004 : 62 : maxi = prec;
1005 : : else
1006 : : // Magic value to give up, unless we can prove arg is non-zero.
1007 : : mini = -2;
1008 : : }
1009 : : // If arg is non-zero, then use [0, prec - 1].
1010 : 9702 : if (!range_includes_zero_p (&lh))
1011 : : {
1012 : 6825 : mini = 0;
1013 : 6825 : maxi = prec - 1;
1014 : : }
1015 : : // If some high bits are known to be zero, we can decrease
1016 : : // the maximum.
1017 : 9702 : wide_int max = lh.upper_bound ();
1018 : 9702 : if (max == 0)
1019 : : {
1020 : : // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO
1021 : : // is 2 with value -1 or prec, return [-1, -1] or [prec, prec].
1022 : : // Otherwise ignore the range.
1023 : 7 : if (mini == -1)
1024 : : maxi = -1;
1025 : 7 : else if (maxi == prec)
1026 : 9702 : mini = prec;
1027 : : }
1028 : : // If value at zero is prec and 0 is in the range, we can't lower
1029 : : // the upper bound. We could create two separate ranges though,
1030 : : // [0,floor_log2(max)][prec,prec] though.
1031 : 9695 : else if (maxi != prec)
1032 : 9635 : maxi = wi::floor_log2 (max);
1033 : :
1034 : 9702 : if (mini == -2)
1035 : : return false;
1036 : 9702 : r.set (type,
1037 : 19404 : wi::shwi (mini, TYPE_PRECISION (type)),
1038 : 9702 : wi::shwi (maxi, TYPE_PRECISION (type)));
1039 : 9702 : return true;
1040 : 9702 : }
1041 : :
1042 : :
1043 : : // Implement range operator for CFN_BUILT_IN_
1044 : : class cfn_clrsb : public range_operator
1045 : : {
1046 : : public:
1047 : : using range_operator::fold_range;
1048 : 963 : virtual bool fold_range (irange &r, tree type, const irange &lh,
1049 : : const irange &, relation_trio) const
1050 : : {
1051 : 963 : if (lh.undefined_p ())
1052 : : return false;
1053 : 963 : int prec = TYPE_PRECISION (lh.type ());
1054 : 963 : r.set (type,
1055 : 1926 : wi::zero (TYPE_PRECISION (type)),
1056 : 963 : wi::shwi (prec - 1, TYPE_PRECISION (type)));
1057 : 963 : return true;
1058 : : }
1059 : : } op_cfn_clrsb;
1060 : :
1061 : :
1062 : : // Implement range operator for CFN_BUILT_IN_
1063 : : class cfn_ubsan : public range_operator
1064 : : {
1065 : : public:
1066 : : cfn_ubsan (enum tree_code code) { m_code = code; }
1067 : : using range_operator::fold_range;
1068 : 14604 : virtual bool fold_range (irange &r, tree type, const irange &lh,
1069 : : const irange &rh, relation_trio rel) const
1070 : : {
1071 : 14604 : bool saved_flag_wrapv = flag_wrapv;
1072 : : // Pretend the arithmetic is wrapping. If there is any overflow,
1073 : : // we'll complain, but will actually do wrapping operation.
1074 : 14604 : flag_wrapv = 1;
1075 : 14604 : bool result = range_op_handler (m_code).fold_range (r, type, lh, rh, rel);
1076 : 14604 : flag_wrapv = saved_flag_wrapv;
1077 : :
1078 : : // If for both arguments vrp_valueize returned non-NULL, this should
1079 : : // have been already folded and if not, it wasn't folded because of
1080 : : // overflow. Avoid removing the UBSAN_CHECK_* calls in that case.
1081 : 14604 : if (result && r.singleton_p ())
1082 : 380 : r.set_varying (type);
1083 : 14604 : return result;
1084 : : }
1085 : : private:
1086 : : enum tree_code m_code;
1087 : : };
1088 : :
1089 : : cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
1090 : : cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
1091 : : cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
1092 : :
1093 : :
1094 : : // Implement range operator for CFN_BUILT_IN_STRLEN
1095 : : class cfn_strlen : public range_operator
1096 : : {
1097 : : public:
1098 : : using range_operator::fold_range;
1099 : 263428 : virtual bool fold_range (irange &r, tree type, const irange &,
1100 : : const irange &, relation_trio) const
1101 : : {
1102 : 263428 : wide_int max = irange_val_max (ptrdiff_type_node);
1103 : : // To account for the terminating NULL, the maximum length
1104 : : // is one less than the maximum array size, which in turn
1105 : : // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
1106 : : // smaller than the former type).
1107 : : // FIXME: Use max_object_size() - 1 here.
1108 : 263428 : r.set (type, wi::zero (TYPE_PRECISION (type)), max - 2);
1109 : 263428 : return true;
1110 : 263428 : }
1111 : : } op_cfn_strlen;
1112 : :
1113 : :
1114 : : // Implement range operator for CFN_BUILT_IN_GOACC_DIM
1115 : : class cfn_goacc_dim : public range_operator
1116 : : {
1117 : : public:
1118 : : cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; }
1119 : : using range_operator::fold_range;
1120 : 11505 : virtual bool fold_range (irange &r, tree type, const irange &lh,
1121 : : const irange &, relation_trio) const
1122 : : {
1123 : 11505 : tree axis_tree;
1124 : 11505 : if (!lh.singleton_p (&axis_tree))
1125 : : return false;
1126 : 11505 : HOST_WIDE_INT axis = TREE_INT_CST_LOW (axis_tree);
1127 : 11505 : int size = oacc_get_fn_dim_size (current_function_decl, axis);
1128 : 11505 : if (!size)
1129 : : // If it's dynamic, the backend might know a hardware limitation.
1130 : 0 : size = targetm.goacc.dim_limit (axis);
1131 : :
1132 : 11505 : r.set (type,
1133 : 29603 : wi::shwi (m_is_pos ? 0 : 1, TYPE_PRECISION (type)),
1134 : : size
1135 : 11505 : ? wi::shwi (size - m_is_pos, TYPE_PRECISION (type))
1136 : : : irange_val_max (type));
1137 : 11505 : return true;
1138 : : }
1139 : : private:
1140 : : bool m_is_pos;
1141 : : } op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
1142 : :
1143 : :
1144 : : // Implement range operator for CFN_BUILT_IN_
1145 : : class cfn_parity : public range_operator
1146 : : {
1147 : : public:
1148 : : using range_operator::fold_range;
1149 : 1142 : virtual bool fold_range (irange &r, tree type, const irange &,
1150 : : const irange &, relation_trio) const
1151 : : {
1152 : 1142 : r = range_true_and_false (type);
1153 : 1142 : return true;
1154 : : }
1155 : : } op_cfn_parity;
1156 : :
1157 : : // Set up a gimple_range_op_handler for any nonstandard function which can be
1158 : : // supported via range-ops.
1159 : :
1160 : : void
1161 : 231935823 : gimple_range_op_handler::maybe_non_standard ()
1162 : : {
1163 : 231935823 : range_op_handler signed_op (OP_WIDEN_MULT_SIGNED);
1164 : 231935823 : gcc_checking_assert (signed_op);
1165 : 231935823 : range_op_handler unsigned_op (OP_WIDEN_MULT_UNSIGNED);
1166 : 231935823 : gcc_checking_assert (unsigned_op);
1167 : :
1168 : 231935823 : if (gimple_code (m_stmt) == GIMPLE_ASSIGN)
1169 : 168104448 : switch (gimple_assign_rhs_code (m_stmt))
1170 : : {
1171 : 1349 : case WIDEN_MULT_EXPR:
1172 : 1349 : {
1173 : 1349 : m_op1 = gimple_assign_rhs1 (m_stmt);
1174 : 1349 : m_op2 = gimple_assign_rhs2 (m_stmt);
1175 : 1349 : tree ret = gimple_assign_lhs (m_stmt);
1176 : 1349 : bool signed1 = TYPE_SIGN (TREE_TYPE (m_op1)) == SIGNED;
1177 : 1349 : bool signed2 = TYPE_SIGN (TREE_TYPE (m_op2)) == SIGNED;
1178 : 1349 : bool signed_ret = TYPE_SIGN (TREE_TYPE (ret)) == SIGNED;
1179 : :
1180 : : /* Normally these operands should all have the same sign, but
1181 : : some passes and violate this by taking mismatched sign args. At
1182 : : the moment the only one that's possible is mismatch inputs and
1183 : : unsigned output. Once ranger supports signs for the operands we
1184 : : can properly fix it, for now only accept the case we can do
1185 : : correctly. */
1186 : 1349 : if ((signed1 ^ signed2) && signed_ret)
1187 : 0 : return;
1188 : :
1189 : 1349 : if (signed2 && !signed1)
1190 : 0 : std::swap (m_op1, m_op2);
1191 : :
1192 : 1349 : if (signed1 || signed2)
1193 : 60 : m_operator = signed_op.range_op ();
1194 : : else
1195 : 1289 : m_operator = unsigned_op.range_op ();
1196 : : break;
1197 : : }
1198 : : default:
1199 : : break;
1200 : : }
1201 : : }
1202 : :
1203 : : // Set up a gimple_range_op_handler for any built in function which can be
1204 : : // supported via range-ops.
1205 : :
1206 : : void
1207 : 57057093 : gimple_range_op_handler::maybe_builtin_call ()
1208 : : {
1209 : 57057093 : gcc_checking_assert (is_a <gcall *> (m_stmt));
1210 : :
1211 : 57057093 : gcall *call = as_a <gcall *> (m_stmt);
1212 : 57057093 : combined_fn func = gimple_call_combined_fn (call);
1213 : 57057093 : if (func == CFN_LAST)
1214 : : return;
1215 : 26121176 : tree type = gimple_range_type (call);
1216 : 26121176 : gcc_checking_assert (type);
1217 : 26121176 : if (!Value_Range::supports_type_p (type))
1218 : : return;
1219 : :
1220 : 26121176 : switch (func)
1221 : : {
1222 : 94785 : case CFN_BUILT_IN_CONSTANT_P:
1223 : 94785 : m_op1 = gimple_call_arg (call, 0);
1224 : 94785 : if (irange::supports_p (TREE_TYPE (m_op1)))
1225 : 93832 : m_operator = &op_cfn_constant_p;
1226 : 953 : else if (frange::supports_p (TREE_TYPE (m_op1)))
1227 : 893 : m_operator = &op_cfn_constant_float_p;
1228 : : break;
1229 : :
1230 : 110588 : CASE_FLT_FN (CFN_BUILT_IN_SIGNBIT):
1231 : 110588 : m_op1 = gimple_call_arg (call, 0);
1232 : 110588 : m_operator = &op_cfn_signbit;
1233 : 110588 : break;
1234 : :
1235 : 1055146 : CASE_CFN_COPYSIGN_ALL:
1236 : 1055146 : m_op1 = gimple_call_arg (call, 0);
1237 : 1055146 : m_op2 = gimple_call_arg (call, 1);
1238 : 1055146 : m_operator = &op_cfn_copysign;
1239 : 1055146 : break;
1240 : :
1241 : 86449 : CASE_CFN_SQRT:
1242 : 86449 : CASE_CFN_SQRT_FN:
1243 : 86449 : m_op1 = gimple_call_arg (call, 0);
1244 : 86449 : m_operator = &op_cfn_sqrt;
1245 : 86449 : break;
1246 : :
1247 : 25446 : CASE_CFN_SIN:
1248 : 25446 : CASE_CFN_SIN_FN:
1249 : 25446 : m_op1 = gimple_call_arg (call, 0);
1250 : 25446 : m_operator = &op_cfn_sin;
1251 : 25446 : break;
1252 : :
1253 : 13880 : CASE_CFN_COS:
1254 : 13880 : CASE_CFN_COS_FN:
1255 : 13880 : m_op1 = gimple_call_arg (call, 0);
1256 : 13880 : m_operator = &op_cfn_cos;
1257 : 13880 : break;
1258 : :
1259 : 32418 : case CFN_BUILT_IN_TOUPPER:
1260 : 32418 : case CFN_BUILT_IN_TOLOWER:
1261 : : // Only proceed If the argument is compatible with the LHS.
1262 : 32418 : m_op1 = gimple_call_arg (call, 0);
1263 : 32418 : if (range_compatible_p (type, TREE_TYPE (m_op1)))
1264 : 64549 : m_operator = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower
1265 : : : &op_cfn_toupper;
1266 : : break;
1267 : :
1268 : 5414 : CASE_CFN_FFS:
1269 : 5414 : m_op1 = gimple_call_arg (call, 0);
1270 : 5414 : m_operator = &op_cfn_ffs;
1271 : 5414 : break;
1272 : :
1273 : 11923 : CASE_CFN_POPCOUNT:
1274 : 11923 : m_op1 = gimple_call_arg (call, 0);
1275 : 11923 : m_operator = &op_cfn_popcount;
1276 : 11923 : break;
1277 : :
1278 : 291145 : CASE_CFN_CLZ:
1279 : 291145 : m_op1 = gimple_call_arg (call, 0);
1280 : 291145 : if (gimple_call_internal_p (call)
1281 : 291145 : && gimple_call_num_args (call) == 2)
1282 : : {
1283 : 170 : m_op2 = gimple_call_arg (call, 1);
1284 : 170 : m_operator = &op_cfn_clz_internal;
1285 : : }
1286 : : else
1287 : 290975 : m_operator = &op_cfn_clz;
1288 : : break;
1289 : :
1290 : 27082 : CASE_CFN_CTZ:
1291 : 27082 : m_op1 = gimple_call_arg (call, 0);
1292 : 27082 : if (gimple_call_internal_p (call)
1293 : 27082 : && gimple_call_num_args (call) == 2)
1294 : : {
1295 : 203 : m_op2 = gimple_call_arg (call, 1);
1296 : 203 : m_operator = &op_cfn_ctz_internal;
1297 : : }
1298 : : else
1299 : 26879 : m_operator = &op_cfn_ctz;
1300 : : break;
1301 : :
1302 : 3443 : CASE_CFN_CLRSB:
1303 : 3443 : m_op1 = gimple_call_arg (call, 0);
1304 : 3443 : m_operator = &op_cfn_clrsb;
1305 : 3443 : break;
1306 : :
1307 : 19713 : case CFN_UBSAN_CHECK_ADD:
1308 : 19713 : m_op1 = gimple_call_arg (call, 0);
1309 : 19713 : m_op2 = gimple_call_arg (call, 1);
1310 : 19713 : m_operator = &op_cfn_ubsan_add;
1311 : 19713 : break;
1312 : :
1313 : 18507 : case CFN_UBSAN_CHECK_SUB:
1314 : 18507 : m_op1 = gimple_call_arg (call, 0);
1315 : 18507 : m_op2 = gimple_call_arg (call, 1);
1316 : 18507 : m_operator = &op_cfn_ubsan_sub;
1317 : 18507 : break;
1318 : :
1319 : 16209 : case CFN_UBSAN_CHECK_MUL:
1320 : 16209 : m_op1 = gimple_call_arg (call, 0);
1321 : 16209 : m_op2 = gimple_call_arg (call, 1);
1322 : 16209 : m_operator = &op_cfn_ubsan_mul;
1323 : 16209 : break;
1324 : :
1325 : 844662 : case CFN_BUILT_IN_STRLEN:
1326 : 844662 : {
1327 : 844662 : tree lhs = gimple_call_lhs (call);
1328 : 844662 : if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node)
1329 : 844662 : == TYPE_PRECISION (TREE_TYPE (lhs))))
1330 : : {
1331 : 844662 : m_op1 = gimple_call_arg (call, 0);
1332 : 844662 : m_operator = &op_cfn_strlen;
1333 : : }
1334 : : break;
1335 : : }
1336 : :
1337 : : // Optimizing these two internal functions helps the loop
1338 : : // optimizer eliminate outer comparisons. Size is [1,N]
1339 : : // and pos is [0,N-1].
1340 : 27561 : case CFN_GOACC_DIM_SIZE:
1341 : : // This call will ensure all the asserts are triggered.
1342 : 27561 : oacc_get_ifn_dim_arg (call);
1343 : 27561 : m_op1 = gimple_call_arg (call, 0);
1344 : 27561 : m_operator = &op_cfn_goacc_dim_size;
1345 : 27561 : break;
1346 : :
1347 : 40608 : case CFN_GOACC_DIM_POS:
1348 : : // This call will ensure all the asserts are triggered.
1349 : 40608 : oacc_get_ifn_dim_arg (call);
1350 : 40608 : m_op1 = gimple_call_arg (call, 0);
1351 : 40608 : m_operator = &op_cfn_goacc_dim_pos;
1352 : 40608 : break;
1353 : :
1354 : 5571 : CASE_CFN_PARITY:
1355 : 5571 : m_operator = &op_cfn_parity;
1356 : 5571 : break;
1357 : :
1358 : 23390626 : default:
1359 : 23390626 : {
1360 : 23390626 : unsigned arg;
1361 : 23390626 : if (gimple_call_fnspec (call).returns_arg (&arg) && arg == 0)
1362 : : {
1363 : 1181164 : m_op1 = gimple_call_arg (call, 0);
1364 : 1181164 : m_operator = &op_cfn_pass_through_arg1;
1365 : : }
1366 : : break;
1367 : : }
1368 : : }
1369 : : }
|