了解 Intel Intrinsics Guide 中的代码示例

Understanding a code-example from the Intel Intrinsics Guide

我正在尝试学习 _mm256_permute2f128_ps() 的功能,但无法完全理解 intel's code-example

DEFINE SELECT4(src1, src2, control) {
    CASE(control[1:0]) OF
    0:  tmp[127:0] := src1[127:0]
    1:  tmp[127:0] := src1[255:128]
    2:  tmp[127:0] := src2[127:0]
    3:  tmp[127:0] := src2[255:128]
    ESAC
    IF control[3]
        tmp[127:0] := 0
    FI
    RETURN tmp[127:0]
}
dst[127:0] := SELECT4(a[255:0], b[255:0], imm8[3:0])
dst[255:128] := SELECT4(a[255:0], b[255:0], imm8[7:4])
dst[MAX:256] := 0

具体没看懂:

在这种情况下,[x:y] 表示法总是指代数字。例如,如果您将 5 作为 imm8 参数传递,那么(因为 5==0b00000101imm8[3:0]==0b0101==5 并且如果它作为 control 传递给 SELECT4 宏,您会得到 control[3]==0==falsecontrol[1:0]==0b01==1control[2] 位将被忽略。

全面评估这个,你得到

dst[127:0]   := SELECT4(a[255:0], b[255:0], 5) == a[255:128]
dst[255:128] := SELECT4(a[255:0], b[255:0], 0) == a[127:0]

这意味着这将交换 a 寄存器的上半部分和下半部分并将其存储到 dst 寄存器中。

dst[MAX:256] := 0 仅与具有较大寄存器的架构相关(如果您有 AVX-512),即,它将位 255 以上的所有内容设置为零。这与传统的 SSE 指令形成对比,后者(如果在支持 AVX 的 CPU 上执行)会使上半部分保持不变(并产生错误的依赖关系——参见 this related question)。