This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
i386-coff: regression from gcc 2.8.1
- To: egcs at egcs dot cygnus dot com
- Subject: i386-coff: regression from gcc 2.8.1
- From: Marc Espie <Marc dot Espie at liafa dot jussieu dot fr>
- Date: Thu, 17 Dec 1998 18:10:30 +0100
- Cc: egcs-bugs at egcs dot cygnus dot com
First some background. I am currently trying to get OpenBSD to switch from
gcc to egcs. So far, so good, I've managed to replace the compiler and rebuild
the whole system, BUT there is a large problem:
code output by egcs-1.1.1 is larger than code output by gcc 2.8.1.
The difference is between 1 and 2%, but, for instance, this means that the
boot disk no longer fits on a floppy: it's roughly 30K larger (that's a
whole COMPRESSED kernel with a ramdisk).
IF the code were better, I could probably manage to get the team to swallow
the pill, but the resulting code is worse !!!
I want to stress that this is an important problem: if I get a proper fix,
we will probably switch to egcs 1.1.1 officially, on *all* the architectures
we support, which means a code base of roughly 200Mbytes, plus various ports,
with the corresponding bug-reports when anything goes wrong...
Moreover, even with -Os, the result is STILL much larger than the old gcc 2.8.1
with -O2.
If you want to reproduce results, you can configure egcs-1.1.1 as i386-netbsd,
OR get the OpenBSD port from our port tree.
I've tried investigating further, and here is what I found:
- ascii data are now aligned with .align 5, but this does NOT account for most
of the size discrepancy.
- code quality is worse: egcs seems to delay putting stuff in registers to
the point of absurdity. Most of the cruft in egcs-1.1.1 seems to come from
code that goes: we have a value on the stack, we perform computations on the
stack, then we load the value in a register, whereas 2.8.1 used to pull the
value to a register BEFORE performing computation... this seems to affect
%eax more often than not.
Here is a very simple code fragment:
-----------------------------------------
typedef unsigned int speed_t;
int
cy_speed(speed_t speed, int *cor, int *bpr)
{
int c, co, br;
if(speed < 50 || speed > 150000)
return -1;
for(c = 0, co = 8; co <= 2048; co <<= 2, c++) {
br = (25000000 + (co * speed) / 2) / (co * speed);
if(br < 0x100) {
*bpr = br;
*cor = c;
return 0;
}
}
return -1;
}
-----------------------------------------
The corresponding 281 assembly code:
-----------------------------------------
.file "a.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
.align 2
.globl _cy_speed
.type _cy_speed,@function
_cy_speed:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
pushl %edi
pushl %esi
pushl %ebx
movl 8(%ebp),%esi
leal -50(%esi),%eax
cmpl $149950,%eax
jbe L2
jmp L11
.align 2,0x90
L10:
movl -8(%ebp),%edx
movl 16(%ebp),%eax
movl %edx,(%eax)
movl 12(%ebp),%eax
movl %ebx,(%eax)
xorl %eax,%eax
jmp L9
.align 2,0x90
L2:
xorl %ebx,%ebx
movl $8,%ecx
.align 2,0x90
L6:
movl %ecx,%edx
imull %esi,%edx
movl %edx,-4(%ebp)
shrl $1,%edx
movl %edx,%edi
addl $25000000,%edi
movl %edi,%eax
xorl %edx,%edx
divl -4(%ebp)
movl %eax,-8(%ebp)
cmpl $255,%eax
jle L10
sall $2,%ecx
incl %ebx
cmpl $2048,%ecx
jle L6
L11:
movl $-1,%eax
L9:
leal -20(%ebp),%esp
popl %ebx
popl %esi
popl %edi
leave
ret
Lfe1:
.size _cy_speed,Lfe1-_cy_speed
-----------------------------------------
Now with egcs 1.1.1:
-----------------------------------------
.file "a.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
.align 2,0x90
.globl _cy_speed
.type _cy_speed,@function
_cy_speed:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
pushl %edi
pushl %esi
pushl %ebx
movl 8(%ebp),%esi
leal -50(%esi),%eax
cmpl $149950,%eax
jbe L2
jmp L11
.align 2,0x90
L10:
movl -8(%ebp),%edx
movl 16(%ebp),%eax
movl %edx,(%eax)
movl 12(%ebp),%eax
movl %ebx,(%eax)
xorl %eax,%eax
jmp L9
.align 2,0x90
L2:
xorl %ebx,%ebx
movl $8,%ecx
.align 2,0x90
L6:
movl %ecx,%edx
imull %esi,%edx
movl %edx,-8(%ebp)
movl %edx,-4(%ebp)
shrl $1,-4(%ebp)
movl -4(%ebp),%edi
addl $25000000,%edi
movl %edi,%eax
xorl %edx,%edx
divl -8(%ebp)
movl %eax,-8(%ebp)
cmpl $255,%eax
jle L10
sall $2,%ecx
incl %ebx
cmpl $2048,%ecx
jle L6
L11:
movl $-1,%eax
L9:
leal -20(%ebp),%esp
popl %ebx
popl %esi
popl %edi
leave
ret
Lfe1:
.size _cy_speed,Lfe1-_cy_speed
-----------------------------------------
For that specific code fragment, I've traced the trouble to the regmove
`optimization'. If I disable it for egcs, I get the exact same code that
I used to get for gcc 2.8.1.
I've got a huge repository of code which show this kind of difference
everywhere. egcs is WORSE than gcc when it comes to i386 assembly.
I've looked at what linux does, and there is no possible comparison: the
configuration is different enough that the assembly code does not even
remotely look like what I get on netbsd/openbsd.
I am a bit out of my depth here, as I don't know i386 assembler all that well.
I've also tried with the latest snapshot, with no obvious difference.
Bottom line is, even apart from the new .align 5, egcs code is slightly larger
for no reasonable reason, e.g., the code is not better, it's even worse as it
does not use registers.
What I'd need is someone who knows more about gcc/egcs internals than I do
to perform experiments with a gcc2.8.1 vs. egcs1.1.1, with a netbsd/openbsd
basic configuration, tell me if I'm missing something.
I suspect some `weighing' of registers may have changed, which makes %eax
less attractive, or maybe the netbsd team missed a configuration change and
we're no longer using egcs to its full potential ?
It could also be a necessary fix for a bug that doesn't manifest itself very
often, but I'm going out on a limb there.
If there is indeed a regression, this is a real problem: the OpenBSD project
is quite prepared to switch to egcs, PROVIDED the compiler is up to what
gcc 2.8.1 did for C code. This does not appear to be the case right now.
I'm perfectly prepared to give more code examples, perform more experiments.
I can't really post the whole `experiment' there, as this amounts to ~12 megs
of assembler tar.gz for each kernel, but I can send whatever snippet you want
to look at... I think that, with a base i386-*bsd configuration, the problem
is pretty easy to reproduce...
--
Marc Espie
|anime, sf, juggling, unicycle, acrobatics, comics...
|AmigaOS, OpenBSD, C++, perl, Icon, PostScript...
| `real programmers don't die, they just get out of beta'