ARM NEON 内部函数将 D(64 位)寄存器转换为 Q(128 位)寄存器的低半部分,而上半部分未定义
Posted
技术标签:
【中文标题】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 【发布时间】:2017-10-24 12:36:32 【问题描述】:我希望能够基本上能够将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 中可能存在部分依赖的不良情况,只设置一半这样的寄存器,但我宁愿编译器在这里找出最好的方法,而不是强制它使用 0 值。
有什么办法吗?
【问题讨论】:
你自己尝试了什么。有任何实验、结果、结论 - 还是什么都没有? 我上面举的两个例子? 你有没有用编程手册检查编译后的输出,看看哪种方式更有效? @PeterJ_01 哦,拜托。你不觉得你对初学者有点太苛刻了吗?大多数人甚至不知道如何打开反汇编。尤其是 android Studio 在 IDE 级别甚至没有这个选项。 @Jake 'Alquimista' LEE 这不是一个初学者的问题。我想说的很高级的问题 【参考方案1】:在aarch32
上,您完全受制于编译器。 (这就是我在汇编中编写 NEON 例程的原因)
另一方面,在 aarch64
上,它几乎是自动的,因为无论如何都不能直接访问高位 64 位。
编译器将在vcombine
上执行trn1
指令。
总而言之,aarch64
总是存在开销,而aarch32
则无法预测。如果您的 aarch32
例程简单而简短,因此不需要太多寄存器,编译器很可能巧妙地分配寄存器,但不太可能。
顺便说一句,在aarch64
,如果初始化低64位,CPU会自动将高64位设置为零。我不知道这是否需要额外的时间。这确实花了我好几天的时间,直到我发现一直以来都出了什么问题。好烦!!!
【讨论】:
感谢您的回答!对于AArch64,我想这取决于编译器是否足够聪明,可以识别出vcombine
可以被淘汰。以上是关于ARM NEON 内部函数将 D(64 位)寄存器转换为 Q(128 位)寄存器的低半部分,而上半部分未定义的主要内容,如果未能解决你的问题,请参考以下文章
对于 ARM Aarch64 的 NEON 编码,如何将寄存器推送到堆栈?似乎 STMFD 不是 Aarch64 指令集的一部分?