This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Hard egcs 1.1 optimizer bug on sparc when using -O2
- To: rth at cygnus dot com, davem at dm dot cobaltmicro dot com, egcs-bugs at cygnus dot com
- Subject: Hard egcs 1.1 optimizer bug on sparc when using -O2
- From: Michael Widenius <monty at monty dot pp dot sci dot fi>
- Date: Thu, 8 Oct 1998 22:02:58 +0300 (EEST)
- cc: davida at analytikerna dot se
- Reply-To: monty at analytikerna dot se
Hi!
I am the MySQL maintainer and while testing egcs 1.1, I come across a
bug that looks like a bug in the while loop optimization code on sparc.
Some background information:
My system is a sun Sparcstation 10, sun4m running Solaris 2.6
gcc -v gives:
Reading specs from /my/gnu/lib/gcc-lib/sparc-sun-solaris2.6/egcs-2.91.57/specs
gcc version egcs-2.91.57 19980901 (egcs-1.1 release)
Compiler and option switches when compiling the problem source:
gcc -DMYSQL_SERVER -DDEFAULT_MYSQL_HOME="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DSHAREDIR="\"/usr/local/mysql/share/mysql\"" -DHAVE_CONFIG_H -I./../include -I./../regex -I. -I../include -I.. -I. -O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -fno-implicit-templates -DDBUG_OFF -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -S sql_table.cc
When compiling the above file (sql/sql_table.cc in the mysql 3.22.8 source
distribution), the following code:
while ((drop=drop_it++))
{
if (drop->type == Alter_drop::KEY && !my_strcasecmp(key_name, drop->name))
break;
}
if (drop)
{
drop_it.remove(); /* bug here !*/
continue;
}
breaks.
The remove code is defined as this:
inline void remove(void) // Remove current
{
list->remove(prev);
el=prev;
current=0; // Safeguard
}
and the list->remove code as this:
void remove(list_node **prev)
{
list_node *node=(*prev)->next;
delete *prev;
*prev=node;
if (!--elements)
last= &first;
}
Here egcs 1.1 when using optimization -O2 or higher, produces the
following code:
.LL4934:
ld [%i4+12],%l3
add %o0,4,%o0
b .LL4513
st %o0,[%fp-1660]
.LL4515:
cmp %o0,0
bne .LL4935
ld [%fp-1660],%o0
ld [%l0+4],%o1
call my_strcasecmp,0
mov %l3,%o0
cmp %o0,0
be .LL4936
cmp %l0,0
.LL4513:
ld [%fp-1660],%o0
.LL4935:
st %o0,[%fp-1656]
ld [%o0],%o1
cmp %o1,0
bne .LL4516
st %o1,[%fp-1652]
b .LL4517
mov 0,%l0
.LL4516:
add %o1,4,%o0
st %o0,[%fp-1660]
ld [%o1+8],%l0
.LL4517:
cmp %l0,0
bne,a .LL4515
ld [%l0+8],%o0 /* This while opt. 'destroys' %o0 */
cmp %l0,0
.LL4936:
be .LL4521
ld [%fp-1656],%o2
ld [%fp-1664],%o1
ld [%o0+4],%o3 /* This is wrong !!!! */
/* Here %o0 is 0 and %o1 holds the correct value to the variable prev */!
st %o3,[%o2]
ld [%o1+12],%o0
add %o0,-1,%o0
cmp %o0,0
bne .LL4533
st %o0,[%o1+12]
add %o1,4,%o0
--------------
With -O1, the important code part is:
O1:
call my_strcasecmp,0
ld [%l0+4],%o1
cmp %o0,0
bne .LL4864
ld [%fp-652],%o0
cmp %l0,0
be .LL4497
ld [%fp-656],%o1
ld [%fp-648],%o2
ld [%o2],%o0 /* This one was missing above */
ld [%o0+4],%o3
st %o3,[%o2]
ld [%o1+12],%o0
add %o0,-1,%o0
cmp %o0,0
------------
egcs 1.0.3a doesn't have this problem. The same code part compiled
with -O6:
call my_strcasecmp,0
mov %l5,%o0
cmp %o0,0
bne .LL4926
ld [%fp-1660],%o0
cmp %l0,0
be .LL4508
ld [%fp-1656],%o3
ld [%fp-1664],%o1
ld [%o3],%o0 /* OK!; %O0 must be fetched */
ld [%o0+4],%o2
st %o2,[%o3]
ld [%o1+12],%o0
add %o0,-1,%o0
cmp %o0,0
bne .LL4520
st %o0,[%o1+12]
add %o1,4,%o0
st %o0,[%o1+8]
.LL4520:
ld [%fp-1656],%o0
st %g0,[%fp-1652]
b .LL4496
st %o0,[%fp-1660]
.LL4508:
Note also that the egcs 1.0.3a code is much more compact than the
egcs 1.1 code!
---------------------
I can't easily make a test case of this, but as all code is available
on the Internet anyone that wants to test this can do the following:
- Download the MySQL 3.22.8 source distribution from:
http://www.tcx.se/Downloads/MySQL-3.22/mysql-3.22.8-beta.tar.gz
- configure it on a sparc + solaris system with
CFLAGS="-O6 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql
- Create a .s file:
cd sql
gcc -DMYSQL_SERVER -DDEFAULT_MYSQL_HOME="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DSHAREDIR="\"/usr/local/mysql/share/mysql\"" -DHAVE_CONFIG_H -I./../include -I./../regex -I. -I../include -I.. -I. -O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -fno-implicit-templates -DDBUG_OFF -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -S sql_table.cc
search in the sql_table.cc file after mysql_alter_table. After this,
jump to the fifth my_strcasecmp function. In this you will find the
offending code with a missing "ld [%o3],%o0"
If you have any questions or wan't a copy of the full sql_table.cc
file or a test case that you can run in MySQL to trigger this bug,
feel free to mail me!
Regards,
Monty
PS: I only wanted to note that we have been VERY pleased with egcs
1.0.1 -> 1.0.3a; We haven't had any problems with this before
and some bugs that we have found in egcs 2.8.1 hasn't found their
way into egcs and we have recommendet all MySQL users to use egcs
over any other compiler. Exellent work! I only hope that I will be
able to help you track down this bug as fast as possible!