TESTCASE for powerpc misoptimization

Franz Sirl Franz.Sirl-kernel@lauterbach.com
Sun May 24 07:59:00 GMT 1998


>  In message < v03130305b18b4b44e3fc@[195.180.235.87] >you write:
>  > Hi,
>  >
>  > on the linux-pmac list an optimization bug with egcs-1.0.3 was reported
>  > (see original message below) with a testcase. I checked with the latest
>  > CVS-egcs and the bug is still there. I massaged the testcase a little bit
>  > for the gcc.dg directory.
>  >
>  > Jeff, what about the other testcase in my status report? Wasn't it fit for
>  > checkin?
>I added this test after minor tweaks (only run it on the rs6000/ppc
>since some targets don't support pic).

Hi Jeff,

this test won't be executed on powerpc unless you change the target restriction 
from ppc-* to powerpc-*.

It turns out the Linux kernel compilation bug (the "mknod" bug) is eventually
the same bug.

The appended testcase#1 produces the follwing correct code for -O2
-fno-expensive-optimizations:

int sys_mknod(const char * filename, int mode, dev_t dev)
{
 1800570:       94 21 ff e0     stwu    r1,-32(r1)
 1800574:       7c 08 02 a6     mflr    r0
 1800578:       93 61 00 0c     stw     r27,12(r1)
 180057c:       93 81 00 10     stw     r28,16(r1)
 1800580:       93 a1 00 14     stw     r29,20(r1)
 1800584:       93 c1 00 18     stw     r30,24(r1)
 1800588:       93 e1 00 1c     stw     r31,28(r1)
 180058c:       90 01 00 24     stw     r0,36(r1)
 1800590:       7c 9b 23 78     mr      r27,r4
 1800594:       7c bd 2b 78     mr      r29,r5
        int error;
        char * tmp;

        tmp = getname(filename);
 1800598:       4b ff ff 59     bl      18004f0 <getname>
 180059c:       57 a5 70 12     rlwinm  r5,r29,14,0,9
 18005a0:       7c 7c 1b 78     mr      r28,r3
 18005a4:       57 bd 06 3e     clrlwi  r29,r29,24
        error = ((long)( tmp )) ;
        do_mknod(tmp,mode,to_kdev_t(dev));
 18005a8:       7c a5 eb 78     or      r5,r5,r29
 18005ac:       7f 64 db 78     mr      r4,r27
 18005b0:       4b ff ff 15     bl      18004c4 <do_mknod>


The same testcase with -O2 produces this wrong code:

int sys_mknod(const char * filename, int mode, dev_t dev)
{
 1800568:       94 21 ff e0     stwu    r1,-32(r1)
 180056c:       7c 08 02 a6     mflr    r0
 1800570:       93 61 00 0c     stw     r27,12(r1)
 1800574:       93 81 00 10     stw     r28,16(r1)
 1800578:       93 a1 00 14     stw     r29,20(r1)
 180057c:       93 c1 00 18     stw     r30,24(r1)
 1800580:       93 e1 00 1c     stw     r31,28(r1)
 1800584:       90 01 00 24     stw     r0,36(r1)
 1800588:       7c 9b 23 78     mr      r27,r4
 180058c:       7c bd 2b 78     mr      r29,r5
        int error;
        char * tmp;

        tmp = getname(filename);
 1800590:       4b ff ff 61     bl      18004f0 <getname>
 1800594:       7c 7c 1b 78     mr      r28,r3
 1800598:       57 bd 70 12     rlwinm  r29,r29,14,0,9
        error = ((long)( tmp )) ;
        do_mknod(tmp,mode,to_kdev_t(dev));
 180059c:       7f 64 db 78     mr      r4,r27
 18005a0:       53 a5 00 2e     rlwimi  r5,r29,0,0,23     <-------
 18005a4:       4b ff ff 21     bl      18004c4 <do_mknod>

As you can see, the rlwimi instruction places r29 into the higher 24 bits of r5,
but r5 is clobbered in getname(), so the lower 8 bits of r5 contain wrong
values.

I additionally appended testcase#2 for the "needed new GOT during reload" bug,
which I already posted 2 times ;-).

Franz.

>----------------------------------
Testcase#1:

/* { dg-do run } */
/* { dg-options "-O2" } */

/*#include <stdio.h>*/

typedef unsigned int dev_t;
typedef unsigned int kdev_t;

static inline kdev_t to_kdev_t(int dev)
{
	int major, minor;
	
	if (sizeof(kdev_t) == 16)
		return (kdev_t)dev;
	major = (dev >> 8);
	minor = (dev & 0xff);
	return ((( major ) << 22 ) | (  minor )) ;

}

void do_mknod(const char * filename, int mode, kdev_t dev)
{
/*	printf("%0x\n",dev);*/
	if (dev==0x15800078)
		exit(0);
	else
		abort();
}


char * getname(const char * filename)
{
	register unsigned int a1,a2,a3,a4,a5,a6,a7,a8,a9;
	a1 = (unsigned int)(filename) *5 + 1;
	a2 = (unsigned int)(filename) *6 + 2;
	a3 = (unsigned int)(filename) *7 + 3;
	a4 = (unsigned int)(filename) *8 + 4;
	a5 = (unsigned int)(filename) *9 + 5;
	a6 = (unsigned int)(filename) *10 + 5;
	a7 = (unsigned int)(filename) *11 + 5;
	a8 = (unsigned int)(filename) *12 + 5;
	a9 = (unsigned int)(filename) *13 + 5;
	return (char *)(a1*a2+a3*a4+a5*a6+a7*a8+a9);
}

int sys_mknod(const char * filename, int mode, dev_t dev)
{
	int error;
	char * tmp;

	tmp = getname(filename);
	error = ((long)( tmp )) ;
	do_mknod(tmp,mode,to_kdev_t(dev));
	return error;
}

int main(void)
{
	return sys_mknod("test",1,0x12345678);
}


>----------------------------------
Testcase#2:

/* { dg-do compile { target rs6000-*-*-* powerpc-*-*-* } } */
/* { dg-options "-O2 -fpic" } */

int
test(void)
{
    double value, maxValue = - (__extension__	((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) { __l: 0x7ff0000000000000ULL }).__d)  ;
    int idx, maxIdx = 1;

    for (idx = 1; idx < 22; idx++) {
        if (value > maxValue) {
            maxValue = value;
            maxIdx = idx;
        }
    }
    return 0 ;
}



More information about the Gcc-bugs mailing list