Hi,

During testing the approved-for-commit middle-end patch for bug 43864 on ARM, I
ran into a gcc.dg/torture/pr46068.c ICE.

The following assert in haifa-sched.c:check_cfg triggered:
...
                  else if (any_condjump_p (head))
                    gcc_assert (/* Usual case.  */
                                (EDGE_COUNT (bb->succs) > 1
                                 && !BARRIER_P (NEXT_INSN (head)))
                                /* Or jump to the next instruction.  */
                                || (EDGE_COUNT (bb->succs) == 1
                                    && (BB_HEAD (EDGE_I (bb->succs, 0)->dest)
                                        == JUMP_LABEL (head))));
...

It triggered on this rtl, a conditional return followed by a barrier:
...
(jump_insn 44 43 93 7 (set (pc)
        (if_then_else (ne (reg:CC 24 cc)
                (const_int 0 [0]))
            (return)
            (pc))) gcc/testsuite/gcc.dg/builtin-unreachable-4.c:13 249
{*cond_return}
     (expr_list:REG_DEAD (reg:CC 24 cc)
        (expr_list:REG_BR_PROB (const_int 9996 [0x270c])
            (nil)))
 -> return)

(barrier 93 44 92)
...

Although this insn sequence is non-optimal (the conditional return can be
optimized to an unconditional one, given that it's followed by a barrier), it's
not incorrect. The patch fixes this ICE by removing the check for the
'EDGE_COUNT (bb->succs) == 1' case.

Bootstrapped and reg-tested on x86_64 and build and reg-tested on arm.

OK for trunk?

Thanks,
- Tom

2011-09-05  Tom de Vries  <t...@codesourcery.com>

        * haifa-sched.c (check_cfg): Remove restriction on conditional jump if
        the containing block has only 1 outgoing edge.
Index: gcc/haifa-sched.c
===================================================================
--- gcc/haifa-sched.c (revision 178145)
+++ gcc/haifa-sched.c (working copy)
@@ -6065,13 +6065,12 @@ check_cfg (rtx head, rtx tail)
 		    gcc_assert (EDGE_COUNT (bb->succs) == 1
 				&& BARRIER_P (NEXT_INSN (head)));
 		  else if (any_condjump_p (head))
-		    gcc_assert (/* Usual case.  */
-                                (EDGE_COUNT (bb->succs) > 1
-                                 && !BARRIER_P (NEXT_INSN (head)))
-                                /* Or jump to the next instruction.  */
-                                || (EDGE_COUNT (bb->succs) == 1
-                                    && (BB_HEAD (EDGE_I (bb->succs, 0)->dest)
-                                        == JUMP_LABEL (head))));
+		    gcc_assert (/* Weird case, like jump to the next insn
+				   or use of __builtin_unreachable ().  */
+				EDGE_COUNT (bb->succs) == 1
+				/* Normal case, one path falls through.  */
+				|| !BARRIER_P (NEXT_INSN (head)));
+
 		}
 	      if (BB_END (bb) == head)
 		{

Reply via email to