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)

Reply via email to