Usando registros ymm como um local de armazenamento "semelhante à memória"

Considere o seguinte loop em x86:

; on entry, rdi has the number of iterations
.top:
; some magic happens here to calculate a result in rax
mov [array + rdi * 8], rax ; store result in output array
dec rdi
jnz .top

É simples: algo calcula um resultado emrax (não mostrado) e, em seguida, armazenamos o resultado em uma matriz, na ordem inversa à medida que indexamos comrdi.

Gostaria de transformar o loop acima para não gravar na memória (podemos assumir que o cálculo não mostrado não grava na memória).

Contanto que o loop conterdi é limitado, eu poderia usar o amplo espaço (512 bytes) fornecido peloymm regs para salvar os valores, mas parece estranho fazer isso, pois você não pode "indexar" um registro arbitrário.

Uma abordagem seria sempre embaralhar toda a "matriz" deymm registra por um elemento e insira o elemento na posição recém-liberada.

Algo assim:

vpermq  ymm3, ymm3, 10_01_00_11b ; left rotate ymm by qword
vpermq  ymm2, ymm2, 10_01_00_11b ; left rotate ymm by qword
vpermq  ymm1, ymm1, 10_01_00_11b ; left rotate ymm by qword
vpermq  ymm0, ymm0, 10_01_00_11b ; left rotate ymm by qword

vblenddd ymm3, ymm3, ymm2, 3     ; promote one qword of ymm2 to ymm3
vblenddd ymm2, ymm2, ymm1, 3     ; promote one qword of ymm1 to ymm2
vblenddd ymm1, ymm1, ymm0, 3     ; promote one qword of ymm0 to ymm1

pinsrq   xmm0, rax, 0  ; playing with mixed-VEX mode fire (see Peter's answer)

Isso mostra apenas o manuseio de quatro dos 16 registros, portanto, evidentemente, para fazer todos os 16, haverá muito código (32 instruções).

Existe uma maneira melhor?

Ramificações imprevisíveis são indesejáveis, mas ainda podemos considerar soluções que as utilizam.

questionAnswers(2)

yourAnswerToTheQuestion