title: Why can a T* be passed in register, but a unique_ptr<T> cannot?
body: <p>I'm watching Chandler Carruth's talk in CppCon 2019:</p>
  
  <p><a href="https://www.youtube.com/watch?v=rHIkrotSwcc" rel="noreferrer">There are no Zero-Cost Abstractions</a></p>
  
  <p>in it, he gives the example of how he was surprised by just how much overhead you incur by using an <code>std::unique_ptr&lt;int&gt;</code> over an <code>int*</code>; that segment starts about at time point 17:25.</p>
  
  <p>You can have a look at the <a href="https://godbolt.org/z/5yv_41" rel="noreferrer">compilation results</a> of his example pair-of-snippets (godbolt.org) - to witness that, indeed, it seems the compiler is not willing to pass the unique_ptr value - which in fact in the bottom line is just an address - inside a register, only in straight memory.</p>
  
  <p>One of the points Mr. Carruth makes at around 27:00 is that the C++ ABI requires by-value parameters (some but not all; perhaps - non-primitive types? non-trivially-constructible types?) to be passed in-memory rather than within a register.</p>
  
  <p>My questions:</p>
  
  <ol>
  <li>Is this actually an ABI requirement on some platforms? (which?) Or maybe it's just some pessimization in certain scenarios?</li>
  <li>Why is the ABI like that? That is, if the fields of a struct/class fit within registers, or even a single register - why should we not be able to pass it within that register?</li>
  <li>Has the C++ standards committee discussed this point in recent years, or ever?</li>
  </ol>
  
  <hr>
  
  <p>PS - So as not to leave this question with no code:</p>
  
  <p>Plain pointer:</p>
  
  <pre><code>void bar(int* ptr) noexcept;
  void baz(int* ptr) noexcept;
  
  void foo(int* ptr) noexcept {
      if (*ptr &gt; 42) {
          bar(ptr); 
          *ptr = 42; 
      }
      baz(ptr);
  }
  </code></pre>
  
  <p>Unique pointer:</p>
  
  <pre><code>using std::unique_ptr;
  void bar(int* ptr) noexcept;
  void baz(unique_ptr&lt;int&gt; ptr) noexcept;
  
  void foo(unique_ptr&lt;int&gt; ptr) noexcept {
      if (*ptr &gt; 42) { 
          bar(ptr.get());
          *ptr = 42; 
      }
      baz(std::move(ptr));
  }
  </code></pre>