aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-eh.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2013-04-30 13:54:14 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2013-04-30 13:54:14 +0000
commit4c1aff1ce430fdf4b46caa632fd44b4d0f557720 (patch)
treeb5bca3706a64ea2adc3ab07083628f891afef77b /gcc/tree-eh.c
parent54b8379a261d1b36958aecbca568ef6475a8e1ca (diff)
downloadgcc-4c1aff1ce430fdf4b46caa632fd44b4d0f557720.zip
gcc-4c1aff1ce430fdf4b46caa632fd44b4d0f557720.tar.gz
gcc-4c1aff1ce430fdf4b46caa632fd44b4d0f557720.tar.bz2
re PR middle-end/57107 (tree check fail in unlink_stmt_vdef)
2013-04-30 Richard Biener <rguenther@suse.de> PR middle-end/57107 * tree-eh.c (sink_clobbers): Preserve virtual SSA form. * g++.dg/torture/pr57107.C: New testcase. From-SVN: r198454
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r--gcc/tree-eh.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 56132e1..c900949 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -3342,7 +3342,24 @@ sink_clobbers (basic_block bb)
if (!any_clobbers)
return 0;
- succbb = single_succ (bb);
+ edge succe = single_succ_edge (bb);
+ succbb = succe->dest;
+
+ /* See if there is a virtual PHI node to take an updated virtual
+ operand from. */
+ gimple vphi = NULL;
+ tree vuse = NULL_TREE;
+ for (gsi = gsi_start_phis (succbb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ tree res = gimple_phi_result (gsi_stmt (gsi));
+ if (virtual_operand_p (res))
+ {
+ vphi = gsi_stmt (gsi);
+ vuse = res;
+ break;
+ }
+ }
+
dgsi = gsi_after_labels (succbb);
gsi = gsi_last_bb (bb);
for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
@@ -3353,7 +3370,6 @@ sink_clobbers (basic_block bb)
continue;
if (gimple_code (stmt) == GIMPLE_LABEL)
break;
- unlink_stmt_vdef (stmt);
lhs = gimple_assign_lhs (stmt);
/* Unfortunately we don't have dominance info updated at this
point, so checking if
@@ -3365,21 +3381,33 @@ sink_clobbers (basic_block bb)
&& TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME
&& !SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0)))
{
+ unlink_stmt_vdef (stmt);
gsi_remove (&gsi, true);
release_defs (stmt);
continue;
}
+
+ /* As we do not change stmt order when sinking across a
+ forwarder edge we can keep virtual operands in place. */
gsi_remove (&gsi, false);
- /* Trigger the operand scanner to cause renaming for virtual
- operands for this statement.
- ??? Given the simple structure of this code manually
- figuring out the reaching definition should not be too hard. */
- if (gimple_vuse (stmt))
- gimple_set_vuse (stmt, NULL_TREE);
- gsi_insert_before (&dgsi, stmt, GSI_SAME_STMT);
+ gsi_insert_before (&dgsi, stmt, GSI_NEW_STMT);
+
+ /* But adjust virtual operands if we sunk across a PHI node. */
+ if (vuse)
+ {
+ gimple use_stmt;
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, vuse)
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, gimple_vdef (stmt));
+ /* Adjust the incoming virtual operand. */
+ SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (vphi, succe), gimple_vuse (stmt));
+ SET_USE (gimple_vuse_op (stmt), vuse);
+ }
}
- return TODO_update_ssa_only_virtuals;
+ return 0;
}
/* At the end of inlining, we can lower EH_DISPATCH. Return true when