Hi!

On the following testcase we ICE because the builtin fn prototype doesn't
have throw () on it (glibc headers provide it, but some other C libraries
apparently don't) and thus we can have EH edges out of the builtin, and
call-cdce unconditionally split the block, leaving EH edge from an empty
bb and the required EH edge missing from the call.

In that case there is no point in splitting the block though, so fixed
thusly (not looking for last stmt, because that might be problematic with
-fcompare-debug).

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

2013-08-15  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/58165
        * tree-call-cdce.c (shrink_wrap_one_built_in_call): If
        bi_call must be the last stmt in a bb, don't split_block, instead
        use fallthru edge from it and give up if there is none.
        Release conds vector when returning early.

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

--- gcc/tree-call-cdce.c.jj     2013-08-13 12:20:33.000000000 +0200
+++ gcc/tree-call-cdce.c        2013-08-15 14:54:28.328435719 +0200
@@ -726,15 +726,28 @@ shrink_wrap_one_built_in_call (gimple bi
      return false and do not do any transformation for
      the call.  */
   if (nconds == 0)
-    return false;
+    {
+      conds.release ();
+      return false;
+    }
 
   bi_call_bb = gimple_bb (bi_call);
 
-  /* Now find the join target bb -- split
-     bi_call_bb if needed.  */
-  bi_call_bsi = gsi_for_stmt (bi_call);
+  /* Now find the join target bb -- split bi_call_bb if needed.  */
+  if (stmt_ends_bb_p (bi_call))
+    {
+      /* If the call must be the last in the bb, don't split the block,
+        it could e.g. have EH edges.  */
+      join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
+      if (join_tgt_in_edge_from_call == NULL)
+       {
+         conds.release ();
+         return false;
+       }
+    }
+  else
+    join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
 
-  join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
   bi_call_bsi = gsi_for_stmt (bi_call);
 
   join_tgt_bb = join_tgt_in_edge_from_call->dest;
--- gcc/testsuite/g++.dg/opt/pr58165.C.jj       2013-08-15 14:39:20.492586499 
+0200
+++ gcc/testsuite/g++.dg/opt/pr58165.C  2013-08-15 14:38:43.000000000 +0200
@@ -0,0 +1,14 @@
+// PR tree-optimization/58165
+// { dg-do compile }
+// { dg-options "-O2" }
+
+extern "C" float sqrtf (float);
+
+struct A { A (); ~A (); };
+
+void
+foo (double d)
+{
+  A a;
+  sqrtf (d);
+}

        Jakub

Reply via email to