6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
// 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.
10
11
//
11
12
// Using the information discovered we form a Coroutine Frame structure to
12
13
// contain those values. All uses of those values are replaced with appropriate
@@ -52,6 +53,16 @@ extern cl::opt<bool> UseNewDbgInfoFormat;
52
53
53
54
enum { SmallVectorThreshold = 32 };
54
55
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
+
55
66
// Provides two way mapping between the blocks and numbers.
56
67
namespace {
57
68
class BlockToIndexMapping {
@@ -123,8 +134,9 @@ class SuspendCrossingInfo {
123
134
124
135
public:
125
136
#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 ;
128
140
#endif
129
141
130
142
SuspendCrossingInfo (Function &F, coro::Shape &Shape);
@@ -207,21 +219,25 @@ class SuspendCrossingInfo {
207
219
} // end anonymous namespace
208
220
209
221
#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 {
212
225
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
+ }
216
231
dbgs () << " \n " ;
217
232
}
218
233
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);
225
241
}
226
242
dbgs () << " \n " ;
227
243
}
@@ -335,7 +351,7 @@ SuspendCrossingInfo::SuspendCrossingInfo(Function &F, coro::Shape &Shape)
335
351
while (computeBlockData</* Initialize*/ false >(RPOT))
336
352
;
337
353
338
- LLVM_DEBUG (dump ());
354
+ LLVM_DEBUG (dump (RPOT ));
339
355
}
340
356
341
357
namespace {
@@ -419,7 +435,7 @@ struct RematGraph {
419
435
void dump () const {
420
436
dbgs () << " Entry (" ;
421
437
if (EntryNode->Node ->getParent ()->hasName ())
422
- dbgs () << EntryNode->Node ->getParent ()-> getName ( );
438
+ dbgs () << getBasicBlockLabel ( EntryNode->Node ->getParent ());
423
439
else
424
440
EntryNode->Node ->getParent ()->printAsOperand (dbgs (), false );
425
441
dbgs () << " ) : " << *EntryNode->Node << " \n " ;
@@ -551,7 +567,7 @@ struct FrameDataInfo {
551
567
552
568
#ifndef NDEBUG
553
569
static void dumpSpills (StringRef Title, const SpillInfo &Spills) {
554
- dbgs () << " ------------- " << Title << " --------------\n " ;
570
+ dbgs () << " ------------- " << Title << " --------------\n " ;
555
571
for (const auto &E : Spills) {
556
572
E.first ->dump ();
557
573
dbgs () << " user: " ;
@@ -813,7 +829,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
813
829
StackLifetime StackLifetimeAnalyzer (F, ExtractAllocas (),
814
830
StackLifetime::LivenessType::May);
815
831
StackLifetimeAnalyzer.run ();
816
- auto IsAllocaInferenre = [&](const AllocaInst *AI1, const AllocaInst *AI2) {
832
+ auto DoAllocasInterfere = [&](const AllocaInst *AI1, const AllocaInst *AI2) {
817
833
return StackLifetimeAnalyzer.getLiveRange (AI1).overlaps (
818
834
StackLifetimeAnalyzer.getLiveRange (AI2));
819
835
};
@@ -833,13 +849,13 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
833
849
for (const auto &A : FrameData.Allocas ) {
834
850
AllocaInst *Alloca = A.Alloca ;
835
851
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
837
853
// NonOverlappedAllocaSet. If it is true, insert the alloca to that
838
854
// NonOverlappedAllocaSet.
839
855
for (auto &AllocaSet : NonOverlapedAllocas) {
840
856
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);
843
859
});
844
860
// If the alignment of A is multiple of the alignment of B, the address
845
861
// of A should satisfy the requirement for aligning for B.
@@ -852,7 +868,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
852
868
return LargestAlloca->getAlign ().value () % Alloca->getAlign ().value () ==
853
869
0 ;
854
870
}();
855
- bool CouldMerge = NoInference && Alignable;
871
+ bool CouldMerge = NoInterference && Alignable;
856
872
if (!CouldMerge)
857
873
continue ;
858
874
AllocaSet.push_back (Alloca);
@@ -1713,6 +1729,51 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
1713
1729
return CleanupRet;
1714
1730
}
1715
1731
1732
+ static BasicBlock::iterator getSpillInsertionPt (const coro::Shape &Shape,
1733
+ Value *Def,
1734
+ const DominatorTree &DT) {
1735
+ BasicBlock::iterator InsertPt;
1736
+ if (auto *Arg = dyn_cast<Argument>(Def)) {
1737
+ // For arguments, we will place the store instruction right after
1738
+ // the coroutine frame pointer instruction, i.e. coro.begin.
1739
+ InsertPt = Shape.getInsertPtAfterFramePtr ();
1740
+
1741
+ // If we're spilling an Argument, make sure we clear 'nocapture'
1742
+ // from the coroutine function.
1743
+ Arg->getParent ()->removeParamAttr (Arg->getArgNo (), Attribute::NoCapture);
1744
+ } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
1745
+ // Don't spill immediately after a suspend; splitting assumes
1746
+ // that the suspend will be followed by a branch.
1747
+ InsertPt = CSI->getParent ()->getSingleSuccessor ()->getFirstNonPHIIt ();
1748
+ } else {
1749
+ auto *I = cast<Instruction>(Def);
1750
+ if (!DT.dominates (Shape.CoroBegin , I)) {
1751
+ // If it is not dominated by CoroBegin, then spill should be
1752
+ // inserted immediately after CoroFrame is computed.
1753
+ InsertPt = Shape.getInsertPtAfterFramePtr ();
1754
+ } else if (auto *II = dyn_cast<InvokeInst>(I)) {
1755
+ // If we are spilling the result of the invoke instruction, split
1756
+ // the normal edge and insert the spill in the new block.
1757
+ auto *NewBB = SplitEdge (II->getParent (), II->getNormalDest ());
1758
+ InsertPt = NewBB->getTerminator ()->getIterator ();
1759
+ } else if (isa<PHINode>(I)) {
1760
+ // Skip the PHINodes and EH pads instructions.
1761
+ BasicBlock *DefBlock = I->getParent ();
1762
+ if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator ()))
1763
+ InsertPt = splitBeforeCatchSwitch (CSI)->getIterator ();
1764
+ else
1765
+ InsertPt = DefBlock->getFirstInsertionPt ();
1766
+ } else {
1767
+ assert (!I->isTerminator () && " unexpected terminator" );
1768
+ // For all other values, the spill is placed immediately after
1769
+ // the definition.
1770
+ InsertPt = I->getNextNode ()->getIterator ();
1771
+ }
1772
+ }
1773
+
1774
+ return InsertPt;
1775
+ }
1776
+
1716
1777
// Replace all alloca and SSA values that are accessed across suspend points
1717
1778
// with GetElementPointer from coroutine frame + loads and stores. Create an
1718
1779
// AllocaSpillBB that will become the new entry block for the resume parts of
@@ -1735,9 +1796,8 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
1735
1796
//
1736
1797
//
1737
1798
static void insertSpills (const FrameDataInfo &FrameData, coro::Shape &Shape) {
1738
- auto *CB = Shape.CoroBegin ;
1739
- LLVMContext &C = CB->getContext ();
1740
- Function *F = CB->getFunction ();
1799
+ LLVMContext &C = Shape.CoroBegin ->getContext ();
1800
+ Function *F = Shape.CoroBegin ->getFunction ();
1741
1801
IRBuilder<> Builder (C);
1742
1802
StructType *FrameTy = Shape.FrameTy ;
1743
1803
Value *FramePtr = Shape.FramePtr ;
@@ -1798,47 +1858,16 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
1798
1858
auto SpillAlignment = Align (FrameData.getAlign (Def));
1799
1859
// Create a store instruction storing the value into the
1800
1860
// coroutine frame.
1801
- BasicBlock::iterator InsertPt;
1861
+ BasicBlock::iterator InsertPt = getSpillInsertionPt (Shape, Def, DT);
1862
+
1802
1863
Type *ByValTy = nullptr ;
1803
1864
if (auto *Arg = dyn_cast<Argument>(Def)) {
1804
- // For arguments, we will place the store instruction right after
1805
- // the coroutine frame pointer instruction, i.e. coro.begin.
1806
- InsertPt = Shape.getInsertPtAfterFramePtr ();
1807
-
1808
1865
// If we're spilling an Argument, make sure we clear 'nocapture'
1809
1866
// from the coroutine function.
1810
1867
Arg->getParent ()->removeParamAttr (Arg->getArgNo (), Attribute::NoCapture);
1811
1868
1812
1869
if (Arg->hasByValAttr ())
1813
1870
ByValTy = Arg->getParamByValType ();
1814
- } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
1815
- // Don't spill immediately after a suspend; splitting assumes
1816
- // that the suspend will be followed by a branch.
1817
- InsertPt = CSI->getParent ()->getSingleSuccessor ()->getFirstNonPHIIt ();
1818
- } else {
1819
- auto *I = cast<Instruction>(Def);
1820
- if (!DT.dominates (CB, I)) {
1821
- // If it is not dominated by CoroBegin, then spill should be
1822
- // inserted immediately after CoroFrame is computed.
1823
- InsertPt = Shape.getInsertPtAfterFramePtr ();
1824
- } else if (auto *II = dyn_cast<InvokeInst>(I)) {
1825
- // If we are spilling the result of the invoke instruction, split
1826
- // the normal edge and insert the spill in the new block.
1827
- auto *NewBB = SplitEdge (II->getParent (), II->getNormalDest ());
1828
- InsertPt = NewBB->getTerminator ()->getIterator ();
1829
- } else if (isa<PHINode>(I)) {
1830
- // Skip the PHINodes and EH pads instructions.
1831
- BasicBlock *DefBlock = I->getParent ();
1832
- if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator ()))
1833
- InsertPt = splitBeforeCatchSwitch (CSI)->getIterator ();
1834
- else
1835
- InsertPt = DefBlock->getFirstInsertionPt ();
1836
- } else {
1837
- assert (!I->isTerminator () && " unexpected terminator" );
1838
- // For all other values, the spill is placed immediately after
1839
- // the definition.
1840
- InsertPt = I->getNextNode ()->getIterator ();
1841
- }
1842
1871
}
1843
1872
1844
1873
auto Index = FrameData.getFieldIndex (Def);
@@ -1980,7 +2009,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
1980
2009
UsersToUpdate.clear ();
1981
2010
for (User *U : Alloca->users ()) {
1982
2011
auto *I = cast<Instruction>(U);
1983
- if (DT.dominates (CB , I))
2012
+ if (DT.dominates (Shape. CoroBegin , I))
1984
2013
UsersToUpdate.push_back (I);
1985
2014
}
1986
2015
if (UsersToUpdate.empty ())
@@ -2022,7 +2051,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
2022
2051
Builder.CreateStore (Value, G);
2023
2052
}
2024
2053
// For each alias to Alloca created before CoroBegin but used after
2025
- // CoroBegin, we recreate them after CoroBegin by appplying the offset
2054
+ // CoroBegin, we recreate them after CoroBegin by applying the offset
2026
2055
// to the pointer in the frame.
2027
2056
for (const auto &Alias : A.Aliases ) {
2028
2057
auto *FramePtr = GetFramePointer (Alloca);
@@ -2031,7 +2060,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
2031
2060
auto *AliasPtr =
2032
2061
Builder.CreatePtrAdd (FramePtr, ConstantInt::get (ITy, Value));
2033
2062
Alias.first ->replaceUsesWithIf (
2034
- AliasPtr, [&](Use &U) { return DT.dominates (CB , U); });
2063
+ AliasPtr, [&](Use &U) { return DT.dominates (Shape. CoroBegin , U); });
2035
2064
}
2036
2065
}
2037
2066
@@ -2044,7 +2073,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
2044
2073
// If there is memory accessing to promise alloca before CoroBegin;
2045
2074
bool HasAccessingPromiseBeforeCB = llvm::any_of (PA->uses (), [&](Use &U) {
2046
2075
auto *Inst = dyn_cast<Instruction>(U.getUser ());
2047
- if (!Inst || DT.dominates (CB , Inst))
2076
+ if (!Inst || DT.dominates (Shape. CoroBegin , Inst))
2048
2077
return false ;
2049
2078
2050
2079
if (auto *CI = dyn_cast<CallInst>(Inst)) {
@@ -2087,8 +2116,9 @@ static void movePHIValuesToInsertedBlock(BasicBlock *SuccBB,
2087
2116
do {
2088
2117
int Index = PN->getBasicBlockIndex (InsertedBB);
2089
2118
Value *V = PN->getIncomingValue (Index);
2090
- PHINode *InputV = PHINode::Create (
2091
- V->getType (), 1 , V->getName () + Twine (" ." ) + SuccBB->getName ());
2119
+ PHINode *InputV =
2120
+ PHINode::Create (V->getType (), 1 ,
2121
+ V->getName () + Twine (" ." ) + getBasicBlockLabel (SuccBB));
2092
2122
InputV->insertBefore (InsertedBB->begin ());
2093
2123
InputV->addIncoming (V, PredBB);
2094
2124
PN->setIncomingValue (Index, InputV);
@@ -2133,10 +2163,10 @@ static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB,
2133
2163
Builder.CreateUnreachable ();
2134
2164
2135
2165
// Create a new cleanuppad which will be the dispatcher.
2136
- auto *NewCleanupPadBB =
2137
- BasicBlock::Create ( CleanupPadBB->getContext (),
2138
- CleanupPadBB-> getName ( ) + Twine (" .corodispatch" ),
2139
- CleanupPadBB->getParent (), CleanupPadBB);
2166
+ auto *NewCleanupPadBB = BasicBlock::Create (
2167
+ CleanupPadBB->getContext (),
2168
+ getBasicBlockLabel (CleanupPadBB ) + Twine (" .corodispatch" ),
2169
+ CleanupPadBB->getParent (), CleanupPadBB);
2140
2170
Builder.SetInsertPoint (NewCleanupPadBB);
2141
2171
auto *SwitchType = Builder.getInt8Ty ();
2142
2172
auto *SetDispatchValuePN =
@@ -2150,13 +2180,14 @@ static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB,
2150
2180
SmallVector<BasicBlock *, 8 > Preds (predecessors (CleanupPadBB));
2151
2181
for (BasicBlock *Pred : Preds) {
2152
2182
// Create a new cleanuppad and move the PHI values to there.
2153
- auto *CaseBB = BasicBlock::Create (CleanupPadBB->getContext (),
2154
- CleanupPadBB->getName () +
2155
- Twine (" .from." ) + Pred->getName (),
2156
- CleanupPadBB->getParent (), CleanupPadBB);
2183
+ auto *CaseBB =
2184
+ BasicBlock::Create (CleanupPadBB->getContext (),
2185
+ getBasicBlockLabel (CleanupPadBB) + Twine (" .from." ) +
2186
+ getBasicBlockLabel (Pred),
2187
+ CleanupPadBB->getParent (), CleanupPadBB);
2157
2188
updatePhiNodes (CleanupPadBB, Pred, CaseBB);
2158
- CaseBB->setName (CleanupPadBB-> getName ( ) + Twine (" .from." ) +
2159
- Pred-> getName ( ));
2189
+ CaseBB->setName (getBasicBlockLabel (CleanupPadBB ) + Twine (" .from." ) +
2190
+ getBasicBlockLabel (Pred ));
2160
2191
Builder.SetInsertPoint (CaseBB);
2161
2192
Builder.CreateBr (CleanupPadBB);
2162
2193
movePHIValuesToInsertedBlock (CleanupPadBB, CaseBB, NewCleanupPadBB);
@@ -2246,7 +2277,8 @@ static void rewritePHIs(BasicBlock &BB) {
2246
2277
SmallVector<BasicBlock *, 8 > Preds (predecessors (&BB));
2247
2278
for (BasicBlock *Pred : Preds) {
2248
2279
auto *IncomingBB = ehAwareSplitEdge (Pred, &BB, LandingPad, ReplPHI);
2249
- IncomingBB->setName (BB.getName () + Twine (" .from." ) + Pred->getName ());
2280
+ IncomingBB->setName (getBasicBlockLabel (&BB) + Twine (" .from." ) +
2281
+ getBasicBlockLabel (Pred));
2250
2282
2251
2283
// Stop the moving of values at ReplPHI, as this is either null or the PHI
2252
2284
// that replaced the landing pad.
@@ -2690,7 +2722,7 @@ static void eliminateSwiftError(Function &F, coro::Shape &Shape) {
2690
2722
}
2691
2723
}
2692
2724
2693
- // / retcon and retcon.once conventions assume that all spill uses can be sunk
2725
+ // / Async and Retcon{Once} conventions assume that all spill uses can be sunk
2694
2726
// / after the coro.begin intrinsic.
2695
2727
static void sinkSpillUsesAfterCoroBegin (Function &F,
2696
2728
const FrameDataInfo &FrameData,
@@ -3122,7 +3154,7 @@ void coro::buildCoroutineFrame(
3122
3154
cleanupSinglePredPHIs (F);
3123
3155
3124
3156
// Transforms multi-edge PHI Nodes, so that any value feeding into a PHI will
3125
- // never has its definition separated from the PHI by the suspend point.
3157
+ // never have its definition separated from the PHI by the suspend point.
3126
3158
rewritePHIs (F);
3127
3159
3128
3160
// Build suspend crossing info.
@@ -3219,6 +3251,7 @@ void coro::buildCoroutineFrame(
3219
3251
Shape.FramePtr = Shape.CoroBegin ;
3220
3252
// For now, this works for C++ programs only.
3221
3253
buildFrameDebugInfo (F, Shape, FrameData);
3254
+ // Insert spills and reloads
3222
3255
insertSpills (FrameData, Shape);
3223
3256
lowerLocalAllocas (LocalAllocas, DeadInstructions);
3224
3257
0 commit comments