2016-04-20 12 views
6

私はDのインラインアセンブラとSSEで遊んでいましたが、私が理解していないものが見つかりました。宣言の直後に2つのfloat4ベクトルを追加しようとすると、計算は正しいです。私が計算を別の関数に入れると、一連のnanが得られます。SSE strangeness with Functions

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

アセンブリは機能的には(私が知る限り)this linkと同じです。

編集:私はfloat4 add(float4 lhs, float rhs)のような追加機能を持たせたいので、私はカスタムのfloat4構造体を使用しています。今のところ、それはこのようなコンパイラエラーになり:

Error: floating point constant expression expected instead of rhs

注:私は

+0

実際にパフォーマンスのためのコードを使用する予定はないと思いますが、コンパイラにベクトルをメモリに格納させ、それらのアドレスをメモリに格納するように強制しています。次に、メモリからアドレスをロードし、ベクトルを再ロードするコードを書いています。 (Windowsの 'vectorcall' ABIでは、他のすべてのAMD64システムで使用されるSysV ABIでは、ベクトルargsがベクトルレジスタに渡されます)。 Dでは、 'lhs_addr'が実際にはレジスタになることができるIDKですが、それでもやはり無駄なreg-regの動きです。理想的には、GNU Cインラインasmのような特定のregs内のベクトルを尋ねる構文があります。 –

+0

'float4 rhs_vec = [rhs、rhs、rhs、rhs];は質問のエラーで許可されていないので、私は自分自身のfloat4型を書こうとしています。現時点では、リンクからコードをコピーしてコピーしていましたが、マイナーチェンジして(うまくいけば)Dで動作させるようにしました。現時点では動作するだけです。しかし、あなたはそのセクションの代わりに何をしますか?これはアセンブリへの私の3回目の進出なので、どんな修正も認められるでしょう。 – Straivers

+0

私はDを知らないのですが、私はSSEとインラインasmタグのためにこの質問を見ました。 DにはIntel Cの組み込み関数のようなものがありますか? '__m128 my_vec = _mm_add_ps(vec1、vec2);'?もしそうなら、あなたはおそらくそれでうまくいくでしょう。 Dのインラインasmシンタックスがレジスタではなくメモリを通してデータを渡すことに限定されているならば、[それはいくつかの命令のラッパーとしてではなく、ループ全体を記述したい場合にのみ役に立ちます](http://stackoverflow.com/質問/ 3323445/what-is-the-asm-asm-and-asm/35959859#3595985)。 GNU-Cスタイルのasmステートメントをサポートしている場合は、それを使用します。 –

答えて

2

あなたのコードは奇妙である、あなたは、DMDのどのバージョンを使用しないDMD 2.071.0を使用していますか?これはうまく動作します:

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

助けていただきありがとうございますが、私は私の質問にいくつかのものを含めることに失敗したことを知った、彼らは以来、質問に追加されている。 – Straivers

+0

@Straivers、Kozzi11は実際にあなたの質問に答えましたか? – DejanLekic

+0

いいえ、むしろ、彼は元の質問に答えました。私は質問を間違って表現していました。これ以降修正されたエラーです。 – Straivers