【问题标题】:Converting between SSE and NEON Intrinsics-Shuffling在 SSE 和 NEON Intrinsics-Shuffle 之间转换
【发布时间】:2011-12-19 05:08:47
【问题描述】:

我正在尝试将用 SSE3 内在函数编写的代码转换为 NEON SIMD,但由于 shuffle 功能而卡住了。我查看了GCC Intrinsics、ARM manuals 和其他论坛,但未能找到解决方案。

代码:

_m128i upper = _mm_loadu_si128((__m128i*)p1);

register __m128i mask1 = _mm_set_epi8 (0x80,0x80,0x80,0x80,0x80,0x80,0x80,12,0x80,10,0x80,7,0x80,4,0x80,1);
register __m128i mask2 = _mm_set_epi8 (0x80,0x80,0x80,0x80,0x80,0x80,12,0x80,10,0x80,7,0x80,4,0x80,1,0x80);
__m128i temp1_upper = _mm_or_si128(_mm_shuffle_epi8(upper,mask1),_mm_shuffle_epi8(upper,mask2));

虽然 vtbl1_u8(uint8x8_t,uint8x8_t) 指令创建了一个查找表,可用于将值分配给目标寄存器,但它仅在 64 位寄存器上运行。此外,shuffle 操作在开始时执行比较,必须在 NEON 中完成,我不知道如何有效地做到这一点。

r0 = (mask0 & 0x80) ? 0 : SELECT(a, mask0 & 0x0f) // SELECT(a,n) 从 a 中提取第 n 个 8 位参数。

r1 = (mask1 & 0x80) ? 0 : SELECT(a, mask1 & 0x0f)

...

我找不到一条指令,它首先检查掩码的高位,然后有效地选择掩码的低 4 位。我知道我们可以比较寄存器中的每个位,然后在条件为时选择低 4 位指定的,但我希望能有效地做到这一点。希望有人可以帮助或提供参考。

非常感谢,

干杯!

【问题讨论】:

    标签: sse shuffle neon intrinsics


    【解决方案1】:

    当索引超出范围时,VTBL 返回 0。

    由于它最多支持两个 Q 寄存器作为查找表,因此非常简单:

    1. 将查找表加载到 Q 寄存器(例如 Q8)
    2. vtbl.8 d0, {q8}, d0(其中 d0 包含您的掩码)

    这样就可以了。

    如果您希望位 4~6 不碍事,您可以在 vtbl 之前将它们屏蔽掉。

    不幸的是,VBIC 对 8 位立即数绝对没用。

    因此,您必须牺牲一个初始化为位掩码操作数的寄存器。

    1. vmov.u8, d1, #0x70
    2. 将查找表加载到 Q 寄存器(例如 Q8)
    3. vbic.i8 d0, d0, d1
    4. vtbl.8 d0, {q8}, d0(其中 d0 包含您的掩码)

    【讨论】:

      【解决方案2】:

      您只需要使用vtbl2_u8 两次,将输入拆分并适当地连接输出:

      #define uint8x16_to_8x8x2(v) ((uint8x8x2_t) { vget_low_u8(v), vget_high_u8(v) })
      
      uint8x16_t a = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
      uint8x16_t b = { 0x80, 0x0f, 0x01, 0x0e, 0x02, 0x0d, 0x03, 0x0c, 0x04, 0x0b, 0x05, 0x0a, 0x06, 0x09, 0x07, 0x08 };
      uint8x16_t c = vcombine_u8(vtbl2_u8(uint8x16_to_8x8x2(a), vget_low_u8(b)), vtbl2_u8(uint8x16_to_8x8x2(a), vget_high_u8(b)));
      // c = 00 ff 11 ee 22 dd 33 cc 44 bb 55 aa 66 99 77 88
      

      正如 Jake 所说,只要索引超出范围,vtbl 就会返回 0,因此您不需要对 0x80 情况进行任何特殊处理。

      【讨论】:

        猜你喜欢
        • 2016-06-25
        • 2012-07-11
        • 1970-01-01
        • 2015-12-08
        • 2022-12-27
        • 1970-01-01
        • 2017-07-03
        • 2016-09-11
        • 2012-04-07
        相关资源
        最近更新 更多