Skip to content

Commit 777b421

Browse files
committed
SILOptimizer: use the new set data structures in various optimizations
1 parent dd9efa8 commit 777b421

File tree

9 files changed

+102
-81
lines changed

9 files changed

+102
-81
lines changed

lib/SILOptimizer/Analysis/ValueTracking.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define DEBUG_TYPE "sil-value-tracking"
1414
#include "swift/SILOptimizer/Analysis/ValueTracking.h"
1515
#include "swift/SIL/InstructionUtils.h"
16+
#include "swift/SIL/NodeBits.h"
1617
#include "swift/SIL/PatternMatch.h"
1718
#include "swift/SIL/SILArgument.h"
1819
#include "swift/SIL/SILInstruction.h"
@@ -40,16 +41,15 @@ static bool isLocalObject(SILValue Obj) {
4041
// Set of values to be checked for their locality.
4142
SmallVector<SILValue, 8> WorkList;
4243
// Set of processed values.
43-
llvm::SmallPtrSet<SILValue, 8> Processed;
44+
ValueSet Processed(Obj->getFunction());
4445
WorkList.push_back(Obj);
4546

4647
while (!WorkList.empty()) {
4748
auto V = WorkList.pop_back_val();
48-
if (!V)
49+
if (!V || isa<SILUndef>(V))
4950
return false;
50-
if (Processed.count(V))
51+
if (!Processed.insert(V))
5152
continue;
52-
Processed.insert(V);
5353
// It should be a local object.
5454
V = getUnderlyingObject(V);
5555
if (isa<AllocationInst>(V))

lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "swift/SIL/MemAccessUtils.h"
4646
#include "swift/SIL/BasicBlockData.h"
4747
#include "swift/SIL/BasicBlockDatastructures.h"
48+
#include "swift/SIL/NodeBits.h"
4849
#include "swift/SILOptimizer/PassManager/Transforms.h"
4950
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
5051
#include "swift/SILOptimizer/Utils/Devirtualize.h"
@@ -178,11 +179,11 @@ class Invariants {
178179
/// Recursively walks the use-def chain starting at \p value and returns
179180
/// true if all visited values are invariant.
180181
bool isInvariantValue(SILValue value,
181-
SmallPtrSetImpl<SILInstruction *> &visited) const {
182+
InstructionSet &visited) const {
182183
if (SILInstruction *inst = value->getDefiningInstruction()) {
183184
// Avoid exponential complexity in case a value is used by multiple
184185
// operands.
185-
if (!visited.insert(inst).second)
186+
if (!visited.insert(inst))
186187
return true;
187188

188189
if (!isMemoryInvariant() && inst->mayReadFromMemory())
@@ -245,7 +246,7 @@ class Invariants {
245246
case TermKind::SwitchValueInst:
246247
case TermKind::SwitchEnumInst:
247248
case TermKind::CheckedCastBranchInst: {
248-
SmallPtrSet<SILInstruction *, 16> visited;
249+
InstructionSet visited(term->getFunction());
249250
return isInvariantValue(term->getOperand(0), visited);
250251
}
251252
default:

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/SIL/DebugUtils.h"
2323
#include "swift/SIL/DynamicCasts.h"
2424
#include "swift/SIL/InstructionUtils.h"
25+
#include "swift/SIL/NodeBits.h"
2526
#include "swift/SIL/PatternMatch.h"
2627
#include "swift/SIL/SILBuilder.h"
2728
#include "swift/SIL/SILVisitor.h"
@@ -1556,17 +1557,17 @@ isTryApplyResultNotUsed(UserListTy &AcceptedUses, TryApplyInst *TAI) {
15561557
if (!recursivelyCollectARCUsers(AcceptedUses, ErrorBB->getArgument(0)))
15571558
return false;
15581559

1559-
SmallPtrSet<SILInstruction *, 8> UsesSet;
1560+
InstructionSet UsesSet(NormalBB->getFunction());
15601561
for (auto *I : AcceptedUses)
15611562
UsesSet.insert(I);
15621563

15631564
// Check if the normal and error blocks are empty, except the ARC uses.
15641565
for (auto &I : *NormalBB) {
1565-
if (!UsesSet.count(&I) && !isa<TermInst>(&I))
1566+
if (!UsesSet.contains(&I) && !isa<TermInst>(&I))
15661567
return false;
15671568
}
15681569
for (auto &I : *ErrorBB) {
1569-
if (!UsesSet.count(&I) && !isa<TermInst>(&I))
1570+
if (!UsesSet.contains(&I) && !isa<TermInst>(&I))
15701571
return false;
15711572
}
15721573
return true;

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/SIL/DebugUtils.h"
2020
#include "swift/SIL/DynamicCasts.h"
2121
#include "swift/SIL/InstructionUtils.h"
22+
#include "swift/SIL/NodeBits.h"
2223
#include "swift/SIL/PatternMatch.h"
2324
#include "swift/SIL/Projection.h"
2425
#include "swift/SIL/SILBuilder.h"
@@ -1526,7 +1527,7 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
15261527
}
15271528
InitEnumDataAddrInst *DataAddrInst = nullptr;
15281529
InjectEnumAddrInst *EnumAddrIns = nullptr;
1529-
llvm::SmallPtrSet<SILInstruction *, 32> WriteSet;
1530+
InstructionSetWithSize WriteSet(IEAI->getFunction());
15301531
for (auto UsersIt : ASO->getUses()) {
15311532
SILInstruction *CurrUser = UsersIt->getUser();
15321533
if (CurrUser->isDeallocatingStack()) {
@@ -1592,7 +1593,7 @@ SILCombiner::visitInjectEnumAddrInst(InjectEnumAddrInst *IEAI) {
15921593
// don't care about what comes before init enum in the basic block
15931594
break;
15941595
}
1595-
if (WriteSet.count(Ins) != 0) {
1596+
if (WriteSet.contains(Ins) != 0) {
15961597
return nullptr;
15971598
}
15981599
}

lib/SILOptimizer/Transforms/COWOpts.cpp

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
#define DEBUG_TYPE "cow-opts"
1818
#include "swift/SILOptimizer/PassManager/Transforms.h"
1919
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
20+
#include "swift/SIL/NodeBits.h"
2021
#include "swift/SIL/SILFunction.h"
2122
#include "swift/SIL/SILBasicBlock.h"
2223
#include "swift/SIL/SILArgument.h"
2324
#include "swift/SIL/SILBuilder.h"
25+
#include "swift/SIL/StackList.h"
2426
#include "llvm/Support/Debug.h"
2527

2628
using namespace swift;
@@ -65,16 +67,13 @@ class COWOptsPass : public SILFunctionTransform {
6567
void run() override;
6668

6769
private:
68-
using InstructionSet = SmallPtrSet<SILInstruction *, 8>;
69-
using VoidPointerSet = SmallPtrSet<void *, 8>;
70-
7170
AliasAnalysis *AA = nullptr;
7271

7372
bool optimizeBeginCOW(BeginCOWMutationInst *BCM);
7473

7574
static void collectEscapePoints(SILValue v,
76-
InstructionSet &escapePoints,
77-
VoidPointerSet &handled);
75+
InstructionSetWithSize &escapePoints,
76+
ValueSet &handled);
7877
};
7978

8079
void COWOptsPass::run() {
@@ -120,37 +119,44 @@ static SILValue skipStructAndExtract(SILValue value) {
120119
}
121120

122121
bool COWOptsPass::optimizeBeginCOW(BeginCOWMutationInst *BCM) {
123-
VoidPointerSet handled;
124-
SmallVector<SILValue, 8> workList;
125-
SmallPtrSet<EndCOWMutationInst *, 4> endCOWMutationInsts;
122+
SILFunction *function = BCM->getFunction();
123+
StackList<EndCOWMutationInst *> endCOWMutationInsts(function);
124+
InstructionSet endCOWMutationsFound(function);
126125

127-
// Collect all end_cow_mutation instructions, used by the begin_cow_mutation,
128-
// looking through block phi-arguments.
129-
workList.push_back(BCM->getOperand());
130-
while (!workList.empty()) {
131-
SILValue v = skipStructAndExtract(workList.pop_back_val());
132-
if (SILPhiArgument *arg = dyn_cast<SILPhiArgument>(v)) {
133-
if (handled.insert(arg).second) {
134-
SmallVector<SILValue, 4> incomingVals;
135-
if (!arg->getIncomingPhiValues(incomingVals))
136-
return false;
137-
for (SILValue incomingVal : incomingVals) {
138-
workList.push_back(incomingVal);
126+
{
127+
// Collect all end_cow_mutation instructions, used by the begin_cow_mutation,
128+
// looking through block phi-arguments.
129+
StackList<SILValue> workList(function);
130+
ValueSet handled(function);
131+
workList.push_back(BCM->getOperand());
132+
while (!workList.empty()) {
133+
SILValue v = skipStructAndExtract(workList.pop_back_val());
134+
if (SILPhiArgument *arg = dyn_cast<SILPhiArgument>(v)) {
135+
if (handled.insert(arg)) {
136+
SmallVector<SILValue, 4> incomingVals;
137+
if (!arg->getIncomingPhiValues(incomingVals))
138+
return false;
139+
for (SILValue incomingVal : incomingVals) {
140+
workList.push_back(incomingVal);
141+
}
139142
}
143+
} else if (auto *ECM = dyn_cast<EndCOWMutationInst>(v)) {
144+
if (endCOWMutationsFound.insert(ECM))
145+
endCOWMutationInsts.push_back(ECM);
146+
} else {
147+
return false;
140148
}
141-
} else if (auto *ECM = dyn_cast<EndCOWMutationInst>(v)) {
142-
endCOWMutationInsts.insert(ECM);
143-
} else {
144-
return false;
145149
}
146150
}
147151

148152
// Collect all uses of the end_cow_instructions, where the buffer can
149153
// potentially escape.
150-
handled.clear();
151-
InstructionSet potentialEscapePoints;
152-
for (EndCOWMutationInst *ECM : endCOWMutationInsts) {
153-
collectEscapePoints(ECM, potentialEscapePoints, handled);
154+
InstructionSetWithSize potentialEscapePoints(function);
155+
{
156+
ValueSet handled(function);
157+
for (EndCOWMutationInst *ECM : endCOWMutationInsts) {
158+
collectEscapePoints(ECM, potentialEscapePoints, handled);
159+
}
154160
}
155161

156162
if (!potentialEscapePoints.empty()) {
@@ -161,10 +167,13 @@ bool COWOptsPass::optimizeBeginCOW(BeginCOWMutationInst *BCM) {
161167
// For store instructions we do a little bit more: only count a store as an
162168
// escape if there is a (potential) load from the same address within the
163169
// liverange.
164-
handled.clear();
165-
SmallVector<SILInstruction *, 8> instWorkList;
166-
SmallVector<SILInstruction *, 8> potentialLoadInsts;
167-
llvm::DenseSet<SILValue> storeAddrs;
170+
StackList<SILInstruction *> instWorkList(function);
171+
StackList<SILInstruction *> potentialLoadInsts(function);
172+
StackList<SILValue> storeAddrs(function);
173+
ValueSet storeAddrsFound(function);
174+
BasicBlockSet handled(function);
175+
int numStoresFound = 0;
176+
int numLoadsFound = 0;
168177

169178
// This is a simple worklist-based backward dataflow analysis.
170179
// Start at the initial begin_cow_mutation and go backward.
@@ -173,27 +182,32 @@ bool COWOptsPass::optimizeBeginCOW(BeginCOWMutationInst *BCM) {
173182
while (!instWorkList.empty()) {
174183
SILInstruction *inst = instWorkList.pop_back_val();
175184
for (;;) {
176-
if (potentialEscapePoints.count(inst) != 0) {
185+
if (potentialEscapePoints.contains(inst)) {
177186
if (auto *store = dyn_cast<StoreInst>(inst)) {
178187
// Don't immediately bail on a store instruction. Instead, remember
179188
// it and check if it interfers with any (potential) load.
180-
storeAddrs.insert(store->getDest());
189+
if (storeAddrsFound.insert(store->getDest())) {
190+
storeAddrs.push_back(store->getDest());
191+
numStoresFound += 1;
192+
}
181193
} else {
182194
return false;
183195
}
184196
}
185-
if (inst->mayReadFromMemory())
197+
if (inst->mayReadFromMemory()) {
186198
potentialLoadInsts.push_back(inst);
199+
numLoadsFound += 1;
200+
}
187201

188202
// An end_cow_mutation marks the begin of the liverange. It's the end
189203
// point of the dataflow analysis.
190204
auto *ECM = dyn_cast<EndCOWMutationInst>(inst);
191-
if (ECM && endCOWMutationInsts.count(ECM) != 0)
205+
if (ECM && endCOWMutationsFound.contains(ECM))
192206
break;
193207

194208
if (inst == &inst->getParent()->front()) {
195209
for (SILBasicBlock *pred : inst->getParent()->getPredecessorBlocks()) {
196-
if (handled.insert(pred).second)
210+
if (handled.insert(pred))
197211
instWorkList.push_back(pred->getTerminator());
198212
}
199213
break;
@@ -205,9 +219,9 @@ bool COWOptsPass::optimizeBeginCOW(BeginCOWMutationInst *BCM) {
205219

206220
// Check if there is any (potential) load from a memory location where the
207221
// buffer is stored to.
208-
if (!storeAddrs.empty()) {
222+
if (numStoresFound != 0) {
209223
// Avoid quadratic behavior. Usually this limit is not exceeded.
210-
if (storeAddrs.size() * potentialLoadInsts.size() > 128)
224+
if (numStoresFound * numLoadsFound > 128)
211225
return false;
212226
for (SILInstruction *load : potentialLoadInsts) {
213227
for (SILValue storeAddr : storeAddrs) {
@@ -235,9 +249,9 @@ bool COWOptsPass::optimizeBeginCOW(BeginCOWMutationInst *BCM) {
235249
}
236250

237251
void COWOptsPass::collectEscapePoints(SILValue v,
238-
InstructionSet &escapePoints,
239-
VoidPointerSet &handled) {
240-
if (!handled.insert(v.getOpaqueValue()).second)
252+
InstructionSetWithSize &escapePoints,
253+
ValueSet &handled) {
254+
if (!handled.insert(v))
241255
return;
242256

243257
for (Operand *use : v->getUses()) {

lib/SILOptimizer/Transforms/CSE.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/SIL/DebugUtils.h"
2020
#include "swift/SIL/Dominance.h"
2121
#include "swift/SIL/InstructionUtils.h"
22+
#include "swift/SIL/NodeBits.h"
2223
#include "swift/SIL/OwnershipUtils.h"
2324
#include "swift/SIL/SILCloner.h"
2425
#include "swift/SIL/SILModule.h"
@@ -848,12 +849,12 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst,
848849
OldOpenedArchetype->castTo<ArchetypeType>(), NewOpenedArchetype);
849850
auto &Builder = Cloner.getBuilder();
850851

851-
llvm::SmallPtrSet<SILInstruction *, 16> Processed;
852+
InstructionSet Processed(Inst->getFunction());
852853
// Now clone each candidate and replace the opened archetype
853854
// by a dominating one.
854855
while (!Candidates.empty()) {
855856
auto Candidate = Candidates.pop_back_val();
856-
if (Processed.count(Candidate))
857+
if (Processed.contains(Candidate))
857858
continue;
858859

859860
// Compute if a candidate depends on the old opened archetype.

0 commit comments

Comments
 (0)