summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Coroutines/CoroFrame.cpp14
-rw-r--r--llvm/test/Transforms/Coroutines/coro-retcon-alloca.ll28
2 files changed, 38 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 0d0ca511ca2..52c167c9f71 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -1042,7 +1042,8 @@ static bool localAllocaNeedsStackSave(CoroAllocaAllocInst *AI) {
/// Turn each of the given local allocas into a normal (dynamic) alloca
/// instruction.
-static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas) {
+static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas,
+ SmallVectorImpl<Instruction*> &DeadInsts) {
for (auto AI : LocalAllocas) {
auto M = AI->getModule();
IRBuilder<> Builder(AI);
@@ -1075,10 +1076,10 @@ static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas) {
StackSave);
}
}
- cast<Instruction>(U)->eraseFromParent();
+ DeadInsts.push_back(cast<Instruction>(U));
}
- AI->eraseFromParent();
+ DeadInsts.push_back(AI);
}
}
@@ -1201,6 +1202,11 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
continue;
}
+ // Ignore alloca.get; we process this as part of coro.alloca.alloc.
+ if (isa<CoroAllocaGetInst>(I)) {
+ continue;
+ }
+
for (User *U : I.users())
if (Checker.isDefinitionAcrossSuspend(I, U)) {
// We cannot spill a token.
@@ -1214,7 +1220,7 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
moveSpillUsesAfterCoroBegin(F, Spills, Shape.CoroBegin);
Shape.FrameTy = buildFrameType(F, Shape, Spills);
Shape.FramePtr = insertSpills(Spills, Shape);
- lowerLocalAllocas(LocalAllocas);
+ lowerLocalAllocas(LocalAllocas, DeadInstructions);
for (auto I : DeadInstructions)
I->eraseFromParent();
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-alloca.ll b/llvm/test/Transforms/Coroutines/coro-retcon-alloca.ll
index 14d5474b8b2..0657a84b461 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-alloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-alloca.ll
@@ -202,6 +202,34 @@ loop2:
; CHECK-NEXT: br i1 %cmp, label %loop2,
; CHECK-NEXT: }
+declare {i8*, i32} @prototype_j(i8*)
+define {i8*, i32} @j(i8* %buffer, i32 %n) {
+entry:
+ %id = call token @llvm.coro.id.retcon(i32 1024, i32 8, i8* %buffer, i8* bitcast ({i8*, i32} (i8*)* @prototype_j to i8*), i8* bitcast (i8* (i32)* @allocate to i8*), i8* bitcast (void (i8*)* @deallocate to i8*))
+ %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
+ br label %forward
+
+back:
+ ; We should encounter this 'get' before we encounter the 'alloc'.
+ %ptr = call i8* @llvm.coro.alloca.get(token %alloca)
+ call void @use(i8* %ptr)
+ call void @llvm.coro.alloca.free(token %alloca)
+ %k = add i32 %n.val, 1
+ %cmp = icmp ugt i32 %k, 128
+ br i1 %cmp, label %forward, label %end
+
+forward:
+ %n.val = phi i32 [ %n, %entry ], [ %k, %back ]
+ call void (...) @llvm.coro.suspend.retcon.isVoid(i32 %n.val)
+ %alloca = call token @llvm.coro.alloca.alloc.i32(i32 %n.val, i32 8)
+ %inc = add i32 %n.val, 1
+ br label %back
+
+end:
+ call i1 @llvm.coro.end(i8* %hdl, i1 0)
+ unreachable
+}
+
declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.suspend.retcon.i1(...)
OpenPOWER on IntegriCloud