Skip to content

Commit 8e4c27d

Browse files
committed
BasicBlockCloner: support for updating DeadEndBlocks.
DeadEndBlocks is used by low-level OSSA utilities. It needs to be valid whenever OSSA transformations is being done.
1 parent e6ec4e4 commit 8e4c27d

File tree

4 files changed

+41
-9
lines changed

4 files changed

+41
-9
lines changed

include/swift/SIL/BasicBlockUtils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class DeadEndBlocks {
8787
/// Used to determine if we need to verify a DeadEndBlocks.
8888
bool isComputed() const { return didComputeValue; }
8989

90+
/// Add any (new) blocks that are backward-reachable from \p reachableBB to
91+
/// the set of reachable blocks.
92+
void updateForReachableBlock(SILBasicBlock *reachableBB);
93+
9094
const SILFunction *getFunction() const { return f; }
9195

9296
/// Performs a simple check if \p block (or its single successor) ends in an
@@ -95,6 +99,9 @@ class DeadEndBlocks {
9599
/// This handles the common case of failure-handling blocks, which e.g.
96100
/// contain a call to fatalError().
97101
static bool triviallyEndsInUnreachable(SILBasicBlock *block);
102+
103+
protected:
104+
void propagateNewlyReachableBlocks(unsigned startIdx);
98105
};
99106

100107
/// Compute joint-postdominating set for \p dominatingBlock and \p

include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class BasicBlockCloner : public SILCloner<BasicBlockCloner> {
170170
/// state is reset each time analyzeAddressProjections is called.
171171
SinkAddressProjections sinkProj;
172172

173+
// If available, the current DeadEndBlocks for incremental update.
174+
DeadEndBlocks *deBlocks;
175+
173176
public:
174177
/// An ordered list of old to new available value pairs.
175178
///
@@ -178,8 +181,8 @@ class BasicBlockCloner : public SILCloner<BasicBlockCloner> {
178181
SmallVector<std::pair<SILValue, SILValue>, 16> availVals;
179182

180183
// Clone blocks starting at `origBB`, within the same function.
181-
BasicBlockCloner(SILBasicBlock *origBB)
182-
: SILCloner(*origBB->getParent()), origBB(origBB) {}
184+
BasicBlockCloner(SILBasicBlock *origBB, DeadEndBlocks *deBlocks = nullptr)
185+
: SILCloner(*origBB->getParent()), origBB(origBB), deBlocks(deBlocks) {}
183186

184187
bool canCloneBlock() {
185188
for (auto &inst : *origBB) {
@@ -218,6 +221,12 @@ class BasicBlockCloner : public SILCloner<BasicBlockCloner> {
218221
successorBBs.reserve(origBB->getSuccessors().size());
219222
llvm::copy(origBB->getSuccessors(), std::back_inserter(successorBBs));
220223
cloneReachableBlocks(origBB, successorBBs, insertAfterBB);
224+
225+
if (deBlocks) {
226+
for (auto *succBB : successorBBs) {
227+
deBlocks->updateForReachableBlock(succBB);
228+
}
229+
}
221230
}
222231

223232
/// Clone the given branch instruction's destination block, splitting

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
namespace swift {
3535

3636
class DominanceInfo;
37+
class DeadEndBlocks;
3738
template <class T> class NullablePtr;
3839

3940
/// Transform a Use Range (Operand*) into a User Range (SILInstruction *)
@@ -202,7 +203,7 @@ SILLinkage getSpecializedLinkage(SILFunction *f, SILLinkage linkage);
202203
/// Tries to perform jump-threading on all checked_cast_br instruction in
203204
/// function \p Fn.
204205
bool tryCheckedCastBrJumpThreading(
205-
SILFunction *fn, DominanceInfo *dt,
206+
SILFunction *fn, DominanceInfo *dt, DeadEndBlocks *deBlocks,
206207
SmallVectorImpl<SILBasicBlock *> &blocksForWorklist,
207208
bool EnableOSSARewriteTerminator);
208209

lib/SIL/Utils/BasicBlockUtils.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,15 @@ void swift::mergeBasicBlockWithSingleSuccessor(SILBasicBlock *BB,
368368
// DeadEndBlocks
369369
//===----------------------------------------------------------------------===//
370370

371+
// Propagate the reachability up the control flow graph.
372+
void DeadEndBlocks::propagateNewlyReachableBlocks(unsigned startIdx) {
373+
for (unsigned idx = startIdx; idx < reachableBlocks.size(); ++idx) {
374+
const SILBasicBlock *bb = reachableBlocks[idx];
375+
for (SILBasicBlock *predBB : bb->getPredecessorBlocks())
376+
reachableBlocks.insert(predBB);
377+
}
378+
}
379+
371380
void DeadEndBlocks::compute() {
372381
assert(reachableBlocks.empty() && "Computed twice");
373382

@@ -379,13 +388,19 @@ void DeadEndBlocks::compute() {
379388
if (TI->isFunctionExiting())
380389
reachableBlocks.insert(&BB);
381390
}
382-
// Propagate the reachability up the control flow graph.
383-
unsigned Idx = 0;
384-
while (Idx < reachableBlocks.size()) {
385-
const SILBasicBlock *BB = reachableBlocks[Idx++];
386-
for (SILBasicBlock *Pred : BB->getPredecessorBlocks())
387-
reachableBlocks.insert(Pred);
391+
propagateNewlyReachableBlocks(0);
392+
}
393+
394+
void DeadEndBlocks::updateForReachableBlock(SILBasicBlock *reachableBB) {
395+
if (!didComputeValue)
396+
return;
397+
398+
assert(reachableBlocks.count(reachableBB));
399+
unsigned numReachable = reachableBlocks.size();
400+
for (SILBasicBlock *predBB : reachableBB->getPredecessorBlocks()) {
401+
reachableBlocks.insert(predBB);
388402
}
403+
propagateNewlyReachableBlocks(numReachable);
389404
}
390405

391406
bool DeadEndBlocks::triviallyEndsInUnreachable(SILBasicBlock *block) {

0 commit comments

Comments
 (0)