LLVM API Documentation
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 */