diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2020-06-04 11:15:21 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2020-06-04 14:33:46 +0200 |
commit | a5b9a237d6b83b5956894ce82b70b97cd7620e41 (patch) | |
tree | 04a1d2489e9f85265d0f4e5ecc34d4a89e2ee6e4 | |
parent | c6e8b9bb06e4ba28dafcd685b8f85167b55ac829 (diff) | |
download | gcc-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.cc | 34 | ||||
-rw-r--r-- | gcc/gimple-range-cfg.h | 1 | ||||
-rw-r--r-- | gcc/gimple-range-stmt.cc | 28 | ||||
-rw-r--r-- | gcc/gimple-range-stmt.h | 1 |
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, |