title: Why does GCC call libc's sqrt() without using its result?
body: <p>Using GCC 6.3, the following C++ code:</p>
  
  <pre><code>#include &lt;cmath&gt;
  #include &lt;iostream&gt;
  
  void norm(double r, double i)
  {
      double n = std::sqrt(r * r + i * i);
      std::cout &lt;&lt; "norm = " &lt;&lt; n;
  }
  </code></pre>
  
  <p>generates the following x86-64 assembly:</p>
  
  <pre><code>norm(double, double):
          mulsd   %xmm1, %xmm1
          subq    $24, %rsp
          mulsd   %xmm0, %xmm0
          addsd   %xmm1, %xmm0
          pxor    %xmm1, %xmm1
          ucomisd %xmm0, %xmm1
          sqrtsd  %xmm0, %xmm2
          movsd   %xmm2, 8(%rsp)
          jbe     .L2
          call    sqrt
  .L2:
          movl    std::cout, %edi
          movl    $7, %edx
          movl    $.LC1, %esi
          call    std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp; std::__ostream_insert&lt;char, std::char_traits&lt;char&gt; &gt;(std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp;, char const*, long)
          movsd   8(%rsp), %xmm0
          movl    std::cout, %edi
          addq    $24, %rsp
          jmp     std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp; std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;::_M_insert&lt;double&gt;(double)
  </code></pre>
  
  <p>For the call to <code>std::sqrt</code>, GCC first does it using <code>sqrtsd</code> and saves the result on to the stack. If it overflows, it then calls the libc <code>sqrt</code> function. But it never saves the <code>xmm0</code> after that and before the second call to <code>operator&lt;&lt;</code>, it restores the value from the stack (because <code>xmm0</code> was lost with the first call to <code>operator&lt;&lt;</code>).</p>
  
  <p>With a simpler <code>std::cout &lt;&lt; n;</code>, it's even more obvious:</p>
  
  <pre><code>subq    $24, %rsp
  movsd   %xmm1, 8(%rsp)
  call    sqrt
  movsd   8(%rsp), %xmm1
  movl    std::cout, %edi
  addq    $24, %rsp
  movapd  %xmm1, %xmm0
  jmp     std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;&amp; std::basic_ostream&lt;char, std::char_traits&lt;char&gt; &gt;::_M_insert&lt;double&gt;(double)
  </code></pre>
  
  <p>Why is GCC not using the <code>xmm0</code> value computed by libc <code>sqrt</code>?</p>