<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - sqrt(denormal float) gives -infinity with fast-math"
   href="https://bugs.llvm.org/show_bug.cgi?id=34994">34994</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>sqrt(denormal float) gives -infinity with fast-math
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Backend: X86
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>newtonallen3@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=19314" name="attach_19314" title="repro case">attachment 19314</a> <a href="attachment.cgi?id=19314&action=edit" title="repro case">[details]</a></span>
repro case

$ cat sqrt_denormal_fastmath.cc

#include <cmath>
#include <iostream>

__attribute__((noinline)) void print_sqrt(float val) {
  const float root = sqrt(val);
  std::cout << "sqrt(" << val << ") = " << root << std::endl;
}

int main(int argc, char** argv) {
  print_sqrt(1e-34);
  print_sqrt(1e-36);
  print_sqrt(1e-38);
  print_sqrt(1e-40);
  print_sqrt(1e-42);
  print_sqrt(1e-44);
  print_sqrt(1e-46);
}


$ clang sqrt_denormal_fastmath.cc -O2 -std=c++11 -ffast-math
$ ./a.out 
sqrt(1e-34) = 1e-17
sqrt(1e-36) = 1e-18
sqrt(1e-38) = -inf
sqrt(9.99995e-41) = -inf
sqrt(1.00053e-42) = -inf
sqrt(9.80909e-45) = -inf
sqrt(0) = 0


The computed square root is correct for normalized floats and for zero, but is
completely wrong for denormal floats (negative infinity).

The square root for denormal floats should either be approximately correct, or
perhaps just rounded to zero.

The problem here is that sqrt is computed in fast-math mode on x86 using the
reciprocal square root instruction (rsqrtss), which returns infinity for an
input value of zero *or* any denormal float. The instructions after rsqrtss fix
up the input=zero case, but don't handle the input=denormal case.

Here's the generated assembly for the sqrt instruction above
(<a href="https://godbolt.org/g/hvbKPQ">https://godbolt.org/g/hvbKPQ</a>)

        rsqrtss xmm3, xmm0
        movaps  xmm1, xmm0
        movaps  xmm4, xmm0
        movss   dword ptr [rsp + 12], xmm4 # 4-byte Spill
        mulss   xmm1, xmm3
        movss   xmm2, dword ptr [rip + .LCPI0_0] # xmm2 = mem[0],zero,zero,zero
        mulss   xmm2, xmm1
        mulss   xmm1, xmm3
        addss   xmm1, dword ptr [rip + .LCPI0_1]
        mulss   xmm1, xmm2
        xorps   xmm0, xmm0
        cmpeqss xmm0, xmm4
        andnps  xmm0, xmm1

The last three instructions (xorps, cmpeqss, andnps) check if the input was
zero and set the output to zero if so. However, there's no check for whether
the input was denormal.

Relevant code:
 - lib/Target/X86/X86ISelLowering.cpp: X86TargetLowering::getSqrtEstimate()</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>