title: Should std::atomic<int*>::load be doing a compare-and-swap loop?
body: <p><strong>Summary</strong>: I had expected that <code>std::atomic&lt;int*&gt;::load</code> with <code>std::memory_order_relaxed</code> would be close to the performance of just loading a pointer directly, at least when the loaded value rarely changes. I saw far worse performance for the atomic load than a normal load on Visual Studio C++ 2012, so I decided to investigate. It turns out that the atomic load is implemented as a <a href="http://en.wikipedia.org/wiki/Compare-and-swap" rel="nofollow">compare-and-swap</a> loop, which I suspect is not the fastest possible implementation.</p>
  
  <p><strong>Question</strong>: Is there some reason that <code>std::atomic&lt;int*&gt;::load</code> needs to do a compare-and-swap loop?</p>
  
  <p><strong>Background</strong>: I believe that MSVC++ 2012 is doing a compare-and-swap loop on atomic load of a pointer based on this test program:</p>
  
  <pre><code>#include &lt;atomic&gt;
  #include &lt;iostream&gt;
  
  template&lt;class T&gt;
  __declspec(noinline) T loadRelaxed(const std::atomic&lt;T&gt;&amp; t) {
    return t.load(std::memory_order_relaxed);
  }
  
  int main() {
    int i = 42;
    char c = 42;
    std::atomic&lt;int*&gt; ptr(&amp;i);
    std::atomic&lt;int&gt; integer;
    std::atomic&lt;char&gt; character;
    std::cout
      &lt;&lt; *loadRelaxed(ptr) &lt;&lt; ' '
      &lt;&lt; loadRelaxed(integer) &lt;&lt; ' '
      &lt;&lt; loadRelaxed(character) &lt;&lt; std::endl;
    return 0;
  }
  </code></pre>
  
  <p>I'm using a <code>__declspec(noinline)</code> function in order to isolate the assembly instructions related to the atomic load. I made a new MSVC++ 2012 project, added an x64 platform, selected the release configuration, ran the program in the debugger and looked at the disassembly. Turns out that both <code>std::atomic&lt;char&gt;</code> and <code>std::atomic&lt;int&gt;</code> parameters end up giving the same call to <code>loadRelaxed&lt;int&gt;</code> - this must be something the optimizer did. Here is the disassembly of the two loadRelaxed instantiations that get called:</p>
  
  <p><strong><code>loadRelaxed&lt;int * __ptr64&gt;</code></strong></p>
  
  <pre><code>000000013F4B1790  prefetchw   [rcx]  
  000000013F4B1793  mov         rax,qword ptr [rcx]  
  000000013F4B1796  mov         rdx,rax  
  000000013F4B1799  lock cmpxchg qword ptr [rcx],rdx  
  000000013F4B179E  jne         loadRelaxed&lt;int * __ptr64&gt;+6h (013F4B1796h)  
  </code></pre>
  
  <p><strong><code>loadRelaxed&lt;int&gt;</code></strong></p>
  
  <pre><code>000000013F3F1940  prefetchw   [rcx]  
  000000013F3F1943  mov         eax,dword ptr [rcx]  
  000000013F3F1945  mov         edx,eax  
  000000013F3F1947  lock cmpxchg dword ptr [rcx],edx  
  000000013F3F194B  jne         loadRelaxed&lt;int&gt;+5h (013F3F1945h)  
  </code></pre>
  
  <p>The instruction <code>lock cmpxchg</code> is atomic <a href="http://en.wikipedia.org/wiki/Compare-and-swap" rel="nofollow">compare-and-swap</a> and we see here that the code for atomically loading a <code>char</code>, an <code>int</code> or an <code>int*</code> is a compare-and-swap loop. I also built this code for 32-bit x86 and that implementation is still based on <code>lock cmpxchg</code>.</p>
  
  <p><strong>Question</strong>: Is there some reason that <code>std::atomic&lt;int*&gt;::load</code> needs to do a compare-and-swap loop?</p>