This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Stabilization on the ARM: an unrolling bug


Jeffrey A Law writes:
 >   > +   /* If there is a more than a single jump to the top of the loop
 >   > +      we cannot (easily) determine the iteration count.  */
 >   > +   if (LABEL_NUSES (JUMP_LABEL (last_loop_insn)) > 1)
 >   > +     {
 >   > +       if (loop_dump_stream)
 >   > + 	fprintf (loop_dump_stream,
 >   > + 		 "Loop iterations: Loop has multiple back edges.\n");
 >   > +       return 0;
 >   > +     }
 > This seems wrong.
 > 
 > For the case we are looking at, we can not determine the iteration count at
 > compile or run time, nor do we even know if the loop iterates one time.  It
 > seems to me those conditions ought to be preventing us from unrolling the
 > loop, not the label count for the head of the loop.

The loop iteration calculating code fails if we have multiple latch
blocks within a LOOP_BEG/LOOP_END pair.  I thought this was an easy
check for this condition.

Consider the following simpler loop which does have a known iteration
count at compile time:

static char fred[20];

void foo(bar)
     int bar;
{
  int i;
  
  for (i = 0; i < (bar ? 4 : 8); i++)
    fred[i] = 0;
}


The RTL from .cse for a 686 shows that we generate two jumps to the
loop head.  Without my patch, loop_iterations only finds the second
jump and assumes that the loop iterates once.

;; Function foo

;; Processing block from 2 to 28, 4 sets.
;; Processing block from 31 to 13, 3 sets.
;; Processing block from 14 to 44, 4 sets.
;; Processing block from 14 to 20, 6 sets.
;; Processing block from 21 to 44, 2 sets.
(note 2 0 4 "" NOTE_INSN_DELETED)

(insn 4 2 5 (set (reg/v:SI 22)
        (mem:SI (reg:SI 16 %argp) 2)) 54 {movsi+2} (nil)
    (expr_list:REG_EQUIV (mem:SI (reg:SI 16 %argp) 2)
        (nil)))

(note 5 4 6 "" NOTE_INSN_FUNCTION_BEG)

(note 6 5 8 "" NOTE_INSN_DELETED)

(note 8 6 11 0 NOTE_INSN_BLOCK_BEG)

(insn 11 8 12 (set (reg/v:SI 23)
        (const_int 0)) 54 {movsi+2} (nil)
    (expr_list:REG_EQUAL (const_int 0)
        (nil)))

(note 12 11 40 "" NOTE_INSN_LOOP_BEG)

(jump_insn 40 12 41 (set (pc)
        (label_ref 13)) -1 (nil)
    (nil))

(barrier 41 40 28)

(code_label 28 41 31 6 "")

(insn 31 28 33 (set (reg:SI 24)
        (mem:SI (symbol_ref:SI ("fred")) 1)) 54 {movsi+2} (nil)
    (nil))

(insn 33 31 35 (set (mem/s:QI (plus:SI (reg:SI 24)
                (reg/v:SI 23)) 0)
        (const_int 0)) 64 {movqi+1} (nil)
    (nil))

(note 35 33 38 "" NOTE_INSN_LOOP_CONT)

(insn 38 35 13 (set (reg/v:SI 23)
        (plus:SI (reg/v:SI 23)
            (const_int 1))) 148 {addsi3+1} (nil)
    (nil))

(code_label 13 38 14 3 "")

(insn 14 13 15 (set (cc0)
        (reg/v:SI 22)) 0 {tstsi_1} (nil)
    (nil))

(jump_insn 15 14 16 (set (pc)
        (if_then_else (eq (cc0)
                (const_int 0))
            (label_ref 20)
            (pc))) 286 {bleu+1} (nil)
    (nil))

(insn 16 15 17 (set (cc0)
        (compare (reg/v:SI 23)
            (const_int 3))) 12 {cmpsi_1} (nil)
    (nil))

(jump_insn 17 16 18 (set (pc)
        (if_then_else (le (cc0)
                (const_int 0))
            (label_ref 28)			<===== (1)
            (pc))) 286 {bleu+1} (nil)
    (nil))

(jump_insn 18 17 19 (set (pc)
        (label_ref 45)) -1 (nil)
    (nil))

(barrier 19 18 20)

(code_label 20 19 21 7 "")

(insn 21 20 22 (set (cc0)
        (compare (reg/v:SI 23)
            (const_int 7))) 12 {cmpsi_1} (nil)
    (nil))

(jump_insn 22 21 44 (set (pc)
        (if_then_else (le (cc0)
                (const_int 0))
            (label_ref 28)			<===== (2)
            (pc))) 286 {bleu+1} (nil)
    (nil))

(note 44 22 45 "" NOTE_INSN_LOOP_END)

(code_label 45 44 47 4 "")

(note 47 45 0 0 NOTE_INSN_BLOCK_END)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]