ビット操作命令セット(BMIセット)は、 IntelおよびAMDのマイクロプロセッサ向けのx86命令セットアーキテクチャの拡張です。これらの命令セットの目的は、ビット操作の速度を向上させることです。これらのセットに含まれるすべての命令は非SIMDであり、汎用レジスタのみを操作します。
Intelが公開した命令セットには、BMI(現在はBMI1と呼ばれる)とBMI2の2つがあります。これらはどちらもHaswellマイクロアーキテクチャで導入され、BMI1はAMDのABM命令セットが提供する機能に対応し、BMI2はそれらを拡張したものです。AMDは他に、ABM(Advanced Bit Manipulation 、 IntelがSSE4.2およびBMI1の一部として実装したSSE4aのサブセット)とTBM(Trailing Bit Manipulation 、 PiledriverベースのプロセッサでBMI1の拡張として導入されたが、Zenベースのプロセッサでは再び廃止された)の2つの命令セットを公開しました。[ 1 ]
AMDは、現在IntelのBMI1を構成する命令をABM( Advanced Bit Manipulation )命令セットの一部として初めて導入し、その後Intelの新しいBMI2命令のサポートも追加しました。AMDは現在、これらの機能の利用可能性をIntelのBMI1およびBMI2 CPUフラグを通じて宣伝し、プログラマーにこれらの機能を適切にターゲットとするよう指示しています。[ 2 ]
インテルはPOPCNTSSE4.2 の一部とLZCNTBMI1 の一部であると考えているが、インテルと AMD はどちらもこれらの 2 つの命令の存在を個別に宣伝しています。同じ名前のPOPCNT別のCPUIDフラグがあり、インテルと AMD は AMD のABMフラグを使用してサポートを示しますLZCNT( LZCNTBMI1 と BMI2 を組み合わせることで拡張 ABM 命令セットが完成するため)。[ 2 ] [ 3 ]
| エンコーディング | 命令 | 説明[ 4 ] |
|---|---|---|
F3 0F B8 /r | POPCNT | 人口数 |
F3 0F BD /r | LZCNT | 先頭のゼロの数 |
LZCNTはビットスキャンリバース(BSR)命令に関連していますが、ZF(結果がゼロの場合)フラグとCF(ソースがゼロの場合)フラグを設定するのではなく、ZF(結果がゼロの場合)フラグとCF(ソースがゼロの場合)フラグを設定します。また、ソースオペランドがゼロの場合、定義された結果(ソースオペランドのサイズ(ビット単位))を生成します。引数がゼロ以外の場合、LZCNTと のBSR合計は引数のビット幅から1を引いた値になります(例えば、32ビット引数が の場合 0x000f0000、LZCNTは12、BSRは19となります)。
のエンコードはLZCNT、ABMがサポートされていない場合は代わりに命令が実行されるというものであるBSR。[ 4 ]:227
以下の命令はBMICPUIDのビットによって有効化される命令です。Intelは公式にはLZCNTBMIの一部としていますが、 CPUID機能フラグLZCNTを使用してサポートを宣伝していますABM。[ 3 ] BMI1はAMDのJaguar、[ 5 ] Piledriver [ 6 ]以降のプロセッサ、およびIntelのHaswell [ 7 ]以降のプロセッサで利用可能です。
| エンコーディング | 命令 | 説明[ 3 ] | 同等のC式[ 8 ] [ 9 ] [ 10 ] |
|---|---|---|---|
VEX.LZ.0F38 F2 /r | ANDN | 論理的ではない | ~x & y |
VEX.LZ.0F38 F7 /r | BEXTR | ビットフィールド抽出(レジスタ付き) | (src >> start) & ((1 << len) - 1) |
VEX.LZ.0F38 F3 /3 | BLSI | 最下位セット分離ビットを抽出する | x & -x |
VEX.LZ.0F38 F3 /2 | BLSMSK | マスクを最下位セットビットまで取得する | x ^ (x - 1) |
VEX.LZ.0F38 F3 /1 | BLSR | 最下位セットビットをリセット | x & (x - 1) |
F3 0F BC /r | TZCNT | 末尾のゼロビットの数を数える | 31 + ( ! x ) - ((( x & - x ) & 0x0000FFFF ) ? 16 : 0 ) - ((( x & - x ) & 0x00FF00FF ) ? 8 : 0 ) - ((( x & - x ) & 0x0F0F0F0F ) ? 4 : 0 ) - ((( x & - x ) & 0x33333333 ) ? 2 : 0 ) - ((( x & - x ) & 0x55555555 ) ? 1 : 0 ) |
TZCNTはビットスキャンフォワード(BSF)命令とほぼ同じですが、ZF(結果がゼロの場合)フラグとCF(ソースがゼロの場合)フラグを設定するのではなく、ZF(結果がゼロの場合)フラグとCF(ソースがゼロの場合)フラグを設定します。引数がゼロ以外の場合、TZCNTとの結果はBSF等しくなります。
と同様にLZCNT、 のエンコードでTZCNTは、BMI1がサポートされていない場合はBSF代わりに 命令が実行される。[ 4 ] : 352
IntelはHaswellプロセッサシリーズにおいて、BMI1とBMI2の両方を導入しました。BMI2を搭載せずBMI1のみをサポートするプロセッサを製造しているのはAMDのみです。BMI2はAMDのExcavatorアーキテクチャ以降でサポートされています。[ 11 ]
| エンコーディング | 命令 | 説明 |
|---|---|---|
VEX.LZ.0F38 F5 /r | BZHI | 指定されたビット位置 [src & (1 << inx)-1] から始まる上位ビットをゼロにします。 |
VEX.LZ.F2.0F38 F6 /r | MULX | フラグや任意の宛先レジスタに影響を与えない符号なし乗算 |
VEX.LZ.F2.0F38 F5 /r | PDEP | 並列ビットデポジット |
VEX.LZ.F3.0F38 F5 /r | PEXT | 並列ビット抽出 |
VEX.LZ.F2.0F3A F0 /r ib | RORX | フラグに影響を与えずに論理的に右に回転する |
VEX.LZ.F3.0F38 F7 /r | SARX | フラグに影響を与えずに算術演算を右にシフトする |
VEX.LZ.F2.0F38 F7 /r | SHRX | フラグに影響を与えずに論理的に右にシフトする |
VEX.LZ.66.0F38 F7 /r | SHLX | フラグに影響を与えずに論理左シフト |
命令PDEPとPEXT命令は、新しい汎用ビットレベル圧縮および展開命令です。これらは2つの入力を取ります。1つはソース、もう1つはセレクタです。セレクタは、パックまたはアンパックするビットを選択するビットマップです。 は、 PEXTソースから選択されたビットを宛先の連続する下位ビットにコピーします。宛先の上位ビットはクリアされます。 は、 PDEP選択されたビットに対してその逆の処理を行います。連続する下位ビットは宛先の選択されたビットにコピーされます。その他の宛先ビットはクリアされます。これは、入力の任意のビットフィールドを抽出したり、以前はコストがかかったビットレベルのシャッフルを大量に実行したりするために使用できます。これらの命令の動作は、ビットレベルのギャザースキャッタSIMD命令に似ていますが、命令PDEPとPEXT命令は(他のBMI命令セットと同様に)汎用レジスタに対して動作します。[ 12 ]
命令は32ビット版と64ビット版で利用可能です。32ビットモードで任意のソースとセレクタを使用する例を以下に示します。
| 命令 | セレクタマスク | ソース | 行き先 |
|---|---|---|---|
PEXT | 0xff00fff0 | 0x12345678 | 0x00012567 |
PDEP | 0xff00fff0 | 0x00012567 | 0x12005670 |
Zen 3以前のAMDプロセッサ[ 13 ]はPDEPとPEXTをマイクロコードで実装しており、レイテンシは(Zen 3の)3サイクル[15]ではなく18サイクル[14]となっている。その結果、これらのプロセッサでは他の命令を使用する方が高速になることが多い。[ 16 ]
TBMはBMI1によって開始された命令セットを補完する命令で構成されています。補完的な性質を持つため、必ずしも直接使用する必要はなく、サポートされている場合は最適化コンパイラによって生成できます。AMDは、Piledriver [ 6 ]シリーズのプロセッサでBMI1とともにTBMを導入しました。その後のAMD JaguarおよびZenベースのプロセッサはTBMをサポートしていません。[ 5 ] Intelプロセッサは(少なくともAlder Lakeまでは)TBMをサポートしていません。
| エンコーディング | 命令 | 説明[ 4 ] | 同等のC式[ 17 ] [ 9 ] |
|---|---|---|---|
XOP.LZ.0A 10 /r id | BEXTR | ビットフィールド抽出(即値付き) | (src >> start) & ((1 << len) - 1) |
XOP.LZ.09 01 /1 | BLCFILL | 一番下のクリアビットから埋める | x & (x + 1) |
XOP.LZ.09 02 /6 | BLCI | 最も低いクリアビットを分離する | x | ~(x + 1) |
XOP.LZ.09 01 /5 | BLCIC | 最低クリアビットを分離し、補数化する | ~x & (x + 1) |
XOP.LZ.09 02 /1 | BLCMSK | 最も低いクリアビットからマスク | x ^ (x + 1) |
XOP.LZ.09 01 /3 | BLCS | 最下位のクリアビットを設定する | x | (x + 1) |
XOP.LZ.09 01 /2 | BLSFILL | 最下位の設定ビットから埋める | x | (x - 1) |
XOP.LZ.09 01 /6 | BLSIC | 最下位のセットビットを分離し、補数をとる | ~x | (x - 1) |
XOP.LZ.09 01 /7 | T1MSKC | 末尾の1からの逆マスク | ~x | (x + 1) |
XOP.LZ.09 01 /4 | TZMSK | 末尾のゼロをマスクする | ~x & (x - 1) |
命令拡張のサポートとは、プロセッサがソフトウェア互換性のためにサポートされている命令を実行できることを意味することに注意してください。プロセッサは、その場合、良好なパフォーマンスを発揮しない可能性があります。例えば、ExcavatorからZen 2プロセッサまでは、PEXT命令とPDEP命令をマイクロコードで実装しているため、他の命令で同じ動作を再現した場合よりも、これらの命令の実行速度が大幅に遅くなります。[ 20 ](実際には、「zp7」と呼ばれるソフトウェア手法は、これらのマシンではより高速です。)[ 21 ]最適なパフォーマンスを得るためには、コンパイラ開発者は、拡張機能の可用性ではなく、アーキテクチャ固有のパフォーマンスプロファイルに基づいて、拡張機能内の個々の命令を使用するように選択することが推奨されます。