From: Stepan Dyatkovskiy Date: Fri, 1 Jun 2012 16:17:57 +0000 (+0000) Subject: PR1255: case ranges. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6bb5c0074dc4cede2ad8efd420ec91288f91b012;p=oota-llvm.git PR1255: case ranges. IntegersSubset devided into IntegersSubsetGeneric and into IntegersSubset itself. The first has no references to ConstantInt and works with IntItem only. IntegersSubsetMapping also made generic. Here added second template parameter "IntegersSubsetTy" that allows to use on of two IntegersSubset types described below. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157815 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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,30 +267,41 @@ 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; - bool IsWide; +protected: - // 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; - } + FlatCollectionTy FlatCollection; + RangeLinksTy RangeLinks; - operator Constant*() { return Array; } - operator const Constant*() const { return Array; } - Constant *operator->() { return Array; } - const Constant *operator->() const { return Array; } +public: + + 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); + } + } typedef IntRange Range; @@ -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) - 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)) + if (RangeLinks[i].first == RangeLinks[i].second) { + if (*RangeLinks[i].first == 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;