mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-03 17:02:03 +00:00
[Utils] Extract EliminateUnreachableBlocks (NFC)
Summary: Extract the functionality of eliminating unreachable basic blocks within a function, previously encapsulated within the -unreachableblockelim pass, and make it available as a function within BlockUtils.h. No functional change intended other than making the logic reusable. Exposing this logic makes it easier to implement https://reviews.llvm.org/D59068, which fixes coroutines bug https://bugs.llvm.org/show_bug.cgi?id=40979. Reviewers: mkazantsev, wmi, davidxl, silvas, davide Reviewed By: davide Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59069 llvm-svn: 355846
This commit is contained in:
parent
da2ae38874
commit
0f1d71d29d
@ -62,6 +62,12 @@ void DeleteDeadBlocks(ArrayRef <BasicBlock *> BBs,
|
||||
DomTreeUpdater *DTU = nullptr,
|
||||
bool KeepOneInputPHIs = false);
|
||||
|
||||
/// Delete all basic blocks from \p F that are not reachable from its entry
|
||||
/// node. If \p KeepOneInputPHIs is true, one-input Phis in successors of
|
||||
/// blocks being deleted will be preserved.
|
||||
bool EliminateUnreachableBlocks(Function &F, DomTreeUpdater *DTU = nullptr,
|
||||
bool KeepOneInputPHIs = false);
|
||||
|
||||
/// We know that BB has one predecessor. If there are any single-entry PHI nodes
|
||||
/// in it, fold them away. This handles the case when all entries to the PHI
|
||||
/// nodes in a block are guaranteed equal, such as when the block has exactly
|
||||
|
@ -40,31 +40,10 @@
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
using namespace llvm;
|
||||
|
||||
static bool eliminateUnreachableBlock(Function &F) {
|
||||
df_iterator_default_set<BasicBlock*> Reachable;
|
||||
|
||||
// Mark all reachable blocks.
|
||||
for (BasicBlock *BB : depth_first_ext(&F, Reachable))
|
||||
(void)BB/* Mark all reachable blocks */;
|
||||
|
||||
// Collect all dead blocks.
|
||||
std::vector<BasicBlock*> DeadBlocks;
|
||||
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
|
||||
if (!Reachable.count(&*I)) {
|
||||
BasicBlock *BB = &*I;
|
||||
DeadBlocks.push_back(BB);
|
||||
}
|
||||
|
||||
// Delete the dead blocks.
|
||||
DeleteDeadBlocks(DeadBlocks);
|
||||
|
||||
return !DeadBlocks.empty();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class UnreachableBlockElimLegacyPass : public FunctionPass {
|
||||
bool runOnFunction(Function &F) override {
|
||||
return eliminateUnreachableBlock(F);
|
||||
return llvm::EliminateUnreachableBlocks(F);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -89,7 +68,7 @@ FunctionPass *llvm::createUnreachableBlockEliminationPass() {
|
||||
|
||||
PreservedAnalyses UnreachableBlockElimPass::run(Function &F,
|
||||
FunctionAnalysisManager &AM) {
|
||||
bool Changed = eliminateUnreachableBlock(F);
|
||||
bool Changed = llvm::EliminateUnreachableBlocks(F);
|
||||
if (!Changed)
|
||||
return PreservedAnalyses::all();
|
||||
PreservedAnalyses PA;
|
||||
|
@ -110,6 +110,28 @@ void llvm::DeleteDeadBlocks(ArrayRef <BasicBlock *> BBs, DomTreeUpdater *DTU,
|
||||
BB->eraseFromParent();
|
||||
}
|
||||
|
||||
bool llvm::EliminateUnreachableBlocks(Function &F, DomTreeUpdater *DTU,
|
||||
bool KeepOneInputPHIs) {
|
||||
df_iterator_default_set<BasicBlock*> Reachable;
|
||||
|
||||
// Mark all reachable blocks.
|
||||
for (BasicBlock *BB : depth_first_ext(&F, Reachable))
|
||||
(void)BB/* Mark all reachable blocks */;
|
||||
|
||||
// Collect all dead blocks.
|
||||
std::vector<BasicBlock*> DeadBlocks;
|
||||
for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
|
||||
if (!Reachable.count(&*I)) {
|
||||
BasicBlock *BB = &*I;
|
||||
DeadBlocks.push_back(BB);
|
||||
}
|
||||
|
||||
// Delete the dead blocks.
|
||||
DeleteDeadBlocks(DeadBlocks, DTU, KeepOneInputPHIs);
|
||||
|
||||
return !DeadBlocks.empty();
|
||||
}
|
||||
|
||||
void llvm::FoldSingleEntryPHINodes(BasicBlock *BB,
|
||||
MemoryDependenceResults *MemDep) {
|
||||
if (!isa<PHINode>(BB->begin())) return;
|
||||
|
@ -25,6 +25,64 @@ static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
|
||||
return Mod;
|
||||
}
|
||||
|
||||
TEST(BasicBlockUtils, EliminateUnreachableBlocks) {
|
||||
LLVMContext C;
|
||||
|
||||
std::unique_ptr<Module> M = parseIR(
|
||||
C,
|
||||
"define i32 @has_unreachable(i1 %cond) {\n"
|
||||
"entry:\n"
|
||||
" br i1 %cond, label %bb0, label %bb1\n"
|
||||
"bb0:\n"
|
||||
" br label %bb1\n"
|
||||
"bb1:\n"
|
||||
" %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]"
|
||||
" ret i32 %phi\n"
|
||||
"bb2:\n"
|
||||
" ret i32 42\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
auto *F = M->getFunction("has_unreachable");
|
||||
DominatorTree DT(*F);
|
||||
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
|
||||
|
||||
EXPECT_EQ(F->size(), (size_t)4);
|
||||
bool Result = EliminateUnreachableBlocks(*F, &DTU);
|
||||
EXPECT_TRUE(Result);
|
||||
EXPECT_EQ(F->size(), (size_t)3);
|
||||
EXPECT_TRUE(DT.verify());
|
||||
}
|
||||
|
||||
TEST(BasicBlockUtils, NoUnreachableBlocksToEliminate) {
|
||||
LLVMContext C;
|
||||
|
||||
std::unique_ptr<Module> M = parseIR(
|
||||
C,
|
||||
"define i32 @no_unreachable(i1 %cond) {\n"
|
||||
"entry:\n"
|
||||
" br i1 %cond, label %bb0, label %bb1\n"
|
||||
"bb0:\n"
|
||||
" br label %bb1\n"
|
||||
"bb1:\n"
|
||||
" %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]"
|
||||
" ret i32 %phi\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
auto *F = M->getFunction("no_unreachable");
|
||||
DominatorTree DT(*F);
|
||||
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
|
||||
|
||||
EXPECT_EQ(F->size(), (size_t)3);
|
||||
bool Result = EliminateUnreachableBlocks(*F, &DTU);
|
||||
EXPECT_FALSE(Result);
|
||||
EXPECT_EQ(F->size(), (size_t)3);
|
||||
EXPECT_TRUE(DT.verify());
|
||||
}
|
||||
|
||||
TEST(BasicBlockUtils, SplitBlockPredecessors) {
|
||||
LLVMContext C;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user