[PATCH][1/2] Improve DSE
Richard Biener
rguenther@suse.de
Wed Jun 4 10:39:00 GMT 2014
This first patch improves DSE by improving the handling of
references with non-invariant addresses such as
a->b[i].c in stmt_kills_ref_p_1.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Richard.
2014-06-04 Richard Biener <rguenther@suse.de>
* tree-ssa-alias.c (stmt_may_clobber_ref_p): Improve handling
of accesses with non-invariant address.
* gcc.dg/tree-ssa/ssa-dse-16.c: New testcase.
Index: gcc/tree-ssa-alias.c
===================================================================
*** gcc/tree-ssa-alias.c (revision 211213)
--- gcc/tree-ssa-alias.c (working copy)
*************** stmt_may_clobber_ref_p (gimple stmt, tre
*** 2174,2184 ****
static bool
stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
{
! /* For a must-alias check we need to be able to constrain
! the access properly.
! FIXME: except for BUILTIN_FREE. */
! if (!ao_ref_base (ref)
! || ref->max_size == -1)
return false;
if (gimple_has_lhs (stmt)
--- 2174,2180 ----
static bool
stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
{
! if (!ao_ref_base (ref))
return false;
if (gimple_has_lhs (stmt)
*************** stmt_kills_ref_p_1 (gimple stmt, ao_ref
*** 2191,2199 ****
might throw as well. */
&& !stmt_can_throw_internal (stmt))
{
! tree base, lhs = gimple_get_lhs (stmt);
HOST_WIDE_INT size, offset, max_size, ref_offset = ref->offset;
! base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
/* We can get MEM[symbol: sZ, index: D.8862_1] here,
so base == ref->base does not always hold. */
if (base != ref->base)
--- 2187,2237 ----
might throw as well. */
&& !stmt_can_throw_internal (stmt))
{
! tree lhs = gimple_get_lhs (stmt);
! /* If LHS is literally a base of the access we are done. */
! if (ref->ref)
! {
! tree base = ref->ref;
! if (handled_component_p (base))
! {
! tree saved_lhs0 = NULL_TREE;
! if (handled_component_p (lhs))
! {
! saved_lhs0 = TREE_OPERAND (lhs, 0);
! TREE_OPERAND (lhs, 0) = integer_zero_node;
! }
! do
! {
! /* Just compare the outermost handled component, if
! they are equal we have found a possible common
! base. */
! tree saved_base0 = TREE_OPERAND (base, 0);
! TREE_OPERAND (base, 0) = integer_zero_node;
! bool res = operand_equal_p (lhs, base, 0);
! TREE_OPERAND (base, 0) = saved_base0;
! if (res)
! break;
! /* Otherwise drop handled components of the access. */
! base = saved_base0;
! }
! while (handled_component_p (base));
! if (saved_lhs0)
! TREE_OPERAND (lhs, 0) = saved_lhs0;
! }
! /* Finally check if lhs is equal or equal to the base candidate
! of the access. */
! if (operand_equal_p (lhs, base, 0))
! return true;
! }
!
! /* Now look for non-literal equal bases with the restriction of
! handling constant offset and size. */
! /* For a must-alias check we need to be able to constrain
! the access properly. */
! if (ref->max_size == -1)
! return false;
HOST_WIDE_INT size, offset, max_size, ref_offset = ref->offset;
! tree base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
/* We can get MEM[symbol: sZ, index: D.8862_1] here,
so base == ref->base does not always hold. */
if (base != ref->base)
*************** stmt_kills_ref_p_1 (gimple stmt, ao_ref
*** 2261,2266 ****
--- 2299,2308 ----
case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMSET_CHK:
{
+ /* For a must-alias check we need to be able to constrain
+ the access properly. */
+ if (ref->max_size == -1)
+ return false;
tree dest = gimple_call_arg (stmt, 0);
tree len = gimple_call_arg (stmt, 2);
if (!tree_fits_shwi_p (len))
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-16.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-16.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-16.c (working copy)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse1-details" } */
+
+struct X { struct A { int a[2]; } b[10]; };
+void foo (struct X *x, int i)
+{
+ struct A a;
+ /* Confuse SRA here with using a variable index, otherwise it will mess
+ with the IL too much. */
+ a.a[i] = 3;
+ a.a[1] = 0;
+ /* The following store is dead. */
+ x->b[i].a[0] = 1;
+ x->b[i] = a;
+}
+
+/* { dg-final { scan-tree-dump "Deleted dead store" "dse1" } } */
+/* { dg-final { cleanup-tree-dump "dse1" } } */
More information about the Gcc-patches
mailing list