1 //===- SpillUtils.cpp - Utilities for checking for spills ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Transforms/Coroutines/SpillUtils.h" 10 #include "CoroInternal.h" 11 #include "llvm/Analysis/CFG.h" 12 #include "llvm/Analysis/PtrUseVisitor.h" 13 #include "llvm/IR/CFG.h" 14 #include "llvm/IR/DebugInfo.h" 15 #include "llvm/IR/Dominators.h" 16 #include "llvm/IR/InstIterator.h" 17 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 18 19 namespace llvm { 20 21 namespace coro { 22 23 namespace { 24 25 typedef SmallPtrSet<BasicBlock *, 8> VisitedBlocksSet; 26 27 // Check for structural coroutine intrinsics that should not be spilled into 28 // the coroutine frame. 29 static bool isCoroutineStructureIntrinsic(Instruction &I) { 30 return isa<CoroIdInst>(&I) || isa<CoroSaveInst>(&I) || 31 isa<CoroSuspendInst>(&I); 32 } 33 34 /// Does control flow starting at the given block ever reach a suspend 35 /// instruction before reaching a block in VisitedOrFreeBBs? 36 static bool isSuspendReachableFrom(BasicBlock *From, 37 VisitedBlocksSet &VisitedOrFreeBBs) { 38 // Eagerly try to add this block to the visited set. If it's already 39 // there, stop recursing; this path doesn't reach a suspend before 40 // either looping or reaching a freeing block. 41 if (!VisitedOrFreeBBs.insert(From).second) 42 return false; 43 44 // We assume that we'll already have split suspends into their own blocks. 45 if (coro::isSuspendBlock(From)) 46 return true; 47 48 // Recurse on the successors. 49 for (auto *Succ : successors(From)) { 50 if (isSuspendReachableFrom(Succ, VisitedOrFreeBBs)) 51 return true; 52 } 53 54 return false; 55 } 56 57 /// Is the given alloca "local", i.e. bounded in lifetime to not cross a 58 /// suspend point? 59 static bool isLocalAlloca(CoroAllocaAllocInst *AI) { 60 // Seed the visited set with all the basic blocks containing a free 61 // so that we won't pass them up. 62 VisitedBlocksSet VisitedOrFreeBBs; 63 for (auto *User : AI->users()) { 64 if (auto FI = dyn_cast<CoroAllocaFreeInst>(User)) 65 VisitedOrFreeBBs.insert(FI->getParent()); 66 } 67 68 return !isSuspendReachableFrom(AI->getParent(), VisitedOrFreeBBs); 69 } 70 71 /// Turn the given coro.alloca.alloc call into a dynamic allocation. 72 /// This happens during the all-instructions iteration, so it must not 73 /// delete the call. 74 static Instruction * 75 lowerNonLocalAlloca(CoroAllocaAllocInst *AI, const coro::Shape &Shape, 76 SmallVectorImpl<Instruction *> &DeadInsts) { 77 IRBuilder<> Builder(AI); 78 auto Alloc = Shape.emitAlloc(Builder, AI->getSize(), nullptr); 79 80 for (User *U : AI->users()) { 81 if (isa<CoroAllocaGetInst>(U)) { 82 U->replaceAllUsesWith(Alloc); 83 } else { 84 auto FI = cast<CoroAllocaFreeInst>(U); 85 Builder.SetInsertPoint(FI); 86 Shape.emitDealloc(Builder, Alloc, nullptr); 87 } 88 DeadInsts.push_back(cast<Instruction>(U)); 89 } 90 91 // Push this on last so that it gets deleted after all the others. 92 DeadInsts.push_back(AI); 93 94 // Return the new allocation value so that we can check for needed spills. 95 return cast<Instruction>(Alloc); 96 } 97 98 // We need to make room to insert a spill after initial PHIs, but before 99 // catchswitch instruction. Placing it before violates the requirement that 100 // catchswitch, like all other EHPads must be the first nonPHI in a block. 101 // 102 // Split away catchswitch into a separate block and insert in its place: 103 // 104 // cleanuppad <InsertPt> cleanupret. 105 // 106 // cleanupret instruction will act as an insert point for the spill. 107 static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) { 108 BasicBlock *CurrentBlock = CatchSwitch->getParent(); 109 BasicBlock *NewBlock = CurrentBlock->splitBasicBlock(CatchSwitch); 110 CurrentBlock->getTerminator()->eraseFromParent(); 111 112 auto *CleanupPad = 113 CleanupPadInst::Create(CatchSwitch->getParentPad(), {}, "", CurrentBlock); 114 auto *CleanupRet = 115 CleanupReturnInst::Create(CleanupPad, NewBlock, CurrentBlock); 116 return CleanupRet; 117 } 118 119 // We use a pointer use visitor to track how an alloca is being used. 120 // The goal is to be able to answer the following three questions: 121 // 1. Should this alloca be allocated on the frame instead. 122 // 2. Could the content of the alloca be modified prior to CoroBegin, which 123 // would require copying the data from the alloca to the frame after 124 // CoroBegin. 125 // 3. Are there any aliases created for this alloca prior to CoroBegin, but 126 // used after CoroBegin. In that case, we will need to recreate the alias 127 // after CoroBegin based off the frame. 128 // 129 // To answer question 1, we track two things: 130 // A. List of all BasicBlocks that use this alloca or any of the aliases of 131 // the alloca. In the end, we check if there exists any two basic blocks that 132 // cross suspension points. If so, this alloca must be put on the frame. 133 // B. Whether the alloca or any alias of the alloca is escaped at some point, 134 // either by storing the address somewhere, or the address is used in a 135 // function call that might capture. If it's ever escaped, this alloca must be 136 // put on the frame conservatively. 137 // 138 // To answer quetion 2, we track through the variable MayWriteBeforeCoroBegin. 139 // Whenever a potential write happens, either through a store instruction, a 140 // function call or any of the memory intrinsics, we check whether this 141 // instruction is prior to CoroBegin. 142 // 143 // To answer question 3, we track the offsets of all aliases created for the 144 // alloca prior to CoroBegin but used after CoroBegin. std::optional is used to 145 // be able to represent the case when the offset is unknown (e.g. when you have 146 // a PHINode that takes in different offset values). We cannot handle unknown 147 // offsets and will assert. This is the potential issue left out. An ideal 148 // solution would likely require a significant redesign. 149 150 namespace { 151 struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> { 152 using Base = PtrUseVisitor<AllocaUseVisitor>; 153 AllocaUseVisitor(const DataLayout &DL, const DominatorTree &DT, 154 const coro::Shape &CoroShape, 155 const SuspendCrossingInfo &Checker, 156 bool ShouldUseLifetimeStartInfo) 157 : PtrUseVisitor(DL), DT(DT), CoroShape(CoroShape), Checker(Checker), 158 ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) { 159 for (AnyCoroSuspendInst *SuspendInst : CoroShape.CoroSuspends) 160 CoroSuspendBBs.insert(SuspendInst->getParent()); 161 } 162 163 void visit(Instruction &I) { 164 Users.insert(&I); 165 Base::visit(I); 166 // If the pointer is escaped prior to CoroBegin, we have to assume it would 167 // be written into before CoroBegin as well. 168 if (PI.isEscaped() && 169 !DT.dominates(CoroShape.CoroBegin, PI.getEscapingInst())) { 170 MayWriteBeforeCoroBegin = true; 171 } 172 } 173 // We need to provide this overload as PtrUseVisitor uses a pointer based 174 // visiting function. 175 void visit(Instruction *I) { return visit(*I); } 176 177 void visitPHINode(PHINode &I) { 178 enqueueUsers(I); 179 handleAlias(I); 180 } 181 182 void visitSelectInst(SelectInst &I) { 183 enqueueUsers(I); 184 handleAlias(I); 185 } 186 187 void visitStoreInst(StoreInst &SI) { 188 // Regardless whether the alias of the alloca is the value operand or the 189 // pointer operand, we need to assume the alloca is been written. 190 handleMayWrite(SI); 191 192 if (SI.getValueOperand() != U->get()) 193 return; 194 195 // We are storing the pointer into a memory location, potentially escaping. 196 // As an optimization, we try to detect simple cases where it doesn't 197 // actually escape, for example: 198 // %ptr = alloca .. 199 // %addr = alloca .. 200 // store %ptr, %addr 201 // %x = load %addr 202 // .. 203 // If %addr is only used by loading from it, we could simply treat %x as 204 // another alias of %ptr, and not considering %ptr being escaped. 205 auto IsSimpleStoreThenLoad = [&]() { 206 auto *AI = dyn_cast<AllocaInst>(SI.getPointerOperand()); 207 // If the memory location we are storing to is not an alloca, it 208 // could be an alias of some other memory locations, which is difficult 209 // to analyze. 210 if (!AI) 211 return false; 212 // StoreAliases contains aliases of the memory location stored into. 213 SmallVector<Instruction *, 4> StoreAliases = {AI}; 214 while (!StoreAliases.empty()) { 215 Instruction *I = StoreAliases.pop_back_val(); 216 for (User *U : I->users()) { 217 // If we are loading from the memory location, we are creating an 218 // alias of the original pointer. 219 if (auto *LI = dyn_cast<LoadInst>(U)) { 220 enqueueUsers(*LI); 221 handleAlias(*LI); 222 continue; 223 } 224 // If we are overriding the memory location, the pointer certainly 225 // won't escape. 226 if (auto *S = dyn_cast<StoreInst>(U)) 227 if (S->getPointerOperand() == I) 228 continue; 229 if (auto *II = dyn_cast<IntrinsicInst>(U)) 230 if (II->isLifetimeStartOrEnd()) 231 continue; 232 // BitCastInst creats aliases of the memory location being stored 233 // into. 234 if (auto *BI = dyn_cast<BitCastInst>(U)) { 235 StoreAliases.push_back(BI); 236 continue; 237 } 238 return false; 239 } 240 } 241 242 return true; 243 }; 244 245 if (!IsSimpleStoreThenLoad()) 246 PI.setEscaped(&SI); 247 } 248 249 // All mem intrinsics modify the data. 250 void visitMemIntrinsic(MemIntrinsic &MI) { handleMayWrite(MI); } 251 252 void visitBitCastInst(BitCastInst &BC) { 253 Base::visitBitCastInst(BC); 254 handleAlias(BC); 255 } 256 257 void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) { 258 Base::visitAddrSpaceCastInst(ASC); 259 handleAlias(ASC); 260 } 261 262 void visitGetElementPtrInst(GetElementPtrInst &GEPI) { 263 // The base visitor will adjust Offset accordingly. 264 Base::visitGetElementPtrInst(GEPI); 265 handleAlias(GEPI); 266 } 267 268 void visitIntrinsicInst(IntrinsicInst &II) { 269 // When we found the lifetime markers refers to a 270 // subrange of the original alloca, ignore the lifetime 271 // markers to avoid misleading the analysis. 272 if (!IsOffsetKnown || !Offset.isZero()) 273 return Base::visitIntrinsicInst(II); 274 switch (II.getIntrinsicID()) { 275 default: 276 return Base::visitIntrinsicInst(II); 277 case Intrinsic::lifetime_start: 278 LifetimeStarts.insert(&II); 279 LifetimeStartBBs.push_back(II.getParent()); 280 break; 281 case Intrinsic::lifetime_end: 282 LifetimeEndBBs.insert(II.getParent()); 283 break; 284 } 285 } 286 287 void visitCallBase(CallBase &CB) { 288 for (unsigned Op = 0, OpCount = CB.arg_size(); Op < OpCount; ++Op) 289 if (U->get() == CB.getArgOperand(Op) && !CB.doesNotCapture(Op)) 290 PI.setEscaped(&CB); 291 handleMayWrite(CB); 292 } 293 294 bool getShouldLiveOnFrame() const { 295 if (!ShouldLiveOnFrame) 296 ShouldLiveOnFrame = computeShouldLiveOnFrame(); 297 return *ShouldLiveOnFrame; 298 } 299 300 bool getMayWriteBeforeCoroBegin() const { return MayWriteBeforeCoroBegin; } 301 302 DenseMap<Instruction *, std::optional<APInt>> getAliasesCopy() const { 303 assert(getShouldLiveOnFrame() && "This method should only be called if the " 304 "alloca needs to live on the frame."); 305 for (const auto &P : AliasOffetMap) 306 if (!P.second) 307 report_fatal_error("Unable to handle an alias with unknown offset " 308 "created before CoroBegin."); 309 return AliasOffetMap; 310 } 311 312 private: 313 const DominatorTree &DT; 314 const coro::Shape &CoroShape; 315 const SuspendCrossingInfo &Checker; 316 // All alias to the original AllocaInst, created before CoroBegin and used 317 // after CoroBegin. Each entry contains the instruction and the offset in the 318 // original Alloca. They need to be recreated after CoroBegin off the frame. 319 DenseMap<Instruction *, std::optional<APInt>> AliasOffetMap{}; 320 SmallPtrSet<Instruction *, 4> Users{}; 321 SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{}; 322 SmallVector<BasicBlock *> LifetimeStartBBs{}; 323 SmallPtrSet<BasicBlock *, 2> LifetimeEndBBs{}; 324 SmallPtrSet<const BasicBlock *, 2> CoroSuspendBBs{}; 325 bool MayWriteBeforeCoroBegin{false}; 326 bool ShouldUseLifetimeStartInfo{true}; 327 328 mutable std::optional<bool> ShouldLiveOnFrame{}; 329 330 bool computeShouldLiveOnFrame() const { 331 // If lifetime information is available, we check it first since it's 332 // more precise. We look at every pair of lifetime.start intrinsic and 333 // every basic block that uses the pointer to see if they cross suspension 334 // points. The uses cover both direct uses as well as indirect uses. 335 if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) { 336 // If there is no explicit lifetime.end, then assume the address can 337 // cross suspension points. 338 if (LifetimeEndBBs.empty()) 339 return true; 340 341 // If there is a path from a lifetime.start to a suspend without a 342 // corresponding lifetime.end, then the alloca's lifetime persists 343 // beyond that suspension point and the alloca must go on the frame. 344 llvm::SmallVector<BasicBlock *> Worklist(LifetimeStartBBs); 345 if (isManyPotentiallyReachableFromMany(Worklist, CoroSuspendBBs, 346 &LifetimeEndBBs, &DT)) 347 return true; 348 349 // Addresses are guaranteed to be identical after every lifetime.start so 350 // we cannot use the local stack if the address escaped and there is a 351 // suspend point between lifetime markers. This should also cover the 352 // case of a single lifetime.start intrinsic in a loop with suspend point. 353 if (PI.isEscaped()) { 354 for (auto *A : LifetimeStarts) { 355 for (auto *B : LifetimeStarts) { 356 if (Checker.hasPathOrLoopCrossingSuspendPoint(A->getParent(), 357 B->getParent())) 358 return true; 359 } 360 } 361 } 362 return false; 363 } 364 // FIXME: Ideally the isEscaped check should come at the beginning. 365 // However there are a few loose ends that need to be fixed first before 366 // we can do that. We need to make sure we are not over-conservative, so 367 // that the data accessed in-between await_suspend and symmetric transfer 368 // is always put on the stack, and also data accessed after coro.end is 369 // always put on the stack (esp the return object). To fix that, we need 370 // to: 371 // 1) Potentially treat sret as nocapture in calls 372 // 2) Special handle the return object and put it on the stack 373 // 3) Utilize lifetime.end intrinsic 374 if (PI.isEscaped()) 375 return true; 376 377 for (auto *U1 : Users) 378 for (auto *U2 : Users) 379 if (Checker.isDefinitionAcrossSuspend(*U1, U2)) 380 return true; 381 382 return false; 383 } 384 385 void handleMayWrite(const Instruction &I) { 386 if (!DT.dominates(CoroShape.CoroBegin, &I)) 387 MayWriteBeforeCoroBegin = true; 388 } 389 390 bool usedAfterCoroBegin(Instruction &I) { 391 for (auto &U : I.uses()) 392 if (DT.dominates(CoroShape.CoroBegin, U)) 393 return true; 394 return false; 395 } 396 397 void handleAlias(Instruction &I) { 398 // We track all aliases created prior to CoroBegin but used after. 399 // These aliases may need to be recreated after CoroBegin if the alloca 400 // need to live on the frame. 401 if (DT.dominates(CoroShape.CoroBegin, &I) || !usedAfterCoroBegin(I)) 402 return; 403 404 if (!IsOffsetKnown) { 405 AliasOffetMap[&I].reset(); 406 } else { 407 auto [Itr, Inserted] = AliasOffetMap.try_emplace(&I, Offset); 408 if (!Inserted && Itr->second && *Itr->second != Offset) { 409 // If we have seen two different possible values for this alias, we set 410 // it to empty. 411 Itr->second.reset(); 412 } 413 } 414 } 415 }; 416 } // namespace 417 418 static void collectFrameAlloca(AllocaInst *AI, const coro::Shape &Shape, 419 const SuspendCrossingInfo &Checker, 420 SmallVectorImpl<AllocaInfo> &Allocas, 421 const DominatorTree &DT) { 422 if (Shape.CoroSuspends.empty()) 423 return; 424 425 // The PromiseAlloca will be specially handled since it needs to be in a 426 // fixed position in the frame. 427 if (AI == Shape.SwitchLowering.PromiseAlloca) 428 return; 429 430 // The __coro_gro alloca should outlive the promise, make sure we 431 // keep it outside the frame. 432 if (AI->hasMetadata(LLVMContext::MD_coro_outside_frame)) 433 return; 434 435 // The code that uses lifetime.start intrinsic does not work for functions 436 // with loops without exit. Disable it on ABIs we know to generate such 437 // code. 438 bool ShouldUseLifetimeStartInfo = 439 (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon && 440 Shape.ABI != coro::ABI::RetconOnce); 441 AllocaUseVisitor Visitor{AI->getDataLayout(), DT, Shape, Checker, 442 ShouldUseLifetimeStartInfo}; 443 Visitor.visitPtr(*AI); 444 if (!Visitor.getShouldLiveOnFrame()) 445 return; 446 Allocas.emplace_back(AI, Visitor.getAliasesCopy(), 447 Visitor.getMayWriteBeforeCoroBegin()); 448 } 449 450 } // namespace 451 452 void collectSpillsFromArgs(SpillInfo &Spills, Function &F, 453 const SuspendCrossingInfo &Checker) { 454 // Collect the spills for arguments and other not-materializable values. 455 for (Argument &A : F.args()) 456 for (User *U : A.users()) 457 if (Checker.isDefinitionAcrossSuspend(A, U)) 458 Spills[&A].push_back(cast<Instruction>(U)); 459 } 460 461 void collectSpillsAndAllocasFromInsts( 462 SpillInfo &Spills, SmallVector<AllocaInfo, 8> &Allocas, 463 SmallVector<Instruction *, 4> &DeadInstructions, 464 SmallVector<CoroAllocaAllocInst *, 4> &LocalAllocas, Function &F, 465 const SuspendCrossingInfo &Checker, const DominatorTree &DT, 466 const coro::Shape &Shape) { 467 468 for (Instruction &I : instructions(F)) { 469 // Values returned from coroutine structure intrinsics should not be part 470 // of the Coroutine Frame. 471 if (isCoroutineStructureIntrinsic(I) || &I == Shape.CoroBegin) 472 continue; 473 474 // Handle alloca.alloc specially here. 475 if (auto AI = dyn_cast<CoroAllocaAllocInst>(&I)) { 476 // Check whether the alloca's lifetime is bounded by suspend points. 477 if (isLocalAlloca(AI)) { 478 LocalAllocas.push_back(AI); 479 continue; 480 } 481 482 // If not, do a quick rewrite of the alloca and then add spills of 483 // the rewritten value. The rewrite doesn't invalidate anything in 484 // Spills because the other alloca intrinsics have no other operands 485 // besides AI, and it doesn't invalidate the iteration because we delay 486 // erasing AI. 487 auto Alloc = lowerNonLocalAlloca(AI, Shape, DeadInstructions); 488 489 for (User *U : Alloc->users()) { 490 if (Checker.isDefinitionAcrossSuspend(*Alloc, U)) 491 Spills[Alloc].push_back(cast<Instruction>(U)); 492 } 493 continue; 494 } 495 496 // Ignore alloca.get; we process this as part of coro.alloca.alloc. 497 if (isa<CoroAllocaGetInst>(I)) 498 continue; 499 500 if (auto *AI = dyn_cast<AllocaInst>(&I)) { 501 collectFrameAlloca(AI, Shape, Checker, Allocas, DT); 502 continue; 503 } 504 505 for (User *U : I.users()) 506 if (Checker.isDefinitionAcrossSuspend(I, U)) { 507 // We cannot spill a token. 508 if (I.getType()->isTokenTy()) 509 report_fatal_error( 510 "token definition is separated from the use by a suspend point"); 511 Spills[&I].push_back(cast<Instruction>(U)); 512 } 513 } 514 } 515 516 void collectSpillsFromDbgInfo(SpillInfo &Spills, Function &F, 517 const SuspendCrossingInfo &Checker) { 518 // We don't want the layout of coroutine frame to be affected 519 // by debug information. So we only choose to salvage DbgValueInst for 520 // whose value is already in the frame. 521 // We would handle the dbg.values for allocas specially 522 for (auto &Iter : Spills) { 523 auto *V = Iter.first; 524 SmallVector<DbgValueInst *, 16> DVIs; 525 SmallVector<DbgVariableRecord *, 16> DVRs; 526 findDbgValues(DVIs, V, &DVRs); 527 for (DbgValueInst *DVI : DVIs) 528 if (Checker.isDefinitionAcrossSuspend(*V, DVI)) 529 Spills[V].push_back(DVI); 530 // Add the instructions which carry debug info that is in the frame. 531 for (DbgVariableRecord *DVR : DVRs) 532 if (Checker.isDefinitionAcrossSuspend(*V, DVR->Marker->MarkedInstr)) 533 Spills[V].push_back(DVR->Marker->MarkedInstr); 534 } 535 } 536 537 /// Async and Retcon{Once} conventions assume that all spill uses can be sunk 538 /// after the coro.begin intrinsic. 539 void sinkSpillUsesAfterCoroBegin(const DominatorTree &Dom, 540 CoroBeginInst *CoroBegin, 541 coro::SpillInfo &Spills, 542 SmallVectorImpl<coro::AllocaInfo> &Allocas) { 543 SmallSetVector<Instruction *, 32> ToMove; 544 SmallVector<Instruction *, 32> Worklist; 545 546 // Collect all users that precede coro.begin. 547 auto collectUsers = [&](Value *Def) { 548 for (User *U : Def->users()) { 549 auto Inst = cast<Instruction>(U); 550 if (Inst->getParent() != CoroBegin->getParent() || 551 Dom.dominates(CoroBegin, Inst)) 552 continue; 553 if (ToMove.insert(Inst)) 554 Worklist.push_back(Inst); 555 } 556 }; 557 std::for_each(Spills.begin(), Spills.end(), 558 [&](auto &I) { collectUsers(I.first); }); 559 std::for_each(Allocas.begin(), Allocas.end(), 560 [&](auto &I) { collectUsers(I.Alloca); }); 561 562 // Recursively collect users before coro.begin. 563 while (!Worklist.empty()) { 564 auto *Def = Worklist.pop_back_val(); 565 for (User *U : Def->users()) { 566 auto Inst = cast<Instruction>(U); 567 if (Dom.dominates(CoroBegin, Inst)) 568 continue; 569 if (ToMove.insert(Inst)) 570 Worklist.push_back(Inst); 571 } 572 } 573 574 // Sort by dominance. 575 SmallVector<Instruction *, 64> InsertionList(ToMove.begin(), ToMove.end()); 576 llvm::sort(InsertionList, [&Dom](Instruction *A, Instruction *B) -> bool { 577 // If a dominates b it should precede (<) b. 578 return Dom.dominates(A, B); 579 }); 580 581 Instruction *InsertPt = CoroBegin->getNextNode(); 582 for (Instruction *Inst : InsertionList) 583 Inst->moveBefore(InsertPt->getIterator()); 584 } 585 586 BasicBlock::iterator getSpillInsertionPt(const coro::Shape &Shape, Value *Def, 587 const DominatorTree &DT) { 588 BasicBlock::iterator InsertPt; 589 if (auto *Arg = dyn_cast<Argument>(Def)) { 590 // For arguments, we will place the store instruction right after 591 // the coroutine frame pointer instruction, i.e. coro.begin. 592 InsertPt = Shape.getInsertPtAfterFramePtr(); 593 594 // If we're spilling an Argument, make sure we clear 'captures' 595 // from the coroutine function. 596 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures); 597 } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) { 598 // Don't spill immediately after a suspend; splitting assumes 599 // that the suspend will be followed by a branch. 600 InsertPt = CSI->getParent()->getSingleSuccessor()->getFirstNonPHIIt(); 601 } else { 602 auto *I = cast<Instruction>(Def); 603 if (!DT.dominates(Shape.CoroBegin, I)) { 604 // If it is not dominated by CoroBegin, then spill should be 605 // inserted immediately after CoroFrame is computed. 606 InsertPt = Shape.getInsertPtAfterFramePtr(); 607 } else if (auto *II = dyn_cast<InvokeInst>(I)) { 608 // If we are spilling the result of the invoke instruction, split 609 // the normal edge and insert the spill in the new block. 610 auto *NewBB = SplitEdge(II->getParent(), II->getNormalDest()); 611 InsertPt = NewBB->getTerminator()->getIterator(); 612 } else if (isa<PHINode>(I)) { 613 // Skip the PHINodes and EH pads instructions. 614 BasicBlock *DefBlock = I->getParent(); 615 if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator())) 616 InsertPt = splitBeforeCatchSwitch(CSI)->getIterator(); 617 else 618 InsertPt = DefBlock->getFirstInsertionPt(); 619 } else { 620 assert(!I->isTerminator() && "unexpected terminator"); 621 // For all other values, the spill is placed immediately after 622 // the definition. 623 InsertPt = I->getNextNode()->getIterator(); 624 } 625 } 626 627 return InsertPt; 628 } 629 630 } // End namespace coro. 631 632 } // End namespace llvm. 633