diff mbox

Fix asm goto handling in outof_cfglayout (PR rtl-optimization/51767)

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

Commit Message

Jakub Jelinek Jan. 5, 2012, 8 p.m. UTC
Hi!

On the following testcase we ICE, because one of the asm gotos degenerates
(has the same fallthru block as jump label destination) and the target
basic block doesn't immediately follow the block ending in the asm goto.
During outof_cfglayout force_nonfallthru_and_redirect incorrectly
adds an unconditional jump right after the asm goto, which means a control
flow insn is in the middle of the basic block.
Fixed by forcing the unconditional jump into a separate basic block after
the asm goto and ensuring there are two different edges to the target
basic block (one from asm goto and the other from the unconditional jump).

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

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.

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


	Jakub

Comments

Richard Henderson Jan. 5, 2012, 8:17 p.m. UTC | #1
On 01/06/2012 07:00 AM, Jakub Jelinek wrote:
> 	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.

Ok.


r~
diff mbox

Patch

--- gcc/cfgrtl.c.jj	2011-11-28 17:58:04.000000000 +0100
+++ gcc/cfgrtl.c	2012-01-05 15:59:27.873569579 +0100
@@ -1129,6 +1129,7 @@  force_nonfallthru_and_redirect (edge e,
   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,
 	}
     }
 
-  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,
       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,
 
       /* 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
--- gcc/testsuite/gcc.c-torture/compile/pr51767.c.jj	2012-01-05 16:25:22.679759517 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr51767.c	2012-01-05 16:25:40.391642696 +0100
@@ -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);
+}