c-使用指定初始化程序时的不同gcc程序集



我正在检查一些由gcc生成的ARM程序集,注意到如果我使用指定的初始化程序,会得到奇怪的结果:

例如,如果我有这个代码:

struct test 
{
int x;
int y;
};
__attribute__((noinline))
struct test get_struct_1(void)
{
struct test x;
x.x = 123456780;
x.y = 123456781;
return x;
}
__attribute__((noinline))
struct test get_struct_2(void)
{
return (struct test){ .x = 123456780, .y = 123456781 };
}

对于ARM(ARM gcc 6.3.0(,我得到了以下gcc-O2-std=C11的输出:

get_struct_1:
ldr r1, .L2
ldr r2, .L2+4
stm r0, {r1, r2}
bx lr
.L2:
.word 123456780
.word 123456781

get_struct_2:     // <--- what is happening here
mov r3, r0
ldr r2, .L5
ldm r2, {r0, r1}
stm r3, {r0, r1}
mov r0, r3
bx lr
.L5:
.word .LANCHOR0

我可以看到第一个函数的常量,但我不明白get_struct_2是如何工作的。

如果我为x86编译,那么这两个函数只需在一条指令中加载相同的64位值。

get_struct_1:
movabs rax, 530242836987890956
ret
get_struct_2:
movabs rax, 530242836987890956
ret

我是否引发了一些未定义的行为,或者这个.LANCHOR0在某种程度上与这些常数有关?

在将常量的加载合并到ldm中后,gcc似乎用额外级别的间接性射中了自己的脚。

不知道为什么,但很明显是一个遗漏的优化错误。

x86-64易于优化;整个8字节常量可以在一个立即数中进行。但ARM经常使用PC的相对负载来计算常量,这些常量对于一个立即数来说太大了。

最新更新