我正在使用来自C ++代码的NEON内在函数进行ARM优化。我理解并掌握了大部分打字问题,但我仍然坚持这一点:
指令vzip_u8
返回uint8x8x2_t
值(实际上是两个uint8x8_t
的数组)。我想将返回的值分配给普通uint16x8_t
。我认为没有适当的vreinterpretq
内在实现这一点,简单的演员阵容被拒绝。
答案 0 :(得分:5)
一些定义要清楚地回答......
NEON有32个寄存器,64位宽(双视图为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指令
...交错两个向量的元素。
vzip Dd,Dm
并且有intrinsic之类的
uint8x8x2_t vzip_u8 (uint8x8_t, uint8x8_t)
从这些我们可以得出结论,uint8x8x2_t实际上是两个随机编号双字寄存器的列表,因为vzip指令对输入寄存器的顺序没有任何要求。
现在答案是......
uint8x8x2_t
可包含非连续的两个双字寄存器,而uint16x8_t
是由两个连续双字寄存器组成的数据结构,其中第一个具有偶数索引(D0-D31-> Q0-Q15)
因此,您不能轻易地将vector array data type
两个双字寄存器转换为四字寄存器。
编译器可能足够聪明,可以帮助您,或者您可以强行转换,但我会检查生成的程序集的正确性和性能。
答案 1 :(得分:4)
您可以使用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;
}
答案 2 :(得分:1)
我找到了一个解决方法:假设val
类型的uint8x8x2_t
成员是一个数组,因此它被视为一个指针。转换和引用指针有效! [采用数据地址会引发“临时”地址警告。]
uint16x8_t Value= *(uint16x8_t*)vzip_u8(arg0, arg1).val;
事实证明,这应该编译并执行(至少在我尝试过的情况下)。我没有看过汇编代码所以我不能授予它正确实现(我的意思是只是将值保存在寄存器中而不是写入/读取到内存中。)
答案 3 :(得分:0)
我遇到了同样的问题,所以我介绍了a flexible data type。
我现在可以定义以下内容:
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 :(得分:-1)
它是4.5和4.6系列中GCC(现已修复)的一个错误。
Bugzilla链接http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48252
请从此错误中获取修复并应用于gcc源并重建它。