2016-11-30 68 views
1

這是我在車道將所有int16x4元素代碼,添加所有INT32元素車道:如何使用NEON內在

#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 

我嘗試添加所有int32x4元素車道。

,但我的代碼看起來效率低下:

#include <arm_neon.h> 
... 
int32x4_t accl = vdupq_n_s32(1); 
int64x2_t accl_1; 
int64_t temp; 
int64_t temp2; 
int32_t sum1; 
accl_1=vpaddlq_s32(accl); 
temp = (int)vgetq_lane_s64(accl_1,0); 
temp2 = (int)vgetq_lane_s64(accl_1,1); 
sum1=temp+temp2; 
printf("%d\n", sum);// 4 

是否有簡單明瞭的方式來做到這一點?我希望編譯後的LLVM彙編代碼簡單明瞭。我也希望sum的最終類型是32位。

我用ellcc交叉編譯器基於LLVM編譯器的基礎架構來編譯它。

我在stackoverflow上看到了類似的問題(Add all elements in a lane),但內部的addv在我的主機上不起作用。

+0

你爲什麼覺得你的代碼看起來效率低下?我沒有看到複雜的循環或分支。只是順序。除了您想要解決的效率之外,還有其他問題嗎?即代碼是做它應該做的事情? – ryyker

+0

由於LLVM彙編代碼在編譯後很複雜,所以我想知道是否有更簡單的方法來完成此操作,如霓虹燈內在。 – Shun

+0

我的目標的問題是通過pass自動生成LLVM-IR,如果LLVM-IR代碼複雜,對我來說很困難。 – Shun

回答

1

如果你只想要一個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 NEON指令和標量算術。 32位ARM的關鍵技巧是,Q寄存器的兩半成對添加僅僅是兩個D寄存器的正常添加 - 不適用於SIMD寄存器佈局不同的AArch64,但AArch64具有無論如何,前述的橫向addv

現在,在LLVM IR中看起來有多麼可怕,我不知道 - 我想這取決於它如何在內部處理向量類型和操作 - 但就最終的ARM機器代碼而言,這兩者都可以被認爲是最優的。

+0

您的回答很有幫助!在我的LLVM IR中有'shufflevector'指令,而不是類型轉換指令,如'trunc'或'sext'。非常感謝! – Shun

相關問題