4

我正在使用 C++ 代码中的 NEON 内在函数进行 ARM 优化。我理解并掌握了大多数打字问题,但我被困在这个问题上:

该指令vzip_u8返回一个uint8x8x2_t值(实际上是一个由两个组成的数组uint8x8_t)。我想将返回的值分配给一个普通的uint16x8_t. 我认为没有适当vreinterpretq的内在实现这一目标,并且拒绝了简单的演员表。

4

5 回答 5

6

一些定义要清楚地回答......

NEON有 32 个寄存器,64 位宽(双视图为 16 个寄存器,128 位宽)。

NEON 单元可以查看相同的寄存器组:

  • 十六个 128 位四字寄存器,Q0-Q15
  • 三十二个 64 位双字寄存器,D0-D31。

uint16x8_t是一种需要 128 位存储的类型,因此它需要在quadword寄存器中。

ARM NEON Intrinsics 有一个vector array data typeARM® C 语言扩展中调用的定义:

...用于加载和存储操作、表查找操作以及作为返回一对向量的操作的结果类型。

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两个双字寄存器转换为四字寄存器......很容易。

编译器可能足够聪明,可以帮助您,或者您可以强制转换,但是我会检查生成的程序集的正确性和性能。

于 2012-12-06T00:07:54.723 回答
4

您可以使用 vcombine_* 内在函数从两个 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;
}
于 2014-09-22T21:34:04.270 回答
1

我找到了一种解决方法:鉴于该类型的val成员uint8x8x2_t是一个数组,因此它被视为一个指针。铸造和遵守指针的作品![而获取数据地址会引发“临时地址”警告。]

uint16x8_t Value= *(uint16x8_t*)vzip_u8(arg0, arg1).val;

事实证明,这可以按应有的方式编译和执行(至少在我尝试过的情况下)。我没有看过汇编代码,所以我不能授予它正确实现(我的意思是将值保存在寄存器中而不是写入/读取到/从内存中。)

于 2012-12-05T07:25:13.400 回答
0

我遇到了同样的问题,所以我引入了一个灵活的数据类型

因此,我现在可以定义以下内容:

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.
于 2015-03-24T10:04:28.720 回答
-1

它是 4.5 和 4.6 系列的 GCC(现已修复)中的一个错误。

Bugzilla 链接http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48252

请从此错误中修复并应用到 gcc 源并重建它。

于 2013-09-04T16:25:22.763 回答