summaryrefslogtreecommitdiff
path: root/gcc/tree-eh.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-18 23:16:16 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-18 23:16:16 +0000
commita9309f853c63d85aa4fcc4b947c2f76cf2e8ebff (patch)
tree7b35321de8d0dd4df0dafa71e743ef081c115373 /gcc/tree-eh.c
parent45ade45a473f927fd02ed0f6ac997b317cdb287b (diff)
downloadgcc-a9309f853c63d85aa4fcc4b947c2f76cf2e8ebff.tar.gz
PR tree-optimization/47290
* tree-eh.c (infinite_empty_loop_p): New function. (cleanup_empty_eh): Use it. * g++.dg/torture/pr47290.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168974 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r--gcc/tree-eh.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 270d76d9480..65d0ff2f9fd 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1,5 +1,5 @@
/* Exception handling semantics and decomposition for trees.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -3724,6 +3724,42 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp)
return false;
}
+/* Return true if edge E_FIRST is part of an empty infinite loop
+ or leads to such a loop through a series of single successor
+ empty bbs. */
+
+static bool
+infinite_empty_loop_p (edge e_first)
+{
+ bool inf_loop = false;
+ edge e;
+
+ if (e_first->dest == e_first->src)
+ return true;
+
+ e_first->src->aux = (void *) 1;
+ for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest))
+ {
+ gimple_stmt_iterator gsi;
+ if (e->dest->aux)
+ {
+ inf_loop = true;
+ break;
+ }
+ e->dest->aux = (void *) 1;
+ gsi = gsi_after_labels (e->dest);
+ if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
+ gsi_next_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ break;
+ }
+ e_first->src->aux = NULL;
+ for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest))
+ e->dest->aux = NULL;
+
+ return inf_loop;
+}
+
/* Examine the block associated with LP to determine if it's an empty
handler for its EH region. If so, attempt to redirect EH edges to
an outer region. Return true the CFG was updated in any way. This
@@ -3763,7 +3799,7 @@ cleanup_empty_eh (eh_landing_pad lp)
if (gsi_end_p (gsi))
{
/* For the degenerate case of an infinite loop bail out. */
- if (e_out->dest == bb)
+ if (infinite_empty_loop_p (e_out))
return false;
return cleanup_empty_eh_unsplit (bb, e_out, lp);