Q寄存器的两个子部分之和的NEON固有

Posted

技术标签:

【中文标题】Q寄存器的两个子部分之和的NEON固有【英文标题】:NEON intrinsic for sum of two subparts of a Q register 【发布时间】:2018-03-27 11:04:35 【问题描述】:

我在 uint16x8_t(一个 Q 寄存器)中有一个值。如果是 asm,我会添加寄存器的两个子部分,例如对于 Q0,它将是 vadd_u16(d0, d1) 我需要的结果。问题是我看不到如何使用 neon 内在函数来获得它,因为没有从 uint16x8_t 到 uint16x4x2_t 的转换能够将低和高部分传递给 vadd_u16。

有很多 vreinterpret_x_y 宏,但没有一个可以从 uint16x8_t 转换为 uint16x4x2_t。我是否遗漏了什么,在 arm-neon 中应该如何进行这样的操作?

【问题讨论】:

【参考方案1】:

您可以使用vget_low and vget_high

然而,问题是编译器会把它弄得一团糟,从而导致严重的性能损失。

android Studio 中的内置 Clang 处理这些特别糟糕,GCC 版本低于 6.x 也是如此

您唯一的选择是将工具链更新为最新的,或者坚持组装。

【讨论】:

这很奇怪,这些被列为 VMOV 指令,而从 Q 寄存器引用 Dn,Dn+1 显然不需要任何操作码。我总是写 neon asm,从来没有做过任何 neon 内在函数,也不知道如何解决这个问题。 @Pavel 我注意到 GCC6.x 或更高版本可以按照您的想法处理它们,但是任何旧版本都会生成带有大量 vmov 的 FUBAR 机器代码。在 Android Studio 上的内置 Clang 上尤其糟糕。 @Pavel 我什至尝试求助于union,但情况会变得更糟。 (内存加载/存储)。这是真正的“内在”。留在你的大会上。 我做内在函数来测试/验证我的代码。似乎最新的 clang/gcc 实际上为我凌乱的内在函数生成了不错的代码。我很好奇 ms arm 或 armcc 会产生什么

以上是关于Q寄存器的两个子部分之和的NEON固有的主要内容,如果未能解决你的问题,请参考以下文章

ARM NEON 内部函数将 D(64 位)寄存器转换为 Q(128 位)寄存器的低半部分,而上半部分未定义

使用 NEON 内部函数存储非相邻 d 寄存器的最快方法

ARMv8 NEON 向量置换

Aarch64 NEON 中的 UADDL 与 UADDL2

ARM NEON 汇编和浮点舍入

ARM-NEON:基于参数的条件寄存器交换