title: std::mutex::lock() produces weird (and unnecessary) asm code
body: <p>I was checking generated asm for some of my code and my eye caught some <a href="https://godbolt.org/z/tknRf6" rel="noreferrer">interesting stuff</a>:</p>
  
  <pre><code>#include &lt;mutex&gt;
  
  std::mutex m;
  
  void foo()
  {
      m.lock();
  }
  </code></pre>
  
  <p>generated asm code (x86-64 gcc 9.2, <code>-std=c++11 -O2</code>):</p>
  
  <pre><code>foo():
          mov     eax, OFFSET FLAT:_ZL28__gthrw___pthread_key_createPjPFvPvE
          test    rax, rax
          je      .L10                  // (1) we can simply bypass lock() call?
          sub     rsp, 8
          mov     edi, OFFSET FLAT:m
          call    __gthrw_pthread_mutex_lock(pthread_mutex_t*)
          test    eax, eax
          jne     .L14                  // (2) waste of space that will never be executed
          add     rsp, 8
          ret
  .L10:
          ret
  .L14:
          mov     edi, eax
          call    std::__throw_system_error(int)
  m:
          .zero   40
  </code></pre>
  
  <p>Questions:</p>
  
  <ul>
  <li>part (1) -- gcc specific: 
  
  <ul>
  <li>what it is doing? (allocating TLS entry?)</li>
  <li>how failing that operation allows us to silently bypass <code>lock()</code> call?</li>
  </ul></li>
  <li>part (2) -- looks like each compiler is affected:
  
  <ul>
  <li><code>std::mutex::lock()</code> <a href="https://en.cppreference.com/w/cpp/thread/mutex/lock" rel="noreferrer">can throw</a> according to standard</li>
  <li>... but it never does in correct code (as discussed in related SO posts), for all intents and purposes <code>std::mutex::lock()</code> is always <code>noexcept</code> in correct code</li>
  <li>is it possible to let compiler know so that it stops emitting unnecessary tests and instruction blocks (like <code>.L14</code> above)?</li>
  </ul></li>
  </ul>
  
  <p><strong>Note:</strong> I can't see how throwing from <code>std::mutex::lock()</code> is better than simply <code>abort()</code>ing. In both cases your program is screwed (no one expects it to fail), but at least in latter case you end up with considerably smaller asm code ("pay only for something you use", remember?).</p>