PR tree-optimization/47365
* tree-ssa-sccvn.h (vn_lookup_kind): Declare.
(vn_reference_lookup_pieces): Adjust.
(vn_reference_lookup): Likewise.
* tree-ssa-sccvn.c (vn_walk_kind): New static global.
(vn_reference_lookup_3): Only look through kills if in
VN_WALKREWRITE mode.
(vn_reference_lookup_pieces): Adjust.
(vn_reference_lookup): Likewise.
(visit_reference_op_load): Likewise.
(visit_reference_op_store): Likewise.
* tree-ssa-pre.c (phi_translate_1): Use VN_WALK mode.
(compute_avail): Likewise.
(eliminate): Likewise.
* gcc.dg/torture/pr47365.c: New testcase.
* gcc.dg/tree-ssa/pr47392.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@169089
138bc75d-0d04-0410-961f-
82ee72b054a4
+2011-01-21 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/47365
+ * tree-ssa-sccvn.h (vn_lookup_kind): Declare.
+ (vn_reference_lookup_pieces): Adjust.
+ (vn_reference_lookup): Likewise.
+ * tree-ssa-sccvn.c (vn_walk_kind): New static global.
+ (vn_reference_lookup_3): Only look through kills if in
+ VN_WALKREWRITE mode.
+ (vn_reference_lookup_pieces): Adjust.
+ (vn_reference_lookup): Likewise.
+ (visit_reference_op_load): Likewise.
+ (visit_reference_op_store): Likewise.
+ * tree-ssa-pre.c (phi_translate_1): Use VN_WALK mode.
+ (compute_avail): Likewise.
+ (eliminate): Likewise.
+
2011-01-21 Jakub Jelinek <jakub@redhat.com>
* tree-ssa-live.c (remove_unused_scope_block_p): Don't remove
+2011-01-21 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/47365
+ * gcc.dg/torture/pr47365.c: New testcase.
+ * gcc.dg/tree-ssa/pr47392.c: Likewise.
+
2011-01-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* g++.dg/other/anon5.C: Skip on mips-sgi-irix*.
--- /dev/null
+/* { dg-do run } */
+
+struct A
+{
+ int i;
+};
+
+struct B
+{
+ struct A a[2];
+};
+
+int i = 1;
+struct B b = { 0, 3 };
+
+static void
+test ()
+{
+ if (b.a[0].i != i)
+ {
+ int t = b.a[0].i;
+ b.a[0] = b.a[1];
+ b.a[1].i = t;
+ }
+
+ if (b.a[1].i == i)
+ __builtin_abort ();
+
+ if (b.a[0].i == 0)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ test ();
+ return 0;
+}
+
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+
+struct A
+{
+ int i;
+};
+
+struct B
+{
+ struct A a[2];
+};
+
+int i = 1;
+struct B b = { 0, 3 };
+
+static void
+test ()
+{
+ if (b.a[0].i != i)
+ {
+ int t = b.a[0].i;
+ b.a[0] = b.a[1];
+ b.a[1].i = t;
+ }
+
+ if (b.a[1].i == i)
+ __builtin_abort ();
+
+ if (b.a[0].i == 0)
+ __builtin_abort ();
+}
+
+int __attribute__((hot))
+main ()
+{
+ test ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
tree result = vn_reference_lookup_pieces (newvuse, ref->set,
ref->type,
newoperands,
- &newref, true);
+ &newref, VN_WALK);
if (result)
VEC_free (vn_reference_op_s, heap, newoperands);
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Starting iteration %d\n", num_iterations);
+ /* ??? We need to clear our PHI translation cache here as the
+ ANTIC sets shrink and we restrict valid translations to
+ those having operands with leaders in ANTIC. Same below
+ for PA ANTIC computation. */
num_iterations++;
changed = false;
for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
already existing along every predecessor, and
it's defined by some predecessor, it is
partially redundant. */
- if (!cant_insert && !all_same && by_some && do_insertion
- && dbg_cnt (treepre_insert))
+ if (!cant_insert && !all_same && by_some)
{
- if (insert_into_preds_of_block (block, get_expression_id (expr),
- avail))
+ if (!do_insertion)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Skipping partial redundancy for "
+ "expression ");
+ print_pre_expr (dump_file, expr);
+ fprintf (dump_file, " (%04d), no redundancy on to be "
+ "optimized for speed edge\n", val);
+ }
+ }
+ else if (dbg_cnt (treepre_insert)
+ && insert_into_preds_of_block (block,
+ get_expression_id (expr),
+ avail))
new_stuff = true;
}
/* If all edges produce the same value and that value is
copy_reference_ops_from_call (stmt, &ops);
vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
gimple_expr_type (stmt),
- ops, &ref, false);
+ ops, &ref, VN_NOWALK);
VEC_free (vn_reference_op_s, heap, ops);
if (!ref)
continue;
vn_reference_lookup (gimple_assign_rhs1 (stmt),
gimple_vuse (stmt),
- true, &ref);
+ VN_WALK, &ref);
if (!ref)
continue;
tree rhs = gimple_assign_rhs1 (stmt);
tree val;
val = vn_reference_lookup (gimple_assign_lhs (stmt),
- gimple_vuse (stmt), true, NULL);
+ gimple_vuse (stmt), VN_WALK, NULL);
if (TREE_CODE (rhs) == SSA_NAME)
rhs = VN_INFO (rhs)->valnum;
if (val
}
static tree *last_vuse_ptr;
+static vn_lookup_kind vn_walk_kind;
/* Callback for walk_non_aliased_vuses. Adjusts the vn_reference_t VR_
with the current VUSE and performs the expression lookup. */
/* For aggregate copies translate the reference through them if
the copy kills ref. */
- else if (gimple_assign_single_p (def_stmt)
+ else if (vn_walk_kind == VN_WALKREWRITE
+ && gimple_assign_single_p (def_stmt)
&& (DECL_P (gimple_assign_rhs1 (def_stmt))
|| TREE_CODE (gimple_assign_rhs1 (def_stmt)) == MEM_REF
|| handled_component_p (gimple_assign_rhs1 (def_stmt))))
tree
vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
VEC (vn_reference_op_s, heap) *operands,
- vn_reference_t *vnresult, bool maywalk)
+ vn_reference_t *vnresult, vn_lookup_kind kind)
{
struct vn_reference_s vr1;
vn_reference_t tmp;
vn_reference_lookup_1 (&vr1, vnresult);
if (!*vnresult
- && maywalk
+ && kind != VN_NOWALK
&& vr1.vuse)
{
ao_ref r;
+ vn_walk_kind = kind;
if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
*vnresult =
(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
stored in the hashtable if one exists. */
tree
-vn_reference_lookup (tree op, tree vuse, bool maywalk,
+vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
vn_reference_t *vnresult)
{
VEC (vn_reference_op_s, heap) *operands;
if ((cst = fully_constant_vn_reference_p (&vr1)))
return cst;
- if (maywalk
+ if (kind != VN_NOWALK
&& vr1.vuse)
{
vn_reference_t wvnresult;
ao_ref r;
ao_ref_init (&r, op);
+ vn_walk_kind = kind;
wvnresult =
(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
vn_reference_lookup_2,
last_vuse = gimple_vuse (stmt);
last_vuse_ptr = &last_vuse;
- result = vn_reference_lookup (op, gimple_vuse (stmt), true, NULL);
+ result = vn_reference_lookup (op, gimple_vuse (stmt), VN_WALKREWRITE, NULL);
last_vuse_ptr = NULL;
/* If we have a VCE, try looking up its operand as it might be stored in
a different type. */
if (!result && TREE_CODE (op) == VIEW_CONVERT_EXPR)
result = vn_reference_lookup (TREE_OPERAND (op, 0), gimple_vuse (stmt),
- true, NULL);
+ VN_WALKREWRITE, NULL);
/* We handle type-punning through unions by value-numbering based
on offset and size of the access. Be prepared to handle a
Otherwise, the vdefs for the store are used when inserting into
the table, since the store generates a new memory state. */
- result = vn_reference_lookup (lhs, gimple_vuse (stmt), false, NULL);
+ result = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_NOWALK, NULL);
if (result)
{
void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree,
VEC (vn_reference_op_s, heap) *);
+typedef enum { VN_NOWALK, VN_WALK, VN_WALKREWRITE } vn_lookup_kind;
tree vn_reference_lookup_pieces (tree, alias_set_type, tree,
VEC (vn_reference_op_s, heap) *,
- vn_reference_t *, bool);
-tree vn_reference_lookup (tree, tree, bool, vn_reference_t *);
+ vn_reference_t *, vn_lookup_kind);
+tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *);
vn_reference_t vn_reference_insert (tree, tree, tree);
vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree,
VEC (vn_reference_op_s, heap) *,