Jeux d'instructions de manipulation de bits
Les jeux d’instructions de manipulation de bits (Bit Manipulation Instruction sets, BMI) sont des extensions de l’architecture de jeu d'instructions x86 pour les microprocesseurs d’Intel et d’AMD. Le but de ces jeux d’instructions est d’améliorer la vitesse de manipulation de bits. Toutes les instructions de ces ensembles sont non-SIMD et ne fonctionnent que sur des registres à usage général.
Il existe deux ensembles publiés par Intel : BMI (maintenant appelé BMI1) et BMI2 ; ils ont tous deux été introduits avec la microarchitecture Haswell avec les fonctionnalités d’appariement BMI1 offertes par le jeu d’instructions ABM d’AMD et BMI2 les étendant. Deux autres ensembles ont été publiés par AMD : ABM (Advanced Bit Manipulation, qui est également un sous-ensemble de SSE4a implémenté par Intel dans le cadre de SSE4.2 et de BMI1), et TBM (Trailing Bit Manipulation, une extension introduite avec les processeurs basés sur Piledriver en tant qu’extension de BMI1, mais abandonnée ensuite dans les processeurs basés sur Zen)[1].
ABM (Advanced Bit Manipulation)
modifierAMD a été le premier à introduire les instructions qui forment maintenant le BMI1 d’Intel dans le cadre de son jeu d’instructions ABM (Advanced Bit Manipulation), puis a ajouté plus tard la prise en charge des nouvelles instructions BMI2 d’Intel. AMD annonce aujourd’hui la disponibilité de ces fonctionnalités via les flags CPU BMI1 et BMI2 d’Intel et demande aux programmeurs de les choisir en conséquence[2].
Tandis qu'Intel considère POPCNT
comme appartenant à SSE4.2 et LZCNT
appartenant à BMI1, Intel et AMD indiquent tous deux de la présence de ces deux instructions individuellement. POPCNT
a un drapeau CPUID de même nom et Intel et AMD utilisent le drapeau AMD ABM
pour indiquer le support de LZCNT
(puisque LZCNT
combiné avec BMI1 et BMI2 complète le jeu d'instructions ABM étendu)[2],[3].
Code | Instruction | Description[4] |
---|---|---|
F3 0F B8 /r
|
POPCNT
|
Comptage de population |
F3 0F BD /r
|
LZCNT
|
Compte le nombre de bits à zéro à gauche (en tête) |
LZCNT
est liée à l'instruction Bit Scan Reverse (BSR
), mais arme les drapeaux ZF (si le résultat vaut zéro) et CF (si la source vaut zéro) plutôt que d'armer le drapeau ZF (si la source vaut zéro). Il produit également un résultat défini (la taille de l'opérande source en bits) si l'opérande source vaut zéro. Pour un argument différent de zéro, la somme des résultats de LZCNT
et de BSR
est la taille en bits de l'argument moins 1 (par exemple, si l'argument 32 bits est 0x000f0000
, LZCNT donne 12 et BSR donne 19, la somme vaut 31).
Le codage de LZCNT
est tel que si ABM n'est pas supporté, alors l'instruction BSR
est exécutée à la place[4]:227.
BMI1 (Bit Manipulation Instruction Set 1)
modifierLes instructions ci-dessous sont celles activées par le bit BMI
dans le CPUID. Intel considère officiellement LZCNT
comme partie de BMI, mais indique le support de LZCNT
à l'aide du flag CPUID ABM
[3]. BMI1 est disponible sur les processeurs AMD Jaguar[5], Piledriver[6] et plus récents, et sur les processeurs Intel Haswell[7] et plus récents.
Code | Instruction | Description[3] | Expression C équivalente[8],[9],[10] |
---|---|---|---|
VEX.LZ.0F38 F2 /r
|
ANDN
|
(NON A) ET B logique | ~x & y
|
VEX.LZ.0F38 F7 /r
|
BEXTR
|
Extraction d'un champ de bits (avec registre) | (src >> start) & ((1 << len) - 1)
|
VEX.LZ.0F38 F3 /3
|
BLSI
|
Extrait le bit isolé à 1 de poids le plus faible | x & -x
|
VEX.LZ.0F38 F3 /2
|
BLSMSK
|
Obtient le masque jusqu'au bit à 1 de poids le plus faible | x ^ (x - 1)
|
VEX.LZ.0F38 F3 /1
|
BLSR
|
Met à zéro le bit à 1 de poids le plus faible | x & (x - 1)
|
F3 0F BC /r
|
TZCNT
|
Compte le nombre de bits à zéro en queue (à droite) |
L'instruction TZCNT
est presque identique à l'instruction Bit Scan Forward (BSF
), mais arme les drapeaux ZF (si le résultat vaut zéro) et CF (si la source vaut zéro) plutôt que d'armer le drapeau ZF (si la source vaut zéro). Pour un argument différent de zéro, les résultats de TZCNT
et de BSF
sont identiques.
Comme avec LZCNT
, le codage de TZCNT
est tel que si BMI1 n'est pas supporté, alors l'instruction BSF
est exécutée à la place[4]:352.
BMI2 (Bit Manipulation Instruction Set 2)
modifierIntel a introduit BMI2 en même temps que BMI1 dans sa gamme de processeurs Haswell. Seul AMD a produit des processeurs supportant BMI1 mais pas BMI 2 ; BMI2 est supporté par l'architecture AMD Excavator et plus récente[11].
Codage | Instruction | Description |
---|---|---|
VEX.LZ.0F38 F5 /r
|
BZHI
|
Mise à zéro des bits les plus élevés à partir d'une position de bit spécifiée [src & (1 << inx)-1] |
VEX.LZ.F2.0F38 F6 /r
|
MULX
|
Multiplication non signée sans affecter les drapeaux, avec des registres de destination quelconques |
VEX.LZ.F2.0F38 F5 /r
|
PDEP
|
Dépôt de bits en parallèle |
VEX.LZ.F3.0F38 F5 /r
|
PEXT
|
Extraction de bits en parallèle |
VEX.LZ.F2.0F3A F0 /r ib
|
RORX
|
Rotation logique vers la droite sans affecter les drapeaux |
VEX.LZ.F3.0F38 F7 /r
|
SARX
|
Décalage arithmétique vers la droite sans affecter les drapeaux |
VEX.LZ.F2.0F38 F7 /r
|
SHRX
|
Décalage logique vers la droite sans affecter les drapeaux |
VEX.LZ.66.0F38 F7 /r
|
SHLX
|
Décalage logique vers la gauche sans affecter les drapeaux |
Dépôt et extraction de bits
modifierLes instructions PDEP
et PEXT
sont de nouvelles instructions généralisées de compression et d’expansion au niveau du bit. Elles prennent deux entrées : l’un est une source, et l’autre est un sélecteur. Le sélecteur est une image bitmap qui sélectionne les bits qui doivent être compressés ou décompressés. PEXT
copie les bits sélectionnés de la source vers les bits de poids faible contigus de la destination ; les bits de destination d’ordre supérieur sont effacés. PDEP
fait l’inverse pour les bits sélectionnés : les bits de poids faible contigus sont copiés sur les bits sélectionnés de la destination ; les autres bits de destination sont effacés. Cela peut être utilisé pour extraire n’importe quel champ de bits de l’entrée, et même effectuer beaucoup de brassage au niveau des bits, ce qui aurait été coûteux auparavant. Bien que ces instructions soient similaires aux instructions SIMD de gather-scatter (en) (collecte-diffusion) au niveau des bits, les instructions PDEP
et PEXT
(comme le reste des jeux d’instructions BMI) fonctionnent sur des registres à usage général[12].
Les instructions sont disponibles en versions 32 bits et 64 bits. Voici un exemple d’utilisation d’une source et d’un sélecteur arbitraires en mode 32 bits :
Instruction | Masque du sélecteur | Source | Destination |
---|---|---|---|
PEXT |
0xff00fff0 |
0x12345678 |
0x00012567
|
PDEP |
0xff00fff0 |
0x00012567 |
0x12005670
|
Les processeurs AMD avant Zen 3[13] qui implémentent PDEP et PEXT le font en microcode, avec une latence de 18 cycles[14] contre 3 cycles sur Zen 3[15]. Par conséquent, il est souvent plus rapide d'utiliser d'autres instructions sur ces processeurs[16].
TBM (Trailing Bit Manipulation)
modifierTBM est constitué d'instructions complémentaires au jeu d'instructions initié par BMI1 ; leur nature complémentaire signifie qu'elles n'ont pas nécessairement besoin d'être utilisées directement mais qu'elles peuvent être générées par un compilateur optimisé si elles sont supportées. AMD a introduit TBM en même temps que BMI1 dans sa gamme de processeurs Piledriver[6] ; les processeurs AMD suivants Jaguar et Zen ne supportent pas TBM[5]. Aucun processeur Intel (au moins jusqu'à Alder Lake) ne supporte TBM.
Codage | Instruction | Description[4] | Expression C équivalente[17],[9] |
---|---|---|---|
XOP.LZ.0A 10 /r id
|
BEXTR
|
Extraire un champ de bits (avec immédiat) | (src >> start) & ((1 << len) - 1)
|
XOP.LZ.09 01 /1
|
BLCFILL
|
Remplir à partir du bit à zéro de poids le plus faible | x & (x + 1)
|
XOP.LZ.09 02 /6
|
BLCI
|
Isoler le bit à zéro de poids le plus faible | x | ~(x + 1)
|
XOP.LZ.09 01 /5
|
BLCIC
|
Isoler le bit à zéro de poids le plus faible et calculer le complément |
~x & (x + 1)
|
XOP.LZ.09 02 /1
|
BLCMSK
|
Masque à partir du bit à zéro de poids le plus faible | x ^ (x + 1)
|
XOP.LZ.09 01 /3
|
BLCS
|
Mettre à 1 le bit de poids le plus faible | x | (x + 1)
|
XOP.LZ.09 01 /2
|
BLSFILL
|
Remplir à partir du bit à 1 de poids le plus faible | x | (x - 1)
|
XOP.LZ.09 01 /6
|
BLSIC
|
Isoler le bit à 1 de poids le plus faible et calculer le complément |
~x | (x - 1)
|
XOP.LZ.09 01 /7
|
T1MSKC
|
Masque inverse pour les zéros en queue (à droite) | ~x | (x + 1)
|
XOP.LZ.09 01 /4
|
TZMSK
|
Masque pour les zéros en queue (à droite) | ~x & (x - 1)
|
CPU supportant ces instructions
modifier- Intel
- Processeurs Nehalem et plus récents (comme Sandy Bridge, Ivy Bridge) (support de POPCNT)
- Processeurs Silvermont (support de POPCNT)
- Processeurs Haswell et plus récents (Skylake, Broadwell, Skylake) (support d'ABM, de BMI1 et de BMI2)[7]
- AMD
- Processeurs basés sur K10 (support d'ABM)
- Processeurs à faible consommation "Cat"
- Processeurs basés sur Bobcat (support d'ABM)[18]
- Processeurs basés sur Jaguar et plus récents (support d'ABM et de BMI1)[5]
- Processeurs basés sur Puma et plus récents (support d'ABM et de BMI1)[5]
- Processeurs "Équipement Lourd"
- Processeurs basés sur Bulldozer (support d'ABM)
- Processeurs basés sur Piledriver (support d'ABM, de BMI1 et de TBM)[1]
- Processeurs basés sur Steamroller (support d' ABM, de BMI1 et de TBM)
- Processeurs basés sur Excavator et plus récents (support d'ABM, de BMI1, de BMI2 et de TBM ; PEXT et PDEP microcodés)[11]
- Processeurs basés sur Zen, Zen+ et Zen 2[19] (support d'ABM, de BMI1 et de BMI2 ; PEXT et PDEP microcodés)
- Processeurs Zen 3 et plus récents (support d'ABM, de BMI1 et de BMI2 ; implémentation entièrement hardware)
On notera que le support des extensions d'instructions signifie que le processeur est capable d'exécuter les instructions supportées dans un objectif de compatibilité logicielle. Le processeur peut très bien ne pas très efficace en faisant cela. Par exemple, les processeurs Excavator jusqu'à Zen 2 implémentent les instructions PEXT et PDEP à l'aide de microcode, ce qui fait que les instructions s'exécutent de façon beaucoup plus lente que le même comportement reproduit avec d'autres instructions[20] (Une méthode logicielle appelée "zp7" est, en fait, plus rapide sur ces machines)[21]. Pour une performance optimale, il est recommandé aux développeurs de compilateurs de choisir d'utiliser les instructions individuelles dans les extensions sur la base de profils de performance spécifiques à l'architecture plutôt que sur la disponibilité de l'extension.
Références
modifier- (en-US) « New "Bulldozer" and "Piledriver" Instructions » (consulté le )
- (en-US) « AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions » (consulté le )
- (en-US) « Intel Advanced Vector Extensions Programming Reference » [PDF], intel.com, Intel, (consulté le )
- (en-US) « AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and System Instructions » [archive du ], AMD, (consulté le )
- (en-US) « Family 16h AMD A-Series Data Sheet », amd.com, AMD, (consulté le )
- (en-US) Brent Hollingsworth, « New "Bulldozer" and "Piledriver" instructions », Advanced Micro Devices, Inc. (consulté le )
- (en-US) Max Locktyukhin, « How to detect New Instruction support in the 4th generation Intel® Core™ processor family », sur www.intel.com, Intel (consulté le )
- (en) « bmiintrin.h from GCC 4.8 » (consulté le )
- (en) « sandpile.org -- x86 architecture -- bits » (consulté le )
- (en) « Abseil - C++ Common Libraries », sur GitHub,
- (en-US) « AMD Excavator Core May Bring Dramatic Performance Increases - Archivé depuis l'original », X-bit labs, (consulté le )
- (en-US) Yedidya Hilewitz et Ruby B. Lee, « A New Basis for Shifters in General-Purpose Processors for Existing and Advanced Bit Manipulations », IEEE Transactions on Computers, palms.princeton.edu, vol. 58, no 8, , p. 1035–1048 (lire en ligne [PDF], consulté le )
- (en-US) « Zen 3 - Microarchitectures - AMD », sur WikiChip
- (en) Agner Fog, « Instruction tables » [PDF] (consulté le )
- (en-US) « Software Optimization Guide for AMD Family 19h Processors », sur AMD Developer Central (consulté le )
- (en) « Saving Private Ryzen: PEXT/PDEP 32/64b replacement functions for #AMD CPUs (BR/#Zen/Zen+/#Zen2) based on @zwegner's zp7 », sur Twitter (consulté le )
- (en-US) « tbmintrin.h from GCC 4.8 » (consulté le )
- (en-US) « BIOS and Kernel Developer's Guide for AMD Family 14h » (consulté le )
- (en-US) « AMD Zen 3 Ryzen Deep Dive Review: 5950X, 5900X, 5800X and 5600X Tested », sur AnandTech (consulté le )
- (en-US) « Dolphin Progress Report: December 2019 and January 2020 », sur Dolphin Emulator, (consulté le )
- (en-US) Zach Wegner, « zwegner/zp7 », sur GitHub,