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