<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>