diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/StructurizeCFG.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/StructurizeCFG.cpp | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp index b3a445368537..f6525ad7de9b 100644 --- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp +++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp @@ -18,10 +18,8 @@ #include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" #include "llvm/Analysis/RegionPass.h" -#include "llvm/IR/Argument.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" -#include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" @@ -33,7 +31,6 @@ #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" -#include "llvm/IR/User.h" #include "llvm/IR/Value.h" #include "llvm/IR/ValueHandle.h" #include "llvm/InitializePasses.h" @@ -41,7 +38,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils.h" @@ -72,6 +68,11 @@ static cl::opt<bool> cl::desc("Allow relaxed uniform region checks"), cl::init(true)); +static cl::opt<unsigned> + ReorderNodeSize("structurizecfg-node-reorder-size", + cl::desc("Limit region size for reordering nodes"), + cl::init(100), cl::Hidden); + // Definition of the complex types used in this pass. using BBValuePair = std::pair<BasicBlock *, Value *>; @@ -266,6 +267,8 @@ class StructurizeCFG { void orderNodes(); + void reorderNodes(); + void analyzeLoops(RegionNode *N); Value *buildCondition(BranchInst *Term, unsigned Idx, bool Invert); @@ -424,6 +427,57 @@ void StructurizeCFG::orderNodes() { } } +/// Change the node ordering to decrease the range of live values, especially +/// the values that capture the control flow path for branches. We do this +/// by moving blocks with a single predecessor and successor to appear after +/// predecessor. The motivation is to move some loop exit blocks into a loop. +/// In cases where a loop has a large number of exit blocks, this reduces the +/// amount of values needed across the loop boundary. +void StructurizeCFG::reorderNodes() { + SmallVector<RegionNode *, 8> NewOrder; + DenseMap<BasicBlock *, unsigned> MoveTo; + BitVector Moved(Order.size()); + + // The benefits of reordering nodes occurs for large regions. + if (Order.size() <= ReorderNodeSize) + return; + + // The algorithm works with two passes over Order. The first pass identifies + // the blocks to move and the position to move them to. The second pass + // creates the new order based upon this information. We move blocks with + // a single predecessor and successor. If there are multiple candidates then + // maintain the original order. + BBSet Seen; + for (int I = Order.size() - 1; I >= 0; --I) { + auto *BB = Order[I]->getEntry(); + Seen.insert(BB); + auto *Pred = BB->getSinglePredecessor(); + auto *Succ = BB->getSingleSuccessor(); + // Consider only those basic blocks that have a predecessor in Order and a + // successor that exits the region. The region may contain subregions that + // have been structurized and are not included in Order. + if (Pred && Succ && Seen.count(Pred) && Succ == ParentRegion->getExit() && + !MoveTo.count(Pred)) { + MoveTo[Pred] = I; + Moved.set(I); + } + } + + // If no blocks have been moved then the original order is good. + if (!Moved.count()) + return; + + for (size_t I = 0, E = Order.size(); I < E; ++I) { + auto *BB = Order[I]->getEntry(); + if (MoveTo.count(BB)) + NewOrder.push_back(Order[MoveTo[BB]]); + if (!Moved[I]) + NewOrder.push_back(Order[I]); + } + + Order.assign(NewOrder); +} + /// Determine the end of the loops void StructurizeCFG::analyzeLoops(RegionNode *N) { if (N->isSubRegion()) { @@ -685,7 +739,7 @@ void StructurizeCFG::simplifyAffectedPhis() { Q.DT = DT; for (WeakVH VH : AffectedPhis) { if (auto Phi = dyn_cast_or_null<PHINode>(VH)) { - if (auto NewValue = SimplifyInstruction(Phi, Q)) { + if (auto NewValue = simplifyInstruction(Phi, Q)) { Phi->replaceAllUsesWith(NewValue); Phi->eraseFromParent(); Changed = true; @@ -1085,12 +1139,13 @@ bool StructurizeCFG::run(Region *R, DominatorTree *DT) { ParentRegion = R; orderNodes(); + reorderNodes(); collectInfos(); createFlow(); insertConditions(false); insertConditions(true); - simplifyConditions(); setPhiValues(); + simplifyConditions(); simplifyAffectedPhis(); rebuildSSA(); |