Advertisement
Guest User

Untitled

a guest
Sep 15th, 2019
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.15 KB | None | 0 0
  1. // take an array of interleaved (x,y) pairs and computes fast_atan2(y,x) estimate on them.
  2. // approximately 15-40x faster than a simple loop with atan2, depending on
  3. // input buffer size.  Generated from vectorized output of fast_atan function.
  4. //
  5. // @param out    array to write output to
  6. // @param in     input array containing interleaved pairs
  7. // @param npair  number of input pairs to process
  8. //
  9. static inline void vatan2_avx(float* __restrict__ out, const float* __restrict__ in, ssize_t npair) {
  10.     // compute how many iterations to do and remainder of pairs left to do manually
  11.     size_t iters = npair/8;
  12.     size_t rem   = npair-iters*8;
  13.  
  14.     // constants
  15.     static const uint32_t signbit = 0x80000000;
  16.     static const uint32_t posnan  = 0x7fffffff;
  17.     static const float    one     = 1.0f;
  18.     static const float    mpi_2   = M_PI_2;
  19.     static const float    mpi     = M_PI;
  20.     static const float    coefa   = -0.0464964749f;
  21.     static const float    coefb   = +0.15931422f;
  22.     static const float    coefc   = -0.327622764f;
  23.    
  24.     __asm__(
  25.         // load constants
  26.         "    vxorps  %%ymm8, %%ymm8, %%ymm8\n\t"  // ymm8 = 0
  27.         "    vbroadcastss %[posnan], %%ymm9 \n\t" // abs() mask
  28.         "    vbroadcastss %[mpi],    %%ymm10\n\t"
  29.         "    vbroadcastss %[mpi_2],  %%ymm11\n\t"
  30.         "    vbroadcastss %[one],    %%ymm12\n\t"
  31.         "    vbroadcastss %[coefa],  %%ymm15\n\t"
  32.         "    vbroadcastss %[coefc],  %%ymm13\n\t"
  33.         "    vbroadcastss %[coefb],  %%ymm14\n\t"
  34.  
  35.         // setup indices, pointers
  36.         "    mov %[in],  %%rax\n\t" // input pointer
  37.         "    mov %[out], %%rcx\n\t" // output pointer
  38.         "    xor %%r8d,  %%r8d\n\t" // r8 = 0
  39.        
  40.         ".p2align 4\n\t"
  41.         ".LOOP%=:\n\t"
  42.         // load bottom part of ymm0 and ymm1
  43.         "    vmovups     (%%rax), %%ymm0\n\t"
  44.         "    vmovups 0x20(%%rax), %%ymm1\n\t"
  45.  
  46.         // increment loop variables
  47.         "    add     $0x01,  %%r8\n\t"  // r8  +=  1
  48.         "    add     $0x40,  %%rax\n\t" // in  += 16
  49.         "    add     $0x20,  %%rcx\n\t" // out +=  8
  50.        
  51.         // de-interleave x,y pairs into separate registers
  52.         "    vshufps      $0x88, %%ymm1, %%ymm0, %%ymm3\n\t"
  53.         "    vshufps      $0xdd, %%ymm1, %%ymm0, %%ymm0\n\t"
  54.         "    vperm2f128   $0x03, %%ymm3, %%ymm3, %%ymm2\n\t"
  55.         "    vperm2f128   $0x03, %%ymm0, %%ymm0, %%ymm1\n\t"
  56.         "    vshufps      $0x44, %%ymm2, %%ymm3, %%ymm4\n\t"
  57.         "    vshufps      $0xee, %%ymm2, %%ymm3, %%ymm2\n\t"
  58.         "    vshufps      $0x44, %%ymm1, %%ymm0, %%ymm3\n\t"
  59.         "    vshufps      $0xee, %%ymm1, %%ymm0, %%ymm1\n\t"
  60.         "    vinsertf128  $0x01, %%xmm2, %%ymm4, %%ymm2\n\t"
  61.         "    vinsertf128  $0x01, %%xmm1, %%ymm3, %%ymm3\n\t"
  62.        
  63.         // absolute values and zero check
  64.         "    vandps       %%ymm9, %%ymm2, %%ymm4\n\t" // abs(x)
  65.         "    vcmpeqps     %%ymm8, %%ymm2, %%ymm0\n\t" // x == 0?
  66.         "    vandps       %%ymm9, %%ymm3, %%ymm6\n\t" // abs(y)
  67.         "    vcmpeqps     %%ymm8, %%ymm3, %%ymm1\n\t" // y == 0?
  68.  
  69.         // compute argument a to polynomial
  70.         "    vmaxps       %%ymm4, %%ymm6, %%ymm5\n\t" // max(abs(x), abs(y))
  71.         "    vandps       %%ymm0, %%ymm1, %%ymm1\n\t" // x == 0 && y == 0
  72.         "    vminps       %%ymm4, %%ymm6, %%ymm0\n\t" // min(abs(x), abs(y))
  73.         "    vcmpltps     %%ymm6, %%ymm4, %%ymm4\n\t" // abs(x) < abs(y)
  74.         "    vrcpps       %%ymm5, %%ymm7        \n\t" // compute 1/max(abs(x), abs(y))
  75.         "    vmulps       %%ymm5, %%ymm7, %%ymm5\n\t"  
  76.         "    vcmpltps     %%ymm8, %%ymm2, %%ymm2\n\t" // x < 0
  77.  
  78.         // compute polynomial
  79.         "    vmulps       %%ymm5, %%ymm7, %%ymm5\n\t"
  80.         "    vaddps       %%ymm7, %%ymm7, %%ymm7\n\t"
  81.         "    vsubps       %%ymm5, %%ymm7, %%ymm7\n\t"
  82.         "    vmulps       %%ymm7, %%ymm0, %%ymm5\n\t"
  83.         "    vmulps       %%ymm5, %%ymm5, %%ymm7\n\t"
  84.         "    vmulps       %%ymm15,%%ymm7, %%ymm0\n\t"
  85.         "    vaddps       %%ymm14,%%ymm0, %%ymm0\n\t"
  86.         "    vmulps       %%ymm7, %%ymm0, %%ymm0\n\t"
  87.         "    vaddps       %%ymm13,%%ymm0, %%ymm0\n\t"
  88.         "    vmulps       %%ymm7, %%ymm0, %%ymm0\n\t"
  89.  
  90.         // finish up
  91.         "    vcmpneqps    %%ymm8, %%ymm3, %%ymm7\n\t"
  92.         "    vaddps       %%ymm12,%%ymm0, %%ymm0\n\t"
  93.         "    vandps       %%ymm4, %%ymm7, %%ymm4\n\t"
  94.         "    vandps       %%ymm2, %%ymm7, %%ymm2\n\t"
  95.         "    vmulps       %%ymm5, %%ymm0, %%ymm0\n\t"
  96.         "    vsubps       %%ymm0, %%ymm11,%%ymm5\n\t"
  97.         "    vblendvps    %%ymm4, %%ymm5, %%ymm0, %%ymm0\n\t"
  98.         "    vsubps       %%ymm0, %%ymm10,%%ymm5\n\t"
  99.         "    vblendvps    %%ymm2, %%ymm5, %%ymm0, %%ymm0\n\t"
  100.         "    vcmpleps     %%ymm3, %%ymm8, %%ymm2\n\t"
  101.         "    vcmpltps     %%ymm8, %%ymm3, %%ymm3\n\t"
  102.         "    vbroadcastss %[signbit], %%ymm8\n\t"
  103.         "    vxorps       %%ymm8, %%ymm0, %%ymm4\n\t"
  104.         "    vandps       %%ymm2, %%ymm7, %%ymm2\n\t"
  105.         "    vandps       %%ymm3, %%ymm7, %%ymm7\n\t"
  106.         "    vblendvps    %%ymm1, %%ymm8, %%ymm4, %%ymm1\n\t"
  107.         "    vblendvps    %%ymm7, %%ymm4, %%ymm1, %%ymm1\n\t"
  108.         "    vblendvps    %%ymm2, %%ymm0, %%ymm1, %%ymm1\n\t"
  109.  
  110.         // store to result
  111.         "    vmovups     %%ymm1,-0x20(%%rcx)\n\t"
  112.  
  113.         // are we done?
  114.         "    cmp    %[iters],%%r8\n\t"
  115.         "    jb     .LOOP%=\n\t"
  116.         VZU
  117.         :
  118.         : [posnan]  "m" (posnan),  [coefa] "m" (coefa),  [coefb] "m"  (coefb),
  119.           [coefc]   "m" (coefc),   [one]   "m" (one),    [mpi_2] "m" (mpi_2),  [mpi]   "m"  (mpi),
  120.           [signbit] "m" (signbit), [in]    "r" (in),     [out]   "r" (out),    [iters] "er" (iters)
  121.         : MMREG(0), MMREG(1), MMREG(2),  MMREG(3),  MMREG(4),  MMREG(5),  MMREG(6),  MMREG(7),
  122.           MMREG(8), MMREG(9), MMREG(10), MMREG(11), MMREG(12), MMREG(13), MMREG(14), MMREG(15),
  123.           "rax", "rcx", "r8", "memory"
  124.     );
  125.  
  126.     // finish remainder
  127.     if (rem > 0) {
  128.         in  += iters*16;
  129.         out += iters*8;
  130.  
  131.         for (size_t ii=0; ii < rem; ii++) {
  132.             out[ii] = fast_atan2(in[2*ii+1], in[2*ii+0]);
  133.         }
  134.     }
  135. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement