Skip to content

Commit 0456d95

Browse files
committed
SIL: Use StackList in BasicBlockWorklist and BasicBlockSetVector
plus: I moved both data structures into a separate header file.
1 parent 0dfaf80 commit 0456d95

17 files changed

+158
-137
lines changed

include/swift/SIL/BasicBlockBits.h

Lines changed: 2 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17-
#ifndef SWIFT_SIL_SILBITFIELD_H
18-
#define SWIFT_SIL_SILBITFIELD_H
17+
#ifndef SWIFT_SIL_BASICBLOCKBITS_H
18+
#define SWIFT_SIL_BASICBLOCKBITS_H
1919

2020
#include "swift/SIL/SILFunction.h"
2121
#include "llvm/ADT/SmallVector.h"
@@ -173,101 +173,6 @@ class BasicBlockSet {
173173
void erase(SILBasicBlock *block) { flag.reset(block); }
174174
};
175175

176-
/// An implementation of `llvm::SetVector<SILBasicBlock *,
177-
/// SmallVector<SILBasicBlock *, N>,
178-
/// BasicBlockSet>`.
179-
///
180-
/// Unfortunately it's not possible to use `llvm::SetVector` directly because
181-
/// the BasicBlockSet constructor needs a `SILFunction` argument.
182-
///
183-
/// Note: This class does not provide a `remove` method intentinally, because
184-
/// it would have a O(n) complexity.
185-
template <unsigned N> class BasicBlockSetVector {
186-
using Vector = llvm::SmallVector<SILBasicBlock *, N>;
187-
188-
Vector vector;
189-
BasicBlockSet set;
190-
191-
public:
192-
using iterator = typename Vector::const_iterator;
193-
194-
BasicBlockSetVector(SILFunction *function) : set(function) {}
195-
196-
iterator begin() const { return vector.begin(); }
197-
iterator end() const { return vector.end(); }
198-
199-
unsigned size() const { return vector.size(); }
200-
bool empty() const { return vector.empty(); }
201-
202-
bool contains(SILBasicBlock *block) const { return set.contains(block); }
203-
204-
/// Returns true if \p block was not contained in the set before inserting.
205-
bool insert(SILBasicBlock *block) {
206-
if (set.insert(block)) {
207-
vector.push_back(block);
208-
return true;
209-
}
210-
return false;
211-
}
212-
};
213-
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-
271176
} // namespace swift
272177

273178
#endif
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//===--- BasicBlockDatastructures.h -----------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines efficient data structures for working with BasicBlocks.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_SIL_BASICBLOCKDATASTRUCTURES_H
18+
#define SWIFT_SIL_BASICBLOCKDATASTRUCTURES_H
19+
20+
#include "swift/SIL/StackList.h"
21+
#include "swift/SIL/BasicBlockBits.h"
22+
23+
namespace swift {
24+
25+
/// An implementation of `llvm::SetVector<SILBasicBlock *,
26+
/// StackList<SILBasicBlock *>,
27+
/// BasicBlockSet>`.
28+
///
29+
/// Unfortunately it's not possible to use `llvm::SetVector` directly because
30+
/// the BasicBlockSet and StackList constructors needs a `SILFunction` argument.
31+
///
32+
/// Note: This class does not provide a `remove` method intentinally, because
33+
/// it would have a O(n) complexity.
34+
class BasicBlockSetVector {
35+
StackList<SILBasicBlock *> vector;
36+
BasicBlockSet set;
37+
38+
public:
39+
using iterator = typename StackList<SILBasicBlock *>::iterator;
40+
41+
BasicBlockSetVector(SILFunction *function) : vector(function), set(function) {}
42+
43+
iterator begin() const { return vector.begin(); }
44+
iterator end() const { return vector.end(); }
45+
46+
bool empty() const { return vector.empty(); }
47+
48+
bool contains(SILBasicBlock *block) const { return set.contains(block); }
49+
50+
/// Returns true if \p block was not contained in the set before inserting.
51+
bool insert(SILBasicBlock *block) {
52+
if (set.insert(block)) {
53+
vector.push_back(block);
54+
return true;
55+
}
56+
return false;
57+
}
58+
};
59+
60+
/// A utility for processing basic blocks in a worklist.
61+
///
62+
/// It is basically a combination of a block vector and a block set. It can be
63+
/// used for typical worklist-processing algorithms.
64+
class BasicBlockWorklist {
65+
StackList<SILBasicBlock *> worklist;
66+
BasicBlockSet visited;
67+
68+
public:
69+
/// Construct an empty worklist.
70+
BasicBlockWorklist(SILFunction *function)
71+
: worklist(function), visited(function) {}
72+
73+
/// Initialize the worklist with \p initialBlock.
74+
BasicBlockWorklist(SILBasicBlock *initialBlock)
75+
: BasicBlockWorklist(initialBlock->getParent()) {
76+
push(initialBlock);
77+
}
78+
79+
/// Pops the last added element from the worklist or returns null, if the
80+
/// worklist is empty.
81+
SILBasicBlock *pop() {
82+
if (worklist.empty())
83+
return nullptr;
84+
return worklist.pop_back_val();
85+
}
86+
87+
/// Pushes \p block onto the worklist if \p block has never been push before.
88+
bool pushIfNotVisited(SILBasicBlock *block) {
89+
if (visited.insert(block)) {
90+
worklist.push_back(block);
91+
return true;
92+
}
93+
return false;
94+
}
95+
96+
/// Like `pushIfNotVisited`, but requires that \p block has never been on the
97+
/// worklist before.
98+
void push(SILBasicBlock *block) {
99+
assert(!visited.contains(block));
100+
visited.insert(block);
101+
worklist.push_back(block);
102+
}
103+
104+
/// Like `pop`, but marks the returned block as "unvisited". This means, that
105+
/// the block can be pushed onto the worklist again.
106+
SILBasicBlock *popAndForget() {
107+
if (worklist.empty())
108+
return nullptr;
109+
SILBasicBlock *block = worklist.pop_back_val();
110+
visited.erase(block);
111+
return block;
112+
}
113+
114+
/// Returns true if \p block was visited, i.e. has been added to the worklist.
115+
bool isVisited(SILBasicBlock *block) const { return visited.contains(block); }
116+
};
117+
118+
} // namespace swift
119+
120+
#endif

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 2 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/BasicBlockBits.h"
35+
#include "swift/SIL/BasicBlockDatastructures.h"
3636
#include "swift/SIL/SILDebugScope.h"
3737
#include "swift/SIL/SILDeclRef.h"
3838
#include "swift/SIL/SILLinkage.h"
@@ -2242,7 +2242,7 @@ void IRGenSILFunction::emitSILFunction() {
22422242
// Invariant: for every block in the work queue, we have visited all
22432243
// of its dominators.
22442244
// Start with the entry block, for which the invariant trivially holds.
2245-
BasicBlockWorklist<32> workQueue(&*CurSILFn->getEntryBlock());
2245+
BasicBlockWorklist workQueue(&*CurSILFn->getEntryBlock());
22462246

22472247
while (SILBasicBlock *bb = workQueue.pop()) {
22482248
// Emit the block.

lib/SIL/Verifier/MemoryLifetimeVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "swift/SIL/SILBasicBlock.h"
1717
#include "swift/SIL/SILFunction.h"
1818
#include "swift/SIL/ApplySite.h"
19-
#include "swift/SIL/BasicBlockBits.h"
19+
#include "swift/SIL/BasicBlockDatastructures.h"
2020
#include "llvm/Support/CommandLine.h"
2121

2222
using namespace swift;
@@ -148,7 +148,7 @@ bool MemoryLifetimeVerifier::isEnumTrivialAt(int locIdx,
148148
SILBasicBlock *startBlock = atInst->getParent();
149149

150150
// Start at atInst an walk up the control flow.
151-
BasicBlockWorklist<32> worklist(startBlock);
151+
BasicBlockWorklist worklist(startBlock);
152152
while (SILBasicBlock *block = worklist.pop()) {
153153
auto start = (block == atInst->getParent() ? atInst->getReverseIterator()
154154
: block->rbegin());

lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp

Lines changed: 2 additions & 2 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/BasicBlockBits.h"
21+
#include "swift/SIL/BasicBlockDatastructures.h"
2222
#include "swift/SILOptimizer/PassManager/Passes.h"
2323
#include "swift/SILOptimizer/PassManager/Transforms.h"
2424
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
@@ -103,7 +103,7 @@ static SILInstruction *getDeinitSafeClosureDestructionPoint(SILBasicBlock *bb) {
103103

104104
static void findReachableExitBlocks(SILInstruction *i,
105105
SmallVectorImpl<SILBasicBlock *> &result) {
106-
BasicBlockWorklist<32> worklist(i->getParent());
106+
BasicBlockWorklist worklist(i->getParent());
107107

108108
while (SILBasicBlock *bb = worklist.pop()) {
109109
if (bb->getTerminator()->isFunctionExiting()) {

lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp

Lines changed: 2 additions & 2 deletions
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/BasicBlockBits.h"
26+
#include "swift/SIL/BasicBlockDatastructures.h"
2727
#include "swift/SILOptimizer/PassManager/Passes.h"
2828
#include "swift/SILOptimizer/PassManager/Transforms.h"
2929
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
@@ -84,7 +84,7 @@ class UnreachableUserCodeReportingState {
8484
///
8585
/// This is a SetVector since several blocks may lead to the same error
8686
/// report and we iterate through these when producing the diagnostic.
87-
BasicBlockSetVector<16> PossiblyUnreachableBlocks;
87+
BasicBlockSetVector PossiblyUnreachableBlocks;
8888

8989
/// The set of blocks in which we reported unreachable code errors.
9090
/// These are used to ensure that we don't issue duplicate reports.

lib/SILOptimizer/Mandatory/MandatoryCombine.cpp

Lines changed: 2 additions & 2 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/BasicBlockBits.h"
34+
#include "swift/SIL/BasicBlockDatastructures.h"
3535
#include "swift/SILOptimizer/PassManager/Passes.h"
3636
#include "swift/SILOptimizer/PassManager/Transforms.h"
3737
#include "swift/SILOptimizer/Utils/CanonicalizeInstruction.h"
@@ -206,7 +206,7 @@ static llvm::cl::opt<bool> EnableCanonicalizationAndTrivialDCE(
206206
"dead code and canonicalizing SIL"));
207207

208208
void MandatoryCombiner::addReachableCodeToWorklist(SILFunction &function) {
209-
BasicBlockWorklist<32> blockWorklist(function.getEntryBlock());
209+
BasicBlockWorklist blockWorklist(function.getEntryBlock());
210210
SmallVector<SILInstruction *, 128> initialInstructionWorklist;
211211

212212
while (SILBasicBlock *block = blockWorklist.pop()) {

lib/SILOptimizer/SILCombiner/SILCombine.cpp

Lines changed: 2 additions & 2 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/BasicBlockBits.h"
27+
#include "swift/SIL/BasicBlockDatastructures.h"
2828
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
2929
#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
3030
#include "swift/SILOptimizer/PassManager/Passes.h"
@@ -67,7 +67,7 @@ static llvm::cl::opt<bool> EnableSILCombineCanonicalize(
6767
/// worklist (this significantly speeds up SILCombine on code where many
6868
/// instructions are dead or constant).
6969
void SILCombiner::addReachableCodeToWorklist(SILBasicBlock *BB) {
70-
BasicBlockWorklist<256> Worklist(BB);
70+
BasicBlockWorklist Worklist(BB);
7171
llvm::SmallVector<SILInstruction *, 128> InstrsForSILCombineWorklist;
7272

7373
while (SILBasicBlock *BB = Worklist.pop()) {

lib/SILOptimizer/Transforms/ARCCodeMotion.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
#define DEBUG_TYPE "sil-rr-code-motion"
7373
#include "swift/SIL/InstructionUtils.h"
7474
#include "swift/SIL/SILBuilder.h"
75-
#include "swift/SIL/BasicBlockBits.h"
75+
#include "swift/SIL/BasicBlockDatastructures.h"
7676
#include "swift/SIL/BasicBlockData.h"
7777
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
7878
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
@@ -554,7 +554,7 @@ void RetainCodeMotionContext::convergeCodeMotionDataFlow() {
554554
// Process each basic block with the genset and killset. Every time the
555555
// BBSetOut of a basic block changes, the optimization is rerun on its
556556
// successors.
557-
BasicBlockWorklist<16> WorkList(BlockStates.getFunction());
557+
BasicBlockWorklist WorkList(BlockStates.getFunction());
558558
// Push into reverse post order so that we can pop from the back and get
559559
// post order.
560560
for (SILBasicBlock *B : PO->getReversePostOrder()) {
@@ -966,7 +966,7 @@ void ReleaseCodeMotionContext::convergeCodeMotionDataFlow() {
966966
// Process each basic block with the gen and kill set. Every time the
967967
// BBSetIn of a basic block changes, the optimization is rerun on its
968968
// predecessors.
969-
BasicBlockWorklist<16> WorkList(BlockStates.getFunction());
969+
BasicBlockWorklist WorkList(BlockStates.getFunction());
970970
// Push into reverse post order so that we can pop from the back and get
971971
// post order.
972972
for (SILBasicBlock *B : PO->getPostOrder()) {

0 commit comments

Comments
 (0)