如何在 ARMv7 NEON 向量之间移动单字数据

Posted

技术标签:

【中文标题】如何在 ARMv7 NEON 向量之间移动单字数据【英文标题】:How to move single-word data between ARMv7 NEON vectors 【发布时间】:2018-05-23 18:16:56 【问题描述】:

我正在尝试使用 ARMv7 NEON 矢量化来开发汇编代码。在某些时候,我需要将一个 32 位值(单字)从一个 NEON 向量复制到另一个向量,例如 mov dm[0], dn[1]。当我查看手册时,我找不到任何可以执行此逻辑的 movvmov 操作,因为它们需要在源或目标中有 ARM 寄存器 r。有什么想法或替代方案吗?

【问题讨论】:

@PaulR 他的意思是移动 32 位字而不是整个寄存器。 ARM NEON 在vtbl/vtbx 中有一个非常灵活的可变字节改组工具。 @EOF vtbl 具有非常长的延迟,并且它会占用一个寄存器。 IMO 不是一个非常明智的解决方案。 @Jake'Alquimista'LEE 是的,但正如我所说,这是一个一般洗牌。如果问题是“如何移动......”,那么vtbl/vtbx 是一个有效的答案。如果问题是“如何优化这个特定的洗牌”,它可能不会。 @EOF 这不是关于优化,而是关于可行性。你不应该简单地建议vtbl而不告诉副作用。 【参考方案1】:

如果你愿意:

1) 移动 d0[0], d1[0]

vext d0, d0, d1, #4
vrev64.32 d0, d0

2) 移动 d0[0], d1[1]

vtrn.32 d1, d0

3) 移动 d0[1], d1[0]

vtrn.32 d0, d1

4) 移动 d0[1], d1[1]

vext d0, d1, d0, #4
vrev64.32 d0, d0

请注意,d1 在 2) 和 3) 的情况下会损坏。为了避免这种情况,您应该将d1 复制到临时寄存器d2 并改用它。

【讨论】:

【参考方案2】:

在 32 位模式下(ARMv7 及更早版本,而非 ARMv8),每个 Q 寄存器别名 2 个d 寄存器/4 个s 寄存器。例如q1d2..3s4..7。您可以单独复制它们。

我不确定在任何 ARM uarches 上写入 s 寄存器然后读取包含的 q 寄存器是否存在合并惩罚。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0002a/ch01s03s02.html 有一个寄存器映射:只有 q0..q7 有 s-寄存器别名。 q8..q15 只有d 寄存器组件。 (即只有 32 个 s 寄存器、32 个 d 寄存器和 16 个 q 寄存器,因此 d16..31 没有可单独寻址的子组件,q8..15 只有 64 位双字元素单独暴露)。

如果没有更好的方法来执行此操作,请将需要切片和切块的向量保留在低 8 个q 寄存器中。


ARMv8 (AArch64) 引入了可以索引到向量寄存器的指令,因为 s3q3 的低位字:重叠/打包已更改。

【讨论】:

以上是关于如何在 ARMv7 NEON 向量之间移动单字数据的主要内容,如果未能解决你的问题,请参考以下文章

在 ARMv7a 上与 Neon 进行 64 位签名比较支持 CMGT 的最有效方法是啥?

Rust 移动开发与跨平台模式探究

Android neon加速优化

性能优化篇:NEON快速入门指南

在 ARMv8 环境中使用向量寄存器 (NEON) 的集合时,双精度不适用

如何使用 arm neon 8bit 乘加和到 32 位向量?