1 //===- CoroSplit.cpp - Converts a coroutine into a state machine ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // This pass builds the coroutine frame and outlines resume and destroy parts 10 // of the coroutine into separate functions. 11 // 12 // We present a coroutine to an LLVM as an ordinary function with suspension 13 // points marked up with intrinsics. We let the optimizer party on the coroutine 14 // as a single function for as long as possible. Shortly before the coroutine is 15 // eligible to be inlined into its callers, we split up the coroutine into parts 16 // corresponding to an initial, resume and destroy invocations of the coroutine, 17 // add them to the current SCC and restart the IPO pipeline to optimize the 18 // coroutine subfunctions we extracted before proceeding to the caller of the 19 // coroutine. 20 //===----------------------------------------------------------------------===// 21 22 #include "CoroInternal.h" 23 #include "llvm/Analysis/CallGraphSCCPass.h" 24 #include "llvm/IR/DebugInfoMetadata.h" 25 #include "llvm/IR/IRBuilder.h" 26 #include "llvm/IR/InstIterator.h" 27 #include "llvm/IR/LegacyPassManager.h" 28 #include "llvm/IR/Verifier.h" 29 #include "llvm/Transforms/Scalar.h" 30 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 31 #include "llvm/Transforms/Utils/Cloning.h" 32 #include "llvm/Transforms/Utils/Local.h" 33 #include "llvm/Transforms/Utils/ValueMapper.h" 34 35 using namespace llvm; 36 37 #define DEBUG_TYPE "coro-split" 38 39 // Create an entry block for a resume function with a switch that will jump to 40 // suspend points. 41 static BasicBlock *createResumeEntryBlock(Function &F, coro::Shape &Shape) { 42 LLVMContext &C = F.getContext(); 43 44 // resume.entry: 45 // %index.addr = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, 46 // i32 2 47 // % index = load i32, i32* %index.addr 48 // switch i32 %index, label %unreachable [ 49 // i32 0, label %resume.0 50 // i32 1, label %resume.1 51 // ... 52 // ] 53 54 auto *NewEntry = BasicBlock::Create(C, "resume.entry", &F); 55 auto *UnreachBB = BasicBlock::Create(C, "unreachable", &F); 56 57 IRBuilder<> Builder(NewEntry); 58 auto *FramePtr = Shape.FramePtr; 59 auto *FrameTy = Shape.FrameTy; 60 auto *GepIndex = Builder.CreateConstInBoundsGEP2_32( 61 FrameTy, FramePtr, 0, coro::Shape::IndexField, "index.addr"); 62 auto *Index = Builder.CreateLoad(GepIndex, "index"); 63 auto *Switch = 64 Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size()); 65 Shape.ResumeSwitch = Switch; 66 67 size_t SuspendIndex = 0; 68 for (CoroSuspendInst *S : Shape.CoroSuspends) { 69 ConstantInt *IndexVal = Shape.getIndex(SuspendIndex); 70 71 // Replace CoroSave with a store to Index: 72 // %index.addr = getelementptr %f.frame... (index field number) 73 // store i32 0, i32* %index.addr1 74 auto *Save = S->getCoroSave(); 75 Builder.SetInsertPoint(Save); 76 if (S->isFinal()) { 77 // Final suspend point is represented by storing zero in ResumeFnAddr. 78 auto *GepIndex = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, 79 0, "ResumeFn.addr"); 80 auto *NullPtr = ConstantPointerNull::get(cast<PointerType>( 81 cast<PointerType>(GepIndex->getType())->getElementType())); 82 Builder.CreateStore(NullPtr, GepIndex); 83 } else { 84 auto *GepIndex = Builder.CreateConstInBoundsGEP2_32( 85 FrameTy, FramePtr, 0, coro::Shape::IndexField, "index.addr"); 86 Builder.CreateStore(IndexVal, GepIndex); 87 } 88 Save->replaceAllUsesWith(ConstantTokenNone::get(C)); 89 Save->eraseFromParent(); 90 91 // Split block before and after coro.suspend and add a jump from an entry 92 // switch: 93 // 94 // whateverBB: 95 // whatever 96 // %0 = call i8 @llvm.coro.suspend(token none, i1 false) 97 // switch i8 %0, label %suspend[i8 0, label %resume 98 // i8 1, label %cleanup] 99 // becomes: 100 // 101 // whateverBB: 102 // whatever 103 // br label %resume.0.landing 104 // 105 // resume.0: ; <--- jump from the switch in the resume.entry 106 // %0 = tail call i8 @llvm.coro.suspend(token none, i1 false) 107 // br label %resume.0.landing 108 // 109 // resume.0.landing: 110 // %1 = phi i8[-1, %whateverBB], [%0, %resume.0] 111 // switch i8 % 1, label %suspend [i8 0, label %resume 112 // i8 1, label %cleanup] 113 114 auto *SuspendBB = S->getParent(); 115 auto *ResumeBB = 116 SuspendBB->splitBasicBlock(S, "resume." + Twine(SuspendIndex)); 117 auto *LandingBB = ResumeBB->splitBasicBlock( 118 S->getNextNode(), ResumeBB->getName() + Twine(".landing")); 119 Switch->addCase(IndexVal, ResumeBB); 120 121 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB); 122 auto *PN = PHINode::Create(Builder.getInt8Ty(), 2, "", &LandingBB->front()); 123 S->replaceAllUsesWith(PN); 124 PN->addIncoming(Builder.getInt8(-1), SuspendBB); 125 PN->addIncoming(S, ResumeBB); 126 127 ++SuspendIndex; 128 } 129 130 Builder.SetInsertPoint(UnreachBB); 131 Builder.CreateUnreachable(); 132 133 return NewEntry; 134 } 135 136 // In Resumers, we replace fallthrough coro.end with ret void and delete the 137 // rest of the block. 138 static void replaceFallthroughCoroEnd(IntrinsicInst *End, 139 ValueToValueMapTy &VMap) { 140 auto *NewE = cast<IntrinsicInst>(VMap[End]); 141 ReturnInst::Create(NewE->getContext(), nullptr, NewE); 142 143 // Remove the rest of the block, by splitting it into an unreachable block. 144 auto *BB = NewE->getParent(); 145 BB->splitBasicBlock(NewE); 146 BB->getTerminator()->eraseFromParent(); 147 } 148 149 // In Resumers, we replace unwind coro.end with True to force the immediate 150 // unwind to caller. 151 static void replaceUnwindCoroEnds(coro::Shape &Shape, ValueToValueMapTy &VMap) { 152 if (Shape.CoroEnds.empty()) 153 return; 154 155 LLVMContext &Context = Shape.CoroEnds.front()->getContext(); 156 auto *True = ConstantInt::getTrue(Context); 157 for (CoroEndInst *CE : Shape.CoroEnds) { 158 if (!CE->isUnwind()) 159 continue; 160 161 auto *NewCE = cast<IntrinsicInst>(VMap[CE]); 162 163 // If coro.end has an associated bundle, add cleanupret instruction. 164 if (auto Bundle = NewCE->getOperandBundle(LLVMContext::OB_funclet)) { 165 Value *FromPad = Bundle->Inputs[0]; 166 auto *CleanupRet = CleanupReturnInst::Create(FromPad, nullptr, NewCE); 167 NewCE->getParent()->splitBasicBlock(NewCE); 168 CleanupRet->getParent()->getTerminator()->eraseFromParent(); 169 } 170 171 NewCE->replaceAllUsesWith(True); 172 NewCE->eraseFromParent(); 173 } 174 } 175 176 // Rewrite final suspend point handling. We do not use suspend index to 177 // represent the final suspend point. Instead we zero-out ResumeFnAddr in the 178 // coroutine frame, since it is undefined behavior to resume a coroutine 179 // suspended at the final suspend point. Thus, in the resume function, we can 180 // simply remove the last case (when coro::Shape is built, the final suspend 181 // point (if present) is always the last element of CoroSuspends array). 182 // In the destroy function, we add a code sequence to check if ResumeFnAddress 183 // is Null, and if so, jump to the appropriate label to handle cleanup from the 184 // final suspend point. 185 static void handleFinalSuspend(IRBuilder<> &Builder, Value *FramePtr, 186 coro::Shape &Shape, SwitchInst *Switch, 187 bool IsDestroy) { 188 assert(Shape.HasFinalSuspend); 189 auto FinalCaseIt = std::prev(Switch->case_end()); 190 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor(); 191 Switch->removeCase(FinalCaseIt); 192 if (IsDestroy) { 193 BasicBlock *OldSwitchBB = Switch->getParent(); 194 auto *NewSwitchBB = OldSwitchBB->splitBasicBlock(Switch, "Switch"); 195 Builder.SetInsertPoint(OldSwitchBB->getTerminator()); 196 auto *GepIndex = Builder.CreateConstInBoundsGEP2_32(Shape.FrameTy, FramePtr, 197 0, 0, "ResumeFn.addr"); 198 auto *Load = Builder.CreateLoad(GepIndex); 199 auto *NullPtr = 200 ConstantPointerNull::get(cast<PointerType>(Load->getType())); 201 auto *Cond = Builder.CreateICmpEQ(Load, NullPtr); 202 Builder.CreateCondBr(Cond, ResumeBB, NewSwitchBB); 203 OldSwitchBB->getTerminator()->eraseFromParent(); 204 } 205 } 206 207 // Create a resume clone by cloning the body of the original function, setting 208 // new entry block and replacing coro.suspend an appropriate value to force 209 // resume or cleanup pass for every suspend point. 210 static Function *createClone(Function &F, Twine Suffix, coro::Shape &Shape, 211 BasicBlock *ResumeEntry, int8_t FnIndex) { 212 Module *M = F.getParent(); 213 auto *FrameTy = Shape.FrameTy; 214 auto *FnPtrTy = cast<PointerType>(FrameTy->getElementType(0)); 215 auto *FnTy = cast<FunctionType>(FnPtrTy->getElementType()); 216 217 Function *NewF = 218 Function::Create(FnTy, GlobalValue::LinkageTypes::InternalLinkage, 219 F.getName() + Suffix, M); 220 NewF->addParamAttr(0, Attribute::NonNull); 221 NewF->addParamAttr(0, Attribute::NoAlias); 222 223 ValueToValueMapTy VMap; 224 // Replace all args with undefs. The buildCoroutineFrame algorithm already 225 // rewritten access to the args that occurs after suspend points with loads 226 // and stores to/from the coroutine frame. 227 for (Argument &A : F.args()) 228 VMap[&A] = UndefValue::get(A.getType()); 229 230 SmallVector<ReturnInst *, 4> Returns; 231 232 CloneFunctionInto(NewF, &F, VMap, /*ModuleLevelChanges=*/true, Returns); 233 234 // Remove old returns. 235 for (ReturnInst *Return : Returns) 236 changeToUnreachable(Return, /*UseLLVMTrap=*/false); 237 238 // Remove old return attributes. 239 NewF->removeAttributes( 240 AttributeList::ReturnIndex, 241 AttributeFuncs::typeIncompatible(NewF->getReturnType())); 242 243 // Make AllocaSpillBlock the new entry block. 244 auto *SwitchBB = cast<BasicBlock>(VMap[ResumeEntry]); 245 auto *Entry = cast<BasicBlock>(VMap[Shape.AllocaSpillBlock]); 246 Entry->moveBefore(&NewF->getEntryBlock()); 247 Entry->getTerminator()->eraseFromParent(); 248 BranchInst::Create(SwitchBB, Entry); 249 Entry->setName("entry" + Suffix); 250 251 // Clear all predecessors of the new entry block. 252 auto *Switch = cast<SwitchInst>(VMap[Shape.ResumeSwitch]); 253 Entry->replaceAllUsesWith(Switch->getDefaultDest()); 254 255 IRBuilder<> Builder(&NewF->getEntryBlock().front()); 256 257 // Remap frame pointer. 258 Argument *NewFramePtr = &*NewF->arg_begin(); 259 Value *OldFramePtr = cast<Value>(VMap[Shape.FramePtr]); 260 NewFramePtr->takeName(OldFramePtr); 261 OldFramePtr->replaceAllUsesWith(NewFramePtr); 262 263 // Remap vFrame pointer. 264 auto *NewVFrame = Builder.CreateBitCast( 265 NewFramePtr, Type::getInt8PtrTy(Builder.getContext()), "vFrame"); 266 Value *OldVFrame = cast<Value>(VMap[Shape.CoroBegin]); 267 OldVFrame->replaceAllUsesWith(NewVFrame); 268 269 // Rewrite final suspend handling as it is not done via switch (allows to 270 // remove final case from the switch, since it is undefined behavior to resume 271 // the coroutine suspended at the final suspend point. 272 if (Shape.HasFinalSuspend) { 273 auto *Switch = cast<SwitchInst>(VMap[Shape.ResumeSwitch]); 274 bool IsDestroy = FnIndex != 0; 275 handleFinalSuspend(Builder, NewFramePtr, Shape, Switch, IsDestroy); 276 } 277 278 // Replace coro suspend with the appropriate resume index. 279 // Replacing coro.suspend with (0) will result in control flow proceeding to 280 // a resume label associated with a suspend point, replacing it with (1) will 281 // result in control flow proceeding to a cleanup label associated with this 282 // suspend point. 283 auto *NewValue = Builder.getInt8(FnIndex ? 1 : 0); 284 for (CoroSuspendInst *CS : Shape.CoroSuspends) { 285 auto *MappedCS = cast<CoroSuspendInst>(VMap[CS]); 286 MappedCS->replaceAllUsesWith(NewValue); 287 MappedCS->eraseFromParent(); 288 } 289 290 // Remove coro.end intrinsics. 291 replaceFallthroughCoroEnd(Shape.CoroEnds.front(), VMap); 292 replaceUnwindCoroEnds(Shape, VMap); 293 // Eliminate coro.free from the clones, replacing it with 'null' in cleanup, 294 // to suppress deallocation code. 295 coro::replaceCoroFree(cast<CoroIdInst>(VMap[Shape.CoroBegin->getId()]), 296 /*Elide=*/FnIndex == 2); 297 298 NewF->setCallingConv(CallingConv::Fast); 299 300 return NewF; 301 } 302 303 static void removeCoroEnds(coro::Shape &Shape) { 304 if (Shape.CoroEnds.empty()) 305 return; 306 307 LLVMContext &Context = Shape.CoroEnds.front()->getContext(); 308 auto *False = ConstantInt::getFalse(Context); 309 310 for (CoroEndInst *CE : Shape.CoroEnds) { 311 CE->replaceAllUsesWith(False); 312 CE->eraseFromParent(); 313 } 314 } 315 316 static void replaceFrameSize(coro::Shape &Shape) { 317 if (Shape.CoroSizes.empty()) 318 return; 319 320 // In the same function all coro.sizes should have the same result type. 321 auto *SizeIntrin = Shape.CoroSizes.back(); 322 Module *M = SizeIntrin->getModule(); 323 const DataLayout &DL = M->getDataLayout(); 324 auto Size = DL.getTypeAllocSize(Shape.FrameTy); 325 auto *SizeConstant = ConstantInt::get(SizeIntrin->getType(), Size); 326 327 for (CoroSizeInst *CS : Shape.CoroSizes) { 328 CS->replaceAllUsesWith(SizeConstant); 329 CS->eraseFromParent(); 330 } 331 } 332 333 // Create a global constant array containing pointers to functions provided and 334 // set Info parameter of CoroBegin to point at this constant. Example: 335 // 336 // @f.resumers = internal constant [2 x void(%f.frame*)*] 337 // [void(%f.frame*)* @f.resume, void(%f.frame*)* @f.destroy] 338 // define void @f() { 339 // ... 340 // call i8* @llvm.coro.begin(i8* null, i32 0, i8* null, 341 // i8* bitcast([2 x void(%f.frame*)*] * @f.resumers to i8*)) 342 // 343 // Assumes that all the functions have the same signature. 344 static void setCoroInfo(Function &F, CoroBeginInst *CoroBegin, 345 std::initializer_list<Function *> Fns) { 346 347 SmallVector<Constant *, 4> Args(Fns.begin(), Fns.end()); 348 assert(!Args.empty()); 349 Function *Part = *Fns.begin(); 350 Module *M = Part->getParent(); 351 auto *ArrTy = ArrayType::get(Part->getType(), Args.size()); 352 353 auto *ConstVal = ConstantArray::get(ArrTy, Args); 354 auto *GV = new GlobalVariable(*M, ConstVal->getType(), /*isConstant=*/true, 355 GlobalVariable::PrivateLinkage, ConstVal, 356 F.getName() + Twine(".resumers")); 357 358 // Update coro.begin instruction to refer to this constant. 359 LLVMContext &C = F.getContext(); 360 auto *BC = ConstantExpr::getPointerCast(GV, Type::getInt8PtrTy(C)); 361 CoroBegin->getId()->setInfo(BC); 362 } 363 364 // Store addresses of Resume/Destroy/Cleanup functions in the coroutine frame. 365 static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn, 366 Function *DestroyFn, Function *CleanupFn) { 367 368 IRBuilder<> Builder(Shape.FramePtr->getNextNode()); 369 auto *ResumeAddr = Builder.CreateConstInBoundsGEP2_32( 370 Shape.FrameTy, Shape.FramePtr, 0, coro::Shape::ResumeField, 371 "resume.addr"); 372 Builder.CreateStore(ResumeFn, ResumeAddr); 373 374 Value *DestroyOrCleanupFn = DestroyFn; 375 376 CoroIdInst *CoroId = Shape.CoroBegin->getId(); 377 if (CoroAllocInst *CA = CoroId->getCoroAlloc()) { 378 // If there is a CoroAlloc and it returns false (meaning we elide the 379 // allocation, use CleanupFn instead of DestroyFn). 380 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn); 381 } 382 383 auto *DestroyAddr = Builder.CreateConstInBoundsGEP2_32( 384 Shape.FrameTy, Shape.FramePtr, 0, coro::Shape::DestroyField, 385 "destroy.addr"); 386 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr); 387 } 388 389 static void postSplitCleanup(Function &F) { 390 removeUnreachableBlocks(F); 391 llvm::legacy::FunctionPassManager FPM(F.getParent()); 392 393 FPM.add(createVerifierPass()); 394 FPM.add(createSCCPPass()); 395 FPM.add(createCFGSimplificationPass()); 396 FPM.add(createEarlyCSEPass()); 397 FPM.add(createCFGSimplificationPass()); 398 399 FPM.doInitialization(); 400 FPM.run(F); 401 FPM.doFinalization(); 402 } 403 404 // Assuming we arrived at the block NewBlock from Prev instruction, store 405 // PHI's incoming values in the ResolvedValues map. 406 static void 407 scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, 408 DenseMap<Value *, Value *> &ResolvedValues) { 409 auto *PrevBB = Prev->getParent(); 410 auto *I = &*NewBlock->begin(); 411 while (auto PN = dyn_cast<PHINode>(I)) { 412 auto V = PN->getIncomingValueForBlock(PrevBB); 413 // See if we already resolved it. 414 auto VI = ResolvedValues.find(V); 415 if (VI != ResolvedValues.end()) 416 V = VI->second; 417 // Remember the value. 418 ResolvedValues[PN] = V; 419 I = I->getNextNode(); 420 } 421 } 422 423 // Replace a sequence of branches leading to a ret, with a clone of a ret 424 // instruction. Suspend instruction represented by a switch, track the PHI 425 // values and select the correct case successor when possible. 426 static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { 427 DenseMap<Value *, Value *> ResolvedValues; 428 429 Instruction *I = InitialInst; 430 while (isa<TerminatorInst>(I)) { 431 if (isa<ReturnInst>(I)) { 432 if (I != InitialInst) 433 ReplaceInstWithInst(InitialInst, I->clone()); 434 return true; 435 } 436 if (auto *BR = dyn_cast<BranchInst>(I)) { 437 if (BR->isUnconditional()) { 438 BasicBlock *BB = BR->getSuccessor(0); 439 scanPHIsAndUpdateValueMap(I, BB, ResolvedValues); 440 I = BB->getFirstNonPHIOrDbgOrLifetime(); 441 continue; 442 } 443 } else if (auto *SI = dyn_cast<SwitchInst>(I)) { 444 Value *V = SI->getCondition(); 445 auto it = ResolvedValues.find(V); 446 if (it != ResolvedValues.end()) 447 V = it->second; 448 if (ConstantInt *Cond = dyn_cast<ConstantInt>(V)) { 449 BasicBlock *BB = SI->findCaseValue(Cond)->getCaseSuccessor(); 450 scanPHIsAndUpdateValueMap(I, BB, ResolvedValues); 451 I = BB->getFirstNonPHIOrDbgOrLifetime(); 452 continue; 453 } 454 } 455 return false; 456 } 457 return false; 458 } 459 460 // Add musttail to any resume instructions that is immediately followed by a 461 // suspend (i.e. ret). We do this even in -O0 to support guaranteed tail call 462 // for symmetrical coroutine control transfer (C++ Coroutines TS extension). 463 // This transformation is done only in the resume part of the coroutine that has 464 // identical signature and calling convention as the coro.resume call. 465 static void addMustTailToCoroResumes(Function &F) { 466 bool changed = false; 467 468 // Collect potential resume instructions. 469 SmallVector<CallInst *, 4> Resumes; 470 for (auto &I : instructions(F)) 471 if (auto *Call = dyn_cast<CallInst>(&I)) 472 if (auto *CalledValue = Call->getCalledValue()) 473 // CoroEarly pass replaced coro resumes with indirect calls to an 474 // address return by CoroSubFnInst intrinsic. See if it is one of those. 475 if (isa<CoroSubFnInst>(CalledValue->stripPointerCasts())) 476 Resumes.push_back(Call); 477 478 // Set musttail on those that are followed by a ret instruction. 479 for (CallInst *Call : Resumes) 480 if (simplifyTerminatorLeadingToRet(Call->getNextNode())) { 481 Call->setTailCallKind(llvm::CallInst::TCK_MustTail); 482 changed = true; 483 } 484 485 if (changed) 486 removeUnreachableBlocks(F); 487 } 488 489 // Coroutine has no suspend points. Remove heap allocation for the coroutine 490 // frame if possible. 491 static void handleNoSuspendCoroutine(CoroBeginInst *CoroBegin, Type *FrameTy) { 492 auto *CoroId = CoroBegin->getId(); 493 auto *AllocInst = CoroId->getCoroAlloc(); 494 coro::replaceCoroFree(CoroId, /*Elide=*/AllocInst != nullptr); 495 if (AllocInst) { 496 IRBuilder<> Builder(AllocInst); 497 // FIXME: Need to handle overaligned members. 498 auto *Frame = Builder.CreateAlloca(FrameTy); 499 auto *VFrame = Builder.CreateBitCast(Frame, Builder.getInt8PtrTy()); 500 AllocInst->replaceAllUsesWith(Builder.getFalse()); 501 AllocInst->eraseFromParent(); 502 CoroBegin->replaceAllUsesWith(VFrame); 503 } else { 504 CoroBegin->replaceAllUsesWith(CoroBegin->getMem()); 505 } 506 CoroBegin->eraseFromParent(); 507 } 508 509 // look for a very simple pattern 510 // coro.save 511 // no other calls 512 // resume or destroy call 513 // coro.suspend 514 // 515 // If there are other calls between coro.save and coro.suspend, they can 516 // potentially resume or destroy the coroutine, so it is unsafe to eliminate a 517 // suspend point. 518 static bool simplifySuspendPoint(CoroSuspendInst *Suspend, 519 CoroBeginInst *CoroBegin) { 520 auto *Save = Suspend->getCoroSave(); 521 auto *BB = Suspend->getParent(); 522 if (BB != Save->getParent()) 523 return false; 524 525 CallSite SingleCallSite; 526 527 // Check that we have only one CallSite. 528 for (Instruction *I = Save->getNextNode(); I != Suspend; 529 I = I->getNextNode()) { 530 if (isa<CoroFrameInst>(I)) 531 continue; 532 if (isa<CoroSubFnInst>(I)) 533 continue; 534 if (CallSite CS = CallSite(I)) { 535 if (SingleCallSite) 536 return false; 537 else 538 SingleCallSite = CS; 539 } 540 } 541 auto *CallInstr = SingleCallSite.getInstruction(); 542 if (!CallInstr) 543 return false; 544 545 auto *Callee = SingleCallSite.getCalledValue()->stripPointerCasts(); 546 547 // See if the callsite is for resumption or destruction of the coroutine. 548 auto *SubFn = dyn_cast<CoroSubFnInst>(Callee); 549 if (!SubFn) 550 return false; 551 552 // Does not refer to the current coroutine, we cannot do anything with it. 553 if (SubFn->getFrame() != CoroBegin) 554 return false; 555 556 // Replace llvm.coro.suspend with the value that results in resumption over 557 // the resume or cleanup path. 558 Suspend->replaceAllUsesWith(SubFn->getRawIndex()); 559 Suspend->eraseFromParent(); 560 Save->eraseFromParent(); 561 562 // No longer need a call to coro.resume or coro.destroy. 563 CallInstr->eraseFromParent(); 564 565 if (SubFn->user_empty()) 566 SubFn->eraseFromParent(); 567 568 return true; 569 } 570 571 // Remove suspend points that are simplified. 572 static void simplifySuspendPoints(coro::Shape &Shape) { 573 auto &S = Shape.CoroSuspends; 574 size_t I = 0, N = S.size(); 575 if (N == 0) 576 return; 577 for (;;) { 578 if (simplifySuspendPoint(S[I], Shape.CoroBegin)) { 579 if (--N == I) 580 break; 581 std::swap(S[I], S[N]); 582 continue; 583 } 584 if (++I == N) 585 break; 586 } 587 S.resize(N); 588 } 589 590 static SmallPtrSet<BasicBlock *, 4> getCoroBeginPredBlocks(CoroBeginInst *CB) { 591 // Collect all blocks that we need to look for instructions to relocate. 592 SmallPtrSet<BasicBlock *, 4> RelocBlocks; 593 SmallVector<BasicBlock *, 4> Work; 594 Work.push_back(CB->getParent()); 595 596 do { 597 BasicBlock *Current = Work.pop_back_val(); 598 for (BasicBlock *BB : predecessors(Current)) 599 if (RelocBlocks.count(BB) == 0) { 600 RelocBlocks.insert(BB); 601 Work.push_back(BB); 602 } 603 } while (!Work.empty()); 604 return RelocBlocks; 605 } 606 607 static SmallPtrSet<Instruction *, 8> 608 getNotRelocatableInstructions(CoroBeginInst *CoroBegin, 609 SmallPtrSetImpl<BasicBlock *> &RelocBlocks) { 610 SmallPtrSet<Instruction *, 8> DoNotRelocate; 611 // Collect all instructions that we should not relocate 612 SmallVector<Instruction *, 8> Work; 613 614 // Start with CoroBegin and terminators of all preceding blocks. 615 Work.push_back(CoroBegin); 616 BasicBlock *CoroBeginBB = CoroBegin->getParent(); 617 for (BasicBlock *BB : RelocBlocks) 618 if (BB != CoroBeginBB) 619 Work.push_back(BB->getTerminator()); 620 621 // For every instruction in the Work list, place its operands in DoNotRelocate 622 // set. 623 do { 624 Instruction *Current = Work.pop_back_val(); 625 DoNotRelocate.insert(Current); 626 for (Value *U : Current->operands()) { 627 auto *I = dyn_cast<Instruction>(U); 628 if (!I) 629 continue; 630 if (isa<AllocaInst>(U)) 631 continue; 632 if (DoNotRelocate.count(I) == 0) { 633 Work.push_back(I); 634 DoNotRelocate.insert(I); 635 } 636 } 637 } while (!Work.empty()); 638 return DoNotRelocate; 639 } 640 641 static void relocateInstructionBefore(CoroBeginInst *CoroBegin, Function &F) { 642 // Analyze which non-alloca instructions are needed for allocation and 643 // relocate the rest to after coro.begin. We need to do it, since some of the 644 // targets of those instructions may be placed into coroutine frame memory 645 // for which becomes available after coro.begin intrinsic. 646 647 auto BlockSet = getCoroBeginPredBlocks(CoroBegin); 648 auto DoNotRelocateSet = getNotRelocatableInstructions(CoroBegin, BlockSet); 649 650 Instruction *InsertPt = CoroBegin->getNextNode(); 651 BasicBlock &BB = F.getEntryBlock(); // TODO: Look at other blocks as well. 652 for (auto B = BB.begin(), E = BB.end(); B != E;) { 653 Instruction &I = *B++; 654 if (isa<AllocaInst>(&I)) 655 continue; 656 if (&I == CoroBegin) 657 break; 658 if (DoNotRelocateSet.count(&I)) 659 continue; 660 I.moveBefore(InsertPt); 661 } 662 } 663 664 static void splitCoroutine(Function &F, CallGraph &CG, CallGraphSCC &SCC) { 665 coro::Shape Shape(F); 666 if (!Shape.CoroBegin) 667 return; 668 669 simplifySuspendPoints(Shape); 670 relocateInstructionBefore(Shape.CoroBegin, F); 671 buildCoroutineFrame(F, Shape); 672 replaceFrameSize(Shape); 673 674 // If there are no suspend points, no split required, just remove 675 // the allocation and deallocation blocks, they are not needed. 676 if (Shape.CoroSuspends.empty()) { 677 handleNoSuspendCoroutine(Shape.CoroBegin, Shape.FrameTy); 678 removeCoroEnds(Shape); 679 postSplitCleanup(F); 680 coro::updateCallGraph(F, {}, CG, SCC); 681 return; 682 } 683 684 auto *ResumeEntry = createResumeEntryBlock(F, Shape); 685 auto ResumeClone = createClone(F, ".resume", Shape, ResumeEntry, 0); 686 auto DestroyClone = createClone(F, ".destroy", Shape, ResumeEntry, 1); 687 auto CleanupClone = createClone(F, ".cleanup", Shape, ResumeEntry, 2); 688 689 // We no longer need coro.end in F. 690 removeCoroEnds(Shape); 691 692 postSplitCleanup(F); 693 postSplitCleanup(*ResumeClone); 694 postSplitCleanup(*DestroyClone); 695 postSplitCleanup(*CleanupClone); 696 697 addMustTailToCoroResumes(*ResumeClone); 698 699 // Store addresses resume/destroy/cleanup functions in the coroutine frame. 700 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone); 701 702 // Create a constant array referring to resume/destroy/clone functions pointed 703 // by the last argument of @llvm.coro.info, so that CoroElide pass can 704 // determined correct function to call. 705 setCoroInfo(F, Shape.CoroBegin, {ResumeClone, DestroyClone, CleanupClone}); 706 707 // Update call graph and add the functions we created to the SCC. 708 coro::updateCallGraph(F, {ResumeClone, DestroyClone, CleanupClone}, CG, SCC); 709 } 710 711 // When we see the coroutine the first time, we insert an indirect call to a 712 // devirt trigger function and mark the coroutine that it is now ready for 713 // split. 714 static void prepareForSplit(Function &F, CallGraph &CG) { 715 Module &M = *F.getParent(); 716 #ifndef NDEBUG 717 Function *DevirtFn = M.getFunction(CORO_DEVIRT_TRIGGER_FN); 718 assert(DevirtFn && "coro.devirt.trigger function not found"); 719 #endif 720 721 F.addFnAttr(CORO_PRESPLIT_ATTR, PREPARED_FOR_SPLIT); 722 723 // Insert an indirect call sequence that will be devirtualized by CoroElide 724 // pass: 725 // %0 = call i8* @llvm.coro.subfn.addr(i8* null, i8 -1) 726 // %1 = bitcast i8* %0 to void(i8*)* 727 // call void %1(i8* null) 728 coro::LowererBase Lowerer(M); 729 Instruction *InsertPt = F.getEntryBlock().getTerminator(); 730 auto *Null = ConstantPointerNull::get(Type::getInt8PtrTy(F.getContext())); 731 auto *DevirtFnAddr = 732 Lowerer.makeSubFnCall(Null, CoroSubFnInst::RestartTrigger, InsertPt); 733 auto *IndirectCall = CallInst::Create(DevirtFnAddr, Null, "", InsertPt); 734 735 // Update CG graph with an indirect call we just added. 736 CG[&F]->addCalledFunction(IndirectCall, CG.getCallsExternalNode()); 737 } 738 739 // Make sure that there is a devirtualization trigger function that CoroSplit 740 // pass uses the force restart CGSCC pipeline. If devirt trigger function is not 741 // found, we will create one and add it to the current SCC. 742 static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC) { 743 Module &M = CG.getModule(); 744 if (M.getFunction(CORO_DEVIRT_TRIGGER_FN)) 745 return; 746 747 LLVMContext &C = M.getContext(); 748 auto *FnTy = FunctionType::get(Type::getVoidTy(C), Type::getInt8PtrTy(C), 749 /*IsVarArgs=*/false); 750 Function *DevirtFn = 751 Function::Create(FnTy, GlobalValue::LinkageTypes::PrivateLinkage, 752 CORO_DEVIRT_TRIGGER_FN, &M); 753 DevirtFn->addFnAttr(Attribute::AlwaysInline); 754 auto *Entry = BasicBlock::Create(C, "entry", DevirtFn); 755 ReturnInst::Create(C, Entry); 756 757 auto *Node = CG.getOrInsertFunction(DevirtFn); 758 759 SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end()); 760 Nodes.push_back(Node); 761 SCC.initialize(Nodes); 762 } 763 764 //===----------------------------------------------------------------------===// 765 // Top Level Driver 766 //===----------------------------------------------------------------------===// 767 768 namespace { 769 770 struct CoroSplit : public CallGraphSCCPass { 771 static char ID; // Pass identification, replacement for typeid 772 CoroSplit() : CallGraphSCCPass(ID) { 773 initializeCoroSplitPass(*PassRegistry::getPassRegistry()); 774 } 775 776 bool Run = false; 777 778 // A coroutine is identified by the presence of coro.begin intrinsic, if 779 // we don't have any, this pass has nothing to do. 780 bool doInitialization(CallGraph &CG) override { 781 Run = coro::declaresIntrinsics(CG.getModule(), {"llvm.coro.begin"}); 782 return CallGraphSCCPass::doInitialization(CG); 783 } 784 785 bool runOnSCC(CallGraphSCC &SCC) override { 786 if (!Run) 787 return false; 788 789 // Find coroutines for processing. 790 SmallVector<Function *, 4> Coroutines; 791 for (CallGraphNode *CGN : SCC) 792 if (auto *F = CGN->getFunction()) 793 if (F->hasFnAttribute(CORO_PRESPLIT_ATTR)) 794 Coroutines.push_back(F); 795 796 if (Coroutines.empty()) 797 return false; 798 799 CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); 800 createDevirtTriggerFunc(CG, SCC); 801 802 for (Function *F : Coroutines) { 803 Attribute Attr = F->getFnAttribute(CORO_PRESPLIT_ATTR); 804 StringRef Value = Attr.getValueAsString(); 805 DEBUG(dbgs() << "CoroSplit: Processing coroutine '" << F->getName() 806 << "' state: " << Value << "\n"); 807 if (Value == UNPREPARED_FOR_SPLIT) { 808 prepareForSplit(*F, CG); 809 continue; 810 } 811 F->removeFnAttr(CORO_PRESPLIT_ATTR); 812 splitCoroutine(*F, CG, SCC); 813 } 814 return true; 815 } 816 817 void getAnalysisUsage(AnalysisUsage &AU) const override { 818 CallGraphSCCPass::getAnalysisUsage(AU); 819 } 820 StringRef getPassName() const override { return "Coroutine Splitting"; } 821 }; 822 } 823 824 char CoroSplit::ID = 0; 825 INITIALIZE_PASS( 826 CoroSplit, "coro-split", 827 "Split coroutine into a set of functions driving its state machine", false, 828 false) 829 830 Pass *llvm::createCoroSplitPass() { return new CoroSplit(); } 831