C 如何使用neon内在特性在通道中添加所有int32元素

C 如何使用neon内在特性在通道中添加所有int32元素,c,arm,llvm,simd,neon,C,Arm,Llvm,Simd,Neon,以下是我在通道中添加所有int16x4元素的代码: #include <arm_neon.h> ... int16x4_t acc = vdup_n_s16(1); int32x2_t acc1; int64x1_t acc2; int32_t sum; acc1 = vpaddl_s16(acc); acc2 = vpaddl_s32(acc1); sum = (int)vget_lane_s64(acc2, 0); printf("%d\n", sum);// 4 #包括基于L

以下是我在通道中添加所有int16x4元素的代码:

#include <arm_neon.h>
...
int16x4_t acc = vdup_n_s16(1);
int32x2_t acc1;
int64x1_t acc2;
int32_t sum;
acc1 = vpaddl_s16(acc);
acc2 = vpaddl_s32(acc1);
sum = (int)vget_lane_s64(acc2, 0);
printf("%d\n", sum);// 4
#包括基于LLVM编译器基础结构的交叉编译器来编译它


我在stackoverflow上看到了类似的问题(),但是内在的
addv
在我的主机上不起作用。

如果您只想要一个32位的结果,可能中间溢出不太可能,或者您根本不关心它,在这种情况下,您可以一直保持32位:

int32x2_t temp = vadd_s32(vget_high_s32(accl), vget_low_s32(accl));
int32x2_t temp2 = vpadd_s32(temp, temp);
int32_t sum1 = vget_lane_s32(temp2, 0);
然而,使用64位累加实际上并不麻烦,而且也可以在不退出NEON的情况下完成—它只是一种不同的操作顺序:

int64x2_t temp = vpaddlq_s32(accl);
int64x1_t temp2 = vadd_s64(vget_high_s64(temp), vget_low_s64(temp));
int32_t sum1 = vget_lane_s32(temp2, 0);
这两种方法都可以归结为3条霓虹灯指令,没有标量运算。32位ARM的关键技巧是,Q寄存器两半的两两相加只是两个D寄存器的正常相加-这不适用于SIMD寄存器布局不同的AArch64,但AArch64仍然具有上述水平
addv


现在,这些在LLVM IR中看起来有多可怕我不知道-我想这取决于它如何在内部处理向量类型和操作-但就最终的ARM机器代码而言,两者都可以被认为是最佳的。

为什么您觉得您的代码看起来效率低下?我没有看到复杂的循环或分支。只是循序渐进。除了效率,还有什么问题是你想要解决的吗?i、 e.代码是否执行了它应该执行的操作?因为LLVM汇编代码在编译后很复杂,所以我想知道是否有更简单的方法来执行此操作,例如neon内在。我的目标问题是通过一个过程自动生成LLVM-IR,如果LLVM-IR代码复杂,对我来说很困难。您的答案很有帮助!在我的LLVM IR中有
shufflevector
指令,而不是类型转换指令,例如
trunc
sext
。谢谢!
int64x2_t temp = vpaddlq_s32(accl);
int64x1_t temp2 = vadd_s64(vget_high_s64(temp), vget_low_s64(temp));
int32_t sum1 = vget_lane_s32(temp2, 0);