[PATCH] Fix PR33563, another DSE miscompile
Richard Guenther
rguenther@suse.de
Wed Sep 26 16:19:00 GMT 2007
We were not handling uses in aggregate stores.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.
Richard.
2007-09-26 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33563
* tree-ssa-dse.c (get_use_of_stmt_lhs): Rename to ...
(get_kill_of_stmt_lhs): ... this. Re-structure. Handle
aggregate stores.
(dse_optimize_stmt): Call get_kill_of_stmt_lhs instead of
get_use_of_stmt_lhs.
* gcc.dg/torture/pr33563.c: New testcase.
Index: tree-ssa-dse.c
===================================================================
*** tree-ssa-dse.c (revision 128810)
--- tree-ssa-dse.c (working copy)
*************** memory_address_same (tree store1, tree s
*** 210,271 ****
== 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 the use is not simple, give up. */
! if (TREE_CODE (*use_stmt) != GIMPLE_MODIFY_STMT
! || get_call_expr_in (*use_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
! || get_call_expr_in (*use_stmt))
! return NULL_TREE;
}
while (1);
-
- return NULL_TREE;
}
/* A helper of dse_optimize_stmt.
--- 210,271 ----
== NULL);
}
! /* Return true if there is a stmt that kills the lhs of STMT and is in the
! virtual def-use chain of STMT without a use inbetween the kill and STMT.
! Returns false if no such stmt is found.
! *FIRST_USE_P is set to the first use of the single virtual def of
! STMT. *USE_P is set to the vop killed by *USE_STMT. */
!
! static bool
! get_kill_of_stmt_lhs (tree stmt,
! use_operand_p * first_use_p,
! use_operand_p * use_p, tree * use_stmt)
{
! tree lhs;
! gcc_assert (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
lhs = GIMPLE_STMT_OPERAND (stmt, 0);
! /* We now walk the chain of single uses of the single VDEFs.
! We succeeded finding a kill if the lhs of the use stmt is
! equal to the original lhs. We can keep walking to the next
! use if there are no possible uses of the original lhs in
! the stmt. */
do
{
! tree use_lhs, use_rhs;
! def_operand_p def_p;
!
! /* 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 false;
! /* Get the single immediate use of the def. */
! if (!single_imm_use (DEF_FROM_PTR (def_p), first_use_p, &stmt))
! return false;
! first_use_p = use_p;
!
! /* If there are possible hidden uses, give up. */
! if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
! return false;
! use_rhs = GIMPLE_STMT_OPERAND (stmt, 1);
! if (TREE_CODE (use_rhs) == CALL_EXPR
! || (!is_gimple_min_invariant (use_rhs)
! && TREE_CODE (use_rhs) != SSA_NAME))
! return false;
!
! /* If the use stmts lhs matches the original lhs we have
! found the kill, otherwise continue walking. */
! use_lhs = GIMPLE_STMT_OPERAND (stmt, 0);
! if (operand_equal_p (use_lhs, lhs, 0))
! {
! *use_stmt = stmt;
! return true;
! }
}
while (1);
}
/* A helper of dse_optimize_stmt.
*************** dse_optimize_stmt (struct dom_walk_data
*** 448,455 ****
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;
--- 448,454 ----
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_kill_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt))
{
record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
return;
Index: testsuite/gcc.dg/torture/pr33563.c
===================================================================
*** testsuite/gcc.dg/torture/pr33563.c (revision 0)
--- testsuite/gcc.dg/torture/pr33563.c (revision 0)
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do run } */
+ /* { dg-options "--param max-aliased-vops=0" } */
+
+ struct T
+ {
+ int a, b;
+ } t, q;
+
+ int main (void)
+ {
+ struct T *p;
+
+ t.a = 1;
+ t.b = 2;
+ q = t;
+ t.a = 3;
+
+ if (q.a != 1)
+ __builtin_abort ();
+
+ return 0;
+ }
More information about the Gcc-patches
mailing list