C++ コードから NEON 組み込み関数を使用して ARM の最適化に取り組んでいます。タイピングの問題のほとんどを理解して習得していますが、これには行き詰まっています:
この命令は値 (実際には 2 つの配列) をvzip_u8
返します。戻り値をプレーンに割り当てたい。それを達成するための適切な組み込みは見当たらず、単純なキャストは拒否されます。uint8x8x2_t
uint8x8_t
uint16x8_t
vreinterpretq
C++ コードから NEON 組み込み関数を使用して ARM の最適化に取り組んでいます。タイピングの問題のほとんどを理解して習得していますが、これには行き詰まっています:
この命令は値 (実際には 2 つの配列) をvzip_u8
返します。戻り値をプレーンに割り当てたい。それを達成するための適切な組み込みは見当たらず、単純なキャストは拒否されます。uint8x8x2_t
uint8x8_t
uint16x8_t
vreinterpretq
明確に答えるいくつかの定義...
NEONには、64 ビット幅の 32 個のレジスタがあります (16 個のレジスタ、128 ビット幅のデュアル ビュー)。
NEON ユニットは、以下と同じレジスタ バンクを表示できます。
- 16 個の 128 ビット クワッドワード レジスタ、Q0 ~ Q15
- 32 個の 64 ビット ダブルワード レジスタ、D0 ~ D31。
uint16x8_t
は 128 ビットのストレージを必要とするタイプであるため、quadword
レジスタに格納する必要があります。
ARM NEON Intrinsics には、ARM® C Language Extensions で呼び出される定義がvector array data type
あります。
... ロードおよびストア操作、テーブル ルックアップ操作、およびベクトルのペアを返す操作の結果の型として使用します。
vzip命令
... 2 つのベクトルの要素をインターリーブします。
vzip Dd, Dm
そして、本質的なようなものを持っています
uint8x8x2_t vzip_u8 (uint8x8_t, uint8x8_t)
これらから、uint8x8x2_t は実際には 2 つの乱数のダブルワード レジスタのリストであると結論付けることができます。これは、vzip 命令には入力レジスタの順序に関する要件がないためです。
今答えは...
uint8x8x2_t
は連続していない 2 つのデュアルワード レジスタを含むことができますuint16x8_t
が、最初の 1 つが偶数インデックス (D0-D31 -> Q0-Q15) を持つ 2 つの連続したデュアルワード レジスタで構成されるデータ構造です。
vector array data type
このため、 2 つのダブルワード レジスタをクワッドワード レジスタにキャストすることはできません... 簡単に。
コンパイラはあなたを支援するのに十分スマートかもしれませんし、変換を強制することもできますが、結果のアセンブリの正確性とパフォーマンスをチェックします。
vcombine_* 組み込み関数を使用して、2 つの 64 ビット ベクトルから 128 ビット ベクトルを構築できます。したがって、このようにあなたが望むものを達成することができます。
#include <arm_neon.h>
uint8x16_t f(uint8x8_t a, uint8x8_t b)
{
uint8x8x2_t tmp = vzip_u8(a,b);
uint8x16_t result;
result = vcombine_u8(tmp.val[0], tmp.val[1]);
return result;
}
回避策を見つけました。型のval
メンバーがuint8x8x2_t
配列であるため、ポインターとして認識されます。ポインターのキャストと逆参照が機能します。[データのアドレスを取得すると、「一時的なアドレス」の警告が発生します。]
uint16x8_t Value= *(uint16x8_t*)vzip_u8(arg0, arg1).val;
これは、必要に応じてコンパイルおよび実行されることがわかりました (少なくとも私が試した場合)。アセンブリ コードを見ていないので、適切に実装されているとは言えません (つまり、メモリへの書き込み/メモリからの読み取りではなく、レジスタに値を保持するだけです)。
私も同じような問題に直面していたので、柔軟なデータ型を導入しました。
したがって、次のように定義できます。
typedef NeonVectorType<uint8x16_t> uint_128bit_t; //suitable for uint8x16_t, uint8x8x2_t, uint32x4_t, etc.
typedef NeonVectorType<uint8x8_t> uint_64bit_t; //suitable for uint8x8_t, uint32x2_t, etc.
4.5 および 4.6 シリーズの GCC のバグ (現在は修正済み) です。
Bugzilla リンクhttp://gcc.gnu.org/bugzilla/show_bug.cgi?id=48252
このバグを修正して gcc ソースに適用し、再構築してください。