5

vld4_f32私はとvld4q_f32ARM NEON 命令の違いを理解する立場にありません。

混乱は、コーディング レベルを上げて、情報量の少ない組み込み関数ではなくアセンブリ命令に目を向け始めたときに始まりました。

ここでvld4バリアント命令を使用する必要がある理由は、大きな配列の4 番目ごとの位置から4 をキャプチャしたいからです。float32_t

代替テキスト

組み込み関数と対応するアセンブリ命令は次のvld4_f32ようになります (このリンクから)

float32x2x4_t vld4_f32 (const float32_t *) 
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]

vld4q_f32組み込み関数とそれに対応するアセンブリ命令は次のようになります。

float32x4x4_t vld4q_f32 (const float32_t *) 
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]

組み込みレベルで見た違いは戻り値の型ですが、アセンブリ命令とレジスタの数を見ると、どちらも同じように見えます。コンパイラまたはアセンブラは、この 2 つの違いをどのように認識しますか?

誰かがこれについてもっと明確にし、4番目のメモリ位置ごとに配置されている4つの float32_t値を単一のレジスタにロードする方法を説明できますか?

4

2 に答える 2

7

はい、違いがわかりました。CodeSourcery を使用して、すべてのロード命令の実際のレジスタの内容を確認しました。私が投稿したリンクは、vld4q_f32 の完全な詳細を示していません。

vld4_f32これは4 つの dレジスタ (例: d16-19) をロードします。各dレジスタは 64 ビット長であるため、この命令は、下の図に示すように、4 の間隔でインターリーブされた最初の 8 つの値をロードします。 代替テキスト

2 番目のケースではvld4q_f32、これは 4 つではなく8 つの dレジスタ (たとえば d16-23) をロードします。このリンクの読者にとって、 8 つのレジスタがロードされることはまったく明らかではありません。a の逆アセンブル コードを見ると、vld4qf328 つの d レジスタを使用していました。

この命令は、実際に私が望んでいたことを実行します。つまりfloat32_t、下の図に示すように、4 の間隔で 4 つの値をロードします。 代替テキスト

于 2010-09-29T12:13:10.370 に答える
2

私は2つの組み込み関数を逆アセンブルしました。誰かに役立つかもしれません:

// C++
uint32x4x4_t r = vld4q_u32( ( uint32_t *) output );
// assembly
VLD4.32         {D16,D18,D20,D22}, [R0]!
VLD4.32         {D17,D19,D21,D23}, [R0]

// C++
uint32x2x4_t r = vld4_u32( ( uint32_t *) output );
// assembly
VLD4.32         {D20-D23}, [R0]
于 2011-04-23T16:22:33.207 に答える