PR rtl-optimization/46777
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 6 Dec 2010 19:28:09 +0000 (19:28 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 6 Dec 2010 19:28:09 +0000 (19:28 +0000)
* cfglayout.c (duplicate_insn_chain): Avoid duplicating
also barrier after tablejump.

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167513 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cfglayout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr46777.c [new file with mode: 0644]

index 285b8b7..047bcef 100644 (file)
@@ -1,3 +1,9 @@
+2010-12-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/46777
+       * cfglayout.c (duplicate_insn_chain): Avoid duplicating
+       also barrier after tablejump.
+
 2010-12-06  Joern Rennecke  <amylaar@spamcop.net>
            Richard Henderson  <rth@redhat.com>
 
index e883af4..f7d4d10 100644 (file)
@@ -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;
index 5244634..3c5c43e 100644 (file)
@@ -1,3 +1,8 @@
+2010-12-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/46777
+       * gcc.dg/pr46777.c: New test.
+
 2010-12-06  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * ada/acats/run_acats (which): Assign output to temporary
diff --git a/gcc/testsuite/gcc.dg/pr46777.c b/gcc/testsuite/gcc.dg/pr46777.c
new file mode 100644 (file)
index 0000000..e9f40a0
--- /dev/null
@@ -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;
+         }
+    }
+}