vpshufb

512bit 内の 128bit に含まれる8bit値16個をまぜまぜします。x86の伝統に従い、128bit 境界は超えられません。

GCC 4.9 では _mm512_shuffle_epi8 が無かったので asm 書きました。

trunk にはあるので、5.0では使えると予想されます。
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/avx512bwintrin.h#L1598


```cpp
#include <immintrin.h>
#include <stdio.h>

unsigned char in[64];
unsigned char table[64];
unsigned char out[64];

static void
test(int idx)
{
    for (int i=0; i<64; i++) {
        in[i] = 100+i;
        table[i] = idx;
    }

    __m512i vtable = _mm512_loadu_si512(table);
    __m512i vin = _mm512_loadu_si512(in);

    __m512i v;

    __asm__ __volatile__("vpshufb %[src1], %[src2], %[dest]\n\t"
                         :[dest]"=v"(v)
                         :[src1]"v"(vtable),
                          [src2]"v"(vin));

    _mm512_storeu_si512(out, v);

    for (int i=0; i<64; i++) {
        printf("idx=%2d,out[%d]=%d\n",
               idx, i, out[i]);
    }
}

int
main()
{
    test(0);

    test(17);

    test(8);
}
```


```
 $ ./sde -- ./a.out
idx= 0,out[0]=100
idx= 0,out[1]=100
idx= 0,out[2]=100
idx= 0,out[3]=100
idx= 0,out[4]=100
idx= 0,out[5]=100
idx= 0,out[6]=100
idx= 0,out[7]=100
idx= 0,out[8]=100
idx= 0,out[9]=100
idx= 0,out[10]=100
idx= 0,out[11]=100
idx= 0,out[12]=100
idx= 0,out[13]=100
idx= 0,out[14]=100
idx= 0,out[15]=100
idx= 0,out[16]=116
idx= 0,out[17]=116
idx= 0,out[18]=116
idx= 0,out[19]=116
idx= 0,out[20]=116
idx= 0,out[21]=116
idx= 0,out[22]=116
idx= 0,out[23]=116
idx= 0,out[24]=116
idx= 0,out[25]=116
idx= 0,out[26]=116
idx= 0,out[27]=116
idx= 0,out[28]=116
idx= 0,out[29]=116
idx= 0,out[30]=116
idx= 0,out[31]=116
idx= 0,out[32]=132
idx= 0,out[33]=132
idx= 0,out[34]=132
idx= 0,out[35]=132
idx= 0,out[36]=132
idx= 0,out[37]=132
idx= 0,out[38]=132
idx= 0,out[39]=132
idx= 0,out[40]=132
idx= 0,out[41]=132
idx= 0,out[42]=132
idx= 0,out[43]=132
idx= 0,out[44]=132
idx= 0,out[45]=132
idx= 0,out[46]=132
idx= 0,out[47]=132
idx= 0,out[48]=148
idx= 0,out[49]=148
idx= 0,out[50]=148
idx= 0,out[51]=148
idx= 0,out[52]=148
idx= 0,out[53]=148
idx= 0,out[54]=148
idx= 0,out[55]=148
idx= 0,out[56]=148
idx= 0,out[57]=148
idx= 0,out[58]=148
idx= 0,out[59]=148
idx= 0,out[60]=148
idx= 0,out[61]=148
idx= 0,out[62]=148
idx= 0,out[63]=148
idx=17,out[0]=101
idx=17,out[1]=101
idx=17,out[2]=101
idx=17,out[3]=101
idx=17,out[4]=101
idx=17,out[5]=101
idx=17,out[6]=101
idx=17,out[7]=101
idx=17,out[8]=101
idx=17,out[9]=101
idx=17,out[10]=101
idx=17,out[11]=101
idx=17,out[12]=101
idx=17,out[13]=101
idx=17,out[14]=101
idx=17,out[15]=101
idx=17,out[16]=117
idx=17,out[17]=117
idx=17,out[18]=117
idx=17,out[19]=117
idx=17,out[20]=117
idx=17,out[21]=117
idx=17,out[22]=117
idx=17,out[23]=117
idx=17,out[24]=117
idx=17,out[25]=117
idx=17,out[26]=117
idx=17,out[27]=117
idx=17,out[28]=117
idx=17,out[29]=117
idx=17,out[30]=117
idx=17,out[31]=117
idx=17,out[32]=133
idx=17,out[33]=133
idx=17,out[34]=133
idx=17,out[35]=133
idx=17,out[36]=133
idx=17,out[37]=133
idx=17,out[38]=133
idx=17,out[39]=133
idx=17,out[40]=133
idx=17,out[41]=133
idx=17,out[42]=133
idx=17,out[43]=133
idx=17,out[44]=133
idx=17,out[45]=133
idx=17,out[46]=133
idx=17,out[47]=133
idx=17,out[48]=149
idx=17,out[49]=149
idx=17,out[50]=149
idx=17,out[51]=149
idx=17,out[52]=149
idx=17,out[53]=149
idx=17,out[54]=149
idx=17,out[55]=149
idx=17,out[56]=149
idx=17,out[57]=149
idx=17,out[58]=149
idx=17,out[59]=149
idx=17,out[60]=149
idx=17,out[61]=149
idx=17,out[62]=149
idx=17,out[63]=149
idx= 8,out[0]=108
idx= 8,out[1]=108
idx= 8,out[2]=108
idx= 8,out[3]=108
idx= 8,out[4]=108
idx= 8,out[5]=108
idx= 8,out[6]=108
idx= 8,out[7]=108
idx= 8,out[8]=108
idx= 8,out[9]=108
idx= 8,out[10]=108
idx= 8,out[11]=108
idx= 8,out[12]=108
idx= 8,out[13]=108
idx= 8,out[14]=108
idx= 8,out[15]=108
idx= 8,out[16]=124
idx= 8,out[17]=124
idx= 8,out[18]=124
idx= 8,out[19]=124
idx= 8,out[20]=124
idx= 8,out[21]=124
idx= 8,out[22]=124
idx= 8,out[23]=124
idx= 8,out[24]=124
idx= 8,out[25]=124
idx= 8,out[26]=124
idx= 8,out[27]=124
idx= 8,out[28]=124
idx= 8,out[29]=124
idx= 8,out[30]=124
idx= 8,out[31]=124
idx= 8,out[32]=140
idx= 8,out[33]=140
idx= 8,out[34]=140
idx= 8,out[35]=140
idx= 8,out[36]=140
idx= 8,out[37]=140
idx= 8,out[38]=140
idx= 8,out[39]=140
idx= 8,out[40]=140
idx= 8,out[41]=140
idx= 8,out[42]=140
idx= 8,out[43]=140
idx= 8,out[44]=140
idx= 8,out[45]=140
idx= 8,out[46]=140
idx= 8,out[47]=140
idx= 8,out[48]=156
idx= 8,out[49]=156
idx= 8,out[50]=156
idx= 8,out[51]=156
idx= 8,out[52]=156
idx= 8,out[53]=156
idx= 8,out[54]=156
idx= 8,out[55]=156
idx= 8,out[56]=156
idx= 8,out[57]=156
idx= 8,out[58]=156
idx= 8,out[59]=156
idx= 8,out[60]=156
idx= 8,out[61]=156
idx= 8,out[62]=156
idx= 8,out[63]=156
```

https://software.intel.com/sites/landingpage/IntrinsicsGuide/ に書いてある疑似コードと挙動合わない気が…？

```
FOR j := 0 to 63
    i := j*8
    IF b[i+7] == 1
        dst[i+7:i] := 0
    ELSE
        index[3:0] := b[i+3:i]
        dst[i+7:i] := a[index*8+7:index*8]
    FI
ENDFOR dst[MAX:512] := 0
```

https://software.intel.com/en-us/intel-isa-extensions に書いてある疑似コードは…意味がよくわからなかった。



それはともかく、GCC 4.9では対応されてない理由が、これがAVX512BWという後から発表された別の拡張になっているからですね。

なお、このAVX512BW拡張はKNL(XeonPhi) では使えません。

```
 $ ./sde -knl -- ./a.out 
TID 0 SDE-ERROR: Executed instruction not valid for specified chip (KNL): 0x4005e5: vpshufb zmm0, zmm1, zmm0
Image: /home/w0/test/avx512/a.out+0x5e5
Function: test
Instruction bytes are: 62 f2 75 48 00 c0 
```

世界は悲しみの炎に包まれた。


明日は @tanakmura が vshufps について書きます。