2016-04-20 30 views
6

Gram z wbudowanym asemblerem D's i SSE, ale znalazłem coś, czego nie rozumiem. Kiedy próbuję dodać dwa wektory float4 natychmiast po deklaracji, obliczenia są poprawne. Jeśli umieściłem obliczenia w oddzielnej funkcji, otrzymam serię nan s.Nieznajoma SSE z funkcjami

//function contents identical to code section in unittest 
float4 add(float4 lhs, float4 rhs) 
{ 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } 
    return res; 
} 

unittest 
{ 
    float4 lhs = {1, 2, 3, 4}; 
    float4 rhs = {4, 3, 2, 1}; 

    println(add(lhs, rhs)); //float4(nan, nan, nan, nan) 

    //identical code starts here 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } //end identical code 
    println(res); //float4(5, 5, 5, 5) 
} 

Zespół funkcjonalnie identyczne (o ile można powiedzieć) do this link.

Edycja: Używam niestandardowej struktury float4 (na razie jest to tylko tablica), ponieważ chcę mieć funkcję dodawania, taką jak float4 add(float4 lhs, float rhs). W tej chwili, że powoduje błąd kompilatora tak:

Error: floating point constant expression expected instead of rhs

Uwaga: Używam DMD 2.071.0

+0

Mam nadzieję, że nie planujesz używać takiego kodu do wydajności. Zmuszasz kompilator do przechowywania wektorów w pamięci, a następnie zapisujesz te adresy w pamięci. Później piszesz kod, który ładuje adresy z pamięci i ponownie ładuje wektory. (W Windows 'vectorcall' ABI oraz w ABI SysV używanym przez wszystkie inne systemy AMD64, wektorowe argumenty są przekazywane w wektorowych rejestrach). W D, IDK, jeśli 'lhs_addr' może być rejestrem, ale nadal jest to bezużyteczny ruch registracyjny. Idealnie istnieje składnia dla zapytania o wektory w określonych regach, jak GNU C inline asm. –

+0

Próbuję napisać własny typ float4, ponieważ 'float4 rhs_vec = [rhs, rhs, rhs, rhs];' jest niedozwolone z błędem w pytaniu. W tej chwili zasadniczo skopiowałem kod z linku i wykonałem kilka drobnych zmian, aby (miejmy nadzieję) sprawiły, że działał w D. W tej chwili to po prostu musi zadziałać. Ale co byś zrobił zamiast sekcji? To tylko moja trzecia podróż do montażu, więc każda korekta byłaby doceniona. – Straivers

+0

Nie wiem D, właśnie widziałem to pytanie z powodu tagów SSE i inline-asm. Czy D ma coś takiego jak wewnętrzna Intel®? '__m128 my_vec = _mm_add_ps (vec1, vec2);'? Jeśli tak, prawdopodobnie lepiej sobie z tym poradzisz. Jeśli wbudowana składnia ASm jest ograniczona do przekazywania danych przez pamięć, a nie do rejestrów, to [jest to przydatne tylko wtedy, gdy chcesz napisać całą pętlę wewnątrz, a nie jako opakowanie dla kilku instrukcji] (http://stackoverflow.com/ pytania/3323445/jaka jest różnica między asem/asmem/35959859 # 3595985). Jeśli obsługuje instrukcje asm w stylu GNU-C, użyj tego. –

Odpowiedz

2

Twój kod jest dziwne, co wersja DMD używacie? Działa to tak, jak się podoba:

import std.stdio; 
import core.simd; 

float4 add(float4 lhs, float4 rhs) 
{ 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } 
    return res; 
} 

void main() 
{ 
    float4 lhs = [1, 2, 3, 4]; 
    float4 rhs = [4, 3, 2, 1]; 

    auto r = add(lhs, rhs); 
    writeln(r.array); //float4(5, 5, 5, 5) 

    //identical code starts here 
    float4 res; 
    auto lhs_addr = &lhs; 
    auto rhs_addr = &rhs; 
    asm 
    { 
     mov RAX, lhs_addr; 
     mov RBX, rhs_addr; 
     movups XMM0, [RAX]; 
     movups XMM1, [RBX]; 

     addps XMM0, XMM1; 
     movups res, XMM0; 
    } //end identical code 
    writeln(res.array); //float4(5, 5, 5, 5) 
} 
+0

Dziękuję za pomoc, ale po prostu zdałem sobie sprawę, że nie uwzględniłem niektórych kwestii w moim pytaniu, ponieważ zostały dodane do pytania. – Straivers

+0

@Straivers, czy Kozzi11 rzeczywiście odpowiedział na twoje pytanie, czy nie? – DejanLekic

+0

Nie. A raczej odpowiedział na oryginalne pytanie, które uświadomiło mi, że niewłaściwie sformułowałem to pytanie. Błąd, który został skorygowany. – Straivers