Hi!

We were ignoring maybe_clean_or_replace_eh_stmt return value,
which tells us if stmt previously could throw but doesn't any longer.
I was a little bit worried that gimple_purge_dead_eh_edges from within
cfg cleanup wouldn't work well, but at least bootstrap/regtested
on x86_64-linux and i686-linux didn't show any issues.  Ok for trunk?

2011-12-19  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/51596
        * tree-cfg.c (replace_uses_by): Call gimple_purge_dead_eh_edges
        when needed.

        * g++.dg/opt/pr51596.C: New test.

--- gcc/tree-cfg.c.jj   2011-12-16 17:34:07.000000000 +0100
+++ gcc/tree-cfg.c      2011-12-19 11:47:12.554921183 +0100
@@ -1627,7 +1627,8 @@ replace_uses_by (tree name, tree val)
          if (fold_stmt (&gsi))
            stmt = gsi_stmt (gsi);
 
-         maybe_clean_or_replace_eh_stmt (orig_stmt, stmt);
+         if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt))
+           gimple_purge_dead_eh_edges (gimple_bb (stmt));
 
          update_stmt (stmt);
        }
--- gcc/testsuite/g++.dg/opt/pr51596.C.jj       2011-12-19 11:49:43.548046185 
+0100
+++ gcc/testsuite/g++.dg/opt/pr51596.C  2011-12-19 11:48:49.000000000 +0100
@@ -0,0 +1,39 @@
+// PR tree-optimization/51596
+// { dg-do compile }
+// { dg-options "-O -fnon-call-exceptions" }
+
+struct A { float v[2]; };
+struct B { int v[2]; };
+
+struct C
+{
+  B c;
+  C f ()
+  {
+    B b;
+    for (int i = 0; i < 2; i++)
+      b.v[i] = c.v[i];
+    return *this;
+  }
+};
+
+struct D
+{
+  A d;
+  D (B x)
+  {
+    for (int i = 0; i < 2; i++)
+      d.v[i] = x.v[i];
+  }
+};
+
+int bar ();
+
+C i;
+
+void
+foo ()
+{
+  while (bar ())
+    D (i.f ().c);
+}

        Jakub

Reply via email to