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