title: Why A / <constant-int> is faster when A is unsigned vs signed?
body: <p>I have been reading through the <a href="https://en.wikibooks.org/wiki/Optimizing_C++" rel="nofollow noreferrer">Optimizing C++ wikibook</a>. In the <a href="https://en.wikibooks.org/wiki/Optimizing_C++/Code_optimization/Faster_operations" rel="nofollow noreferrer">faster operations chapter</a> one of the advice is as follows:</p>
  
  <blockquote>
    <p><strong>Integer division by a constant</strong></p>
    
    <p>When you divide an integer (that is known to be positive or zero) by a
    constant, convert the integer to unsigned.</p>
    
    <p>If s is a signed integer, u is an unsigned integer, and C is a
    constant integer expression (positive or negative), the operation s /
    C is slower than u / C, and s % C is slower than u % C. This is most
    significant when C is a power of two, but in all cases, the sign must
    be taken into account during division.</p>
    
    <p>The conversion from signed to unsigned, however, is free of charge, as
    it is only a reinterpretation of the same bits. Therefore, if s is a
    signed integer that you know to be positive or zero, you can speed up
    its division using the following (equivalent) expressions: (unsigned)s
    / C and (unsigned)s % C.</p>
  </blockquote>
  
  <p>I tested this statement with gcc and the <code>u / C</code> expression seems to perform consistently better than the <code>s / c</code></p>
  
  <p>The following example is also provided below:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;chrono&gt;
  #include &lt;cstdlib&gt;
  #include &lt;vector&gt;
  #include &lt;numeric&gt;
  
  using namespace std;
  
  int main(int argc, char *argv[])
  {
  
      constexpr int vsize = 1e6;
      std::vector&lt;int&gt; x(vsize);
      std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
  
      constexpr int a = 5;
  
    auto start_signed = std::chrono::system_clock::now();
    int sum_signed = 0;
      for ([[gnu::unused]] auto  i : x)
      {
          // signed is by default
          int v = rand() % 30 + 1985;   // v in the range 1985-2014
  
          sum_signed += v / a;
      }
    auto end_signed = std::chrono::system_clock::now();
  
    auto start_unsigned = std::chrono::system_clock::now();
    int sum_unsigned = 0;
      for ([[gnu::unused]] auto  i : x)
      {
          int v = rand() % 30 + 1985;   // v in the range 1985-2014
          sum_unsigned += static_cast&lt;unsigned int&gt;(v) / a;
      }
    auto end_unsigned = std::chrono::system_clock::now();
  
    // signed
    std::chrono::duration&lt;double&gt; diff_signed = end_signed - start_signed;
    std::cout &lt;&lt; "sum_signed: " &lt;&lt; sum_signed &lt;&lt; std::endl;
    std::cout &lt;&lt; "Time it took SIGNED: " &lt;&lt; diff_signed.count() * 1000 &lt;&lt; "ms" &lt;&lt; std::endl;
  
    // unsigned
    std::chrono::duration&lt;double&gt; diff_unsigned = end_unsigned - start_unsigned;
    std::cout &lt;&lt; "sum_unsigned: " &lt;&lt; sum_unsigned &lt;&lt; std::endl;
    std::cout &lt;&lt; "Time it took UNSIGNED: " &lt;&lt; diff_unsigned.count() * 1000 &lt;&lt; "ms" &lt;&lt; std::endl;
  
    return 0;
  }
  </code></pre>
  
  <p>You can compile and run the example here: <a href="http://cpp.sh/8kie3" rel="nofollow noreferrer">http://cpp.sh/8kie3</a></p>
  
  <p>Why is this happening?</p>