This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Pentium optimization problem
- From: Pavel Zeman <pzem6685 at artax dot karlin dot mff dot cuni dot cz>
- To: gcc at gcc dot gnu dot org
- Date: Thu, 13 Jun 2002 12:19:21 +0200 (CEST)
- Subject: Pentium optimization problem
Hello,
I've compiled GNU bc (http://www.gnu.org/software/bc/bc.html) using GCC
3.0.4 with different options and I've noticed that it runs much slower
when compiled for pentium than when compiled for pentiumpro.
Using gprof I found that the problem is in the _one_mult function:
static void
_one_mult (num, size, digit, result)
unsigned char *num;
int size, digit;
unsigned char *result; {
int carry, value;
unsigned char *nptr, *rptr;
if (digit == 0)
memset (result, 0, size);
else
{
if (digit == 1)
memcpy (result, num, size);
else
{
/* Initialize */
nptr = (unsigned char *) (num+size-1);
rptr = (unsigned char *) (result+size-1);
carry = 0;
while (size-- > 0)
{
value = *nptr-- * digit + carry;
*rptr-- = value % BASE;
carry = value / BASE;
}
if (carry != 0) *rptr = carry;
}
}
}
When compiled with "-O2 -march=pentium -mcpu=pentium -fomit-frame-pointer"
options, GCC generates following code:
_one_mult:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $12, %esp
movl 40(%esp), %ebp
movl 32(%esp), %edx
movl 36(%esp), %ecx
movl 44(%esp), %eax
testl %ebp, %ebp
je .L366
cmpl $1, %ebp
je .L367
leal -1(%ecx,%eax), %esi
leal -1(%ecx,%edx), %edi
movl %ecx, %eax
xorl %ebx, %ebx
jmp .L368
.p2align 4,,7
.L363:
xorl %edx, %edx
movb (%edi), %dl
imull %ebp, %edx
addl %ebx, %edx
decl %edi
movl %edx, 4(%esp)
movl $10, %ebx
movl %edx, %eax
sarl $31, %edx
idivl %ebx
movl $1717986919, %eax
movb %dl, (%esi)
imull 4(%esp)
movl %edx, %ebx
decl %esi
sarl $2, %ebx
movl 4(%esp), %edx
sarl $31, %edx
movl %edx, 4(%esp)
movl 4(%esp), %eax
subl %eax, %ebx
movl %ecx, %eax
.L368:
decl %ecx
testl %eax, %eax
jg .L363
testl %ebx, %ebx
je .L357
movb %bl, (%esi)
.L357:
addl $12, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.p2align 4,,7
.L367:
movl %ecx, 40(%esp)
movl %edx, 36(%esp)
movl %eax, 32(%esp)
addl $12, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
jmp memcpy
.p2align 4,,7
.L366:
movl %ecx, 40(%esp)
movl %eax, 32(%esp)
movl $0, 36(%esp)
addl $12, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
jmp memset
When compiled with "-O2 -march=pentium -mcpu=pentiumpro -fomit-frame-pointer"
options, the code looks like this:
_one_mult:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
subl $12, %esp
movl 40(%esp), %ebp
movl 32(%esp), %edx
movl 36(%esp), %ebx
testl %ebp, %ebp
movl 44(%esp), %eax
je .L366
cmpl $1, %ebp
je .L367
leal -1(%ebx,%eax), %esi
movl %ebx, %eax
leal -1(%ebx,%edx), %edi
decl %ebx
xorl %edx, %edx
testl %eax, %eax
jle .L365
.p2align 4
.L363:
movzbl (%edi), %ecx
movl $1717986919, %eax
decl %edi
imull %ebp, %ecx
addl %edx, %ecx
imull %ecx
movl %edx, 4(%esp)
movl 4(%esp), %edx
movl %eax, (%esp)
movl %ecx, %eax
sarl $31, %eax
sarl $2, %edx
subl %eax, %edx
leal (%edx,%edx,4), %eax
addl %eax, %eax
subl %eax, %ecx
movl %ebx, %eax
movb %cl, (%esi)
decl %ebx
decl %esi
testl %eax, %eax
jg .L363
.L365:
testl %edx, %edx
je .L357
movb %dl, (%esi)
.L357:
addl $12, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
.p2align 4,,7
.L367:
movl %ebx, 40(%esp)
movl %edx, 36(%esp)
movl %eax, 32(%esp)
addl $12, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
jmp memcpy
.p2align 4,,7
.L366:
movl %ebx, 40(%esp)
movl $0, 36(%esp)
movl %eax, 32(%esp)
addl $12, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
jmp memset
The main difference is in the division by BASE in the while loop. The
pentium pro version uses 2 imull's while the pentium version uses 2
imull's and 1 idivl. I think (I my tests prove it) that the pentium
version is slower even on a pentium because of the slow idivl
instruction.
Is this a bug in pentium optimization?
Pavel