Hi!

In gimple_fold_call (called from fold_stmt from replace_uses_by from cfg
cleanup) we weren't calling maybe_clean_or_replace_eh_stmt, so when
we've replaced a printf call (which can throw) with puts (which can throw
too), nothing would update EH stmts.  It would be problematic calling
gimple_purge_dead_eh_edges, because callers might be surprised by that,
especially when this happens during cfg cleanup, so instead I just assert
it is not needed and don't try to fold if a throwing stmt would be replaced
by non-throwing.  FAB pass can handle that instead.  No folding
has been actually disabled because of that check during bootstrap/regtest,
so it is there just in case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

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

        PR tree-optimization/51481
        * gimple-fold.c (gimple_fold_call): Call
        maybe_clean_or_replace_eh_stmt.  Avoid optimization if stmt has EH
        edges, but gimple_fold_builtin result can't throw.

        * gcc.dg/pr51481.c: New test.

--- gcc/gimple-fold.c.jj        2011-12-11 22:02:37.000000000 +0100
+++ gcc/gimple-fold.c   2011-12-12 11:42:34.740168390 +0100
@@ -1117,10 +1117,21 @@ gimple_fold_call (gimple_stmt_iterator *
   if (callee && DECL_BUILT_IN (callee))
     {
       tree result = gimple_fold_builtin (stmt);
-      if (result)
+      if (result
+         /* Disallow EH edge removal here.  We can't call
+            gimple_purge_dead_eh_edges here.  */
+         && (lookup_stmt_eh_lp (stmt) == 0
+             || tree_could_throw_p (result)))
        {
           if (!update_call_from_tree (gsi, result))
            gimplify_and_update_call_from_tree (gsi, result);
+         if (!gsi_end_p (*gsi))
+           {
+             gimple new_stmt = gsi_stmt (*gsi);
+             bool update_eh ATTRIBUTE_UNUSED
+               = maybe_clean_or_replace_eh_stmt (stmt, new_stmt);
+             gcc_assert (!update_eh);
+           }
          changed = true;
        }
     }
--- gcc/testsuite/gcc.dg/pr51481.c.jj   2011-12-12 11:18:27.304678207 +0100
+++ gcc/testsuite/gcc.dg/pr51481.c      2011-12-12 11:18:02.000000000 +0100
@@ -0,0 +1,33 @@
+/* PR tree-optimization/51481 */
+/* { dg-do compile } */
+/* { dg-options "-O -fexceptions -fipa-cp -fipa-cp-clone" } */
+
+extern const unsigned short int **foo (void)
+  __attribute__ ((__nothrow__, __const__));
+struct S { unsigned short s1; int s2; };
+extern struct S *s[26];
+
+void
+bar (int x, struct S *y, ...)
+{
+  static struct S *t;
+  __builtin_va_list ap;
+  __builtin_va_start (ap, y);
+  if (t != s[7])
+    {
+      const char *p = "aAbBc";
+      t = s[7];
+      while ((*foo ())[(unsigned char) *p])
+       p++;
+    }
+  __builtin_printf (x == 0 ? "abc\n" : "def\n");
+  if (y != 0)
+    __builtin_printf ("ghi %d %d", y->s2, y->s1);
+  __builtin_va_end (ap);
+}
+
+void
+baz (char *x)
+{
+  bar (1, 0, x);
+}

        Jakub

Reply via email to