[英]Data type compatibility with NEON intrinsics
我正在使用來自C ++代碼的NEON內在函數進行ARM優化。 我理解並掌握了大多數打字問題,但我仍然堅持這一點:
指令vzip_u8
返回uint8x8x2_t
值(實際上是兩個uint8x8_t
的數組)。 我想將返回的值分配給普通的uint16x8_t
。 我認為沒有適當的vreinterpretq
內在實現它,並且簡單的強制轉換被拒絕。
一些定義要清楚地回答......
NEON有32個寄存器,64位寬(雙視圖為16個寄存器,128位寬)。
NEON單元可以查看相同的寄存器組:
- 16個128位四字寄存器,Q0-Q15
- 32個64位雙字寄存器,D0-D31。
uint16x8_t
是一種需要128位存儲的類型,因此它需要位於quadword
寄存器中。
ARM NEON Intrinsics在ARM®C語言擴展中有一個稱為vector array data type
的定義:
...用於加載和存儲操作,表查找操作,以及返回一對向量的結果操作類型。
vzip指令
...交錯兩個向量的元素。
vzip Dd,Dm
並且具有內在的相似性
uint8x8x2_t vzip_u8 (uint8x8_t, uint8x8_t)
從這些我們可以得出結論,uint8x8x2_t實際上是兩個隨機編號雙字寄存器的列表,因為vzip指令對輸入寄存器的順序沒有任何要求。
現在答案是......
uint8x8x2_t
可以包含非連續的兩個雙字寄存器,而uint16x8_t
是由兩個連續雙字寄存器組成的數據結構,第一個具有偶數索引(D0-D31-> Q0-Q15)。
因此,您無法將具有兩個雙字寄存器的vector array data type
轉換為四字寄存器....
編譯器可能足夠聰明,可以幫助您,或者您可以強制轉換,但是我會檢查生成的程序集的正確性和性能。
您可以使用vcombine_ * intrinsics從兩個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;
}
我找到了一個解決方法:假設uint8x8x2_t
類型的val
成員是一個數組,因此它被視為一個指針。 轉換和引用指針有效! [獲取數據地址會引發“臨時”地址警告。]
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源並重建它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.