diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/dse.c | 32 | ||||
-rw-r--r-- | gcc/tree-ssa-dse.c | 80 |
4 files changed, 118 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8fa8e7c..f454c19 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2007-05-13 Revital Eres <eres@il.ibm.com> + + * tree-ssa-dse.c (get_use_of_stmt_lhs): New function + which walks virtual def-use chains to find redundant stores. + (dse_optimize_stmt): Call it. + 2007-05-12 Steven Bosscher <steven@gcc.gnu.org> * gcse.c (gcse_main): Do jump bypassing in CPROP2. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b4ad8f7..586fc11 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-05-13 Revital Eres <eres@il.ibm.com> + + * gcc.dg/dse.c: New test. + 2007-05-12 Richard Guenther <rguenther@suse.de> PR tree-optimization/31797 diff --git a/gcc/testsuite/gcc.dg/dse.c b/gcc/testsuite/gcc.dg/dse.c new file mode 100644 index 0000000..4a859ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/dse.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse-details" } */ + +#define N 256 + +struct +{ + int x; + int y; +} S[100]; + +int z[100]; + +int +foo (void) +{ + int i; + int x, y; + + S[5].x = 0; + S[5].y = 0; + + x = 5 + z[0]; + y = z[0]; + + S[5].x = x; + S[5].y = y; +} + +/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1" } } */ +/* { dg-final { cleanup-tree-dump "dse*" } } */ + diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index bb5d14d..596d4a8 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -237,6 +237,59 @@ memory_address_same (tree store1, tree store2) == NULL); } +/* Return the use stmt for the lhs of STMT following the virtual + def-use chains. Returns the MODIFY_EXPR stmt which lhs is equal to + the lhs of STMT or NULL_TREE if no such stmt can be found. */ +static tree +get_use_of_stmt_lhs (tree stmt, + use_operand_p * first_use_p, + use_operand_p * use_p, tree * use_stmt) +{ + tree usevar, lhs; + def_operand_p def_p; + + if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) + return NULL_TREE; + + lhs = GIMPLE_STMT_OPERAND (stmt, 0); + + /* The stmt must have a single VDEF. */ + def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_VDEF); + if (def_p == NULL_DEF_OPERAND_P) + return NULL_TREE; + + if (!has_single_use (DEF_FROM_PTR (def_p))) + return NULL_TREE; + /* Get the immediate use of the def. */ + single_imm_use (DEF_FROM_PTR (def_p), use_p, use_stmt); + gcc_assert (*use_p != NULL_USE_OPERAND_P); + first_use_p = use_p; + if (TREE_CODE (*use_stmt) != GIMPLE_MODIFY_STMT) + return NULL_TREE; + + do + { + /* Look at the use stmt and see if it's LHS matches + stmt's lhs SSA_NAME. */ + def_p = SINGLE_SSA_DEF_OPERAND (*use_stmt, SSA_OP_VDEF); + if (def_p == NULL_DEF_OPERAND_P) + return NULL_TREE; + + usevar = GIMPLE_STMT_OPERAND (*use_stmt, 0); + if (operand_equal_p (usevar, lhs, 0)) + return *use_stmt; + + if (!has_single_use (DEF_FROM_PTR (def_p))) + return NULL_TREE; + single_imm_use (DEF_FROM_PTR (def_p), use_p, use_stmt); + gcc_assert (*use_p != NULL_USE_OPERAND_P); + if (TREE_CODE (*use_stmt) != GIMPLE_MODIFY_STMT) + return NULL_TREE; + } + while (1); + + return NULL_TREE; +} /* A helper of dse_optimize_stmt. Given a GIMPLE_MODIFY_STMT in STMT, check that each VDEF has one @@ -593,10 +646,29 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, /* If this is a partial store into an aggregate, record it. */ dse_record_partial_aggregate_store (stmt, dse_gd); - /* If we have precisely one immediate use at this point, then we may - 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 (GIMPLE_STMT_OPERAND (stmt, 0), + GIMPLE_STMT_OPERAND (use_stmt, 0), 0) + && !dse_partial_kill_p (stmt, dse_gd)) + && memory_address_same (stmt, use_stmt)) + { + /* If we have precisely one immediate use at this point, but + the stores are not to the same memory location then walk the + virtual def-use chain to get the stmt which stores to that same + memory location. */ + if (get_use_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt) == + NULL_TREE) + { + record_voperand_set (dse_gd->stores, &bd->stores, ann->uid); + return; + } + } + + /* If we have precisely one immediate use at this point and the + stores are to the same memory location or there is a chain of + virtual uses from stmt and the stmt which stores to that same + memory location, then we may have found redundant store. */ if (use_p != NULL_USE_OPERAND_P && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt)) && (operand_equal_p (GIMPLE_STMT_OPERAND (stmt, 0), |