aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2020-06-04 11:15:21 +0200
committerAldy Hernandez <aldyh@redhat.com>2020-06-04 14:33:46 +0200
commita5b9a237d6b83b5956894ce82b70b97cd7620e41 (patch)
tree04a1d2489e9f85265d0f4e5ecc34d4a89e2ee6e4
parentc6e8b9bb06e4ba28dafcd685b8f85167b55ac829 (diff)
downloadgcc-a5b9a237d6b83b5956894ce82b70b97cd7620e41.zip
gcc-a5b9a237d6b83b5956894ce82b70b97cd7620e41.tar.gz
gcc-a5b9a237d6b83b5956894ce82b70b97cd7620e41.tar.bz2
Adjust range_of_range_op to handle non-trivial assignments involving an ADDR_EXPR.
-rw-r--r--gcc/gimple-range-cfg.cc34
-rw-r--r--gcc/gimple-range-cfg.h1
-rw-r--r--gcc/gimple-range-stmt.cc28
-rw-r--r--gcc/gimple-range-stmt.h1
4 files changed, 53 insertions, 11 deletions
diff --git a/gcc/gimple-range-cfg.cc b/gcc/gimple-range-cfg.cc
index 23cef01..f513fd8 100644
--- a/gcc/gimple-range-cfg.cc
+++ b/gcc/gimple-range-cfg.cc
@@ -144,6 +144,9 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s)
tree op1 = gimple_range_operand1 (s);
tree op2 = gimple_range_operand2 (s);
+ if (range_of_non_trivial_assignment (r, s))
+ return true;
+
if (range_of_expr (range1, op1, s))
{
if (!op2)
@@ -157,6 +160,37 @@ gimple_ranger::range_of_range_op (irange &r, gimple *s)
}
+// Calculate the range of a non-trivial assignment. That is, is one
+// inolving arithmetic on an SSA name (for example, an ADDR_EXPR).
+// Return the range in R.
+//
+// If a range cannot be calculated, return false.
+
+bool
+gimple_ranger::range_of_non_trivial_assignment (irange &r, gimple *stmt)
+{
+ if (gimple_code (stmt) != GIMPLE_ASSIGN)
+ return false;
+
+ tree base = gimple_range_base_of_assignment (stmt);
+ if (base && TREE_CODE (base) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
+ {
+ widest_irange range1;
+ tree ssa = TREE_OPERAND (base, 0);
+ if (range_of_expr (range1, ssa, stmt))
+ {
+ tree type = TREE_TYPE (ssa);
+ range_operator *op = range_op_handler (POINTER_PLUS_EXPR, type);
+ int_range<1> offset (TREE_OPERAND (base, 1), TREE_OPERAND (base, 1));
+ op->fold_range (r, type, range1, offset);
+ return true;
+ }
+ }
+ return false;
+}
+
+
// Calculate a range for phi statement S and return it in R.
// If a range cannot be calculated, return false.
diff --git a/gcc/gimple-range-cfg.h b/gcc/gimple-range-cfg.h
index 18d730b..7e74ddf 100644
--- a/gcc/gimple-range-cfg.h
+++ b/gcc/gimple-range-cfg.h
@@ -36,6 +36,7 @@ protected:
bool range_of_call (irange &r, gcall *call);
bool range_of_cond_expr (irange &r, gassign* cond);
private:
+ bool range_of_non_trivial_assignment (irange &r, gimple *s);
bool range_of_builtin_call (irange &r, gcall *call);
void range_of_builtin_ubsan_call (irange &r, gcall *call, tree_code code);
};
diff --git a/gcc/gimple-range-stmt.cc b/gcc/gimple-range-stmt.cc
index f5d3a3f..81f2bb5 100644
--- a/gcc/gimple-range-stmt.cc
+++ b/gcc/gimple-range-stmt.cc
@@ -287,6 +287,17 @@ gimple_range_fold (const gimple *stmt, irange &res,
return true;
}
+// Return the base of the RHS of an assignment.
+
+tree
+gimple_range_base_of_assignment (const gimple *stmt)
+{
+ gcc_checking_assert (gimple_code (stmt) == GIMPLE_ASSIGN);
+ tree op1 = gimple_assign_rhs1 (stmt);
+ if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+ return get_base_address (TREE_OPERAND (op1, 0));
+ return op1;
+}
// Return the first operand of this statement if it is a valid operand
// supported by ranges, otherwise return NULL_TREE. Special case is
@@ -303,24 +314,19 @@ gimple_range_operand1 (const gimple *stmt)
return gimple_cond_lhs (stmt);
case GIMPLE_ASSIGN:
{
- tree expr = gimple_assign_rhs1 (stmt);
- if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
+ tree base = gimple_range_base_of_assignment (stmt);
+ if (base && TREE_CODE (base) == MEM_REF)
{
// If the base address is an SSA_NAME, we return it
// here. This allows processing of the range of that
// name, while the rest of the expression is simply
// ignored. The code in range_ops will see the
// ADDR_EXPR and do the right thing.
- tree base = get_base_address (TREE_OPERAND (expr, 0));
- if (base != NULL_TREE && TREE_CODE (base) == MEM_REF)
- {
- // If the base address is an SSA_NAME, return it.
- tree b = TREE_OPERAND (base, 0);
- if (TREE_CODE (b) == SSA_NAME)
- return b;
- }
+ tree ssa = TREE_OPERAND (base, 0);
+ if (TREE_CODE (ssa) == SSA_NAME)
+ return ssa;
}
- return expr;
+ return base;
}
default:
break;
diff --git a/gcc/gimple-range-stmt.h b/gcc/gimple-range-stmt.h
index ddc6872..c27f15d 100644
--- a/gcc/gimple-range-stmt.h
+++ b/gcc/gimple-range-stmt.h
@@ -38,6 +38,7 @@ extern gimple *gimple_outgoing_edge_range_p (irange &r, edge e);
// These routines provide a GIMPLE interface to the range-ops code.
extern tree gimple_range_operand1 (const gimple *s);
extern tree gimple_range_operand2 (const gimple *s);
+extern tree gimple_range_base_of_assignment (const gimple *s);
extern bool gimple_range_fold (const gimple *s, irange &res,
const irange &r1);
extern bool gimple_range_fold (const gimple *s, irange &res,