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)

modifier

AMD 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)

modifier

Les 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)

modifier

Intel 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

modifier

Les 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)

modifier

TBM 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

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
  1. a et b (en-US) « New "Bulldozer" and "Piledriver" Instructions » (consulté le )
  2. a et b (en-US) « AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions » (consulté le )
  3. a b et c (en-US) « Intel Advanced Vector Extensions Programming Reference » [PDF], intel.com, Intel, (consulté le )
  4. a b c et d (en-US) « AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and System Instructions » [archive du ], AMD, (consulté le )
  5. a b c et d (en-US) « Family 16h AMD A-Series Data Sheet », amd.com, AMD, (consulté le )
  6. a et b (en-US) Brent Hollingsworth, « New "Bulldozer" and "Piledriver" instructions », Advanced Micro Devices, Inc. (consulté le )
  7. a et b (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 )
  8. (en) « bmiintrin.h from GCC 4.8 » (consulté le )
  9. a et b (en) « sandpile.org -- x86 architecture -- bits » (consulté le )
  10. (en) « Abseil - C++ Common Libraries », sur GitHub,
  11. a et b (en-US) « AMD Excavator Core May Bring Dramatic Performance Increases - Archivé depuis l'original », X-bit labs, (consulté le )
  12. (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 )
  13. (en-US) « Zen 3 - Microarchitectures - AMD », sur WikiChip
  14. (en) Agner Fog, « Instruction tables » [PDF] (consulté le )
  15. (en-US) « Software Optimization Guide for AMD Family 19h Processors », sur AMD Developer Central (consulté le )
  16. (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 )
  17. (en-US) « tbmintrin.h from GCC 4.8 » (consulté le )
  18. (en-US) « BIOS and Kernel Developer's Guide for AMD Family 14h » (consulté le )
  19. (en-US) « AMD Zen 3 Ryzen Deep Dive Review: 5950X, 5900X, 5800X and 5600X Tested », sur AnandTech (consulté le )
  20. (en-US) « Dolphin Progress Report: December 2019 and January 2020 », sur Dolphin Emulator, (consulté le )
  21. (en-US) Zach Wegner, « zwegner/zp7 », sur GitHub,