Index: llvm/lib/Transforms/Coroutines/CoroFrame.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -1374,6 +1374,19 @@ // Build suspend crossing info. SuspendCrossingInfo Checker(F, Shape); + // Collect lifetime.start info for each alloca. + llvm::DenseMap LifetimeMap; + for (Instruction &I : instructions(F)) { + auto *II = dyn_cast(&I); + if (!II || II->getIntrinsicID() != Intrinsic::lifetime_start) + continue; + + if (auto *AI = dyn_cast(I.getOperand(1)->stripPointerCasts())) { + assert(LifetimeMap.find(&I) == LifetimeMap.end()); + LifetimeMap[AI] = &I; + } + } + IRBuilder<> Builder(F.getContext()); SpillInfo Spills; SmallVector LocalAllocas; @@ -1441,8 +1454,11 @@ continue; } + auto Iter = LifetimeMap.find(&I); + auto *LI = (Iter == LifetimeMap.end()) ? &I : Iter->second; for (User *U : I.users()) - if (Checker.isDefinitionAcrossSuspend(I, U)) { + // Check against lifetime.start if the instruction has the info. + if (Checker.isDefinitionAcrossSuspend(*LI, U)) { // We cannot spill a token. if (I.getType()->isTokenTy()) report_fatal_error( Index: llvm/lib/Transforms/Coroutines/CoroSplit.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -567,8 +567,9 @@ // branching to the original beginning of the coroutine. Make this // the entry block of the cloned function. auto *Entry = cast(VMap[Shape.AllocaSpillBlock]); + auto *OldEntry = &NewF->getEntryBlock(); Entry->setName("entry" + Suffix); - Entry->moveBefore(&NewF->getEntryBlock()); + Entry->moveBefore(OldEntry); Entry->getTerminator()->eraseFromParent(); // Clear all predecessors of the new entry block. There should be @@ -581,8 +582,14 @@ Builder.CreateUnreachable(); BranchToEntry->eraseFromParent(); - // TODO: move any allocas into Entry that weren't moved into the frame. - // (Currently we move all allocas into the frame.) + // Move any allocas into Entry that weren't moved into the frame. + for (auto IT = OldEntry->begin(), End = OldEntry->end(); IT != End;) { + Instruction &I = *IT++; + if (!isa(&I) || I.getNumUses() == 0) + continue; + + I.moveBefore(*Entry, Entry->getFirstInsertionPt()); + } // Branch from the entry to the appropriate place. Builder.SetInsertPoint(Entry); Index: llvm/test/Transforms/Coroutines/coro-split-02.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-split-02.ll +++ llvm/test/Transforms/Coroutines/coro-split-02.ll @@ -14,6 +14,7 @@ define void @a() "coroutine.presplit"="1" { entry: %ref.tmp7 = alloca %"struct.lean_future::Awaiter", align 8 + %testval = alloca i32 %id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) %alloc = call i8* @malloc(i64 16) #3 %vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc) @@ -28,6 +29,9 @@ await.ready: %StrayCoroSave = call token @llvm.coro.save(i8* null) %val = load i32, i32* %Result.i19 + %cast = bitcast i32* %testval to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %cast) + call void @llvm.lifetime.end.p0i8(i64 4, i8* %cast) call void @print(i32 %val) br label %exit exit: @@ -36,10 +40,14 @@ } ; CHECK-LABEL: @a.resume( +; CHECK: %testval = alloca i32 ; CHECK: getelementptr inbounds %a.Frame ; CHECK-NEXT: getelementptr inbounds %"struct.lean_future::Awaiter" ; CHECK-NOT: call token @llvm.coro.save(i8* null) ; CHECK-NEXT: %val = load i32, i32* %Result +; CHECK-NEXT: %cast = bitcast i32* %testval to i8* +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* %cast) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* %cast) ; CHECK-NEXT: call void @print(i32 %val) ; CHECK-NEXT: ret void @@ -55,4 +63,6 @@ declare void @"\01??3@YAXPEAX@Z"(i8*) local_unnamed_addr #10 declare i8* @llvm.coro.free(token, i8* nocapture readonly) #2 declare i1 @llvm.coro.end(i8*, i1) #3 +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #4 +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #4