Skip to content

Commit d6a7e9b

Browse files
authored
Merge pull request #35935 from eeckstein/basicblock-worklist
SIL: A utility for processing basic blocks in a worklist.
2 parents ee0e69b + 214b7a9 commit d6a7e9b

32 files changed

+141
-167
lines changed

include/swift/SIL/SILBitfield.h renamed to include/swift/SIL/BasicBlockBits.h

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- SILBitField.h - Defines the bitfield utilities ---------*- C++ -*-===//
1+
//===--- BasicBlockBits.h - SILBasicBlock bit utilities ---------*- C++ -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
// This file defines the BasicBlockBitfield and BasicBlockFlag utilities.
13+
// This file defines utilities for BasicBlock bit fields and sets.
1414
//
1515
//===----------------------------------------------------------------------===//
1616

@@ -211,6 +211,63 @@ template <unsigned N> class BasicBlockSetVector {
211211
}
212212
};
213213

214+
/// A utility for processing basic blocks in a worklist.
215+
///
216+
/// It is basically a combination of a block vector and a block set. It can be
217+
/// used for typical worklist-processing algorithms.
218+
template <unsigned N> class BasicBlockWorklist {
219+
llvm::SmallVector<SILBasicBlock *, N> worklist;
220+
BasicBlockSet visited;
221+
222+
public:
223+
/// Construct an empty worklist.
224+
BasicBlockWorklist(SILFunction *function) : visited(function) {}
225+
226+
/// Initialize the worklist with \p initialBlock.
227+
BasicBlockWorklist(SILBasicBlock *initialBlock)
228+
: visited(initialBlock->getParent()) {
229+
push(initialBlock);
230+
}
231+
232+
/// Pops the last added element from the worklist or returns null, if the
233+
/// worklist is empty.
234+
SILBasicBlock *pop() {
235+
if (worklist.empty())
236+
return nullptr;
237+
return worklist.pop_back_val();
238+
}
239+
240+
/// Pushes \p block onto the worklist if \p block has never been push before.
241+
bool pushIfNotVisited(SILBasicBlock *block) {
242+
if (visited.insert(block)) {
243+
worklist.push_back(block);
244+
return true;
245+
}
246+
return false;
247+
}
248+
249+
/// Like `pushIfNotVisited`, but requires that \p block has never been on the
250+
/// worklist before.
251+
void push(SILBasicBlock *block) {
252+
assert(!visited.contains(block));
253+
visited.insert(block);
254+
worklist.push_back(block);
255+
}
256+
257+
/// Like `pop`, but marks the returned block as "unvisited". This means, that
258+
/// the block can be pushed onto the worklist again.
259+
SILBasicBlock *popAndForget() {
260+
if (worklist.empty())
261+
return nullptr;
262+
SILBasicBlock *block = worklist.pop_back_val();
263+
visited.erase(block);
264+
return block;
265+
}
266+
267+
/// Returns true if \p block was visited, i.e. has been added to the worklist.
268+
bool isVisited(SILBasicBlock *block) const { return visited.contains(block); }
269+
};
270+
214271
} // namespace swift
215272

216273
#endif

include/swift/SIL/BasicBlockUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#define SWIFT_SIL_BASICBLOCKUTILS_H
1515

1616
#include "swift/SIL/SILValue.h"
17-
#include "swift/SIL/SILBitfield.h"
17+
#include "swift/SIL/BasicBlockBits.h"
1818
#include "llvm/ADT/SetVector.h"
1919
#include "llvm/ADT/SmallPtrSet.h"
2020
#include "llvm/ADT/SmallVector.h"

include/swift/SIL/LinearLifetimeChecker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include "swift/SIL/SILFunction.h"
2222
#include "swift/SIL/SILValue.h"
2323
#include "swift/SIL/BasicBlockUtils.h"
24-
#include "swift/SIL/SILBitfield.h"
24+
#include "swift/SIL/BasicBlockBits.h"
2525
#include "llvm/ADT/SmallPtrSet.h"
2626

2727
namespace swift {

include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#define SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H
2424

2525
#include "swift/SIL/SILBasicBlock.h"
26-
#include "swift/SIL/SILBitfield.h"
26+
#include "swift/SIL/BasicBlockBits.h"
2727
#include "swift/SIL/SILCloner.h"
2828
#include "swift/SIL/SILInstruction.h"
2929
#include "swift/SILOptimizer/Utils/InstOptUtils.h"

include/swift/SILOptimizer/Utils/ValueLifetime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +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"
23+
#include "swift/SIL/BasicBlockBits.h"
2424
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
2525

2626
namespace swift {

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "swift/SIL/InstructionUtils.h"
3333
#include "swift/SIL/MemAccessUtils.h"
3434
#include "swift/SIL/PrettyStackTrace.h"
35-
#include "swift/SIL/SILBitfield.h"
35+
#include "swift/SIL/BasicBlockBits.h"
3636
#include "swift/SIL/SILDebugScope.h"
3737
#include "swift/SIL/SILDeclRef.h"
3838
#include "swift/SIL/SILLinkage.h"
@@ -2017,16 +2017,10 @@ void IRGenSILFunction::emitSILFunction() {
20172017

20182018
// Invariant: for every block in the work queue, we have visited all
20192019
// of its dominators.
2020-
BasicBlockSet visitedBlocks(CurSILFn);
2021-
SmallVector<SILBasicBlock*, 8> workQueue; // really a stack
2022-
2023-
// Queue up the entry block, for which the invariant trivially holds.
2024-
visitedBlocks.insert(&*CurSILFn->begin());
2025-
workQueue.push_back(&*CurSILFn->begin());
2026-
2027-
while (!workQueue.empty()) {
2028-
auto bb = workQueue.pop_back_val();
2020+
// Start with the entry block, for which the invariant trivially holds.
2021+
BasicBlockWorklist<32> workQueue(&*CurSILFn->getEntryBlock());
20292022

2023+
while (SILBasicBlock *bb = workQueue.pop()) {
20302024
// Emit the block.
20312025
visitSILBasicBlock(bb);
20322026

@@ -2052,15 +2046,14 @@ void IRGenSILFunction::emitSILFunction() {
20522046
// Therefore the invariant holds of all the successors, and we can
20532047
// queue them up if we haven't already visited them.
20542048
for (auto *succBB : bb->getSuccessorBlocks()) {
2055-
if (visitedBlocks.insert(succBB))
2056-
workQueue.push_back(succBB);
2049+
workQueue.pushIfNotVisited(succBB);
20572050
}
20582051
}
20592052

20602053
// If there are dead blocks in the SIL function, we might have left
20612054
// invalid blocks in the IR. Do another pass and kill them off.
20622055
for (SILBasicBlock &bb : *CurSILFn)
2063-
if (!visitedBlocks.contains(&bb))
2056+
if (!workQueue.isVisited(&bb))
20642057
LoweredBBs[&bb].bb->eraseFromParent();
20652058

20662059
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include "swift/SIL/OwnershipUtils.h"
3434
#include "swift/SIL/PostOrder.h"
3535
#include "swift/SIL/PrettyStackTrace.h"
36-
#include "swift/SIL/SILBitfield.h"
36+
#include "swift/SIL/BasicBlockBits.h"
3737
#include "swift/SIL/SILDebugScope.h"
3838
#include "swift/SIL/SILFunction.h"
3939
#include "swift/SIL/SILModule.h"

lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
#include "swift/SIL/InstructionUtils.h"
6363
#include "swift/SIL/Projection.h"
6464
#include "swift/SIL/LoopInfo.h"
65-
#include "swift/SIL/SILBitfield.h"
65+
#include "swift/SIL/BasicBlockBits.h"
6666
#include "swift/SIL/SILCloner.h"
6767
#include "llvm/ADT/SmallSet.h"
6868
#include "llvm/Support/CommandLine.h"

lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "swift/SIL/SILArgument.h"
2626
#include "swift/SIL/SILBuilder.h"
2727
#include "swift/SIL/SILInstruction.h"
28-
#include "swift/SIL/SILBitfield.h"
28+
#include "swift/SIL/BasicBlockBits.h"
2929
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
3030
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
3131
#include "swift/SILOptimizer/Analysis/ArraySemantic.h"

lib/SILOptimizer/LoopTransforms/LICM.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "swift/SIL/SILArgument.h"
2020
#include "swift/SIL/SILBuilder.h"
2121
#include "swift/SIL/SILInstruction.h"
22-
#include "swift/SIL/SILBitfield.h"
22+
#include "swift/SIL/BasicBlockBits.h"
2323
#include "swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h"
2424
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
2525
#include "swift/SILOptimizer/Analysis/Analysis.h"

lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
#include "swift/SIL/SILFunction.h"
3838
#include "swift/SIL/SILUndef.h"
3939
#include "swift/SIL/InstructionUtils.h"
40-
#include "swift/SIL/SILBitfield.h"
40+
#include "swift/SIL/BasicBlockBits.h"
4141
#include "swift/SILOptimizer/Analysis/ClosureScope.h"
4242
#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
4343
#include "swift/SILOptimizer/PassManager/Transforms.h"

lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include "swift/SIL/SILArgument.h"
1919
#include "swift/SIL/SILBuilder.h"
2020
#include "swift/SIL/SILInstruction.h"
21-
#include "swift/SIL/SILBitfield.h"
21+
#include "swift/SIL/BasicBlockBits.h"
2222
#include "swift/SILOptimizer/PassManager/Passes.h"
2323
#include "swift/SILOptimizer/PassManager/Transforms.h"
2424
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
@@ -103,22 +103,16 @@ static SILInstruction *getDeinitSafeClosureDestructionPoint(SILBasicBlock *bb) {
103103

104104
static void findReachableExitBlocks(SILInstruction *i,
105105
SmallVectorImpl<SILBasicBlock *> &result) {
106-
SmallVector<SILBasicBlock *, 32> worklist;
107-
BasicBlockSet visitedBlocks(i->getFunction());
106+
BasicBlockWorklist<32> worklist(i->getParent());
108107

109-
visitedBlocks.insert(i->getParent());
110-
worklist.push_back(i->getParent());
111-
112-
while (!worklist.empty()) {
113-
auto *bb = worklist.pop_back_val();
108+
while (SILBasicBlock *bb = worklist.pop()) {
114109
if (bb->getTerminator()->isFunctionExiting()) {
115110
result.push_back(bb);
116111
continue;
117112
}
118-
llvm::copy_if(bb->getSuccessorBlocks(), std::back_inserter(worklist),
119-
[&](SILBasicBlock *bb) {
120-
return visitedBlocks.insert(bb);
121-
});
113+
for (SILBasicBlock *succ : bb->getSuccessors()) {
114+
worklist.pushIfNotVisited(succ);
115+
}
122116
}
123117
}
124118

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include "swift/AST/Stmt.h"
1919
#include "swift/ClangImporter/ClangModule.h"
2020
#include "swift/SIL/BasicBlockData.h"
21-
#include "swift/SIL/SILBitfield.h"
21+
#include "swift/SIL/BasicBlockBits.h"
2222
#include "swift/SIL/SILValue.h"
2323
#include "swift/SIL/InstructionUtils.h"
2424
#include "swift/SIL/SILArgument.h"

lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "swift/SIL/SILBuilder.h"
2424
#include "swift/SIL/SILUndef.h"
2525
#include "swift/SIL/TerminatorUtils.h"
26-
#include "swift/SIL/SILBitfield.h"
26+
#include "swift/SIL/BasicBlockBits.h"
2727
#include "swift/SILOptimizer/PassManager/Passes.h"
2828
#include "swift/SILOptimizer/PassManager/Transforms.h"
2929
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"

lib/SILOptimizer/Mandatory/MandatoryCombine.cpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include "swift/SIL/BasicBlockUtils.h"
3232
#include "swift/SIL/SILInstructionWorklist.h"
3333
#include "swift/SIL/SILVisitor.h"
34-
#include "swift/SIL/SILBitfield.h"
34+
#include "swift/SIL/BasicBlockBits.h"
3535
#include "swift/SILOptimizer/PassManager/Passes.h"
3636
#include "swift/SILOptimizer/PassManager/Transforms.h"
3737
#include "swift/SILOptimizer/Utils/CanonicalizeInstruction.h"
@@ -206,19 +206,10 @@ static llvm::cl::opt<bool> EnableCanonicalizationAndTrivialDCE(
206206
"dead code and canonicalizing SIL"));
207207

208208
void MandatoryCombiner::addReachableCodeToWorklist(SILFunction &function) {
209-
SmallVector<SILBasicBlock *, 32> blockWorklist;
210-
BasicBlockSet blockAlreadyAddedToWorklist(&function);
209+
BasicBlockWorklist<32> blockWorklist(function.getEntryBlock());
211210
SmallVector<SILInstruction *, 128> initialInstructionWorklist;
212211

213-
{
214-
auto *firstBlock = &*function.begin();
215-
blockWorklist.push_back(firstBlock);
216-
blockAlreadyAddedToWorklist.insert(firstBlock);
217-
}
218-
219-
while (!blockWorklist.empty()) {
220-
auto *block = blockWorklist.pop_back_val();
221-
212+
while (SILBasicBlock *block = blockWorklist.pop()) {
222213
for (auto iterator = block->begin(), end = block->end(); iterator != end;) {
223214
auto *instruction = &*iterator;
224215
++iterator;
@@ -236,11 +227,9 @@ void MandatoryCombiner::addReachableCodeToWorklist(SILFunction &function) {
236227
initialInstructionWorklist.push_back(instruction);
237228
}
238229

239-
llvm::copy_if(block->getSuccessorBlocks(),
240-
std::back_inserter(blockWorklist),
241-
[&](SILBasicBlock *block) -> bool {
242-
return blockAlreadyAddedToWorklist.insert(block);
243-
});
230+
for (SILBasicBlock *succ : block->getSuccessors()) {
231+
blockWorklist.pushIfNotVisited(succ);
232+
}
244233
}
245234

246235
worklist.addInitialGroup(initialInstructionWorklist);

lib/SILOptimizer/Mandatory/OSLogOptimization.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
#include "swift/SIL/SILLocation.h"
9292
#include "swift/SIL/SILModule.h"
9393
#include "swift/SIL/TypeLowering.h"
94-
#include "swift/SIL/SILBitfield.h"
94+
#include "swift/SIL/BasicBlockBits.h"
9595
#include "swift/SILOptimizer/PassManager/Passes.h"
9696
#include "swift/SILOptimizer/PassManager/Transforms.h"
9797
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "swift/SIL/LinearLifetimeChecker.h"
2121
#include "swift/SIL/OwnershipUtils.h"
2222
#include "swift/SIL/SILBuilder.h"
23-
#include "swift/SIL/SILBitfield.h"
23+
#include "swift/SIL/BasicBlockBits.h"
2424
#include "swift/SILOptimizer/PassManager/Passes.h"
2525
#include "swift/SILOptimizer/PassManager/Transforms.h"
2626
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"

lib/SILOptimizer/Mandatory/YieldOnceCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "swift/SIL/CFG.h"
2727
#include "swift/SIL/Dominance.h"
2828
#include "swift/SIL/TerminatorUtils.h"
29-
#include "swift/SIL/SILBitfield.h"
29+
#include "swift/SIL/BasicBlockBits.h"
3030
#include "swift/SIL/BasicBlockData.h"
3131
#include "swift/SILOptimizer/PassManager/Transforms.h"
3232
#include "llvm/ADT/BreadthFirstIterator.h"

lib/SILOptimizer/SILCombiner/SILCombine.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include "swift/SIL/DebugUtils.h"
2525
#include "swift/SIL/SILBuilder.h"
2626
#include "swift/SIL/SILVisitor.h"
27-
#include "swift/SIL/SILBitfield.h"
27+
#include "swift/SIL/BasicBlockBits.h"
2828
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
2929
#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
3030
#include "swift/SILOptimizer/PassManager/Passes.h"
@@ -61,17 +61,10 @@ static llvm::cl::opt<bool> EnableSinkingOwnedForwardingInstToUses(
6161
/// worklist (this significantly speeds up SILCombine on code where many
6262
/// instructions are dead or constant).
6363
void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
64-
llvm::SmallVector<SILBasicBlock *, 256> Worklist;
64+
BasicBlockWorklist<256> Worklist(BB);
6565
llvm::SmallVector<SILInstruction *, 128> InstrsForSILCombineWorklist;
66-
BasicBlockSet Visited(BB->getParent());
67-
68-
Worklist.push_back(BB);
69-
do {
70-
BB = Worklist.pop_back_val();
71-
72-
// We have now visited this block! If we've already been here, ignore it.
73-
if (!Visited.insert(BB)) continue;
7466

67+
while (SILBasicBlock *BB = Worklist.pop()) {
7568
for (SILBasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
7669
SILInstruction *Inst = &*BBI;
7770
++BBI;
@@ -98,9 +91,10 @@ void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
9891
}
9992

10093
// Recursively visit successors.
101-
for (auto SI = BB->succ_begin(), SE = BB->succ_end(); SI != SE; ++SI)
102-
Worklist.push_back(*SI);
103-
} while (!Worklist.empty());
94+
for (SILBasicBlock *Succ : BB->getSuccessors()) {
95+
Worklist.pushIfNotVisited(Succ);
96+
}
97+
}
10498

10599
// Once we've found all of the instructions to add to the worklist, add them
106100
// in reverse order. This way SILCombine will visit from the top of the

lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "swift/SIL/InstructionUtils.h"
2020
#include "swift/SIL/PatternMatch.h"
2121
#include "swift/SIL/Projection.h"
22-
#include "swift/SIL/SILBitfield.h"
22+
#include "swift/SIL/BasicBlockBits.h"
2323
#include "swift/SIL/SILBuilder.h"
2424
#include "swift/SIL/SILInstruction.h"
2525
#include "swift/SIL/SILVisitor.h"

0 commit comments

Comments
 (0)