如何在 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]
。当我查看手册时,我找不到任何可以执行此逻辑的 mov
或 vmov
操作,因为它们需要在源或目标中有 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
寄存器。例如q1
是 d2..3
和 s4..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) 引入了可以索引到向量寄存器的指令,因为 s3
是 q3
的低位字:重叠/打包已更改。
【讨论】:
以上是关于如何在 ARMv7 NEON 向量之间移动单字数据的主要内容,如果未能解决你的问题,请参考以下文章
在 ARMv7a 上与 Neon 进行 64 位签名比较支持 CMGT 的最有效方法是啥?