re PR tree-optimization/41783 (r151561 (PRE fix) regresses zeusmp)

PR tree-optimization/41783
	* tree-ssa-alias.c (get_continuation_for_phi): Export, add a special
	case for simple diamonds
	* tree-ssa-alias.h (get_continuation_for_phi): Declare.
	* tree-ssa-pre.c (translate_vuse_through_block): Add same_valid
	argument, use alias oracle to skip some vdefs.
	(phi_translate_1): Change call to above, don't allocate new
	value ids if they can stay the same.
	(compute_avail): Allow vuse walking when looking up references.

testsuite/
	* gcc.dg/pr41783.c: New test.
	* gcc.dg/tree-ssa/ssa-pre-23.c: Adjust.
	* gcc.dg/tree-ssa/ssa-pre-24.c: Don't xfail anymore.
	* gcc.dg/tree-ssa/ssa-pre-27.c: New test.

From-SVN: r153551
This commit is contained in:
Michael Matz 2009-10-26 13:00:36 +00:00 committed by Michael Matz
parent bd02b3a0c9
commit 842809179e
8 changed files with 129 additions and 37 deletions

View File

@ -1,3 +1,15 @@
2009-10-26 Michael Matz <matz@suse.de>
PR tree-optimization/41783
* tree-ssa-alias.c (get_continuation_for_phi): Export, add a special
case for simple diamonds.
* tree-ssa-alias.h (get_continuation_for_phi): Declare.
* tree-ssa-pre.c (translate_vuse_through_block): Add same_valid
argument, use alias oracle to skip some vdefs.
(phi_translate_1): Change call to above, don't allocate new
value ids if they can stay the same.
(compute_avail): Allow vuse walking when looking up references.
2009-10-26 Richard Guenther <rguenther@suse.de>
PR tree-optimization/41826

View File

@ -1,3 +1,11 @@
2009-10-26 Michael Matz <matz@suse.de>
PR tree-optimization/41783
* gcc.dg/pr41783.c: New test.
* gcc.dg/tree-ssa/ssa-pre-23.c: Adjust.
* gcc.dg/tree-ssa/ssa-pre-24.c: Don't xfail anymore.
* gcc.dg/tree-ssa/ssa-pre-27.c: New test.
2009-10-26 Janus Weil <janus@gcc.gnu.org>
PR fortran/41714

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-pre" } */
int db[100];
int a_global_var, fact;
int main()
{
int i,j=0;
do
{
for (i=0; i<100; ++i)
db[i] = i;
fact = a_global_var * i;
}
while (j++ < 100);
}
/* We want to have exactly one load (not two) from a_global_var,
and we want that load to be into a PRE temporary. */
/* { dg-final { scan-tree-dump-times "= a_global_var;" 1 "pre" } } */
/* { dg-final { scan-tree-dump "pretmp\[^\\n\]* = a_global_var;" "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -9,5 +9,5 @@ void foo(int n)
global.y += global.x*global.x;
}
/* { dg-final { scan-tree-dump "Eliminated: 2" "pre" } } */
/* { dg-final { scan-tree-dump "Eliminated: 3" "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -9,12 +9,7 @@ void foo(int *p, double *x, int n)
}
/* We should remove the unnecessary insertion of a phi-node and
_not_ end up using the phi result for replacement *p.
The issue here is that when PHI-translating the virtual operands
we assign different value-numbers to the load. Re-running VN
after insertion or trying to be clever and doing this on the
fly during PHI translation would solve this. The next copyprop
fixes this anyway. */
_not_ end up using the phi result for replacement *p. */
/* { dg-final { scan-tree-dump-not "= prephitmp" "pre" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-not "= prephitmp" "pre" } } */
/* { dg-final { cleanup-tree-dump "pre" } } */

View File

@ -1313,8 +1313,6 @@ stmt_may_clobber_ref_p (gimple stmt, tree ref)
}
static tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
/* Walk the virtual use-def chain of VUSE until hitting the virtual operand
TARGET or a statement clobbering the memory reference REF in which
case false is returned. The walk starts with VUSE, one argument of PHI. */
@ -1358,7 +1356,7 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
clobber REF. Returns NULL_TREE if no suitable virtual operand can
be found. */
static tree
tree
get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
{
unsigned nargs = gimple_phi_num_args (phi);
@ -1375,6 +1373,7 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
tree arg1 = PHI_ARG_DEF (phi, 1);
gimple def0 = SSA_NAME_DEF_STMT (arg0);
gimple def1 = SSA_NAME_DEF_STMT (arg1);
tree common_vuse;
if (arg0 == arg1)
return arg0;
@ -1393,6 +1392,26 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
if (maybe_skip_until (phi, arg1, ref, arg0, visited))
return arg1;
}
/* Special case of a diamond:
MEM_1 = ...
goto (cond) ? L1 : L2
L1: store1 = ... #MEM_2 = vuse(MEM_1)
goto L3
L2: store2 = ... #MEM_3 = vuse(MEM_1)
L3: MEM_4 = PHI<MEM_2, MEM_3>
We were called with the PHI at L3, MEM_2 and MEM_3 don't
dominate each other, but still we can easily skip this PHI node
if we recognize that the vuse MEM operand is the same for both,
and that we can skip both statements (they don't clobber us).
This is still linear. Don't use maybe_skip_until, that might
potentially be slow. */
else if ((common_vuse = gimple_vuse (def0))
&& common_vuse == gimple_vuse (def1))
{
if (!stmt_may_clobber_ref_p_1 (def0, ref)
&& !stmt_may_clobber_ref_p_1 (def1, ref))
return common_vuse;
}
}
return NULL_TREE;

View File

@ -99,6 +99,7 @@ extern bool refs_output_dependent_p (tree, tree);
extern bool ref_maybe_used_by_stmt_p (gimple, tree);
extern bool stmt_may_clobber_ref_p (gimple, tree);
extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
extern tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
extern void *walk_non_aliased_vuses (ao_ref *, tree,
void *(*)(ao_ref *, tree, void *),
void *(*)(ao_ref *, tree, void *), void *);

View File

@ -1243,43 +1243,74 @@ do_unary:
}
/* Translate the VUSE backwards through phi nodes in PHIBLOCK, so that
it has the value it would have in BLOCK. */
it has the value it would have in BLOCK. Set *SAME_VALID to true
in case the new vuse doesn't change the value id of the OPERANDS. */
static tree
translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
alias_set_type set, tree type, tree vuse,
basic_block phiblock,
basic_block block)
basic_block block, bool *same_valid)
{
gimple phi = SSA_NAME_DEF_STMT (vuse);
ao_ref ref;
edge e = NULL;
bool use_oracle;
*same_valid = true;
if (gimple_bb (phi) != phiblock)
return vuse;
if (gimple_code (phi) == GIMPLE_PHI)
{
edge e = find_edge (block, phiblock);
return PHI_ARG_DEF (phi, e->dest_idx);
}
if (!ao_ref_init_from_vn_reference (&ref, set, type, operands))
return NULL_TREE;
use_oracle = ao_ref_init_from_vn_reference (&ref, set, type, operands);
/* Use the alias-oracle to find either the PHI node in this block,
the first VUSE used in this block that is equivalent to vuse or
the first VUSE which definition in this block kills the value. */
while (!stmt_may_clobber_ref_p_1 (phi, &ref))
if (gimple_code (phi) == GIMPLE_PHI)
e = find_edge (block, phiblock);
else if (use_oracle)
while (!stmt_may_clobber_ref_p_1 (phi, &ref))
{
vuse = gimple_vuse (phi);
phi = SSA_NAME_DEF_STMT (vuse);
if (gimple_bb (phi) != phiblock)
return vuse;
if (gimple_code (phi) == GIMPLE_PHI)
{
e = find_edge (block, phiblock);
break;
}
}
else
return NULL_TREE;
if (e)
{
vuse = gimple_vuse (phi);
phi = SSA_NAME_DEF_STMT (vuse);
if (gimple_bb (phi) != phiblock)
return vuse;
if (gimple_code (phi) == GIMPLE_PHI)
if (use_oracle)
{
edge e = find_edge (block, phiblock);
return PHI_ARG_DEF (phi, e->dest_idx);
bitmap visited = NULL;
/* Try to find a vuse that dominates this phi node by skipping
non-clobbering statements. */
vuse = get_continuation_for_phi (phi, &ref, &visited);
if (visited)
BITMAP_FREE (visited);
}
else
vuse = NULL_TREE;
if (!vuse)
{
/* If we didn't find any, the value ID can't stay the same,
but return the translated vuse. */
*same_valid = false;
vuse = PHI_ARG_DEF (phi, e->dest_idx);
}
/* ??? We would like to return vuse here as this is the canonical
upmost vdef that this reference is associated with. But during
insertion of the references into the hash tables we only ever
directly insert with their direct gimple_vuse, hence returning
something else would make us not find the other expression. */
return PHI_ARG_DEF (phi, e->dest_idx);
}
return NULL_TREE;
@ -1541,7 +1572,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
tree vuse = ref->vuse;
tree newvuse = vuse;
VEC (vn_reference_op_s, heap) *newoperands = NULL;
bool changed = false;
bool changed = false, same_valid = true;
unsigned int i, j;
vn_reference_op_t operand;
vn_reference_t newref;
@ -1647,16 +1678,16 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
{
newvuse = translate_vuse_through_block (newoperands,
ref->set, ref->type,
vuse, phiblock, pred);
vuse, phiblock, pred,
&same_valid);
if (newvuse == NULL_TREE)
{
VEC_free (vn_reference_op_s, heap, newoperands);
return NULL;
}
}
changed |= newvuse != vuse;
if (changed)
if (changed || newvuse != vuse)
{
unsigned int new_val_id;
pre_expr constant;
@ -1690,9 +1721,15 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
}
else
{
new_val_id = get_next_value_id ();
VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
get_max_value_id() + 1);
if (changed || !same_valid)
{
new_val_id = get_next_value_id ();
VEC_safe_grow_cleared (bitmap_set_t, heap,
value_expressions,
get_max_value_id() + 1);
}
else
new_val_id = ref->value_id;
newref = vn_reference_insert_pieces (newvuse, ref->set,
ref->type,
newoperands,
@ -3914,7 +3951,7 @@ compute_avail (void)
vn_reference_lookup (gimple_assign_rhs1 (stmt),
gimple_vuse (stmt),
false, &ref);
true, &ref);
if (!ref)
continue;