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, 211 insertions, 329 deletions
diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index 4d76fab..bb9e769 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -182,12 +182,7 @@ protected: IntType Low; IntType High; bool IsEmpty : 1; - enum Type { - SINGLE_NUMBER, - RANGE, - UNKNOWN - }; - Type RangeType; + bool IsSingleNumber : 1; public: typedef IntRange<IntType> self; @@ -196,30 +191,15 @@ public: IntRange() : IsEmpty(true) {} IntRange(const self &RHS) : Low(RHS.Low), High(RHS.High), - IsEmpty(RHS.IsEmpty), RangeType(RHS.RangeType) {} + IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} IntRange(const IntType &C) : - Low(C), High(C), IsEmpty(false), RangeType(SINGLE_NUMBER) {} + Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} IntRange(const IntType &L, const IntType &H) : Low(L), High(H), - IsEmpty(false), RangeType(UNKNOWN) {} + IsEmpty(false), IsSingleNumber(Low == High) {} bool isEmpty() const { return IsEmpty; } - bool isSingleNumber() const { - switch (RangeType) { - case SINGLE_NUMBER: - return true; - case RANGE: - return false; - case UNKNOWN: - if (Low == High) { - const_cast<Type&>(RangeType) = SINGLE_NUMBER; - return true; - } - const_cast<Type&>(RangeType) = RANGE; - return false; - } - llvm_unreachable("Unknown state?!"); - } + bool isSingleNumber() const { return IsSingleNumber; } const IntType& getLow() const { assert(!IsEmpty && "Range is empty."); @@ -233,13 +213,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; } @@ -532,7 +512,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 915c777..87d0755 100644 --- a/include/llvm/Support/IntegersSubsetMapping.h +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -58,16 +58,22 @@ public: protected: - typedef std::map<RangeEx, SuccessorClass*> CaseItems; + typedef std::list<Cluster> 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 SingleNumbersOnly; + bool Sorted; bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { return LItem->first.getHigh() >= RItem->first.getLow(); @@ -85,6 +91,18 @@ 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, @@ -195,7 +213,7 @@ protected: } } - void onLROpen(const IntTy &Pt, + void onRLOpen(const IntTy &Pt, SuccessorClass *LS, SuccessorClass *RS) { switch (State) { @@ -211,7 +229,7 @@ protected: OpenPt = Pt; } - void onLRClose(const IntTy &Pt) { + void onRLClose(const IntTy &Pt) { switch (State) { case INTERSECT_OPENED: if (IntersectionMapping) @@ -227,48 +245,6 @@ 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: @@ -280,18 +256,15 @@ public: typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; typedef std::list<Case> Cases; - typedef typename Cases::iterator CasesIt; - - IntegersSubsetMapping() : SingleNumbersOnly(true) {} - bool verify() { - RangeIterator DummyErrItem; - return verify(DummyErrItem); + IntegersSubsetMapping() { + Sorted = false; } 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) { @@ -302,36 +275,10 @@ 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(); @@ -356,6 +303,8 @@ public: } RangeEx R(*Low, *High, Weight); add(R, Successor); + // We recollected the Items, but we kept it sorted. + Sorted = true; } /// Adds a constant value. @@ -374,10 +323,8 @@ public: add(REx, S); } void add(const RangeEx &R, SuccessorClass *S = 0) { - //Items.push_back(std::make_pair(R, S)); - Items.insert(std::make_pair(R, S)); - if (!R.isSingleNumber()) - SingleNumbersOnly = false; + Items.push_back(std::make_pair(R, S)); + Sorted = false; } /// Adds all ranges and values from given ranges set to the current @@ -390,17 +337,9 @@ public: } void add(self& RHS) { - //Items.insert(Items.begin(), RHS.Items.begin(), RHS.Items.end()); - Items.insert(RHS.Items.begin(), RHS.Items.end()); - if (!RHS.SingleNumbersOnly) - SingleNumbersOnly = false; + Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); } - 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); @@ -409,34 +348,6 @@ 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, @@ -444,16 +355,10 @@ 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(); - CaseItemConstIt el = Items.end(), er = RHS.Items.end(); - while (L != el && R != er) { + while (L != Items.end() && R != RHS.Items.end()) { const Cluster &LCluster = *L; const RangeEx &LRange = LCluster.first; const Cluster &RCluster = *R; @@ -472,36 +377,7 @@ 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()) @@ -514,7 +390,7 @@ public: Machine.onLOpen(LRange.getLow(), LCluster.second); } else - Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); + Machine.onRLOpen(LRange.getLow(), LCluster.second, RCluster.second); if (LRange.getHigh() < RRange.getHigh()) { Machine.onLClose(LRange.getHigh()); @@ -535,7 +411,7 @@ public: } } else { - Machine.onLRClose(LRange.getHigh()); + Machine.onRLClose(LRange.getHigh()); ++L; ++R; } @@ -565,20 +441,7 @@ public: } /// Builds the finalized case objects. - 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; - } + void getCases(Cases& TheCases) { CRSMap TheCRSMap; for (RangeIterator i = this->begin(); i != this->end(); ++i) TheCRSMap[i->second].push_back(i->first); @@ -595,22 +458,6 @@ 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 2d07407..42b9099 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2450,23 +2450,22 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, size_t numCmps = 0; for (Clusterifier::RangeIterator i = TheClusterifier.begin(), e = TheClusterifier.end(); i != e; ++i, ++numCmps) { - const Clusterifier::RangeEx &R = i->first; - MachineBasicBlock *MBB = i->second; + Clusterifier::Cluster &C = *i; unsigned W = 0; if (BPI) { - W = BPI->getEdgeWeight(SI.getParent(), MBB->getBasicBlock()); + W = BPI->getEdgeWeight(SI.getParent(), C.second->getBasicBlock()); if (!W) W = 16; - W *= R.Weight; - BPI->setEdgeWeight(SI.getParent(), MBB->getBasicBlock(), W); + W *= C.first.Weight; + BPI->setEdgeWeight(SI.getParent(), C.second->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(R.getLow().toConstantInt(), - R.getHigh().toConstantInt(), MBB, W)); + Cases.push_back(Case(C.first.getLow().toConstantInt(), + C.first.getHigh().toConstantInt(), C.second, W)); - if (R.getLow() != R.getHigh()) + if (C.first.getLow() != C.first.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 d2bd9d0..1547439 100644 --- a/lib/Transforms/Utils/LowerSwitch.cpp +++ b/lib/Transforms/Utils/LowerSwitch.cpp @@ -238,14 +238,13 @@ unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) { size_t numCmps = 0; for (IntegersSubsetToBB::RangeIterator i = TheClusterifier.begin(), e = TheClusterifier.end(); i != e; ++i, ++numCmps) { - const IntegersSubsetToBB::RangeTy &R = i->first; - BasicBlock *S = i->second; + IntegersSubsetToBB::Cluster &C = *i; // FIXME: Currently work with ConstantInt based numbers. // Changing it to APInt based is a pretty heavy for this commit. - Cases.push_back(CaseRange(R.getLow().toConstantInt(), - R.getHigh().toConstantInt(), S)); - if (R.isSingleNumber()) + Cases.push_back(CaseRange(C.first.getLow().toConstantInt(), + C.first.getHigh().toConstantInt(), C.second)); + if (C.first.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 4a58eb3..f37ea91 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -56,12 +56,26 @@ 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, - IntegersSubsetToBB &Mapping); + std::vector<ValueEqualityComparisonCase> &Cases); bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, BasicBlock *Pred, IRBuilder<> &Builder); @@ -518,25 +532,72 @@ Value *SimplifyCFGOpt::isValueEqualityComparison(TerminatorInst *TI) { /// decode all of the 'cases' that it represents and return the 'default' block. BasicBlock *SimplifyCFGOpt:: GetValueEqualityComparisonCases(TerminatorInst *TI, - IntegersSubsetToBB &Mapping) { + std::vector<ValueEqualityComparisonCase> + &Cases) { if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { - for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); - i != e; ++i) - Mapping.add(i.getCaseValueEx(), i.getCaseSuccessor()); + 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())); return SI->getDefaultDest(); } - + BranchInst *BI = cast<BranchInst>(TI); ICmpInst *ICI = cast<ICmpInst>(BI->getCondition()); - IntegersSubsetToBB Builder; - - Mapping.add( - IntItem::fromConstantInt(GetConstantInt(ICI->getOperand(1), TD)), - BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE)); - + BasicBlock *Succ = BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE); + Cases.push_back(ValueEqualityComparisonCase(GetConstantInt(ICI->getOperand(1), + TD), + Succ)); 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 @@ -555,27 +616,23 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, if (ThisVal != PredVal) return false; // Different predicates. // Find out information about when control will move from Pred to TI's block. - IntegersSubsetToBB PredCases; + std::vector<ValueEqualityComparisonCase> 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. - IntegersSubsetToBB ThisCases; + std::vector<ValueEqualityComparisonCase> 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 (!PredCases.isOverlapped(ThisCases)) + if (!ValuesOverlap(PredCases, ThisCases)) return false; if (isa<BranchInst>(TI)) { @@ -587,7 +644,7 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, (void) NI; // Remove PHI node entries for the dead edge. - ThisCases.begin()->second->removePredecessor(TI->getParent()); + ThisCases[0].Dest->removePredecessor(TI->getParent()); DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator() << "Through successor TI: " << *TI << "Leaving: " << *NI << "\n"); @@ -598,45 +655,45 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, SwitchInst *SI = cast<SwitchInst>(TI); // Okay, TI has cases that are statically dead, prune them away. - IRBuilder<> CodeBuilder(SI); - CodeBuilder.SetCurrentDebugLocation(SI->getDebugLoc()); + SmallPtrSet<Constant*, 16> DeadCases; + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + DeadCases.insert(PredCases[i].Value); DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator() << "Through successor TI: " << *TI); - // 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"); + 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"); 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(); - const IntItem* TIVIntITem = PredCases.getCaseSingleNumber(TIBB); - assert(TIVIntITem && "No edge from pred to succ?"); + 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?"); // 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 = ThisCases.findSuccessor(*TIVIntITem); + BasicBlock *TheRealDest = 0; + for (unsigned i = 0, e = ThisCases.size(); i != e; ++i) + if (ThisCases[i].Value == TIV) { + TheRealDest = ThisCases[i].Dest; + break; + } // If not handled by any explicit cases, it is handled by the default case. if (TheRealDest == 0) TheRealDest = ThisDef; @@ -702,10 +759,10 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI, if (PCV == CV && SafeToMergeTerminators(TI, PTI)) { // Figure out which 'cases' to copy from SI to PSI. - IntegersSubsetToBB BBCases; + std::vector<ValueEqualityComparisonCase> BBCases; BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases); - IntegersSubsetToBB PredCases; + std::vector<ValueEqualityComparisonCase> PredCases; BasicBlock *PredDefault = GetValueEqualityComparisonCases(PTI, PredCases); // Based on whether the default edge from PTI goes to BB or not, fill in @@ -716,51 +773,61 @@ 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. - - 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. + 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. 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. - IntegersSubsetToBB BBPredCase; - PredCases.detachCase(BBPredCase, BB); - IntegersSubsetToBB CasesWithBBDef; - IntegersSubsetToBB InharitedCases; + 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; + } // Okay, now we know which constants were sent to BB from the // predecessor. Figure out where they will all go now. - 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); - + 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 there are any constants vectored to BB that TI doesn't handle, // they must go to the default destination of TI. - PredCases.add(CasesWithBBDef, BBDefault); - for (unsigned i = 0, e = CasesWithBBDef.size(); i != e; ++i) + for (std::set<ConstantInt*, ConstantIntOrdering>::iterator I = + PTIHandled.begin(), + E = PTIHandled.end(); I != E; ++I) { + PredCases.push_back(ValueEqualityComparisonCase(*I, BBDefault)); NewSuccessors.push_back(BBDefault); + } } // Okay, at this point, we know which new successor Pred will get. Make @@ -781,12 +848,8 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI, SwitchInst *NewSI = Builder.CreateSwitch(CV, PredDefault, PredCases.size()); NewSI->setDebugLoc(PTI->getDebugLoc()); - 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); + for (unsigned i = 0, e = PredCases.size(); i != e; ++i) + NewSI->addCase(PredCases[i].Value, PredCases[i].Dest); EraseTerminatorInstAndDCECond(PTI); diff --git a/test/Transforms/SimplifyCFG/switch_create.ll b/test/Transforms/SimplifyCFG/switch_create.ll index c62afd5..546cc75 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 34, label %lor.end ; CHECK: i8 62, label %lor.end +; CHECK: i8 34, label %lor.end ; CHECK: i8 92, label %lor.end ; CHECK: ] } diff --git a/unittests/Support/IntegersSubsetTest.cpp b/unittests/Support/IntegersSubsetTest.cpp index a103161..5d1dde4 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, &successors[0]); + LHSMapping.add(Ranges); 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, &successors[1]); + RHSMapping.add(Ranges); Mapping LExclude, Intersection; @@ -217,10 +217,8 @@ 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()); @@ -229,10 +227,8 @@ 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()); @@ -245,11 +241,9 @@ namespace { EXPECT_EQ(LExclude.size(), ExcludeResSize); unsigned i = 0; - 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]); - } + for (Mapping::RangeIterator rei = LExclude.begin(), + e = LExclude.end(); rei != e; ++rei, ++i) + EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1])); } else EXPECT_TRUE(LExclude.empty()); } |