diff mbox

Don't duplicate BARRIER after tablejump in cfglayout bb header or footer (PR rtl-optimization/46777)

Message ID 20101206183809.GV29412@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 6, 2010, 6:38 p.m. UTC
Hi!

The following testcase ICEs, because a BB has a tablejump followed
by BARRIER in its il.rtl->header, and during unrolling duplicate_insn_chain
doesn't (intentionally) duplicate the tablejump, but does duplicate
the BARRIER into a header of many bbs, which breaks out of cfglayout
pass.

Fixed by not duplicating the corresponding BARRIER either.

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

2010-12-06  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/46777
	* cfglayout.c (duplicate_insn_chain): Avoid duplicating
	also barrier after tablejump.

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


	Jakub

Comments

Jeff Law Dec. 6, 2010, 7:12 p.m. UTC | #1
On 12/06/10 11:38, Jakub Jelinek wrote:
> Hi!
>
> The following testcase ICEs, because a BB has a tablejump followed
> by BARRIER in its il.rtl->header, and during unrolling duplicate_insn_chain
> doesn't (intentionally) duplicate the tablejump, but does duplicate
> the BARRIER into a header of many bbs, which breaks out of cfglayout
> pass.
>
> Fixed by not duplicating the corresponding BARRIER either.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2010-12-06  Jakub Jelinek<jakub@redhat.com>
>
> 	PR rtl-optimization/46777
> 	* cfglayout.c (duplicate_insn_chain): Avoid duplicating
> 	also barrier after tablejump.
>
> 	* gcc.dg/pr46777.c: New test.
OK.
Jeff
Paolo Bonzini Dec. 6, 2010, 8:17 p.m. UTC | #2
On 12/06/2010 07:38 PM, Jakub Jelinek wrote:
> Hi!
>
> The following testcase ICEs, because a BB has a tablejump followed
> by BARRIER in its il.rtl->header, and during unrolling duplicate_insn_chain
> doesn't (intentionally) duplicate the tablejump, but does duplicate
> the BARRIER into a header of many bbs, which breaks out of cfglayout
> pass.
>
> Fixed by not duplicating the corresponding BARRIER either.

I'm even more convinced that dropping (and eventually outlawing) 
BARRIERs in cfglayout mode would be a good idea...

Paolo
diff mbox

Patch

--- gcc/cfglayout.c.jj	2010-11-19 20:56:55.000000000 +0100
+++ gcc/cfglayout.c	2010-12-06 14:51:01.000000000 +0100
@@ -1177,7 +1177,20 @@  duplicate_insn_chain (rtx from, rtx to)
 	     moved far from original jump.  */
 	  if (GET_CODE (PATTERN (insn)) == ADDR_VEC
 	      || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
-	    break;
+	    {
+	      /* Avoid copying following barrier as well if any
+		 (and debug insns in between).  */
+	      rtx next;
+
+	      for (next = NEXT_INSN (insn);
+		   next != NEXT_INSN (to);
+		   next = NEXT_INSN (next))
+		if (!DEBUG_INSN_P (next))
+		  break;
+	      if (next != NEXT_INSN (to) && BARRIER_P (next))
+		insn = next;
+	      break;
+	    }
 	  copy = emit_copy_of_insn_after (insn, get_last_insn ());
           maybe_copy_prologue_epilogue_insn (insn, copy);
 	  break;
--- gcc/testsuite/gcc.dg/pr46777.c.jj	2010-12-06 15:12:33.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr46777.c	2010-12-06 15:10:21.000000000 +0100
@@ -0,0 +1,49 @@ 
+/* PR rtl-optimization/46777 */
+/* { dg-do compile } */
+/* { dg-options "-fgcse -O -fno-tree-dominator-opts -funroll-loops" } */
+
+struct S { char s[256]; };
+
+static inline int
+foo (int x, int y)
+{
+  switch (x)
+    {
+    case 1:
+    case 2:
+      return 3;
+    case 3:
+    case 4:
+      return 2;
+    case 5:
+      switch (y)
+	{
+	case 4:
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+void
+bar (struct S *x, int *y, int *z, int **w)
+{
+  switch (*y ? x->s[*y] : foo (y[1], y[0]))
+    {
+    case 3:
+      if (y + 2 == z)
+	for (;;)
+	  {
+	    y += 2;
+	    switch (*y ? x->s[*y] : foo (y[1], y[0]))
+	      {
+	      case 6:
+		break;
+	      default:
+		*w = y;
+	      }
+	    if (y == z)
+	      break;
+	  }
+    }
+}