http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56451
--- Comment #1 from Kazumoto Kojima <kkojima at gcc dot gnu.org> 2013-02-26
00:32:07 UTC ---
Before dbr_schedule, the insns look like:
r1 := 0xc0000000
(A) if (r5 > r1) goto L0
(B) if (r5 < r1) goto L1
r1 := 0x80000000
(C) if (r4 >= r1) goto L0
L1: r0 := 1
goto L2
L0: r0 := 2
L2:
On SH, insns (A),(B),(C) can have delayed slot. dbr_schedule fills
a slot of (A) first:
r1 := 0xc0000000
(A) [if (r5 > r1) goto L2 | r0 := 2]
(B) if (r5 < r1) goto L1
r1 := 0x80000000
(C) if (r4 >= r1) goto L0
L1: r0 := 1
goto L2
L0: r0 := 2
L2:
Curiously, in the problematic case, dbr_schedule tries (C) next and
redundant_insn checks that r0 := 2 is whether redundant or not with
scanning insns backward from (C). It finds the insn in the slot of
(A) and deletes the insn r0 := 2 at L0 as an unnecessary one.
r1 := 0xc0000000
(A) [if (r5 > r1) goto L2 | r0 := 2]
(B) if (r5 < r1) goto L1
r1 := 0x80000000
(C) if (r4 >= r1) goto L0
L1: r0 := 1
goto L2
L0:
L2:
Then dbr_schedule fills the slot of (B):
r1 := 0xc0000000
(A) [if (r5 > r1) goto L2 | r0 := 2]
(B) [if (r5 < r1) goto L2 | r0 := 1]
r1 := 0x80000000
(C) if (r4 >= r1) goto L0
L1: r0 := 1
goto L2
L0:
L2:
Now (C) and r0 := 1 at L1 are useless because r0 is 1 before (C).
It seems to me that the above is an unexpected scenario to redundant_insn,
i.e. dbr_schedule uses it unsafely somewhere, though I gave up to find
where problematic use occurs. An easy patch below might be a bit
overkill but it fixes the problem for me.
--- ORIG/trunk/gcc/reorg.c 2013-01-11 11:35:58.000000000 +0900
+++ trunk/gcc/reorg.c 2013-02-25 17:17:34.000000000 +0900
@@ -1514,7 +1514,7 @@ redundant_insn (rtx insn, rtx target, rt
trial && insns_to_search > 0;
trial = PREV_INSN (trial))
{
- if (LABEL_P (trial))
+ if (LABEL_P (trial) || JUMP_P (trial))
return 0;
if (!INSN_P (trial))