Skip to content

Commit 7c46d17

Browse files
committed
[loop-arc] Change Loop ARC Pairing Context to be a Loop Visitor
1 parent 1400227 commit 7c46d17

File tree

3 files changed

+77
-104
lines changed

3 files changed

+77
-104
lines changed

lib/SILPasses/ARC/ARCSequenceOpts.cpp

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,9 @@ static SILInstruction *createDecrement(SILValue Ptr, SILInstruction *InsertPt) {
7777
return B.createReleaseValue(Loc, Ptr);
7878
}
7979

80-
namespace {
81-
82-
class CodeMotionOrDeleteCallback : public ARCMatchingSetCallback {
83-
bool Changed = false;
84-
llvm::SmallVector<SILInstruction *, 16> InstructionsToDelete;
85-
86-
public:
87-
virtual void processMatchingSet(ARCMatchingSet &Set) override final;
88-
89-
// Delete instructions after we have processed all matching sets so that we do
90-
// not remove instructions that may be insertion points for other retain,
91-
// releases.
92-
virtual void finalize() override final {
93-
while (!InstructionsToDelete.empty()) {
94-
InstructionsToDelete.pop_back_val()->eraseFromParent();
95-
}
96-
}
97-
98-
bool madeChange() const { return Changed; }
99-
};
100-
}
80+
//===----------------------------------------------------------------------===//
81+
// Mutating Callback
82+
//===----------------------------------------------------------------------===//
10183

10284
// This routine takes in the ARCMatchingSet \p MatchSet and inserts new
10385
// increments, decrements at the insertion points and adds the old increment,
@@ -222,35 +204,8 @@ processFunctionWithLoopSupport(SILFunction &F, bool FreezePostDomReleases,
222204

223205
DEBUG(llvm::dbgs() << "***** Processing " << F.getName() << " *****\n");
224206

225-
bool Changed = false;
226207
LoopARCPairingContext Context(F, AA, LRFI, LI, RCFI);
227-
CodeMotionOrDeleteCallback Callback;
228-
// Until we do not remove any instructions or have nested increments,
229-
// decrements...
230-
while (true) {
231-
// Compute matching sets of increments, decrements, and their insertion
232-
// points.
233-
//
234-
// We need to blot pointers we remove after processing an individual pointer
235-
// so we don't process pairs after we have paired them up. Thus we pass in a
236-
// lambda that performs the work for us.
237-
bool ShouldRunAgain = Context.run(FreezePostDomReleases, Callback);
238-
239-
Changed |= Callback.madeChange();
240-
241-
// If we did not remove any instructions or have any nested increments, do
242-
// not perform another iteration.
243-
if (!ShouldRunAgain)
244-
break;
245-
246-
// Otherwise, perform another iteration.
247-
DEBUG(llvm::dbgs() << "\n<<< Made a Change! Reprocessing Function! >>>\n");
248-
}
249-
250-
DEBUG(llvm::dbgs() << "\n");
251-
252-
// Return true if we moved or deleted any instructions.
253-
return Changed;
208+
return Context.process(FreezePostDomReleases);
254209
}
255210

256211
//===----------------------------------------------------------------------===//

lib/SILPasses/ARC/GlobalARCPairingAnalysis.cpp

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ bool ARCMatchingSetBuilder::matchUpIncDecSetsForPtr() {
360360
// ARC Pairing Context
361361
//===----------------------------------------------------------------------===//
362362

363-
bool ARCPairingContext::performMatching(ARCMatchingSetCallback &Callback) {
363+
bool ARCPairingContext::performMatching(CodeMotionOrDeleteCallback &Callback) {
364364
bool MatchedPair = false;
365365

366366
DEBUG(llvm::dbgs() << "**** Computing ARC Matching Sets for " << F.getName()
@@ -404,9 +404,15 @@ bool ARCPairingContext::performMatching(ARCMatchingSetCallback &Callback) {
404404
// Loop ARC
405405
//===----------------------------------------------------------------------===//
406406

407-
void LoopARCPairingContext::processLoop(const LoopRegion *Region,
408-
bool FreezePostDomReleases,
409-
ARCMatchingSetCallback &Callback) {
407+
void LoopARCPairingContext::runOnLoop(SILLoop *L) {
408+
processRegion(LRFI->getRegion(L));
409+
}
410+
411+
void LoopARCPairingContext::runOnFunction(SILFunction *F) {
412+
processRegion(LRFI->getTopLevelRegion());
413+
}
414+
415+
void LoopARCPairingContext::processRegion(const LoopRegion *Region) {
410416
bool NestingDetected = Evaluator.runOnLoop(Region, FreezePostDomReleases);
411417
bool MatchedPair = Context.performMatching(Callback);
412418
Context.DecToIncStateMap.clear();
@@ -422,35 +428,3 @@ void LoopARCPairingContext::processLoop(const LoopRegion *Region,
422428

423429
Evaluator.summarizeLoop(Region);
424430
}
425-
426-
bool LoopARCPairingContext::run(bool FreezePostDomReleases,
427-
ARCMatchingSetCallback &Callback) {
428-
// We visit the loop nest inside out via a depth first, post order using this
429-
// worklist.
430-
llvm::SmallVector<std::pair<SILLoop *, bool>, 32> Worklist;
431-
for (auto *L : SLI->getTopLevelLoops()) {
432-
Worklist.push_back({L, L->empty()});
433-
}
434-
435-
while (Worklist.size()) {
436-
SILLoop *L;
437-
bool Visited;
438-
std::tie(L, Visited) = Worklist.pop_back_val();
439-
440-
if (!Visited) {
441-
Worklist.push_back({L, true});
442-
for (auto *SubLoop : L->getSubLoops()) {
443-
Worklist.push_back({SubLoop, SubLoop->empty()});
444-
}
445-
continue;
446-
}
447-
448-
processLoop(LRFI->getRegion(L), FreezePostDomReleases, Callback);
449-
}
450-
451-
processLoop(LRFI->getTopLevelRegion(), FreezePostDomReleases, Callback);
452-
453-
// We always return false since we are iterating internally rather than
454-
// externally.
455-
return false;
456-
}

lib/SILPasses/ARC/GlobalARCPairingAnalysis.h

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "GlobalARCSequenceDataflow.h"
1717
#include "GlobalLoopARCSequenceDataflow.h"
1818
#include "swift/SIL/SILValue.h"
19+
#include "swift/SILPasses/Utils/LoopUtils.h"
1920
#include "llvm/ADT/SetVector.h"
2021

2122
namespace swift {
@@ -31,13 +32,31 @@ class RCIdentityFunctionInfo;
3132
/// A set of matching reference count increments, decrements, increment
3233
/// insertion pts, and decrement insertion pts.
3334
struct ARCMatchingSet {
35+
36+
/// The pointer that this ARCMatchingSet is providing matching increment and
37+
/// decrement sets for.
38+
///
39+
/// TODO: This should really be called RCIdentity.
3440
SILValue Ptr;
41+
42+
/// The set of reference count increments that were paired.
3543
llvm::SetVector<SILInstruction *> Increments;
44+
45+
/// An insertion point for an increment means the earliest point in the
46+
/// program after the increment has occured that the increment can be moved to
47+
/// without moving the increment over an instruction that may decrement a
48+
/// reference count.
3649
llvm::SetVector<SILInstruction *> IncrementInsertPts;
50+
51+
/// The set of reference count decrements that were paired.
3752
llvm::SetVector<SILInstruction *> Decrements;
53+
54+
/// An insertion point for a decrement means the latest point in the program
55+
/// before the decrement that the optimizer conservatively assumes that a
56+
/// reference counted value could be used.
3857
llvm::SetVector<SILInstruction *> DecrementInsertPts;
3958

40-
// This is a data structure that can not be moved.
59+
// This is a data structure that can not be moved or copied.
4160
ARCMatchingSet() = default;
4261
ARCMatchingSet(const ARCMatchingSet &) = delete;
4362
ARCMatchingSet(ARCMatchingSet &&) = delete;
@@ -53,24 +72,31 @@ struct ARCMatchingSet {
5372
}
5473
};
5574

56-
/// A structure that via its virtual calls recieves the results of the analysis.
57-
///
58-
/// TODO: We could potentially pass in all of the matching sets as a list and
59-
/// use less virtual calls at the cost of potentially greater numbers of moves.
60-
struct ARCMatchingSetCallback {
61-
virtual ~ARCMatchingSetCallback() = default;
75+
class CodeMotionOrDeleteCallback {
76+
bool Changed = false;
77+
llvm::SmallVector<SILInstruction *, 16> InstructionsToDelete;
6278

79+
public:
6380
/// This call should process \p Set and modify any internal state of
6481
/// ARCMatchingSetCallback given \p Set. This call should not remove any
6582
/// instructions since any removed instruction might be used as an insertion
6683
/// point for another retain, release pair.
67-
virtual void processMatchingSet(ARCMatchingSet &Set) {}
84+
void processMatchingSet(ARCMatchingSet &Set);
85+
86+
// Delete instructions after we have processed all matching sets so that we do
87+
// not remove instructions that may be insertion points for other retain,
88+
// releases.
89+
void finalize() {
90+
while (!InstructionsToDelete.empty()) {
91+
InstructionsToDelete.pop_back_val()->eraseFromParent();
92+
}
93+
}
6894

69-
/// This call should perform any deletion of instructions necessary. It is run
70-
/// strictly after all computation has been completed.
71-
virtual void finalize() {}
95+
bool madeChange() const { return Changed; }
7296
};
7397

98+
/// A wrapper around the results of the bottomup/topdown dataflow that knows how
99+
/// to pair the retains/releases in those results.
74100
struct ARCPairingContext {
75101
SILFunction &F;
76102
BlotMapVector<SILInstruction *, TopDownRefCountState> DecToIncStateMap;
@@ -79,9 +105,14 @@ struct ARCPairingContext {
79105

80106
ARCPairingContext(SILFunction &F, RCIdentityFunctionInfo *RCIA)
81107
: F(F), DecToIncStateMap(), IncToDecStateMap(), RCIA(RCIA) {}
82-
bool performMatching(ARCMatchingSetCallback &Callback);
108+
bool performMatching(CodeMotionOrDeleteCallback &Callback);
83109
};
84110

111+
/// A composition of an ARCSequenceDataflowEvaluator and an
112+
/// ARCPairingContext. The evaluator performs top down/bottom up dataflows
113+
/// clearing the dataflow at loop boundaries. Then the results of the evaluator
114+
/// are placed into the ARCPairingContext and then the ARCPairingContext is used
115+
/// to pair retains/releases.
85116
struct BlockARCPairingContext {
86117
ARCPairingContext Context;
87118
ARCSequenceDataflowEvaluator Evaluator;
@@ -91,7 +122,7 @@ struct BlockARCPairingContext {
91122
: Context(F, RCFI), Evaluator(F, AA, POTA, RCFI, Context.DecToIncStateMap,
92123
Context.IncToDecStateMap) {}
93124

94-
bool run(bool FreezePostDomReleases, ARCMatchingSetCallback &Callback) {
125+
bool run(bool FreezePostDomReleases, CodeMotionOrDeleteCallback &Callback) {
95126
bool NestingDetected = Evaluator.run(FreezePostDomReleases);
96127
Evaluator.clear();
97128

@@ -100,23 +131,36 @@ struct BlockARCPairingContext {
100131
}
101132
};
102133

103-
struct LoopARCPairingContext {
134+
/// A composition of a LoopARCSequenceDataflowEvaluator and an
135+
/// ARCPairingContext. The loop nest is processed bottom up. For each loop, we
136+
/// run the evaluator on the loop and then use the ARCPairingContext to pair
137+
/// retains/releases and eliminate them.
138+
struct LoopARCPairingContext : SILLoopVisitor {
104139
ARCPairingContext Context;
105140
LoopARCSequenceDataflowEvaluator Evaluator;
106141
LoopRegionFunctionInfo *LRFI;
107142
SILLoopInfo *SLI;
143+
CodeMotionOrDeleteCallback Callback;
144+
bool FreezePostDomReleases = false;
108145

109146
LoopARCPairingContext(SILFunction &F, AliasAnalysis *AA,
110147
LoopRegionFunctionInfo *LRFI, SILLoopInfo *SLI,
111148
RCIdentityFunctionInfo *RCFI)
112-
: Context(F, RCFI),
149+
: SILLoopVisitor(&F, SLI), Context(F, RCFI),
113150
Evaluator(F, AA, LRFI, SLI, RCFI, Context.DecToIncStateMap,
114151
Context.IncToDecStateMap),
115-
LRFI(LRFI), SLI(SLI) {}
152+
LRFI(LRFI), SLI(SLI), Callback() {}
153+
154+
bool process(bool FreezePDReleases) {
155+
FreezePostDomReleases = FreezePDReleases;
156+
run();
157+
return Callback.madeChange();
158+
}
159+
160+
void runOnLoop(SILLoop *L) override;
161+
void runOnFunction(SILFunction *F) override;
116162

117-
bool run(bool FreezePostDomReleases, ARCMatchingSetCallback &Callback);
118-
void processLoop(const LoopRegion *R, bool FreezePostDomReleases,
119-
ARCMatchingSetCallback &Callback);
163+
void processRegion(const LoopRegion *R);
120164
};
121165

122166
} // end swift namespace

0 commit comments

Comments
 (0)