aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-12-13 01:57:34 +0000
committerChris Lattner <sabre@nondot.org>2010-12-13 01:57:34 +0000
commitcd4b709d73f8705571d5680d5d7c1962a1239fda (patch)
tree751665013a2aa419d36c419be7ef3ba0c66aeb2e
parent9a2b72acc9651be04c12ba713702ddc5d449ce72 (diff)
downloadexternal_llvm-cd4b709d73f8705571d5680d5d7c1962a1239fda.zip
external_llvm-cd4b709d73f8705571d5680d5d7c1962a1239fda.tar.gz
external_llvm-cd4b709d73f8705571d5680d5d7c1962a1239fda.tar.bz2
move the "br (X == 0 | X == 1), T, F" -> switch optimization to a new
location in simplifycfg. In the old days, SimplifyCFG was never run on the entry block, so we had to scan over all preds of the BB passed into simplifycfg to do this xform, now we can just check blocks ending with a condbranch. This avoids a scan over all preds of every simplified block, which should be a significant compile-time perf win on functions with lots of edges. No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121668 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp113
1 files changed, 56 insertions, 57 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index 132dc33..8cc63e6 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -44,7 +44,7 @@ class SimplifyCFGOpt {
ConstantInt *GetConstantInt(Value *V);
Value *GatherConstantSetEQs(Value *V, std::vector<ConstantInt*> &Values);
Value *GatherConstantSetNEs(Value *V, std::vector<ConstantInt*> &Values);
- bool GatherValueComparisons(Instruction *Cond, Value *&CompVal,
+ bool GatherValueComparisons(Value *Cond, Value *&CompVal,
std::vector<ConstantInt*> &Values);
Value *isValueEqualityComparison(TerminatorInst *TI);
BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,
@@ -353,8 +353,11 @@ GatherConstantSetNEs(Value *V, std::vector<ConstantInt*> &Values) {
/// GatherValueComparisons - If the specified Cond is an 'and' or 'or' of a
/// bunch of comparisons of one value against constants, return the value and
/// the constants being compared.
-bool SimplifyCFGOpt::GatherValueComparisons(Instruction *Cond, Value *&CompVal,
+bool SimplifyCFGOpt::GatherValueComparisons(Value *CondV, Value *&CompVal,
std::vector<ConstantInt*> &Values) {
+ Instruction *Cond = dyn_cast<Instruction>(CondV);
+ if (Cond == 0) return false;
+
if (Cond->getOpcode() == Instruction::Or) {
CompVal = GatherConstantSetEQs(Cond, Values);
@@ -1970,6 +1973,57 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
if (PBI != BI && PBI->isConditional())
if (SimplifyCondBranchToCondBranch(PBI, BI))
return SimplifyCFG(BB) | true;
+
+
+ // Change br (X == 0 | X == 1), T, F into a switch instruction.
+ // If this is a bunch of seteq's or'd together, or if it's a bunch of
+ // 'setne's and'ed together, collect them.
+ Value *CompVal = 0;
+ std::vector<ConstantInt*> Values;
+ bool TrueWhenEqual = GatherValueComparisons(BI->getCondition(), CompVal,
+ Values);
+ if (CompVal) {
+ // There might be duplicate constants in the list, which the switch
+ // instruction can't handle, remove them now.
+ std::sort(Values.begin(), Values.end(), ConstantIntOrdering());
+ Values.erase(std::unique(Values.begin(), Values.end()), Values.end());
+
+ // Figure out which block is which destination.
+ BasicBlock *DefaultBB = BI->getSuccessor(1);
+ BasicBlock *EdgeBB = BI->getSuccessor(0);
+ if (!TrueWhenEqual) std::swap(DefaultBB, EdgeBB);
+
+ // Convert pointer to int before we switch.
+ if (CompVal->getType()->isPointerTy()) {
+ assert(TD && "Cannot switch on pointer without TargetData");
+ CompVal = new PtrToIntInst(CompVal,
+ TD->getIntPtrType(CompVal->getContext()),
+ "magicptr", BI);
+ }
+
+ // Create the new switch instruction now.
+ SwitchInst *New = SwitchInst::Create(CompVal, DefaultBB,
+ Values.size(), BI);
+
+ // Add all of the 'cases' to the switch instruction.
+ for (unsigned i = 0, e = Values.size(); i != e; ++i)
+ New->addCase(Values[i], EdgeBB);
+
+ // We added edges from PI to the EdgeBB. As such, if there were any
+ // PHI nodes in EdgeBB, they need entries to be added corresponding to
+ // the number of edges added.
+ for (BasicBlock::iterator BBI = EdgeBB->begin();
+ isa<PHINode>(BBI); ++BBI) {
+ PHINode *PN = cast<PHINode>(BBI);
+ Value *InVal = PN->getIncomingValueForBlock(BB);
+ for (unsigned i = 0, e = Values.size()-1; i != e; ++i)
+ PN->addIncoming(InVal, BB);
+ }
+
+ // Erase the old branch instruction.
+ EraseTerminatorInstAndDCECond(BI);
+ return true;
+ }
}
} else if (isa<UnreachableInst>(BB->getTerminator())) {
// If there are any instructions immediately before the unreachable that can
@@ -2179,61 +2233,6 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
}
}
- for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
- BranchInst *BI = dyn_cast<BranchInst>((*PI)->getTerminator());
- // Change br (X == 0 | X == 1), T, F into a switch instruction.
- if (BI && BI->isConditional() && isa<Instruction>(BI->getCondition())) {
- Instruction *Cond = cast<Instruction>(BI->getCondition());
- // If this is a bunch of seteq's or'd together, or if it's a bunch of
- // 'setne's and'ed together, collect them.
- Value *CompVal = 0;
- std::vector<ConstantInt*> Values;
- bool TrueWhenEqual = GatherValueComparisons(Cond, CompVal, Values);
- if (CompVal) {
- // There might be duplicate constants in the list, which the switch
- // instruction can't handle, remove them now.
- std::sort(Values.begin(), Values.end(), ConstantIntOrdering());
- Values.erase(std::unique(Values.begin(), Values.end()), Values.end());
-
- // Figure out which block is which destination.
- BasicBlock *DefaultBB = BI->getSuccessor(1);
- BasicBlock *EdgeBB = BI->getSuccessor(0);
- if (!TrueWhenEqual) std::swap(DefaultBB, EdgeBB);
-
- // Convert pointer to int before we switch.
- if (CompVal->getType()->isPointerTy()) {
- assert(TD && "Cannot switch on pointer without TargetData");
- CompVal = new PtrToIntInst(CompVal,
- TD->getIntPtrType(CompVal->getContext()),
- "magicptr", BI);
- }
-
- // Create the new switch instruction now.
- SwitchInst *New = SwitchInst::Create(CompVal, DefaultBB,
- Values.size(), BI);
-
- // Add all of the 'cases' to the switch instruction.
- for (unsigned i = 0, e = Values.size(); i != e; ++i)
- New->addCase(Values[i], EdgeBB);
-
- // We added edges from PI to the EdgeBB. As such, if there were any
- // PHI nodes in EdgeBB, they need entries to be added corresponding to
- // the number of edges added.
- for (BasicBlock::iterator BBI = EdgeBB->begin();
- isa<PHINode>(BBI); ++BBI) {
- PHINode *PN = cast<PHINode>(BBI);
- Value *InVal = PN->getIncomingValueForBlock(*PI);
- for (unsigned i = 0, e = Values.size()-1; i != e; ++i)
- PN->addIncoming(InVal, *PI);
- }
-
- // Erase the old branch instruction.
- EraseTerminatorInstAndDCECond(BI);
- return true;
- }
- }
- }
-
return Changed;
}