Skip to content

Commit 094494e

Browse files
committed
SILOptimizer: add basic block utilities ReachingReturnBlocks and NonErrorHandlingBlocks
* ReachingReturnBlocks: computes the set of blocks from which a path to the return-block exists (does not include paths to a throw-block) * NonErrorHandlingBlocks: computes the set of blocks which are not used for error handling, i.e. not (exclusively) reachable from the error-block of a try_apply
1 parent ff2db93 commit 094494e

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/SIL/BasicBlockBits.h"
2727
#include "swift/SIL/SILCloner.h"
2828
#include "swift/SIL/SILInstruction.h"
29+
#include "swift/SIL/BasicBlockDatastructures.h"
2930
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
3031

3132
namespace swift {
@@ -54,6 +55,34 @@ class ReachableBlocks {
5455
bool isVisited(SILBasicBlock *bb) const { return visited.contains(bb); }
5556
};
5657

58+
/// Computes the set of blocks from which a path to the return-block exists.
59+
/// This does not include pathes to a throw-block.
60+
class ReachingReturnBlocks {
61+
BasicBlockWorklist worklist;
62+
63+
public:
64+
ReachingReturnBlocks(SILFunction *function);
65+
66+
/// Returns true if there exists a path from \p block to the return-block.
67+
bool reachesReturn(SILBasicBlock *block) const {
68+
return worklist.isVisited(block);
69+
}
70+
};
71+
72+
/// Computes the set of blocks which are not used for error handling, i.e. not
73+
/// (exclusively) reachable from the error-block of a try_apply.
74+
class NonErrorHandlingBlocks {
75+
BasicBlockWorklist worklist;
76+
77+
public:
78+
NonErrorHandlingBlocks(SILFunction *function);
79+
80+
/// Returns true if there exists a path from \p block to the return-block.
81+
bool isNonErrorHandling(SILBasicBlock *block) const {
82+
return worklist.isVisited(block);
83+
}
84+
};
85+
5786
/// Remove all instructions in the body of \p bb in safe manner by using
5887
/// undef.
5988
void clearBlockBody(SILBasicBlock *bb);

lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,33 @@ bool ReachableBlocks::visit(function_ref<bool(SILBasicBlock *)> visitor) {
3939
return true;
4040
}
4141

42+
ReachingReturnBlocks::ReachingReturnBlocks(SILFunction *function)
43+
: worklist(function) {
44+
for (SILBasicBlock &block : *function) {
45+
if (isa<ReturnInst>(block.getTerminator()))
46+
worklist.push(&block);
47+
}
48+
49+
while (SILBasicBlock *block = worklist.pop()) {
50+
for (SILBasicBlock *pred : block->getPredecessorBlocks()) {
51+
worklist.pushIfNotVisited(pred);
52+
}
53+
}
54+
}
55+
56+
NonErrorHandlingBlocks::NonErrorHandlingBlocks(SILFunction *function)
57+
: worklist(function->getEntryBlock()) {
58+
while (SILBasicBlock *block = worklist.pop()) {
59+
if (auto ta = dyn_cast<TryApplyInst>(block->getTerminator())) {
60+
worklist.pushIfNotVisited(ta->getNormalBB());
61+
} else {
62+
for (SILBasicBlock *succ : block->getSuccessorBlocks()) {
63+
worklist.pushIfNotVisited(succ);
64+
}
65+
}
66+
}
67+
}
68+
4269
/// Remove all instructions in the body of \p bb in safe manner by using
4370
/// undef.
4471
void swift::clearBlockBody(SILBasicBlock *bb) {

0 commit comments

Comments
 (0)