<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - [x86-64] missed optimization: missed tail call in placement-new"
   href="https://bugs.llvm.org/show_bug.cgi?id=51000">51000</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[x86-64] missed optimization: missed tail call in placement-new
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>arthur.j.odwyer@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>// <a href="https://godbolt.org/z/sqz6eaezs">https://godbolt.org/z/sqz6eaezs</a>
#include <new>
struct T {
    int x;
    T(int) noexcept;
    ~T();
};
T factory(int) noexcept;
alignas(T) char buffer[sizeof(T)];
void placement_new() {
    ::new ((void*)buffer) T(42);
}
void placement_call() {
    ::new ((void*)buffer) T(factory(42));
}

clang++ -O2 -std=c++20 -emit-llvm test.cpp

The dumped LLVM code for this does correctly have "tail call" in both cases:

  define dso_local void @_Z13placement_newv() local_unnamed_addr #0 !dbg !18 {
    tail call void @_ZN1TC1Ei(%struct.T* nonnull align 4 dereferenceable(4)
bitcast ([4 x i8]* @buffer to %struct.T*), i32 42) #2, !dbg !21
    ret void, !dbg !22
  }
  define dso_local void @_Z14placement_callv() local_unnamed_addr #0 !dbg !23 {
    tail call void @_Z7factoryi(%struct.T* sret(%struct.T) align 4 bitcast ([4
x i8]* @buffer to %struct.T*), i32 42) #2, !dbg !24
    ret void, !dbg !25
  }

However, somewhere between the LLVM code and the backend codegen, the compiler
is failing to generate an actual `jmp` tail call for `placement_call` the way
it's able to for `placement_new`.

  _Z13placement_newv: # @_Z13placement_newv
    movl $buffer, %edi
    movl $42, %esi
    jmp _ZN1TC1Ei # TAILCALL
  _Z14placement_callv: # @_Z14placement_callv
    pushq %rax
    movl $buffer, %edi
    movl $42, %esi
    callq _Z7factoryi
    popq %rax
    retq

Reproduces on x86-64, RISCV-32, RISCV-64, ARMv7-a. So it's somehow happening
after -emit-llvm, but not backend-arch-specific??

Note that right now GCC has the same symptom; but ICC and MSVC both get this
right and generate tail-calls appropriately in both cases. So this isn't any
obscure C++ corner case AFAICT; seems it's truly just a missed optimization.

Some other (possibly related) missed-tail-call bugs: PR50138, PR48508, PR45591,
PR13826.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>