66//
77// ===----------------------------------------------------------------------===//
88// This file contains classes used to discover if for a particular value
9- // there from sue to definition that crosses a suspend block.
9+ // its definition preceeds and its uses follow a suspend block. This is
10+ // referred to as a suspend crossing value.
1011//
1112// Using the information discovered we form a Coroutine Frame structure to
1213// contain those values. All uses of those values are replaced with appropriate
@@ -52,6 +53,16 @@ extern cl::opt<bool> UseNewDbgInfoFormat;
5253
5354enum { SmallVectorThreshold = 32 };
5455
56+ static std::string getBasicBlockLabel (const BasicBlock *BB) {
57+ if (BB->hasName ())
58+ return BB->getName ().str ();
59+
60+ std::string S;
61+ raw_string_ostream OS (S);
62+ BB->printAsOperand (OS, false );
63+ return OS.str ().substr (1 );
64+ }
65+
5566// Provides two way mapping between the blocks and numbers.
5667namespace {
5768class BlockToIndexMapping {
@@ -123,8 +134,9 @@ class SuspendCrossingInfo {
123134
124135public:
125136#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
126- void dump () const ;
127- void dump (StringRef Label, BitVector const &BV) const ;
137+ void dump (const ReversePostOrderTraversal<Function *> &RPOT) const ;
138+ void dump (StringRef Label, BitVector const &BV,
139+ const ReversePostOrderTraversal<Function *> &RPOT) const ;
128140#endif
129141
130142 SuspendCrossingInfo (Function &F, coro::Shape &Shape);
@@ -207,21 +219,25 @@ class SuspendCrossingInfo {
207219} // end anonymous namespace
208220
209221#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
210- LLVM_DUMP_METHOD void SuspendCrossingInfo::dump (StringRef Label,
211- BitVector const &BV) const {
222+ LLVM_DUMP_METHOD void SuspendCrossingInfo::dump (
223+ StringRef Label, BitVector const &BV,
224+ const ReversePostOrderTraversal<Function *> &RPOT) const {
212225 dbgs () << Label << " :" ;
213- for (size_t I = 0 , N = BV.size (); I < N; ++I)
214- if (BV[I])
215- dbgs () << " " << Mapping.indexToBlock (I)->getName ();
226+ for (const BasicBlock *BB : RPOT) {
227+ auto BBNo = Mapping.blockToIndex (BB);
228+ if (BV[BBNo])
229+ dbgs () << " " << getBasicBlockLabel (BB);
230+ }
216231 dbgs () << " \n " ;
217232}
218233
219- LLVM_DUMP_METHOD void SuspendCrossingInfo::dump () const {
220- for (size_t I = 0 , N = Block.size (); I < N; ++I) {
221- BasicBlock *const B = Mapping.indexToBlock (I);
222- dbgs () << B->getName () << " :\n " ;
223- dump (" Consumes" , Block[I].Consumes );
224- dump (" Kills" , Block[I].Kills );
234+ LLVM_DUMP_METHOD void SuspendCrossingInfo::dump (
235+ const ReversePostOrderTraversal<Function *> &RPOT) const {
236+ for (const BasicBlock *BB : RPOT) {
237+ auto BBNo = Mapping.blockToIndex (BB);
238+ dbgs () << getBasicBlockLabel (BB) << " :\n " ;
239+ dump (" Consumes" , Block[BBNo].Consumes , RPOT);
240+ dump (" Kills" , Block[BBNo].Kills , RPOT);
225241 }
226242 dbgs () << " \n " ;
227243}
@@ -335,7 +351,7 @@ SuspendCrossingInfo::SuspendCrossingInfo(Function &F, coro::Shape &Shape)
335351 while (computeBlockData</* Initialize*/ false >(RPOT))
336352 ;
337353
338- LLVM_DEBUG (dump ());
354+ LLVM_DEBUG (dump (RPOT ));
339355}
340356
341357namespace {
@@ -419,7 +435,7 @@ struct RematGraph {
419435 void dump () const {
420436 dbgs () << " Entry (" ;
421437 if (EntryNode->Node ->getParent ()->hasName ())
422- dbgs () << EntryNode->Node ->getParent ()-> getName ( );
438+ dbgs () << getBasicBlockLabel ( EntryNode->Node ->getParent ());
423439 else
424440 EntryNode->Node ->getParent ()->printAsOperand (dbgs (), false );
425441 dbgs () << " ) : " << *EntryNode->Node << " \n " ;
@@ -551,7 +567,7 @@ struct FrameDataInfo {
551567
552568#ifndef NDEBUG
553569static void dumpSpills (StringRef Title, const SpillInfo &Spills) {
554- dbgs () << " ------------- " << Title << " --------------\n " ;
570+ dbgs () << " ------------- " << Title << " --------------\n " ;
555571 for (const auto &E : Spills) {
556572 E.first ->dump ();
557573 dbgs () << " user: " ;
@@ -813,7 +829,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
813829 StackLifetime StackLifetimeAnalyzer (F, ExtractAllocas (),
814830 StackLifetime::LivenessType::May);
815831 StackLifetimeAnalyzer.run ();
816- auto IsAllocaInferenre = [&](const AllocaInst *AI1, const AllocaInst *AI2) {
832+ auto DoAllocasInterfere = [&](const AllocaInst *AI1, const AllocaInst *AI2) {
817833 return StackLifetimeAnalyzer.getLiveRange (AI1).overlaps (
818834 StackLifetimeAnalyzer.getLiveRange (AI2));
819835 };
@@ -833,13 +849,13 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
833849 for (const auto &A : FrameData.Allocas ) {
834850 AllocaInst *Alloca = A.Alloca ;
835851 bool Merged = false ;
836- // Try to find if the Alloca is not inferenced with any existing
852+ // Try to find if the Alloca does not interfere with any existing
837853 // NonOverlappedAllocaSet. If it is true, insert the alloca to that
838854 // NonOverlappedAllocaSet.
839855 for (auto &AllocaSet : NonOverlapedAllocas) {
840856 assert (!AllocaSet.empty () && " Processing Alloca Set is not empty.\n " );
841- bool NoInference = none_of (AllocaSet, [&](auto Iter) {
842- return IsAllocaInferenre (Alloca, Iter);
857+ bool NoInterference = none_of (AllocaSet, [&](auto Iter) {
858+ return DoAllocasInterfere (Alloca, Iter);
843859 });
844860 // If the alignment of A is multiple of the alignment of B, the address
845861 // of A should satisfy the requirement for aligning for B.
@@ -852,7 +868,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
852868 return LargestAlloca->getAlign ().value () % Alloca->getAlign ().value () ==
853869 0 ;
854870 }();
855- bool CouldMerge = NoInference && Alignable;
871+ bool CouldMerge = NoInterference && Alignable;
856872 if (!CouldMerge)
857873 continue ;
858874 AllocaSet.push_back (Alloca);
@@ -1730,6 +1746,51 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
17301746 return CleanupRet;
17311747}
17321748
1749+ static BasicBlock::iterator getSpillInsertionPt (const coro::Shape &Shape,
1750+ Value *Def,
1751+ const DominatorTree &DT) {
1752+ BasicBlock::iterator InsertPt;
1753+ if (auto *Arg = dyn_cast<Argument>(Def)) {
1754+ // For arguments, we will place the store instruction right after
1755+ // the coroutine frame pointer instruction, i.e. coro.begin.
1756+ InsertPt = Shape.getInsertPtAfterFramePtr ();
1757+
1758+ // If we're spilling an Argument, make sure we clear 'nocapture'
1759+ // from the coroutine function.
1760+ Arg->getParent ()->removeParamAttr (Arg->getArgNo (), Attribute::NoCapture);
1761+ } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
1762+ // Don't spill immediately after a suspend; splitting assumes
1763+ // that the suspend will be followed by a branch.
1764+ InsertPt = CSI->getParent ()->getSingleSuccessor ()->getFirstNonPHIIt ();
1765+ } else {
1766+ auto *I = cast<Instruction>(Def);
1767+ if (!DT.dominates (Shape.CoroBegin , I)) {
1768+ // If it is not dominated by CoroBegin, then spill should be
1769+ // inserted immediately after CoroFrame is computed.
1770+ InsertPt = Shape.getInsertPtAfterFramePtr ();
1771+ } else if (auto *II = dyn_cast<InvokeInst>(I)) {
1772+ // If we are spilling the result of the invoke instruction, split
1773+ // the normal edge and insert the spill in the new block.
1774+ auto *NewBB = SplitEdge (II->getParent (), II->getNormalDest ());
1775+ InsertPt = NewBB->getTerminator ()->getIterator ();
1776+ } else if (isa<PHINode>(I)) {
1777+ // Skip the PHINodes and EH pads instructions.
1778+ BasicBlock *DefBlock = I->getParent ();
1779+ if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator ()))
1780+ InsertPt = splitBeforeCatchSwitch (CSI)->getIterator ();
1781+ else
1782+ InsertPt = DefBlock->getFirstInsertionPt ();
1783+ } else {
1784+ assert (!I->isTerminator () && " unexpected terminator" );
1785+ // For all other values, the spill is placed immediately after
1786+ // the definition.
1787+ InsertPt = I->getNextNode ()->getIterator ();
1788+ }
1789+ }
1790+
1791+ return InsertPt;
1792+ }
1793+
17331794// Replace all alloca and SSA values that are accessed across suspend points
17341795// with GetElementPointer from coroutine frame + loads and stores. Create an
17351796// AllocaSpillBB that will become the new entry block for the resume parts of
@@ -1752,9 +1813,8 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
17521813//
17531814//
17541815static void insertSpills (const FrameDataInfo &FrameData, coro::Shape &Shape) {
1755- auto *CB = Shape.CoroBegin ;
1756- LLVMContext &C = CB->getContext ();
1757- Function *F = CB->getFunction ();
1816+ LLVMContext &C = Shape.CoroBegin ->getContext ();
1817+ Function *F = Shape.CoroBegin ->getFunction ();
17581818 IRBuilder<> Builder (C);
17591819 StructType *FrameTy = Shape.FrameTy ;
17601820 Value *FramePtr = Shape.FramePtr ;
@@ -1815,47 +1875,16 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
18151875 auto SpillAlignment = Align (FrameData.getAlign (Def));
18161876 // Create a store instruction storing the value into the
18171877 // coroutine frame.
1818- BasicBlock::iterator InsertPt;
1878+ BasicBlock::iterator InsertPt = getSpillInsertionPt (Shape, Def, DT);
1879+
18191880 Type *ByValTy = nullptr ;
18201881 if (auto *Arg = dyn_cast<Argument>(Def)) {
1821- // For arguments, we will place the store instruction right after
1822- // the coroutine frame pointer instruction, i.e. coro.begin.
1823- InsertPt = Shape.getInsertPtAfterFramePtr ();
1824-
18251882 // If we're spilling an Argument, make sure we clear 'nocapture'
18261883 // from the coroutine function.
18271884 Arg->getParent ()->removeParamAttr (Arg->getArgNo (), Attribute::NoCapture);
18281885
18291886 if (Arg->hasByValAttr ())
18301887 ByValTy = Arg->getParamByValType ();
1831- } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
1832- // Don't spill immediately after a suspend; splitting assumes
1833- // that the suspend will be followed by a branch.
1834- InsertPt = CSI->getParent ()->getSingleSuccessor ()->getFirstNonPHIIt ();
1835- } else {
1836- auto *I = cast<Instruction>(Def);
1837- if (!DT.dominates (CB, I)) {
1838- // If it is not dominated by CoroBegin, then spill should be
1839- // inserted immediately after CoroFrame is computed.
1840- InsertPt = Shape.getInsertPtAfterFramePtr ();
1841- } else if (auto *II = dyn_cast<InvokeInst>(I)) {
1842- // If we are spilling the result of the invoke instruction, split
1843- // the normal edge and insert the spill in the new block.
1844- auto *NewBB = SplitEdge (II->getParent (), II->getNormalDest ());
1845- InsertPt = NewBB->getTerminator ()->getIterator ();
1846- } else if (isa<PHINode>(I)) {
1847- // Skip the PHINodes and EH pads instructions.
1848- BasicBlock *DefBlock = I->getParent ();
1849- if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator ()))
1850- InsertPt = splitBeforeCatchSwitch (CSI)->getIterator ();
1851- else
1852- InsertPt = DefBlock->getFirstInsertionPt ();
1853- } else {
1854- assert (!I->isTerminator () && " unexpected terminator" );
1855- // For all other values, the spill is placed immediately after
1856- // the definition.
1857- InsertPt = I->getNextNode ()->getIterator ();
1858- }
18591888 }
18601889
18611890 auto Index = FrameData.getFieldIndex (Def);
@@ -1998,7 +2027,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
19982027 UsersToUpdate.clear ();
19992028 for (User *U : Alloca->users ()) {
20002029 auto *I = cast<Instruction>(U);
2001- if (DT.dominates (CB , I))
2030+ if (DT.dominates (Shape. CoroBegin , I))
20022031 UsersToUpdate.push_back (I);
20032032 }
20042033 if (UsersToUpdate.empty ())
@@ -2040,7 +2069,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
20402069 Builder.CreateStore (Value, G);
20412070 }
20422071 // For each alias to Alloca created before CoroBegin but used after
2043- // CoroBegin, we recreate them after CoroBegin by appplying the offset
2072+ // CoroBegin, we recreate them after CoroBegin by applying the offset
20442073 // to the pointer in the frame.
20452074 for (const auto &Alias : A.Aliases ) {
20462075 auto *FramePtr = GetFramePointer (Alloca);
@@ -2049,7 +2078,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
20492078 auto *AliasPtr =
20502079 Builder.CreatePtrAdd (FramePtr, ConstantInt::get (ITy, Value));
20512080 Alias.first ->replaceUsesWithIf (
2052- AliasPtr, [&](Use &U) { return DT.dominates (CB , U); });
2081+ AliasPtr, [&](Use &U) { return DT.dominates (Shape. CoroBegin , U); });
20532082 }
20542083 }
20552084
@@ -2062,7 +2091,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
20622091 // If there is memory accessing to promise alloca before CoroBegin;
20632092 bool HasAccessingPromiseBeforeCB = llvm::any_of (PA->uses (), [&](Use &U) {
20642093 auto *Inst = dyn_cast<Instruction>(U.getUser ());
2065- if (!Inst || DT.dominates (CB , Inst))
2094+ if (!Inst || DT.dominates (Shape. CoroBegin , Inst))
20662095 return false ;
20672096
20682097 if (auto *CI = dyn_cast<CallInst>(Inst)) {
@@ -2105,8 +2134,9 @@ static void movePHIValuesToInsertedBlock(BasicBlock *SuccBB,
21052134 do {
21062135 int Index = PN->getBasicBlockIndex (InsertedBB);
21072136 Value *V = PN->getIncomingValue (Index);
2108- PHINode *InputV = PHINode::Create (
2109- V->getType (), 1 , V->getName () + Twine (" ." ) + SuccBB->getName ());
2137+ PHINode *InputV =
2138+ PHINode::Create (V->getType (), 1 ,
2139+ V->getName () + Twine (" ." ) + getBasicBlockLabel (SuccBB));
21102140 InputV->insertBefore (InsertedBB->begin ());
21112141 InputV->addIncoming (V, PredBB);
21122142 PN->setIncomingValue (Index, InputV);
@@ -2151,10 +2181,10 @@ static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB,
21512181 Builder.CreateUnreachable ();
21522182
21532183 // Create a new cleanuppad which will be the dispatcher.
2154- auto *NewCleanupPadBB =
2155- BasicBlock::Create ( CleanupPadBB->getContext (),
2156- CleanupPadBB-> getName ( ) + Twine (" .corodispatch" ),
2157- CleanupPadBB->getParent (), CleanupPadBB);
2184+ auto *NewCleanupPadBB = BasicBlock::Create (
2185+ CleanupPadBB->getContext (),
2186+ getBasicBlockLabel (CleanupPadBB ) + Twine (" .corodispatch" ),
2187+ CleanupPadBB->getParent (), CleanupPadBB);
21582188 Builder.SetInsertPoint (NewCleanupPadBB);
21592189 auto *SwitchType = Builder.getInt8Ty ();
21602190 auto *SetDispatchValuePN =
@@ -2168,13 +2198,14 @@ static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB,
21682198 SmallVector<BasicBlock *, 8 > Preds (predecessors (CleanupPadBB));
21692199 for (BasicBlock *Pred : Preds) {
21702200 // Create a new cleanuppad and move the PHI values to there.
2171- auto *CaseBB = BasicBlock::Create (CleanupPadBB->getContext (),
2172- CleanupPadBB->getName () +
2173- Twine (" .from." ) + Pred->getName (),
2174- CleanupPadBB->getParent (), CleanupPadBB);
2201+ auto *CaseBB =
2202+ BasicBlock::Create (CleanupPadBB->getContext (),
2203+ getBasicBlockLabel (CleanupPadBB) + Twine (" .from." ) +
2204+ getBasicBlockLabel (Pred),
2205+ CleanupPadBB->getParent (), CleanupPadBB);
21752206 updatePhiNodes (CleanupPadBB, Pred, CaseBB);
2176- CaseBB->setName (CleanupPadBB-> getName ( ) + Twine (" .from." ) +
2177- Pred-> getName ( ));
2207+ CaseBB->setName (getBasicBlockLabel (CleanupPadBB ) + Twine (" .from." ) +
2208+ getBasicBlockLabel (Pred ));
21782209 Builder.SetInsertPoint (CaseBB);
21792210 Builder.CreateBr (CleanupPadBB);
21802211 movePHIValuesToInsertedBlock (CleanupPadBB, CaseBB, NewCleanupPadBB);
@@ -2264,7 +2295,8 @@ static void rewritePHIs(BasicBlock &BB) {
22642295 SmallVector<BasicBlock *, 8 > Preds (predecessors (&BB));
22652296 for (BasicBlock *Pred : Preds) {
22662297 auto *IncomingBB = ehAwareSplitEdge (Pred, &BB, LandingPad, ReplPHI);
2267- IncomingBB->setName (BB.getName () + Twine (" .from." ) + Pred->getName ());
2298+ IncomingBB->setName (getBasicBlockLabel (&BB) + Twine (" .from." ) +
2299+ getBasicBlockLabel (Pred));
22682300
22692301 // Stop the moving of values at ReplPHI, as this is either null or the PHI
22702302 // that replaced the landing pad.
@@ -2708,7 +2740,7 @@ static void eliminateSwiftError(Function &F, coro::Shape &Shape) {
27082740 }
27092741}
27102742
2711- // / retcon and retcon.once conventions assume that all spill uses can be sunk
2743+ // / Async and Retcon{Once} conventions assume that all spill uses can be sunk
27122744// / after the coro.begin intrinsic.
27132745static void sinkSpillUsesAfterCoroBegin (Function &F,
27142746 const FrameDataInfo &FrameData,
@@ -3142,7 +3174,7 @@ void coro::buildCoroutineFrame(
31423174 cleanupSinglePredPHIs (F);
31433175
31443176 // Transforms multi-edge PHI Nodes, so that any value feeding into a PHI will
3145- // never has its definition separated from the PHI by the suspend point.
3177+ // never have its definition separated from the PHI by the suspend point.
31463178 rewritePHIs (F);
31473179
31483180 // Build suspend crossing info.
@@ -3239,6 +3271,7 @@ void coro::buildCoroutineFrame(
32393271 Shape.FramePtr = Shape.CoroBegin ;
32403272 // For now, this works for C++ programs only.
32413273 buildFrameDebugInfo (F, Shape, FrameData);
3274+ // Insert spills and reloads
32423275 insertSpills (FrameData, Shape);
32433276 lowerLocalAllocas (LocalAllocas, DeadInstructions);
32443277
0 commit comments