xref: /llvm-project/llvm/lib/Transforms/Coroutines/SpillUtils.cpp (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
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