我们正在运行一个科学计划,我们想要实现AVX功能。整个程序(用Fortran + C编写)将被矢量化,此刻我正试图在GCC内联汇编中实现复数乘法。用于复数乘法的汇编代码/ AVX指令。 (GCC内联汇编)
的组件,代码需要4个复数和执行两个复数乘法一次:
v2complex cmult(v2complex *a, v2complex *b) {
v2complex ret;
asm (
"vmovupd %2,%%ymm1;"
"vmovupd %2, %%ymm2;"
"vmovddup %%ymm2, %%ymm2;"
"vshufpd $15,%%ymm1,%%ymm1,%%ymm1;"
"vmulpd %1, %%ymm2, %%ymm2;"
"vmulpd %1, %%ymm1, %%ymm1;"
"vshufpd $5,%%ymm1,%%ymm1, %%ymm1;"
"vaddsubpd %%ymm1, %%ymm2,%%ymm1;"
"vmovupd %%ymm1, %0;"
:
"=m"(ret)
:
"m" (*a),
"m" (*b)
);
return ret;
}
其中a和b是256位双精度:
typedef union v2complex {
__m256d v;
complex c[2];
} v2complex;
的问题是,该代码主要产生正确的结果,但有时会失败。
我对装配很新,但我试图自己弄清楚。似乎C程序(优化的-O3)与汇编代码中使用的寄存器ymm
交互。例如,我可以在执行乘法之前打印出其中一个值(例如a),并且程序不会给出错误的结果。
我的问题是如何告诉GCC不要与ymm交互。我没有设法将 放入ymm
来破坏寄存器列表。
非常感谢你,这解决了这个问题=)。我使用gcc 4.7.2和thx来提供建议。 –
不要使用'“r”(a),“r”(b)'用'vmovupd(%2),%% ymm1'等,GCC会假定* a和* b不被访问(除非你添加一个“内存”clobber)。 –