]> gcc.gnu.org Git - gcc.git/blob - gcc/gimple-range-op.cc
d7c6dfa933d1f63192953807815778b38956f3df
[gcc.git] / gcc / gimple-range-op.cc
1 /* Code for GIMPLE range op related routines.
2 Copyright (C) 2019-2022 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
47 // Given stmt S, fill VEC, up to VEC_SIZE elements, with relevant ssa-names
48 // on the statement. For efficiency, it is an error to not pass in enough
49 // elements for the vector. Return the number of ssa-names.
50
51 unsigned
52 gimple_range_ssa_names (tree *vec, unsigned vec_size, gimple *stmt)
53 {
54 tree ssa;
55 int count = 0;
56
57 gimple_range_op_handler handler (stmt);
58 if (handler)
59 {
60 gcc_checking_assert (vec_size >= 2);
61 if ((ssa = gimple_range_ssa_p (handler.operand1 ())))
62 vec[count++] = ssa;
63 if ((ssa = gimple_range_ssa_p (handler.operand2 ())))
64 vec[count++] = ssa;
65 }
66 else if (is_a<gassign *> (stmt)
67 && gimple_assign_rhs_code (stmt) == COND_EXPR)
68 {
69 gcc_checking_assert (vec_size >= 3);
70 gassign *st = as_a<gassign *> (stmt);
71 if ((ssa = gimple_range_ssa_p (gimple_assign_rhs1 (st))))
72 vec[count++] = ssa;
73 if ((ssa = gimple_range_ssa_p (gimple_assign_rhs2 (st))))
74 vec[count++] = ssa;
75 if ((ssa = gimple_range_ssa_p (gimple_assign_rhs3 (st))))
76 vec[count++] = ssa;
77 }
78 return count;
79 }
80
81 // Return the base of the RHS of an assignment.
82
83 static tree
84 gimple_range_base_of_assignment (const gimple *stmt)
85 {
86 gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
87 tree op1 = gimple_assign_rhs1 (stmt);
88 if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
89 return get_base_address (TREE_OPERAND (op1, 0));
90 return op1;
91 }
92
93 // If statement is supported by range-ops, set the CODE and return the TYPE.
94
95 static tree
96 get_code_and_type (gimple *s, enum tree_code &code)
97 {
98 tree type = NULL_TREE;
99 code = NOP_EXPR;
100
101 if (const gassign *ass = dyn_cast<const gassign *> (s))
102 {
103 code = gimple_assign_rhs_code (ass);
104 // The LHS of a comparison is always an int, so we must look at
105 // the operands.
106 if (TREE_CODE_CLASS (code) == tcc_comparison)
107 type = TREE_TYPE (gimple_assign_rhs1 (ass));
108 else
109 type = TREE_TYPE (gimple_assign_lhs (ass));
110 }
111 else if (const gcond *cond = dyn_cast<const gcond *> (s))
112 {
113 code = gimple_cond_code (cond);
114 type = TREE_TYPE (gimple_cond_lhs (cond));
115 }
116 return type;
117 }
118
119 // If statement S has a supported range_op handler return TRUE.
120
121 bool
122 gimple_range_op_handler::supported_p (gimple *s)
123 {
124 enum tree_code code;
125 tree type = get_code_and_type (s, code);
126 if (type && range_op_handler (code, type))
127 return true;
128 if (is_a <gcall *> (s) && gimple_range_op_handler (s))
129 return true;
130 return false;
131 }
132
133 // Construct a handler object for statement S.
134
135 gimple_range_op_handler::gimple_range_op_handler (gimple *s)
136 {
137 enum tree_code code;
138 tree type = get_code_and_type (s, code);
139 m_stmt = s;
140 m_op1 = NULL_TREE;
141 m_op2 = NULL_TREE;
142 if (type)
143 set_op_handler (code, type);
144
145 if (m_valid)
146 switch (gimple_code (m_stmt))
147 {
148 case GIMPLE_COND:
149 m_op1 = gimple_cond_lhs (m_stmt);
150 m_op2 = gimple_cond_rhs (m_stmt);
151 return;
152 case GIMPLE_ASSIGN:
153 m_op1 = gimple_range_base_of_assignment (m_stmt);
154 if (m_op1 && TREE_CODE (m_op1) == MEM_REF)
155 {
156 // If the base address is an SSA_NAME, we return it
157 // here. This allows processing of the range of that
158 // name, while the rest of the expression is simply
159 // ignored. The code in range_ops will see the
160 // ADDR_EXPR and do the right thing.
161 tree ssa = TREE_OPERAND (m_op1, 0);
162 if (TREE_CODE (ssa) == SSA_NAME)
163 m_op1 = ssa;
164 }
165 if (gimple_num_ops (m_stmt) >= 3)
166 m_op2 = gimple_assign_rhs2 (m_stmt);
167 return;
168 default:
169 gcc_unreachable ();
170 return;
171 }
172 // If no range-op table entry handled this stmt, check for other supported
173 // statements.
174 if (is_a <gcall *> (m_stmt))
175 maybe_builtin_call ();
176 }
177
178 // Calculate what we can determine of the range of this unary
179 // statement's operand if the lhs of the expression has the range
180 // LHS_RANGE. Return false if nothing can be determined.
181
182 bool
183 gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range)
184 {
185 gcc_checking_assert (gimple_num_ops (m_stmt) < 3);
186 // Give up on empty ranges.
187 if (lhs_range.undefined_p ())
188 return false;
189
190 // Unary operations require the type of the first operand in the
191 // second range position.
192 tree type = TREE_TYPE (operand1 ());
193 Value_Range type_range (type);
194 type_range.set_varying (type);
195 return op1_range (r, type, lhs_range, type_range);
196 }
197
198 // Calculate what we can determine of the range of this statement's
199 // first operand if the lhs of the expression has the range LHS_RANGE
200 // and the second operand has the range OP2_RANGE. Return false if
201 // nothing can be determined.
202
203 bool
204 gimple_range_op_handler::calc_op1 (vrange &r, const vrange &lhs_range,
205 const vrange &op2_range)
206 {
207 // Give up on empty ranges.
208 if (lhs_range.undefined_p ())
209 return false;
210
211 // Unary operation are allowed to pass a range in for second operand
212 // as there are often additional restrictions beyond the type which
213 // can be imposed. See operator_cast::op1_range().
214 tree type = TREE_TYPE (operand1 ());
215 // If op2 is undefined, solve as if it is varying.
216 if (op2_range.undefined_p ())
217 {
218 if (gimple_num_ops (m_stmt) < 3)
219 return false;
220 tree op2_type;
221 // This is sometimes invoked on single operand stmts.
222 if (operand2 ())
223 op2_type = TREE_TYPE (operand2 ());
224 else
225 op2_type = TREE_TYPE (operand1 ());
226 Value_Range trange (op2_type);
227 trange.set_varying (op2_type);
228 return op1_range (r, type, lhs_range, trange);
229 }
230 return op1_range (r, type, lhs_range, op2_range);
231 }
232
233 // Calculate what we can determine of the range of this statement's
234 // second operand if the lhs of the expression has the range LHS_RANGE
235 // and the first operand has the range OP1_RANGE. Return false if
236 // nothing can be determined.
237
238 bool
239 gimple_range_op_handler::calc_op2 (vrange &r, const vrange &lhs_range,
240 const vrange &op1_range)
241 {
242 // Give up on empty ranges.
243 if (lhs_range.undefined_p ())
244 return false;
245
246 tree type = TREE_TYPE (operand2 ());
247 // If op1 is undefined, solve as if it is varying.
248 if (op1_range.undefined_p ())
249 {
250 tree op1_type = TREE_TYPE (operand1 ());
251 Value_Range trange (op1_type);
252 trange.set_varying (op1_type);
253 return op2_range (r, type, lhs_range, trange);
254 }
255 return op2_range (r, type, lhs_range, op1_range);
256 }
257
258 // --------------------------------------------------------------------
259
260 // Implement range operator for float CFN_BUILT_IN_CONSTANT_P.
261 class cfn_constant_float_p : public range_operator_float
262 {
263 public:
264 using range_operator_float::fold_range;
265 virtual bool fold_range (irange &r, tree type, const frange &lh,
266 const irange &, relation_kind) const
267 {
268 if (lh.singleton_p ())
269 {
270 r.set (build_one_cst (type), build_one_cst (type));
271 return true;
272 }
273 if (cfun->after_inlining)
274 {
275 r.set_zero (type);
276 return true;
277 }
278 return false;
279 }
280 } op_cfn_constant_float_p;
281
282 // Implement range operator for integral CFN_BUILT_IN_CONSTANT_P.
283 class cfn_constant_p : public range_operator
284 {
285 public:
286 using range_operator::fold_range;
287 virtual bool fold_range (irange &r, tree type, const irange &lh,
288 const irange &, relation_kind) const
289 {
290 if (lh.singleton_p ())
291 {
292 r.set (build_one_cst (type), build_one_cst (type));
293 return true;
294 }
295 if (cfun->after_inlining)
296 {
297 r.set_zero (type);
298 return true;
299 }
300 return false;
301 }
302 } op_cfn_constant_p;
303
304 // Implement range operator for CFN_BUILT_IN_SIGNBIT.
305 class cfn_signbit : public range_operator_float
306 {
307 public:
308 using range_operator_float::fold_range;
309 virtual bool fold_range (irange &r, tree type, const frange &lh,
310 const irange &, relation_kind) const
311 {
312 bool signbit;
313 if (lh.signbit_p (signbit))
314 {
315 if (signbit)
316 r.set_nonzero (type);
317 else
318 r.set_zero (type);
319 return true;
320 }
321 return false;
322 }
323 } op_cfn_signbit;
324
325 // Implement range operator for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.
326 class cfn_toupper_tolower : public range_operator
327 {
328 public:
329 using range_operator::fold_range;
330 cfn_toupper_tolower (bool toupper) { m_toupper = toupper; }
331 virtual bool fold_range (irange &r, tree type, const irange &lh,
332 const irange &, relation_kind) const;
333 private:
334 bool get_letter_range (tree type, irange &lowers, irange &uppers) const;
335 bool m_toupper;
336 } op_cfn_toupper (true), op_cfn_tolower (false);
337
338 // Return TRUE if we recognize the target character set and return the
339 // range for lower case and upper case letters.
340
341 bool
342 cfn_toupper_tolower::get_letter_range (tree type, irange &lowers,
343 irange &uppers) const
344 {
345 // ASCII
346 int a = lang_hooks.to_target_charset ('a');
347 int z = lang_hooks.to_target_charset ('z');
348 int A = lang_hooks.to_target_charset ('A');
349 int Z = lang_hooks.to_target_charset ('Z');
350
351 if ((z - a == 25) && (Z - A == 25))
352 {
353 lowers = int_range<2> (build_int_cst (type, a), build_int_cst (type, z));
354 uppers = int_range<2> (build_int_cst (type, A), build_int_cst (type, Z));
355 return true;
356 }
357 // Unknown character set.
358 return false;
359 }
360
361 bool
362 cfn_toupper_tolower::fold_range (irange &r, tree type, const irange &lh,
363 const irange &, relation_kind) const
364 {
365 int_range<3> lowers;
366 int_range<3> uppers;
367 if (!get_letter_range (type, lowers, uppers))
368 return false;
369
370 r = lh;
371 if (m_toupper)
372 {
373 // Return the range passed in without any lower case characters,
374 // but including all the upper case ones.
375 lowers.invert ();
376 r.intersect (lowers);
377 r.union_ (uppers);
378 }
379 else
380 {
381 // Return the range passed in without any lower case characters,
382 // but including all the upper case ones.
383 uppers.invert ();
384 r.intersect (uppers);
385 r.union_ (lowers);
386 }
387 return true;
388 }
389
390 // Implement range operator for CFN_BUILT_IN_FFS and CFN_BUILT_IN_POPCOUNT.
391 class cfn_popcount : public range_operator
392 {
393 public:
394 using range_operator::fold_range;
395 virtual bool fold_range (irange &r, tree type, const irange &lh,
396 const irange &, relation_kind) const
397 {
398 if (lh.undefined_p ())
399 return false;
400 // __builtin_ffs* and __builtin_popcount* return [0, prec].
401 int prec = TYPE_PRECISION (lh.type ());
402 // If arg is non-zero, then ffs or popcount are non-zero.
403 int mini = range_includes_zero_p (&lh) ? 0 : 1;
404 int maxi = prec;
405
406 // If some high bits are known to be zero, decrease the maximum.
407 int_range_max tmp = lh;
408 if (TYPE_SIGN (tmp.type ()) == SIGNED)
409 range_cast (tmp, unsigned_type_for (tmp.type ()));
410 wide_int max = tmp.upper_bound ();
411 maxi = wi::floor_log2 (max) + 1;
412 r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
413 return true;
414 }
415 } op_cfn_popcount;
416
417 // Implement range operator for CFN_BUILT_IN_CLZ
418 class cfn_clz : public range_operator
419 {
420 public:
421 cfn_clz (bool internal) { m_gimple_call_internal_p = internal; }
422 using range_operator::fold_range;
423 virtual bool fold_range (irange &r, tree type, const irange &lh,
424 const irange &, relation_kind) const;
425 private:
426 bool m_gimple_call_internal_p;
427 } op_cfn_clz (false), op_cfn_clz_internal (true);
428
429 bool
430 cfn_clz::fold_range (irange &r, tree type, const irange &lh,
431 const irange &, relation_kind) const
432 {
433 // __builtin_c[lt]z* return [0, prec-1], except when the
434 // argument is 0, but that is undefined behavior.
435 //
436 // For __builtin_c[lt]z* consider argument of 0 always undefined
437 // behavior, for internal fns depending on C?Z_DEFINED_ALUE_AT_ZERO.
438 if (lh.undefined_p ())
439 return false;
440 int prec = TYPE_PRECISION (lh.type ());
441 int mini = 0;
442 int maxi = prec - 1;
443 int zerov = 0;
444 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (lh.type ());
445 if (m_gimple_call_internal_p)
446 {
447 if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
448 && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
449 {
450 // Only handle the single common value.
451 if (zerov == prec)
452 maxi = prec;
453 else
454 // Magic value to give up, unless we can prove arg is non-zero.
455 mini = -2;
456 }
457 }
458
459 // From clz of minimum we can compute result maximum.
460 if (wi::gt_p (lh.lower_bound (), 0, TYPE_SIGN (lh.type ())))
461 {
462 maxi = prec - 1 - wi::floor_log2 (lh.lower_bound ());
463 if (mini == -2)
464 mini = 0;
465 }
466 else if (!range_includes_zero_p (&lh))
467 {
468 mini = 0;
469 maxi = prec - 1;
470 }
471 if (mini == -2)
472 return false;
473 // From clz of maximum we can compute result minimum.
474 wide_int max = lh.upper_bound ();
475 int newmini = prec - 1 - wi::floor_log2 (max);
476 if (max == 0)
477 {
478 // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec,
479 // return [prec, prec], otherwise ignore the range.
480 if (maxi == prec)
481 mini = prec;
482 }
483 else
484 mini = newmini;
485
486 if (mini == -2)
487 return false;
488 r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
489 return true;
490 }
491
492 // Implement range operator for CFN_BUILT_IN_CTZ
493 class cfn_ctz : public range_operator
494 {
495 public:
496 cfn_ctz (bool internal) { m_gimple_call_internal_p = internal; }
497 using range_operator::fold_range;
498 virtual bool fold_range (irange &r, tree type, const irange &lh,
499 const irange &, relation_kind) const;
500 private:
501 bool m_gimple_call_internal_p;
502 } op_cfn_ctz (false), op_cfn_ctz_internal (true);
503
504 bool
505 cfn_ctz::fold_range (irange &r, tree type, const irange &lh,
506 const irange &, relation_kind) const
507 {
508 if (lh.undefined_p ())
509 return false;
510 int prec = TYPE_PRECISION (lh.type ());
511 int mini = 0;
512 int maxi = prec - 1;
513 int zerov = 0;
514 scalar_int_mode mode = SCALAR_INT_TYPE_MODE (lh.type ());
515
516 if (m_gimple_call_internal_p)
517 {
518 if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
519 && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov) == 2)
520 {
521 // Handle only the two common values.
522 if (zerov == -1)
523 mini = -1;
524 else if (zerov == prec)
525 maxi = prec;
526 else
527 // Magic value to give up, unless we can prove arg is non-zero.
528 mini = -2;
529 }
530 }
531 // If arg is non-zero, then use [0, prec - 1].
532 if (!range_includes_zero_p (&lh))
533 {
534 mini = 0;
535 maxi = prec - 1;
536 }
537 // If some high bits are known to be zero, we can decrease
538 // the maximum.
539 wide_int max = lh.upper_bound ();
540 if (max == 0)
541 {
542 // Argument is [0, 0]. If CTZ_DEFINED_VALUE_AT_ZERO
543 // is 2 with value -1 or prec, return [-1, -1] or [prec, prec].
544 // Otherwise ignore the range.
545 if (mini == -1)
546 maxi = -1;
547 else if (maxi == prec)
548 mini = prec;
549 }
550 // If value at zero is prec and 0 is in the range, we can't lower
551 // the upper bound. We could create two separate ranges though,
552 // [0,floor_log2(max)][prec,prec] though.
553 else if (maxi != prec)
554 maxi = wi::floor_log2 (max);
555
556 if (mini == -2)
557 return false;
558 r.set (build_int_cst (type, mini), build_int_cst (type, maxi));
559 return true;
560 }
561
562
563 // Implement range operator for CFN_BUILT_IN_
564 class cfn_clrsb : public range_operator
565 {
566 public:
567 using range_operator::fold_range;
568 virtual bool fold_range (irange &r, tree type, const irange &lh,
569 const irange &, relation_kind) const
570 {
571 if (lh.undefined_p ())
572 return false;
573 int prec = TYPE_PRECISION (lh.type ());
574 r.set (build_int_cst (type, 0), build_int_cst (type, prec - 1));
575 return true;
576 }
577 } op_cfn_clrsb;
578
579
580 // Implement range operator for CFN_BUILT_IN_
581 class cfn_ubsan : public range_operator
582 {
583 public:
584 cfn_ubsan (enum tree_code code) { m_code = code; }
585 using range_operator::fold_range;
586 virtual bool fold_range (irange &r, tree type, const irange &lh,
587 const irange &rh, relation_kind rel) const
588 {
589 range_op_handler handler (m_code, type);
590 gcc_checking_assert (handler);
591
592 bool saved_flag_wrapv = flag_wrapv;
593 // Pretend the arithmetic is wrapping. If there is any overflow,
594 // we'll complain, but will actually do wrapping operation.
595 flag_wrapv = 1;
596 bool result = handler.fold_range (r, type, lh, rh, rel);
597 flag_wrapv = saved_flag_wrapv;
598
599 // If for both arguments vrp_valueize returned non-NULL, this should
600 // have been already folded and if not, it wasn't folded because of
601 // overflow. Avoid removing the UBSAN_CHECK_* calls in that case.
602 if (result && r.singleton_p ())
603 r.set_varying (type);
604 return result;
605 }
606 private:
607 enum tree_code m_code;
608 };
609
610 cfn_ubsan op_cfn_ubsan_add (PLUS_EXPR);
611 cfn_ubsan op_cfn_ubsan_sub (MINUS_EXPR);
612 cfn_ubsan op_cfn_ubsan_mul (MULT_EXPR);
613
614
615 // Implement range operator for CFN_BUILT_IN_STRLEN
616 class cfn_strlen : public range_operator
617 {
618 public:
619 using range_operator::fold_range;
620 virtual bool fold_range (irange &r, tree type, const irange &,
621 const irange &, relation_kind) const
622 {
623 tree max = vrp_val_max (ptrdiff_type_node);
624 wide_int wmax
625 = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
626 tree range_min = build_zero_cst (type);
627 // To account for the terminating NULL, the maximum length
628 // is one less than the maximum array size, which in turn
629 // is one less than PTRDIFF_MAX (or SIZE_MAX where it's
630 // smaller than the former type).
631 // FIXME: Use max_object_size() - 1 here.
632 tree range_max = wide_int_to_tree (type, wmax - 2);
633 r.set (range_min, range_max);
634 return true;
635 }
636 } op_cfn_strlen;
637
638
639 // Implement range operator for CFN_BUILT_IN_GOACC_DIM
640 class cfn_goacc_dim : public range_operator
641 {
642 public:
643 cfn_goacc_dim (bool is_pos) { m_is_pos = is_pos; }
644 using range_operator::fold_range;
645 virtual bool fold_range (irange &r, tree type, const irange &lh,
646 const irange &, relation_kind) const
647 {
648 tree axis_tree;
649 if (!lh.singleton_p (&axis_tree))
650 return false;
651 HOST_WIDE_INT axis = TREE_INT_CST_LOW (axis_tree);
652 int size = oacc_get_fn_dim_size (current_function_decl, axis);
653 if (!size)
654 // If it's dynamic, the backend might know a hardware limitation.
655 size = targetm.goacc.dim_limit (axis);
656
657 r.set (build_int_cst (type, m_is_pos ? 0 : 1),
658 size
659 ? build_int_cst (type, size - m_is_pos) : vrp_val_max (type));
660 return true;
661 }
662 private:
663 bool m_is_pos;
664 } op_cfn_goacc_dim_size (false), op_cfn_goacc_dim_pos (true);
665
666
667 // Implement range operator for CFN_BUILT_IN_
668 class cfn_parity : public range_operator
669 {
670 public:
671 using range_operator::fold_range;
672 virtual bool fold_range (irange &r, tree type, const irange &,
673 const irange &, relation_kind) const
674 {
675 r.set (build_zero_cst (type), build_one_cst (type));
676 return true;
677 }
678 } op_cfn_parity;
679
680 // Set up a gimple_range_op_handler for any built in function which can be
681 // supported via range-ops.
682
683 void
684 gimple_range_op_handler::maybe_builtin_call ()
685 {
686 gcc_checking_assert (is_a <gcall *> (m_stmt));
687
688 gcall *call = as_a <gcall *> (m_stmt);
689 combined_fn func = gimple_call_combined_fn (call);
690 if (func == CFN_LAST)
691 return;
692 tree type = gimple_range_type (call);
693 gcc_checking_assert (type);
694 if (!Value_Range::supports_type_p (type))
695 return;
696
697 switch (func)
698 {
699 case CFN_BUILT_IN_CONSTANT_P:
700 m_op1 = gimple_call_arg (call, 0);
701 m_valid = true;
702 if (irange::supports_p (TREE_TYPE (m_op1)))
703 m_int = &op_cfn_constant_p;
704 else if (frange::supports_p (TREE_TYPE (m_op1)))
705 m_float = &op_cfn_constant_float_p;
706 else
707 m_valid = false;
708 break;
709
710 case CFN_BUILT_IN_SIGNBIT:
711 m_op1 = gimple_call_arg (call, 0);
712 m_float = &op_cfn_signbit;
713 m_valid = true;
714 break;
715
716 case CFN_BUILT_IN_TOUPPER:
717 case CFN_BUILT_IN_TOLOWER:
718 // Only proceed If the argument is compatible with the LHS.
719 m_op1 = gimple_call_arg (call, 0);
720 if (range_compatible_p (type, TREE_TYPE (m_op1)))
721 {
722 m_valid = true;
723 m_int = (func == CFN_BUILT_IN_TOLOWER) ? &op_cfn_tolower
724 : &op_cfn_toupper;
725 }
726 break;
727
728 CASE_CFN_FFS:
729 CASE_CFN_POPCOUNT:
730 m_op1 = gimple_call_arg (call, 0);
731 m_int = &op_cfn_popcount;
732 m_valid = true;
733 break;
734
735 CASE_CFN_CLZ:
736 m_op1 = gimple_call_arg (call, 0);
737 m_valid = true;
738 if (gimple_call_internal_p (call))
739 m_int = &op_cfn_clz_internal;
740 else
741 m_int = &op_cfn_clz;
742 break;
743
744 CASE_CFN_CTZ:
745 m_op1 = gimple_call_arg (call, 0);
746 m_valid = true;
747 if (gimple_call_internal_p (call))
748 m_int = &op_cfn_ctz_internal;
749 else
750 m_int = &op_cfn_ctz;
751 break;
752
753 CASE_CFN_CLRSB:
754 m_op1 = gimple_call_arg (call, 0);
755 m_valid = true;
756 m_int = &op_cfn_clrsb;
757 break;
758
759 case CFN_UBSAN_CHECK_ADD:
760 m_op1 = gimple_call_arg (call, 0);
761 m_op2 = gimple_call_arg (call, 1);
762 m_valid = true;
763 m_int = &op_cfn_ubsan_add;
764 break;
765
766 case CFN_UBSAN_CHECK_SUB:
767 m_op1 = gimple_call_arg (call, 0);
768 m_op2 = gimple_call_arg (call, 1);
769 m_valid = true;
770 m_int = &op_cfn_ubsan_sub;
771 break;
772
773 case CFN_UBSAN_CHECK_MUL:
774 m_op1 = gimple_call_arg (call, 0);
775 m_op2 = gimple_call_arg (call, 1);
776 m_valid = true;
777 m_int = &op_cfn_ubsan_mul;
778 break;
779
780 case CFN_BUILT_IN_STRLEN:
781 {
782 tree lhs = gimple_call_lhs (call);
783 if (lhs && ptrdiff_type_node && (TYPE_PRECISION (ptrdiff_type_node)
784 == TYPE_PRECISION (TREE_TYPE (lhs))))
785 {
786 m_op1 = gimple_call_arg (call, 0);
787 m_valid = true;
788 m_int = &op_cfn_strlen;
789 }
790 break;
791 }
792
793 // Optimizing these two internal functions helps the loop
794 // optimizer eliminate outer comparisons. Size is [1,N]
795 // and pos is [0,N-1].
796 case CFN_GOACC_DIM_SIZE:
797 // This call will ensure all the asserts are triggered.
798 oacc_get_ifn_dim_arg (call);
799 m_op1 = gimple_call_arg (call, 0);
800 m_valid = true;
801 m_int = &op_cfn_goacc_dim_size;
802 break;
803
804 case CFN_GOACC_DIM_POS:
805 // This call will ensure all the asserts are triggered.
806 oacc_get_ifn_dim_arg (call);
807 m_op1 = gimple_call_arg (call, 0);
808 m_valid = true;
809 m_int = &op_cfn_goacc_dim_pos;
810 break;
811
812 CASE_CFN_PARITY:
813 m_valid = true;
814 m_int = &op_cfn_parity;
815 break;
816
817 default:
818 break;
819 }
820 }
This page took 0.071289 seconds and 4 git commands to generate.