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

ARM NEON intrinsics convert D (64-bit) register to low half of Q (128-bit) register, leaving upper half undefined

我希望能够在没有开销的情况下将 uint8x8_t 类型转换为 uint8x16_t,同时保留高 64 位未定义。如果您只关心底部 64 位,但希望使用 128 位指令,这很有用,例如:

uint8x16_t data = (uint8x16_t)vld1_u8(src); // if you can somehow do this uint8x16_t shifted = vextq_u8(oldData, data, 2);

根据我对 ARM 汇编的理解,这应该是可能的,因为可以将负载发布到 D 寄存器,然后解释为 Q 寄存器。

我能想到的一些方法是:

我想 CPU 中可能存在部分依赖关系的棘手情况,只设置了一半这样的寄存器,但我宁愿编译器在这里找到最好的方法而不是强制它使用 0 值。

有什么办法吗?

aarch32 上,您完全受制于编译器。 (这就是我用汇编写NEON例程的原因)

另一方面,在 aarch64 上,它几乎是自动的,因为无论如何都不能直接访问上层 64 位。

虽然编译器会在 vcombine 上执行 trn1 指令。

总而言之,aarch64 上总是有开销,而 aarch32 上则不可预测。如果您的 aarch32 例程简单而简短,因此不需要很多寄存器,编译器很可能会巧妙地分配寄存器,否则就不太可能了。

顺便说一句,在 aarch64 上,如果您初始化低 64 位,CPU 会自动将高 64 位设置为零。我不知道这是否需要额外的时间。我确实花了好几天时间才发现一直以来出了什么问题。好烦!!!