re PR tree-optimization/47365 (wrong code with -O -ftree-pre)
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. * gcc.dg/torture/pr47365.c: New testcase. * gcc.dg/tree-ssa/pr47392.c: Likewise. From-SVN: r169089
This commit is contained in:
parent
33e39b6685
commit
3bc27de7f1
|
@ -1,3 +1,20 @@
|
|||
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
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
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*.
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* { 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* { 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" } } */
|
|
@ -1681,7 +1681,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
|
|||
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);
|
||||
|
||||
|
@ -2594,6 +2594,10 @@ compute_antic (void)
|
|||
{
|
||||
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--)
|
||||
|
@ -3607,11 +3611,23 @@ do_regular_insertion (basic_block block, basic_block dom)
|
|||
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
|
||||
|
@ -3999,7 +4015,7 @@ compute_avail (void)
|
|||
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;
|
||||
|
@ -4069,7 +4085,7 @@ compute_avail (void)
|
|||
|
||||
vn_reference_lookup (gimple_assign_rhs1 (stmt),
|
||||
gimple_vuse (stmt),
|
||||
true, &ref);
|
||||
VN_WALK, &ref);
|
||||
if (!ref)
|
||||
continue;
|
||||
|
||||
|
@ -4313,7 +4329,7 @@ eliminate (void)
|
|||
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
|
||||
|
|
|
@ -1243,6 +1243,7 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
|
|||
}
|
||||
|
||||
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. */
|
||||
|
@ -1379,7 +1380,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
|
|||
|
||||
/* 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))))
|
||||
|
@ -1473,7 +1475,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
|
|||
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;
|
||||
|
@ -1501,10 +1503,11 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
|
|||
|
||||
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,
|
||||
|
@ -1527,7 +1530,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
|
|||
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;
|
||||
|
@ -1545,12 +1548,13 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk,
|
|||
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,
|
||||
|
@ -2257,14 +2261,14 @@ visit_reference_op_load (tree lhs, tree op, gimple stmt)
|
|||
|
||||
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
|
||||
|
@ -2375,7 +2379,7 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -187,10 +187,11 @@ void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
|
|||
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) *,
|
||||
|
|
Loading…
Reference in New Issue