This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Stabilization on the ARM: an unrolling bug
- To: law at cygnus dot com
- Subject: Re: Stabilization on the ARM: an unrolling bug
- From: Michael Hayes <m dot hayes at elec dot canterbury dot ac dot nz>
- Date: Sun, 10 Jan 1999 22:39:34 +1300 (NZDT)
- Cc: Michael Hayes <m dot hayes at elec dot canterbury dot ac dot nz>, richard dot earnshaw at arm dot com, egcs-patches at cygnus dot com
- References: <"13975.58389.743226.112717"@ongaonga.elec.canterbury.ac.nz><16886.915954334@hurl.cygnus.com>
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)