Commit 70c1e886 by Alan Lawrence Committed by Alan Lawrence

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
parent d75d9f91
2016-01-18 Alan Lawrence <alan.lawrence@arm.com> 2016-01-18 Alan Lawrence <alan.lawrence@arm.com>
PR target/63679 PR target/63679
* 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.
2016-01-18 Alan Lawrence <alan.lawrence@arm.com>
PR target/63679
* tree-sra.c (disqualified_constants, constant_decl_p): New. * tree-sra.c (disqualified_constants, constant_decl_p): New.
(sra_initialize): Allocate disqualified_constants. (sra_initialize): Allocate disqualified_constants.
(sra_deinitialize): Free disqualified_constants. (sra_deinitialize): Free disqualified_constants.
......
2016-01-18 Alan Lawrence <alan.lawrence@arm.com> 2016-01-18 Alan Lawrence <alan.lawrence@arm.com>
PR target/63679 PR target/63679
* 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.
2016-01-18 Alan Lawrence <alan.lawrence@arm.com>
PR target/63679
* gcc.dg/tree-ssa/sra-17.c: New. * gcc.dg/tree-ssa/sra-17.c: New.
* gcc.dg/tree-ssa/sra-18.c: New. * gcc.dg/tree-ssa/sra-18.c: New.
......
/* Test normalization of ARRAY_REF expressions to MEM_REFs in dom. */
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-fre -fdump-tree-dom2" } */
#define N 8
int
main (int argc, char **argv)
{
int a[N];
for (int i = 0; i < N; i++)
a[i] = 2*i + 1;
int *p = &a[0];
__builtin_printf ("%d\n", a[argc]);
return *(++p);
}
/* { dg-final { scan-tree-dump-times "return 3;" 1 "dom2"} } */
/* Test normalization of ARRAY_REF expressions to MEM_REFs in dom. */
/* { dg-do compile } */
/* { dg-options "-O1 -fno-tree-fre -fdump-tree-dom2" } */
int
main (int argc, char **argv)
{
union {
int a[4];
int b[2];
} u;
u.a[0] = 1;
u.a[1] = 42;
u.a[2] = 3;
u.a[3] = 4;
__builtin_printf ("%d\n", u.a[argc]);
return u.b[1];
}
/* { dg-final { scan-tree-dump-times "return 42;" 1 "dom2" } } */
/* Test normalization of MEM_REF expressions in dom. */
/* { dg-do compile } */
/* { dg-options "-O3 -fno-tree-fre -fno-tree-pre -fdump-tree-optimized" } */
typedef struct {
int a[8];
} foo;
foo f;
int
test ()
{
foo g;
g.a[0] = 1; g.a[1] = 2; g.a[2] = 3; g.a[3] = 4;
g.a[4] = 5; g.a[5] = 6; g.a[6] = 7; g.a[7] = 8;
f=g;
return f.a[2];
}
/* { dg-final { scan-tree-dump-times "return 3;" 1 "optimized" } } */
...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const.h" #include "fold-const.h"
#include "tree-eh.h" #include "tree-eh.h"
#include "internal-fn.h" #include "internal-fn.h"
#include "tree-dfa.h"
static bool hashable_expr_equal_p (const struct hashable_expr *, static bool hashable_expr_equal_p (const struct hashable_expr *,
const struct hashable_expr *); const struct hashable_expr *);
...@@ -209,11 +210,70 @@ avail_expr_hash (class expr_hash_elt *p) ...@@ -209,11 +210,70 @@ avail_expr_hash (class expr_hash_elt *p)
const struct hashable_expr *expr = p->expr (); const struct hashable_expr *expr = p->expr ();
inchash::hash hstate; 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); inchash::add_hashable_expr (expr, hstate);
return hstate.end (); 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 /* Compare two hashable_expr structures for equivalence. They are
considered equivalent when the expressions they denote must considered equivalent when the expressions they denote must
necessarily be equal. The logic is intended to follow that of necessarily be equal. The logic is intended to follow that of
...@@ -246,9 +306,10 @@ hashable_expr_equal_p (const struct hashable_expr *expr0, ...@@ -246,9 +306,10 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
switch (expr0->kind) switch (expr0->kind)
{ {
case EXPR_SINGLE: case EXPR_SINGLE:
return operand_equal_p (expr0->ops.single.rhs, return equal_mem_array_ref_p (expr0->ops.single.rhs,
expr1->ops.single.rhs, 0); expr1->ops.single.rhs)
|| operand_equal_p (expr0->ops.single.rhs,
expr1->ops.single.rhs, 0);
case EXPR_UNARY: case EXPR_UNARY:
if (expr0->ops.unary.op != expr1->ops.unary.op) if (expr0->ops.unary.op != expr1->ops.unary.op)
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment