{
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);
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);
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);
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.
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))
{
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;
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;
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);
r = range1;
r.union_ (range2);
}
+ gcc_checking_assert (range_compatible_p (r.type (), type));
return true;
}
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