title: SSE/NEON table lookup optimization
body: <p>i have the following lookup and interpolation code to optimize. (float table with size 128)
  It will be used with an Intel compiler on windows, GCC on OSX and GCC with neon OSX.</p>
  
  <pre><code>for(unsigned int i = 0 ; i &lt; 4 ; i++)
  {
      const int iIdx = (int)m_fIndex[i];
      const float frac = m_fIndex - iIdx;
      m_fResult[i] = sftable[iIdx].val + sftable[iIdx].val2 * frac;
  }
  </code></pre>
  
  <p>i vecorized everything with sse/neon. (the macros convert into sse/neon instructions)</p>
  
  <pre><code>VEC_INT iIdx = VEC_FLOAT2INT(m_fIndex);
  VEC_FLOAT frac = VEC_SUB(m_fIndex ,VEC_INT2FLOAT(iIdx);
  m_fResult[0] = sftable[iIdx[0]].val2;
  m_fResult[1] = sftable[iIdx[1]].val2;
  m_fResult[2] = sftable[iIdx[2]].val2;
  m_fResult[3] = sftable[iIdx[3]].val2;
  m_fResult=VEC_MUL( m_fResult,frac);
  frac[0] = sftable[iIdx[0]].val1;
  frac[1] = sftable[iIdx[1]].val1;
  frac[2] = sftable[iIdx[2]].val1;
  frac[3] = sftable[iIdx[3]].val1;
  m_fResult=VEC_ADD( m_fResult,frac);
  </code></pre>
  
  <p>i think that the table access and move into aligned memory is the real bottleneck here.
  I am not good with assembler but there are a lot of unpcklps and mov:</p>
  
  <pre><code>10026751  mov         eax,dword ptr [esp+4270h] 
  10026758  movaps      xmm3,xmmword ptr [eax+16640h] 
  1002675F  cvttps2dq   xmm5,xmm3 
  10026763  cvtdq2ps    xmm4,xmm5 
  10026766  movd        edx,xmm5 
  1002676A  movdqa      xmm6,xmm5 
  1002676E  movdqa      xmm1,xmm5 
  10026772  psrldq      xmm6,4 
  10026777  movdqa      xmm2,xmm5 
  1002677B  movd        ebx,xmm6 
  1002677F  subps       xmm3,xmm4 
  10026782  psrldq      xmm1,8 
  10026787  movd        edi,xmm1 
  1002678B  psrldq      xmm2,0Ch 
  10026790  movdqa      xmmword ptr [esp+4F40h],xmm5 
  10026799  mov         ecx,dword ptr [eax+edx*8+10CF4h] 
  100267A0  movss       xmm0,dword ptr [eax+edx*8+10CF4h] 
  100267A9  mov         dword ptr [eax+166B0h],ecx 
  100267AF  movd        ecx,xmm2 
  100267B3  mov         esi,dword ptr [eax+ebx*8+10CF4h] 
  100267BA  movss       xmm4,dword ptr [eax+ebx*8+10CF4h] 
  100267C3  mov         dword ptr [eax+166B4h],esi 
  100267C9  mov         edx,dword ptr [eax+edi*8+10CF4h] 
  100267D0  movss       xmm7,dword ptr [eax+edi*8+10CF4h] 
  100267D9  mov         dword ptr [eax+166B8h],edx 
  100267DF  movss       xmm1,dword ptr [eax+ecx*8+10CF4h] 
  100267E8  unpcklps    xmm0,xmm7 
  100267EB  unpcklps    xmm4,xmm1 
  100267EE  unpcklps    xmm0,xmm4 
  100267F1  mulps       xmm0,xmm3 
  100267F4  movaps      xmmword ptr [eax+166B0h],xmm0 
  100267FB  mov         ebx,dword ptr [esp+4F40h] 
  10026802  mov         edi,dword ptr [esp+4F44h] 
  10026809  mov         ecx,dword ptr [esp+4F48h] 
  10026810  mov         esi,dword ptr [esp+4F4Ch] 
  10026817  movss       xmm2,dword ptr [eax+ebx*8+10CF0h] 
  10026820  movss       xmm5,dword ptr [eax+edi*8+10CF0h] 
  10026829  movss       xmm3,dword ptr [eax+ecx*8+10CF0h] 
  10026832  movss       xmm6,dword ptr [eax+esi*8+10CF0h] 
  1002683B  unpcklps    xmm2,xmm3 
  1002683E  unpcklps    xmm5,xmm6 
  10026841  unpcklps    xmm2,xmm5 
  10026844  mulps       xmm2,xmm0 
  10026847  movaps      xmmword ptr [eax+166B0h],xmm2
  </code></pre>
  
  <p>When profiling there is not much benefit with the sse version on win.</p>
  
  <p>Do you have any suggestions how to improve ?
  Any side effects with neon/gcc to be expected ?</p>
  
  <p>Currently i consider just making the first part vecorized and do the tablereadout and interpolation in a loop, hoping that it will be benefit from compiler optimization.</p>