title: What's So Difficult About `uint64_t`? (Conversion Assembly From `float`)
body: <p>I am in a situation where I need to compute something like <code>size_t s=(size_t)floorf(f);</code>.  That is, the argument is a float, but it has an integer value (assume <code>floorf(f)</code> is small enough to be represented exactly).  While optimizing this, I discovered something interesting.</p>
  
  <p>Here are some conversions from <code>float</code> to integers (GCC 5.2.0 -O3).  For clarity, the conversion given is the return value of a test function.</p>
  
  <p>Here's <code>int32_t x=(int32_t)f</code>:</p>
  
  <pre><code>    cvttss2si   eax, xmm0
      ret
  </code></pre>
  
  <p>Here's <code>uint32_t x=(uint32_t)f</code>:</p>
  
  <pre><code>    cvttss2si   rax, xmm0
      ret
  </code></pre>
  
  <p>Here's <code>int64_t x=(int64_t)f</code>:</p>
  
  <pre><code>    cvttss2si   rax, xmm0
      ret
  </code></pre>
  
  <p>Last, here's <code>uint64_t x=(uint64_t)f;</code>:</p>
  
  <pre><code>    ucomiss xmm0, DWORD PTR .LC2[rip]
      jnb .L4
      cvttss2si   rax, xmm0
      ret
  .L4:
      subss   xmm0, DWORD PTR .LC2[rip]
      movabs  rdx, -9223372036854775808
      cvttss2si   rax, xmm0
      xor rax, rdx
      ret
  
  .LC2:
      .long   1593835520
  </code></pre>
  
  <p>This last one is much more complex than the others.  Moreover, Clang and MSVC behave similarly.  For your convenience, I've translated it into pseudo-C:</p>
  
  <pre><code>float lc2 = (float)(/* 2^63 - 1 */);
  if (f&lt;lc2) {
      return (uint64_t)f;
  } else {
      f -= lc2;
      uint64_t temp = (uint64_t)f;
      temp ^= /* 2^63 */; //Toggle highest bit
      return temp;
  }
  </code></pre>
  
  <p>This looks like it is trying to compute the first overflow mod 64 correctly.  That seems kindof bogus, since <a href="http://www.jaist.ac.jp/iscenter-new/mpc/altix/altixdata/opt/intel/vtune/doc/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc68.htm">the documentation for cvttss2si</a> tells me that if an overflow happens (at 2^32, not 2^64), "the indefinite integer value (80000000H) is returned".</p>
  
  <p>My questions:</p>
  
  <ol>
  <li>What is this really doing, and <em>why?</em></li>
  <li>Why wasn't something similar done for the other integer types?</li>
  <li>How can I change the conversion so as to produce similar code (only output lines 3 and 4) (again, assume that the value is exactly representable)?</li>
  </ol>