LLVM API Documentation

IntegersSubset.h
Go to the documentation of this file.
00001 //===-- llvm/IntegersSubset.h - The subset of integers ----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 /// @file
00011 /// This file contains class that implements constant set of ranges:
00012 /// [<Low0,High0>,...,<LowN,HighN>]. Initially, this class was created for
00013 /// SwitchInst and was used for case value representation that may contain
00014 /// multiple ranges for a single successor.
00015 //
00016 //===----------------------------------------------------------------------===//
00017 
00018 #ifndef LLVM_SUPPORT_INTEGERSSUBSET_H
00019 #define LLVM_SUPPORT_INTEGERSSUBSET_H
00020 
00021 #include "llvm/IR/Constants.h"
00022 #include "llvm/IR/DerivedTypes.h"
00023 #include "llvm/IR/LLVMContext.h"
00024 #include <list>
00025 
00026 namespace llvm {
00027 
00028   // The IntItem is a wrapper for APInt.
00029   // 1. It determines sign of integer, it allows to use
00030   //    comparison operators >,<,>=,<=, and as result we got shorter and cleaner
00031   //    constructions.
00032   // 2. It helps to implement PR1255 (case ranges) as a series of small patches.
00033   // 3. Currently we can interpret IntItem both as ConstantInt and as APInt.
00034   //    It allows to provide SwitchInst methods that works with ConstantInt for
00035   //    non-updated passes. And it allows to use APInt interface for new methods.
00036   // 4. IntItem can be easily replaced with APInt.
00037 
00038   // The set of macros that allows to propagate APInt operators to the IntItem.
00039 
00040 #define INT_ITEM_DEFINE_COMPARISON(op,func) \
00041   bool operator op (const APInt& RHS) const { \
00042     return getAPIntValue().func(RHS); \
00043   }
00044 
00045 #define INT_ITEM_DEFINE_UNARY_OP(op) \
00046   IntItem operator op () const { \
00047     APInt res = op(getAPIntValue()); \
00048     Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
00049     return IntItem(cast<ConstantInt>(NewVal)); \
00050   }
00051 
00052 #define INT_ITEM_DEFINE_BINARY_OP(op) \
00053   IntItem operator op (const APInt& RHS) const { \
00054     APInt res = getAPIntValue() op RHS; \
00055     Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
00056     return IntItem(cast<ConstantInt>(NewVal)); \
00057   }
00058 
00059 #define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \
00060   IntItem& operator op (const APInt& RHS) {\
00061     APInt res = getAPIntValue();\
00062     res op RHS; \
00063     Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
00064     ConstantIntVal = cast<ConstantInt>(NewVal); \
00065     return *this; \
00066   }
00067 
00068 #define INT_ITEM_DEFINE_PREINCDEC(op) \
00069     IntItem& operator op () { \
00070       APInt res = getAPIntValue(); \
00071       op(res); \
00072       Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
00073       ConstantIntVal = cast<ConstantInt>(NewVal); \
00074       return *this; \
00075     }
00076 
00077 #define INT_ITEM_DEFINE_POSTINCDEC(op) \
00078     IntItem& operator op (int) { \
00079       APInt res = getAPIntValue();\
00080       op(res); \
00081       Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \
00082       OldConstantIntVal = ConstantIntVal; \
00083       ConstantIntVal = cast<ConstantInt>(NewVal); \
00084       return IntItem(OldConstantIntVal); \
00085     }
00086 
00087 #define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \
00088   RetTy operator op (IntTy RHS) const { \
00089     return (*this) op APInt(getAPIntValue().getBitWidth(), RHS); \
00090   }
00091 
00092 class IntItem {
00093   ConstantInt *ConstantIntVal;
00094   const APInt* APIntVal;
00095   IntItem(const ConstantInt *V) :
00096     ConstantIntVal(const_cast<ConstantInt*>(V)),
00097     APIntVal(&ConstantIntVal->getValue()){}
00098   const APInt& getAPIntValue() const {
00099     return *APIntVal;
00100   }
00101 public:
00102 
00103   IntItem() {}
00104 
00105   operator const APInt&() const {
00106     return getAPIntValue();
00107   }
00108 
00109   // Propagate APInt operators.
00110   // Note, that
00111   // /,/=,>>,>>= are not implemented in APInt.
00112   // <<= is implemented for unsigned RHS, but not implemented for APInt RHS.
00113 
00114   INT_ITEM_DEFINE_COMPARISON(<, ult)
00115   INT_ITEM_DEFINE_COMPARISON(>, ugt)
00116   INT_ITEM_DEFINE_COMPARISON(<=, ule)
00117   INT_ITEM_DEFINE_COMPARISON(>=, uge)
00118 
00119   INT_ITEM_DEFINE_COMPARISON(==, eq)
00120   INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t)
00121 
00122   INT_ITEM_DEFINE_COMPARISON(!=, ne)
00123   INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t)
00124 
00125   INT_ITEM_DEFINE_BINARY_OP(*)
00126   INT_ITEM_DEFINE_BINARY_OP(+)
00127   INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t)
00128   INT_ITEM_DEFINE_BINARY_OP(-)
00129   INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t)
00130   INT_ITEM_DEFINE_BINARY_OP(<<)
00131   INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned)
00132   INT_ITEM_DEFINE_BINARY_OP(&)
00133   INT_ITEM_DEFINE_BINARY_OP(^)
00134   INT_ITEM_DEFINE_BINARY_OP(|)
00135 
00136   INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=)
00137   INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=)
00138   INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=)
00139   INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=)
00140   INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=)
00141   INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=)
00142 
00143   // Special case for <<=
00144   IntItem& operator <<= (unsigned RHS) {
00145     APInt res = getAPIntValue();
00146     res <<= RHS;
00147     Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res);
00148     ConstantIntVal = cast<ConstantInt>(NewVal);
00149     return *this;
00150   }
00151 
00152   INT_ITEM_DEFINE_UNARY_OP(-)
00153   INT_ITEM_DEFINE_UNARY_OP(~)
00154 
00155   INT_ITEM_DEFINE_PREINCDEC(++)
00156   INT_ITEM_DEFINE_PREINCDEC(--)
00157 
00158   // The set of workarounds, since currently we use ConstantInt implemented
00159   // integer.
00160 
00161   static IntItem fromConstantInt(const ConstantInt *V) {
00162     return IntItem(V);
00163   }
00164   static IntItem fromType(Type* Ty, const APInt& V) {
00165     ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V));
00166     return fromConstantInt(C);
00167   }
00168   static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) {
00169     ConstantInt *C = cast<ConstantInt>(ConstantInt::get(
00170         LikeThis.ConstantIntVal->getContext(), V));
00171     return fromConstantInt(C);
00172   }
00173   ConstantInt *toConstantInt() const {
00174     return ConstantIntVal;
00175   }
00176 };
00177 
00178 template<class IntType>
00179 class IntRange {
00180 protected:
00181     IntType Low;
00182     IntType High;
00183     bool IsEmpty : 1;
00184     bool IsSingleNumber : 1;
00185 
00186 public:
00187     typedef IntRange<IntType> self;
00188     typedef std::pair<self, self> SubRes;
00189 
00190     IntRange() : IsEmpty(true) {}
00191     IntRange(const self &RHS) :
00192       Low(RHS.Low), High(RHS.High),
00193       IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {}
00194     IntRange(const IntType &C) :
00195       Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {}
00196 
00197     IntRange(const IntType &L, const IntType &H) : Low(L), High(H),
00198       IsEmpty(false), IsSingleNumber(Low == High) {}
00199 
00200     bool isEmpty() const { return IsEmpty; }
00201     bool isSingleNumber() const { return IsSingleNumber; }
00202 
00203     const IntType& getLow() const {
00204       assert(!IsEmpty && "Range is empty.");
00205       return Low;
00206     }
00207     const IntType& getHigh() const {
00208       assert(!IsEmpty && "Range is empty.");
00209       return High;
00210     }
00211 
00212     bool operator<(const self &RHS) const {
00213       assert(!IsEmpty && "Left range is empty.");
00214       assert(!RHS.IsEmpty && "Right range is empty.");
00215       if (Low == RHS.Low) {
00216         if (High > RHS.High)
00217           return true;
00218         return false;
00219       }
00220       if (Low < RHS.Low)
00221         return true;
00222       return false;
00223     }
00224 
00225     bool operator==(const self &RHS) const {
00226       assert(!IsEmpty && "Left range is empty.");
00227       assert(!RHS.IsEmpty && "Right range is empty.");
00228       return Low == RHS.Low && High == RHS.High;
00229     }
00230 
00231     bool operator!=(const self &RHS) const {
00232       return !operator ==(RHS);
00233     }
00234 
00235     static bool LessBySize(const self &LHS, const self &RHS) {
00236       return (LHS.High - LHS.Low) < (RHS.High - RHS.Low);
00237     }
00238 
00239     bool isInRange(const IntType &IntVal) const {
00240       assert(!IsEmpty && "Range is empty.");
00241       return IntVal >= Low && IntVal <= High;
00242     }
00243 
00244     SubRes sub(const self &RHS) const {
00245       SubRes Res;
00246 
00247       // RHS is either more global and includes this range or
00248       // if it doesn't intersected with this range.
00249       if (!isInRange(RHS.Low) && !isInRange(RHS.High)) {
00250 
00251         // If RHS more global (it is enough to check
00252         // only one border in this case.
00253         if (RHS.isInRange(Low))
00254           return std::make_pair(self(Low, High), self());
00255 
00256         return Res;
00257       }
00258 
00259       if (Low < RHS.Low) {
00260         Res.first.Low = Low;
00261         IntType NewHigh = RHS.Low;
00262         --NewHigh;
00263         Res.first.High = NewHigh;
00264       }
00265       if (High > RHS.High) {
00266         IntType NewLow = RHS.High;
00267         ++NewLow;
00268         Res.second.Low = NewLow;
00269         Res.second.High = High;
00270       }
00271       return Res;
00272     }
00273   };
00274 
00275 //===----------------------------------------------------------------------===//
00276 /// IntegersSubsetGeneric - class that implements the subset of integers. It
00277 /// consists from ranges and single numbers.
00278 template <class IntTy>
00279 class IntegersSubsetGeneric {
00280 public:
00281   // Use Chris Lattner idea, that was initially described here:
00282   // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html
00283   // In short, for more compact memory consumption we can store flat
00284   // numbers collection, and define range as pair of indices.
00285   // In that case we can safe some memory on 32 bit machines.
00286   typedef std::vector<IntTy> FlatCollectionTy;
00287   typedef std::pair<IntTy*, IntTy*> RangeLinkTy;
00288   typedef std::vector<RangeLinkTy> RangeLinksTy;
00289   typedef typename RangeLinksTy::const_iterator RangeLinksConstIt;
00290 
00291   typedef IntegersSubsetGeneric<IntTy> self;
00292 
00293 protected:
00294 
00295   FlatCollectionTy FlatCollection;
00296   RangeLinksTy RangeLinks;
00297 
00298   bool IsSingleNumber;
00299   bool IsSingleNumbersOnly;
00300 
00301 public:
00302 
00303   template<class RangesCollectionTy>
00304   explicit IntegersSubsetGeneric(const RangesCollectionTy& Links) {
00305     assert(Links.size() && "Empty ranges are not allowed.");
00306 
00307     // In case of big set of single numbers consumes additional RAM space,
00308     // but allows to avoid additional reallocation.
00309     FlatCollection.reserve(Links.size() * 2);
00310     RangeLinks.reserve(Links.size());
00311     IsSingleNumbersOnly = true;
00312     for (typename RangesCollectionTy::const_iterator i = Links.begin(),
00313          e = Links.end(); i != e; ++i) {
00314       RangeLinkTy RangeLink;
00315       FlatCollection.push_back(i->getLow());
00316       RangeLink.first = &FlatCollection.back();
00317       if (i->getLow() != i->getHigh()) {
00318         FlatCollection.push_back(i->getHigh());
00319         IsSingleNumbersOnly = false;
00320       }
00321       RangeLink.second = &FlatCollection.back();
00322       RangeLinks.push_back(RangeLink);
00323     }
00324     IsSingleNumber = IsSingleNumbersOnly && RangeLinks.size() == 1;
00325   }
00326 
00327   IntegersSubsetGeneric(const self& RHS) {
00328     *this = RHS;
00329   }
00330 
00331   self& operator=(const self& RHS) {
00332     FlatCollection.clear();
00333     RangeLinks.clear();
00334     FlatCollection.reserve(RHS.RangeLinks.size() * 2);
00335     RangeLinks.reserve(RHS.RangeLinks.size());
00336     for (RangeLinksConstIt i = RHS.RangeLinks.begin(), e = RHS.RangeLinks.end();
00337          i != e; ++i) {
00338       RangeLinkTy RangeLink;
00339       FlatCollection.push_back(*(i->first));
00340       RangeLink.first = &FlatCollection.back();
00341       if (i->first != i->second)
00342         FlatCollection.push_back(*(i->second));
00343       RangeLink.second = &FlatCollection.back();
00344       RangeLinks.push_back(RangeLink);
00345     }
00346     IsSingleNumber = RHS.IsSingleNumber;
00347     IsSingleNumbersOnly = RHS.IsSingleNumbersOnly;
00348     return *this;
00349   }
00350 
00351   typedef IntRange<IntTy> Range;
00352 
00353   /// Checks is the given constant satisfies this case. Returns
00354   /// true if it equals to one of contained values or belongs to the one of
00355   /// contained ranges.
00356   bool isSatisfies(const IntTy &CheckingVal) const {
00357     if (IsSingleNumber)
00358       return FlatCollection.front() == CheckingVal;
00359     if (IsSingleNumbersOnly)
00360       return std::find(FlatCollection.begin(),
00361                        FlatCollection.end(),
00362                        CheckingVal) != FlatCollection.end();
00363 
00364     for (unsigned i = 0, e = getNumItems(); i < e; ++i) {
00365       if (RangeLinks[i].first == RangeLinks[i].second) {
00366         if (*RangeLinks[i].first == CheckingVal)
00367           return true;
00368       } else if (*RangeLinks[i].first <= CheckingVal &&
00369                  *RangeLinks[i].second >= CheckingVal)
00370         return true;
00371     }
00372     return false;
00373   }
00374 
00375   /// Returns set's item with given index.
00376   Range getItem(unsigned idx) const {
00377     const RangeLinkTy &Link = RangeLinks[idx];
00378     if (Link.first != Link.second)
00379       return Range(*Link.first, *Link.second);
00380     else
00381       return Range(*Link.first);
00382   }
00383 
00384   /// Return number of items (ranges) stored in set.
00385   unsigned getNumItems() const {
00386     return RangeLinks.size();
00387   }
00388 
00389   /// Returns true if whole subset contains single element.
00390   bool isSingleNumber() const {
00391     return IsSingleNumber;
00392   }
00393 
00394   /// Returns true if whole subset contains only single numbers, no ranges.
00395   bool isSingleNumbersOnly() const {
00396     return IsSingleNumbersOnly;
00397   }
00398 
00399   /// Does the same like getItem(idx).isSingleNumber(), but
00400   /// works faster, since we avoid creation of temporary range object.
00401   bool isSingleNumber(unsigned idx) const {
00402     return RangeLinks[idx].first == RangeLinks[idx].second;
00403   }
00404 
00405   /// Returns set the size, that equals number of all values + sizes of all
00406   /// ranges.
00407   /// Ranges set is considered as flat numbers collection.
00408   /// E.g.: for range [<0>, <1>, <4,8>] the size will 7;
00409   ///       for range [<0>, <1>, <5>] the size will 3
00410   unsigned getSize() const {
00411     APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0);
00412     for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
00413       const APInt Low = getItem(i).getLow();
00414       const APInt High = getItem(i).getHigh();
00415       APInt S = High - Low + 1;
00416       sz += S;
00417     }
00418     return sz.getZExtValue();
00419   }
00420 
00421   /// Allows to access single value even if it belongs to some range.
00422   /// Ranges set is considered as flat numbers collection.
00423   /// [<1>, <4,8>] is considered as [1,4,5,6,7,8]
00424   /// For range [<1>, <4,8>] getSingleValue(3) returns 6.
00425   APInt getSingleValue(unsigned idx) const {
00426     APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0);
00427     for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
00428       const APInt Low = getItem(i).getLow();
00429       const APInt High = getItem(i).getHigh();
00430       APInt S = High - Low + 1;
00431       APInt oldSz = sz;
00432       sz += S;
00433       if (sz.ugt(idx)) {
00434         APInt Res = Low;
00435         APInt Offset(oldSz.getBitWidth(), idx);
00436         Offset -= oldSz;
00437         Res += Offset;
00438         return Res;
00439       }
00440     }
00441     assert(0 && "Index exceeds high border.");
00442     return sz;
00443   }
00444 
00445   /// Does the same as getSingleValue, but works only if subset contains
00446   /// single numbers only.
00447   const IntTy& getSingleNumber(unsigned idx) const {
00448     assert(IsSingleNumbersOnly && "This method works properly if subset "
00449                                   "contains single numbers only.");
00450     return FlatCollection[idx];
00451   }
00452 };
00453 
00454 //===----------------------------------------------------------------------===//
00455 /// IntegersSubset - currently is extension of IntegersSubsetGeneric
00456 /// that also supports conversion to/from Constant* object.
00457 class IntegersSubset : public IntegersSubsetGeneric<IntItem> {
00458 
00459   typedef IntegersSubsetGeneric<IntItem> ParentTy;
00460 
00461   Constant *Holder;
00462 
00463   static unsigned getNumItemsFromConstant(Constant *C) {
00464     return cast<ArrayType>(C->getType())->getNumElements();
00465   }
00466 
00467   static Range getItemFromConstant(Constant *C, unsigned idx) {
00468     const Constant *CV = C->getAggregateElement(idx);
00469 
00470     unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements();
00471     switch (NumEls) {
00472     case 1:
00473       return Range(IntItem::fromConstantInt(
00474                      cast<ConstantInt>(CV->getAggregateElement(0U))),
00475                    IntItem::fromConstantInt(cast<ConstantInt>(
00476                      cast<ConstantInt>(CV->getAggregateElement(0U)))));
00477     case 2:
00478       return Range(IntItem::fromConstantInt(
00479                      cast<ConstantInt>(CV->getAggregateElement(0U))),
00480                    IntItem::fromConstantInt(
00481                    cast<ConstantInt>(CV->getAggregateElement(1))));
00482     default:
00483       assert(0 && "Only pairs and single numbers are allowed here.");
00484       return Range();
00485     }
00486   }
00487 
00488   std::vector<Range> rangesFromConstant(Constant *C) {
00489     unsigned NumItems = getNumItemsFromConstant(C);
00490     std::vector<Range> r;
00491     r.reserve(NumItems);
00492     for (unsigned i = 0, e = NumItems; i != e; ++i)
00493       r.push_back(getItemFromConstant(C, i));
00494     return r;
00495   }
00496 
00497 public:
00498 
00499   explicit IntegersSubset(Constant *C) : ParentTy(rangesFromConstant(C)),
00500                           Holder(C) {}
00501 
00502   IntegersSubset(const IntegersSubset& RHS) :
00503     ParentTy(*(const ParentTy *)&RHS), // FIXME: tweak for msvc.
00504     Holder(RHS.Holder) {}
00505 
00506   template<class RangesCollectionTy>
00507   explicit IntegersSubset(const RangesCollectionTy& Src) : ParentTy(Src) {
00508     std::vector<Constant*> Elts;
00509     Elts.reserve(Src.size());
00510     for (typename RangesCollectionTy::const_iterator i = Src.begin(),
00511          e = Src.end(); i != e; ++i) {
00512       const Range &R = *i;
00513       std::vector<Constant*> r;
00514       if (R.isSingleNumber()) {
00515         r.reserve(2);
00516         // FIXME: Since currently we have ConstantInt based numbers
00517         // use hack-conversion of IntItem to ConstantInt
00518         r.push_back(R.getLow().toConstantInt());
00519         r.push_back(R.getHigh().toConstantInt());
00520       } else {
00521         r.reserve(1);
00522         r.push_back(R.getLow().toConstantInt());
00523       }
00524       Constant *CV = ConstantVector::get(r);
00525       Elts.push_back(CV);
00526     }
00527     ArrayType *ArrTy =
00528         ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size());
00529     Holder = ConstantArray::get(ArrTy, Elts);
00530   }
00531 
00532   operator Constant*() { return Holder; }
00533   operator const Constant*() const { return Holder; }
00534   Constant *operator->() { return Holder; }
00535   const Constant *operator->() const { return Holder; }
00536 };
00537 
00538 }
00539 
00540 #endif /* CLLVM_SUPPORT_INTEGERSSUBSET_H */