diff options
-rw-r--r-- | include/llvm/Support/IntegersSubset.h | 36 | ||||
-rw-r--r-- | include/llvm/Support/IntegersSubsetMapping.h | 223 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 15 | ||||
-rw-r--r-- | lib/Transforms/Utils/LowerSwitch.cpp | 9 | ||||
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 233 | ||||
-rw-r--r-- | test/Transforms/SimplifyCFG/switch_create.ll | 2 | ||||
-rw-r--r-- | unittests/Support/IntegersSubsetTest.cpp | 22 |
7 files changed, 329 insertions, 211 deletions
diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index bb9e769..06df793 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -182,7 +182,12 @@ protected: IntType Low; IntType High; bool IsEmpty : 1; - bool IsSingleNumber : 1; + enum Type { + SINGLE_NUMBER, + RANGE, + UNKNOWN + }; + Type RangeType; public: typedef IntRange<IntType> self; @@ -191,15 +196,30 @@ public: IntRange() : IsEmpty(true) {} IntRange(const self &RHS) : Low(RHS.Low), High(RHS.High), - IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} + IsEmpty(RHS.IsEmpty), RangeType(RHS.RangeType) {} IntRange(const IntType &C) : - Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} + Low(C), High(C), IsEmpty(false), RangeType(SINGLE_NUMBER) {} IntRange(const IntType &L, const IntType &H) : Low(L), High(H), - IsEmpty(false), IsSingleNumber(Low == High) {} + IsEmpty(false), RangeType(UNKNOWN) {} bool isEmpty() const { return IsEmpty; } - bool isSingleNumber() const { return IsSingleNumber; } + bool isSingleNumber() const { + switch (RangeType) { + case SINGLE_NUMBER: + return true; + case RANGE: + return false; + case UNKNOWN: + default: + if (Low == High) { + const_cast<Type&>(RangeType) = SINGLE_NUMBER; + return true; + } + const_cast<Type&>(RangeType) = RANGE; + return false; + } + } const IntType& getLow() const { assert(!IsEmpty && "Range is empty."); @@ -213,13 +233,13 @@ public: bool operator<(const self &RHS) const { assert(!IsEmpty && "Left range is empty."); assert(!RHS.IsEmpty && "Right range is empty."); + if (Low < RHS.Low) + return true; if (Low == RHS.Low) { if (High > RHS.High) return true; return false; } - if (Low < RHS.Low) - return true; return false; } @@ -512,7 +532,7 @@ public: e = Src.end(); i != e; ++i) { const Range &R = *i; std::vector<Constant*> r; - if (R.isSingleNumber()) { + if (!R.isSingleNumber()) { r.reserve(2); // FIXME: Since currently we have ConstantInt based numbers // use hack-conversion of IntItem to ConstantInt diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h index 87d0755..915c777 100644 --- a/include/llvm/Support/IntegersSubsetMapping.h +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -58,22 +58,16 @@ public: protected: - typedef std::list<Cluster> CaseItems; + typedef std::map<RangeEx, SuccessorClass*> CaseItems; typedef typename CaseItems::iterator CaseItemIt; typedef typename CaseItems::const_iterator CaseItemConstIt; // TODO: Change unclean CRS prefixes to SubsetMap for example. typedef std::map<SuccessorClass*, RangesCollection > CRSMap; typedef typename CRSMap::iterator CRSMapIt; - - struct ClustersCmp { - bool operator()(const Cluster &C1, const Cluster &C2) { - return C1.first < C2.first; - } - }; CaseItems Items; - bool Sorted; + bool SingleNumbersOnly; bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { return LItem->first.getHigh() >= RItem->first.getLow(); @@ -91,18 +85,6 @@ protected: return LItem->first.getHigh() >= RLow; } - void sort() { - if (!Sorted) { - std::vector<Cluster> clustersVector; - clustersVector.reserve(Items.size()); - clustersVector.insert(clustersVector.begin(), Items.begin(), Items.end()); - std::sort(clustersVector.begin(), clustersVector.end(), ClustersCmp()); - Items.clear(); - Items.insert(Items.begin(), clustersVector.begin(), clustersVector.end()); - Sorted = true; - } - } - enum DiffProcessState { L_OPENED, INTERSECT_OPENED, @@ -213,7 +195,7 @@ protected: } } - void onRLOpen(const IntTy &Pt, + void onLROpen(const IntTy &Pt, SuccessorClass *LS, SuccessorClass *RS) { switch (State) { @@ -229,7 +211,7 @@ protected: OpenPt = Pt; } - void onRLClose(const IntTy &Pt) { + void onLRClose(const IntTy &Pt) { switch (State) { case INTERSECT_OPENED: if (IntersectionMapping) @@ -245,6 +227,48 @@ protected: bool isLOpened() { return State == L_OPENED; } bool isROpened() { return State == R_OPENED; } }; + + void diff_single_numbers(self *LExclude, self *Intersection, self *RExclude, + const self& RHS) { + + CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); + CaseItemConstIt el = Items.end(), er = RHS.Items.end(); + while (L != el && R != er) { + const Cluster &LCluster = *L; + const RangeEx &LRange = LCluster.first; + const Cluster &RCluster = *R; + const RangeEx &RRange = RCluster.first; + + if (LRange.getLow() < RRange.getLow()) { + if (LExclude) + LExclude->add(LRange.getLow(), LCluster.second); + ++L; + } else if (LRange.getLow() > RRange.getLow()) { + if (RExclude) + RExclude->add(RRange.getLow(), RCluster.second); + ++R; + } else { + if (Intersection) + Intersection->add(LRange.getLow(), LCluster.second); + ++L; + ++R; + } + } + + if (L != Items.end()) { + if (LExclude) + do { + LExclude->add(L->first, L->second); + ++L; + } while (L != Items.end()); + } else if (R != RHS.Items.end()) { + if (RExclude) + do { + RExclude->add(R->first, R->second); + ++R; + } while (R != RHS.Items.end()); + } + } public: @@ -256,15 +280,18 @@ public: typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; typedef std::list<Case> Cases; + typedef typename Cases::iterator CasesIt; + + IntegersSubsetMapping() : SingleNumbersOnly(true) {} - IntegersSubsetMapping() { - Sorted = false; + bool verify() { + RangeIterator DummyErrItem; + return verify(DummyErrItem); } bool verify(RangeIterator& errItem) { if (Items.empty()) return true; - sort(); for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); j != e; i = j++) { if (isIntersected(i, j) && i->second != j->second) { @@ -275,10 +302,36 @@ public: return true; } + bool isOverlapped(self &RHS) { + if (Items.empty() || RHS.empty()) + return true; + + for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), + el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { + + const RangeTy &LRange = L->first; + const RangeTy &RRange = R->first; + + if (LRange.getLow() > RRange.getLow()) { + if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) + ++R; + else + return true; + } else if (LRange.getLow() < RRange.getLow()) { + if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) + ++L; + else + return true; + } else // iRange.getLow() == jRange.getLow() + return true; + } + return false; + } + + void optimize() { if (Items.size() < 2) return; - sort(); CaseItems OldItems = Items; Items.clear(); const IntTy *Low = &OldItems.begin()->first.getLow(); @@ -303,8 +356,6 @@ public: } RangeEx R(*Low, *High, Weight); add(R, Successor); - // We recollected the Items, but we kept it sorted. - Sorted = true; } /// Adds a constant value. @@ -323,8 +374,10 @@ public: add(REx, S); } void add(const RangeEx &R, SuccessorClass *S = 0) { - Items.push_back(std::make_pair(R, S)); - Sorted = false; + //Items.push_back(std::make_pair(R, S)); + Items.insert(std::make_pair(R, S)); + if (!R.isSingleNumber()) + SingleNumbersOnly = false; } /// Adds all ranges and values from given ranges set to the current @@ -337,9 +390,17 @@ public: } void add(self& RHS) { - Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); + //Items.insert(Items.begin(), RHS.Items.begin(), RHS.Items.end()); + Items.insert(RHS.Items.begin(), RHS.Items.end()); + if (!RHS.SingleNumbersOnly) + SingleNumbersOnly = false; } + void add(self& RHS, SuccessorClass *S) { + for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) + add(i->first, S); + } + void add(const RangesCollection& RHS, SuccessorClass *S = 0) { for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) add(*i, S); @@ -348,6 +409,34 @@ public: /// Removes items from set. void removeItem(RangeIterator i) { Items.erase(i); } + /// Moves whole case from current mapping to the NewMapping object. + void detachCase(self& NewMapping, SuccessorClass *Succ) { + for (CaseItemIt i = Items.begin(); i != Items.end();) + if (i->second == Succ) { + NewMapping.add(i->first, i->second); + Items.erase(i++); + } else + ++i; + } + + /// Removes all clusters for given successor. + void removeCase(SuccessorClass *Succ) { + for (CaseItemIt i = Items.begin(); i != Items.end();) + if (i->second == Succ) { + Items.erase(i++); + } else + ++i; + } + + /// Find successor that satisfies given value. + SuccessorClass *findSuccessor(const IntTy& Val) { + for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { + if (i->first.isInRange(Val)) + return i->second; + } + return 0; + } + /// Calculates the difference between this mapping and RHS. /// THIS without RHS is placed into LExclude, /// RHS without THIS is placed into RExclude, @@ -355,10 +444,16 @@ public: void diff(self *LExclude, self *Intersection, self *RExclude, const self& RHS) { + if (SingleNumbersOnly && RHS.SingleNumbersOnly) { + diff_single_numbers(LExclude, Intersection, RExclude, RHS); + return; + } + DiffStateMachine Machine(LExclude, Intersection, RExclude); CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); - while (L != Items.end() && R != RHS.Items.end()) { + CaseItemConstIt el = Items.end(), er = RHS.Items.end(); + while (L != el && R != er) { const Cluster &LCluster = *L; const RangeEx &LRange = LCluster.first; const Cluster &RCluster = *R; @@ -377,7 +472,36 @@ public: ++R; continue; } + + if (LRange.isSingleNumber() && RRange.isSingleNumber()) { + Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); + Machine.onLRClose(LRange.getLow()); + ++L; + ++R; + continue; + } + if (LRange.isSingleNumber()) { + Machine.onLOpen(LRange.getLow(), LCluster.second); + Machine.onLClose(LRange.getLow()); + ++L; + while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { + Machine.onLOpen(LRange.getLow(), LCluster.second); + Machine.onLClose(LRange.getLow()); + ++L; + } + continue; + } else if (RRange.isSingleNumber()) { + Machine.onROpen(R->first.getLow(), R->second); + Machine.onRClose(R->first.getHigh()); + ++R; + while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { + Machine.onROpen(R->first.getLow(), R->second); + Machine.onRClose(R->first.getHigh()); + ++R; + } + continue; + } else if (LRange.getLow() < RRange.getLow()) { // May be opened in previous iteration. if (!Machine.isLOpened()) @@ -390,7 +514,7 @@ public: Machine.onLOpen(LRange.getLow(), LCluster.second); } else - Machine.onRLOpen(LRange.getLow(), LCluster.second, RCluster.second); + Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); if (LRange.getHigh() < RRange.getHigh()) { Machine.onLClose(LRange.getHigh()); @@ -411,7 +535,7 @@ public: } } else { - Machine.onRLClose(LRange.getHigh()); + Machine.onLRClose(LRange.getHigh()); ++L; ++R; } @@ -441,7 +565,20 @@ public: } /// Builds the finalized case objects. - void getCases(Cases& TheCases) { + void getCases(Cases& TheCases, bool PreventMerging = false) { + //FIXME: PreventMerging is a temporary parameter. + //Currently a set of passes is still knows nothing about + //switches with case ranges, and if these passes meet switch + //with complex case that crashs the application. + if (PreventMerging) { + for (RangeIterator i = this->begin(); i != this->end(); ++i) { + RangesCollection SingleRange; + SingleRange.push_back(i->first); + TheCases.push_back(std::make_pair(i->second, + IntegersSubsetTy(SingleRange))); + } + return; + } CRSMap TheCRSMap; for (RangeIterator i = this->begin(); i != this->end(); ++i) TheCRSMap[i->second].push_back(i->first); @@ -458,6 +595,22 @@ public: return IntegersSubsetTy(Ranges); } + /// Returns pointer to value of case if it is single-numbered or 0 + /// in another case. + const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { + const IntTy* Res = 0; + for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) + if (i->second == Succ) { + if (!i->first.isSingleNumber()) + return 0; + if (Res) + return 0; + else + Res = &(i->first.getLow()); + } + return Res; + } + /// Returns true if there is no ranges and values inside. bool empty() const { return Items.empty(); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 957d00a..72e5769 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2450,22 +2450,23 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, size_t numCmps = 0; for (Clusterifier::RangeIterator i = TheClusterifier.begin(), e = TheClusterifier.end(); i != e; ++i, ++numCmps) { - Clusterifier::Cluster &C = *i; + const Clusterifier::RangeEx &R = i->first; + MachineBasicBlock *MBB = i->second; unsigned W = 0; if (BPI) { - W = BPI->getEdgeWeight(SI.getParent(), C.second->getBasicBlock()); + W = BPI->getEdgeWeight(SI.getParent(), MBB->getBasicBlock()); if (!W) W = 16; - W *= C.first.Weight; - BPI->setEdgeWeight(SI.getParent(), C.second->getBasicBlock(), W); + W *= R.Weight; + BPI->setEdgeWeight(SI.getParent(), MBB->getBasicBlock(), W); } // FIXME: Currently work with ConstantInt based numbers. // Changing it to APInt based is a pretty heavy for this commit. - Cases.push_back(Case(C.first.getLow().toConstantInt(), - C.first.getHigh().toConstantInt(), C.second, W)); + Cases.push_back(Case(R.getLow().toConstantInt(), + R.getHigh().toConstantInt(), MBB, W)); - if (C.first.getLow() != C.first.getHigh()) + if (R.getLow() != R.getHigh()) // A range counts double, since it requires two compares. ++numCmps; } diff --git a/lib/Transforms/Utils/LowerSwitch.cpp b/lib/Transforms/Utils/LowerSwitch.cpp index 1547439..d2bd9d0 100644 --- a/lib/Transforms/Utils/LowerSwitch.cpp +++ b/lib/Transforms/Utils/LowerSwitch.cpp @@ -238,13 +238,14 @@ unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) { size_t numCmps = 0; for (IntegersSubsetToBB::RangeIterator i = TheClusterifier.begin(), e = TheClusterifier.end(); i != e; ++i, ++numCmps) { - IntegersSubsetToBB::Cluster &C = *i; + const IntegersSubsetToBB::RangeTy &R = i->first; + BasicBlock *S = i->second; // FIXME: Currently work with ConstantInt based numbers. // Changing it to APInt based is a pretty heavy for this commit. - Cases.push_back(CaseRange(C.first.getLow().toConstantInt(), - C.first.getHigh().toConstantInt(), C.second)); - if (C.first.isSingleNumber()) + Cases.push_back(CaseRange(R.getLow().toConstantInt(), + R.getHigh().toConstantInt(), S)); + if (R.isSingleNumber()) // A range counts double, since it requires two compares. ++numCmps; } diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index f37ea91..4a58eb3 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -56,26 +56,12 @@ DupRet("simplifycfg-dup-ret", cl::Hidden, cl::init(false), STATISTIC(NumSpeculations, "Number of speculative executed instructions"); namespace { - /// ValueEqualityComparisonCase - Represents a case of a switch. - struct ValueEqualityComparisonCase { - ConstantInt *Value; - BasicBlock *Dest; - - ValueEqualityComparisonCase(ConstantInt *Value, BasicBlock *Dest) - : Value(Value), Dest(Dest) {} - - bool operator<(ValueEqualityComparisonCase RHS) const { - // Comparing pointers is ok as we only rely on the order for uniquing. - return Value < RHS.Value; - } - }; - class SimplifyCFGOpt { const TargetData *const TD; Value *isValueEqualityComparison(TerminatorInst *TI); BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI, - std::vector<ValueEqualityComparisonCase> &Cases); + IntegersSubsetToBB &Mapping); bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, BasicBlock *Pred, IRBuilder<> &Builder); @@ -532,72 +518,25 @@ Value *SimplifyCFGOpt::isValueEqualityComparison(TerminatorInst *TI) { /// decode all of the 'cases' that it represents and return the 'default' block. BasicBlock *SimplifyCFGOpt:: GetValueEqualityComparisonCases(TerminatorInst *TI, - std::vector<ValueEqualityComparisonCase> - &Cases) { + IntegersSubsetToBB &Mapping) { if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { - Cases.reserve(SI->getNumCases()); - for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) - Cases.push_back(ValueEqualityComparisonCase(i.getCaseValue(), - i.getCaseSuccessor())); + for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); + i != e; ++i) + Mapping.add(i.getCaseValueEx(), i.getCaseSuccessor()); return SI->getDefaultDest(); } - + BranchInst *BI = cast<BranchInst>(TI); ICmpInst *ICI = cast<ICmpInst>(BI->getCondition()); - BasicBlock *Succ = BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE); - Cases.push_back(ValueEqualityComparisonCase(GetConstantInt(ICI->getOperand(1), - TD), - Succ)); + IntegersSubsetToBB Builder; + + Mapping.add( + IntItem::fromConstantInt(GetConstantInt(ICI->getOperand(1), TD)), + BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE)); + return BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_EQ); } - -/// EliminateBlockCases - Given a vector of bb/value pairs, remove any entries -/// in the list that match the specified block. -static void EliminateBlockCases(BasicBlock *BB, - std::vector<ValueEqualityComparisonCase> &Cases) { - for (unsigned i = 0, e = Cases.size(); i != e; ++i) - if (Cases[i].Dest == BB) { - Cases.erase(Cases.begin()+i); - --i; --e; - } -} - -/// ValuesOverlap - Return true if there are any keys in C1 that exist in C2 as -/// well. -static bool -ValuesOverlap(std::vector<ValueEqualityComparisonCase> &C1, - std::vector<ValueEqualityComparisonCase > &C2) { - std::vector<ValueEqualityComparisonCase> *V1 = &C1, *V2 = &C2; - - // Make V1 be smaller than V2. - if (V1->size() > V2->size()) - std::swap(V1, V2); - - if (V1->size() == 0) return false; - if (V1->size() == 1) { - // Just scan V2. - ConstantInt *TheVal = (*V1)[0].Value; - for (unsigned i = 0, e = V2->size(); i != e; ++i) - if (TheVal == (*V2)[i].Value) - return true; - } - - // Otherwise, just sort both lists and compare element by element. - array_pod_sort(V1->begin(), V1->end()); - array_pod_sort(V2->begin(), V2->end()); - unsigned i1 = 0, i2 = 0, e1 = V1->size(), e2 = V2->size(); - while (i1 != e1 && i2 != e2) { - if ((*V1)[i1].Value == (*V2)[i2].Value) - return true; - if ((*V1)[i1].Value < (*V2)[i2].Value) - ++i1; - else - ++i2; - } - return false; -} - /// SimplifyEqualityComparisonWithOnlyPredecessor - If TI is known to be a /// terminator instruction and its block is known to only have a single /// predecessor block, check to see if that predecessor is also a value @@ -616,23 +555,27 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, if (ThisVal != PredVal) return false; // Different predicates. // Find out information about when control will move from Pred to TI's block. - std::vector<ValueEqualityComparisonCase> PredCases; + IntegersSubsetToBB PredCases; BasicBlock *PredDef = GetValueEqualityComparisonCases(Pred->getTerminator(), PredCases); - EliminateBlockCases(PredDef, PredCases); // Remove default from cases. + // Remove default from cases. + PredCases.removeCase(PredDef); + // Find information about how control leaves this block. - std::vector<ValueEqualityComparisonCase> ThisCases; + IntegersSubsetToBB ThisCases; BasicBlock *ThisDef = GetValueEqualityComparisonCases(TI, ThisCases); - EliminateBlockCases(ThisDef, ThisCases); // Remove default from cases. + // Remove default from cases. + ThisCases.removeCase(ThisDef); + // If TI's block is the default block from Pred's comparison, potentially // simplify TI based on this knowledge. if (PredDef == TI->getParent()) { // If we are here, we know that the value is none of those cases listed in // PredCases. If there are any cases in ThisCases that are in PredCases, we // can simplify TI. - if (!ValuesOverlap(PredCases, ThisCases)) + if (!PredCases.isOverlapped(ThisCases)) return false; if (isa<BranchInst>(TI)) { @@ -644,7 +587,7 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, (void) NI; // Remove PHI node entries for the dead edge. - ThisCases[0].Dest->removePredecessor(TI->getParent()); + ThisCases.begin()->second->removePredecessor(TI->getParent()); DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator() << "Through successor TI: " << *TI << "Leaving: " << *NI << "\n"); @@ -655,45 +598,45 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, SwitchInst *SI = cast<SwitchInst>(TI); // Okay, TI has cases that are statically dead, prune them away. - SmallPtrSet<Constant*, 16> DeadCases; - for (unsigned i = 0, e = PredCases.size(); i != e; ++i) - DeadCases.insert(PredCases[i].Value); + IRBuilder<> CodeBuilder(SI); + CodeBuilder.SetCurrentDebugLocation(SI->getDebugLoc()); DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator() << "Through successor TI: " << *TI); - for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) { - --i; - if (DeadCases.count(i.getCaseValue())) { - i.getCaseSuccessor()->removePredecessor(TI->getParent()); - SI->removeCase(i); - } - } - - DEBUG(dbgs() << "Leaving: " << *TI << "\n"); + // Okay, TI has cases that are statically dead, prune them away. + IntegersSubsetToBB NewThisCases; + IntegersSubsetToBB WastedCases; + ThisCases.diff(&NewThisCases, &WastedCases, 0, PredCases); + + IntegersSubsetToBB::Cases Cases; + NewThisCases.getCases(Cases, true/*temporary prevent complex cases*/); + + SwitchInst *NewSI = + CodeBuilder.CreateSwitch(ThisVal, SI->getDefaultDest(), Cases.size()); + + for (IntegersSubsetToBB::RangeIterator i = WastedCases.begin(), + e = WastedCases.end(); i != e; ++i) + i->second->removePredecessor(TI->getParent()); + + for (IntegersSubsetToBB::CasesIt i = Cases.begin(), e = Cases.end(); + i != e; ++i) + NewSI->addCase(i->second, i->first); + + EraseTerminatorInstAndDCECond(SI); + DEBUG(dbgs() << "Leaving: " << *NewSI << "\n"); return true; } // Otherwise, TI's block must correspond to some matched value. Find out // which value (or set of values) this is. - ConstantInt *TIV = 0; BasicBlock *TIBB = TI->getParent(); - for (unsigned i = 0, e = PredCases.size(); i != e; ++i) - if (PredCases[i].Dest == TIBB) { - if (TIV != 0) - return false; // Cannot handle multiple values coming to this block. - TIV = PredCases[i].Value; - } - assert(TIV && "No edge from pred to succ?"); + const IntItem* TIVIntITem = PredCases.getCaseSingleNumber(TIBB); + assert(TIVIntITem && "No edge from pred to succ?"); // Okay, we found the one constant that our value can be if we get into TI's // BB. Find out which successor will unconditionally be branched to. - BasicBlock *TheRealDest = 0; - for (unsigned i = 0, e = ThisCases.size(); i != e; ++i) - if (ThisCases[i].Value == TIV) { - TheRealDest = ThisCases[i].Dest; - break; - } + BasicBlock *TheRealDest = ThisCases.findSuccessor(*TIVIntITem); // If not handled by any explicit cases, it is handled by the default case. if (TheRealDest == 0) TheRealDest = ThisDef; @@ -759,10 +702,10 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI, if (PCV == CV && SafeToMergeTerminators(TI, PTI)) { // Figure out which 'cases' to copy from SI to PSI. - std::vector<ValueEqualityComparisonCase> BBCases; + IntegersSubsetToBB BBCases; BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases); - std::vector<ValueEqualityComparisonCase> PredCases; + IntegersSubsetToBB PredCases; BasicBlock *PredDefault = GetValueEqualityComparisonCases(PTI, PredCases); // Based on whether the default edge from PTI goes to BB or not, fill in @@ -773,61 +716,51 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI, if (PredDefault == BB) { // If this is the default destination from PTI, only the edges in TI // that don't occur in PTI, or that branch to BB will be activated. - std::set<ConstantInt*, ConstantIntOrdering> PTIHandled; - for (unsigned i = 0, e = PredCases.size(); i != e; ++i) - if (PredCases[i].Dest != BB) - PTIHandled.insert(PredCases[i].Value); - else { - // The default destination is BB, we don't need explicit targets. - std::swap(PredCases[i], PredCases.back()); - PredCases.pop_back(); - --i; --e; - } - - // Reconstruct the new switch statement we will be building. + + PredCases.removeCase(BB); + IntegersSubsetToBB NewBBCases; + BBCases.diff(&NewBBCases, 0, 0, PredCases); + PredCases.add(NewBBCases); + for (IntegersSubsetToBB::RangeIterator i = NewBBCases.begin(), + e = NewBBCases.end(); i != e; ++i) + NewSuccessors.push_back(i->second); + + // Replace the default if needed. if (PredDefault != BBDefault) { PredDefault->removePredecessor(Pred); PredDefault = BBDefault; NewSuccessors.push_back(BBDefault); } - for (unsigned i = 0, e = BBCases.size(); i != e; ++i) - if (!PTIHandled.count(BBCases[i].Value) && - BBCases[i].Dest != BBDefault) { - PredCases.push_back(BBCases[i]); - NewSuccessors.push_back(BBCases[i].Dest); - } } else { // If this is not the default destination from PSI, only the edges // in SI that occur in PSI with a destination of BB will be // activated. - std::set<ConstantInt*, ConstantIntOrdering> PTIHandled; - for (unsigned i = 0, e = PredCases.size(); i != e; ++i) - if (PredCases[i].Dest == BB) { - PTIHandled.insert(PredCases[i].Value); - std::swap(PredCases[i], PredCases.back()); - PredCases.pop_back(); - --i; --e; - } + IntegersSubsetToBB BBPredCase; + PredCases.detachCase(BBPredCase, BB); + IntegersSubsetToBB CasesWithBBDef; + IntegersSubsetToBB InharitedCases; // Okay, now we know which constants were sent to BB from the // predecessor. Figure out where they will all go now. - for (unsigned i = 0, e = BBCases.size(); i != e; ++i) - if (PTIHandled.count(BBCases[i].Value)) { - // If this is one we are capable of getting... - PredCases.push_back(BBCases[i]); - NewSuccessors.push_back(BBCases[i].Dest); - PTIHandled.erase(BBCases[i].Value);// This constant is taken care of - } - + if (!BBPredCase.empty()) { + BBCases.diff( + 0, // LHS excl RHS + &InharitedCases, // intersection + &CasesWithBBDef, // RHS excl LHS + BBPredCase); // RHS. + } + PredCases.add(InharitedCases); + for (IntegersSubsetToBB::RangeIterator i = InharitedCases.begin(), + e = InharitedCases.end(); + i != e; ++i) + NewSuccessors.push_back(i->second); + // If there are any constants vectored to BB that TI doesn't handle, // they must go to the default destination of TI. - for (std::set<ConstantInt*, ConstantIntOrdering>::iterator I = - PTIHandled.begin(), - E = PTIHandled.end(); I != E; ++I) { - PredCases.push_back(ValueEqualityComparisonCase(*I, BBDefault)); + PredCases.add(CasesWithBBDef, BBDefault); + for (unsigned i = 0, e = CasesWithBBDef.size(); i != e; ++i) NewSuccessors.push_back(BBDefault); - } } // Okay, at this point, we know which new successor Pred will get. Make @@ -848,8 +781,12 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI, SwitchInst *NewSI = Builder.CreateSwitch(CV, PredDefault, PredCases.size()); NewSI->setDebugLoc(PTI->getDebugLoc()); - for (unsigned i = 0, e = PredCases.size(); i != e; ++i) - NewSI->addCase(PredCases[i].Value, PredCases[i].Dest); + IntegersSubsetToBB::Cases Cases; + PredCases.getCases(Cases, true/*temporary prevent complex case*/); + + for (IntegersSubsetToBB::CasesIt i = Cases.begin(), e = Cases.end(); + i != e; ++i) + NewSI->addCase(i->second, i->first); EraseTerminatorInstAndDCECond(PTI); diff --git a/test/Transforms/SimplifyCFG/switch_create.ll b/test/Transforms/SimplifyCFG/switch_create.ll index 546cc75..c62afd5 100644 --- a/test/Transforms/SimplifyCFG/switch_create.ll +++ b/test/Transforms/SimplifyCFG/switch_create.ll @@ -82,8 +82,8 @@ lor.end: ; preds = %lor.rhs, %lor.lhs.f ; CHECK: @test4 ; CHECK: switch i8 %c, label %lor.rhs [ -; CHECK: i8 62, label %lor.end ; CHECK: i8 34, label %lor.end +; CHECK: i8 62, label %lor.end ; CHECK: i8 92, label %lor.end ; CHECK: ] } diff --git a/unittests/Support/IntegersSubsetTest.cpp b/unittests/Support/IntegersSubsetTest.cpp index 5d1dde4..a103161 100644 --- a/unittests/Support/IntegersSubsetTest.cpp +++ b/unittests/Support/IntegersSubsetTest.cpp @@ -193,20 +193,20 @@ namespace { const unsigned_ranges IntersectRes, unsigned IntersectResSize ) { - + unsigned successors[2] = {0, 1}; Mapping::RangesCollection Ranges; Mapping LHSMapping; for (unsigned i = 0; i < LSize; ++i) Ranges.push_back(Range(Int(LHS[i][0]), Int(LHS[i][1]))); - LHSMapping.add(Ranges); + LHSMapping.add(Ranges, &successors[0]); Ranges.clear(); Mapping RHSMapping; for (unsigned i = 0; i < RSize; ++i) Ranges.push_back(Range(Int(RHS[i][0]), Int(RHS[i][1]))); - RHSMapping.add(Ranges); + RHSMapping.add(Ranges, &successors[1]); Mapping LExclude, Intersection; @@ -217,8 +217,10 @@ namespace { unsigned i = 0; for (Mapping::RangeIterator rei = LExclude.begin(), - e = LExclude.end(); rei != e; ++rei, ++i) + e = LExclude.end(); rei != e; ++rei, ++i) { EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1])); + EXPECT_EQ(rei->second, &successors[0]); + } } else EXPECT_TRUE(LExclude.empty()); @@ -227,8 +229,10 @@ namespace { unsigned i = 0; for (Mapping::RangeIterator ii = Intersection.begin(), - e = Intersection.end(); ii != e; ++ii, ++i) + e = Intersection.end(); ii != e; ++ii, ++i) { EXPECT_EQ(ii->first, Range(IntersectRes[i][0], IntersectRes[i][1])); + EXPECT_EQ(ii->second, &successors[0]); + } } else EXPECT_TRUE(Intersection.empty()); @@ -241,9 +245,11 @@ namespace { EXPECT_EQ(LExclude.size(), ExcludeResSize); unsigned i = 0; - for (Mapping::RangeIterator rei = LExclude.begin(), - e = LExclude.end(); rei != e; ++rei, ++i) - EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1])); + for (Mapping::RangeIterator lei = LExclude.begin(), + e = LExclude.end(); lei != e; ++lei, ++i) { + EXPECT_EQ(lei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1])); + EXPECT_EQ(lei->second, &successors[0]); + } } else EXPECT_TRUE(LExclude.empty()); } |