diff options
author | Alan Lawrence <alan.lawrence@arm.com> | 2016-01-18 12:40:43 +0000 |
---|---|---|
committer | Alan Lawrence <alalaw01@gcc.gnu.org> | 2016-01-18 12:40:43 +0000 |
commit | 70c1e88677b6ae08f831c65dcabb61c769ec81b9 (patch) | |
tree | eaea0b92557fe575b8ace8128f18a7c2ea06d16e /gcc/tree-ssa-scopedtables.c | |
parent | d75d9f91e3b35766c80935212f248fc72ae48f58 (diff) | |
download | gcc-70c1e88677b6ae08f831c65dcabb61c769ec81b9.zip gcc-70c1e88677b6ae08f831c65dcabb61c769ec81b9.tar.gz gcc-70c1e88677b6ae08f831c65dcabb61c769ec81b9.tar.bz2 |
Equate MEM_REFs and ARRAY_REFs in tree-ssa-scopedtables.c
PR target/63679
gcc/:
* tree-ssa-scopedtables.c (avail_expr_hash): Hash MEM_REF and ARRAY_REF
using get_ref_base_and_extent.
(equal_mem_array_ref_p): New.
(hashable_expr_equal_p): Add call to previous.
gcc/testsuite/:
* gcc.dg/tree-ssa/ssa-dom-cse-5.c: New.
* gcc.dg/tree-ssa/ssa-dom-cse-6.c: New.
* gcc.dg/tree-ssa/ssa-dom-cse-7.c: New.
From-SVN: r232508
Diffstat (limited to 'gcc/tree-ssa-scopedtables.c')
-rw-r--r-- | gcc/tree-ssa-scopedtables.c | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c index 16d29d6..af79535 100644 --- a/gcc/tree-ssa-scopedtables.c +++ b/gcc/tree-ssa-scopedtables.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "tree-eh.h" #include "internal-fn.h" +#include "tree-dfa.h" static bool hashable_expr_equal_p (const struct hashable_expr *, const struct hashable_expr *); @@ -209,11 +210,70 @@ avail_expr_hash (class expr_hash_elt *p) const struct hashable_expr *expr = p->expr (); inchash::hash hstate; + if (expr->kind == EXPR_SINGLE) + { + /* T could potentially be a switch index or a goto dest. */ + tree t = expr->ops.single.rhs; + if (TREE_CODE (t) == MEM_REF || TREE_CODE (t) == ARRAY_REF) + { + /* Make equivalent statements of both these kinds hash together. + Dealing with both MEM_REF and ARRAY_REF allows us not to care + about equivalence with other statements not considered here. */ + bool reverse; + HOST_WIDE_INT offset, size, max_size; + tree base = get_ref_base_and_extent (t, &offset, &size, &max_size, + &reverse); + /* Strictly, we could try to normalize variable-sized accesses too, + but here we just deal with the common case. */ + if (size == max_size) + { + enum tree_code code = MEM_REF; + hstate.add_object (code); + inchash::add_expr (base, hstate); + hstate.add_object (offset); + hstate.add_object (size); + return hstate.end (); + } + } + } + inchash::add_hashable_expr (expr, hstate); return hstate.end (); } +/* Compares trees T0 and T1 to see if they are MEM_REF or ARRAY_REFs equivalent + to each other. (That is, they return the value of the same bit of memory.) + + Return TRUE if the two are so equivalent; FALSE if not (which could still + mean the two are equivalent by other means). */ + +static bool +equal_mem_array_ref_p (tree t0, tree t1) +{ + if (TREE_CODE (t0) != MEM_REF && TREE_CODE (t0) != ARRAY_REF) + return false; + if (TREE_CODE (t1) != MEM_REF && TREE_CODE (t1) != ARRAY_REF) + return false; + + if (!types_compatible_p (TREE_TYPE (t0), TREE_TYPE (t1))) + return false; + bool rev0; + HOST_WIDE_INT off0, sz0, max0; + tree base0 = get_ref_base_and_extent (t0, &off0, &sz0, &max0, &rev0); + + bool rev1; + HOST_WIDE_INT off1, sz1, max1; + tree base1 = get_ref_base_and_extent (t1, &off1, &sz1, &max1, &rev1); + + /* Types were compatible, so these are sanity checks. */ + gcc_assert (sz0 == sz1); + gcc_assert (max0 == max1); + gcc_assert (rev0 == rev1); + + return (off0 == off1) && operand_equal_p (base0, base1, 0); +} + /* Compare two hashable_expr structures for equivalence. They are considered equivalent when the expressions they denote must necessarily be equal. The logic is intended to follow that of @@ -246,9 +306,10 @@ hashable_expr_equal_p (const struct hashable_expr *expr0, switch (expr0->kind) { case EXPR_SINGLE: - return operand_equal_p (expr0->ops.single.rhs, - expr1->ops.single.rhs, 0); - + return equal_mem_array_ref_p (expr0->ops.single.rhs, + expr1->ops.single.rhs) + || operand_equal_p (expr0->ops.single.rhs, + expr1->ops.single.rhs, 0); case EXPR_UNARY: if (expr0->ops.unary.op != expr1->ops.unary.op) return false; |