Los conjuntos de instrucciones de manipulación de bits ( conjuntos BMI ) son extensiones de la arquitectura de conjuntos de instrucciones x86 para microprocesadores de Intel y AMD . El propósito de estos conjuntos de instrucciones es mejorar la velocidad de manipulación de bits . Todas las instrucciones en estos conjuntos no son SIMD y operan solo en registros de propósito general .
Hay dos conjuntos publicados por Intel: BMI (ahora denominado BMI1) y BMI2; ambos se introdujeron con la microarquitectura Haswell con BMI1 que coincide con las características ofrecidas por el conjunto de instrucciones ABM de AMD y BMI2 que las extiende. Otros dos conjuntos fueron publicados por AMD: ABM ( Advanced Bit Manipulation , que también es un subconjunto de SSE4a implementado por Intel como parte de SSE4.2 y BMI1), y TBM ( Trailing Bit Manipulation , una extensión introducida con los procesadores basados en Piledriver como una extensión de BMI1, pero abandonada nuevamente en los procesadores basados en Zen ). [1]
AMD fue el primero en introducir las instrucciones que ahora forman parte del conjunto de instrucciones BMI1 de Intel como parte de su conjunto de instrucciones ABM ( Advanced Bit Manipulation ), y luego agregó soporte para las nuevas instrucciones BMI2 de Intel. AMD anuncia hoy la disponibilidad de estas funciones a través de los cpuflags BMI1 y BMI2 de Intel e instruye a los programadores para que las utilicen en consecuencia. [2]
Si bien Intel lo considera POPCNT
parte de SSE4.2 y LZCNT
de BMI1, tanto Intel como AMD anuncian la presencia de estas dos instrucciones de forma individual. POPCNT
tiene un indicador CPUID independiente con el mismo nombre, e Intel y AMD utilizan ABM
el indicador de AMD para indicar LZCNT
compatibilidad (ya que LZCNT
combinado con BMI1 y BMI2 completa el conjunto de instrucciones ABM expandido). [2] [3]
LZCNT
está relacionada con la instrucción Bit Scan Reverse ( BSR
), pero establece los indicadores ZF (si el resultado es cero) y CF (si la fuente es cero) en lugar de establecer ZF (si la fuente es cero). Además, produce un resultado definido (el tamaño del operando de la fuente en bits) si el operando de la fuente es cero. Para un argumento distinto de cero, la suma de LZCNT
y BSR
los resultados es el ancho de bits del argumento menos 1 (por ejemplo, si el argumento de 32 bits es 0x000f0000
, LZCNT da 12 y BSR da 19).
La codificación de LZCNT
es tal que si no se admite ABM, BSR
se ejecuta la instrucción en su lugar. [4] : 227
Las instrucciones que aparecen a continuación son las que se habilitan mediante el BMI
bit en CPUID. Intel lo considera oficialmente LZCNT
como parte de BMI, pero anuncia LZCNT
su compatibilidad mediante el ABM
indicador de función CPUID. [3] BMI1 está disponible en los procesadores Jaguar , [5] Piledriver [6] y posteriores de AMD , y en los procesadores Haswell [7] y posteriores de Intel .
TZCNT
es casi idéntica a la BSF
instrucción Bit Scan Forward ( ), pero establece los indicadores ZF (si el resultado es cero) y CF (si la fuente es cero) en lugar de establecer ZF (si la fuente es cero). Para un argumento distinto de cero, el resultado de TZCNT
y BSF
es igual.
Al igual que con LZCNT
, la codificación de TZCNT
es tal que si no se admite BMI1, BSF
se ejecuta la instrucción en su lugar. [4] : 352
Intel introdujo BMI2 junto con BMI1 en su línea de procesadores Haswell. Solo AMD ha producido procesadores compatibles con BMI1 sin BMI2; BMI2 es compatible con la arquitectura Excavator de AMD y las más nuevas. [11]
Las instrucciones PDEP
y PEXT
son nuevas instrucciones generalizadas de compresión y expansión a nivel de bits. Reciben dos entradas; una es una fuente y la otra es un selector. El selector es un mapa de bits que selecciona los bits que se van a empaquetar o desempaquetar. PEXT
copia los bits seleccionados de la fuente a los bits de orden inferior contiguos del destino; los bits de destino de orden superior se borran. PDEP
hace lo contrario para los bits seleccionados: los bits de orden inferior contiguos se copian a los bits seleccionados del destino; los demás bits de destino se borran. Esto se puede utilizar para extraer cualquier campo de bits de la entrada e incluso para realizar una gran cantidad de barajas a nivel de bits que antes habrían sido costosas. Si bien lo que hacen estas instrucciones es similar a las instrucciones SIMD de recopilación y dispersiónPDEP
a nivel de bits, las instrucciones y PEXT
(al igual que el resto de los conjuntos de instrucciones BMI) operan en registros de propósito general. [12]
Las instrucciones están disponibles en versiones de 32 y 64 bits. Un ejemplo que utiliza una fuente y un selector arbitrarios en modo de 32 bits es:
Los procesadores AMD anteriores a Zen 3 [13] que implementan PDEP y PEXT lo hacen en microcódigo, con una latencia de 18 ciclos [14] en lugar de 3 ciclos (Zen 3). [15] Como resultado, a menudo es más rápido usar otras instrucciones en estos procesadores. [16]
TBM consta de instrucciones complementarias al conjunto de instrucciones iniciado por BMI1; su naturaleza complementaria significa que no necesariamente necesitan usarse directamente, pero pueden generarse mediante un compilador optimizador cuando sea compatible. AMD introdujo TBM junto con BMI1 en su línea de procesadores Piledriver [6] ; los procesadores posteriores basados en AMD Jaguar y Zen no admiten TBM. [5] Ningún procesador Intel (al menos a través de Alder Lake ) admite TBM.
Tenga en cuenta que la compatibilidad con extensiones de instrucciones significa que el procesador es capaz de ejecutar las instrucciones admitidas para fines de compatibilidad de software. El procesador podría no funcionar bien al hacerlo. Por ejemplo, los procesadores Excavator a Zen 2 implementan instrucciones PEXT y PDEP utilizando microcódigo, lo que da como resultado que las instrucciones se ejecuten significativamente más lento que el mismo comportamiento recreado utilizando otras instrucciones. [20] (Un método de software llamado "zp7" es, de hecho, más rápido en estas máquinas). [21] Para un rendimiento óptimo, se recomienda que los desarrolladores de compiladores elijan usar instrucciones individuales en las extensiones según los perfiles de rendimiento específicos de la arquitectura en lugar de la disponibilidad de la extensión.