Strange side-effect of -march=i386 on some builtin functions

Regis Duchesne hpreg@vmware.com
Tue Jun 26 15:54:00 GMT 2001


Using gcc 3.0 (i386-pc-linux-gnu) from the latest debian unstable, I
try to compile the following code:

bug.c
-----
unsigned int strlen(const char *s);
int abs(int j);


int
foo(char const *s)
{
   return abs(strlen(s));
}


int
main(int argc,
     char **argv)
{
   return 0;
}
-----

> gcc -O6 -Wall -c bug.c; gcc -o bug bug.o; gdb bug
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(no debugging symbols found)...
(gdb) disass foo
Dump of assembler code for function foo:
0x804842c <foo>:	push   %ebp
0x804842d <foo+1>:	mov    %esp,%ebp
0x804842f <foo+3>:	xor    %eax,%eax
0x8048431 <foo+5>:	push   %edi
0x8048432 <foo+6>:	cld    
0x8048433 <foo+7>:	mov    0x8(%ebp),%edi
0x8048436 <foo+10>:	mov    $0xffffffff,%ecx
0x804843b <foo+15>:	repnz scas %es:(%edi),%al
0x804843d <foo+17>:	not    %ecx
0x804843f <foo+19>:	mov    %ecx,%eax
0x8048441 <foo+21>:	dec    %eax
0x8048442 <foo+22>:	js     0x804844c <foo+32>
0x8048444 <foo+24>:	mov    (%esp,1),%edi
0x8048447 <foo+27>:	leave  
0x8048448 <foo+28>:	ret    
0x8048449 <foo+29>:	lea    0x0(%esi),%esi
0x804844c <foo+32>:	neg    %eax
0x804844e <foo+34>:	jmp    0x8048444 <foo+24>
End of assembler dump.
(gdb) quit

This is what I expect: for both abs() and strlen(), gcc's builtin functions are used.

Now I add the -march=i586 command line option:

> gcc -O6 -Wall -march=i586 -c bug.c; gcc -o bug bug.o; gdb bug
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(no debugging symbols found)...
(gdb) disass foo
Dump of assembler code for function foo:
0x8048470 <foo>:	push   %ebp
0x8048471 <foo+1>:	mov    %esp,%ebp
0x8048473 <foo+3>:	sub    $0x14,%esp
0x8048476 <foo+6>:	mov    0x8(%ebp),%eax
0x8048479 <foo+9>:	push   %eax
0x804847a <foo+10>:	call   0x804833c <strlen>
0x804847f <foo+15>:	test   %eax,%eax
0x8048481 <foo+17>:	js     0x8048490 <foo+32>
0x8048483 <foo+19>:	add    $0x10,%esp
0x8048486 <foo+22>:	mov    %ebp,%esp
0x8048488 <foo+24>:	pop    %ebp
0x8048489 <foo+25>:	ret    
0x804848a <foo+26>:	lea    0x0(%esi),%esi
0x8048490 <foo+32>:	neg    %eax
0x8048492 <foo+34>:	jmp    0x8048483 <foo+19>
0x8048494 <foo+36>:	lea    0x0(%esi),%esi
0x804849a <foo+42>:	lea    0x0(%edi),%edi
End of assembler dump.
(gdb) quit

As you can see, with that option on the command line, only the abs()
builtin function is used inline, and strlen() must be implemented
elsewhere !

This raises 2 questions:

1) Why does the -march=i586 option have an impact on the way builtin functions are used?

2) Why is it a problem for strlen() but not for abs()?

A possible answer to those 2 questions is possibly that
__builtin_strlen() is only defined for the i386 arch, but not for the
i586 arch. If this is the case, I think this is wrong, because the
builtin code also works on a i586, and so at least the same code (or
better) should be used for __builtin_strlen() on i586.

This is a problem for me, because the code in question is used in
standalone code (i.e. not linked with the glibc), and it forces me to
provide my own implementation of strlen() instead of the optimized one
built in gcc :(

Thanks in advance for any additional info,
-- 
Regis "HPReg" Duchesne
VMware, Inc. - Member of Technical Staff
http://www.VMware.com/



More information about the Gcc-bugs mailing list