2016-04-20 44 views
6

Ho giocato con l'assembler inline e SSE di D's, ma ho trovato qualcosa che non capisco. Quando provo ad aggiungere due vettori float4 immediatamente dopo la dichiarazione, il calcolo è corretto. Se inserisco il calcolo in una funzione separata, ottengo una serie di nan s.SSE stranezza con funzioni

//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) 
} 

Il complesso è funzionalmente identica (per quanto posso dire) a this link.

Modifica: sto usando una struttura personalizzata float4 (per ora, è solo un array) perché voglio essere in grado di avere una funzione di aggiunta come float4 add(float4 lhs, float rhs). Per il momento, che si traduce in un errore di compilazione come questo:

Error: floating point constant expression expected instead of rhs

Nota: sto usando DMD 2.071.0

+0

Spero che non stiate progettando di utilizzare effettivamente un codice del genere per le prestazioni. Stai costringendo il compilatore a memorizzare i vettori in memoria e quindi memorizzarli in memoria. Quindi stai scrivendo il codice che carica gli indirizzi dalla memoria e ricarica i vettori. (Nell'ABI 'vectorcall' di Windows, e nell'ABI SysV utilizzato da tutti gli altri sistemi AMD64, gli argomenti vettoriali sono passati nei registri vettoriali). In D, IDK se 'lhs_addr' può effettivamente essere un registro, ma è comunque una mossa reg-reg inutile al meglio. Idealmente c'è una sintassi per chiedere i vettori in regs specifici, come GNU C inline asm. –

+0

Sto provando a scrivere il mio tipo float4 perché 'float4 rhs_vec = [rhs, rhs, rhs, rhs];' non è consentito con l'errore nella domanda. Al momento ho essenzialmente copiato il codice dal link, e ho apportato qualche piccola modifica (si spera) a farlo funzionare in D. Al momento, deve solo funzionare. Tuttavia, cosa faresti invece per la sezione? Questa è solo la mia terza incursione in assemblea, quindi qualsiasi correzione sarebbe apprezzata. – Straivers

+0

Non conosco D, ho appena visto questa domanda a causa dei tag SSE e inline-asm. D ha qualcosa di simile agli intrinsechi Intel C? '__m128 my_vec = _mm_add_ps (vec1, vec2);'? Se è così, probabilmente farai meglio con quello. Se la sintassi in linea asm di D'è limitata al passaggio dei dati attraverso la memoria, non ai registri, allora [è utile solo se vuoi scrivere un intero ciclo al suo interno, non come un wrapper per alcune istruzioni] (http://stackoverflow.com/ domande/3323445/what-is-the-differenze-tra-asm-e-asm/35.959.859 # 3.595.985). Se supporta istruzioni asm in stile GNU-C, allora usa quello. –

risposta

2

Il codice è strano, quale versione di DMD si usa? Funziona come previsto:

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

Grazie per il tuo aiuto, ma ho appena realizzato che non sono riuscito a includere alcune cose nella mia domanda, da allora sono state aggiunte alla domanda. – Straivers

+0

@Straivers, Kozzi11 ha effettivamente risposto alla tua domanda o no? – DejanLekic

+0

No. O meglio, ha risposto alla domanda originale, che mi ha fatto capire che ho formulato la domanda in modo errato. Un errore che è stato poi corretto. – Straivers