[英]builtin pcmpistri not working in gcc
我正在嘗試編寫一個strcmp版本,該版本利用利用 GCC 內在函數的 SSE4.2 新指令。
這是我到目前為止的代碼:
#include <stdio.h>
#include <smmintrin.h>
int main(int argc, char const *argv[])
{
int n;
const char str1[16] = "foo bar";
const char str2[16] = "foo quxx";
/* Safety check for SSE4.2 support */
__builtin_cpu_init();
if(__builtin_cpu_supports("sse4.2"))
puts("Ok SSE4.2");
else
{
puts("Nok SSE4.2");
return -__LINE__;
}
/* Load strings into registers */
__v16qi xmm1 = __builtin_ia32_loaddqu(str1);
__v16qi xmm2 = __builtin_ia32_loaddqu(str2);
/* Print to check registers were loaded correctly */
printf("xmm1: %s\nxmm2: %s\n", (const char *) &xmm1, (const char *) &xmm2);
/* Perform compare */
n = __builtin_ia32_pcmpistri128(xmm1, xmm2, (_SIDD_CMP_EQUAL_EACH | _SIDD_LEAST_SIGNIFICANT));
/* Print result */
printf("n: %d\n", n);
return 0;
}
它應該打印第一個不同字節的索引,但它總是打印 0。
我試圖調試它幾個小時,直到我在生成的程序集中看到這個:
call printf
movdqa -64(%rbp), %xmm1
movdqa -80(%rbp), %xmm0
pcmpistri $8, %xmm1, %xmm0
movl %ecx, %eax
pcmpistrm $8, %xmm1, %xmm0
movl %eax, -84(%rbp)
movl -84(%rbp), %eax
根據維基教科書,在輸出索引的指令(就像我正在嘗試使用的pcmpistri
一樣)的情況下,結果保存在ECX
寄存器中,但是,如果我pcmpistri
話,緊隨pcmpistri
的指令會覆蓋EAX
寄存器!
我認為這可能是讓我發瘋的錯誤,但我沒有組裝經驗,我可能錯了。
有人遇到這個問題嗎? 有誰知道如何解決這個問題?
我的Ubuntu 16.04下用GCC 5.4和6.2試過(實際上,慶典在Windows中)與任何-O0
, -O1
和-O2
(顯然-msse4.2
)。
讓我認為這是 GCC 錯誤的原因是,從 Visual Studio 2017 編譯的類似代碼 undex MSVC 可以正常工作:
#include <stdio.h>
#include <nmmintrin.h>
int main()
{
__m128i a, b;
const int mode = _SIDD_CMP_EQUAL_EACH | _SIDD_LEAST_SIGNIFICANT;
a.m128i_u16[7] = 0xFFFF;
a.m128i_u16[6] = 0xFFFF;
a.m128i_u16[5] = 0xFFFF;
a.m128i_u16[4] = 0xFFFF;
a.m128i_u16[3] = 0xFFFF;
a.m128i_u16[2] = 0xFFFF;
a.m128i_u16[1] = 0x0001;
a.m128i_u16[0] = 0xFFFF;
b.m128i_u16[7] = 0x0001;
b.m128i_u16[6] = 0x0001;
b.m128i_u16[5] = 0x0001;
b.m128i_u16[4] = 0x0001;
b.m128i_u16[3] = 0x0001;
b.m128i_u16[2] = 0x0001;
b.m128i_u16[1] = 0x0001;
b.m128i_u16[0] = 0x0001;
int returnValue = _mm_cmpistri(a, b, mode);
printf_s("%i\n", returnValue);
return 0;
}
您可能會驚訝地發現反匯編代碼實際上以相反的順序(即從左到右)呈現每條指令的參數列表。 所以 "movl %ecx, %eax" 實際上是 "MOV eax, ecx" ! 只需在指令級別中逐步在調試模式下運行您的代碼並跟蹤寄存器更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.