gcc处理alloca的原因是什么?

时间:2017-02-27 21:41:34

标签: c gcc x86 alloca

在大多数平台上,alloca只是归结为堆栈指针的内联调整(例如,在x64上从rsp减去,加上一些逻辑来维持堆栈对齐)。

我正在查看gcc为alloca生成的代码,这很奇怪。采用以下简单示例 1

#include <alloca.h>
#include <stddef.h>

volatile void *psink;

void func(size_t x) {
  psink = alloca(x);
}

这将编译为-O2处的以下程序集:

func(unsigned long):
        push    rbp
        add     rdi, 30
        and     rdi, -16
        mov     rbp, rsp
        sub     rsp, rdi
        lea     rax, [rsp+15]
        and     rax, -16
        mov     QWORD PTR psink[rip], rax
        leave
        ret

这里有几个令人困惑的事情。我理解gcc需要将分配的大小四舍五入到16的倍数(以保持堆栈对齐),通常的方法是(size + 15) & ~0xF,但它在{{1}增加30 }}?怎么了?

其次,我希望add rdi, 30的结果是新的alloca值,它已经很好地对齐了。相反,gcc这样做:

rsp

这似乎是“重新调整” lea rax, [rsp+15] and rax, -16 作为rsp的结果使用的值 - 但我们已经完成了将alloca与16字节边界对齐的工作第一名。

这是怎么回事?

您可以使用代码on godbolt。值得注意的是rspclang至少在x86上执行“预期的事情”。使用VLA(如之前的评论中所述),iccgcc可以正常运行,clang会产生憎恶。

1这里,对icc的赋值只是为了消耗psink的结果,否则编译器就会完全省略它。

1 个答案:

答案 0 :(得分:7)

这是一个非常古老的,正常的优先级bug。代码工作正常。只是当大小大于1个字节时,不必要地分配16个字节。所以这不是一个正确性错误,它是一个小的效率错误。