aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20051110-1.c31
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20051110-2.c39
-rw-r--r--gcc/tree-ssa-dse.c72
5 files changed, 151 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bb8033c..5a7d54f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-11-11 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * tree-ssa-dse.c (struct address_walk_data, memory_ssa_name_same)
+ (memory_address_same): New.
+ (dse_optimize_stmt): Call memory_address_same.
+
2005-11-12 Hans-Peter Nilsson <hp@axis.com>
PR middle-end/24750
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 71698c4..aebb7a1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-11 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * gcc.c-torture/execute/20051110-1.c,
+ gcc.c-torture/execute/20051110-2.c: New tests.
+
2005-11-12 Hans-Peter Nilsson <hp@axis.com>
PR middle-end/24750
diff --git a/gcc/testsuite/gcc.c-torture/execute/20051110-1.c b/gcc/testsuite/gcc.c-torture/execute/20051110-1.c
new file mode 100644
index 0000000..9fa3df8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20051110-1.c
@@ -0,0 +1,31 @@
+void add_unwind_adjustsp (long);
+void abort (void);
+
+unsigned char bytes[5];
+
+void
+add_unwind_adjustsp (long offset)
+{
+ int n;
+ unsigned long o;
+
+ o = (long) ((offset - 0x204) >> 2);
+
+ n = 0;
+ while (o)
+ {
+ bytes[n] = o & 0x7f;
+ o >>= 7;
+ if (o)
+ bytes[n] |= 0x80;
+ n++;
+ }
+}
+
+int main(void)
+{
+ add_unwind_adjustsp (4132);
+ if (bytes[0] != 0x88 || bytes[1] != 0x07)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20051110-2.c b/gcc/testsuite/gcc.c-torture/execute/20051110-2.c
new file mode 100644
index 0000000..57bfeeb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20051110-2.c
@@ -0,0 +1,39 @@
+void add_unwind_adjustsp (long);
+void abort (void);
+
+unsigned char bytes[5];
+
+int flag;
+
+void
+add_unwind_adjustsp (long offset)
+{
+ int n;
+ unsigned long o;
+
+ o = (long) ((offset - 0x204) >> 2);
+
+ n = 0;
+ do
+ {
+a:
+ bytes[n] = o & 0x7f;
+ o >>= 7;
+ if (o)
+ {
+ bytes[n] |= 0x80;
+ if (flag)
+ goto a;
+ }
+ n++;
+ }
+ while (o);
+}
+
+int main(void)
+{
+ add_unwind_adjustsp (4132);
+ if (bytes[0] != 0x88 || bytes[1] != 0x07)
+ abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 7087018..fa3ba96 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -83,6 +83,13 @@ struct dse_block_local_data
bitmap stores;
};
+/* Basic blocks of the potentially dead store and the following
+ store, for memory_address_same. */
+struct address_walk_data
+{
+ basic_block store1_bb, store2_bb;
+};
+
static bool gate_dse (void);
static void tree_ssa_dse (void);
static void dse_initialize_block_local_data (struct dom_walk_data *,
@@ -145,6 +152,64 @@ dse_initialize_block_local_data (struct dom_walk_data *walk_data,
}
}
+/* Helper function for memory_address_same via walk_tree. Returns
+ non-NULL if it finds an SSA_NAME which is part of the address,
+ such that the definition of the SSA_NAME post-dominates the store
+ we want to delete but not the store that we believe makes it
+ redundant. This indicates that the address may change between
+ the two stores. */
+
+static tree
+memory_ssa_name_same (tree *expr_p, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
+{
+ struct address_walk_data *walk_data = data;
+ tree expr = *expr_p;
+ tree def_stmt;
+ basic_block def_bb;
+
+ if (TREE_CODE (expr) != SSA_NAME)
+ return NULL_TREE;
+
+ /* If we've found a default definition, then there's no problem. Both
+ stores will post-dominate it. And def_bb will be NULL. */
+ if (expr == default_def (SSA_NAME_VAR (expr)))
+ return NULL_TREE;
+
+ def_stmt = SSA_NAME_DEF_STMT (expr);
+ def_bb = bb_for_stmt (def_stmt);
+
+ /* DEF_STMT must dominate both stores. So if it is in the same
+ basic block as one, it does not post-dominate that store. */
+ if (walk_data->store1_bb != def_bb
+ && dominated_by_p (CDI_POST_DOMINATORS, walk_data->store1_bb, def_bb))
+ {
+ if (walk_data->store2_bb == def_bb
+ || !dominated_by_p (CDI_POST_DOMINATORS, walk_data->store2_bb,
+ def_bb))
+ /* Return non-NULL to stop the walk. */
+ return def_stmt;
+ }
+
+ return NULL_TREE;
+}
+
+/* Return TRUE if the destination memory address in STORE1 and STORE2
+ might be modified after STORE1, before control reaches STORE2. */
+
+static bool
+memory_address_same (tree store1, tree store2)
+{
+ struct address_walk_data walk_data;
+
+ walk_data.store1_bb = bb_for_stmt (store1);
+ walk_data.store2_bb = bb_for_stmt (store2);
+
+ return (walk_tree (&TREE_OPERAND (store1, 0), memory_ssa_name_same,
+ &walk_data, NULL)
+ == NULL);
+}
+
/* Attempt to eliminate dead stores in the statement referenced by BSI.
A dead store is a store into a memory location which will later be
@@ -251,11 +316,14 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
}
/* If we have precisely one immediate use at this point, then we may
- have found redundant store. */
+ have found redundant store. Make sure that the stores are to
+ the same memory location. This includes checking that any
+ SSA-form variables in the address will have the same values. */
if (use_p != NULL_USE_OPERAND_P
&& bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
&& operand_equal_p (TREE_OPERAND (stmt, 0),
- TREE_OPERAND (use_stmt, 0), 0))
+ TREE_OPERAND (use_stmt, 0), 0)
+ && memory_address_same (stmt, use_stmt))
{
/* Make sure we propagate the ABNORMAL bit setting. */
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (first_use_p)))