我在SSE2 intrinsincs中具有以下代碼。它處理來自Kinect的輸入。將SSE2移植到ARM NEON intrinsincs
__m128i md = _mm_setr_epi16((r0<<3) | (r1>>5), ((r1<<6) | (r2>>2)), ((r2<<9) | (r3<<1) | (r4>>7)), ((r4<<4) | (r5>>4)), ((r5<<7) | (r6>>1)),((r6<<10) | (r7<<2) | (r8>>6)), ((r8<<5) | (r9>>3)), ((r9<<8) | (r10) ));
md = _mm_and_si128(md, mmask);
__m128i mz = _mm_load_si128((__m128i *) &depth_ref_z[i]);
__m128i mZ = _mm_load_si128((__m128i *) &depth_ref_Z[i]);
mz = _mm_cmpgt_epi16(md, mz);
mZ = _mm_cmpgt_epi16(mZ, md);
mz = _mm_and_si128(mz, mZ);
md = _mm_and_si128(mz, md);
_mm_store_si128((__m128i *) frame,md)
if(_mm_movemask_epi8(mz)){ ... }
這基本上解包11 uint8_t(R0-R10)至8 uint16_t在SSE寄存器(mmask指定是恆定的,先前創建的)。然後它將兩個數組中的對應元素加載兩個寄存器作爲邊界。它檢查它們並創建一個寄存器,其中的元素不符合標準清零。然後存儲它們並進一步處理每個元素。當沒有任何元素通過時,movemask可以作爲一個很好的優化,在這種情況下,處理可以被跳過。
這很好,現在我想將它移植到NEON。除了兩個部分外,大部分內容都很簡單。看看SSE2代碼中的彙編輸出(gcc),我發現它不是在_mm_setr_epi16中執行8個uint16_t移動,而是將它們轉換爲uint32_t,最後執行4個移動。這似乎是有效的,因爲編譯器照顧它,我沒有改變代碼。我是否應該在NEON情況下手動應用?而不是8 vsetq_lane_u16做轉移,並執行4 vsetq_lane_u32?我是否會遇到任何問題,是否值得?
最後一部分是movemask,因爲我還沒有找到相應的東西。任何人都可以提出建議