https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103226
--- Comment #19 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
This looks like a target or RTL problem.
The .optimized dumps between x86-64 and bfin-elf look the same for:
-O2 -fno-tree-vrp -fno-tree-vectorize -fno-thread-jumps -fno-ivopts
-fno-tree-pre -fdisable-tree-pre -fdisable-tree-cunrolli -fdisable-tree-cunroll
-fdisable-tree-ivcanon
and yet bfin-elf hangs.
The problem is this loop:
e = !f && (n = 5);
if (e)
for (h = 0; h < 9; h++)
for (i = 0; i < 6; i++)
if (a)
g[h] = 4;
The register holding &g[h] overflows past the end and writes 4 to f, causing an
infinite loop.
Ultimately this boils down to:
cc = (a == 0)
<snip>
<snip>
R1 = 4 (X);
P5 = 9 (X);
LSETUP (.L5, .L25) LC1 = P5;
.L5:
P2 = I0; ;; p2 = &g
P0 = P2 + (P4 << 2); ;; p0 = &g[h]
P2 = 6 (X); ;; i = 6
.L7:
if cc jump .L6 (bp); ;; <<<< BOO HISS!!!!! <<<<<
[P0] = R1; ;; *(p0) = 4
.L6:
P2 += -1; ;; i--
cc =P2==0;
if !cc jump .L7; ;; if (i==0) goto .L7
.L25:
P4 += 1;
The first time we check CC, it's the a==0 gate skipping the write to g[h].
Then we overwrite CC with the inner loop latch (i==0) and jump back to L7 where
the check against CC is no longer related to "a", and false. So we overrwrite
[P0] with 4. This write is incorrect, but it's the eventual overflow of P0
into &f that causes a write to 4, and an infinite loop because if(e) will
always be false.
My RTL knowledge is very old and probably incorrect, but by *.alignments we
have:
;; THIS IS A CHECK FOR if(a)
(code_label 41 143 29 8 7 (nil) [1 uses])
(jump_insn 31 29 32 8 (set (pc)
(if_then_else (ne (reg:BI 34 CC [89])
(const_int 0 [0]))
(label_ref:SI 38)
(pc))) "j.c":19:10 124 {cbranchbi4}
(int_list:REG_BR_PROB 536870916 (nil))
-> 38)
<snip>
<snip>
;; HERE WE SET PC BUT DONT CLOBBER CC
(code_label 38 37 39 10 6 (nil) [1 uses])
(note 39 38 142 10 [bb 10] NOTE_INSN_BASIC_BLOCK)
(jump_insn 142 39 46 10 (parallel [
(set (pc)
(if_then_else (ne (reg:SI 10 P2 [98])
(const_int 1 [0x1]))
(label_ref:SI 41)
(pc)))
(set (reg:SI 10 P2 [98])
(plus:SI (reg:SI 10 P2 [98])
(const_int -1 [0xffffffffffffffff])))
(unspec [
(const_int 0 [0])
] 10)
(clobber (scratch:SI))
]) "j.c":18:19 96 {loop_end}
(int_list:REG_BR_PROB 920304124 (nil))
-> 41)
And in the *.reorg pass we clobber the CC and end up with the problematic
sequence:
(code_label 41 143 29 8 7 (nil) [1 uses])
(note 29 41 31 8 [bb 8] NOTE_INSN_BASIC_BLOCK)
(jump_insn:TI 31 29 32 8 (set (pc)
(if_then_else (ne (reg:BI 34 CC [89])
(const_int 0 [0]))
(label_ref:SI 38)
(pc))) "j.c":19:10 124 {cbranchbi4}
(int_list:REG_BR_PROB 536870916 (nil))
-> 38)
(note 32 31 37 9 [bb 9] NOTE_INSN_BASIC_BLOCK)
(insn:TI 37 32 38 9 (set (mem:SI (reg/f:SI 8 P0 [92]) [1 g[h_33]+0 S4 A32])
(reg:SI 1 R1 [93])) "j.c":20:14 19 {*movsi_insn}
(nil))
(code_label 38 37 39 10 6 (nil) [1 uses])
(note 39 38 218 10 [bb 10] NOTE_INSN_BASIC_BLOCK)
(insn 218 39 219 10 (set (reg:SI 10 P2 [98])
(plus:SI (reg:SI 10 P2 [98])
(const_int -1 [0xffffffffffffffff]))) "j.c":18:19 50 {addsi3}
(nil))
(insn 219 218 220 10 (set (reg:BI 34 CC)
(eq:BI (reg:SI 10 P2 [98])
(const_int 0 [0]))) "j.c":18:19 118 {compare_eq}
(nil))
(jump_insn 220 219 46 10 (set (pc)
(if_then_else (eq (reg:BI 34 CC)
(const_int 0 [0]))
(label_ref 41)
(pc))) "j.c":18:19 124 {cbranchbi4}
(nil)
-> 41)