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)