diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-01-15 11:53:26 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-01-15 11:53:26 +0000 |
commit | 7b960d37a6e13afaf0d2f1777a2f5d1a27a659b4 (patch) | |
tree | 67ed89e55330179795b12967f60c0b05168d6454 /gcc/tree-cfgcleanup.c | |
parent | 3e0b231e70a616c194497b29d61503e4c009630a (diff) | |
download | gcc-7b960d37a6e13afaf0d2f1777a2f5d1a27a659b4.tar.gz |
2010-01-15 Richard Guenther <rguenther@suse.de>
PR middle-end/42739
* tree-cfgcleanup.c (remove_forwarder_block): Move destination
labels of computed or non-local gotos to the destination.
* tree-cfg.c (gimple_verify_flow_info): Verify that a EH
landing pad label is the first label.
* g++.dg/torture/pr42739.C: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155937 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-cfgcleanup.c')
-rw-r--r-- | gcc/tree-cfgcleanup.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 9fb489a743d..5904407a35b 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -338,7 +338,6 @@ remove_forwarder_block (basic_block bb) gimple label; edge_iterator ei; gimple_stmt_iterator gsi, gsi_to; - bool seen_abnormal_edge = false; /* We check for infinite loops already in tree_forwarder_block_p. However it may happen that the infinite loop is created @@ -365,14 +364,10 @@ remove_forwarder_block (basic_block bb) So if there is an abnormal edge to BB, proceed only if there is no abnormal edge to DEST and there are no phi nodes in DEST. */ - if (has_abnormal_incoming_edge_p (bb)) - { - seen_abnormal_edge = true; - - if (has_abnormal_incoming_edge_p (dest) - || !gimple_seq_empty_p (phi_nodes (dest))) - return false; - } + if (has_abnormal_incoming_edge_p (bb) + && (has_abnormal_incoming_edge_p (dest) + || !gimple_seq_empty_p (phi_nodes (dest)))) + return false; /* If there are phi nodes in DEST, and some of the blocks that are predecessors of BB are also predecessors of DEST, check that the @@ -419,16 +414,40 @@ remove_forwarder_block (basic_block bb) } } - if (seen_abnormal_edge) + /* Move nonlocal labels and computed goto targets as well as user + defined labels and labels with an EH landing pad number to the + new block, so that the redirection of the abnormal edges works, + jump targets end up in a sane place and debug information for + labels is retained. */ + gsi_to = gsi_start_bb (dest); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) + { + tree decl; + label = gsi_stmt (gsi); + if (is_gimple_debug (label)) + break; + decl = gimple_label_label (label); + if (EH_LANDING_PAD_NR (decl) != 0 + || DECL_NONLOCAL (decl) + || FORCED_LABEL (decl) + || !DECL_ARTIFICIAL (decl)) + { + gsi_remove (&gsi, false); + gsi_insert_before (&gsi_to, label, GSI_SAME_STMT); + } + else + gsi_next (&gsi); + } + + /* Move debug statements if the destination has just a single + predecessor. */ + if (single_pred_p (dest)) { - /* Move the labels to the new block, so that the redirection of - the abnormal edges works. */ - gsi_to = gsi_start_bb (dest); - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) + gsi_to = gsi_after_labels (dest); + for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); ) { - label = gsi_stmt (gsi); - gcc_assert (gimple_code (label) == GIMPLE_LABEL - || is_gimple_debug (label)); + if (!is_gimple_debug (gsi_stmt (gsi))) + break; gsi_remove (&gsi, false); gsi_insert_before (&gsi_to, label, GSI_SAME_STMT); } |