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 precedes 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
@@ -124,7 +125,8 @@ class SuspendCrossingInfo {
124
125
public:
125
126
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
126
127
void dump () const ;
127
- void dump (StringRef Label, BitVector const &BV) const ;
128
+ void dump (StringRef Label, BitVector const &BV,
129
+ const ReversePostOrderTraversal<Function *> &RPOT) const ;
128
130
#endif
129
131
130
132
SuspendCrossingInfo (Function &F, coro::Shape &Shape);
@@ -207,21 +209,41 @@ class SuspendCrossingInfo {
207
209
} // end anonymous namespace
208
210
209
211
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
210
- LLVM_DUMP_METHOD void SuspendCrossingInfo::dump (StringRef Label,
211
- BitVector const &BV) const {
212
+ static std::string getBasicBlockLabel (const BasicBlock *BB) {
213
+ if (BB->hasName ())
214
+ return BB->getName ().str ();
215
+
216
+ std::string S;
217
+ raw_string_ostream OS (S);
218
+ BB->printAsOperand (OS, false );
219
+ return OS.str ().substr (1 );
220
+ }
221
+
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
234
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 );
235
+ if (Block.empty ())
236
+ return ;
237
+
238
+ BasicBlock *const B = Mapping.indexToBlock (0 );
239
+ Function *F = B->getParent ();
240
+
241
+ ReversePostOrderTraversal<Function *> RPOT (F);
242
+ for (const BasicBlock *BB : RPOT) {
243
+ auto BBNo = Mapping.blockToIndex (BB);
244
+ dbgs () << getBasicBlockLabel (BB) << " :\n " ;
245
+ dump (" Consumes" , Block[BBNo].Consumes , RPOT);
246
+ dump (" Kills" , Block[BBNo].Kills , RPOT);
225
247
}
226
248
dbgs () << " \n " ;
227
249
}
@@ -418,10 +440,7 @@ struct RematGraph {
418
440
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
419
441
void dump () const {
420
442
dbgs () << " Entry (" ;
421
- if (EntryNode->Node ->getParent ()->hasName ())
422
- dbgs () << EntryNode->Node ->getParent ()->getName ();
423
- else
424
- EntryNode->Node ->getParent ()->printAsOperand (dbgs (), false );
443
+ dbgs () << getBasicBlockLabel (EntryNode->Node ->getParent ());
425
444
dbgs () << " ) : " << *EntryNode->Node << " \n " ;
426
445
for (auto &E : Remats) {
427
446
dbgs () << *(E.first ) << " \n " ;
@@ -551,7 +570,7 @@ struct FrameDataInfo {
551
570
552
571
#ifndef NDEBUG
553
572
static void dumpSpills (StringRef Title, const SpillInfo &Spills) {
554
- dbgs () << " ------------- " << Title << " --------------\n " ;
573
+ dbgs () << " ------------- " << Title << " --------------\n " ;
555
574
for (const auto &E : Spills) {
556
575
E.first ->dump ();
557
576
dbgs () << " user: " ;
@@ -813,7 +832,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
813
832
StackLifetime StackLifetimeAnalyzer (F, ExtractAllocas (),
814
833
StackLifetime::LivenessType::May);
815
834
StackLifetimeAnalyzer.run ();
816
- auto IsAllocaInferenre = [&](const AllocaInst *AI1, const AllocaInst *AI2) {
835
+ auto DoAllocasInterfere = [&](const AllocaInst *AI1, const AllocaInst *AI2) {
817
836
return StackLifetimeAnalyzer.getLiveRange (AI1).overlaps (
818
837
StackLifetimeAnalyzer.getLiveRange (AI2));
819
838
};
@@ -833,13 +852,13 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
833
852
for (const auto &A : FrameData.Allocas ) {
834
853
AllocaInst *Alloca = A.Alloca ;
835
854
bool Merged = false ;
836
- // Try to find if the Alloca is not inferenced with any existing
855
+ // Try to find if the Alloca does not interfere with any existing
837
856
// NonOverlappedAllocaSet. If it is true, insert the alloca to that
838
857
// NonOverlappedAllocaSet.
839
858
for (auto &AllocaSet : NonOverlapedAllocas) {
840
859
assert (!AllocaSet.empty () && " Processing Alloca Set is not empty.\n " );
841
- bool NoInference = none_of (AllocaSet, [&](auto Iter) {
842
- return IsAllocaInferenre (Alloca, Iter);
860
+ bool NoInterference = none_of (AllocaSet, [&](auto Iter) {
861
+ return DoAllocasInterfere (Alloca, Iter);
843
862
});
844
863
// If the alignment of A is multiple of the alignment of B, the address
845
864
// of A should satisfy the requirement for aligning for B.
@@ -852,7 +871,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
852
871
return LargestAlloca->getAlign ().value () % Alloca->getAlign ().value () ==
853
872
0 ;
854
873
}();
855
- bool CouldMerge = NoInference && Alignable;
874
+ bool CouldMerge = NoInterference && Alignable;
856
875
if (!CouldMerge)
857
876
continue ;
858
877
AllocaSet.push_back (Alloca);
@@ -1714,6 +1733,51 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
1714
1733
return CleanupRet;
1715
1734
}
1716
1735
1736
+ static BasicBlock::iterator getSpillInsertionPt (const coro::Shape &Shape,
1737
+ Value *Def,
1738
+ const DominatorTree &DT) {
1739
+ BasicBlock::iterator InsertPt;
1740
+ if (auto *Arg = dyn_cast<Argument>(Def)) {
1741
+ // For arguments, we will place the store instruction right after
1742
+ // the coroutine frame pointer instruction, i.e. coro.begin.
1743
+ InsertPt = Shape.getInsertPtAfterFramePtr ();
1744
+
1745
+ // If we're spilling an Argument, make sure we clear 'nocapture'
1746
+ // from the coroutine function.
1747
+ Arg->getParent ()->removeParamAttr (Arg->getArgNo (), Attribute::NoCapture);
1748
+ } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
1749
+ // Don't spill immediately after a suspend; splitting assumes
1750
+ // that the suspend will be followed by a branch.
1751
+ InsertPt = CSI->getParent ()->getSingleSuccessor ()->getFirstNonPHIIt ();
1752
+ } else {
1753
+ auto *I = cast<Instruction>(Def);
1754
+ if (!DT.dominates (Shape.CoroBegin , I)) {
1755
+ // If it is not dominated by CoroBegin, then spill should be
1756
+ // inserted immediately after CoroFrame is computed.
1757
+ InsertPt = Shape.getInsertPtAfterFramePtr ();
1758
+ } else if (auto *II = dyn_cast<InvokeInst>(I)) {
1759
+ // If we are spilling the result of the invoke instruction, split
1760
+ // the normal edge and insert the spill in the new block.
1761
+ auto *NewBB = SplitEdge (II->getParent (), II->getNormalDest ());
1762
+ InsertPt = NewBB->getTerminator ()->getIterator ();
1763
+ } else if (isa<PHINode>(I)) {
1764
+ // Skip the PHINodes and EH pads instructions.
1765
+ BasicBlock *DefBlock = I->getParent ();
1766
+ if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator ()))
1767
+ InsertPt = splitBeforeCatchSwitch (CSI)->getIterator ();
1768
+ else
1769
+ InsertPt = DefBlock->getFirstInsertionPt ();
1770
+ } else {
1771
+ assert (!I->isTerminator () && " unexpected terminator" );
1772
+ // For all other values, the spill is placed immediately after
1773
+ // the definition.
1774
+ InsertPt = I->getNextNode ()->getIterator ();
1775
+ }
1776
+ }
1777
+
1778
+ return InsertPt;
1779
+ }
1780
+
1717
1781
// Replace all alloca and SSA values that are accessed across suspend points
1718
1782
// with GetElementPointer from coroutine frame + loads and stores. Create an
1719
1783
// AllocaSpillBB that will become the new entry block for the resume parts of
@@ -1736,9 +1800,8 @@ static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) {
1736
1800
//
1737
1801
//
1738
1802
static void insertSpills (const FrameDataInfo &FrameData, coro::Shape &Shape) {
1739
- auto *CB = Shape.CoroBegin ;
1740
- LLVMContext &C = CB->getContext ();
1741
- Function *F = CB->getFunction ();
1803
+ LLVMContext &C = Shape.CoroBegin ->getContext ();
1804
+ Function *F = Shape.CoroBegin ->getFunction ();
1742
1805
IRBuilder<> Builder (C);
1743
1806
StructType *FrameTy = Shape.FrameTy ;
1744
1807
Value *FramePtr = Shape.FramePtr ;
@@ -1799,47 +1862,16 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
1799
1862
auto SpillAlignment = Align (FrameData.getAlign (Def));
1800
1863
// Create a store instruction storing the value into the
1801
1864
// coroutine frame.
1802
- BasicBlock::iterator InsertPt;
1865
+ BasicBlock::iterator InsertPt = getSpillInsertionPt (Shape, Def, DT);
1866
+
1803
1867
Type *ByValTy = nullptr ;
1804
1868
if (auto *Arg = dyn_cast<Argument>(Def)) {
1805
- // For arguments, we will place the store instruction right after
1806
- // the coroutine frame pointer instruction, i.e. coro.begin.
1807
- InsertPt = Shape.getInsertPtAfterFramePtr ();
1808
-
1809
1869
// If we're spilling an Argument, make sure we clear 'nocapture'
1810
1870
// from the coroutine function.
1811
1871
Arg->getParent ()->removeParamAttr (Arg->getArgNo (), Attribute::NoCapture);
1812
1872
1813
1873
if (Arg->hasByValAttr ())
1814
1874
ByValTy = Arg->getParamByValType ();
1815
- } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) {
1816
- // Don't spill immediately after a suspend; splitting assumes
1817
- // that the suspend will be followed by a branch.
1818
- InsertPt = CSI->getParent ()->getSingleSuccessor ()->getFirstNonPHIIt ();
1819
- } else {
1820
- auto *I = cast<Instruction>(Def);
1821
- if (!DT.dominates (CB, I)) {
1822
- // If it is not dominated by CoroBegin, then spill should be
1823
- // inserted immediately after CoroFrame is computed.
1824
- InsertPt = Shape.getInsertPtAfterFramePtr ();
1825
- } else if (auto *II = dyn_cast<InvokeInst>(I)) {
1826
- // If we are spilling the result of the invoke instruction, split
1827
- // the normal edge and insert the spill in the new block.
1828
- auto *NewBB = SplitEdge (II->getParent (), II->getNormalDest ());
1829
- InsertPt = NewBB->getTerminator ()->getIterator ();
1830
- } else if (isa<PHINode>(I)) {
1831
- // Skip the PHINodes and EH pads instructions.
1832
- BasicBlock *DefBlock = I->getParent ();
1833
- if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator ()))
1834
- InsertPt = splitBeforeCatchSwitch (CSI)->getIterator ();
1835
- else
1836
- InsertPt = DefBlock->getFirstInsertionPt ();
1837
- } else {
1838
- assert (!I->isTerminator () && " unexpected terminator" );
1839
- // For all other values, the spill is placed immediately after
1840
- // the definition.
1841
- InsertPt = I->getNextNode ()->getIterator ();
1842
- }
1843
1875
}
1844
1876
1845
1877
auto Index = FrameData.getFieldIndex (Def);
@@ -1982,7 +2014,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
1982
2014
UsersToUpdate.clear ();
1983
2015
for (User *U : Alloca->users ()) {
1984
2016
auto *I = cast<Instruction>(U);
1985
- if (DT.dominates (CB , I))
2017
+ if (DT.dominates (Shape. CoroBegin , I))
1986
2018
UsersToUpdate.push_back (I);
1987
2019
}
1988
2020
if (UsersToUpdate.empty ())
@@ -2024,7 +2056,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
2024
2056
Builder.CreateStore (Value, G);
2025
2057
}
2026
2058
// For each alias to Alloca created before CoroBegin but used after
2027
- // CoroBegin, we recreate them after CoroBegin by appplying the offset
2059
+ // CoroBegin, we recreate them after CoroBegin by applying the offset
2028
2060
// to the pointer in the frame.
2029
2061
for (const auto &Alias : A.Aliases ) {
2030
2062
auto *FramePtr = GetFramePointer (Alloca);
@@ -2033,7 +2065,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
2033
2065
auto *AliasPtr =
2034
2066
Builder.CreatePtrAdd (FramePtr, ConstantInt::get (ITy, Value));
2035
2067
Alias.first ->replaceUsesWithIf (
2036
- AliasPtr, [&](Use &U) { return DT.dominates (CB , U); });
2068
+ AliasPtr, [&](Use &U) { return DT.dominates (Shape. CoroBegin , U); });
2037
2069
}
2038
2070
}
2039
2071
@@ -2046,7 +2078,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
2046
2078
// If there is memory accessing to promise alloca before CoroBegin;
2047
2079
bool HasAccessingPromiseBeforeCB = llvm::any_of (PA->uses (), [&](Use &U) {
2048
2080
auto *Inst = dyn_cast<Instruction>(U.getUser ());
2049
- if (!Inst || DT.dominates (CB , Inst))
2081
+ if (!Inst || DT.dominates (Shape. CoroBegin , Inst))
2050
2082
return false ;
2051
2083
2052
2084
if (auto *CI = dyn_cast<CallInst>(Inst)) {
@@ -2692,7 +2724,7 @@ static void eliminateSwiftError(Function &F, coro::Shape &Shape) {
2692
2724
}
2693
2725
}
2694
2726
2695
- // / retcon and retcon.once conventions assume that all spill uses can be sunk
2727
+ // / Async and Retcon{Once} conventions assume that all spill uses can be sunk
2696
2728
// / after the coro.begin intrinsic.
2697
2729
static void sinkSpillUsesAfterCoroBegin (Function &F,
2698
2730
const FrameDataInfo &FrameData,
@@ -2728,7 +2760,7 @@ static void sinkSpillUsesAfterCoroBegin(Function &F,
2728
2760
// Sort by dominance.
2729
2761
SmallVector<Instruction *, 64 > InsertionList (ToMove.begin (), ToMove.end ());
2730
2762
llvm::sort (InsertionList, [&Dom](Instruction *A, Instruction *B) -> bool {
2731
- // If a dominates b it should preceed (<) b.
2763
+ // If a dominates b it should precede (<) b.
2732
2764
return Dom.dominates (A, B);
2733
2765
});
2734
2766
@@ -3126,7 +3158,7 @@ void coro::buildCoroutineFrame(
3126
3158
cleanupSinglePredPHIs (F);
3127
3159
3128
3160
// Transforms multi-edge PHI Nodes, so that any value feeding into a PHI will
3129
- // never has its definition separated from the PHI by the suspend point.
3161
+ // never have its definition separated from the PHI by the suspend point.
3130
3162
rewritePHIs (F);
3131
3163
3132
3164
// Build suspend crossing info.
@@ -3223,6 +3255,7 @@ void coro::buildCoroutineFrame(
3223
3255
Shape.FramePtr = Shape.CoroBegin ;
3224
3256
// For now, this works for C++ programs only.
3225
3257
buildFrameDebugInfo (F, Shape, FrameData);
3258
+ // Insert spills and reloads
3226
3259
insertSpills (FrameData, Shape);
3227
3260
lowerLocalAllocas (LocalAllocas, DeadInstructions);
3228
3261
0 commit comments