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