From 573527bd5dc546a198a122cd6d1da62246d2d9be Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 21 May 2002 20:49:37 +0000 Subject: [PATCH] New CFG Simplification pass: removed from the old DCE pass git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2700 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SimplifyCFG.cpp | 100 ++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 lib/Transforms/Scalar/SimplifyCFG.cpp diff --git a/lib/Transforms/Scalar/SimplifyCFG.cpp b/lib/Transforms/Scalar/SimplifyCFG.cpp new file mode 100644 index 00000000000..14c42e261d2 --- /dev/null +++ b/lib/Transforms/Scalar/SimplifyCFG.cpp @@ -0,0 +1,100 @@ +//===- SimplifyCFG.cpp - CFG Simplification Pass --------------------------===// +// +// This file implements dead code elimination and basic block merging. +// +// Specifically, this: +// * removes basic blocks with no predecessors +// * merges a basic block into its predecessor if there is only one and the +// predecessor only has one successor. +// * Eliminates PHI nodes for basic blocks with a single predecessor +// * Eliminates a basic block that only contains an unconditional branch +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Module.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Support/CFG.h" +#include "llvm/Pass.h" +#include "Support/StatisticReporter.h" +#include + +static Statistic<> NumSimpl("cfgsimplify\t- Number of blocks simplified"); + +namespace { + struct CFGSimplifyPass : public FunctionPass { + const char *getPassName() const { return "Simplify CFG"; } + + virtual bool runOnFunction(Function *F); + }; +} + +Pass *createCFGSimplificationPass() { + return new CFGSimplifyPass(); +} + +static bool MarkAliveBlocks(BasicBlock *BB, std::set &Reachable) { + if (Reachable.count(BB)) return false; + Reachable.insert(BB); + + bool Changed = ConstantFoldTerminator(BB); + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + MarkAliveBlocks(*SI, Reachable); + + return Changed; +} + + +// It is possible that we may require multiple passes over the code to fully +// simplify the CFG. +// +bool CFGSimplifyPass::runOnFunction(Function *F) { + std::set Reachable; + bool Changed = MarkAliveBlocks(F->front(), Reachable); + + // If there are unreachable blocks in the CFG... + if (Reachable.size() != F->size()) { + assert(Reachable.size() < F->size()); + NumSimpl += F->size()-Reachable.size(); + + // Loop over all of the basic blocks that are not reachable, dropping all of + // their internal references... + for (Function::iterator I = F->begin()+1, E = F->end(); I != E; ++I) + if (!Reachable.count(*I)) { + BasicBlock *BB = *I; + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI!=SE; ++SI) + if (Reachable.count(*SI)) + (*SI)->removePredecessor(BB); + BB->dropAllReferences(); + } + + for (Function::iterator I = F->begin()+1; I != F->end();) + if (!Reachable.count(*I)) + delete F->getBasicBlocks().remove(I); + else + ++I; + + Changed = true; + } + + bool LocalChange = true; + while (LocalChange) { + LocalChange = false; + + // Loop over all of the basic blocks (except the first one) and remove them + // if they are unneeded... + // + for (Function::iterator BBIt = F->begin()+1; BBIt != F->end(); ) { + if (SimplifyCFG(BBIt)) { + LocalChange = true; + ++NumSimpl; + } else { + ++BBIt; + } + } + Changed |= LocalChange; + } + + return Changed; +}