PR tree-optimization/45970
* tree-ssa-alias.h (stmt_kills_ref_p): Declare.
* tree-ssa-alias.c (stmt_kills_ref_p_1): New function.
(stmt_kills_ref_p): Likewise.
* tree-ssa-dse.c (dse_optimize_stmt): Use it.
* gcc.dg/tree-ssa/ssa-dse-13.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@165422
138bc75d-0d04-0410-961f-
82ee72b054a4
2010-10-13 Richard Guenther <rguenther@suse.de>
+ PR tree-optimization/45970
+ * tree-ssa-alias.h (stmt_kills_ref_p): Declare.
+ * tree-ssa-alias.c (stmt_kills_ref_p_1): New function.
+ (stmt_kills_ref_p): Likewise.
+ * tree-ssa-dse.c (dse_optimize_stmt): Use it.
+
+2010-10-13 Richard Guenther <rguenther@suse.de>
+
PR tree-optimization/45982
* tree-ssa-structalias.c (make_constraints_to): New function.
(make_constraint_to): Implement in terms of make_constraints_to.
2010-10-13 Richard Guenther <rguenther@suse.de>
+ PR tree-optimization/45970
+ * gcc.dg/tree-ssa/ssa-dse-13.c: New testcase.
+
+2010-10-13 Richard Guenther <rguenther@suse.de>
+
PR tree-optimization/45982
* gcc.dg/torture/pr45982.c: New testcase.
* gcc.dg/tree-ssa/pr24287.c: Adjust.
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-dse1-details" } */
+
+struct A { char c[4]; } a, b;
+
+void
+f1 (void)
+{
+ __builtin_memcpy (&a.c[0], "a", 1);
+ a = b;
+}
+
+void
+f2 (void)
+{
+ __builtin_memcpy (&a.c[0], "a", 1);
+ __builtin_memcpy (&a.c[0], "cdef", 4);
+}
+
+/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1" } } */
+/* { dg-final { cleanup-tree-dump "dse1" } } */
return stmt_may_clobber_ref_p_1 (stmt, &r);
}
+/* If STMT kills the memory reference REF return true, otherwise
+ return false. */
+
+static bool
+stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref)
+{
+ if (gimple_has_lhs (stmt)
+ && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME)
+ {
+ tree base, lhs = gimple_get_lhs (stmt);
+ HOST_WIDE_INT size, offset, max_size;
+ ao_ref_base (ref);
+ 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)
+ {
+ /* For a must-alias check we need to be able to constrain
+ the accesses properly. */
+ if (size != -1 && size == max_size
+ && ref->max_size != -1)
+ {
+ if (offset <= ref->offset
+ && offset + size >= ref->offset + ref->max_size)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+stmt_kills_ref_p (gimple stmt, tree ref)
+{
+ ao_ref r;
+ ao_ref_init (&r, ref);
+ return stmt_kills_ref_p_1 (stmt, &r);
+}
+
/* Walk the virtual use-def chain of VUSE until hitting the virtual operand
TARGET or a statement clobbering the memory reference REF in which
extern bool stmt_may_clobber_ref_p (gimple, tree);
extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
extern bool call_may_clobber_ref_p (gimple, tree);
+extern bool stmt_kills_ref_p (gimple, tree);
extern tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
extern void *walk_non_aliased_vuses (ao_ref *, tree,
void *(*)(ao_ref *, tree, void *),
virtual uses from stmt and the stmt which stores to that same
memory location, then we may have found redundant store. */
if (bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
- && operand_equal_p (gimple_assign_lhs (stmt),
- gimple_assign_lhs (use_stmt), 0))
+ && (operand_equal_p (gimple_assign_lhs (stmt),
+ gimple_assign_lhs (use_stmt), 0)
+ || stmt_kills_ref_p (use_stmt, gimple_assign_lhs (stmt))))
{
/* If use_stmt is or might be a nop assignment, e.g. for
struct { ... } S a, b, *p; ...