summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGor Nishanov <GorNishanov@gmail.com>2017-05-23 03:46:59 +0000
committerGor Nishanov <GorNishanov@gmail.com>2017-05-23 03:46:59 +0000
commit68fe6ee7685d5100f926716933277fcfb642483b (patch)
tree12d4b964842a3fe94269a8f5ddad7546002873c6
parent5e6c542ae37efb3f174c9c2bd9afc433ecec2dfd (diff)
downloadbcm5719-llvm-68fe6ee7685d5100f926716933277fcfb642483b.tar.gz
bcm5719-llvm-68fe6ee7685d5100f926716933277fcfb642483b.zip
[coroutines] Replace all coro.frame builtins with an SSA value of coro.begin
SemaCoroutine forms expressions referring to the coroutine frame of the enclosing coroutine using coro.frame builtin. During codegen, we emit llvm.coro.begin intrinsic that returns the address of the coroutine frame. When coro.frame is emitted, we replace it with SSA value of coro.begin. llvm-svn: 303598
-rw-r--r--clang/lib/CodeGen/CGCoroutine.cpp25
-rw-r--r--clang/test/CodeGenCoroutines/coro-alloc.cpp9
-rw-r--r--clang/test/CodeGenCoroutines/coro-await.cpp6
-rw-r--r--clang/test/CodeGenCoroutines/coro-builtins.c22
4 files changed, 39 insertions, 23 deletions
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index f6d06d0bdd0..9537d924e2e 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -57,6 +57,11 @@ struct clang::CodeGen::CGCoroData {
// builtin.
llvm::CallInst *CoroId = nullptr;
+ // Stores the llvm.coro.begin emitted in the function so that we can replace
+ // all coro.frame intrinsics with direct SSA value of coro.begin that returns
+ // the address of the coroutine frame of the current coroutine.
+ llvm::CallInst *CoroBegin = nullptr;
+
// If coro.id came from the builtin, remember the expression to give better
// diagnostic. If CoroIdExpr is nullptr, the coro.id was created by
// EmitCoroutineBody.
@@ -330,8 +335,9 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
auto *Phi = Builder.CreatePHI(VoidPtrTy, 2);
Phi->addIncoming(NullPtr, EntryBB);
Phi->addIncoming(AllocateCall, AllocOrInvokeContBB);
- Builder.CreateCall(
+ auto *CoroBegin = Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::coro_begin), {CoroId, Phi});
+ CurCoro.Data->CoroBegin = CoroBegin;
CurCoro.Data->CleanupJD = getJumpDestInCurrentScope(RetBB);
{
@@ -388,6 +394,17 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
switch (IID) {
default:
break;
+ // The coro.frame builtin is replaced with an SSA value of the coro.begin
+ // intrinsic.
+ case llvm::Intrinsic::coro_frame: {
+ if (CurCoro.Data && CurCoro.Data->CoroBegin) {
+ return RValue::get(CurCoro.Data->CoroBegin);
+ }
+ CGM.Error(E->getLocStart(), "this builtin expect that __builtin_coro_begin "
+ "has been used earlier in this function");
+ auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
+ return RValue::get(NullPtr);
+ }
// The following three intrinsics take a token parameter referring to a token
// returned by earlier call to @llvm.coro.id. Since we cannot represent it in
// builtins, we patch it up here.
@@ -414,10 +431,16 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
llvm::Value *F = CGM.getIntrinsic(IID);
llvm::CallInst *Call = Builder.CreateCall(F, Args);
+ // Note: The following code is to enable to emit coroutine intrinsics by
+ // hand to experiment with coroutines in C.
// If we see @llvm.coro.id remember it in the CoroData. We will update
// coro.alloc, coro.begin and coro.free intrinsics to refer to it.
if (IID == llvm::Intrinsic::coro_id) {
createCoroData(*this, CurCoro, Call, E);
}
+ else if (IID == llvm::Intrinsic::coro_begin) {
+ if (CurCoro.Data)
+ CurCoro.Data->CoroBegin = Call;
+ }
return RValue::get(Call);
}
diff --git a/clang/test/CodeGenCoroutines/coro-alloc.cpp b/clang/test/CodeGenCoroutines/coro-alloc.cpp
index 14e429ebc22..730fc37c213 100644
--- a/clang/test/CodeGenCoroutines/coro-alloc.cpp
+++ b/clang/test/CodeGenCoroutines/coro-alloc.cpp
@@ -66,9 +66,8 @@ extern "C" void f0(global_new_delete_tag) {
// CHECK: [[InitBB]]:
// CHECK: %[[PHI:.+]] = phi i8* [ null, %{{.+}} ], [ %call, %[[AllocBB]] ]
- // CHECK: call i8* @llvm.coro.begin(token %[[ID]], i8* %[[PHI]])
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(token %[[ID]], i8* %[[PHI]])
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
// CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
// CHECK: call void @_ZdlPv(i8* %[[MEM]])
co_return;
@@ -93,7 +92,7 @@ extern "C" void f1(promise_new_tag ) {
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
// CHECK: call i8* @_ZNSt12experimental16coroutine_traitsIJv15promise_new_tagEE12promise_typenwEm(i64 %[[SIZE]])
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
// CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
// CHECK: call void @_ZdlPv(i8* %[[MEM]])
co_return;
@@ -118,7 +117,7 @@ extern "C" void f2(promise_delete_tag) {
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
// CHECK: call i8* @_Znwm(i64 %[[SIZE]])
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
// CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv18promise_delete_tagEE12promise_typedlEPv(i8* %[[MEM]])
co_return;
@@ -143,7 +142,7 @@ extern "C" void f3(promise_sized_delete_tag) {
// CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
// CHECK: call i8* @_Znwm(i64 %[[SIZE]])
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
// CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
// CHECK: %[[SIZE2:.+]] = call i64 @llvm.coro.size.i64()
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJv24promise_sized_delete_tagEE12promise_typedlEPvm(i8* %[[MEM]], i64 %[[SIZE2]])
diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp
index b0fd0129de3..8a9b9919e36 100644
--- a/clang/test/CodeGenCoroutines/coro-await.cpp
+++ b/clang/test/CodeGenCoroutines/coro-await.cpp
@@ -40,6 +40,7 @@ struct std::experimental::coroutine_traits<void> {
// CHECK-LABEL: f0(
extern "C" void f0() {
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
co_await suspend_always{};
// See if we need to suspend:
@@ -54,7 +55,6 @@ extern "C" void f0() {
// ---------------------------
// Build the coroutine handle and pass it to await_suspend
// ---------------------------
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
// CHECK: call i8* @_ZNSt12experimental16coroutine_handleINS_16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(i8* %[[FRAME]])
// ... many lines of code to coerce coroutine_handle into an i8* scalar
// CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
@@ -100,8 +100,9 @@ struct std::experimental::coroutine_traits<void,int> {
// CHECK-LABEL: f1(
extern "C" void f1(int) {
- co_yield 42;
// CHECK: %[[PROMISE:.+]] = alloca %"struct.std::experimental::coroutine_traits<void, int>::promise_type"
+ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+ co_yield 42;
// CHECK: call void @_ZNSt12experimental16coroutine_traitsIJviEE12promise_type11yield_valueEi(%struct.suspend_maybe* sret %[[AWAITER:.+]], %"struct.std::experimental::coroutine_traits<void, int>::promise_type"* %[[PROMISE]], i32 42)
// See if we need to suspend:
@@ -116,7 +117,6 @@ extern "C" void f1(int) {
// ---------------------------
// Build the coroutine handle and pass it to await_suspend
// ---------------------------
- // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.frame()
// CHECK: call i8* @_ZNSt12experimental16coroutine_handleINS_16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(i8* %[[FRAME]])
// ... many lines of code to coerce coroutine_handle into an i8* scalar
// CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
diff --git a/clang/test/CodeGenCoroutines/coro-builtins.c b/clang/test/CodeGenCoroutines/coro-builtins.c
index d18d5e730f9..9ec21476425 100644
--- a/clang/test/CodeGenCoroutines/coro-builtins.c
+++ b/clang/test/CodeGenCoroutines/coro-builtins.c
@@ -2,7 +2,7 @@
void *myAlloc(long long);
-// CHECK-LABEL: f(
+// CHECK-LABEL: f(
void f(int n) {
// CHECK: %n.addr = alloca i32
// CHECK: %n_copy = alloca i32
@@ -19,31 +19,25 @@ void f(int n) {
// CHECK-NEXT: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
// CHECK-NEXT: %[[MEM:.+]] = call i8* @myAlloc(i64 %[[SIZE]])
- // CHECK-NEXT: %[[BEG:.+]] = call i8* @llvm.coro.begin(token %[[COROID]], i8* %[[MEM]])
+ // CHECK-NEXT: %[[FRAME:.+]] = call i8* @llvm.coro.begin(token %[[COROID]], i8* %[[MEM]])
__builtin_coro_begin(myAlloc(__builtin_coro_size()));
- // CHECK-NEXT: %[[FRAME1:.+]] = call i8* @llvm.coro.frame()
- // CHECK-NEXT: call void @llvm.coro.resume(i8* %[[FRAME1]])
+ // CHECK-NEXT: call void @llvm.coro.resume(i8* %[[FRAME]])
__builtin_coro_resume(__builtin_coro_frame());
- // CHECK-NEXT: %[[FRAME2:.+]] = call i8* @llvm.coro.frame()
- // CHECK-NEXT: call void @llvm.coro.destroy(i8* %[[FRAME2]])
+ // CHECK-NEXT: call void @llvm.coro.destroy(i8* %[[FRAME]])
__builtin_coro_destroy(__builtin_coro_frame());
- // CHECK-NEXT: %[[FRAME3:.+]] = call i8* @llvm.coro.frame()
- // CHECK-NEXT: call i1 @llvm.coro.done(i8* %[[FRAME3]])
+ // CHECK-NEXT: call i1 @llvm.coro.done(i8* %[[FRAME]])
__builtin_coro_done(__builtin_coro_frame());
- // CHECK-NEXT: %[[FRAME4:.+]] = call i8* @llvm.coro.frame()
- // CHECK-NEXT: call i8* @llvm.coro.promise(i8* %[[FRAME4]], i32 48, i1 false)
+ // CHECK-NEXT: call i8* @llvm.coro.promise(i8* %[[FRAME]], i32 48, i1 false)
__builtin_coro_promise(__builtin_coro_frame(), 48, 0);
- // CHECK-NEXT: %[[FRAME5:.+]] = call i8* @llvm.coro.frame()
- // CHECK-NEXT: call i8* @llvm.coro.free(token %[[COROID]], i8* %[[FRAME5]])
+ // CHECK-NEXT: call i8* @llvm.coro.free(token %[[COROID]], i8* %[[FRAME]])
__builtin_coro_free(__builtin_coro_frame());
- // CHECK-NEXT: %[[FRAME6:.+]] = call i8* @llvm.coro.frame()
- // CHECK-NEXT: call i1 @llvm.coro.end(i8* %[[FRAME6]], i1 false)
+ // CHECK-NEXT: call i1 @llvm.coro.end(i8* %[[FRAME]], i1 false)
__builtin_coro_end(__builtin_coro_frame(), 0);
// CHECK-NEXT: call i8 @llvm.coro.suspend(token none, i1 true)
OpenPOWER on IntegriCloud