Skip to content

Commit 3e8612b

Browse files
committed
SILOptimizer: use the BasicBlockFlag utility in ValueLifetimeAnalysis
1 parent 763bfed commit 3e8612b

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

include/swift/SILOptimizer/Utils/ValueLifetime.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/Basic/STLExtras.h"
2121
#include "swift/SIL/SILBuilder.h"
2222
#include "swift/SIL/SILInstruction.h"
23+
#include "swift/SIL/SILBitfield.h"
2324
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2425

2526
namespace swift {
@@ -34,7 +35,10 @@ class ValueLifetimeAnalysis {
3435
PointerUnion<SILInstruction *, SILArgument *> defValue;
3536

3637
/// The set of blocks where the value is live.
37-
llvm::SmallSetVector<SILBasicBlock *, 16> liveBlocks;
38+
llvm::SmallVector<SILBasicBlock *, 16> liveBlocks;
39+
40+
/// True for blocks which are in liveBlocks.
41+
BasicBlockFlag inLiveBlocks;
3842

3943
/// The set of instructions where the value is used, or the users-list
4044
/// provided with the constructor.
@@ -66,7 +70,7 @@ class ValueLifetimeAnalysis {
6670
/// iterators.
6771
template <typename RangeTy>
6872
ValueLifetimeAnalysis(SILArgument *def, const RangeTy &useRange)
69-
: defValue(def), userSet() {
73+
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
7074
for (SILInstruction *use : useRange)
7175
userSet.insert(use);
7276
propagateLiveness();
@@ -75,7 +79,7 @@ class ValueLifetimeAnalysis {
7579
ValueLifetimeAnalysis(
7680
SILArgument *def,
7781
llvm::iterator_range<ValueBaseUseIterator> useRange)
78-
: defValue(def), userSet() {
82+
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
7983
for (Operand *use : useRange)
8084
userSet.insert(use->getUser());
8185
propagateLiveness();
@@ -84,7 +88,7 @@ class ValueLifetimeAnalysis {
8488
template <typename RangeTy>
8589
ValueLifetimeAnalysis(
8690
SILInstruction *def, const RangeTy &useRange)
87-
: defValue(def), userSet() {
91+
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
8892
for (SILInstruction *use : useRange)
8993
userSet.insert(use);
9094
propagateLiveness();
@@ -93,7 +97,7 @@ class ValueLifetimeAnalysis {
9397
ValueLifetimeAnalysis(
9498
SILInstruction *def,
9599
llvm::iterator_range<ValueBaseUseIterator> useRange)
96-
: defValue(def), userSet() {
100+
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
97101
for (Operand *use : useRange)
98102
userSet.insert(use->getUser());
99103
propagateLiveness();
@@ -144,7 +148,7 @@ class ValueLifetimeAnalysis {
144148

145149
/// Returns true if the value is alive at the begin of block \p bb.
146150
bool isAliveAtBeginOfBlock(SILBasicBlock *bb) {
147-
return liveBlocks.count(bb) &&
151+
return inLiveBlocks.get(bb) &&
148152
(hasUsersBeforeDef || bb != getDefValueParentBlock());
149153
}
150154

lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ void ArrayInfo::getLastDestroys(
360360
// copy_values, using ValueLifetimeAnalysis. The frontier is a list of
361361
// instructions that mark the exits of the flow of control from the
362362
// \c destroys.
363-
ValueLifetimeAnalysis lifetimeAnalysis =
364-
ValueLifetimeAnalysis(arrayValue->getDefiningInstruction(), destroys);
363+
ValueLifetimeAnalysis lifetimeAnalysis(arrayValue->getDefiningInstruction(),
364+
destroys);
365365
ValueLifetimeAnalysis::Frontier frontier;
366366
lifetimeAnalysis.computeFrontier(frontier,
367367
ValueLifetimeAnalysis::DontModifyCFG);

lib/SILOptimizer/Mandatory/OSLogOptimization.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -881,8 +881,7 @@ getEndPointsOfDataDependentChain(SILValue value, SILFunction *fun,
881881
SILInstruction *valueDefinition = value->getDefiningInstruction();
882882
SILInstruction *def =
883883
valueDefinition ? valueDefinition : &(value->getParentBlock()->front());
884-
ValueLifetimeAnalysis lifetimeAnalysis =
885-
ValueLifetimeAnalysis(def, transitiveUsers);
884+
ValueLifetimeAnalysis lifetimeAnalysis(def, transitiveUsers);
886885
ValueLifetimeAnalysis::Frontier frontier;
887886
bool hasCriticlEdges = lifetimeAnalysis.computeFrontier(
888887
frontier, ValueLifetimeAnalysis::DontModifyCFG);

lib/SILOptimizer/Utils/ValueLifetime.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,14 @@ void ValueLifetimeAnalysis::propagateLiveness() {
2727
// Compute the def block only if we have a SILInstruction. If we have a
2828
// SILArgument, this will be nullptr.
2929
auto *defBB = getDefValueParentBlock();
30-
SmallVector<SILBasicBlock *, 64> worklist;
3130
int numUsersBeforeDef = 0;
3231

3332
// Find the initial set of blocks where the value is live, because
3433
// it is used in those blocks.
3534
for (SILInstruction *user : userSet) {
3635
SILBasicBlock *userBlock = user->getParent();
37-
if (liveBlocks.insert(userBlock))
38-
worklist.push_back(userBlock);
36+
if (!inLiveBlocks.testAndSet(userBlock))
37+
liveBlocks.push_back(userBlock);
3938

4039
// A user in the defBB could potentially be located before the defValue. If
4140
// we had a SILArgument, defBB will be nullptr, so we should always have
@@ -62,8 +61,9 @@ void ValueLifetimeAnalysis::propagateLiveness() {
6261

6362
// Now propagate liveness backwards until we hit the block that defines the
6463
// value.
65-
while (!worklist.empty()) {
66-
auto *bb = worklist.pop_back_val();
64+
unsigned workIdx = 0;
65+
while (workIdx < liveBlocks.size()) {
66+
auto *bb = liveBlocks[workIdx++];
6767

6868
// Don't go beyond the definition.
6969
if (bb == defBB && !hasUsersBeforeDef)
@@ -72,8 +72,8 @@ void ValueLifetimeAnalysis::propagateLiveness() {
7272
for (auto *predBB : bb->getPredecessorBlocks()) {
7373
// If it's already in the set, then we've already queued and/or
7474
// processed the predecessors.
75-
if (liveBlocks.insert(predBB))
76-
worklist.push_back(predBB);
75+
if (!inLiveBlocks.testAndSet(predBB))
76+
liveBlocks.push_back(predBB);
7777
}
7878
}
7979
}
@@ -186,7 +186,8 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
186186
}
187187
}
188188
// Handle "exit" edges from the lifetime region.
189-
llvm::SmallPtrSet<SILBasicBlock *, 16> unhandledFrontierBlocks;
189+
BasicBlockSet unhandledFrontierBlocks(getFunction());
190+
bool unhandledFrontierBlocksFound = false;
190191
for (SILBasicBlock *frontierBB : frontierBlocks) {
191192
assert(mode != UsersMustPostDomDef);
192193
bool needSplit = false;
@@ -201,12 +202,13 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
201202
if (needSplit) {
202203
// We need to split the critical edge to create a frontier instruction.
203204
unhandledFrontierBlocks.insert(frontierBB);
205+
unhandledFrontierBlocksFound = true;
204206
} else {
205207
// The first instruction of the exit-block is part of the frontier.
206208
frontier.push_back(&*frontierBB->begin());
207209
}
208210
}
209-
if (unhandledFrontierBlocks.size() == 0) {
211+
if (!unhandledFrontierBlocksFound) {
210212
return true;
211213
}
212214

@@ -222,7 +224,7 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
222224
succBlocks.push_back(succ);
223225

224226
for (unsigned i = 0, e = succBlocks.size(); i != e; ++i) {
225-
if (unhandledFrontierBlocks.count(succBlocks[i])) {
227+
if (unhandledFrontierBlocks.contains(succBlocks[i])) {
226228
assert((isCriticalEdge(term, i) || userSet.count(term)) &&
227229
"actually not a critical edge?");
228230
noCriticalEdges = false;
@@ -244,7 +246,7 @@ bool ValueLifetimeAnalysis::computeFrontier(FrontierImpl &frontier, Mode mode,
244246
bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *inst) {
245247
SILBasicBlock *bb = inst->getParent();
246248
// Check if the value is not live anywhere in inst's block.
247-
if (!liveBlocks.count(bb))
249+
if (!inLiveBlocks.get(bb))
248250
return false;
249251
for (const SILSuccessor &succ : bb->getSuccessors()) {
250252
// If the value is live at the beginning of any successor block it is also
@@ -288,7 +290,7 @@ blockContainsDeallocRef(SILBasicBlock *bb,
288290
}
289291

290292
bool ValueLifetimeAnalysis::containsDeallocRef(const FrontierImpl &frontier) {
291-
SmallPtrSet<SILBasicBlock *, 8> frontierBlocks;
293+
BasicBlockSet frontierBlocks(getFunction());
292294
// Search in live blocks where the value is not alive until the end of the
293295
// block, i.e. the live range is terminated by a frontier instruction.
294296
for (SILInstruction *frontierInst : frontier) {
@@ -300,7 +302,7 @@ bool ValueLifetimeAnalysis::containsDeallocRef(const FrontierImpl &frontier) {
300302
// Search in all other live blocks where the value is alive until the end of
301303
// the block.
302304
for (SILBasicBlock *bb : liveBlocks) {
303-
if (frontierBlocks.count(bb) == 0) {
305+
if (frontierBlocks.contains(bb) == 0) {
304306
if (blockContainsDeallocRef(bb, defValue, bb->getTerminator()))
305307
return true;
306308
}

0 commit comments

Comments
 (0)