<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 - Missed optimization: std::unique_ptr destructor emits check contradicting assume / unreachable"
href="https://bugs.llvm.org/show_bug.cgi?id=39889">39889</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Missed optimization: std::unique_ptr destructor emits check contradicting assume / unreachable
</td>
</tr>
<tr>
<th>Product</th>
<td>new-bugs
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</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>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>costan@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>I've been trying to find a way to tell Clang that a std::unique_ptr's pointer
cannot be null, so the emitted destructor code does not contain an unnecessary
check. GCC's optimizer seems to be able to figure this out. MSVC's optimizer
misses this opportunity.
<a href="https://godbolt.org/z/rywaj3">https://godbolt.org/z/rywaj3</a> has my code and the compilers I've used. I will
also include the code at the end of the bug. In this example, the code
generated for Handle::~Handle(), which contains an inlined
unique_ptr<Handle>::~unique_ptr(), should not contain a test/je sequence. The
check contradicts the assumption that the unique_ptr is not null.
I tried expressing the assumption using the GCC-style __builtin_unreachable()
as well as Clang's __builtin_assume(). I tried to be more or less explicit in
the predicate -- tried ptr_, ptr_.get(), ptr_.get() != nullptr. I tried -O2,
-O3 and -Ofast.
Here is the code in the godbolt link above. The code can be simplified by
inlining the ASSUME(x) macro. I am submitting the current form so developers
can easily compare output across Clang, GCC and MSVC.
#include <memory>
#include <utility>
#if defined(__clang__)
// #define ASSUME(x) __builtin_assume(static_cast<bool>(x))
#define ASSUME(x) if(!static_cast<bool>(x)) __builtin_unreachable()
#elif defined(__GNUC__)
#define ASSUME(x) if(!static_cast<bool>(x)) __builtin_unreachable()
#elif defined(_MSC_VER)
#define ASSUME(x) __assume(static_cast<bool>(x))
#else
#error "No ASSUME definition"
#endif
struct Resource {
~Resource() noexcept;
};
class HandleBase {
public:
HandleBase() noexcept = default;
virtual ~HandleBase();
};
class Handle : public HandleBase {
const std::unique_ptr<Resource> ptr_;
public:
Handle();
~Handle() override;
};
Handle::Handle() : ptr_(std::make_unique<Resource>()) {}
Handle::~Handle() {
ASSUME(ptr_.get() != nullptr);
}</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>