是否有用于 16 字节宽 VTBL 的 Armv8-A 内在函数?

Is there an Armv8-A intrinsic for 16-byte wide VTBL?

根据我经常使用的来源 Searchable Neon Arm Intrinsic Guide, 只有这些(四个 类 个)内在函数用于查找 table 和 8 字节目标寄存器(为简洁起见省略了 uint8x8 和 poly8x8_t 变体)。

int8x8_t vtbl1_s8 (int8x8_t a, int8x8_t b)
int8x8_t vtbl2_s8 (int8x8x2_t a, int8x8_t b)
int8x8_t vtbl3_s8 (int8x8x3_t a, int8x8_t b)
int8x8_t vtbl4_s8 (int8x8x4_t a, int8x8_t b)

令我惊讶的是我的源代码

uint8x16_t oddeven(uint8x16_t a) {
    auto l = vget_low_u8(a);
    auto h = vget_high_u8(a);
    auto lh = vuzp_u8(l,h);
    return vcombine_u8(lh.val[0], lh.val[1]);
}

为 odd/even 交织 16 字节向量生成了这个几乎单一的指令代码:

adrp    x8, .LCPI0_0
ldr     q1, [x8, :lo12:.LCPI0_0]
tbl     v0.16b, { v0.16b }, v1.16b
ret

就是这样,tbl v0.16.b, { } 变体显然在一条指令中对原始数据执行完整的 16->16 排列。这是(未)记录的,还是可以用内在函数生成的?

See full code and listing in Godbolt.org

不,即使 aarch64 上的 tbl 指令接受 16 字节排列,也没有内在函数。

您可以在内在指南中找到它,方法是搜索 tbl(指令助记符),然后搜索 "search within page" 搜索 16,直到找到某些 uint8x16_t 版本从中找到它们的内在命名方案。 uint8x16_t vqtbl1q_u8 (uint8x16_t t, uint8x16_t idx)

(感谢@RossRidge 首先指出了正确的名称;这个答案的重点是建议一种基于已知指令助记符查找内在函数的方法。它更适用于英特尔的 x86 内在查找器,其中元素大小是助记符的一部分,因此搜索 asm 助记符通常会缩小内在结果列表的范围,足以进行视觉扫描。)