re PR rtl-optimization/51767 (ICE with degenerated asm goto)
authorJakub Jelinek <jakub@redhat.com>
Thu, 5 Jan 2012 20:20:57 +0000 (21:20 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 5 Jan 2012 20:20:57 +0000 (21:20 +0100)
PR rtl-optimization/51767
* cfgrtl.c (force_nonfallthru_and_redirect): Force addition
of jump_block and add an extra edge for degenerated asm gotos.

* gcc.c-torture/compile/pr51767.c: New test.

From-SVN: r182922

gcc/ChangeLog
gcc/cfgrtl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr51767.c [new file with mode: 0644]

index 2e59648f2fa74a791cee6749cb683d8e9e109c23..1bd3bb2629564a5449bb801eb59dfd119057ba4c 100644 (file)
@@ -1,5 +1,9 @@
 2012-01-05  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/51767
+       * cfgrtl.c (force_nonfallthru_and_redirect): Force addition
+       of jump_block and add an extra edge for degenerated asm gotos.
+
        PR middle-end/51768
        * stmt.c (check_unique_operand_names): Don't ICE during error
        reporting if i is from labels chain.
index 4b1d8350de5d5b0a39de00e917f5d44e33d068ed..635955b799033b058b55761a7ebabd092e4c345e 100644 (file)
@@ -1,7 +1,7 @@
 /* Control flow graph manipulation code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011, 2012 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1129,6 +1129,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
   rtx note;
   edge new_edge;
   int abnormal_edge_flags = 0;
+  bool asm_goto_edge = false;
   int loc;
 
   /* In the case the last instruction is conditional jump to the next
@@ -1208,8 +1209,28 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
        }
     }
 
-  if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags)
+  /* If e->src ends with asm goto, see if any of the ASM_OPERANDS_LABELs
+     don't point to target label.  */
+  if (JUMP_P (BB_END (e->src))
+      && target != EXIT_BLOCK_PTR
+      && e->dest == target
+      && (e->flags & EDGE_FALLTHRU)
+      && (note = extract_asm_operands (PATTERN (BB_END (e->src)))))
     {
+      int i, n = ASM_OPERANDS_LABEL_LENGTH (note);
+
+      for (i = 0; i < n; ++i)
+       if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (target))
+         {
+           asm_goto_edge = true;
+           break;
+         }
+    }
+
+  if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags || asm_goto_edge)
+    {
+      gcov_type count = e->count;
+      int probability = e->probability;
       /* Create the new structures.  */
 
       /* If the old block ended with a tablejump, skip its table
@@ -1220,7 +1241,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
       note = NEXT_INSN (note);
 
       jump_block = create_basic_block (note, NULL, e->src);
-      jump_block->count = e->count;
+      jump_block->count = count;
       jump_block->frequency = EDGE_FREQUENCY (e);
       jump_block->loop_depth = target->loop_depth;
 
@@ -1236,13 +1257,27 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
 
       /* Wire edge in.  */
       new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU);
-      new_edge->probability = e->probability;
-      new_edge->count = e->count;
+      new_edge->probability = probability;
+      new_edge->count = count;
 
       /* Redirect old edge.  */
       redirect_edge_pred (e, jump_block);
       e->probability = REG_BR_PROB_BASE;
 
+      /* If asm goto has any label refs to target's label,
+        add also edge from asm goto bb to target.  */
+      if (asm_goto_edge)
+       {
+         new_edge->probability /= 2;
+         new_edge->count /= 2;
+         jump_block->count /= 2;
+         jump_block->frequency /= 2;
+         new_edge = make_edge (new_edge->src, target,
+                               e->flags & ~EDGE_FALLTHRU);
+         new_edge->probability = probability - probability / 2;
+         new_edge->count = count - count / 2;
+       }
+
       new_bb = jump_block;
     }
   else
index 5341574befe099b904ccba1a545271e3098cceb6..8db8b22655a28dc11b2e9f019623988a1d6364e7 100644 (file)
@@ -1,5 +1,8 @@
 2012-01-05  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/51767
+       * gcc.c-torture/compile/pr51767.c: New test.
+
        PR middle-end/51768
        * c-c++-common/pr51768.c: New test.
 
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr51767.c b/gcc/testsuite/gcc.c-torture/compile/pr51767.c
new file mode 100644 (file)
index 0000000..62a192d
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR rtl-optimization/51767 */
+
+extern void fn1 (void), fn2 (void);
+
+static inline __attribute__((always_inline)) int
+foo (int *x, long y)
+{
+  asm goto ("" : : "r" (x), "r" (y) : "memory" : lab);
+  return 0;
+lab:
+  return 1;
+}
+
+void
+bar (int *x)
+{
+  if (foo (x, 23))
+    fn1 ();
+  else
+    fn2 ();
+
+  foo (x, 2);
+}