This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
TESTCASE for powerpc misoptimization
- To: egcs-bugs at cygnus dot com
- Subject: TESTCASE for powerpc misoptimization
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Fri, 22 May 1998 06:45:55 -0700 (PDT)
- Cc: warner at lothar dot com, law at cygnus dot com
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?
Franz.
testcase:
/* { dg-do run } */
/* { dg-options "-O2 -fpic" } */
void foo1(int a, char *b, int c)
{
c =a+c+234;
}
int foo2(int d)
{
return d*d;
}
int bar1, bar2, bar3;
char * bar4;
int main(void) {
int h;
bar1 = foo2(1);
bar2 = foo2(1);
h = foo2(1);
foo1(1, "a", foo2(1));
foo1(bar1, "a", foo2(1));
foo2(1);
h = foo2(1);
bar3 = 1;
bar4 = "a";
foo1(1, "n", foo2(1));
foo1(1, "o", foo2(1));
foo1(1, "p", foo2(1));
foo1(bar1, "a", foo2(1));
bar3 = h;
bar4 = "b"; foo1(bar1, "b", foo2(1));
foo1(1, "q", foo2(1));
bar4 = "c"; foo1(1, "c", foo2(1));
bar4 = "d"; foo1(1, "d", foo2(1));
bar4 = "e"; foo1(1, "e", foo2(1));
bar4 = "f"; foo1(1, "f", foo2(1));
bar4 = "g"; foo1(1, "g", foo2(1));
bar4 = "h"; foo1(1, "h", foo2(1));
bar4 = "i"; foo1(1, "i", foo2(1));
bar4 = "j"; foo1(1, "j", foo2(1));
bar4 = "k"; foo1(1, "k", foo2(1));
bar4 = "l"; foo1(1, "l", foo2(1));
bar4 = "m";
foo1(bar2, "m", foo2(1));
exit(0);
}
warner@lothar.com wrote:
>Ok, I've got a weird one for you folks. I'm seeing a bug in the -fpic
>optimizer under egcs. The result of the bug is a crash during startup of the
>perl5 Gtk module because the register used to point to the GOT is mistakenly
>used to hold an intermediate result too early, trashing the GOT pointer which
>is then used to look up another global and segfaults.
>
>First, my environment:
> linux-pmac on a PowerCenterPro
> kernel is from the vger CVS archive, up-to-date as of mid May.
> egcs-1.0-2e installed from ftp.linuxppc.org RPM (latest available RPM)
> binutils-2.9.1-1a also from RPM (latest available RPM)
>
>compile the following with
> gcc -c -g -O2 -fpic foo.c
>then disassemble with
> objdump -d --source --reloc foo.o >foo.dis
> ------ begin -------
>void foo1(int, char *, int);
>int foo2(int);
>int bar1, bar2, bar3;
>char * bar4;
>
>void initPerlGdkDefs(void) {
> int h;
> bar1 = foo2(1);
> bar2 = foo2(1);
>
> h = foo2(1);
> foo1(1, "a", foo2(1));
> foo1(bar1, "a", foo2(1));
> foo2(1);
>
> h = foo2(1);
> bar3 = 1;
> bar4 = "a";
> foo1(1, "n", foo2(1));
> foo1(1, "o", foo2(1));
> foo1(1, "p", foo2(1));
> foo1(bar1, "a", foo2(1));
>
> bar3 = h;
> bar4 = "b"; foo1(bar1, "b", foo2(1));
> foo1(1, "q", foo2(1));
> bar4 = "c"; foo1(1, "c", foo2(1));
> bar4 = "d"; foo1(1, "d", foo2(1));
> bar4 = "e"; foo1(1, "e", foo2(1));
> bar4 = "f"; foo1(1, "f", foo2(1));
> bar4 = "g"; foo1(1, "g", foo2(1));
> bar4 = "h"; foo1(1, "h", foo2(1));
> bar4 = "i"; foo1(1, "i", foo2(1));
> bar4 = "j"; foo1(1, "j", foo2(1));
> bar4 = "k"; foo1(1, "k", foo2(1));
> bar4 = "l"; foo1(1, "l", foo2(1));
> bar4 = "m";
> foo1(bar2, "m", foo2(1));
>}
> ------ end ------
>
>I apologize for the contrived example, and for its length, but removing any
>statements at all results in the bug going away. The function used to be the
>initPerlGdkDefs() function of the GtkDefs.c file of the Gtk-0.2.1 perl5
>module,
>but is barely recognizable now.
>
>The bug is the following: if you look at the disassembled output, near the
>end:
> foo1(bar2, "m", foo2(1));
> 2d4: 38 60 00 01 li r3,1
> 2d8: 91 3b 00 00 stw r9,0(r27)
> 2dc: 81 3d 00 00 lwz r9,0(r29)
> 2de: R_PPC_GOT16 bar2
> 2e0: 83 a9 00 00 lwz r29,0(r9)
> 2e4: 48 00 00 01 bl 2e4 <initPerlGdkDefs+0x2e4>
> 2e4: R_PPC_PLTREL24 foo2
> 2e8: 81 3d 00 00 lwz r9,0(r29)
> 2ea: R_PPC_GOT16 .LC17
> 2ec: 7c 65 1b 78 mr r5,r3
> 2f0: 80 89 00 00 lwz r4,0(r9)
> 2f4: 7f a3 eb 78 mr r3,r29
> 2f8: 48 00 00 01 bl 2f8 <initPerlGdkDefs+0x2f8>
> 2f8: R_PPC_PLTREL24 foo1
>
>
>>From what I can tell, you get at some symbol in the GOT by doing a series of:
> lwz temp, GOT_OFFSET(r29)
> lwz dest, 0(temp)
>It looks like r29 holds the GOT pointer, and r9 is used as the temporary to do
>the dereference necessary to put the "m" string constant into r4. But at 2e0,
>r29 gets clobbered to hold 'bar2' in anticipation of transferring it into
>r3 at
>2f4. So the statement at 2e8 gets a segfault as we dereference 'bar2' plus
>some offset that should have pointed into the GOT table.
>
>In trying to minimize the test case, I discovered that it is strongly
>dependent upon having enough code in the middle of the function (removing any
>of the mostly identical 'bar4 = "c"; foo1(1, "c", foo2(1));' lines made the
>problem go away), and it depends upon the string constants in those middle
>lines being the same (perhaps it is merging identical strings into one,
>allowing the pointer to be re-used without a second GOT lookup but then
>requiring a spare register to hold that pointer across the foo2()
>calls?). Basically any way I shortened or modified the function from where it
>is now makes the problem go away. Compiling with -fPIC instead of -fpic makes
>the problem go away. -O1 instead of -O2 makes it go away, but turning off
>debugging doesn't seem to affect it.
>
>The number of lines necessary to trigger the bug makes me think that a
>register
>is getting allocated for each line, and the GOT table pointer is not getting
>protected from this allocation and gets clobbered.
>
>Does this help anyone? I'd be happy to try this against newer egcs versions,
>(especially if they came in RPM packages that were easy to back out..).
>Obviously I can just compile it -O1 and get a working module, but I thought
>that a real test case might be useful to the compiler wizards out there.
>
>Hope this does something for somebody,
> -Brian
> warner@lothar.com