Patchwork [committed] Fix endless moving of landing pads in ehcleanup (PR tree-optimization/47290)

login
register
mail settings
Submitter Jakub Jelinek
Date Jan. 18, 2011, 11:18 p.m.
Message ID <20110118231842.GM2724@tyan-ft48-01.lab.bos.redhat.com>
Download mbox | patch
Permalink /patch/79375/
State New
Headers show

Comments

Jakub Jelinek - Jan. 18, 2011, 11:18 p.m.
Hi!

This patch fixes endless moving of landing pads across empty bbs with single
successor if the landing pad is followed by empty infinite loop.
Approved by Richard in bugzilla, bootstrapped/regtested on x86_64-linux and
i686-linux, committed to trunk.

2011-01-19  Jakub Jelinek  <jakub@redhat.com>

	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.


	Jakub

Patch

--- gcc/tree-eh.c.jj	2010-11-19 20:56:55.000000000 +0100
+++ gcc/tree-eh.c	2011-01-18 18:16:11.000000000 +0100
@@ -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
   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);
--- gcc/testsuite/g++.dg/torture/pr47290.C.jj	2011-01-18 18:10:09.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr47290.C	2011-01-18 18:10:09.000000000 +0100
@@ -0,0 +1,19 @@ 
+// PR tree-optimization/47290
+// { dg-do compile }
+
+struct V
+{
+  V (int = 0);
+  ~V ()
+  {
+    for (;;)
+      ;
+  }
+  int size ();
+};
+
+struct S
+{
+  V a, b;
+  S () : b (a.size ()) {}
+} s;