diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index 95110ea2c10..ee797b9dde0 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -19,6 +19,8 @@ #ifndef CONSTANTRANGESSET_H_ #define CONSTANTRANGESSET_H_ +#include + #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" @@ -109,8 +111,12 @@ public: INT_ITEM_DEFINE_COMPARISON(>, ugt) INT_ITEM_DEFINE_COMPARISON(<=, ule) INT_ITEM_DEFINE_COMPARISON(>=, uge) + INT_ITEM_DEFINE_COMPARISON(==, eq) + INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t) + INT_ITEM_DEFINE_COMPARISON(!=, ne) + INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t) INT_ITEM_DEFINE_BINARY_OP(*) INT_ITEM_DEFINE_BINARY_OP(+) @@ -160,7 +166,7 @@ public: LikeThis.ConstantIntVal->getContext(), V)); return fromConstantInt(C); } - ConstantInt *toConstantInt() { + ConstantInt *toConstantInt() const { return ConstantIntVal; } }; @@ -261,31 +267,42 @@ struct IntRange { }; //===----------------------------------------------------------------------===// -/// ConstantRangesSet - class that implements constant set of ranges. -/// It is a wrapper for some real "holder" class (currently ConstantArray). -/// It contains functions, that allows to parse "holder" like a set of ranges. -/// Note: It is assumed that "holder" is inherited from Constant object. -/// ConstantRangesSet may be converted to and from Constant* pointer. -/// -class IntegersSubset { - Constant *Array; +/// IntegersSubsetGeneric - class that implements the subset of integers. It +/// consists from ranges and single numbers. +class IntegersSubsetGeneric { +public: + // Use Chris Lattner idea, that was initially described here: + // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html + // In short, for more compact memory consumption we can store flat + // numbers collection, and define range as pair of indices. + // In that case we can safe some memory on 32 bit machines. + typedef std::list FlatCollectionTy; + typedef std::pair RangeLinkTy; + typedef SmallVector RangeLinksTy; + typedef RangeLinksTy::iterator RangeLinksConstIt; + +protected: + + FlatCollectionTy FlatCollection; + RangeLinksTy RangeLinks; + public: - bool IsWide; - - // implicit - IntegersSubset(Constant *V) : Array(V) { - ArrayType *ArrTy = cast(Array->getType()); - VectorType *VecTy = cast(ArrTy->getElementType()); - IntegerType *IntTy = cast(VecTy->getElementType()); - IsWide = IntTy->getBitWidth() > 64; + template + IntegersSubsetGeneric(const RangesCollectionTy& Links) { + assert(Links.size() && "Empty ranges are not allowed."); + for (typename RangesCollectionTy::const_iterator i = Links.begin(), + e = Links.end(); i != e; ++i) { + RangeLinkTy RangeLink; + FlatCollection.push_back(i->Low); + RangeLink.first = &FlatCollection.back(); + if (i->Low != i->High) + FlatCollection.push_back(i->High); + RangeLink.second = &FlatCollection.back(); + RangeLinks.push_back(RangeLink); + } } - operator Constant*() { return Array; } - operator const Constant*() const { return Array; } - Constant *operator->() { return Array; } - const Constant *operator->() const { return Array; } - typedef IntRange Range; /// Checks is the given constant satisfies this case. Returns @@ -293,81 +310,33 @@ public: /// contained ranges. bool isSatisfies(const IntItem &CheckingVal) const { for (unsigned i = 0, e = getNumItems(); i < e; ++i) { - const Constant *CV = Array->getAggregateElement(i); - unsigned VecSize = cast(CV->getType())->getNumElements(); - switch (VecSize) { - case 1: - if (cast(CV->getAggregateElement(0U))->getValue() == - CheckingVal) + if (RangeLinks[i].first == RangeLinks[i].second) { + if (*RangeLinks[i].first == CheckingVal) return true; - break; - case 2: { - const APInt &Lo = - cast(CV->getAggregateElement(0U))->getValue(); - const APInt &Hi = - cast(CV->getAggregateElement(1))->getValue(); - if (Lo.uge(CheckingVal) && Hi.ule(CheckingVal)) - return true; - } - break; - default: - assert(0 && "Only pairs and single numbers are allowed here."); - break; - } + } else if (*RangeLinks[i].first >= CheckingVal && + *RangeLinks[i].second <= CheckingVal) + return true; } return false; } /// Returns set's item with given index. - Range getItem(unsigned idx) { - Constant *CV = Array->getAggregateElement(idx); - unsigned NumEls = cast(CV->getType())->getNumElements(); - switch (NumEls) { - case 1: - return Range(IntItem::fromConstantInt( - cast(CV->getAggregateElement(0U)))); - case 2: - return Range(IntItem::fromConstantInt( - cast(CV->getAggregateElement(0U))), - IntItem::fromConstantInt( - cast(CV->getAggregateElement(1U)))); - default: - assert(0 && "Only pairs and single numbers are allowed here."); - return Range(); - } - } - - const Range getItem(unsigned idx) const { - const Constant *CV = Array->getAggregateElement(idx); - - unsigned NumEls = cast(CV->getType())->getNumElements(); - switch (NumEls) { - case 1: - return Range(IntItem::fromConstantInt( - cast(CV->getAggregateElement(0U))), - IntItem::fromConstantInt(cast( - cast(CV->getAggregateElement(0U))))); - case 2: - return Range(IntItem::fromConstantInt( - cast(CV->getAggregateElement(0U))), - IntItem::fromConstantInt( - cast(CV->getAggregateElement(1)))); - default: - assert(0 && "Only pairs and single numbers are allowed here."); - return Range(); - } - } + Range getItem(unsigned idx) const { + const RangeLinkTy &Link = RangeLinks[idx]; + if (Link.first != Link.second) + return Range(*Link.first, *Link.second); + else + return Range(*Link.first); + } /// Return number of items (ranges) stored in set. unsigned getNumItems() const { - return cast(Array->getType())->getNumElements(); + return RangeLinks.size(); } - bool isWideNumberFormat() const { return IsWide; } - bool isSingleNumber(unsigned idx) const { - Constant *CV = Array->getAggregateElement(idx); - return cast(CV->getType())->getNumElements() == 1; + return RangeLinks.size() == 1 && + RangeLinks[0].first == RangeLinks[0].second; } /// Returns set the size, that equals number of all values + sizes of all @@ -411,6 +380,86 @@ public: } }; +//===----------------------------------------------------------------------===// +/// IntegersSubset - currenly is extension of IntegersSubsetGeneric +/// that also supports conversion to/from Constant* object. +class IntegersSubset : public IntegersSubsetGeneric { + Constant *Holder; + + static unsigned getNumItemsFromConstant(Constant *C) { + return cast(C->getType())->getNumElements(); + } + + static Range getItemFromConstant(Constant *C, unsigned idx) { + const Constant *CV = C->getAggregateElement(idx); + + unsigned NumEls = cast(CV->getType())->getNumElements(); + switch (NumEls) { + case 1: + return Range(IntItem::fromConstantInt( + cast(CV->getAggregateElement(0U))), + IntItem::fromConstantInt(cast( + cast(CV->getAggregateElement(0U))))); + case 2: + return Range(IntItem::fromConstantInt( + cast(CV->getAggregateElement(0U))), + IntItem::fromConstantInt( + cast(CV->getAggregateElement(1)))); + default: + assert(0 && "Only pairs and single numbers are allowed here."); + return Range(); + } + } + + std::vector rangesFromConstant(Constant *C) { + unsigned NumItems = getNumItemsFromConstant(C); + std::vector r; + r.reserve(NumItems); + for (unsigned i = 0, e = NumItems; i != e; ++i) + r.push_back(getItemFromConstant(C, i)); + return r; + } + +public: + + IntegersSubset(Constant *C) : IntegersSubsetGeneric(rangesFromConstant(C)), + Holder(C) {} + + // implicit + template + IntegersSubset(const RangesCollectionTy& Src) : + IntegersSubsetGeneric(Src) { + + std::vector Elts; + Elts.reserve(Src.size()); + for (typename RangesCollectionTy::const_iterator i = Src.begin(), + e = Src.end(); i != e; ++i) { + const Range &R = *i; + std::vector r; + if (R.Low != R.High) { + r.reserve(2); + // FIXME: Since currently we have ConstantInt based numbers + // use hack-conversion of IntItem to ConstantInt + r.push_back(R.Low.toConstantInt()); + r.push_back(R.High.toConstantInt()); + } else { + r.reserve(1); + r.push_back(R.Low.toConstantInt()); + } + Constant *CV = ConstantVector::get(r); + Elts.push_back(CV); + } + ArrayType *ArrTy = + ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); + Holder = ConstantArray::get(ArrTy, Elts); + } + + operator Constant*() { return Holder; } + operator const Constant*() const { return Holder; } + Constant *operator->() { return Holder; } + const Constant *operator->() const { return Holder; } +}; + } #endif /* CONSTANTRANGESSET_H_ */ diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h index 374a68772eb..1ea1f0d7c2e 100644 --- a/include/llvm/Support/IntegersSubsetMapping.h +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -26,14 +26,14 @@ namespace llvm { -template +template class IntegersSubsetMapping { public: - typedef IntegersSubset::Range RangeTy; + typedef IntRange RangeTy; struct RangeEx : public RangeTy { - typedef IntegersSubset::Range RangeTy; + typedef IntRange RangeTy; RangeEx() : Weight(1) {} RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {} RangeEx(const IntItem &C) : RangeTy(C), Weight(1) {} @@ -88,31 +88,6 @@ protected: Sorted = true; } } - - IntegersSubset getCase(RangesCollection& Src) { - std::vector Elts; - Elts.reserve(Src.size()); - for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) { - RangeTy &R = *i; - std::vector r; - if (R.isSingleNumber()) { - r.reserve(2); - // FIXME: Since currently we have ConstantInt based numbers - // use hack-conversion of IntItem to ConstantInt - r.push_back(R.Low.toConstantInt()); - r.push_back(R.High.toConstantInt()); - } else { - r.reserve(1); - r.push_back(R.Low.toConstantInt()); - } - Constant *CV = ConstantVector::get(r); - Elts.push_back(CV); - } - ArrayType *ArrTy = - ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); - Constant *Array = ConstantArray::get(ArrTy, Elts); - return IntegersSubset(Array); - } public: @@ -122,7 +97,7 @@ public: // factory. typedef CaseItemIt RangeIterator; - typedef std::pair Case; + typedef std::pair Case; typedef std::list Cases; IntegersSubsetMapping() { @@ -214,7 +189,7 @@ public: for (RangeIterator i = this->begin(); i != this->end(); ++i) TheCRSMap[i->second].push_back(i->first); for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) - TheCases.push_back(std::make_pair(i->first, getCase(i->second))); + TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); } /// Builds the finalized case objects ignoring successor values, as though @@ -223,7 +198,7 @@ public: RangesCollection Ranges; for (RangeIterator i = this->begin(); i != this->end(); ++i) Ranges.push_back(i->first); - return getCase(Ranges); + return IntegersSubsetTy(Ranges); } /// Returns true if there is no ranges and values inside. @@ -234,7 +209,7 @@ public: }; class BasicBlock; -typedef IntegersSubsetMapping IntegersSubsetToBB; +typedef IntegersSubsetMapping IntegersSubsetToBB; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 15c4258ddb8..ff3993f2224 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2427,7 +2427,7 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, /// Use a shorter form of declaration, and also /// show the we want to use CRSBuilder as Clusterifier. - typedef IntegersSubsetMapping Clusterifier; + typedef IntegersSubsetMapping Clusterifier; Clusterifier TheClusterifier;