Bug 37824 - funroll-loops miscompiles php
funroll-loops miscompiles php
Status: RESOLVED INVALID
Product: gcc
Classification: Unclassified
Component: regression
4.4.0
: P3 normal
: ---
Assigned To: Not yet assigned to anyone
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2008-10-14 11:33 UTC by Anton Blanchard
Modified: 2008-10-14 21:59 UTC (History)
1 user (show)

See Also:
Host:
Target: powerpc-linux
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anton Blanchard 2008-10-14 11:33:33 UTC
A gcc checkout from yesterday (4.4.0 20081013) is miscompiling php when built with 64bit and funroll-loops. A cut down test case is below but at this stage im not sure if its a violation of the aliasing rules.

good:
# gcc -m64 -O2 -o /tmp/foo /tmp/foo.c
# /tmp/foo
0xfffffabef50
0xfffffabef50
0xfffffabef50
0xfffffabef50
0xfffffabef50
0xfffffabef50

bad:
# gcc -m64 -funroll-loops -O2 -o /tmp/foo /tmp/foo.c
# /tmp/foo
0xfffffacef50
0xfffffacef50
(nil)
(nil)
(nil)
0xfffffacef50

code:

#include <stdio.h>
#include <stdlib.h>

void foo(int count, void **p)
{
        while (--count >= 0) {
                long *q = *(long **)(--p);
                *p = 0;
                printf("%p\n", q);
        }
}

int main()
{
        int i;
        long a;
        long *b = malloc(8 * sizeof(long));

        for (i = 0; i < 8; i++)
                *b++ = (unsigned long)&a;

        b--;
        foo(6, (void **)b);
        return 0;
}
Comment 1 Anton Blanchard 2008-10-14 11:59:24 UTC
Alan Modra points out the cast is not required and removing it does fix the issue.

BTW -Wstrict-aliasing (or -Wstrict-aliasing=2) doesn't warn about the code.
Comment 2 Richard Biener 2008-10-14 13:20:40 UTC
It is indeed an aliasing violation, you store a long and read a long*.

Fix it like

int main()
{
        int i;
        long a;
        long **b = malloc(8 * sizeof(long));

        for (i = 0; i < 8; i++)
                *b++ = &a;

        b--;
        foo(6, (void **)b);
Comment 3 Andrew Pinski 2008-10-14 21:59:14 UTC
There are two aliasing violations here.
The first is what Richard mentioned and the second is also in foo, there is a load from p via long* and also a store via void*.  That is where the issue comes down to here and not the other one but both are undefined code .