-funroll-loops regression in gcc3.0

dalej@apple.com dalej@apple.com
Thu Apr 26 16:05:00 GMT 2001

int foo;
void f(int p[4]) {
   int i;
   if ( foo )
     for ( i=0; i<4; i++ )
       p[i] = 0;
     for ( i=0; i<4; i++ )
       p[i] = foo;

Try this with -O3 -funroll-loops.  The first loop isn't unrolled (I'm on 
Darwin, but I'm fairly sure the target doesn't matter).  This is a 
regression from gcc2.95.

The code at the bottom of the first loop originally looks like this:

(jump_insn/i 113 112 114 (set (pc)...    ; conditional, to top of loop

(jump_insn/i 114 113 115 (set (pc)   ; unconditional, out of loop 
          (label_ref 119)) -1 (nil)      (nil))

(barrier/i 115 114 116)

(jump_insn/i 116 115 117 (set (pc)        ; dead, unreachable
          (label_ref 100)) -1 (nil)     (nil))

(barrier/i 117 116 118)

(note/i 118 117 119 NOTE_INSN_LOOP_END)

(code_label/i 119 118 120 117 "" "" [0 uses])

(jump_insn/i 120 119 121 (set (pc)
          (label_ref 123)) -1 (nil)

The jump_optimize() phase in 2.95 behaves differently from that in 3.0.
Both eliminate the dead insn 116 first.  Then 2.95 eliminates branches
to the following instruction, so 114 goes away.  But 3.0 does
branch-to-branch elimination instead, so 114 becomes a branch to 123,
and 120 goes away.  The difference is that in 3.0 the remaining jump is
inside the LOOP, where it doesn't belong; this confuses the unrolling
code.  (And possibly other code, for all I know.)

I tried to fix this by copying the branch-to-following removal up  
(doing it twice).
That works on this example, but got some kind of crash in gcc.c when 
(That was at a time when there were some other problems in jump.c, so 
I'll try it again
overnight.)  It could also be fixed in unroll.c (there is a comment that 
suggests this, in fact)
but I'm not sure that will fix the entire problem.  Maybe somebody 
familiar with jump.c
could look at this?

(-funroll-all-loops does unroll the first loop, but the code is very 

More information about the Gcc-bugs mailing list