2016-04-20 1 views
6

J'ai joué avec l'assembleur en ligne de D et SSE, mais j'ai trouvé quelque chose que je ne comprends pas. Lorsque j'essaie d'ajouter deux vecteurs float4 immédiatement après la déclaration, le calcul est correct. Si je place le calcul dans une fonction séparée, j'obtiens une série de nan s.SSE étrangeté avec les fonctions

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

L'ensemble est fonctionnellement identique (pour autant que je peux dire) à this link. Editer: J'utilise une structure float4 personnalisée (pour l'instant, c'est juste un tableau) parce que je veux pouvoir avoir une fonction d'addition comme float4 add(float4 lhs, float rhs). Pour le moment, cela aboutit à une erreur de compilation comme ceci:

Error: floating point constant expression expected instead of rhs

Note: J'utilise DMD 2.071.0

+0

J'espère que vous ne prévoyez pas d'utiliser le code comme ça pour la performance. Vous forcez le compilateur à stocker les vecteurs en mémoire, puis à stocker ces adresses en mémoire. Ensuite, vous écrivez du code qui charge les adresses de la mémoire et recharge les vecteurs. (Dans l'ABI Windows 'vectorcall', et dans l'ABI SysV utilisé par tous les autres systèmes AMD64, les arguments vectoriels sont transmis dans les registres vectoriels). Dans D, IDK si 'lhs_addr' peut effectivement être un registre, mais c'est toujours un mouvement reg-reg inutile au mieux. Idéalement, il y a une syntaxe pour demander les vecteurs dans des regs spécifiques, comme GNU C inline asm. –

+0

J'essaie d'écrire mon propre type float4 car 'float4 rhs_vec = [rhs, rhs, rhs, rhs];' n'est pas autorisé avec l'erreur dans la question. Pour l'instant, j'ai essentiellement copié le code du lien, et j'ai fait quelques modifications mineures pour (espérons-le) que cela fonctionne dans D. Pour le moment, ça doit juste marcher. Cependant, que feriez-vous plutôt pour la section? Ceci est seulement ma troisième incursion dans l'assemblage, donc toute correction serait appréciée. – Straivers

+0

Je ne sais pas D, je viens de voir cette question à cause des balises SSE et inline-asm. Est-ce que D a quelque chose comme l'intrinsèque Intel C? '__m128 my_vec = _mm_add_ps (vec1, vec2);'? Si oui, vous ferez probablement mieux avec cela. Si la syntaxe inline de D est limitée à la transmission de données par la mémoire, pas aux registres, alors [c'est seulement utile si vous voulez écrire une boucle entière à l'intérieur, pas comme un wrapper pour quelques instructions] (http://stackoverflow.com/ questions/3323445/quoi-est-la-différence-entre-asm-et-asm/35959859 # 3595985). S'il prend en charge les instructions asm de style GNU-C, utilisez-le. –

Répondre

2

Votre code est wierd, quelle version de DMD utilisez-vous? Cela fonctionne comme excitée:

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

Merci pour votre aide, mais je viens de réaliser que j'ai omis d'inclure certaines choses dans ma question, elles ont depuis été ajoutées à la question. – Straivers

+0

@Straivers, est-ce que Kozzi11 a répondu à votre question ou non? – DejanLekic

+0

Non. Ou plutôt, il a répondu à la question initiale, ce qui m'a fait réaliser que j'avais mal formulé la question. Une erreur qui a été corrigée depuis. – Straivers