我正在使用基于GCC 4.6.1的MinGW64构建Windows 64bit目标.我正在玩新的英特尔AVX指令.我的命令行参数是-march=corei7-avx -mtune=corei7-avx -mavx.
但是当我在堆栈上分配局部变量时,我开始遇到分段错误错误.GCC使用对准移动VMOVAPS和VMOVAPD移动__m256和__m256d周围,并且这些指令需要32字节对齐.但是,Windows 64bit的堆栈只有16字节对齐.
如何将GCC的堆栈对齐更改为32个字节?
我尝试使用-mstackrealign但无济于事,因为它只对齐16个字节.我也无法__attribute__((force_align_arg_pointer))工作,无论如何它都会对齐16个字节.我无法找到任何其他可以解决此问题的编译器选项.任何帮助是极大的赞赏.
编辑:
我尝试使用-mpreferred-stack-boundary=5,但GCC说这个目标不支持5.我没有想法.
Nor*_* P. 15
我一直在探索这个问题,提交了GCC错误报告,并发现这是与MinGW64相关的问题.见GCC Bug#49001.显然,GCC不支持Windows上的32字节堆栈对齐.这有效地防止了256位AVX指令的使用.
我调查了几个方法来处理这个问题.最简单和最直接的解决方案是用未对齐的替代品VMOVUPS等替换对齐的内存访问VMOVAPS/PD/DQA.所以我昨晚学习了Python(非常好的工具,顺便说一下)并且完成了以下脚本输入汇编程序文件由GCC生成:
import re
import fileinput
import sys
# fix aligned stack access
# replace aligned vmov* by unaligned vmov* with 32-byte aligned operands
# see Intel's AVX programming guide, page 39
vmova = re.compile(r"\s*?vmov(\w+).*?((\(%r.*?%ymm)|(%ymm.*?\(%r))")
aligndict = {"aps" : "ups", "apd" : "upd", "dqa" : "dqu"};
for line in fileinput.FileInput(sys.argv[1:],inplace=1):
m = vmova.match(line)
if m and m.group(1) in aligndict:
s = m.group(1)
print line.replace("vmov"+s, "vmov"+aligndict[s]),
else:
print line,
Run Code Online (Sandbox Code Playgroud)
这种方法非常安全且万无一失.虽然我在极少数情况下观察到了性能损失.当堆栈未对齐时,内存访问跨越缓存行边界.幸运的是,代码的执行速度与对齐访问一样快.我的建议:关键循环中的内联函数!
我还尝试使用另一个Python脚本修复每个函数prolog中的堆栈分配,尝试始终在32字节边界对齐它.这似乎适用于某些代码,但不适用于其他代码.我必须依赖GCC的良好意愿,它将分配对齐的局部变量(相对于堆栈指针),它通常会这样做.情况并非总是如此,特别是当由于在函数调用之前需要保存所有ymm寄存器而导致严重的寄存器溢出时.(所有ymm寄存器都是被调用者保存).如果有兴趣,我可以发布脚本.
最好的解决方案是修复GCC MinGW64构建.不幸的是,我不知道它的内部工作,上周就开始使用它了.