AVX/AVX2による整数比較命令

# はじめに
整数比較命令について説明します．

整数に対する比較命令で，同一(==)であるか比較するeq命令と，大きい（>）かを比較するgt命令があります．
なお，すべてepiに対する比較命令です．
符号付き整数であるepuに対する比較命令は，AVX512からサポートされています．

## _mm256_cmpgt_epi8|16|32 (AVX2)
```cpp
__m256i _mm256_cmpgt_epi8 (__m256i a, __m256i b)
__m256i _mm256_cmpgt_epi16 (__m256i a, __m256i b)
__m256i _mm256_cmpgt_epi32 (__m256i a, __m256i b)
Instruction: vpcmpgtd ymm, ymm, ymm //epi8
Instruction: vpcmpgtw ymm, ymm, ymm //epi16
Instruction: vpcmpgtd ymm, ymm, ymm //epi32
```

| Architecture | Latency | Throughput |Uops |
|--------------|:-------:|:----------:|:---:|
| Alderlake    |    1    |    0.5     |  -  |
| Icelake      |    1    |    0.5     |  1  |
| Skylake      |    1    |    0.5     |  1  |
| Broadwell    |    1    |    0.5     |  1  |
| Haswell      |    1    |    0.5     |  1  |
| Zen3         |    1    | 0.25(0.5)  |  1  |
| Zen2         |    1    | 0.33(0.5)  |  1  |
| Zen          |    1    | 0.67(1)    |  2  |

* Zenの()はメモリから呼び出すときのスループットで，遅くなります
* epi64に対する命令を分けています

cmpgt same same (全て同じレジスタを指定)する場合

| Architecture | Latency | Throughput |Uops |
|--------------|:-------:|:----------:|:---:|
| Alderlake    |   0.2   |    0.02    |  -  |
| Icelake      |   0.2   |    0.22    |  1  |
| Skylake      |   0.2   |    0.25    |  1  |
| Broadwell    |   0.3   |    0.25    |  1  |
| Haswell      |   0.3   |    0.25    |  1  |
| Zen3         |   0.2   |    0.02    |  1  |
| Zen2         |   0.3   |    0.25    |  1  |
| Zen          |   0.6   |    0.5     |  2  |

* 比較の引数が同じ場合は動作が速いです．全て0が出力されます．
* 誤差等を無視すればxor same sameとほぼ同じ速度と動作です．

**説明**  
8/16/32ビット整数に対する大なりの比較命令です．

```cpp
dst[i+7:i] := ( a[i+7:i] > b[i+7:i] ) ? 0xFF : 0
dst[i+15:i] := ( a[i+15:i] > b[i+15:i] ) ? 0xFFFF : 0
dst[i+31:i] := ( a[i+31:i] > b[i+31:i] ) ? 0xFFFFFFFF : 0
```

## _mm256_cmpgt_epi64
```cpp
__m256i _mm256_cmpgt_epi64 (__m256i a, __m256i b)
Instruction: vpcmpgtq ymm, ymm, ymm
```

| Architecture | Latency | Throughput |Uops |
|--------------|:-------:|:----------:|:---:|
| Alderlake    |    3    |     1      |  -  |
| Icelake      |    3    |     1      |  1  |
| Skylake      |    3    |     1      |  1  |
| Broadwell    |    5    |     1      |  1  |
| Haswell      |    5    |     1      |  1  |
| Zen3         |    1    | 0.25(0.5)  |  1  |
| Zen2         |    1    |     1      |  1  |
| Zen          |    2    |     2      |  2  |

* IntelのCPUは，これだけP5のポートを使うため遅いです．他の命令はP0，P1ポートを使います．
* AMDのCPUも，使えるポートが通常より少ない（Zen3だけ同じに）

**説明**  
64ビット整数に対する大なりの比較命令です．

```cpp
dst[i+63:i] := ( a[i+63:i] > b[i+63:i] ) ? 0xFFFFFFFFFFFFFFFF : 0
```

## _mm256_cmpeq_epi8|16|32
```cpp
__m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
__m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
__m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
Instruction: vpcmpeqb ymm, ymm, ymm //epi8
Instruction: vpcmpeqw ymm, ymm, ymm //epi16
Instruction: vpcmpeqd ymm, ymm, ymm //epi32
```

| Architecture | Latency | Throughput |Uops |
|--------------|:-------:|:----------:|:---:|
| Alderlake    |    1    |    0.5     |  -  |
| Icelake      |    1    |    0.5     |  1  |
| Skylake      |    1    |    0.5     |  1  |
| Broadwell    |    1    |    0.5     |  1  |
| Haswell      |    1    |    0.5     |  1  |
| Zen3         |    1    | 0.25(0.5)  |  1  |
| Zen2         |    1    | 0.33(0.5)  |  1  |
| Zen          |    1    | 0.67(1)    |  2  |

eq same same（全てのビットを1にする命令）

| Architecture | Latency | Throughput |Uops |
|--------------|:-------:|:----------:|:---:|
| Alderlake    |   0.2   |     0.5    |  -  |
| Icelake      |   0.2   |     0.5    |  1  |
| Skylake      |   0.5   |     0.5    |  1  |
| Broadwell    |   0.5   |     0.5    |  1  |
| Haswell      |   0.5   |     0.5    |  1  |
| Zen3         |   0.2   |    0.24    |  1  |
| Zen2         |   0.3   |    0.33    |  1  |
| Zen          |   0.7   |    0.66    |  2  |

* 普通のgtより高速です．
* eq same sameよりかは遅いです．

**説明**  

8/16/32ビット整数に対する同一比較命令です．

```cpp
dst[i+7:i] := ( a[i+7:i] == b[i+7:i] ) ? 0xFF : 0
dst[i+15:i] := ( a[i+15:i] == b[i+15:i] ) ? 0xFFFF : 0
dst[i+31:i] := ( a[i+31:i] > b[i+31:i] ) ? 0xFFFFFFFF : 0
```

## _mm256_cmpeq_epi64

```cpp
__m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
Instruction: vpcmpeqq ymm, ymm, ymm
```

| Architecture | Latency | Throughput |Uops |
|--------------|:-------:|:----------:|:---:|
| Alderlake    |    1    |    0.5     |  -  |
| Icelake      |    1    |    0.5     |  1  |
| Skylake      |    1    |    0.5     |  1  |
| Broadwell    |    1    |    0.5     |  1  |
| Haswell      |    1    |    0.5     |  1  |
| Zen3         |    1    |    0.5     |  1  |
| Zen2         |    1    |    0.5     |  1  |
| Zen          |    1    |     1      |  2  |

* epi64に対する命令は遅いです．

**説明**  
64ビット整数に対する同一比較命令です．

```cpp
dst[i+63:i] := ( a[i+63:i] == b[i+63:i] ) ? 0xFFFFFFFFFFFFFFFF : 0
```