title: Optimization barrier for microbenchmarks in MSVC: tell the optimizer you clobber memory?
body: <p>Chandler Carruth introduced two functions in his <a href="https://www.youtube.com/watch?v=nXaxk27zwlk" rel="noreferrer">CppCon2015 talk</a> that can be used to do some fine-grained inhibition of the optimizer. They are useful to write micro-benchmarks that the optimizer won't simply nuke into meaninglessness. </p>
  
  <pre><code>void clobber() {
    asm volatile("" : : : "memory");
  }
  
  void escape(void* p) {
    asm volatile("" : : "g"(p) : "memory");
  }    
  </code></pre>
  
  <p>These use inline assembly statements to change the assumptions of the optimizer.</p>
  
  <p>The assembly statement in <code>clobber</code> states that the assembly code in it can read and write anywhere in memory. The actual assembly code is empty, but the optimizer won't look into it because it's <code>asm volatile</code>. It believes it when we tell it the code might read and write everywhere in memory. This effectively prevents the optimizer from reordering or discarding memory writes prior to the call to <code>clobber</code>, and forces memory reads after the call to <code>clobber</code>&dagger;.</p>
  
  <p>The one in <code>escape</code>, additionally makes the pointer <code>p</code> visible to the assembly block. Again, because the optimizer won't look into the actual inline assembly code that code can be empty, and the optimizer will still assume that the block uses the address pointed by the pointer <code>p</code>. This effectively forces whatever <code>p</code> points to be in memory and not not in a register, because the assembly block might perform a read from that address.</p>
  
  <p>(This is important because the <code>clobber</code> function won't force reads nor writes for anything that the compilers decides to put in a register, since the assembly statement in <code>clobber</code> doesn't state that anything in particular must be visible to the assembly.)</p>
  
  <p>All of this happens without any additional code being generated directly by these "barriers".  They are purely compile-time artifacts.</p>
  
  <p>These use language extensions supported in GCC and in Clang, though. Is there a way to have similar behaviour when using MSVC? </p>
  
  <hr>
  
  <p>&dagger; To understand why the optimizer has to think this way, imagine if the assembly block were a loop adding 1 to every byte in memory.</p>