Loop optimizer misses simple optimisation?
Kamil Iskra
kiskra@ernie.icslab.agh.edu.pl
Tue Apr 28 07:23:00 GMT 1998
Hi,
In a debate on comp.sys.amiga.programmer, a debate that I would sum up as
"Does GCC really optimize so well as some people claim?" I came across a
relatively simple source where GCC indeed does perform rather poorly:
#define N (1UL<<22)
#define eN N
unsigned char a[N + 1];
main ()
{
unsigned int i;
for (i = 2; i <= (1UL << 11); i++)
if (a[i])
{
unsigned int j;
for (j = 2; j <= eN / i; j++)
a[i * j] = 0;
}
}
The author used GCC 2.6.3, I checked with EGCS 1.0.2 and the problem is
still there. Please have a look at what I get under m68k-linux, when
compiling with -O2:
.file "te2.c"
.version "01.01"
| GNU C version egcs-2.90.27 980315 (egcs-1.0.2 release) (m68k-unknown-linux-gnu) compiled by GNU C version egcs-2.90.27 980315 (egcs-1.0.2 release).
| options passed: -O2
| options enabled: -fdefer-pop -fcse-follow-jumps -fcse-skip-blocks
| -fexpensive-optimizations -fthread-jumps -fstrength-reduce -fpeephole
| -fforce-mem -ffunction-cse -finline -fkeep-static-consts -fcaller-saves
| -freg-struct-return -frerun-cse-after-loop -frerun-loop-opt -fcommon
| -fverbose-asm -fgnu-linker -fregmove -falias-check -fargument-alias
| -m68020 -mc68020 -mbitfield -m68881 -m68030 -m68332 -mcpu32
gcc2_compiled.:
.text
.align 2
.globl main
.type main,@function
main:
link.w %a6,#0
movm.l #0x3820,-(%sp)
moveq.l #2,%d2 | 9 movsi+1/2
move.l #a,%d4 | 105 movsi+1/1
lea a+2,%a2 | 109 movsi+1/1
moveq.l #4,%d3 | 114 movsi+1/2
.align 2
.L5:
tst.b (%a2)+ | 23 tstqi+1
jbeq .L4 | 24 beq
move.w #2,%a1 | 29 movsi+1/2
moveq.l #64,%d0 | 117 movsi+1/1
swap %d0
divu.l %d2,%d0 | 79 udivmodsi4
cmp.l %a1,%d0 | 80 cmpsi+1/1
jbcs .L4 | 81 bltu
move.l %d3,%a0 | 124 movsi+1/1
add.l %d4,%a0 | 96 *addsi3_internal/2
.align 2
.L10:
clr.b (%a0) | 43 movqi+1/3
add.l %d2,%a0 | 92 *addsi3_internal/2
addq.l #1,%a1 | 47 *addsi3_internal/2
moveq.l #64,%d0 | 120 movsi+1/1
swap %d0
divu.l %d2,%d0 | 32 udivmodsi4
cmp.l %a1,%d0 | 34 cmpsi+1/1
jbcc .L10 | 35 bgeu
.L4:
addq.l #2,%d3 | 111 *addsi3_internal/4
addq.l #1,%d2 | 61 *addsi3_internal/4
cmp.l #2048,%d2 | 13 cmpsi+1/2
jbls .L5 | 14 bleu
movm.l (%sp)+,#0x41c
unlk %a6
rts
.Lfe1:
.size main,.Lfe1-main
.comm a,4194305,1
.ident "GCC: (GNU) egcs-2.90.27 980315 (egcs-1.0.2 release)"
Have a look at insn 32: the division eN/i was not moved out of the
innermost loop, even though it clearly can be done.
I checked it on i486-linux and the problem is there, as well, unless I
can't grok i486 assembler (which happens to be almost true, actually :-).
Funny thing is that, on m68k, when I use -m68000, making udivmodsi4
unavailable, the optimisation is performed: the libcall is generated just
once.
Is this some sort of optimizer bug, or is this case more difficult than it
looks?
/ Kamil Iskra AmigaOS Linux/i386 Linux/m68k \
| GeekGadgets GCC maintainer UNIX system administrator |
| iskra@student.uci.agh.edu.pl kiskra@ernie.icslab.agh.edu.pl |
\ kamil@dwd.interkom.pl http://student.uci.agh.edu.pl/~iskra /
More information about the Gcc
mailing list