我想讓編譯器通過參數化我的C代碼中的內聯彙編來自動選擇寄存器,但是我遇到了一些麻煩。誰能告訴我發生了什麼問題?如果我使用我已註釋掉的代碼(強制與%xmm0有關),它將編譯並獲得預期結果。但是,如果我離開它註釋掉作爲寫到這裏,我得到的編譯器錯誤:嘗試在gcc中使用(SSE4)blendvpd和行內彙編
/tmp/ccJxmSbm.s: Assembler messages:
/tmp/ccJxmSbm.s:81: Error: the first operand of `blendvpd' must be `%xmm0'
另外,如果我什麼都不做除了去掉printf語句,代碼塊編譯成功過。所以它與移動參數有關,爲printf調用做準備。我已經明確地加入了應該強制使用%xmm0的「Yz」約束,但它看起來並沒有被尊重。
這裏是有問題的代碼:
#include <stdio.h>
const unsigned long long myConst[2] = {0x0000000000000000,0xffffffffffffffff};
const unsigned long long myConst2[2] = {0x0000000000000000,0x1111111111111111};
const unsigned long long myConst3[2] = {0xabcdef,0x0000000000000000};
#define ASSIGN_CONST128(val, const) \
val = *((__uint128_t *)const);
int main(void)
{
register __uint128_t regVal1 /* asm("%xmm0") */ ;
register __uint128_t regVal2;
register __uint128_t regVal3;
ASSIGN_CONST128(regVal1, myConst);
ASSIGN_CONST128(regVal2, myConst2);
ASSIGN_CONST128(regVal3, myConst3);
asm("blendvpd %[mask], %[val1], %[val2]" :
[val2] "+x" (regVal3) :
[mask] "Yz" (regVal1),
[val1] "x" (regVal2));
printf("REGVAL1: %016llx%016llx (original=%016llx%016llx)\n"
"REGVAL2: %016llx%016llx (original=%016llx%016llx)\n"
"REGVAL3: %016llx%016llx (original=%016llx%016llx)\n",
(unsigned long long)(regVal1>>64), (unsigned long long)regVal1,
myConst[1], myConst[0],
(unsigned long long)(regVal2>>64), (unsigned long long)regVal2,
myConst2[1], myConst2[0],
(unsigned long long)(regVal3>>64), (unsigned long long)regVal3,
myConst3[1], myConst3[0]);
// Expected result:
// REGVAL1: ffffffffffffffff0000000000000000 (original=ffffffffffffffff0000000000000000)
// REGVAL2: 11111111111111110000000000000000 (original=11111111111111110000000000000000)
// REGVAL3: 1111111111111111abcdef (original=0000000000000000abcdef)
}
我明白任何想法。
'__uint128_t'與'__m128d'不一樣。僅供參考,'icc'在此代碼上崩潰,'clang'拒絕編譯。 –
我的純粹無知。當我更改爲__m128i(實際上需要整數變體,如果它有所不同),我開始注意到編譯器手持多少。似乎所有與這種類型的對象的交互現在都必須在彙編中完成。不一定是問題,但我很難弄清楚。 – Marty
所以,現在我製作了兩個「無符號長整型」臨時變量,並使用movlpd/movhpd將xmmX寄存器內容移入它們。然後我可以對「unsigned long long」變量執行printf。 – Marty