数据类型与NEON内在函数的兼容性

时间:2012-12-04 20:35:07

标签: gcc arm neon intrinsics

我正在使用来自C ++代码的NEON内在函数进行ARM优化。我理解并掌握了大部分打字问题,但我仍然坚持这一点:

指令vzip_u8返回uint8x8x2_t值(实际上是两个uint8x8_t的数组)。我想将返回的值分配给普通uint16x8_t。我认为没有适当的vreinterpretq内在实现这一点,简单的演员阵容被拒绝。

5 个答案:

答案 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源并重建它。