This is the mail archive of the gcc@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]

i386-coff: regression from gcc 2.8.1


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'


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