mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 19:06:05 +00:00

Set the writable and dead_on_unwind attributes for sret arguments. These indicate that the argument points to writable memory (and it's legal to introduce spurious writes to it on entry to the function) and that the argument memory will not be used if the call unwinds. This enables additional MemCpyOpt/DSE/LICM optimizations.
84 lines
2.6 KiB
C++
84 lines
2.6 KiB
C++
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm %s -o - -disable-llvm-passes | FileCheck %s
|
|
|
|
#include "Inputs/coroutine.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace std {
|
|
|
|
struct nothrow_t {};
|
|
constexpr nothrow_t nothrow = {};
|
|
|
|
} // end namespace std
|
|
|
|
// Required when get_return_object_on_allocation_failure() is defined by
|
|
// the promise.
|
|
void* operator new(__SIZE_TYPE__ __sz, const std::nothrow_t&) noexcept;
|
|
void operator delete(void* __p, const std::nothrow_t&) noexcept;
|
|
|
|
|
|
template <class RetObject>
|
|
struct promise_type {
|
|
RetObject get_return_object();
|
|
suspend_always initial_suspend();
|
|
suspend_never final_suspend() noexcept;
|
|
void return_void();
|
|
static void unhandled_exception();
|
|
};
|
|
|
|
struct coro {
|
|
using promise_type = promise_type<coro>;
|
|
coro(coro const&);
|
|
struct Impl;
|
|
Impl *impl;
|
|
};
|
|
|
|
// Verify that the RVO is applied.
|
|
// CHECK-LABEL: define{{.*}} void @_Z1fi(ptr dead_on_unwind noalias writable sret(%struct.coro) align 8 %agg.result, i32 noundef %0)
|
|
coro f(int) {
|
|
// CHECK: %call = call noalias noundef nonnull ptr @_Znwm(
|
|
// CHECK-NEXT: br label %[[CoroInit:.*]]
|
|
|
|
// CHECK: {{.*}}[[CoroInit]]:
|
|
// CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro) align 8 %agg.result
|
|
co_return;
|
|
}
|
|
|
|
|
|
template <class RetObject>
|
|
struct promise_type_with_on_alloc_failure {
|
|
static RetObject get_return_object_on_allocation_failure();
|
|
RetObject get_return_object();
|
|
suspend_always initial_suspend();
|
|
suspend_never final_suspend() noexcept;
|
|
void return_void();
|
|
static void unhandled_exception();
|
|
};
|
|
|
|
struct coro_two {
|
|
using promise_type = promise_type_with_on_alloc_failure<coro_two>;
|
|
coro_two(coro_two const&);
|
|
struct Impl;
|
|
Impl *impl;
|
|
};
|
|
|
|
// Verify that the RVO is applied.
|
|
// CHECK-LABEL: define{{.*}} void @_Z1hi(ptr dead_on_unwind noalias writable sret(%struct.coro_two) align 8 %agg.result, i32 noundef %0)
|
|
coro_two h(int) {
|
|
|
|
// CHECK: %call = call noalias noundef ptr @_ZnwmRKSt9nothrow_t
|
|
// CHECK-NEXT: %[[CheckNull:.*]] = icmp ne ptr %call, null
|
|
// CHECK-NEXT: br i1 %[[CheckNull]], label %[[InitOnSuccess:.*]], label %[[InitOnFailure:.*]]
|
|
|
|
// CHECK: {{.*}}[[InitOnFailure]]:
|
|
// CHECK-NEXT: call void @{{.*get_return_object_on_allocation_failureEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result
|
|
// CHECK-NEXT: br label %[[RetLabel:.*]]
|
|
|
|
// CHECK: {{.*}}[[InitOnSuccess]]:
|
|
// CHECK: call void @{{.*get_return_objectEv}}(ptr dead_on_unwind writable sret(%struct.coro_two) align 8 %agg.result
|
|
|
|
// CHECK: [[RetLabel]]:
|
|
// CHECK-NEXT: ret void
|
|
co_return;
|
|
}
|