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  <rguent...@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" } } */

Reply via email to