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:
parent
8d972839df
commit
7f8fdb9ff9
4 changed files with 123 additions and 40 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
51
gcc/testsuite/gcc.c-torture/execute/pr40022.c
Normal file
51
gcc/testsuite/gcc.c-torture/execute/pr40022.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue