aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-scopedtables.c
diff options
context:
space:
mode:
authorAlan Lawrence <alan.lawrence@arm.com>2016-01-18 12:40:43 +0000
committerAlan Lawrence <alalaw01@gcc.gnu.org>2016-01-18 12:40:43 +0000
commit70c1e88677b6ae08f831c65dcabb61c769ec81b9 (patch)
treeeaea0b92557fe575b8ace8128f18a7c2ea06d16e /gcc/tree-ssa-scopedtables.c
parentd75d9f91e3b35766c80935212f248fc72ae48f58 (diff)
downloadgcc-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.c67
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;