非常简单的代码:
void *allocateMemory5DArray(size_t x, size_t y, size_t z, size_t q, size_t r)
{
int (*array)[x][y][z][q][r];
array = malloc(sizeof(*array));
return array;
}
Run Code Online (Sandbox Code Playgroud)
-O0gcc
需要 296 字节的堆栈,生成的代码长度 > 180 行。任何人都可以解释其背后的原理吗?
其他编译器(除了 clang)也会生成奇怪的代码,但不像gcc
:)
这种行为也发生在 VLA 中,Clang 也生成比 GCC 更短的代码。
虽然GCC生成的代码较长,-O0
拥有最快的编译时间(显然这是最快的GCC),汇编代码不优化,但我们并没有要求这一点。当 时-O1
,GCC 通过优化牺牲了时间,生成的代码与 clang 非常相似。
Clang 和 GCC 在 VLA 方面存在差异。第一个不支持结构中的VLA,原因:
Clang 对 C-99 VLA 很满意,但仅此而已。GCC 4.1(考虑到 GCC 4.5 对 C99 “基本上完全支持”)生成了类似的(小)尺寸:
...
mov %rax, QWORD PTR [%rbp-56]
mov %rdx, QWORD PTR [%rbp-48]
mov %rcx, QWORD PTR [%rbp-40]
mov %rsi, QWORD PTR [%rbp-32]
mov %rdi, QWORD PTR [%rbp-24]
...
Run Code Online (Sandbox Code Playgroud)
但是,在 GCC 4.8 中,代码变得更大。GCC 4.8文件没有说明有关 VLA 的任何更改,考虑到生成的代码中的明显差异,这很奇怪。
GCC 中 C99 功能的状态表明存在与 VLA 相关的“GCC 4.5 中修复的各种极端情况”。但是,4.5 更新日志什么也没说。令人惊讶的是,汇编在 4.4 中略有不同,但在 4.5 中没有。
看起来 Clang 关于结构中 VLA 的原因非常准确,在某些情况下,它们可能会扩展到整个 VLA 功能。
这种不良行为是众所周知的。Linux 的内核以性能的名义摆脱了它们:
Buffer allocation | Encoding throughput (Mbit/s)
---------------------------------------------------
on-stack, VLA | 3988
on-stack, fixed | 4494
kmalloc | 1967
Run Code Online (Sandbox Code Playgroud)
这对 CLang 建设者来说也是个好消息。
归档时间: |
|
查看次数: |
305 次 |
最近记录: |