我希望能够基本上能够将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值。
有没有办法做到这一点?
答案 0 :(得分:0)
在aarch32
上,你完全处于编译器的怜悯之中。 (这就是我在装配中编写NEON例程的原因)
另一方面,在aarch64
,它几乎是自动的,因为无论如何都无法直接访问高64位。
编译器将在trn1
上执行vcombine
指令。
总结一下,aarch64
上总是存在开销,而aarch32
上却无法预测。如果你的aarch32
例程简单而且很短,那么就不需要很多寄存器,编译器很可能会巧妙地分配寄存器,但其他情况不太可能。
BTW,在aarch64
上,如果初始化低64位,CPU会自动将高64位设置为零。我不知道它是否需要额外的时间。这花费了我几天,直到我一直发现出了什么问题。太烦人了!!!