re PR tree-optimization/67955 (tree-dse does not use pointer info)
authorTom de Vries <tom@codesourcery.com>
Tue, 6 Dec 2016 23:18:17 +0000 (23:18 +0000)
committerJeff Law <law@gcc.gnu.org>
Tue, 6 Dec 2016 23:18:17 +0000 (16:18 -0700)
PR tree-optimization/67955
* tree-ssa-alias.c (same_addr_size_stores_p): New function.
(stmt_kills_ref_p): Use it.

PR tree-optimization/67955
* gcc.dg/tree-ssa/dse-points-to.c: New test.

From-SVN: r243325

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/dse-points-to.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index 61eeea3..797b711 100644 (file)
@@ -1,3 +1,9 @@
+2016-12-06  Tom de Vries  <tom@codesourcery.com>
+
+       PR tree-optimization/67955
+       * tree-ssa-alias.c (same_addr_size_stores_p): New function.
+       (stmt_kills_ref_p): Use it.
+
 2016-12-06  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR middle-end/78700
index 5adcdd2..6090a96 100644 (file)
@@ -1,3 +1,8 @@
+2016-12-06  Tom de Vries  <tom@codesourcery.com>
+
+       PR tree-optimization/67955
+       * gcc.dg/tree-ssa/dse-points-to.c: New test.
+
 2016-12-06  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        PR target/78658
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dse-points-to.c b/gcc/testsuite/gcc.dg/tree-ssa/dse-points-to.c
new file mode 100644 (file)
index 0000000..8003556
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fno-tree-vrp" } */
+/* { dg-additional-options "-fdump-tree-dse1-details" } */
+
+int
+f ()
+{
+  int a;
+  int *p = &a;
+  *p = 1;
+  a = 2;
+  return a;
+}
+
+/* { dg-final { scan-tree-dump-times "Deleted dead store.*p_1" 1 "dse1"} } */
index 10f1677..37b581d 100644 (file)
@@ -2316,6 +2316,78 @@ stmt_may_clobber_ref_p (gimple *stmt, tree ref)
   return stmt_may_clobber_ref_p_1 (stmt, &r);
 }
 
+/* Return true if store1 and store2 described by corresponding tuples
+   <BASE, OFFSET, SIZE, MAX_SIZE> have the same size and store to the same
+   address.  */
+
+static bool
+same_addr_size_stores_p (tree base1, HOST_WIDE_INT offset1, HOST_WIDE_INT size1,
+                        HOST_WIDE_INT max_size1,
+                        tree base2, HOST_WIDE_INT offset2, HOST_WIDE_INT size2,
+                        HOST_WIDE_INT max_size2)
+{
+  /* For now, just handle VAR_DECL.  */
+  bool base1_obj_p = VAR_P (base1);
+  bool base2_obj_p = VAR_P (base2);
+
+  /* We need one object.  */
+  if (base1_obj_p == base2_obj_p)
+    return false;
+  tree obj = base1_obj_p ? base1 : base2;
+
+  /* And we need one MEM_REF.  */
+  bool base1_memref_p = TREE_CODE (base1) == MEM_REF;
+  bool base2_memref_p = TREE_CODE (base2) == MEM_REF;
+  if (base1_memref_p == base2_memref_p)
+    return false;
+  tree memref = base1_memref_p ? base1 : base2;
+
+  /* Sizes need to be valid.  */
+  if (max_size1 == -1 || max_size2 == -1
+      || size1 == -1 || size2 == -1)
+    return false;
+
+  /* Max_size needs to match size.  */
+  if (max_size1 != size1
+      || max_size2 != size2)
+    return false;
+
+  /* Sizes need to match.  */
+  if (size1 != size2)
+    return false;
+
+  /* Offsets need to be 0.  */
+  if (offset1 != 0
+      || offset2 != 0)
+    return false;
+
+  /* Check that memref is a store to pointer with singleton points-to info.  */
+  if (!tree_int_cst_equal (TREE_OPERAND (memref, 1), integer_zero_node))
+    return false;
+  tree ptr = TREE_OPERAND (memref, 0);
+  if (TREE_CODE (ptr) != SSA_NAME)
+    return false;
+  struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
+  unsigned int pt_uid;
+  if (pi == NULL
+      || !pt_solution_singleton_or_null_p (&pi->pt, &pt_uid))
+    return false;
+
+  /* Check that ptr points relative to obj.  */
+  unsigned int obj_uid = (DECL_PT_UID_SET_P (obj)
+                         ? DECL_PT_UID (obj)
+                         : DECL_UID (obj));
+  if (obj_uid != pt_uid)
+    return false;
+
+  /* Check that the object size is the same as the store size.  That ensures us
+     that ptr points to the start of obj.  */
+  if (!tree_fits_shwi_p (DECL_SIZE (obj)))
+    return false;
+  HOST_WIDE_INT obj_size = tree_to_shwi (DECL_SIZE (obj));
+  return obj_size == size1;
+}
+
 /* If STMT kills the memory reference REF return true, otherwise
    return false.  */
 
@@ -2393,6 +2465,11 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
         so base == ref->base does not always hold.  */
       if (base != ref->base)
        {
+         /* Try using points-to info.  */
+         if (same_addr_size_stores_p (base, offset, size, max_size, ref->base,
+                                      ref->offset, ref->size, ref->max_size))
+           return true;
+
          /* If both base and ref->base are MEM_REFs, only compare the
             first operand, and if the second operand isn't equal constant,
             try to add the offsets into offset and ref_offset.  */