Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why gcc emits unneeded memory accesses when passing trivial struct by value?

It's known that some small structs with no non-trivial copy-ctor and no non-trivial dtor are passed in registers.

Quoting ARM Procedural Call Standard:

Fundamental types larger than 32 bits may be passed as parameters to, or returned as the result of, function calls. When these types are in core registers the following rules apply:  A double-word sized type is passed in two consecutive registers (e.g., r0 and r1, or r2 and r3). The content of the registers is as if the value had been loaded from memory representation with a single LDM instruction.

And indeed, I can easily confirm this with clang. gcc however emits a bunch of memory loads and stores for such a simple code snippet:

struct Trivial {
    int i1;
    int i2;
};

int foo(Trivial t)
{
    return t.i1 + t.i2;
}

$ clang++ arm.cpp -O2 -mabi=aapcs -c -S && cat arm.s

add r0, r0, r1
bx  lr

$ g++ arm.cpp -O2 -mabi=aapcs -c -S && cat arm.s

sub     sp, sp, #8
add     r3, sp, #8
stmdb   r3, {r0, r1}
ldmia   sp, {r0, r3}
add     r0, r0, r3
add     sp, sp, #8
bx      lr

I'm using the gcc and clang supplied by ArchlinuxARM distro, running on raspberry pi 2 (gcc 5.2), but I've also reproduced it with gcc based cross-compilers.

like image 725
Sergio Martins Avatar asked Dec 21 '15 00:12

Sergio Martins


1 Answers

This has been confirmed as a gcc bug here, now we wait.

like image 178
Sergio Martins Avatar answered Nov 18 '22 14:11

Sergio Martins