optimization/7465: Same function produces bad ARM code with C++ but correct one with C
eric.paire@ri.silicomp.fr
eric.paire@ri.silicomp.fr
Thu Aug 1 05:46:00 GMT 2002
>Number: 7465
>Category: optimization
>Synopsis: Same function produced bad ARM code with C++ but correct one with C
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: wrong-code
>Submitter-Id: net
>Arrival-Date: Thu Aug 01 05:46:06 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Eric PAIRE
>Release: 3.1.1
>Organization:
Silicomp Research Institute
>Environment:
System: Linux cheetah.ri.silicomp.com 2.4.7-10 #1 Thu Sep 6 17:27:27 EDT 2001 i686 unknown
Architecture: i686
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: arm-unknown-elf
configured with: ../gnu_tools/gcc/configure --target=arm-elf --prefix=/home/paire/ecos/gcc-3.1.1+binutils-2.12.1-cross/ --with-stabs --with-gnu-as --with-gnu-ld --with-headers=/home/paire/ecos/build-at91-ecos/install/include --with-libs=/home/paire/ecos/build-at91-ecos/install/lib --enable-languages=c,c++ --disable-nls
>Description:
With the same input code, GCC generates wrong ARM code when used
with the C++ front-end, but correct one when used with the C front-end.
Although visible with the ARM back-end, it seems to be completely independent
from it and only related to the instruction scheduler.
I have made a short investigation, and it seems that the only
difference between the RTL generated by the C and the one generated by
the C++ is in the alias set computation. I have written a short program
that shows up the problem (unfortunately, only visible by people familiar
with the ARM assembler).
>How-To-Repeat:
The same program can be named foo.c and foo.cc (in order to activate
the two front-ends). The problem is that the "obj" value dereferenced to
get the "next_element" field has been overwritten by "gs.last_element"
instead of being kept from the the original "h" value.
------ Cut Here ------ Cut Here ------ Cut Here ------ Cut Here ------
typedef struct object
{
struct object *next_element;
} object;
struct globals
{
void *last_element;
} gs;
void free_obj(object *h);
void free_ptr(void *h)
{
object *obj = *(object **)h;
*(void **)h = gs.last_element;
gs.last_element = h;
free_obj(obj->next_element); // The value of "obj" is incorrect with C++
}
------ Cut Here ------ Cut Here ------ Cut Here ------ Cut Here ------
when generated with the C front-end:
00000000 <free_ptr>:
0: e92d4010 stmdb sp!, {r4, lr}
4: e59f401c ldr r4, [pc, #28] ; 28 <free_ptr+0x28>
8: e5903000 ldr r3, [r0]
c: e1a01000 mov r1, r0
10: e5942000 ldr r2, [r4]
14: e5930000 ldr r0, [r3]
18: e5812000 str r2, [r1]
1c: e5841000 str r1, [r4]
20: e8bd4010 ldmia sp!, {r4, lr}
24: eafffffe b 0 <free_ptr>
24: R_ARM_PC24 free_obj
28: 00000000 andeq r0, r0, r0
28: R_ARM_ABS32 gs
Notice that at offset 8, "obj" is kept in r3 and that at offset 14, r0
contains the right "obj->next_element".
BUT, when generated with the C++ front-end
00000000 <_Z8free_ptrPv>:
0: e52de004 str lr, [sp, -#4]!
4: e59f1014 ldr r1, [pc, #20] ; 20 <_Z8free_ptrPv+0x20>
8: e5913000 ldr r3, [r1]
c: e5803000 str r3, [r0]
10: e5810000 str r0, [r1]
14: e5930000 ldr r0, [r3]
18: e49de004 ldr lr, [sp], #4
1c: eafffffe b 0 <_Z8free_ptrPv>
1c: R_ARM_PC24 _Z8free_objP6object
20: 00000000 andeq r0, r0, r0
20: R_ARM_ABS32 gs
Notice that "obj" is not kept, but instead at line c, "obj" is overwritten
with r3 containing "gs.last_element", thus leading to the bug that the
"obj->next_element" is in fact "gs.last_element".
>Fix:
The (temporary) fix for the C++ front-end (since the C front-end works
correctly) is to modify the code to help the front-end to detect aliasing:
Replace
*(void **)h = gs.last_element;
by
*(object **)h = (object *)gs.last_element;
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the Gcc-bugs
mailing list