home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.asm.x86      Ahh, the lost art of x86 assembly      4,675 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 4,459 of 4,675   
   James Van Buskirk to All   
   Bit reversal in AVX2 (1/2)   
   22 May 22 03:05:58   
   
   From: not_valid@nospicedham.comcast.net   
      
   Just for fun I thought I would try various strategies for permuting   
   an array of single-precision floating point numbers using AVX2.   
   bitrev1.asm just does vpunpckl/hdq/qdq or its lane-crossing   
   synthesis with vperm2i128 and has a hard limit of 24 clocks to   
   bit-reverse a 64-element array because all of these operations   
   use pipeline 5.   
      
   D:\gfortran\james\bitrev>type bitrev1.asm   
   format MS64 COFF   
      
   section '.text' code readable writeable executable   
   public bitrev1   
   bitrev1:   
      sub rsp, 56   
      vmovdqu [rsp+32], xmm6   
      vmovdqu [rsp+16], xmm7   
      vmovdqu [rsp], xmm8   
      
      vmovdqu ymm0, [rcx]   
      vmovdqu ymm1, [rcx+32]   
      vmovdqu ymm2, [rcx+64]   
      vmovdqu ymm3, [rcx+96]   
      vmovdqu ymm4, [rcx+128]   
      vmovdqu ymm5, [rcx+160]   
      vmovdqu ymm6, [rcx+192]   
      vmovdqu ymm8, [rcx+224]   
      
      vperm2i128 ymm7, ymm0, ymm1, 32   
      vperm2i128 ymm0, ymm0, ymm1, 49   
      vperm2i128 ymm1, ymm2, ymm3, 32   
      vperm2i128 ymm2, ymm2, ymm3, 49   
      vperm2i128 ymm3, ymm4, ymm5, 32   
      vperm2i128 ymm4, ymm4, ymm5, 49   
      vperm2i128 ymm5, ymm6, ymm8, 32   
      vperm2i128 ymm6, ymm6, ymm8, 49   
      
      vpunpckldq ymm8, ymm7, ymm3   
      vpunpckhdq ymm7, ymm7, ymm3   
      vpunpckldq ymm3, ymm0, ymm4   
      vpunpckhdq ymm0, ymm0, ymm4   
      vpunpckldq ymm4, ymm1, ymm5   
      vpunpckhdq ymm1, ymm1, ymm5   
      vpunpckldq ymm5, ymm2, ymm6   
      vpunpckhdq ymm6, ymm2, ymm6   
      
      vpunpcklqdq ymm2, ymm8, ymm4   
      vpunpckhqdq ymm8, ymm8, ymm4   
      vpunpcklqdq ymm4, ymm7, ymm1   
      vpunpckhqdq ymm7, ymm7, ymm1   
      vpunpcklqdq ymm1, ymm3, ymm5   
      vpunpckhqdq ymm3, ymm3, ymm5   
      vpunpcklqdq ymm5, ymm0, ymm6   
      vpunpckhqdq ymm0, ymm0, ymm6   
      
      vmovdqu [rcx], ymm2   
      vmovdqu [rcx+32], ymm1   
      vmovdqu [rcx+64], ymm4   
      vmovdqu [rcx+96], ymm5   
      vmovdqu [rcx+128], ymm8   
      vmovdqu [rcx+160], ymm3   
      vmovdqu [rcx+192], ymm7   
      vmovdqu [rcx+224], ymm0   
      
   epilog:   
      vmovdqu xmm6, [rsp+32]   
      vmovdqu xmm7, [rsp+16]   
      vmovdqu xmm8, [rsp]   
      add rsp, 56   
      ret   
      
   D:\gfortran\james\bitrev>fasm bitrev1.asm   
   flat assembler  version 1.71.49  (1048576 kilobytes memory)   
   1 passes, 357 bytes.   
      
   bitrev2.asm is the ugliest version, using permutations up front   
   and in back to shift the data into position and then vpblendd   
   to shift data between registers. It has the potential to be fastest   
   because only 14 operations require pipeline 5.   
      
   D:\gfortran\james\bitrev>type bitrev2.asm   
   format MS64 COFF   
      
   section '.text' code readable writeable executable   
   public bitrev2   
   bitrev2:   
      sub rsp, 56   
      vmovdqu [rsp+32], xmm6   
      vmovdqu [rsp+16], xmm7   
      vmovdqu [rsp], xmm8   
      
      vmovdqu ymm0, [rcx]   
      vmovdqu ymm4, [rcx+32]   
      vmovdqu ymm2, [rcx+64]   
      vmovdqu ymm6, [rcx+96]   
      vmovdqu ymm1, [rcx+128]   
      vmovdqu ymm5, [rcx+160]   
      vmovdqu ymm3, [rcx+192]   
      vmovdqu ymm8, [rcx+224]   
      
      vmovdqu ymm7, yword [perm0]   
      vpermd ymm1, ymm7, ymm1   
      vpermq ymm2, ymm2, 177   
      vmovdqu ymm7, yword [perm1]   
      vpermd ymm3, ymm7, ymm3   
      vpermq ymm4, ymm4, 78   
      vmovdqu ymm7, yword [perm0+16]   
      vpermd ymm5, ymm7, ymm5   
      vpermq ymm6, ymm6, 27   
      vmovdqu ymm7, yword [perm1+16]   
      vpermd ymm8, ymm7, ymm8   
      
      vpblendd ymm7, ymm0, ymm4, 240   
      vpblendd ymm0, ymm0, ymm4, 15   
      vpblendd ymm4, ymm2, ymm6, 240   
      vpblendd ymm2, ymm2, ymm6, 15   
      vpblendd ymm6, ymm1, ymm5, 240   
      vpblendd ymm1, ymm1, ymm5, 15   
      vpblendd ymm5, ymm3, ymm8, 240   
      vpblendd ymm3, ymm3, ymm8, 15   
      
      vpblendd ymm8, ymm7, ymm4, 204   
      vpblendd ymm7, ymm7, ymm4, 51   
      vpblendd ymm4, ymm0, ymm2, 204   
      vpblendd ymm0, ymm0, ymm2, 51   
      vpblendd ymm2, ymm6, ymm5, 204   
      vpblendd ymm6, ymm6, ymm5, 51   
      vpblendd ymm5, ymm1, ymm3, 204   
      vpblendd ymm1, ymm1, ymm3, 51   
      
      vpblendd ymm3, ymm8, ymm2, 170   
      vpblendd ymm8, ymm8, ymm2, 85   
      vpblendd ymm2, ymm7, ymm1, 170   
      vpblendd ymm7, ymm7, ymm1, 85   
      vpblendd ymm1, ymm4, ymm5, 170   
      vpblendd ymm4, ymm4, ymm5, 85   
      vpblendd ymm5, ymm0, ymm6, 170   
      vpblendd ymm0, ymm0, ymm6, 85   
      
      vmovdqu ymm6, yword [perm1+8]   
      vpermd  ymm8, ymm6, ymm8   
      vmovdqu ymm6, yword [perm2]   
      vpermd  ymm2, ymm6, ymm2   
      vmovdqu ymm6, yword [perm3]   
      vpermd  ymm7, ymm6, ymm7   
      vpermq  ymm1, ymm1, 78   
      vmovdqu ymm6, yword [perm1+24]   
      vpermd  ymm4, ymm6, ymm4   
      vmovdqu ymm6, yword [perm2+16]   
      vpermd  ymm5, ymm6, ymm5   
      vmovdqu ymm6, yword [perm3+16]   
      vpermd  ymm0, ymm6, ymm0   
      
      vmovdqu [rcx], ymm3   
      vmovdqu [rcx+32], ymm1   
      vmovdqu [rcx+64], ymm2   
      vmovdqu [rcx+96], ymm5   
      vmovdqu [rcx+128], ymm8   
      vmovdqu [rcx+160], ymm4   
      vmovdqu [rcx+192], ymm7   
      vmovdqu [rcx+224], ymm0   
      
   .epilog:   
      vmovdqu xmm6, [rsp+32]   
      vmovdqu xmm7, [rsp+16]   
      vmovdqu xmm8, [rsp]   
      add rsp, 56   
      ret   
      
   section '.data' data readable writeable align 32   
      align 32   
      perm0 dd 1,0,7,6,5,4,3,2,1,0,7,6   
      perm1 dd 7,6,1,0,3,2,5,4,7,6,1,0,3,2   
      perm2 dd 2,7,0,5,6,3,4,1,2,7,0,5   
      perm3 dd 3,6,1,4,7,2,5,0,3,6,1,4   
      
   D:\gfortran\james\bitrev>fasm bitrev2.asm   
   flat assembler  version 1.71.49  (1048576 kilobytes memory)   
   3 passes, 901 bytes.   
      
   bitrev3.asm uses vpgatherdd, which is a really slow instruction.   
   It was the easiest to write, though.   
      
   D:\gfortran\james\bitrev>type bitrev3.asm   
   format MS64 COFF   
      
   section '.text' code readable writeable executable   
   public bitrev3   
   bitrev3:   
      sub rsp, 72   
      vmovdqu [rsp+48], xmm6   
      vmovdqu [rsp+32], xmm7   
      vmovdqu [rsp+16], xmm8   
      vmovdqu [rsp], xmm9   
      
      vmovdqu ymm6, yword [table]   
      
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm0, [rcx+ymm6], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm1, [rcx+ymm6+16], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm2, [rcx+ymm6+8], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm3, [rcx+ymm6+24], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm4, [rcx+ymm6+4], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm5, [rcx+ymm6+20], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm8, [rcx+ymm6+12], ymm7   
      vpcmpeqd ymm7, ymm7, ymm7   
      vpgatherdd ymm9, [rcx+ymm6+28], ymm7   
      
      vmovdqu [rcx], ymm0   
      vmovdqu [rcx+32], ymm1   
      vmovdqu [rcx+64], ymm2   
      vmovdqu [rcx+96], ymm3   
      vmovdqu [rcx+128], ymm4   
      vmovdqu [rcx+160], ymm5   
      vmovdqu [rcx+192], ymm8   
      vmovdqu [rcx+224], ymm9   
      
   epilog:   
      vmovdqu xmm6, [rsp+48]   
      vmovdqu xmm7, [rsp+32]   
      vmovdqu xmm8, [rsp+16]   
      vmovdqu xmm9, [rsp]   
      add rsp, 72   
      ret   
      
   section '.data' data readable writeable align 32   
      align 32   
      table dd 0,128,64,192,32,160,96,224   
      
   D:\gfortran\james\bitrev>fasm bitrev3.asm   
   flat assembler  version 1.71.49  (1048576 kilobytes memory)   
   3 passes, 401 bytes.   
      
   bitrev4.asm just reads addresses to swap from a lookup table. It   
   seems to have a hard limit of 56 clocks because my Haswell appears   
   to have only only store pipeline.   
      
   D:\gfortran\james\bitrev>type bitrev4.asm   
   format MS64 COFF   
      
   section '.text' code readable writeable executable   
      
   [continued in next message]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca