1 //===-- llvm/IntegersSubset.h - The subset of integers ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// @file 11 /// This file contains class that implements constant set of ranges: 12 /// [<Low0,High0>,...,<LowN,HighN>]. Initially, this class was created for 13 /// SwitchInst and was used for case value representation that may contain 14 /// multiple ranges for a single successor. 15 // 16 //===----------------------------------------------------------------------===// 17 18 #ifndef LLVM_SUPPORT_INTEGERSSUBSET_H 19 #define LLVM_SUPPORT_INTEGERSSUBSET_H 20 21 #include "llvm/IR/Constants.h" 22 #include "llvm/IR/DerivedTypes.h" 23 #include "llvm/IR/LLVMContext.h" 24 #include <list> 25 26 namespace llvm { 27 28 // The IntItem is a wrapper for APInt. 29 // 1. It determines sign of integer, it allows to use 30 // comparison operators >,<,>=,<=, and as result we got shorter and cleaner 31 // constructions. 32 // 2. It helps to implement PR1255 (case ranges) as a series of small patches. 33 // 3. Currently we can interpret IntItem both as ConstantInt and as APInt. 34 // It allows to provide SwitchInst methods that works with ConstantInt for 35 // non-updated passes. And it allows to use APInt interface for new methods. 36 // 4. IntItem can be easily replaced with APInt. 37 38 // The set of macros that allows to propagate APInt operators to the IntItem. 39 40 #define INT_ITEM_DEFINE_COMPARISON(op,func) \ 41 bool operator op (const APInt& RHS) const { \ 42 return getAPIntValue().func(RHS); \ 43 } 44 45 #define INT_ITEM_DEFINE_UNARY_OP(op) \ 46 IntItem operator op () const { \ 47 APInt res = op(getAPIntValue()); \ 48 Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 49 return IntItem(cast<ConstantInt>(NewVal)); \ 50 } 51 52 #define INT_ITEM_DEFINE_BINARY_OP(op) \ 53 IntItem operator op (const APInt& RHS) const { \ 54 APInt res = getAPIntValue() op RHS; \ 55 Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 56 return IntItem(cast<ConstantInt>(NewVal)); \ 57 } 58 59 #define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \ 60 IntItem& operator op (const APInt& RHS) {\ 61 APInt res = getAPIntValue();\ 62 res op RHS; \ 63 Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 64 ConstantIntVal = cast<ConstantInt>(NewVal); \ 65 return *this; \ 66 } 67 68 #define INT_ITEM_DEFINE_PREINCDEC(op) \ 69 IntItem& operator op () { \ 70 APInt res = getAPIntValue(); \ 71 op(res); \ 72 Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 73 ConstantIntVal = cast<ConstantInt>(NewVal); \ 74 return *this; \ 75 } 76 77 #define INT_ITEM_DEFINE_POSTINCDEC(op) \ 78 IntItem& operator op (int) { \ 79 APInt res = getAPIntValue();\ 80 op(res); \ 81 Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 82 OldConstantIntVal = ConstantIntVal; \ 83 ConstantIntVal = cast<ConstantInt>(NewVal); \ 84 return IntItem(OldConstantIntVal); \ 85 } 86 87 #define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \ 88 RetTy operator op (IntTy RHS) const { \ 89 return (*this) op APInt(getAPIntValue().getBitWidth(), RHS); \ 90 } 91 92 class IntItem { 93 ConstantInt *ConstantIntVal; 94 const APInt* APIntVal; IntItem(const ConstantInt * V)95 IntItem(const ConstantInt *V) : 96 ConstantIntVal(const_cast<ConstantInt*>(V)), 97 APIntVal(&ConstantIntVal->getValue()){} getAPIntValue()98 const APInt& getAPIntValue() const { 99 return *APIntVal; 100 } 101 public: 102 IntItem()103 IntItem() {} 104 105 operator const APInt&() const { 106 return getAPIntValue(); 107 } 108 109 // Propagate APInt operators. 110 // Note, that 111 // /,/=,>>,>>= are not implemented in APInt. 112 // <<= is implemented for unsigned RHS, but not implemented for APInt RHS. 113 114 INT_ITEM_DEFINE_COMPARISON(<, ult) 115 INT_ITEM_DEFINE_COMPARISON(>, ugt) 116 INT_ITEM_DEFINE_COMPARISON(<=, ule) 117 INT_ITEM_DEFINE_COMPARISON(>=, uge) 118 119 INT_ITEM_DEFINE_COMPARISON(==, eq) 120 INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t) 121 122 INT_ITEM_DEFINE_COMPARISON(!=, ne) 123 INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t) 124 125 INT_ITEM_DEFINE_BINARY_OP(*) 126 INT_ITEM_DEFINE_BINARY_OP(+) 127 INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t) 128 INT_ITEM_DEFINE_BINARY_OP(-) 129 INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t) 130 INT_ITEM_DEFINE_BINARY_OP(<<) 131 INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned) 132 INT_ITEM_DEFINE_BINARY_OP(&) 133 INT_ITEM_DEFINE_BINARY_OP(^) 134 INT_ITEM_DEFINE_BINARY_OP(|) 135 136 INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=) 137 INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=) 138 INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=) 139 INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=) 140 INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=) 141 INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=) 142 143 // Special case for <<= 144 IntItem& operator <<= (unsigned RHS) { 145 APInt res = getAPIntValue(); 146 res <<= RHS; 147 Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); 148 ConstantIntVal = cast<ConstantInt>(NewVal); 149 return *this; 150 } 151 152 INT_ITEM_DEFINE_UNARY_OP(-) 153 INT_ITEM_DEFINE_UNARY_OP(~) 154 155 INT_ITEM_DEFINE_PREINCDEC(++) 156 INT_ITEM_DEFINE_PREINCDEC(--) 157 158 // The set of workarounds, since currently we use ConstantInt implemented 159 // integer. 160 fromConstantInt(const ConstantInt * V)161 static IntItem fromConstantInt(const ConstantInt *V) { 162 return IntItem(V); 163 } fromType(Type * Ty,const APInt & V)164 static IntItem fromType(Type* Ty, const APInt& V) { 165 ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V)); 166 return fromConstantInt(C); 167 } withImplLikeThis(const IntItem & LikeThis,const APInt & V)168 static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) { 169 ConstantInt *C = cast<ConstantInt>(ConstantInt::get( 170 LikeThis.ConstantIntVal->getContext(), V)); 171 return fromConstantInt(C); 172 } toConstantInt()173 ConstantInt *toConstantInt() const { 174 return ConstantIntVal; 175 } 176 }; 177 178 template<class IntType> 179 class IntRange { 180 protected: 181 IntType Low; 182 IntType High; 183 bool IsEmpty : 1; 184 bool IsSingleNumber : 1; 185 186 public: 187 typedef IntRange<IntType> self; 188 typedef std::pair<self, self> SubRes; 189 IntRange()190 IntRange() : IsEmpty(true) {} IntRange(const self & RHS)191 IntRange(const self &RHS) : 192 Low(RHS.Low), High(RHS.High), 193 IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} IntRange(const IntType & C)194 IntRange(const IntType &C) : 195 Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} 196 IntRange(const IntType & L,const IntType & H)197 IntRange(const IntType &L, const IntType &H) : Low(L), High(H), 198 IsEmpty(false), IsSingleNumber(Low == High) {} 199 isEmpty()200 bool isEmpty() const { return IsEmpty; } isSingleNumber()201 bool isSingleNumber() const { return IsSingleNumber; } 202 getLow()203 const IntType& getLow() const { 204 assert(!IsEmpty && "Range is empty."); 205 return Low; 206 } getHigh()207 const IntType& getHigh() const { 208 assert(!IsEmpty && "Range is empty."); 209 return High; 210 } 211 212 bool operator<(const self &RHS) const { 213 assert(!IsEmpty && "Left range is empty."); 214 assert(!RHS.IsEmpty && "Right range is empty."); 215 if (Low == RHS.Low) { 216 if (High > RHS.High) 217 return true; 218 return false; 219 } 220 if (Low < RHS.Low) 221 return true; 222 return false; 223 } 224 225 bool operator==(const self &RHS) const { 226 assert(!IsEmpty && "Left range is empty."); 227 assert(!RHS.IsEmpty && "Right range is empty."); 228 return Low == RHS.Low && High == RHS.High; 229 } 230 231 bool operator!=(const self &RHS) const { 232 return !operator ==(RHS); 233 } 234 LessBySize(const self & LHS,const self & RHS)235 static bool LessBySize(const self &LHS, const self &RHS) { 236 return (LHS.High - LHS.Low) < (RHS.High - RHS.Low); 237 } 238 isInRange(const IntType & IntVal)239 bool isInRange(const IntType &IntVal) const { 240 assert(!IsEmpty && "Range is empty."); 241 return IntVal >= Low && IntVal <= High; 242 } 243 sub(const self & RHS)244 SubRes sub(const self &RHS) const { 245 SubRes Res; 246 247 // RHS is either more global and includes this range or 248 // if it doesn't intersected with this range. 249 if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { 250 251 // If RHS more global (it is enough to check 252 // only one border in this case. 253 if (RHS.isInRange(Low)) 254 return std::make_pair(self(Low, High), self()); 255 256 return Res; 257 } 258 259 if (Low < RHS.Low) { 260 Res.first.Low = Low; 261 IntType NewHigh = RHS.Low; 262 --NewHigh; 263 Res.first.High = NewHigh; 264 } 265 if (High > RHS.High) { 266 IntType NewLow = RHS.High; 267 ++NewLow; 268 Res.second.Low = NewLow; 269 Res.second.High = High; 270 } 271 return Res; 272 } 273 }; 274 275 //===----------------------------------------------------------------------===// 276 /// IntegersSubsetGeneric - class that implements the subset of integers. It 277 /// consists from ranges and single numbers. 278 template <class IntTy> 279 class IntegersSubsetGeneric { 280 public: 281 // Use Chris Lattner idea, that was initially described here: 282 // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html 283 // In short, for more compact memory consumption we can store flat 284 // numbers collection, and define range as pair of indices. 285 // In that case we can safe some memory on 32 bit machines. 286 typedef std::vector<IntTy> FlatCollectionTy; 287 typedef std::pair<IntTy*, IntTy*> RangeLinkTy; 288 typedef std::vector<RangeLinkTy> RangeLinksTy; 289 typedef typename RangeLinksTy::const_iterator RangeLinksConstIt; 290 291 typedef IntegersSubsetGeneric<IntTy> self; 292 293 protected: 294 295 FlatCollectionTy FlatCollection; 296 RangeLinksTy RangeLinks; 297 298 bool IsSingleNumber; 299 bool IsSingleNumbersOnly; 300 301 public: 302 303 template<class RangesCollectionTy> IntegersSubsetGeneric(const RangesCollectionTy & Links)304 explicit IntegersSubsetGeneric(const RangesCollectionTy& Links) { 305 assert(Links.size() && "Empty ranges are not allowed."); 306 307 // In case of big set of single numbers consumes additional RAM space, 308 // but allows to avoid additional reallocation. 309 FlatCollection.reserve(Links.size() * 2); 310 RangeLinks.reserve(Links.size()); 311 IsSingleNumbersOnly = true; 312 for (typename RangesCollectionTy::const_iterator i = Links.begin(), 313 e = Links.end(); i != e; ++i) { 314 RangeLinkTy RangeLink; 315 FlatCollection.push_back(i->getLow()); 316 RangeLink.first = &FlatCollection.back(); 317 if (i->getLow() != i->getHigh()) { 318 FlatCollection.push_back(i->getHigh()); 319 IsSingleNumbersOnly = false; 320 } 321 RangeLink.second = &FlatCollection.back(); 322 RangeLinks.push_back(RangeLink); 323 } 324 IsSingleNumber = IsSingleNumbersOnly && RangeLinks.size() == 1; 325 } 326 IntegersSubsetGeneric(const self & RHS)327 IntegersSubsetGeneric(const self& RHS) { 328 *this = RHS; 329 } 330 331 self& operator=(const self& RHS) { 332 FlatCollection.clear(); 333 RangeLinks.clear(); 334 FlatCollection.reserve(RHS.RangeLinks.size() * 2); 335 RangeLinks.reserve(RHS.RangeLinks.size()); 336 for (RangeLinksConstIt i = RHS.RangeLinks.begin(), e = RHS.RangeLinks.end(); 337 i != e; ++i) { 338 RangeLinkTy RangeLink; 339 FlatCollection.push_back(*(i->first)); 340 RangeLink.first = &FlatCollection.back(); 341 if (i->first != i->second) 342 FlatCollection.push_back(*(i->second)); 343 RangeLink.second = &FlatCollection.back(); 344 RangeLinks.push_back(RangeLink); 345 } 346 IsSingleNumber = RHS.IsSingleNumber; 347 IsSingleNumbersOnly = RHS.IsSingleNumbersOnly; 348 return *this; 349 } 350 351 typedef IntRange<IntTy> Range; 352 353 /// Checks is the given constant satisfies this case. Returns 354 /// true if it equals to one of contained values or belongs to the one of 355 /// contained ranges. isSatisfies(const IntTy & CheckingVal)356 bool isSatisfies(const IntTy &CheckingVal) const { 357 if (IsSingleNumber) 358 return FlatCollection.front() == CheckingVal; 359 if (IsSingleNumbersOnly) 360 return std::find(FlatCollection.begin(), 361 FlatCollection.end(), 362 CheckingVal) != FlatCollection.end(); 363 364 for (size_t i = 0, e = getNumItems(); i < e; ++i) { 365 if (RangeLinks[i].first == RangeLinks[i].second) { 366 if (*RangeLinks[i].first == CheckingVal) 367 return true; 368 } else if (*RangeLinks[i].first <= CheckingVal && 369 *RangeLinks[i].second >= CheckingVal) 370 return true; 371 } 372 return false; 373 } 374 375 /// Returns set's item with given index. getItem(unsigned idx)376 Range getItem(unsigned idx) const { 377 const RangeLinkTy &Link = RangeLinks[idx]; 378 if (Link.first != Link.second) 379 return Range(*Link.first, *Link.second); 380 else 381 return Range(*Link.first); 382 } 383 384 /// Return number of items (ranges) stored in set. getNumItems()385 size_t getNumItems() const { 386 return RangeLinks.size(); 387 } 388 389 /// Returns true if whole subset contains single element. isSingleNumber()390 bool isSingleNumber() const { 391 return IsSingleNumber; 392 } 393 394 /// Returns true if whole subset contains only single numbers, no ranges. isSingleNumbersOnly()395 bool isSingleNumbersOnly() const { 396 return IsSingleNumbersOnly; 397 } 398 399 /// Does the same like getItem(idx).isSingleNumber(), but 400 /// works faster, since we avoid creation of temporary range object. isSingleNumber(unsigned idx)401 bool isSingleNumber(unsigned idx) const { 402 return RangeLinks[idx].first == RangeLinks[idx].second; 403 } 404 405 /// Returns set the size, that equals number of all values + sizes of all 406 /// ranges. 407 /// Ranges set is considered as flat numbers collection. 408 /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; 409 /// for range [<0>, <1>, <5>] the size will 3 getSize()410 unsigned getSize() const { 411 APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); 412 for (size_t i = 0, e = getNumItems(); i != e; ++i) { 413 const APInt Low = getItem(i).getLow(); 414 const APInt High = getItem(i).getHigh(); 415 APInt S = High - Low + 1; 416 sz += S; 417 } 418 return sz.getZExtValue(); 419 } 420 421 /// Allows to access single value even if it belongs to some range. 422 /// Ranges set is considered as flat numbers collection. 423 /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] 424 /// For range [<1>, <4,8>] getSingleValue(3) returns 6. getSingleValue(unsigned idx)425 APInt getSingleValue(unsigned idx) const { 426 APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); 427 for (unsigned i = 0, e = getNumItems(); i != e; ++i) { 428 const APInt Low = getItem(i).getLow(); 429 const APInt High = getItem(i).getHigh(); 430 APInt S = High - Low + 1; 431 APInt oldSz = sz; 432 sz += S; 433 if (sz.ugt(idx)) { 434 APInt Res = Low; 435 APInt Offset(oldSz.getBitWidth(), idx); 436 Offset -= oldSz; 437 Res += Offset; 438 return Res; 439 } 440 } 441 assert(0 && "Index exceeds high border."); 442 return sz; 443 } 444 445 /// Does the same as getSingleValue, but works only if subset contains 446 /// single numbers only. getSingleNumber(unsigned idx)447 const IntTy& getSingleNumber(unsigned idx) const { 448 assert(IsSingleNumbersOnly && "This method works properly if subset " 449 "contains single numbers only."); 450 return FlatCollection[idx]; 451 } 452 }; 453 454 //===----------------------------------------------------------------------===// 455 /// IntegersSubset - currently is extension of IntegersSubsetGeneric 456 /// that also supports conversion to/from Constant* object. 457 class IntegersSubset : public IntegersSubsetGeneric<IntItem> { 458 459 typedef IntegersSubsetGeneric<IntItem> ParentTy; 460 461 Constant *Holder; 462 getNumItemsFromConstant(Constant * C)463 static unsigned getNumItemsFromConstant(Constant *C) { 464 return cast<ArrayType>(C->getType())->getNumElements(); 465 } 466 getItemFromConstant(Constant * C,unsigned idx)467 static Range getItemFromConstant(Constant *C, unsigned idx) { 468 const Constant *CV = C->getAggregateElement(idx); 469 470 unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements(); 471 switch (NumEls) { 472 case 1: 473 return Range(IntItem::fromConstantInt( 474 cast<ConstantInt>(CV->getAggregateElement(0U))), 475 IntItem::fromConstantInt(cast<ConstantInt>( 476 cast<ConstantInt>(CV->getAggregateElement(0U))))); 477 case 2: 478 return Range(IntItem::fromConstantInt( 479 cast<ConstantInt>(CV->getAggregateElement(0U))), 480 IntItem::fromConstantInt( 481 cast<ConstantInt>(CV->getAggregateElement(1)))); 482 default: 483 assert(0 && "Only pairs and single numbers are allowed here."); 484 return Range(); 485 } 486 } 487 rangesFromConstant(Constant * C)488 std::vector<Range> rangesFromConstant(Constant *C) { 489 unsigned NumItems = getNumItemsFromConstant(C); 490 std::vector<Range> r; 491 r.reserve(NumItems); 492 for (unsigned i = 0, e = NumItems; i != e; ++i) 493 r.push_back(getItemFromConstant(C, i)); 494 return r; 495 } 496 497 public: 498 IntegersSubset(Constant * C)499 explicit IntegersSubset(Constant *C) : ParentTy(rangesFromConstant(C)), 500 Holder(C) {} 501 IntegersSubset(const IntegersSubset & RHS)502 IntegersSubset(const IntegersSubset& RHS) : 503 ParentTy(*(const ParentTy *)&RHS), // FIXME: tweak for msvc. 504 Holder(RHS.Holder) {} 505 506 template<class RangesCollectionTy> IntegersSubset(const RangesCollectionTy & Src)507 explicit IntegersSubset(const RangesCollectionTy& Src) : ParentTy(Src) { 508 std::vector<Constant*> Elts; 509 Elts.reserve(Src.size()); 510 for (typename RangesCollectionTy::const_iterator i = Src.begin(), 511 e = Src.end(); i != e; ++i) { 512 const Range &R = *i; 513 std::vector<Constant*> r; 514 if (R.isSingleNumber()) { 515 r.reserve(2); 516 // FIXME: Since currently we have ConstantInt based numbers 517 // use hack-conversion of IntItem to ConstantInt 518 r.push_back(R.getLow().toConstantInt()); 519 r.push_back(R.getHigh().toConstantInt()); 520 } else { 521 r.reserve(1); 522 r.push_back(R.getLow().toConstantInt()); 523 } 524 Constant *CV = ConstantVector::get(r); 525 Elts.push_back(CV); 526 } 527 ArrayType *ArrTy = 528 ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); 529 Holder = ConstantArray::get(ArrTy, Elts); 530 } 531 532 operator Constant*() { return Holder; } 533 operator const Constant*() const { return Holder; } 534 Constant *operator->() { return Holder; } 535 const Constant *operator->() const { return Holder; } 536 }; 537 538 } 539 540 #endif /* CLLVM_SUPPORT_INTEGERSSUBSET_H */ 541