wbudowane pcmpistri nie pracuje w gcc

głosy
1

Próbuję napisać strcmp wersji, która wykorzystuje SSE4.2 nowych instrukcji wykorzystujących intrinsics GCC.

Jest to kod mam tak daleko:

#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;
}

Należy wydrukować indeks pierwszego bajta inny, lecz zawsze drukuje 0.

Próbowałem debugować go przez kilka godzin, dopóki nie zobaczyłem to w wygenerowanym montażu:

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

Według Wikibooks w przypadku instrukcji, które wyjście indeks (podobnie jak pcmpistripróbuję użyć) wynik zostaje zapisany w ECXrejestrze, ale jeśli ja pamiętam poprawnie, instrukcja natychmiast po pcmpistrizadajnikami które zarejestrują się EAX!

Myślę, że to może być błąd, który doprowadza mnie do szału, ale nie mam doświadczenia w montażu i jestem prawdopodobnie źle.

Każdy doświadcza tego problemu? Czy ktoś wie jak rozwiązać ten problem?

Próbowałem z GCC 5.4 i 6.2 w Ubuntu 16.04 (faktycznie, bash na Windows) albo z -O0, -O1i -O2(i oczywiście -msse4.2).

Co sprawia, że ​​myślę, że to bug GCC jest, że podobny kod skompilowany undex MSVC z Visual Studio 2017 działa prawidłowo:

#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;
}
Utwórz 16/05/2017 o 17:02
użytkownik
W innych językach...                            


1 odpowiedzi

głosy
0

Yo może być zaskoczony, aby dowiedzieć się, które rzeczywiście demontażu prezentuje Kod listę argumentów każdej instrukcji w odwrotnej kolejności, czyli od lewej do rigth. Tak więc "movl% ecx,% eax" jest w rzeczywistości "MOV EAX, ECX"! Wystarczy uruchomić swój kod w trybie debugowania krok po kroku w Instruction Level i śledzenia zmian zarejestrować.

Odpowiedział 01/03/2020 o 08:13
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more