blob: 648cc91b80886587a3a7fef39242913f3d388868 [file] [log] [blame]
Chris Lattner573527b2002-05-21 20:49:37 +00001//===- SimplifyCFG.cpp - CFG Simplification Pass --------------------------===//
2//
3// This file implements dead code elimination and basic block merging.
4//
5// Specifically, this:
6// * removes basic blocks with no predecessors
7// * merges a basic block into its predecessor if there is only one and the
8// predecessor only has one successor.
9// * Eliminates PHI nodes for basic blocks with a single predecessor
10// * Eliminates a basic block that only contains an unconditional branch
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Transforms/Scalar.h"
15#include "llvm/Transforms/Utils/Local.h"
16#include "llvm/Module.h"
Chris Lattner573527b2002-05-21 20:49:37 +000017#include "llvm/Support/CFG.h"
18#include "llvm/Pass.h"
Chris Lattnera92f6962002-10-01 22:38:41 +000019#include "Support/Statistic.h"
Chris Lattner573527b2002-05-21 20:49:37 +000020#include <set>
21
Chris Lattner573527b2002-05-21 20:49:37 +000022namespace {
Chris Lattnera92f6962002-10-01 22:38:41 +000023 Statistic<> NumSimpl("cfgsimplify", "Number of blocks simplified");
24
Chris Lattner573527b2002-05-21 20:49:37 +000025 struct CFGSimplifyPass : public FunctionPass {
Chris Lattner7e708292002-06-25 16:13:24 +000026 virtual bool runOnFunction(Function &F);
Chris Lattner573527b2002-05-21 20:49:37 +000027 };
Chris Lattnera6275cc2002-07-26 21:12:46 +000028 RegisterOpt<CFGSimplifyPass> X("simplifycfg", "Simplify the CFG");
Chris Lattner573527b2002-05-21 20:49:37 +000029}
30
Chris Lattnerb55803a2003-10-05 19:14:16 +000031FunctionPass *createCFGSimplificationPass() {
Chris Lattner573527b2002-05-21 20:49:37 +000032 return new CFGSimplifyPass();
33}
34
35static bool MarkAliveBlocks(BasicBlock *BB, std::set<BasicBlock*> &Reachable) {
36 if (Reachable.count(BB)) return false;
37 Reachable.insert(BB);
38
39 bool Changed = ConstantFoldTerminator(BB);
40 for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
41 MarkAliveBlocks(*SI, Reachable);
42
43 return Changed;
44}
45
46
47// It is possible that we may require multiple passes over the code to fully
48// simplify the CFG.
49//
Chris Lattner7e708292002-06-25 16:13:24 +000050bool CFGSimplifyPass::runOnFunction(Function &F) {
Chris Lattner573527b2002-05-21 20:49:37 +000051 std::set<BasicBlock*> Reachable;
Chris Lattner7e708292002-06-25 16:13:24 +000052 bool Changed = MarkAliveBlocks(F.begin(), Reachable);
Chris Lattner573527b2002-05-21 20:49:37 +000053
54 // If there are unreachable blocks in the CFG...
Chris Lattner7e708292002-06-25 16:13:24 +000055 if (Reachable.size() != F.size()) {
56 assert(Reachable.size() < F.size());
57 NumSimpl += F.size()-Reachable.size();
Chris Lattner573527b2002-05-21 20:49:37 +000058
59 // Loop over all of the basic blocks that are not reachable, dropping all of
60 // their internal references...
Chris Lattner7e708292002-06-25 16:13:24 +000061 for (Function::iterator BB = ++F.begin(), E = F.end(); BB != E; ++BB)
62 if (!Reachable.count(BB)) {
Chris Lattner573527b2002-05-21 20:49:37 +000063 for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI!=SE; ++SI)
64 if (Reachable.count(*SI))
65 (*SI)->removePredecessor(BB);
66 BB->dropAllReferences();
67 }
68
Chris Lattner7e708292002-06-25 16:13:24 +000069 for (Function::iterator I = ++F.begin(); I != F.end();)
70 if (!Reachable.count(I))
71 I = F.getBasicBlockList().erase(I);
Chris Lattner573527b2002-05-21 20:49:37 +000072 else
73 ++I;
74
75 Changed = true;
76 }
77
78 bool LocalChange = true;
79 while (LocalChange) {
80 LocalChange = false;
81
82 // Loop over all of the basic blocks (except the first one) and remove them
83 // if they are unneeded...
84 //
Chris Lattner7e708292002-06-25 16:13:24 +000085 for (Function::iterator BBIt = ++F.begin(); BBIt != F.end(); ) {
86 if (SimplifyCFG(BBIt++)) {
Chris Lattner573527b2002-05-21 20:49:37 +000087 LocalChange = true;
88 ++NumSimpl;
Chris Lattner573527b2002-05-21 20:49:37 +000089 }
90 }
91 Changed |= LocalChange;
92 }
93
94 return Changed;
95}