Extraños efectos de rendimiento de tiendas dependientes cercanas en un bucle de búsqueda de puntero en IvyBridge. Agregar una carga adicional lo acelera?

Primero tengo la configuración a continuación en un IvyBridge, insertaré el código de carga útil de medición en la ubicación comentada. Los primeros 8 bytes debuf almacenar la dirección debuf en sí, lo uso para crear una dependencia transportada en bucle:

section .bss
align   64
buf:    resb    64

section .text
global _start
_start:
    mov rcx,         1000000000
    mov qword [buf], buf
    mov rax,         buf
loop:
    ; I will insert payload here
    ; as is described below 

    dec rcx
    jne loop

    xor rdi,    rdi
    mov rax,    60
    syscall
caso 1

I inserción en la ubicación de la carga útil:

mov qword [rax+8],  8
mov rax,            [rax]

perf muestra que el bucle es 5.4c / iter. Es algo comprensible, porque la latencia L1d es de 4 ciclos.

case 2:

I invertir el orden de estas dos instrucciones:

mov rax,            [rax]
mov qword [rax+8],  8

El resultado de repente se convierte en 9c / iter. No entiendo por qué. Debido a que la primera instrucción de la siguiente iteración no depende de la segunda instrucción de la iteración actual, esta configuración no debería ser diferente con el caso 1.

También utilicé la herramienta IACA para analizar estos dos casos de forma estática, pero la herramienta no es confiable, ya que predice el mismo resultado 5.71c / iter para ambos casos, lo que contradice el experimento.

case 3:

Then un inserto irrelevantemov instrucción para el caso 2:

mov rax,            [rax]
mov qword [rax+8],  8
mov rbx,            [rax+16] 

Ahora el resultado se convierte en 6.8c / iter. Pero, ¿cómo puede un @ irrelevanmov insertó aumentar la velocidad de 9c / iter a 6.8c / iter?

a herramienta IACA predice un resultado incorrecto como en el caso anterior, muestra 5.24c / iter.

Ahora estoy totalmente confundido, ¿cómo comprender los resultados anteriores?

Editar para más información:

En los casos 1 y 2, hay una direcciónrax+8. Los mismos resultados se mantienen para los casos 1 y 2 sirax+8 se cambia arax+16 orax+24. Pero sucede algo sorprendente cuando se cambia arax+32: El caso 1 se convierte en 5.3c / ITER, el caso 2 se convierte de repente 4.2c / iter

Editar para másperf eventos
$ perf stat -ecycles,ld_blocks_partial.address_alias,int_misc.recovery_cycles,machine_clears.count,uops_executed.stall_cycles,resource_stalls.any ./a.out

case 1 para[rax+8]:

 5,429,070,287      cycles                                                        (66.53%)
         6,941      ld_blocks_partial.address_alias                                     (66.75%)
       426,528      int_misc.recovery_cycles                                      (66.83%)
        17,117      machine_clears.count                                          (66.84%)
 2,182,476,446      uops_executed.stall_cycles                                     (66.63%)
 4,386,210,668      resource_stalls.any                                           (66.41%)

case 2 para[rax+8]:

 9,018,343,290      cycles                                                        (66.59%)
         8,266      ld_blocks_partial.address_alias                                     (66.73%)
       377,824      int_misc.recovery_cycles                                      (66.76%)
        10,159      machine_clears.count                                          (66.76%)
 7,010,861,225      uops_executed.stall_cycles                                     (66.65%)
 7,993,995,420      resource_stalls.any                                           (66.51%)

case 3 para[rax+8]:

 6,810,946,768      cycles                                                        (66.69%)
         1,641      ld_blocks_partial.address_alias                                     (66.73%)
       223,062      int_misc.recovery_cycles                                      (66.73%)
         7,349      machine_clears.count                                          (66.74%)
 3,618,236,557      uops_executed.stall_cycles                                     (66.58%)
 5,777,653,144      resource_stalls.any                                           (66.53%)

case 2 para[rax+32]:

 4,202,233,246      cycles                                                        (66.68%)
         2,969      ld_blocks_partial.address_alias                                     (66.68%)
       149,308      int_misc.recovery_cycles                                      (66.68%)
         4,522      machine_clears.count                                          (66.68%)
 1,202,497,606      uops_executed.stall_cycles                                     (66.64%)
 3,179,044,737      resource_stalls.any                                           (66.64%)

Respuestas a la pregunta(1)

Su respuesta a la pregunta