re PR tree-optimization/50768 (ICE: in execute_todo, at passes.c:1731 with -O2 -ftracer)

2011-10-19  Richard Guenther  <rguenther@suse.de>

	PR middle-end/50768
	* gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.

	* gcc.dg/torture/pr50768.c: New testcase.

From-SVN: r180187
This commit is contained in:
Richard Guenther 2011-10-19 12:59:21 +00:00 committed by Richard Biener
parent 854b5fd7b5
commit e256dfce35
4 changed files with 79 additions and 77 deletions

View File

@ -1,3 +1,8 @@
2011-10-19 Richard Guenther <rguenther@suse.de>
PR middle-end/50768
* gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.
2011-10-19 Andrey Belevantsev <abel@ispras.ru>
PR rtl-optimization/50340

View File

@ -534,25 +534,22 @@ void
gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
{
tree lhs;
tree tmp = NULL_TREE; /* Silence warning. */
gimple stmt, new_stmt;
gimple_stmt_iterator i;
gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx;
gimple last = NULL;
gimple laststore = NULL;
gimple last;
gimple laststore;
tree reaching_vuse;
stmt = gsi_stmt (*si_p);
gcc_assert (is_gimple_call (stmt));
lhs = gimple_call_lhs (stmt);
reaching_vuse = gimple_vuse (stmt);
push_gimplify_context (&gctx);
gctx.into_ssa = gimple_in_ssa_p (cfun);
lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
{
gimplify_and_add (expr, &stmts);
@ -571,105 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
}
}
else
tmp = get_initialized_tmp_var (expr, &stmts, NULL);
{
tree tmp = get_initialized_tmp_var (expr, &stmts, NULL);
new_stmt = gimple_build_assign (lhs, tmp);
i = gsi_last (stmts);
gsi_insert_after_without_update (&i, new_stmt,
GSI_CONTINUE_LINKING);
}
pop_gimplify_context (NULL);
if (gimple_has_location (stmt))
annotate_all_with_location (stmts, gimple_location (stmt));
/* The replacement can expose previously unreferenced variables. */
/* First iterate over the replacement statements backward, assigning
virtual operands to their defining statements. */
laststore = NULL;
for (i = gsi_last (stmts); !gsi_end_p (i); gsi_prev (&i))
{
new_stmt = gsi_stmt (i);
if (gimple_assign_single_p (new_stmt)
&& !is_gimple_reg (gimple_assign_lhs (new_stmt)))
{
tree vdef;
if (!laststore)
vdef = gimple_vdef (stmt);
else
vdef = make_ssa_name (gimple_vop (cfun), new_stmt);
gimple_set_vdef (new_stmt, vdef);
if (TREE_CODE (vdef) == SSA_NAME)
SSA_NAME_DEF_STMT (vdef) = new_stmt;
laststore = new_stmt;
}
}
/* Second iterate over the statements forward, assigning virtual
operands to their uses. */
last = NULL;
reaching_vuse = gimple_vuse (stmt);
for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
{
/* Do not insert the last stmt in this loop but remember it
for replacing the original statement. */
if (last)
{
gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p);
}
new_stmt = gsi_stmt (i);
/* The replacement can expose previously unreferenced variables. */
if (gimple_in_ssa_p (cfun))
find_new_referenced_vars (new_stmt);
/* If the new statement possibly has a VUSE, update it with exact SSA
name we know will reach this one. */
if (gimple_has_mem_ops (new_stmt))
{
/* If we've also seen a previous store create a new VDEF for
the latter one, and make that the new reaching VUSE. */
if (laststore)
{
reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
gimple_set_vdef (laststore, reaching_vuse);
update_stmt (laststore);
laststore = NULL;
}
gimple_set_vuse (new_stmt, reaching_vuse);
gimple_set_modified (new_stmt, true);
}
if (gimple_assign_single_p (new_stmt)
&& !is_gimple_reg (gimple_assign_lhs (new_stmt)))
{
laststore = new_stmt;
}
gimple_set_vuse (new_stmt, reaching_vuse);
gimple_set_modified (new_stmt, true);
if (gimple_vdef (new_stmt))
reaching_vuse = gimple_vdef (new_stmt);
last = new_stmt;
}
if (lhs == NULL_TREE)
/* If the new sequence does not do a store release the virtual
definition of the original statement. */
if (reaching_vuse
&& reaching_vuse == gimple_vuse (stmt))
{
/* If we replace a call without LHS that has a VDEF and our new
sequence ends with a store we must make that store have the same
vdef in order not to break the sequencing. This can happen
for instance when folding memcpy calls into assignments. */
if (gimple_vdef (stmt) && laststore)
{
gimple_set_vdef (laststore, gimple_vdef (stmt));
if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
update_stmt (laststore);
}
else if (gimple_in_ssa_p (cfun))
tree vdef = gimple_vdef (stmt);
if (vdef
&& TREE_CODE (vdef) == SSA_NAME)
{
unlink_stmt_vdef (stmt);
release_defs (stmt);
release_ssa_name (vdef);
}
new_stmt = last;
}
else
{
if (last)
{
gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p);
}
if (laststore && is_gimple_reg (lhs))
{
gimple_set_vdef (laststore, gimple_vdef (stmt));
update_stmt (laststore);
if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
laststore = NULL;
}
else if (laststore)
{
reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
gimple_set_vdef (laststore, reaching_vuse);
update_stmt (laststore);
laststore = NULL;
}
new_stmt = gimple_build_assign (lhs, tmp);
if (!is_gimple_reg (tmp))
gimple_set_vuse (new_stmt, reaching_vuse);
if (!is_gimple_reg (lhs))
{
gimple_set_vdef (new_stmt, gimple_vdef (stmt));
if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = new_stmt;
}
else if (reaching_vuse == gimple_vuse (stmt))
unlink_stmt_vdef (stmt);
}
gimple_set_location (new_stmt, gimple_location (stmt));
gsi_replace (si_p, new_stmt, false);
/* Finally replace rhe original statement with the last. */
gsi_replace (si_p, last, false);
}
/* Return the string length, maximum string length or maximum value of

View File

@ -1,3 +1,8 @@
2011-10-19 Richard Guenther <rguenther@suse.de>
PR middle-end/50768
* gcc.dg/torture/pr50768.c: New testcase.
2011-10-19 Alexander Monakov <amonakov@ispras.ru>
PR rtl-optimization/50340

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-ftracer" } */
char data[8];
int l1;
void
test1 (void)
{
char buf[8];
__builtin___mempcpy_chk (buf, data, l1 ? sizeof (buf) : 4,
__builtin_object_size (buf, 0));
if (__builtin___memmove_chk
(buf, data, l1 ? sizeof (buf) : 4,
__builtin_object_size (buf, 0)) != buf)
__builtin_abort ();
}