我們正在運行一個科學計劃,我們想要實現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)。 –