From: Stepan Dyatkovskiy Date: Fri, 11 May 2012 10:34:23 +0000 (+0000) Subject: PR1255: ConstantRangesSet and CRSBuilder classes moved from include/llvm to include... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cb7a5f5f577e9477f6d5e3d0fa1558c4f229c1a6;p=oota-llvm.git PR1255: ConstantRangesSet and CRSBuilder classes moved from include/llvm to include/llvm/Support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156613 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CRSBuilder.h b/include/llvm/CRSBuilder.h deleted file mode 100644 index 9257abc3848..00000000000 --- a/include/llvm/CRSBuilder.h +++ /dev/null @@ -1,252 +0,0 @@ -//===- CRSBuilder.h - ConstantRangesSet Builder -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// @file -/// CRSBuilder allows to build and parse ConstantRangesSet objects. -/// There is such features like add/remove range, or combine -/// Two ConstantRangesSet object with neighboring ranges merging. -/// Set IsReadonly=true if you want to operate with "const ConstantInt" and -/// "const ConstantRangesSet" objects. -// -//===----------------------------------------------------------------------===// - -#ifndef CRSBUILDER_H_ -#define CRSBUILDER_H_ - -#include "llvm/ConstantRangesSet.h" -#include -#include -#include - -namespace llvm { - -template -class CRSBuilderBase { -public: - - typedef ConstantRangesSet::RangeT RangeTy; - - struct RangeEx : public RangeTy { - typedef ConstantRangesSet::RangeT RangeTy; - typedef typename RangeTy::ConstantIntTy ConstantIntTy; - RangeEx() : Weight(1) {} - RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {} - RangeEx(ConstantIntTy *C) : RangeTy(C), Weight(1) {} - RangeEx(ConstantIntTy *L, ConstantIntTy *H) : RangeTy(L, H), Weight(1) {} - RangeEx(ConstantIntTy *L, ConstantIntTy *H, unsigned W) : - RangeTy(L, H), Weight(W) {} - unsigned Weight; - }; - - typedef std::pair Cluster; - -protected: - - typedef std::vector CaseItems; - typedef typename CaseItems::iterator CaseItemIt; - typedef typename CaseItems::const_iterator CaseItemConstIt; - - struct ClustersCmp { - bool operator()(const Cluster &C1, const Cluster &C2) { - return C1.first < C2.first; - } - }; - - CaseItems Items; - bool Sorted; - - bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { - return LItem->first.High->getValue().uge(RItem->first.Low->getValue()); - } - - bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { - if (LItem->second != RItem->second) { - assert(!isIntersected(LItem, RItem) && - "Intersected items with different successors!"); - return false; - } - APInt RLow = RItem->first.Low->getValue(); - if (RLow != APInt::getNullValue(RLow.getBitWidth())) - --RLow; - return LItem->first.High->getValue().uge(RLow); - } - - void sort() { - if (!Sorted) { - std::sort(Items.begin(), Items.end(), ClustersCmp()); - Sorted = true; - } - } - -public: - - typedef typename CRSConstantTypes::ConstantIntTy ConstantIntTy; - typedef typename CRSConstantTypes::ConstantRangesSetTy ConstantRangesSetTy; - - // Don't public CaseItems itself. Don't allow edit the Items directly. - // Just present the user way to iterate over the internal collection - // sharing iterator, begin() and end(). Editing should be controlled by - // factory. - typedef CaseItemIt RangeIterator; - - CRSBuilderBase() { - Items.reserve(32); - Sorted = false; - } - - bool verify() { - if (Items.empty()) - return true; - sort(); - for (CaseItemIt i = Items.begin(), j = i+1, e = Items.end(); - j != e; i = j++) { - if (isIntersected(j, i) && j->second != i->second) - return false; - } - return true; - } - - void optimize() { - if (Items.size() < 2) - return; - sort(); - CaseItems OldItems = Items; - Items.clear(); - ConstantIntTy *Low = OldItems.begin()->first.Low; - ConstantIntTy *High = OldItems.begin()->first.High; - unsigned Weight = 1; - SuccessorClass *Successor = OldItems.begin()->second; - for (CaseItemIt i = OldItems.begin(), j = i+1, e = OldItems.end(); - j != e; i = j++) { - if (isJoinable(i, j)) { - ConstantIntTy *CurHigh = j->first.High; - ++Weight; - if (CurHigh->getValue().ugt(High->getValue())) - High = CurHigh; - } else { - RangeEx R(Low, High, Weight); - add(R, Successor); - Low = j->first.Low; - High = j->first.High; - Weight = 1; - Successor = j->second; - } - } - RangeEx R(Low, High, Weight); - add(R, Successor); - // We recollected the Items, but we kept it sorted. - Sorted = true; - } - - /// Adds a constant value. - void add(ConstantIntTy *C, SuccessorClass *S = 0) { - RangeTy R(C); - add(R, S); - } - - /// Adds a range. - void add(ConstantIntTy *Low, ConstantIntTy *High, SuccessorClass *S = 0) { - RangeTy R(Low, High); - add(R, S); - } - void add(RangeTy &R, SuccessorClass *S = 0) { - RangeEx REx = R; - add(REx, S); - } - void add(RangeEx &R, SuccessorClass *S = 0) { - Items.push_back(std::make_pair(R, S)); - Sorted = false; - } - - /// Adds all ranges and values from given ranges set to the current - /// CRSBuilder object. - void add(ConstantRangesSetTy &CRS, SuccessorClass *S = 0) { - for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { - RangeTy R = CRS.getItem(i); - add(R, S); - } - } - - /// Removes items from set. - void removeItem(RangeIterator i) { Items.erase(i); } - - /// Returns true if there is no ranges and values inside. - bool empty() const { return Items.empty(); } - - RangeIterator begin() { return Items.begin(); } - RangeIterator end() { return Items.end(); } -}; - -template -class CRSBuilderT : public CRSBuilderBase { - - typedef typename CRSBuilderBase::RangeTy RangeTy; - typedef typename CRSBuilderBase::RangeIterator - RangeIterator; - - typedef std::list RangesCollection; - typedef typename RangesCollection::iterator RangesCollectionIt; - - typedef std::map CRSMap; - typedef typename CRSMap::iterator CRSMapIt; - - ConstantRangesSet getCase(RangesCollection& Src) { - std::vector Elts; - Elts.reserve(Src.size()); - for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) { - const RangeTy &R = *i; - std::vector r; - if (R.Low != R.High) { - r.reserve(2); - r.push_back(R.Low); - r.push_back(R.High); - } else { - r.reserve(1); - r.push_back(R.Low); - } - 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 ConstantRangesSet(Array); - } - -public: - - typedef std::pair Case; - typedef std::list Cases; - - /// Builds the finalized case objects. - void getCases(Cases& TheCases) { - CRSMap TheCRSMap; - 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))); - } - - /// Builds the finalized case objects ignoring successor values, as though - /// all ranges belongs to the same successor. - ConstantRangesSet getCase() { - RangesCollection Ranges; - for (RangeIterator i = this->begin(); i != this->end(); ++i) - Ranges.push_back(i->first); - return getCase(Ranges); - } -}; - -class BasicBlock; -typedef CRSBuilderT CRSBuilder; -typedef CRSBuilderBase CRSBuilderConst; - -} - -#endif /* CRSBUILDER_H_ */ diff --git a/include/llvm/ConstantRangesSet.h b/include/llvm/ConstantRangesSet.h deleted file mode 100644 index 2d3ee8bafaf..00000000000 --- a/include/llvm/ConstantRangesSet.h +++ /dev/null @@ -1,272 +0,0 @@ -//===-- llvm/ConstantRangesSet.h - The constant set of ranges ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// @file -/// This file contains class that implements constant set of ranges: -/// [,...,]. Mainly, this set is used by SwitchInst and -/// represents case value that may contain multiple ranges for a single -/// successor. -/// -// -//===----------------------------------------------------------------------===// - -#ifndef CONSTANTRANGESSET_H_ -#define CONSTANTRANGESSET_H_ - -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" - -namespace llvm { - -class ConstantRangesSet; - -template struct CRSConstantTypes { - typedef ConstantInt ConstantIntTy; - typedef ConstantRangesSet ConstantRangesSetTy; -}; - -template <> -struct CRSConstantTypes { - typedef const ConstantInt ConstantIntTy; - typedef const ConstantRangesSet ConstantRangesSetTy; -}; - -//===----------------------------------------------------------------------===// -/// 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 ConstantRangesSet { - Constant *Array; -public: - - // implicit - ConstantRangesSet(Constant *V) : Array(V) {} - - operator Constant*() { return Array; } - operator const Constant*() const { return Array; } - Constant *operator->() { return Array; } - const Constant *operator->() const { return Array; } - - template - struct RangeT { - - typedef typename CRSConstantTypes::ConstantIntTy ConstantIntTy; - typedef std::pair SubRes; - - ConstantIntTy *Low; - ConstantIntTy *High; - - RangeT() : Low(0), High(0) {} - RangeT(const RangeT &RHS) : Low(RHS.Low), High(RHS.High) {} - RangeT(ConstantIntTy *C) : Low(C), High(C) {} - RangeT(ConstantIntTy *L, ConstantIntTy *H) : Low(L), High(H) {} - - bool operator<(const RangeT &RHS) const { - assert(Low && High && "Case range is not initialized."); - assert(RHS.Low && RHS.High && "Right case range is not initialized."); - const APInt &LowInt = Low->getValue(); - const APInt &HighInt = High->getValue(); - const APInt &RHSLowInt = RHS.Low->getValue(); - const APInt &RHSHighInt = RHS.High->getValue(); - if (LowInt.getBitWidth() == RHSLowInt.getBitWidth()) { - if (LowInt.eq(RHSLowInt)) { - if (HighInt.ult(RHSHighInt)) - return true; - return false; - } - if (LowInt.ult(RHSLowInt)) - return true; - return false; - } else - return LowInt.getBitWidth() < RHSLowInt.getBitWidth(); - } - - bool operator==(const RangeT &RHS) const { - assert(Low && High && "Case range is not initialized."); - assert(RHS.Low && RHS.High && "Right case range is not initialized."); - if (Low->getValue().getBitWidth() != RHS.Low->getValue().getBitWidth()) - return false; - return Low->getValue() == RHS.Low->getValue() && - High->getValue() == RHS.High->getValue(); - } - - bool operator!=(const RangeT &RHS) const { - return !operator ==(RHS); - } - - static bool LessBySize(const RangeT &LHS, const RangeT &RHS) { - assert(LHS.Low->getBitWidth() == RHS.Low->getBitWidth() && - "This type of comparison requires equal bit width for LHS and RHS"); - APInt LSize = LHS.High->getValue() - LHS.Low->getValue(); - APInt RSize = RHS.High->getValue() - RHS.Low->getValue();; - return LSize.ult(RSize); - } - - bool isInRange(const APInt &IntVal) const { - assert(Low && High && "Case range is not initialized."); - if (IntVal.getBitWidth() != Low->getValue().getBitWidth()) - return false; - return IntVal.uge(Low->getValue()) && IntVal.ule(High->getValue()); - } - - bool isInRange(const ConstantIntTy *CI) const { - const APInt& IntVal = CI->getValue(); - return isInRange(IntVal); - } - - SubRes sub(const RangeT &RHS) const { - SubRes Res; - - // RHS is either more global and includes this range or - // if it doesn't intersected with this range. - if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { - - // If RHS more global (it is enough to check - // only one border in this case. - if (RHS.isInRange(Low)) - return std::make_pair(RangeT(Low, High), RangeT()); - - return Res; - } - - const APInt& LoInt = Low->getValue(); - const APInt& HiInt = High->getValue(); - APInt RHSLoInt = RHS.Low->getValue(); - APInt RHSHiInt = RHS.High->getValue(); - if (LoInt.ult(RHSLoInt)) { - Res.first.Low = Low; - Res.first.High = ConstantIntTy::get(RHS.Low->getContext(), --RHSLoInt); - } - if (HiInt.ugt(RHSHiInt)) { - Res.second.Low = ConstantIntTy::get(RHS.High->getContext(), ++RHSHiInt); - Res.second.High = High; - } - return Res; - } - }; - - typedef RangeT Range; - - /// Checks is the given constant satisfies this case. Returns - /// true if it equals to one of contained values or belongs to the one of - /// contained ranges. - bool isSatisfies(const ConstantInt *C) const { - const APInt &CheckingVal = C->getValue(); - 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)) - return true; - } - break; - default: - assert(0 && "Only pairs and single numbers are allowed here."); - break; - } - } - 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(cast(CV->getAggregateElement(0U)), - cast(CV->getAggregateElement(0U))); - case 2: - return Range(cast(CV->getAggregateElement(0U)), - cast(CV->getAggregateElement(1))); - 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(cast( - const_cast(CV->getAggregateElement(0U))), - cast( - const_cast(CV->getAggregateElement(0U)))); - case 2: - return Range(cast( - const_cast(CV->getAggregateElement(0U))), - cast( - const_cast(CV->getAggregateElement(1)))); - default: - assert(0 && "Only pairs and single numbers are allowed here."); - return Range(); - } - } - - /// Return number of items (ranges) stored in set. - unsigned getNumItems() const { - return cast(Array->getType())->getNumElements(); - } - - /// Returns set the size, that equals number of all values + sizes of all - /// ranges. - /// Ranges set is considered as flat numbers collection. - /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; - /// for range [<0>, <1>, <5>] the size will 3 - unsigned getSize() const { - APInt sz(getItem(0).Low->getBitWidth(), 0); - for (unsigned i = 0, e = getNumItems(); i != e; ++i) { - const APInt &S = getItem(i).High->getValue() - getItem(i).Low->getValue(); - sz += S; - } - return sz.getZExtValue(); - } - - /// Allows to access single value even if it belongs to some range. - /// Ranges set is considered as flat numbers collection. - /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] - /// For range [<1>, <4,8>] getSingleValue(3) returns 6. - APInt getSingleValue(unsigned idx) const { - APInt sz(getItem(0).Low->getBitWidth(), 0); - for (unsigned i = 0, e = getNumItems(); i != e; ++i) { - const APInt& S = getItem(i).High->getValue() - getItem(i).Low->getValue(); - APInt oldSz = sz; - sz += S; - if (oldSz.uge(i) && sz.ult(i)) { - APInt Res = getItem(i).Low->getValue(); - APInt Offset(oldSz.getBitWidth(), i); - Offset -= oldSz; - Res += Offset; - return Res; - } - } - assert(0 && "Index exceeds high border."); - return sz; - } -}; - -} - -#endif /* CONSTANTRANGESSET_H_ */ diff --git a/include/llvm/Support/CRSBuilder.h b/include/llvm/Support/CRSBuilder.h new file mode 100644 index 00000000000..1fd1683f713 --- /dev/null +++ b/include/llvm/Support/CRSBuilder.h @@ -0,0 +1,252 @@ +//===- CRSBuilder.h - ConstantRangesSet Builder -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// CRSBuilder allows to build and parse ConstantRangesSet objects. +/// There is such features like add/remove range, or combine +/// Two ConstantRangesSet object with neighboring ranges merging. +/// Set IsReadonly=true if you want to operate with "const ConstantInt" and +/// "const ConstantRangesSet" objects. +// +//===----------------------------------------------------------------------===// + +#ifndef CRSBUILDER_H_ +#define CRSBUILDER_H_ + +#include "llvm/Support/ConstantRangesSet.h" +#include +#include +#include + +namespace llvm { + +template +class CRSBuilderBase { +public: + + typedef ConstantRangesSet::RangeT RangeTy; + + struct RangeEx : public RangeTy { + typedef ConstantRangesSet::RangeT RangeTy; + typedef typename RangeTy::ConstantIntTy ConstantIntTy; + RangeEx() : Weight(1) {} + RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {} + RangeEx(ConstantIntTy *C) : RangeTy(C), Weight(1) {} + RangeEx(ConstantIntTy *L, ConstantIntTy *H) : RangeTy(L, H), Weight(1) {} + RangeEx(ConstantIntTy *L, ConstantIntTy *H, unsigned W) : + RangeTy(L, H), Weight(W) {} + unsigned Weight; + }; + + typedef std::pair Cluster; + +protected: + + typedef std::vector CaseItems; + typedef typename CaseItems::iterator CaseItemIt; + typedef typename CaseItems::const_iterator CaseItemConstIt; + + struct ClustersCmp { + bool operator()(const Cluster &C1, const Cluster &C2) { + return C1.first < C2.first; + } + }; + + CaseItems Items; + bool Sorted; + + bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { + return LItem->first.High->getValue().uge(RItem->first.Low->getValue()); + } + + bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { + if (LItem->second != RItem->second) { + assert(!isIntersected(LItem, RItem) && + "Intersected items with different successors!"); + return false; + } + APInt RLow = RItem->first.Low->getValue(); + if (RLow != APInt::getNullValue(RLow.getBitWidth())) + --RLow; + return LItem->first.High->getValue().uge(RLow); + } + + void sort() { + if (!Sorted) { + std::sort(Items.begin(), Items.end(), ClustersCmp()); + Sorted = true; + } + } + +public: + + typedef typename CRSConstantTypes::ConstantIntTy ConstantIntTy; + typedef typename CRSConstantTypes::ConstantRangesSetTy ConstantRangesSetTy; + + // Don't public CaseItems itself. Don't allow edit the Items directly. + // Just present the user way to iterate over the internal collection + // sharing iterator, begin() and end(). Editing should be controlled by + // factory. + typedef CaseItemIt RangeIterator; + + CRSBuilderBase() { + Items.reserve(32); + Sorted = false; + } + + bool verify() { + if (Items.empty()) + return true; + sort(); + for (CaseItemIt i = Items.begin(), j = i+1, e = Items.end(); + j != e; i = j++) { + if (isIntersected(j, i) && j->second != i->second) + return false; + } + return true; + } + + void optimize() { + if (Items.size() < 2) + return; + sort(); + CaseItems OldItems = Items; + Items.clear(); + ConstantIntTy *Low = OldItems.begin()->first.Low; + ConstantIntTy *High = OldItems.begin()->first.High; + unsigned Weight = 1; + SuccessorClass *Successor = OldItems.begin()->second; + for (CaseItemIt i = OldItems.begin(), j = i+1, e = OldItems.end(); + j != e; i = j++) { + if (isJoinable(i, j)) { + ConstantIntTy *CurHigh = j->first.High; + ++Weight; + if (CurHigh->getValue().ugt(High->getValue())) + High = CurHigh; + } else { + RangeEx R(Low, High, Weight); + add(R, Successor); + Low = j->first.Low; + High = j->first.High; + Weight = 1; + Successor = j->second; + } + } + RangeEx R(Low, High, Weight); + add(R, Successor); + // We recollected the Items, but we kept it sorted. + Sorted = true; + } + + /// Adds a constant value. + void add(ConstantIntTy *C, SuccessorClass *S = 0) { + RangeTy R(C); + add(R, S); + } + + /// Adds a range. + void add(ConstantIntTy *Low, ConstantIntTy *High, SuccessorClass *S = 0) { + RangeTy R(Low, High); + add(R, S); + } + void add(RangeTy &R, SuccessorClass *S = 0) { + RangeEx REx = R; + add(REx, S); + } + void add(RangeEx &R, SuccessorClass *S = 0) { + Items.push_back(std::make_pair(R, S)); + Sorted = false; + } + + /// Adds all ranges and values from given ranges set to the current + /// CRSBuilder object. + void add(ConstantRangesSetTy &CRS, SuccessorClass *S = 0) { + for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { + RangeTy R = CRS.getItem(i); + add(R, S); + } + } + + /// Removes items from set. + void removeItem(RangeIterator i) { Items.erase(i); } + + /// Returns true if there is no ranges and values inside. + bool empty() const { return Items.empty(); } + + RangeIterator begin() { return Items.begin(); } + RangeIterator end() { return Items.end(); } +}; + +template +class CRSBuilderT : public CRSBuilderBase { + + typedef typename CRSBuilderBase::RangeTy RangeTy; + typedef typename CRSBuilderBase::RangeIterator + RangeIterator; + + typedef std::list RangesCollection; + typedef typename RangesCollection::iterator RangesCollectionIt; + + typedef std::map CRSMap; + typedef typename CRSMap::iterator CRSMapIt; + + ConstantRangesSet getCase(RangesCollection& Src) { + std::vector Elts; + Elts.reserve(Src.size()); + for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) { + const RangeTy &R = *i; + std::vector r; + if (R.Low != R.High) { + r.reserve(2); + r.push_back(R.Low); + r.push_back(R.High); + } else { + r.reserve(1); + r.push_back(R.Low); + } + 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 ConstantRangesSet(Array); + } + +public: + + typedef std::pair Case; + typedef std::list Cases; + + /// Builds the finalized case objects. + void getCases(Cases& TheCases) { + CRSMap TheCRSMap; + 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))); + } + + /// Builds the finalized case objects ignoring successor values, as though + /// all ranges belongs to the same successor. + ConstantRangesSet getCase() { + RangesCollection Ranges; + for (RangeIterator i = this->begin(); i != this->end(); ++i) + Ranges.push_back(i->first); + return getCase(Ranges); + } +}; + +class BasicBlock; +typedef CRSBuilderT CRSBuilder; +typedef CRSBuilderBase CRSBuilderConst; + +} + +#endif /* CRSBUILDER_H_ */ diff --git a/include/llvm/Support/ConstantRangesSet.h b/include/llvm/Support/ConstantRangesSet.h new file mode 100644 index 00000000000..2d3ee8bafaf --- /dev/null +++ b/include/llvm/Support/ConstantRangesSet.h @@ -0,0 +1,272 @@ +//===-- llvm/ConstantRangesSet.h - The constant set of ranges ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains class that implements constant set of ranges: +/// [,...,]. Mainly, this set is used by SwitchInst and +/// represents case value that may contain multiple ranges for a single +/// successor. +/// +// +//===----------------------------------------------------------------------===// + +#ifndef CONSTANTRANGESSET_H_ +#define CONSTANTRANGESSET_H_ + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" + +namespace llvm { + +class ConstantRangesSet; + +template struct CRSConstantTypes { + typedef ConstantInt ConstantIntTy; + typedef ConstantRangesSet ConstantRangesSetTy; +}; + +template <> +struct CRSConstantTypes { + typedef const ConstantInt ConstantIntTy; + typedef const ConstantRangesSet ConstantRangesSetTy; +}; + +//===----------------------------------------------------------------------===// +/// 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 ConstantRangesSet { + Constant *Array; +public: + + // implicit + ConstantRangesSet(Constant *V) : Array(V) {} + + operator Constant*() { return Array; } + operator const Constant*() const { return Array; } + Constant *operator->() { return Array; } + const Constant *operator->() const { return Array; } + + template + struct RangeT { + + typedef typename CRSConstantTypes::ConstantIntTy ConstantIntTy; + typedef std::pair SubRes; + + ConstantIntTy *Low; + ConstantIntTy *High; + + RangeT() : Low(0), High(0) {} + RangeT(const RangeT &RHS) : Low(RHS.Low), High(RHS.High) {} + RangeT(ConstantIntTy *C) : Low(C), High(C) {} + RangeT(ConstantIntTy *L, ConstantIntTy *H) : Low(L), High(H) {} + + bool operator<(const RangeT &RHS) const { + assert(Low && High && "Case range is not initialized."); + assert(RHS.Low && RHS.High && "Right case range is not initialized."); + const APInt &LowInt = Low->getValue(); + const APInt &HighInt = High->getValue(); + const APInt &RHSLowInt = RHS.Low->getValue(); + const APInt &RHSHighInt = RHS.High->getValue(); + if (LowInt.getBitWidth() == RHSLowInt.getBitWidth()) { + if (LowInt.eq(RHSLowInt)) { + if (HighInt.ult(RHSHighInt)) + return true; + return false; + } + if (LowInt.ult(RHSLowInt)) + return true; + return false; + } else + return LowInt.getBitWidth() < RHSLowInt.getBitWidth(); + } + + bool operator==(const RangeT &RHS) const { + assert(Low && High && "Case range is not initialized."); + assert(RHS.Low && RHS.High && "Right case range is not initialized."); + if (Low->getValue().getBitWidth() != RHS.Low->getValue().getBitWidth()) + return false; + return Low->getValue() == RHS.Low->getValue() && + High->getValue() == RHS.High->getValue(); + } + + bool operator!=(const RangeT &RHS) const { + return !operator ==(RHS); + } + + static bool LessBySize(const RangeT &LHS, const RangeT &RHS) { + assert(LHS.Low->getBitWidth() == RHS.Low->getBitWidth() && + "This type of comparison requires equal bit width for LHS and RHS"); + APInt LSize = LHS.High->getValue() - LHS.Low->getValue(); + APInt RSize = RHS.High->getValue() - RHS.Low->getValue();; + return LSize.ult(RSize); + } + + bool isInRange(const APInt &IntVal) const { + assert(Low && High && "Case range is not initialized."); + if (IntVal.getBitWidth() != Low->getValue().getBitWidth()) + return false; + return IntVal.uge(Low->getValue()) && IntVal.ule(High->getValue()); + } + + bool isInRange(const ConstantIntTy *CI) const { + const APInt& IntVal = CI->getValue(); + return isInRange(IntVal); + } + + SubRes sub(const RangeT &RHS) const { + SubRes Res; + + // RHS is either more global and includes this range or + // if it doesn't intersected with this range. + if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { + + // If RHS more global (it is enough to check + // only one border in this case. + if (RHS.isInRange(Low)) + return std::make_pair(RangeT(Low, High), RangeT()); + + return Res; + } + + const APInt& LoInt = Low->getValue(); + const APInt& HiInt = High->getValue(); + APInt RHSLoInt = RHS.Low->getValue(); + APInt RHSHiInt = RHS.High->getValue(); + if (LoInt.ult(RHSLoInt)) { + Res.first.Low = Low; + Res.first.High = ConstantIntTy::get(RHS.Low->getContext(), --RHSLoInt); + } + if (HiInt.ugt(RHSHiInt)) { + Res.second.Low = ConstantIntTy::get(RHS.High->getContext(), ++RHSHiInt); + Res.second.High = High; + } + return Res; + } + }; + + typedef RangeT Range; + + /// Checks is the given constant satisfies this case. Returns + /// true if it equals to one of contained values or belongs to the one of + /// contained ranges. + bool isSatisfies(const ConstantInt *C) const { + const APInt &CheckingVal = C->getValue(); + 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)) + return true; + } + break; + default: + assert(0 && "Only pairs and single numbers are allowed here."); + break; + } + } + 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(cast(CV->getAggregateElement(0U)), + cast(CV->getAggregateElement(0U))); + case 2: + return Range(cast(CV->getAggregateElement(0U)), + cast(CV->getAggregateElement(1))); + 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(cast( + const_cast(CV->getAggregateElement(0U))), + cast( + const_cast(CV->getAggregateElement(0U)))); + case 2: + return Range(cast( + const_cast(CV->getAggregateElement(0U))), + cast( + const_cast(CV->getAggregateElement(1)))); + default: + assert(0 && "Only pairs and single numbers are allowed here."); + return Range(); + } + } + + /// Return number of items (ranges) stored in set. + unsigned getNumItems() const { + return cast(Array->getType())->getNumElements(); + } + + /// Returns set the size, that equals number of all values + sizes of all + /// ranges. + /// Ranges set is considered as flat numbers collection. + /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; + /// for range [<0>, <1>, <5>] the size will 3 + unsigned getSize() const { + APInt sz(getItem(0).Low->getBitWidth(), 0); + for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + const APInt &S = getItem(i).High->getValue() - getItem(i).Low->getValue(); + sz += S; + } + return sz.getZExtValue(); + } + + /// Allows to access single value even if it belongs to some range. + /// Ranges set is considered as flat numbers collection. + /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] + /// For range [<1>, <4,8>] getSingleValue(3) returns 6. + APInt getSingleValue(unsigned idx) const { + APInt sz(getItem(0).Low->getBitWidth(), 0); + for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + const APInt& S = getItem(i).High->getValue() - getItem(i).Low->getValue(); + APInt oldSz = sz; + sz += S; + if (oldSz.uge(i) && sz.ult(i)) { + APInt Res = getItem(i).Low->getValue(); + APInt Offset(oldSz.getBitWidth(), i); + Offset -= oldSz; + Res += Offset; + return Res; + } + } + assert(0 && "Index exceeds high border."); + return sz; + } +}; + +} + +#endif /* CONSTANTRANGESSET_H_ */