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]
Other format: [Raw text]

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



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