x86_64 – Ensamblaje – condiciones de lazo y fuera de servicio

No estoy pidiendo un punto de referencia.

( Si ese fuera el caso, lo habría hecho yo mismo ) .


Mi pregunta:

Tiendo a evitar los modos de direccionamiento indirecto / indexado por conveniencia.

Como reemplazo, a menudo uso el direccionamiento inmediato, absoluto o de registro.

El código:

; %esi has the array address. Say we iterate a doubleword (4bytes) array. ; %ecx is the array elements count (0x98767) myloop: ... ;do whatever with %esi add $4, %esi dec %ecx jnz 0x98767; 

Aquí, tenemos un combo serializado (dec y jnz) que impide una correcta ejecución fuera de servicio (dependencia).

¿Hay alguna manera de evitar eso / romper el dep? (No soy un experto en ensamblaje).

Al optimizar las CPU Intel, siempre coloque la instrucción de configuración de banderas justo antes de la instrucción de salto condicional (si es una de las simples enumeradas en la tabla a continuación), para que puedan fusionarse macro en un uop en los decodificadores.

Hacer esto no es significativamente peor para las CPU antiguas que no hacen macro fusión. Colocar la configuración de indicador más temprano puede acortar la penalización de error de bifurcación en uno para tales CPU, permitiendo que se detecte un error de predicción antes. No tengo puntos de referencia, pero no creo que la pequeña desventaja en las CPU cada vez más raras justifique que se pierda el beneficio del rendimiento del front-end (deencoding y emisión) para las CPU que realizan fusión. El rendimiento total de uop a menudo puede ser un cuello de botella.

AMD Bulldozer / Piledriver / Steamroller puede fusionar test/cmp con cualquier jcc , pero solo con test/cmp , sin ninguna otra instrucción ALU. Así que definitivamente se compara con las twigs.

De la guía de microarch de Agner Fog , Tabla 9.2 (para Sandybridge / Ivybridge):

 First | can pair with these | cannot pair with instruction | (and the inverse) | --------------------------------------------- cmp |jz, jc, jb, ja, jl, jg| js, jp, jo add, sub |jz, jc, jb, ja, jl, jg| js, jp, jo adc, sbb |none | inc, dec |jz, jl, jg | jc, jb, ja, js, jp, jo test | all | and | all | or, xor, not, neg | none | shift, rotate | none | Table 9.2. Instruction fusion 

Entonces, básicamente, inc/dec puede macro fusible con un jcc siempre que la condición solo dependa de los bits que se modifiquen mediante inc/dec .

(De lo contrario, no se fusionan macro, y obtienes un uop extra insertado para unir las banderas (como cuando lees eax después de escribir al ). O en CPUs anteriores, un locking de banderas parciales).

Core2 / Nehalem tenía una capacidad de macro fusión más limitada (solo para CMP / TEST con combinaciones de JCC más limitadas), y Core2 no podía fusionarse en modo de 64 bits.

Lea también las guías de optimización de As y C de Agner Fog si aún no lo ha hecho. Están llenos de conocimiento esencial.