ARM NEON:vld4_f32 和 vld4q_f32 有啥区别?

Posted

技术标签:

【中文标题】ARM NEON:vld4_f32 和 vld4q_f32 有啥区别?【英文标题】:ARM NEON: What's the difference between vld4_f32 and vld4q_f32?ARM NEON:vld4_f32 和 vld4q_f32 有什么区别? 【发布时间】:2010-09-29 08:07:09 【问题描述】:

我无法区分 ARM NEON 指令中的 vld4_f32vld4q_f32

当我提高编码水平并开始查看汇编指令而不是信息量较少的内在函数时,困惑就开始了。

我需要在这里使用 vld4 变体指令的原因是,我想从每个 第 4 个位置捕获 4 float32_t's strong> 我的大数组。

vld4_f32 内部函数和相应的汇编指令如下所示 (From this link)

float32x2x4_t vld4_f32 (const float32_t *) 
Form of expected instruction(s): vld4.32 d0, d1, d2, d3, [r0]

vld4q_f32 内部函数及其对应的汇编指令如下所示

float32x4x4_t vld4q_f32 (const float32_t *) 
Form of expected instruction(s): vld4.32 d0, d1, d2, d3, [r0]

嗯,在内部函数级别我看到的区别是返回类型,但是如果我查看汇编指令和寄存器的数量,它们看起来都一样。编译器或汇编器如何知道两者之间的区别?

有人可以对此进行更多澄清并解释我如何将 4 个 float32_t 值加载到单个寄存器中,这些值位于 每 4 个内存位置 到单个寄存器中?

【问题讨论】:

【参考方案1】:

是的,我发现了不同之处。我使用 CodeSourcery 查看所有加载指令的实际寄存器内容。我发布的链接没有提供有关 vld4q_f32 的完整详细信息。

好的,首先是vld4_f32,这会加载4个d寄存器(例如d16-19)每个d寄存器是64位长,所以这条指令会加载前 8 个值以 4 的间隔交错,如下图所示。

在第二种情况下vld4q_f32,这将加载 8 d 寄存器(例如 d16-23)而不是四个。对于这个link 的读者来说,完全不清楚是否会加载 8 个寄存器。当我查看 vld4qf32 的反汇编代码时,它使用了 8 个 d 寄存器。

这条指令确实会做我希望它做的事情,即加载 4 个float32_t 值,它们的间隔为 4,如下图所示。

【讨论】:

嗯,vld4q 加载了 4 个 q 寄存器,顾名思义……【参考方案2】:

我已经反汇编了两个内在函数,也许对某人有帮助:

// C++
uint32x4x4_t r = vld4q_u32( ( uint32_t *) output );
// assembly
VLD4.32         D16,D18,D20,D22, [R0]!
VLD4.32         D17,D19,D21,D23, [R0]

// C++
uint32x2x4_t r = vld4_u32( ( uint32_t *) output );
// assembly
VLD4.32         D20-D23, [R0]

【讨论】:

以上是关于ARM NEON:vld4_f32 和 vld4q_f32 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

ARM NEON 汇编和浮点舍入

带有溢出的 ARM Neon 浮点整数转换的行为

arm_neon.h 是不是缺少所有 float16_t 类型?

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

如何使用 ARM NEON 内在函数将 u8 掩码转换为 u32 掩码?

GCC 向量扩展和 ARM NEON 的内存对齐问题