Go Wiki: AVX512
Go 1.11リリースでは、AVX-512サポートが導入されました。
このページでは、新機能の使用方法と重要なエンコーダーの詳細について説明します。
用語
ほとんどの用語は、Intel Software Developer’s manualからのものです。
サフィックスは、AT&Tにも近いGoアセンブラ構文に由来しており、サイズサフィックスも使用します。
あいまいさを避けるために、いくつかの用語がリストされています(たとえば、オペコードは異なる意味を持つ場合があります)。
用語 | 説明 |
---|---|
オペランド | 「命令引数」と同じです。 |
オペコード | 命令グループを参照する名前。たとえば、VADDPD はオペコードです。VEXとEVEXの両方でエンコードされた形式とすべてのオペランドの組み合わせを指します。 AVX-512のGoアセンブラオペコードのほとんどはIntelマニュアルのエントリと一致していますが、追加のサイズサフィックスが使用される場合を除きます。 (例: VCVTTPD2DQY はVCVTTPD2DQ です)。 |
オペコードサフィックス | 一部のオペコードのプロパティをオーバーライドするサフィックス。「.」の後(ドット)にリストされます。 たとえば、 VADDPD.Z には「Z」オペコードサフィックスがあります。複数のドットで区切られたオペコードサフィックスが存在する可能性があります。 |
サイズサフィックス | オペランドだけでは推測できない場合に、命令オペランドのサイズを指定するサフィックス。 たとえば、 VCVTSS2USIL には「L」サイズサフィックスがあります。 |
オプマスク | {k1} 表記の両方と、K レジスタオペランドを持つ命令の説明に使用されます。EVEXプレフィックスのマスキングサポートに関連しています。 |
レジスタブロック | レジスタ範囲をエンコードするマルチソースオペランド。 Intelマニュアルでは、レジスタブロックに +n 表記を使用しています。たとえば、 +3 は4つのレジスタのレジスタブロックです。 |
FP | 浮動小数点 |
新しいレジスタ
EVEX対応命令は、64ビットモードでは追加の16個のX
(128ビットxmm)およびY
(256ビットymm)レジスタと32個の新しいZ
(512ビットzmm)レジスタにアクセスできます。32ビットモードではZ0-Z7
のみが取得されます。
新しいオプマスクレジスタはK0-K7
と呼ばれます。
マスキングと特殊なオプマスク命令(KADDB
など)の両方に使用できます。
マスキングサポート
マスキングをサポートする命令は、K
レジスタオペランドを省略できます。
この場合、K0
レジスタは暗黙的に使用され(「すべて1」)、マージマスキングが実行されます。
これは事実上「マスキングなし」です。
K1-K7
レジスタを使用して、デフォルトのオプマスクをオーバーライドできます。
K
レジスタは、宛先オペランドの直前に配置する必要があります。
ゼロイングマスキングは、Z
オペコードサフィックスを使用して有効にできます。ゼロイングマスキングには、K0以外のマスクレジスタを指定する必要があります。
たとえば、VADDPD.Z (AX), Z30, K3, Z10
はゼロイングマスキングと明示的なK
レジスタを使用します。
Z
オペコードサフィックスを削除すると、K3
マスクによるマージマスキングになります。K3
オペランドを削除すると、アセンブラエラーが発生します。Z
オペコードサフィックスとK3
オペランドの両方を削除すると、K0
マスクによるマージマスキングになります。
{k1}
オペランドにK0
レジスタを使用することはコンパイル時エラーです(詳細はマニュアルを参照してください)。
EVEXブロードキャスト/丸め/SAEサポート
オペコードサフィックスを介して有効化された埋め込みブロードキャスト、丸め、SAE。
{er}
が有効なreg-reg FP命令の場合、丸めオペコードサフィックスを指定できます。
RU_SAE
:+Infに向かって丸めるRD_SAE
:-Infに向かって丸めるRZ_SAE
:0に向かって丸めるRN_SAE
:最も近い値に向かって丸める
丸めモードの詳細については、MXCSR.RC情報を参照してください。
{sae}
が有効なreg-reg FP命令の場合、例外抑制をSAE
オペコードサフィックスで指定できます。
m32bcst/m64bcst
オペランドを持つreg-mem命令の場合、BCST
オペコードサフィックスを使用してブロードキャストを有効にできます。
ゼロイングオペコードサフィックスは、これらのいずれかと組み合わせることができます。
たとえば、VMAXPD.SAE.Z Z3, Z2, Z1
はZ
とSAE
の両方のオペコードサフィックスを使用します。
ゼロイングオペコードサフィックスは最後に置く必要があります。そうでない場合、コンパイルエラーになります。
レジスタブロック(マルチソース)オペランド
レジスタブロックは、レジスタ範囲構文を使用して指定されます。
最初の(低い)レジスタのみを指定すれば十分ですが、Goアセンブラでは、可読性の理由から両端を含む明示的な範囲が必要です。
たとえば、+3
範囲を持つ命令は、VP4DPWSSD Z25, [Z0-Z3], (AX)
のように使用できます。
範囲[Z0-Z3]
は、「Z0、Z1、Z2、Z3のレジスタブロック」のように読み取られます。
無効な範囲はコンパイルエラーになります。
EVEXプレフィックスを持つAVX1およびAVX2命令
EVEXプレフィックスを使用してエンコードできる以前から存在するオペコードは、より広いレジスタファイル、ゼロイング/マージマスキングなど、AVX-512機能にアクセスできるようになりました。たとえば、VADDPD
は、512ビットベクトルレジスタを使用できるようになりました。
詳細については、「エンコーダーの詳細」を参照してください。
サポートされている拡張機能
サポートされている拡張機能の最新リストを取得する最適な方法は、テストスイートディレクトリ内でls -1
を実行することです。
最新のリストには以下が含まれています。
aes_avx512f
avx512_4fmaps
avx512_4vnniw
avx512_bitalg
avx512_ifma
avx512_vbmi
avx512_vbmi2
avx512_vnni
avx512_vpopcntdq
avx512bw
avx512cd
avx512dq
avx512er
avx512f
avx512pf
gfni_avx512f
vpclmulqdq_avx512f
128ビットおよび256ビット命令には、さらにavx512vl
が必要です。
つまり、VADDPD
がavx512f
で使用できる場合でも、avx512vl
を使用しないとX
およびY
引数は使用できません。
ファイル名はGNU as
(gas)の規則に従います。
avx512extmap.csvを使用すると、命名スキームをより明確にできます。
サイズサフィックス付きの命令
一部のオペコードはIntelマニュアルのエントリと一致しません。
このセクションは、検索の便宜のために提供されています。
Intelオペコード | Goアセンブラオペコード |
---|---|
VCVTPD2DQ |
VCVTPD2DQX 、VCVTPD2DQY |
VCVTPD2PS |
VCVTPD2PSX 、VCVTPD2PSY |
VCVTTPD2DQ |
VCVTTPD2DQX 、VCVTTPD2DQY |
VCVTQQ2PS |
VCVTQQ2PSX 、VCVTQQ2PSY |
VCVTUQQ2PS |
VCVTUQQ2PSX 、VCVTUQQ2PSY |
VCVTPD2UDQ |
VCVTPD2UDQX 、VCVTPD2UDQY |
VCVTTPD2UDQ |
VCVTTPD2UDQX 、VCVTTPD2UDQY |
VFPCLASSPD |
VFPCLASSPDX 、VFPCLASSPDY 、VFPCLASSPDZ |
VFPCLASSPS |
VFPCLASSPSX 、VFPCLASSPSY 、VFPCLASSPSZ |
VCVTSD2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTTSD2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTTSS2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTSS2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTSD2USI |
VCVTSD2USIL 、VCVTSD2USIQ |
VCVTSS2USI |
VCVTSS2USIL 、VCVTSS2USIQ |
VCVTTSD2USI |
VCVTTSD2USIL 、VCVTTSD2USIQ |
VCVTTSS2USI |
VCVTTSS2USIL 、VCVTTSS2USIQ |
VCVTUSI2SD |
VCVTUSI2SDL 、VCVTUSI2SDQ |
VCVTUSI2SS |
VCVTUSI2SSL 、VCVTUSI2SSQ |
VCVTSI2SD |
VCVTSI2SDL 、VCVTSI2SDQ |
VCVTSI2SS |
VCVTSI2SSL 、VCVTSI2SSQ |
ANDN |
ANDNL 、ANDNQ |
BEXTR |
BEXTRL 、BEXTRQ |
BLSI |
BLSIL 、BLSIQ |
BLSMSK |
BLSMSKL 、BLSMSKQ |
BLSR |
BLSRL 、BLSRQ |
BZHI |
BZHIL 、BZHIQ |
MULX |
MULXL 、MULXQ |
PDEP |
PDEPL 、PDEPQ |
PEXT |
PEXTL 、PEXTQ |
RORX |
RORXL 、RORXQ |
SARX |
SARXL 、SARXQ |
SHLX |
SHLXL 、SHLXQ |
SHRX |
SHRXL 、SHRXQ |
エンコーダーの詳細
古いエンコーダーとのビット単位の比較は、エンコーダーテーブルの順序がわずかに異なるため、VEXでエンコードされた命令では失敗する可能性があります。
この違いは、reg-regの場合に{reg, reg/mem}
と{reg/mem, reg}
の両方の形式を持つ命令(VMOVUPS
など)で発生する可能性があります。
これはコードの動作に影響を与えず、コードを大きくしたり効率を低下させたりしません。
新しいエンコーディング選択スキームは、Intel XEDから借用されています。
以下のいずれかが当てはまる場合、EVEXエンコーディングが使用されます。
- 命令が新しいレジスタ(上位16個の
X
/Y
、Z
またはK
レジスタ)を使用する。 - 命令が
BCST
などのEVEX関連のオペコードサフィックスを使用する。 - 命令がAVX-512でのみ使用可能なオペランドの組み合わせを使用する。
その他のすべてのケースでは、VEXエンコーディングが使用されます。
つまり、可能な限りVEXが使用され、必要な場合にのみEVEXが使用されます。
EVEXでエンコードされた命令では、可能な限り圧縮disp8が適用されます。
これには、場合によっては異なるN乗数を持つブロードキャストdisp8も含まれます。
経験豊富な読者は、avx_optabs.goを検査して、任意の命令のN乗数について学ぶことができます。
たとえば、VADDPD
には次のものがあります。
- 512ビット形式の場合
N=64
;ブロードキャスト時のN=8
- 256ビット形式の場合
N=32
;ブロードキャスト時のN=8
- 128ビット形式の場合
N=16
;ブロードキャスト時のN=8
例
多数の例は、Goアセンブラのテストスイートにあります。
各ファイルは、特定のAVX-512拡張機能でサポートされているすべての命令形式のいくつかの例を提供しています。
すべての例には、生成されたマシンコードも含まれています。
Intel® Optimization Manualから採用された「AVX-512CDを使用したベクトル化されたヒストグラム更新」を以下に示します。
for i := 0; i < 512; i++ {
histo[key[i]] += 1
}
top:
VMOVUPS 0x40(SP)(DX*4), Z4 //; vmovups zmm4, [rsp+rdx*4+0x40]
VPXORD Z1, Z1, Z1 //; vpxord zmm1, zmm1, zmm1
KMOVW K1, K2 //; kmovw k2, k1
VPCONFLICTD Z4, Z2 //; vpconflictd zmm2, zmm4
VPGATHERDD (AX)(Z4*4), K2, Z1 //; vpgatherdd zmm1{k2}, [rax+zmm4*4]
VPTESTMD histo<>(SB), Z2, K0 //; vptestmd k0, zmm2, [rip+0x185c]
KMOVW K0, CX //; kmovw ecx, k0
VPADDD Z0, Z1, Z3 //; vpaddd zmm3, zmm1, zmm0
TESTL CX, CX //; test ecx, ecx
JZ noConflicts //; jz noConflicts
VMOVUPS histo<>(SB), Z1 //; vmovups zmm1, [rip+0x1884]
VPTESTMD histo<>(SB), Z2, K0 //; vptestmd k0, zmm2, [rip+0x18ba]
VPLZCNTD Z2, Z5 //; vplzcntd zmm5, zmm2
XORB BX, BX //; xor bl, bl
KMOVW K0, CX //; kmovw ecx, k0
VPSUBD Z5, Z1, Z1 //; vpsubd zmm1, zmm1, zmm5
VPSUBD Z5, Z1, Z1 //; vpsubd zmm1, zmm1, zmm5
resolveConflicts:
VPBROADCASTD CX, Z5 //; vpbroadcastd zmm5, ecx
KMOVW CX, K2 //; kmovw k2, ecx
VPERMD Z3, Z1, K2, Z3 //; vpermd zmm3{k2}, zmm1, zmm3
VPADDD Z0, Z3, K2, Z3 //; vpaddd zmm3{k2}, zmm3, zmm0
VPTESTMD Z2, Z5, K2, K0 //; vptestmd k0{k2}, zmm5, zmm2
KMOVW K0, SI //; kmovw esi, k0
ANDL SI, CX //; and ecx, esi
JZ noConflicts //; jz noConflicts
ADDB $1, BX //; add bl, 0x1
CMPB BX, $16 //; cmp bl, 0x10
JB resolveConflicts //; jb resolveConflicts
noConflicts:
KMOVW K1, K2 //; kmovw k2, k1
VPSCATTERDD Z3, K2, (AX)(Z4*4) //; vpscatterdd [rax+zmm4*4]{k2}, zmm3
ADDL $16, DX //; add edx, 0x10
CMPL DX, $1024 //; cmp edx, 0x400
JB top //; jb top
このコンテンツは、Go Wikiの一部です。