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

Hard egcs 1.1 optimizer bug on sparc when using -O2



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!


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