title: Why is this sequence of instructions faster?
body: <p>I was comparing GCC and Clang output for the evaluation of a floating point expression and stumbled upon a performance difference I couldn't explain.</p>
  
  <p>Source code</p>
  
  <pre><code>float evaluate(float a, float b) {
      return (a - b + 1.0f) * (a - b) * (a - b - 1.0f);
  }
  </code></pre>
  
  <p>GCC 7.2 (-std=c++1y -O2) produced</p>
  
  <pre><code>evaluate(float, float):
    subss xmm0, xmm1
    movss xmm2, DWORD PTR .LC0[rip]
    movaps xmm1, xmm0
    addss xmm1, xmm2
    mulss xmm1, xmm0
    subss xmm0, xmm2
    mulss xmm0, xmm1
    ret
  .LC0:
    .long 1065353216
  </code></pre>
  
  <p>While Clang 5.0.0 (-std=c++1y -O2) produced</p>
  
  <pre><code>.LCPI0_0:
    .long 1065353216 # float 1
  .LCPI0_1:
    .long 3212836864 # float -1
  evaluate(float, float): # @evaluate(float, float)
    subss xmm0, xmm1
    movss xmm1, dword ptr [rip + .LCPI0_0] # xmm1 = mem[0],zero,zero,zero
    addss xmm1, xmm0
    mulss xmm1, xmm0
    addss xmm0, dword ptr [rip + .LCPI0_1]
    mulss xmm0, xmm1
    ret
  </code></pre>
  
  <p>GCC seems to prefer <code>movaps</code> over <code>movss</code>, even though <code>movss</code> is sufficient in this case. As noted by <a href="https://stackoverflow.com/users/224132/peter-cordes" title="Peter Cordes">Peter Cordes</a>, this is actually better as using <code>movaps</code> avoid stalls from partial updates to XMM registers.</p>
  
  <p>GCC uses three instead of two XMM registers.</p>
  
  <p>Clang uses two constants and only addss for them rather than only having one and using subss to subtract one from a register.</p>
  
  <p>I graphed the instruction-level true dependencies for these sequences and Clang's is one level shorter.</p>
  
  <p>Performance-wise, quite differently from what I expected, <strong>GCC version is about 30% faster</strong>.</p>
  
  <p>I've tested this on Intel (Broadwell) and AMD (Bulldozer) CPUs and I don't see why the GCC code would be any faster here.</p>
  
  <p><strong>The original benchmark used bad inline asm code. After creating two object files (one with GCC, one with Clang) for the C++ code of the function of interest and linking against them with GCC the performance difference disappeared.</strong> Peter Cordes has hinted that this might be because of <code>-O1</code> leaving out the <code>.p2align</code> directives.</p>
  
  <p>I looked at the compiler output of the new benchmarking method and asserted that both implementations of <code>evaluate()</code> have the exact same code as above and that the compiler is actually calling them.</p>