aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/LICM.cpp42
1 files changed, 36 insertions, 6 deletions
diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp
index 9a30fbf9d1..88abccda00 100644
--- a/lib/Transforms/Scalar/LICM.cpp
+++ b/lib/Transforms/Scalar/LICM.cpp
@@ -8,6 +8,7 @@
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/Dominators.h"
#include "llvm/iOperators.h"
#include "llvm/iMemory.h"
#include "llvm/Support/InstVisitor.h"
@@ -30,6 +31,7 @@ namespace {
AU.preservesCFG();
AU.addRequiredID(LoopPreheadersID);
AU.addRequired<LoopInfo>();
+ AU.addRequired<DominatorTree>();
AU.addRequired<AliasAnalysis>();
}
@@ -43,6 +45,14 @@ namespace {
///
void visitLoop(Loop *L);
+ /// HoistRegion - Walk the specified region of the CFG (defined by all
+ /// blocks dominated by the specified block, and that are in the current
+ /// loop) in depth first order w.r.t the DominatorTree. This allows us to
+ /// visit defintions before uses, allowing us to hoist a loop body in one
+ /// pass without iteration.
+ ///
+ void HoistRegion(DominatorTree::Node *N);
+
/// inCurrentLoop - Little predicate that returns false if the specified
/// basic block is in a subloop of the current one, not the current one
/// itself.
@@ -139,22 +149,42 @@ void LICM::visitLoop(Loop *L) {
// their loop, into this loop, so there is no need to process the BODIES of
// the subloops).
//
- for (std::vector<BasicBlock*>::const_iterator
- I = L->getBlocks().begin(), E = L->getBlocks().end(); I != E; ++I)
- if (inCurrentLoop(*I))
- visit(**I);
+ // Traverse the body of the loop in depth first order on the dominator tree so
+ // that we are guaranteed to see definitions before we see uses. This allows
+ // us to perform the LICM transformation in one pass, without iteration.
+ //
+ HoistRegion(getAnalysis<DominatorTree>()[L->getHeader()]);
// Clear out loops state information for the next iteration
CurLoop = 0;
Preheader = 0;
}
+/// HoistRegion - Walk the specified region of the CFG (defined by all blocks
+/// dominated by the specified block, and that are in the current loop) in depth
+/// first order w.r.t the DominatorTree. This allows us to visit defintions
+/// before uses, allowing us to hoist a loop body in one pass without iteration.
+///
+void LICM::HoistRegion(DominatorTree::Node *N) {
+ assert(N != 0 && "Null dominator tree node?");
+
+ // This subregion is not in the loop, it has already been already been hoisted
+ if (!inCurrentLoop(N->getNode()))
+ return;
+
+ visit(*N->getNode());
+
+ const std::vector<DominatorTree::Node*> &Children = N->getChildren();
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ HoistRegion(Children[i]);
+}
+
+
/// hoist - When an instruction is found to only use loop invariant operands
/// that is safe to hoist, this instruction is called to do the dirty work.
///
void LICM::hoist(Instruction &Inst) {
- if (Inst.use_empty()) return; // Don't (re) hoist dead instructions!
- //cerr << "Hoisting " << Inst;
+ DEBUG(std::cerr << "LICM hoisting: " << Inst);
BasicBlock *Header = CurLoop->getHeader();