GCC优化内存访问[重复]
Posted
技术标签:
【中文标题】GCC优化内存访问[重复]【英文标题】:GCC optimizing memory accesses [duplicate] 【发布时间】:2020-11-01 19:42:55 【问题描述】:我有一段 C 代码,它有一个 int
数组 - 该代码对数组进行了多次读取。当我使用 -O0 标志将 GCC 编译为 X86 程序集时,在程序集中,对数组的所有读取访问都是使用 movl
指令进行的 - 32 位加载。这是有道理的,因为int
s 是 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 的一部分/调用约定)
【参考方案1】:
无需过多详细介绍我的工作,我需要使用
-O3
标志,但我需要对 32 位 int 数组的所有访问才能使用 32 位访问。
这是矛盾的。请参阅this reference 网站、C11 草案标准n1570 和 C++11 草案标准n3337。
这些标准并不要求对 32 位数组的所有访问都使用 32 位访问。
使用最近的GCC 10,使用gcc -fverbose-asm -O3 -S foo.c
,然后查看foo.s
以了解编译器优化的原因。
你可以试试其他编译器,
比如Compcert或Clang(甚至tinycc,或nwcc,或者从Frama-C开始写你自己的,或者甚至从头开始......)。如果他们的许可证适合您的工作,请向您的老板征求许可。
您还可以根据自己的需要改进这些编译器,或者编写自己的 GCC plugin 以满足您的需要。
如果你坚持使用 GCC,你可以考虑使用various assembler-related extensions。当然,请阅读invoking GCC。
GCC 是free software,你可以研究它的源代码然后改进它。
Download the source code 的 GCC。然后编译并install它。特别关注its pass manager。您当然可以删除让您烦恼的优化。你可能可以用你的 GCC 插件来做到这一点。寻求帮助并订阅gcc-help@gcc.gnu.org
mailing list。
【讨论】:
抱歉,这些文件很长 - 我应该在其中查看什么?为什么它是矛盾的 - 我不能关闭 -O3 所做的某些特定优化吗? 因为 C 标准规定这样的优化是合法的 您当然可以关闭某些优化。您只需要下载 GCC 的源代码并深入了解它。 可以从listed mirrors下载GCC源代码,例如mirrors.kernel.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.xz @Phidias:公平地说,其他代码中可能会发生其他优化,例如arr[0] = arr[1] = 0;
可以用一个整数 mov qword ptr [rdi], 0
存储完成。自动矢量化是与商店合并不同的优化。如果您只想在大多数正常情况下易于阅读 asm,而不是对编译器可能执行的操作有任何严格的正确性要求,那么这个答案完全是矫枉过正。但考虑到你提出问题的方式,它并没有真正错,只是不是很有帮助。另请参阅How to remove "noise" from GCC asm output?以上是关于GCC优化内存访问[重复]的主要内容,如果未能解决你的问题,请参考以下文章