私は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
注:私は
実際にパフォーマンスのためのコードを使用する予定はないと思いますが、コンパイラにベクトルをメモリに格納させ、それらのアドレスをメモリに格納するように強制しています。次に、メモリからアドレスをロードし、ベクトルを再ロードするコードを書いています。 (Windowsの 'vectorcall' ABIでは、他のすべてのAMD64システムで使用されるSysV ABIでは、ベクトルargsがベクトルレジスタに渡されます)。 Dでは、 'lhs_addr'が実際にはレジスタになることができるIDKですが、それでもやはり無駄なreg-regの動きです。理想的には、GNU Cインラインasmのような特定のregs内のベクトルを尋ねる構文があります。 –
'float4 rhs_vec = [rhs、rhs、rhs、rhs];は質問のエラーで許可されていないので、私は自分自身のfloat4型を書こうとしています。現時点では、リンクからコードをコピーしてコピーしていましたが、マイナーチェンジして(うまくいけば)Dで動作させるようにしました。現時点では動作するだけです。しかし、あなたはそのセクションの代わりに何をしますか?これはアセンブリへの私の3回目の進出なので、どんな修正も認められるでしょう。 – Straivers
私は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ステートメントをサポートしている場合は、それを使用します。 –