ARM NEON:vld4_f32和vld4q_f32有什么区别?

5
我不能区分ARM NEON指令中的vld4_f32vld4q_f32之间的差异。当我提高编码水平并开始查看汇编指令而不是信息较少的内部函数时,混淆开始了。我需要在这里使用vld4变体指令的原因是,我想从我的大型数组的每个第四个位置捕获4float32_t

alt text

< p > vld4_f32 内置函数和相应的汇编指令如下所示(来自此链接

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值加载到一个单独的寄存器中?
2个回答

6

是的,我找到了区别。我使用CodeSourcery查看了所有加载指令的实际寄存器内容。我发布的链接没有提供关于vld4q_f32的完整细节。

首先是 vld4_f32,它加载了4个 d 寄存器(例如d16-19),每个d寄存器长64位,因此该指令将交错地加载前8个值,间隔为4,如下图所示。 alt text

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

这个指令确实会做我希望它做的事情,即加载4个float32_t值,这些值在图像下方显示的间隔为4。

1
好的,vld4q 加载 4 个 q 寄存器,正如其名称所示... - jcayzac

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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接