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
This commit is contained in:
Erik Eckstein
2021-10-25 13:40:35 +02:00
parent ff2db93922
commit 094494e1ed
2 changed files with 56 additions and 0 deletions

View File

@@ -26,6 +26,7 @@
#include "swift/SIL/BasicBlockBits.h" #include "swift/SIL/BasicBlockBits.h"
#include "swift/SIL/SILCloner.h" #include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILInstruction.h"
#include "swift/SIL/BasicBlockDatastructures.h"
#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h"
namespace swift { namespace swift {
@@ -54,6 +55,34 @@ public:
bool isVisited(SILBasicBlock *bb) const { return visited.contains(bb); } bool isVisited(SILBasicBlock *bb) const { return visited.contains(bb); }
}; };
/// Computes the set of blocks from which a path to the return-block exists.
/// This does not include pathes to a throw-block.
class ReachingReturnBlocks {
BasicBlockWorklist worklist;
public:
ReachingReturnBlocks(SILFunction *function);
/// Returns true if there exists a path from \p block to the return-block.
bool reachesReturn(SILBasicBlock *block) const {
return worklist.isVisited(block);
}
};
/// 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.
class NonErrorHandlingBlocks {
BasicBlockWorklist worklist;
public:
NonErrorHandlingBlocks(SILFunction *function);
/// Returns true if there exists a path from \p block to the return-block.
bool isNonErrorHandling(SILBasicBlock *block) const {
return worklist.isVisited(block);
}
};
/// Remove all instructions in the body of \p bb in safe manner by using /// Remove all instructions in the body of \p bb in safe manner by using
/// undef. /// undef.
void clearBlockBody(SILBasicBlock *bb); void clearBlockBody(SILBasicBlock *bb);

View File

@@ -39,6 +39,33 @@ bool ReachableBlocks::visit(function_ref<bool(SILBasicBlock *)> visitor) {
return true; return true;
} }
ReachingReturnBlocks::ReachingReturnBlocks(SILFunction *function)
: worklist(function) {
for (SILBasicBlock &block : *function) {
if (isa<ReturnInst>(block.getTerminator()))
worklist.push(&block);
}
while (SILBasicBlock *block = worklist.pop()) {
for (SILBasicBlock *pred : block->getPredecessorBlocks()) {
worklist.pushIfNotVisited(pred);
}
}
}
NonErrorHandlingBlocks::NonErrorHandlingBlocks(SILFunction *function)
: worklist(function->getEntryBlock()) {
while (SILBasicBlock *block = worklist.pop()) {
if (auto ta = dyn_cast<TryApplyInst>(block->getTerminator())) {
worklist.pushIfNotVisited(ta->getNormalBB());
} else {
for (SILBasicBlock *succ : block->getSuccessorBlocks()) {
worklist.pushIfNotVisited(succ);
}
}
}
}
/// Remove all instructions in the body of \p bb in safe manner by using /// Remove all instructions in the body of \p bb in safe manner by using
/// undef. /// undef.
void swift::clearBlockBody(SILBasicBlock *bb) { void swift::clearBlockBody(SILBasicBlock *bb) {