【发布时间】:2020-11-01 19:42:55
【问题描述】:
我有一段 C 代码,它有一个 int 数组 - 该代码对数组进行了多次读取。当我使用 -O0 标志将 GCC 编译为 X86 程序集时,在程序集中,对数组的所有读取访问都是使用 movl 指令进行的 - 32 位加载。这是有道理的,因为ints 是 32 位的,因此访问它们的数组应该使用 32 位加载。
但是,当我使用 -O3 标志编译它时,读取到数组的几个 32 位 movl 被替换为 64 位加载到 XMM 寄存器中......我假设这是某种优化,但优化的反汇编很难破译,我对发生的事情有点迷茫。
无需过多详细介绍我的工作,我需要使用 O3 标志,但我需要对我的 32 位 int 数组的所有访问才能使用 32 位访问。
是否有人对可能发生的情况以及如何在仍使用 -O3 标志的同时将所有加载到我的数组的负载强制为 32 位有任何见解?
重现示例:
这是 C 代码:
#include <stdlib.h>
int main() {
int* arr = malloc(sizeof(int) * 64);
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += arr [i] + arr[i+1];
}
if (sum == 0)
return 0;
else
return 1;
}
对于未优化的反汇编,编译(注意反汇编中的 32 位加载):
gcc -S -fverbose-asm -o mb64BitLoadsNoOpt.s mb64BitLoads.c
为了优化反汇编,编译(注意在反汇编中加载 XMM 寄存器 64 位):
gcc -O3 -S -fverbose-asm -o mb64BitLoadsOpt mb64BitLoads.c
【问题讨论】:
-
在您的问题中包含您的 C 或 C++ 代码以及该代码的反汇编。使用适当的语言标签 - 不能同时使用。
-
尝试使用
gcc -Wall -Wextra -O3 -S -fverbose-asm yourcode.c,然后检查yourcode.s。请注意,C 和 C++ 是不同的编程语言。请参阅this reference website 并在您的问题中提供一些minimal reproducible example -
I need to use the O3 flag, but I need all accesses to my 32 bit int array to use 32 bit accesses.你为什么需要那个?目标硬件是否不支持 O3 生成的指令? -
@Phidias 很难说出您想要达到的目标。但是你可以用例如编译它吗?
-mno-sse2或使用-march -
@t.niese:或
-fno-tree-vectorize,这不会阻止它使用 SSE2 进行 memcpy,也不会破坏浮点代码(其中用于 XMM 寄存器的 SSE2 是 ABI 的一部分/调用约定)
标签: c gcc compilation x86