Commit 7f8fdb9f by Richard Guenther Committed by Richard Biener

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
parent 8d972839
2009-05-05 Richard Guenther <rguenther@suse.de> 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 PR middle-end/40023
* builtins.c (gimplify_va_arg_expr): Properly build the * builtins.c (gimplify_va_arg_expr): Properly build the
address. address.
......
2009-05-05 Richard Guenther <rguenther@suse.de> 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 PR middle-end/40023
* gcc.c-torture/compile/pr40023.c: New testcase. * gcc.c-torture/compile/pr40023.c: New testcase.
......
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;
}
...@@ -90,12 +90,12 @@ along with GCC; see the file COPYING3. If not see ...@@ -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 /* 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 struct phiprop_d
{ {
tree value; tree value;
gimple vop_stmt; tree vuse;
}; };
/* Verify if the value recorded for NAME in PHIVN is still valid at /* Verify if the value recorded for NAME in PHIVN is still valid at
...@@ -104,34 +104,27 @@ struct phiprop_d ...@@ -104,34 +104,27 @@ struct phiprop_d
static bool static bool
phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb) phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
{ {
gimple vop_stmt = phivn[SSA_NAME_VERSION (name)].vop_stmt; tree vuse = phivn[SSA_NAME_VERSION (name)].vuse;
tree vuse; gimple use_stmt;
imm_use_iterator ui2;
bool ok = true;
/* The def stmts of all virtual uses need to be post-dominated /* The def stmts of the virtual uses need to be dominated by bb. */
by bb. */ gcc_assert (vuse != NULL_TREE);
if ((vuse = gimple_vuse (vop_stmt)))
{
gimple use_stmt;
imm_use_iterator ui2;
bool ok = true;
FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse) 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. */ ok = false;
if (((is_gimple_assign (use_stmt) BREAK_FROM_IMM_USE_STMT (ui2);
&& 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);
}
} }
if (!ok)
return false;
} }
return true; return ok;
} }
/* Insert a new phi node for the dereference of PHI at basic_block /* 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, ...@@ -154,6 +147,12 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
res = gimple_assign_lhs (use_stmt); res = gimple_assign_lhs (use_stmt);
SSA_NAME_DEF_STMT (res) = new_phi = create_phi_node (res, bb); 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 /* Add PHI arguments for each edge inserting loads of the
addressable operands. */ addressable operands. */
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
...@@ -171,8 +170,19 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt, ...@@ -171,8 +170,19 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
} }
if (TREE_CODE (old_arg) == SSA_NAME) 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 else
{ {
gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR); gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
...@@ -188,9 +198,15 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt, ...@@ -188,9 +198,15 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
gimple_assign_set_lhs (tmp, new_var); gimple_assign_set_lhs (tmp, new_var);
gsi_insert_on_edge (e, tmp); gsi_insert_on_edge (e, tmp);
update_stmt (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); add_phi_arg (new_phi, new_var, e);
...@@ -198,6 +214,9 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt, ...@@ -198,6 +214,9 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
update_stmt (new_phi); update_stmt (new_phi);
if (dump_file && (dump_flags & TDF_DETAILS))
print_gimple_stmt (dump_file, new_phi, 0, 0);
return res; return res;
} }
...@@ -270,6 +289,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, ...@@ -270,6 +289,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
phi_inserted = false; phi_inserted = false;
FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr) FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
{ {
gimple def_stmt;
tree vuse; tree vuse;
/* Check whether this is a load of *ptr. */ /* Check whether this is a load of *ptr. */
...@@ -281,17 +301,15 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, ...@@ -281,17 +301,15 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
&& !stmt_can_throw_internal (use_stmt))) && !stmt_can_throw_internal (use_stmt)))
continue; continue;
/* Check if we can move the loads. The def stmts of all virtual uses /* Check if we can move the loads. The def stmt of the virtual use
need to be post-dominated by bb. */ needs to be in a different basic block dominating bb. */
if ((vuse = gimple_vuse (use_stmt)) != NULL_TREE) vuse = gimple_vuse (use_stmt);
{ def_stmt = SSA_NAME_DEF_STMT (vuse);
gimple def_stmt = SSA_NAME_DEF_STMT (vuse); if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
if (!SSA_NAME_IS_DEFAULT_DEF (vuse) && (gimple_bb (def_stmt) == bb
&& (gimple_bb (def_stmt) == bb || !dominated_by_p (CDI_DOMINATORS,
|| !dominated_by_p (CDI_DOMINATORS, bb, gimple_bb (def_stmt))))
bb, gimple_bb (def_stmt)))) goto next;
goto next;
}
/* Found a proper dereference. Insert a phi node if this /* Found a proper dereference. Insert a phi node if this
is the first load transformation. */ is the first load transformation. */
...@@ -301,7 +319,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, ...@@ -301,7 +319,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
/* Remember the value we created for *ptr. */ /* Remember the value we created for *ptr. */
phivn[SSA_NAME_VERSION (ptr)].value = res; 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 /* 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 want to delete it here we also have to delete all intermediate
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment