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

时间:2017-10-24 12:36:33

标签: c arm intrinsics neon

我希望能够基本上能够将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寄存器。

我能想到的一些方法是:

  • data = vcombine_u8(vld1_u8(src), vdup_n_u8(0)); - 编译器似乎努力将上半部分设置为0,即使这是不必要的
  • data = vld1q_u8(src); - 执行128位加载(在我的情况下很好),但在具有64位NEON单元的处理器上可能会更慢?

我想在CPU中可能存在一个部分依赖的icky case,只设置了这样的寄存器的一半,但我宁愿编译器在这里找出最好的方法,而不是强迫它使用0值。

有没有办法做到这一点?

1 个答案:

答案 0 :(得分:0)

aarch32上,你完全处于编译器的怜悯之中。 (这就是我在装配中编写NEON例程的原因)

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

编译器将在trn1上执行vcombine指令。

总结一下,aarch64上总是存在开销,而aarch32上却无法预测。如果你的aarch32例程简单而且很短,那么就不需要很多寄存器,编译器很可能会巧妙地分配寄存器,但其他情况不太可能。

BTW,在aarch64上,如果初始化低64位,CPU会自动将高64位设置为零。我不知道它是否需要额外的时间。这花费了我几天,直到我一直发现出了什么问题。太烦人了!!!