Patchwork Fix tree-call-cdce.c (PR tree-optimization/58165)

login
register
mail settings
Submitter Jakub Jelinek
Date Aug. 15, 2013, 7:03 p.m.
Message ID <20130815190309.GC1814@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/267422/
State New
Headers show

Comments

Jakub Jelinek - Aug. 15, 2013, 7:03 p.m.
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  <jakub@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.


	Jakub
Richard Guenther - Aug. 16, 2013, 6:44 a.m.
Jakub Jelinek <jakub@redhat.com> wrote:
>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?
>
Ok,.
Thanks,
Richard.

>2013-08-15  Jakub Jelinek  <jakub@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

Patch

--- 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);
+}