title: LLVM/Clang generating useless-looking instructions
body: <p>If I write this code:</p>
  
  <pre><code>void loop1(int N, double* R, double* A, double* B) {
      for (int i = 0; i &lt; N; i += 1) {
          R[i] = A[i] + B[i];
      }
  }
  </code></pre>
  
  <p>Clang (<code>-O3</code>) generates the following x64 ASM as part of an unrolled version of the loop (<a href="https://godbolt.org/z/KpUofx" rel="nofollow noreferrer">Compiler Explorer</a>):</p>
  
  <pre><code>.LBB0_14:
      movupd  xmm0, xmmword ptr [rdx + 8*rax]
      movupd  xmm1, xmmword ptr [rdx + 8*rax + 16]
      movupd  xmm2, xmmword ptr [rcx + 8*rax]
      addpd   xmm2, xmm0
      movupd  xmm0, xmmword ptr [rcx + 8*rax + 16]
      addpd   xmm0, xmm1
      movupd  xmmword ptr [rsi + 8*rax], xmm2
      movupd  xmmword ptr [rsi + 8*rax + 16], xmm0
  </code></pre>
  
  <p><code>rdx</code> and <code>rcx</code> are holding my input pointers (<code>A</code>/<code>B</code>), <code>rsi</code> is the output (<code>R</code>), and <code>rax</code> is an offset counter.  So it's loading two pairs of inputs/outputs at a time, adding them using SIMD instructions, and writing them to the output - so far so good.</p>
  
  <p>If instead I write the following:</p>
  
  <pre><code>void loop2(int N, double* R, double* A, double* B) {
      for (int i = 0; i &lt; N; i += 2) {
          R[i] = A[i] + B[i];
          R[i + 1] = A[i + 1] + B[i + 1];
      }
  }
  </code></pre>
  
  <p>LLVM generates the following (<a href="https://godbolt.org/z/riDoef" rel="nofollow noreferrer">Compiler Explorer</a>):</p>
  
  <pre><code>.LBB0_13:
      movupd  xmm0, xmmword ptr [rdx + 8*rdi]
      movupd  xmm1, xmmword ptr [rdx + 8*rdi + 16]
      movupd  xmm2, xmmword ptr [rcx + 8*rdi]
      addpd   xmm2, xmm0
      movupd  xmm0, xmmword ptr [rcx + 8*rdi + 16]
      addpd   xmm0, xmm1
  
      movapd  xmm1, xmm2
      unpckhpd        xmm1, xmm0      # xmm1 = xmm1[1],xmm0[1]
      unpcklpd        xmm2, xmm0      # xmm2 = xmm2[0],xmm0[0]
      movapd  xmm0, xmm2
      unpcklpd        xmm0, xmm1      # xmm0 = xmm0[0],xmm1[0]
      unpckhpd        xmm2, xmm1      # xmm2 = xmm2[1],xmm1[1]
  
      movupd  xmmword ptr [rsi + 8*rdi + 16], xmm2
      movupd  xmmword ptr [rsi + 8*rdi], xmm0
  </code></pre>
  
  <p>Spacing added for clarity, because it's that middle section with the <code>unpckhpd</code> etc. that's confusing me.  As far as I can see, the overall effect of those 6 instructions is just to swap <code>xmm0</code> and <code>xmm2</code>, which seems like a waste of time.</p>
  
  <p>Any idea why it's doing this?  And is there a way to stop it? :p</p>
  
  <hr>
  
  <p><em>EDIT</em>: I edited the ASM for <code>loop2()</code> to remove all similar blocks (and swap around the registers in the subsequent writes), and it appeared to run correctly and the same speed as <code>loop1()</code> (~40% faster)</p>