re PR middle-end/40022 (Alpine miscompilation)

2009-05-05  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/40022
	* tree-ssa-phiprop.c (struct phiprop_d): Exchange vop_stmt for
	the only vuse.
	(phivn_valid_p): Fix tuplification error, simplify.
	(phiprop_insert_phi): Add dumps.
	(propagate_with_phi): Simplify.

	* gcc.c-torture/execute/pr40022.c: New testcase.

From-SVN: r147128
This commit is contained in:
Richard Guenther 2009-05-05 16:09:46 +00:00 committed by Richard Biener
parent 8d972839df
commit 7f8fdb9ff9
4 changed files with 123 additions and 40 deletions

View file

@ -1,3 +1,12 @@
2009-05-05 Richard Guenther <rguenther@suse.de>
PR tree-optimization/40022
* tree-ssa-phiprop.c (struct phiprop_d): Exchange vop_stmt for
the only vuse.
(phivn_valid_p): Fix tuplification error, simplify.
(phiprop_insert_phi): Add dumps.
(propagate_with_phi): Simplify.
2009-05-05 Richard Guenther <rguenther@suse.de>
PR middle-end/40023

View file

@ -1,3 +1,8 @@
2009-05-05 Richard Guenther <rguenther@suse.de>
PR tree-optimization/40022
* gcc.c-torture/execute/pr40022.c: New testcase.
2009-05-05 Richard Guenther <rguenther@suse.de>
PR middle-end/40023

View file

@ -0,0 +1,51 @@
extern void abort (void);
struct A
{
struct A *a;
};
struct B
{
struct A *b;
};
__attribute__((noinline))
struct A *
foo (struct A *x)
{
asm volatile ("" : : "g" (x) : "memory");
return x;
}
__attribute__((noinline))
void
bar (struct B *w, struct A *x, struct A *y, struct A *z)
{
struct A **c;
c = &w->b;
*c = foo (x);
while (*c)
c = &(*c)->a;
*c = foo (y);
while (*c)
c = &(*c)->a;
*c = foo (z);
}
struct B d;
struct A e, f, g;
int
main (void)
{
f.a = &g;
bar (&d, &e, &f, 0);
if (d.b == 0
|| d.b->a == 0
|| d.b->a->a == 0
|| d.b->a->a->a != 0)
abort ();
return 0;
}

View file

@ -90,12 +90,12 @@ along with GCC; see the file COPYING3. If not see
/* Structure to keep track of the value of a dereferenced PHI result
and the set of virtual operands used for that dereference. */
and the virtual operand used for that dereference. */
struct phiprop_d
{
tree value;
gimple vop_stmt;
tree vuse;
};
/* Verify if the value recorded for NAME in PHIVN is still valid at
@ -104,34 +104,27 @@ struct phiprop_d
static bool
phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
{
gimple vop_stmt = phivn[SSA_NAME_VERSION (name)].vop_stmt;
tree vuse;
tree vuse = phivn[SSA_NAME_VERSION (name)].vuse;
gimple use_stmt;
imm_use_iterator ui2;
bool ok = true;
/* The def stmts of all virtual uses need to be post-dominated
by bb. */
if ((vuse = gimple_vuse (vop_stmt)))
/* The def stmts of the virtual uses need to be dominated by bb. */
gcc_assert (vuse != NULL_TREE);
FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
{
gimple use_stmt;
imm_use_iterator ui2;
bool ok = true;
FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
/* If BB does not dominate a VDEF, the value is invalid. */
if ((gimple_vdef (use_stmt) != NULL_TREE
|| gimple_code (use_stmt) == GIMPLE_PHI)
&& !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
{
/* If BB does not dominate a VDEF, the value is invalid. */
if (((is_gimple_assign (use_stmt)
&& gimple_vdef (use_stmt))
|| gimple_code (use_stmt) == GIMPLE_PHI)
&& !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
{
ok = false;
BREAK_FROM_IMM_USE_STMT (ui2);
}
ok = false;
BREAK_FROM_IMM_USE_STMT (ui2);
}
if (!ok)
return false;
}
return true;
return ok;
}
/* Insert a new phi node for the dereference of PHI at basic_block
@ -154,6 +147,12 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
res = gimple_assign_lhs (use_stmt);
SSA_NAME_DEF_STMT (res) = new_phi = create_phi_node (res, bb);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Inserting PHI for result of load ");
print_gimple_stmt (dump_file, use_stmt, 0, 0);
}
/* Add PHI arguments for each edge inserting loads of the
addressable operands. */
FOR_EACH_EDGE (e, ei, bb->preds)
@ -171,8 +170,19 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
}
if (TREE_CODE (old_arg) == SSA_NAME)
/* Reuse a formerly created dereference. */
new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " for edge defining ");
print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
fprintf (dump_file, " reusing PHI result ");
print_generic_expr (dump_file,
phivn[SSA_NAME_VERSION (old_arg)].value, 0);
fprintf (dump_file, "\n");
}
/* Reuse a formerly created dereference. */
new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
}
else
{
gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
@ -188,9 +198,15 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
gimple_assign_set_lhs (tmp, new_var);
gsi_insert_on_edge (e, tmp);
update_stmt (tmp);
mark_symbols_for_renaming (tmp);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " for edge defining ");
print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
fprintf (dump_file, " inserting load ");
print_gimple_stmt (dump_file, tmp, 0, 0);
}
}
add_phi_arg (new_phi, new_var, e);
@ -198,6 +214,9 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
update_stmt (new_phi);
if (dump_file && (dump_flags & TDF_DETAILS))
print_gimple_stmt (dump_file, new_phi, 0, 0);
return res;
}
@ -270,6 +289,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
phi_inserted = false;
FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
{
gimple def_stmt;
tree vuse;
/* Check whether this is a load of *ptr. */
@ -281,17 +301,15 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
&& !stmt_can_throw_internal (use_stmt)))
continue;
/* Check if we can move the loads. The def stmts of all virtual uses
need to be post-dominated by bb. */
if ((vuse = gimple_vuse (use_stmt)) != NULL_TREE)
{
gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
&& (gimple_bb (def_stmt) == bb
|| !dominated_by_p (CDI_DOMINATORS,
bb, gimple_bb (def_stmt))))
goto next;
}
/* Check if we can move the loads. The def stmt of the virtual use
needs to be in a different basic block dominating bb. */
vuse = gimple_vuse (use_stmt);
def_stmt = SSA_NAME_DEF_STMT (vuse);
if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
&& (gimple_bb (def_stmt) == bb
|| !dominated_by_p (CDI_DOMINATORS,
bb, gimple_bb (def_stmt))))
goto next;
/* Found a proper dereference. Insert a phi node if this
is the first load transformation. */
@ -301,7 +319,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
/* Remember the value we created for *ptr. */
phivn[SSA_NAME_VERSION (ptr)].value = res;
phivn[SSA_NAME_VERSION (ptr)].vop_stmt = use_stmt;
phivn[SSA_NAME_VERSION (ptr)].vuse = vuse;
/* Remove old stmt. The phi is taken care of by DCE, if we
want to delete it here we also have to delete all intermediate