Commit e256dfce by Richard Guenther Committed by Richard Biener

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
parent 854b5fd7
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> 2011-10-19 Andrey Belevantsev <abel@ispras.ru>
PR rtl-optimization/50340 PR rtl-optimization/50340
...@@ -534,25 +534,22 @@ void ...@@ -534,25 +534,22 @@ void
gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr) gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
{ {
tree lhs; tree lhs;
tree tmp = NULL_TREE; /* Silence warning. */
gimple stmt, new_stmt; gimple stmt, new_stmt;
gimple_stmt_iterator i; gimple_stmt_iterator i;
gimple_seq stmts = gimple_seq_alloc(); gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx; struct gimplify_ctx gctx;
gimple last = NULL; gimple last;
gimple laststore = NULL; gimple laststore;
tree reaching_vuse; tree reaching_vuse;
stmt = gsi_stmt (*si_p); stmt = gsi_stmt (*si_p);
gcc_assert (is_gimple_call (stmt)); gcc_assert (is_gimple_call (stmt));
lhs = gimple_call_lhs (stmt);
reaching_vuse = gimple_vuse (stmt);
push_gimplify_context (&gctx); push_gimplify_context (&gctx);
gctx.into_ssa = gimple_in_ssa_p (cfun); gctx.into_ssa = gimple_in_ssa_p (cfun);
lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE) if (lhs == NULL_TREE)
{ {
gimplify_and_add (expr, &stmts); gimplify_and_add (expr, &stmts);
...@@ -571,105 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr) ...@@ -571,105 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
} }
} }
else 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); pop_gimplify_context (NULL);
if (gimple_has_location (stmt)) if (gimple_has_location (stmt))
annotate_all_with_location (stmts, gimple_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)) 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) if (last)
{ {
gsi_insert_before (si_p, last, GSI_NEW_STMT); gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p); gsi_next (si_p);
} }
new_stmt = gsi_stmt (i); new_stmt = gsi_stmt (i);
/* The replacement can expose previously unreferenced variables. */
if (gimple_in_ssa_p (cfun)) if (gimple_in_ssa_p (cfun))
find_new_referenced_vars (new_stmt); find_new_referenced_vars (new_stmt);
/* If the new statement possibly has a VUSE, update it with exact SSA /* If the new statement possibly has a VUSE, update it with exact SSA
name we know will reach this one. */ name we know will reach this one. */
if (gimple_has_mem_ops (new_stmt)) if (gimple_has_mem_ops (new_stmt))
{ gimple_set_vuse (new_stmt, reaching_vuse);
/* If we've also seen a previous store create a new VDEF for gimple_set_modified (new_stmt, true);
the latter one, and make that the new reaching VUSE. */ if (gimple_vdef (new_stmt))
if (laststore) reaching_vuse = gimple_vdef (new_stmt);
{
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;
}
last = 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 tree vdef = gimple_vdef (stmt);
sequence ends with a store we must make that store have the same if (vdef
vdef in order not to break the sequencing. This can happen && TREE_CODE (vdef) == SSA_NAME)
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))
{ {
unlink_stmt_vdef (stmt); 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)); /* Finally replace rhe original statement with the last. */
gsi_replace (si_p, new_stmt, false); gsi_replace (si_p, last, false);
} }
/* Return the string length, maximum string length or maximum value of /* Return the string length, maximum string length or maximum value of
......
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> 2011-10-19 Alexander Monakov <amonakov@ispras.ru>
PR rtl-optimization/50340 PR rtl-optimization/50340
......
/* { 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 ();
}
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