* [PATCH] Fix PR50768, rewrite gimplify_and_update_call_from_tree
@ 2011-10-19 12:14 Richard Guenther
0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2011-10-19 12:14 UTC (permalink / raw)
To: gcc-patches
So my previous patch has caused some bugs - not unreasonable given
the complexity of that function. Thus the following patch makes
it readable and understandable again, by exchanging the intricate
one-stage processing with a two-stage one, first assigning VDEFs
and then assigning VUSEs in a second stage. Also doing the
lhs assignment processing upfront which removes the need for
all the duplicate code at the tail.
Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu, let's
hope it can stay this simple ;)
Thanks,
Richard.
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.
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c (revision 180166)
--- gcc/gimple-fold.c (working copy)
*************** void
*** 534,558 ****
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;
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);
if (lhs == NULL_TREE)
{
gimplify_and_add (expr, &stmts);
--- 534,555 ----
gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
{
tree lhs;
gimple stmt, new_stmt;
gimple_stmt_iterator i;
gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx;
! gimple last;
! gimple laststore;
tree reaching_vuse;
stmt = gsi_stmt (*si_p);
gcc_assert (is_gimple_call (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);
*************** gimplify_and_update_call_from_tree (gimp
*** 571,675 ****
}
}
else
! tmp = get_initialized_tmp_var (expr, &stmts, NULL);
pop_gimplify_context (NULL);
if (gimple_has_location (stmt))
annotate_all_with_location (stmts, gimple_location (stmt));
! /* The replacement can expose previously unreferenced variables. */
for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
{
if (last)
{
gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p);
}
new_stmt = gsi_stmt (i);
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;
! }
last = new_stmt;
}
! if (lhs == NULL_TREE)
{
! /* 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))
{
unlink_stmt_vdef (stmt);
! release_defs (stmt);
! }
! 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);
}
/* Return the string length, maximum string length or maximum value of
--- 568,648 ----
}
}
else
! {
! 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));
! /* 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);
! 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))
! 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 the new sequence does not do a store release the virtual
! definition of the original statement. */
! if (reaching_vuse
! && reaching_vuse == gimple_vuse (stmt))
{
! tree vdef = gimple_vdef (stmt);
! if (vdef)
{
unlink_stmt_vdef (stmt);
! release_ssa_name (vdef);
}
}
! /* 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
Index: gcc/testsuite/gcc.dg/torture/pr50768.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr50768.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr50768.c (revision 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 ();
+ }
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-10-19 10:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-19 12:14 [PATCH] Fix PR50768, rewrite gimplify_and_update_call_from_tree Richard Guenther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).