问题描述
我有这个(和类似的)代码片段,我希望在其中发出 umull2 或 pmull2 指令。编译器 clang-11.0.1,选项 -O3 -std=c++11 -target aarch64
#include "stdint.h"
#include "arm_neon.h"
inline poly16x8_t vmull_low_p8(poly8x16_t a,poly8x16_t b) {
return vmull_p8(vget_low_p8(a),vget_low_p8(b));
}
// evaluates polynomials of length `len > 0` using Horner's method
// for 16 points `x`,`X = x 2^m mod n`
poly16x8x2_t p(const uint8_t *input,int len,poly8x16_t x,poly8x16_t X) {
auto ptr = input + len;
auto L = vdupq_n_p16(*--ptr),H = L;
while (ptr > input) {
auto s = vuzpq_p8(vreinterpretq_p8_p16(L),vreinterpretq_p8_p16(H));
auto a = vmull_low_p8(s.val[0],x);
auto b = vmull_high_p8(s.val[0],x);
auto A = vmull_low_p8(s.val[1],X);
auto B = vmull_high_p8(s.val[1],X);
auto C = vdupq_n_p16(*--ptr);
L = C ^ a ^ A;
H = C ^ b ^ B;
}
return {L,H};
}
而不是像这样的代码
ldrb w9,[x8,#-1]!
uzp1 v6.16b,v2.16b,v3.16b
uzp2 v2.16b,v3.16b
pmull v3.8h,v6.8b,v0.8b
pmull2 v7.8h,v0.8b
pmull v6.8h,v4.8b
pmull2 v2.8h,v2.8b,v4.8b
编译器选择了
ldrb w9,v0.8b
ext v6.16b,v6.16b,#8 // aligns top 8 bytes over bottom 8 bytes
pmull v7.8h,v1.8b // uses a copy of v0.8 also shifted by 8 bytes
ext v2.16b,#8
pmull v6.8h,v4.8b
pmull v2.8h,v5.8b
处理 uint8x16_t 或 uint16x8_t 无关紧要——这似乎是 clang 避免访问寄存器的最高位的反复出现的主题。我还没有找到一种 -mtune=cortex-73
类型的选项来强制生成不同的代码,所以我至少可以评估这是否通常性能较低(我希望它在小内核上)。 ARM64 gcc 按预期工作。
如果已知 ext
指令与 pmull
双重发出,而两个 pmull
则不会,这可能无关紧要(除了明智的大小和分配较少的寄存器)。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)