On 7/15/21 9:06 AM, Richard Biener wrote:
On Thu, Jul 15, 2021 at 1:06 PM Aldy Hernandez <al...@redhat.com> wrote:
Currently gimple_expr_type is ICEing because it calls gimple_call_return_type.
I still think gimple_call_return_type should return void_type_node
instead of ICEing, but this will also fix my problem.
Anyone have a problem with this?
It's still somewhat inconsistent, no? Because for a call without a LHS
it's now either void_type_node or the type of the return value.
It's probably known I dislike gimple_expr_type itself (it was introduced
to make the transition to tuples easier). I wonder why you can't simply
fix range_of_call to do
tree lhs = gimple_call_lhs (call);
if (lhs)
type = TREE_TYPE (lhs);
Richard.
You are correct. There are indeed inconsistencies, and they exist in
multiple places. In fact, none of them do exactly what we are looking
for all the time, and there are times we do care about the stmt when
there is no LHS. In addition, we almost always then have to check
whether the type we found is supported.
So instead, much as we did for types with range_compatible_p (), we'll
provide a function for statements which does exactly what we need. This
patch eliminates all the ranger calls to both gimple_expr_type () and
gimple_call_return_type () . This will also simplify the life of
anyone who goes to eventually remove gimple_expr_type () as there will
now be less uses.
The function will return a type if and only if we can find the type in
an orderly fashion, and then determine if it is also supported by ranger.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
commit 478cc962ad174bfc64c573152a0658935651fce3
Author: Andrew MacLeod <amacl...@redhat.com>
Date: Thu Jul 15 11:07:12 2021 -0400
Add gimple_range_type for statements.
The existing mechanisms for picking up the type of a statement are
inconsistent with the needs of ranger. Encapsulate all the bits
required to pick up the return type of a statement in one place, and check
whether the type is supported.
* gimple-range-fold.cc (adjust_pointer_diff_expr): Use
gimple_range_type.
(fold_using_range::fold_stmt): Ditto.
(fold_using_range::range_of_range_op): Ditto.
(fold_using_range::range_of_phi): Ditto.
(fold_using_range::range_of_call): Ditto.
(fold_using_range::range_of_builtin_ubsan_call): Ditto.
(fold_using_range::range_of_builtin_call): Ditto.
(fold_using_range::range_of_cond_expr): Ditto.
* gimple-range-fold.h (gimple_range_type): New.
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index eff5d1f89f2..f8578c013bc 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -362,7 +362,7 @@ adjust_pointer_diff_expr (irange &res, const gimple *diff_stmt)
{
tree max = vrp_val_max (ptrdiff_type_node);
wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE (max)));
- tree expr_type = gimple_expr_type (diff_stmt);
+ tree expr_type = gimple_range_type (diff_stmt);
tree range_min = build_zero_cst (expr_type);
tree range_max = wide_int_to_tree (expr_type, wmax - 1);
int_range<2> r (range_min, range_max);
@@ -522,16 +522,8 @@ fold_using_range::fold_stmt (irange &r, gimple *s, fur_source &src, tree name)
if (!res)
{
- // If no name is specified, try the expression kind.
- if (!name)
- {
- tree t = gimple_expr_type (s);
- if (!irange::supports_type_p (t))
- return false;
- r.set_varying (t);
- return true;
- }
- if (!gimple_range_ssa_p (name))
+ // If no name specified or range is unsupported, bail.
+ if (!name || !gimple_range_ssa_p (name))
return false;
// We don't understand the stmt, so return the global range.
r = gimple_range_global (name);
@@ -558,10 +550,11 @@ bool
fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
{
int_range_max range1, range2;
- tree type = gimple_expr_type (s);
+ tree type = gimple_range_type (s);
+ if (!type)
+ return false;
range_operator *handler = gimple_range_handler (s);
gcc_checking_assert (handler);
- gcc_checking_assert (irange::supports_type_p (type));
tree lhs = gimple_get_lhs (s);
tree op1 = gimple_range_operand1 (s);
@@ -719,11 +712,11 @@ bool
fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
{
tree phi_def = gimple_phi_result (phi);
- tree type = TREE_TYPE (phi_def);
+ tree type = gimple_range_type (phi);
int_range_max arg_range;
unsigned x;
- if (!irange::supports_type_p (type))
+ if (!type)
return false;
// Start with an empty range, unioning in each argument's range.
@@ -780,13 +773,13 @@ fold_using_range::range_of_phi (irange &r, gphi *phi, fur_source &src)
bool
fold_using_range::range_of_call (irange &r, gcall *call, fur_source &src)
{
- tree type = gimple_call_return_type (call);
+ tree type = gimple_range_type (call);
+ if (!type)
+ return false;
+
tree lhs = gimple_call_lhs (call);
bool strict_overflow_p;
- if (!irange::supports_type_p (type))
- return false;
-
if (range_of_builtin_call (r, call, src))
;
else if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
@@ -817,7 +810,7 @@ fold_using_range::range_of_builtin_ubsan_call (irange &r, gcall *call,
{
gcc_checking_assert (code == PLUS_EXPR || code == MINUS_EXPR
|| code == MULT_EXPR);
- tree type = gimple_call_return_type (call);
+ tree type = gimple_range_type (call);
range_operator *op = range_op_handler (code, type);
gcc_checking_assert (op);
int_range_max ir0, ir1;
@@ -853,7 +846,7 @@ fold_using_range::range_of_builtin_call (irange &r, gcall *call,
if (func == CFN_LAST)
return false;
- tree type = gimple_call_return_type (call);
+ tree type = gimple_range_type (call);
tree arg;
int mini, maxi, zerov = 0, prec;
scalar_int_mode mode;
@@ -1094,12 +1087,12 @@ fold_using_range::range_of_cond_expr (irange &r, gassign *s, fur_source &src)
tree op1 = gimple_assign_rhs2 (s);
tree op2 = gimple_assign_rhs3 (s);
- gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR);
- gcc_checking_assert (useless_type_conversion_p (TREE_TYPE (op1),
- TREE_TYPE (op2)));
- if (!irange::supports_type_p (TREE_TYPE (op1)))
+ tree type = gimple_range_type (s);
+ if (!type)
return false;
+ gcc_checking_assert (gimple_assign_rhs_code (s) == COND_EXPR);
+ gcc_checking_assert (range_compatible_p (TREE_TYPE (op1), TREE_TYPE (op2)));
src.get_operand (cond_range, cond);
src.get_operand (range1, op1);
src.get_operand (range2, op2);
@@ -1118,6 +1111,7 @@ fold_using_range::range_of_cond_expr (irange &r, gassign *s, fur_source &src)
r = range1;
r.union_ (range2);
}
+ gcc_checking_assert (range_compatible_p (r.type (), type));
return true;
}
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index dc1b28f9acc..ceed7ba48e1 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -56,6 +56,36 @@ gimple_range_handler (const gimple *s)
return NULL;
}
+// Return the type of range which statement S calculates. If the type is
+// unsupported or no type can be determined, return NULL_TREE.
+
+static inline tree
+gimple_range_type (const gimple *s)
+{
+ tree lhs = gimple_get_lhs (s);
+ tree type = NULL_TREE;
+ if (lhs)
+ type = TREE_TYPE (lhs);
+ else
+ {
+ enum gimple_code code = gimple_code (s);
+ if (code == GIMPLE_COND)
+ type = boolean_type_node;
+ else if (code == GIMPLE_PHI)
+ type = TREE_TYPE (gimple_phi_result (s));
+ else if (code == GIMPLE_CALL)
+ {
+ type = gimple_call_fntype (s);
+ // If it has a type, get the return type.
+ if (type)
+ type = TREE_TYPE (type);
+ }
+ }
+ if (irange::supports_type_p (type))
+ return type;
+ return NULL_TREE;
+}
+
// Return EXP if it is an SSA_NAME with a type supported by gimple ranges.
static inline tree