1239310Sdim//===-- llvm/IntegersSubset.h - The subset of integers ----------*- C++ -*-===// 2239310Sdim// 3239310Sdim// The LLVM Compiler Infrastructure 4239310Sdim// 5239310Sdim// This file is distributed under the University of Illinois Open Source 6239310Sdim// License. See LICENSE.TXT for details. 7239310Sdim// 8239310Sdim//===----------------------------------------------------------------------===// 9239310Sdim// 10239310Sdim/// @file 11239310Sdim/// This file contains class that implements constant set of ranges: 12239310Sdim/// [<Low0,High0>,...,<LowN,HighN>]. Initially, this class was created for 13239310Sdim/// SwitchInst and was used for case value representation that may contain 14239310Sdim/// multiple ranges for a single successor. 15239310Sdim// 16239310Sdim//===----------------------------------------------------------------------===// 17239310Sdim 18249423Sdim#ifndef LLVM_SUPPORT_INTEGERSSUBSET_H 19249423Sdim#define LLVM_SUPPORT_INTEGERSSUBSET_H 20239310Sdim 21249423Sdim#include "llvm/IR/Constants.h" 22249423Sdim#include "llvm/IR/DerivedTypes.h" 23249423Sdim#include "llvm/IR/LLVMContext.h" 24239310Sdim#include <list> 25239310Sdim 26239310Sdimnamespace llvm { 27239310Sdim 28239310Sdim // The IntItem is a wrapper for APInt. 29239310Sdim // 1. It determines sign of integer, it allows to use 30239310Sdim // comparison operators >,<,>=,<=, and as result we got shorter and cleaner 31239310Sdim // constructions. 32239310Sdim // 2. It helps to implement PR1255 (case ranges) as a series of small patches. 33239310Sdim // 3. Currently we can interpret IntItem both as ConstantInt and as APInt. 34239310Sdim // It allows to provide SwitchInst methods that works with ConstantInt for 35239310Sdim // non-updated passes. And it allows to use APInt interface for new methods. 36239310Sdim // 4. IntItem can be easily replaced with APInt. 37239310Sdim 38239310Sdim // The set of macros that allows to propagate APInt operators to the IntItem. 39239310Sdim 40239310Sdim#define INT_ITEM_DEFINE_COMPARISON(op,func) \ 41239310Sdim bool operator op (const APInt& RHS) const { \ 42239310Sdim return getAPIntValue().func(RHS); \ 43239310Sdim } 44239310Sdim 45239310Sdim#define INT_ITEM_DEFINE_UNARY_OP(op) \ 46239310Sdim IntItem operator op () const { \ 47239310Sdim APInt res = op(getAPIntValue()); \ 48239310Sdim Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 49239310Sdim return IntItem(cast<ConstantInt>(NewVal)); \ 50239310Sdim } 51239310Sdim 52239310Sdim#define INT_ITEM_DEFINE_BINARY_OP(op) \ 53239310Sdim IntItem operator op (const APInt& RHS) const { \ 54239310Sdim APInt res = getAPIntValue() op RHS; \ 55239310Sdim Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 56239310Sdim return IntItem(cast<ConstantInt>(NewVal)); \ 57239310Sdim } 58239310Sdim 59239310Sdim#define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \ 60239310Sdim IntItem& operator op (const APInt& RHS) {\ 61239310Sdim APInt res = getAPIntValue();\ 62239310Sdim res op RHS; \ 63239310Sdim Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 64239310Sdim ConstantIntVal = cast<ConstantInt>(NewVal); \ 65239310Sdim return *this; \ 66239310Sdim } 67239310Sdim 68239310Sdim#define INT_ITEM_DEFINE_PREINCDEC(op) \ 69239310Sdim IntItem& operator op () { \ 70239310Sdim APInt res = getAPIntValue(); \ 71239310Sdim op(res); \ 72239310Sdim Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 73239310Sdim ConstantIntVal = cast<ConstantInt>(NewVal); \ 74239310Sdim return *this; \ 75239310Sdim } 76239310Sdim 77239310Sdim#define INT_ITEM_DEFINE_POSTINCDEC(op) \ 78239310Sdim IntItem& operator op (int) { \ 79239310Sdim APInt res = getAPIntValue();\ 80239310Sdim op(res); \ 81239310Sdim Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ 82239310Sdim OldConstantIntVal = ConstantIntVal; \ 83239310Sdim ConstantIntVal = cast<ConstantInt>(NewVal); \ 84239310Sdim return IntItem(OldConstantIntVal); \ 85239310Sdim } 86239310Sdim 87239310Sdim#define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \ 88239310Sdim RetTy operator op (IntTy RHS) const { \ 89239310Sdim return (*this) op APInt(getAPIntValue().getBitWidth(), RHS); \ 90239310Sdim } 91239310Sdim 92239310Sdimclass IntItem { 93239310Sdim ConstantInt *ConstantIntVal; 94239310Sdim const APInt* APIntVal; 95239310Sdim IntItem(const ConstantInt *V) : 96239310Sdim ConstantIntVal(const_cast<ConstantInt*>(V)), 97239310Sdim APIntVal(&ConstantIntVal->getValue()){} 98239310Sdim const APInt& getAPIntValue() const { 99239310Sdim return *APIntVal; 100239310Sdim } 101239310Sdimpublic: 102239310Sdim 103239310Sdim IntItem() {} 104239310Sdim 105239310Sdim operator const APInt&() const { 106239310Sdim return getAPIntValue(); 107239310Sdim } 108239310Sdim 109239310Sdim // Propagate APInt operators. 110239310Sdim // Note, that 111239310Sdim // /,/=,>>,>>= are not implemented in APInt. 112239310Sdim // <<= is implemented for unsigned RHS, but not implemented for APInt RHS. 113239310Sdim 114239310Sdim INT_ITEM_DEFINE_COMPARISON(<, ult) 115239310Sdim INT_ITEM_DEFINE_COMPARISON(>, ugt) 116239310Sdim INT_ITEM_DEFINE_COMPARISON(<=, ule) 117239310Sdim INT_ITEM_DEFINE_COMPARISON(>=, uge) 118239310Sdim 119239310Sdim INT_ITEM_DEFINE_COMPARISON(==, eq) 120239310Sdim INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t) 121239310Sdim 122239310Sdim INT_ITEM_DEFINE_COMPARISON(!=, ne) 123239310Sdim INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t) 124239310Sdim 125239310Sdim INT_ITEM_DEFINE_BINARY_OP(*) 126239310Sdim INT_ITEM_DEFINE_BINARY_OP(+) 127239310Sdim INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t) 128239310Sdim INT_ITEM_DEFINE_BINARY_OP(-) 129239310Sdim INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t) 130239310Sdim INT_ITEM_DEFINE_BINARY_OP(<<) 131239310Sdim INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned) 132239310Sdim INT_ITEM_DEFINE_BINARY_OP(&) 133239310Sdim INT_ITEM_DEFINE_BINARY_OP(^) 134239310Sdim INT_ITEM_DEFINE_BINARY_OP(|) 135239310Sdim 136239310Sdim INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=) 137239310Sdim INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=) 138239310Sdim INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=) 139239310Sdim INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=) 140239310Sdim INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=) 141239310Sdim INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=) 142239310Sdim 143239310Sdim // Special case for <<= 144239310Sdim IntItem& operator <<= (unsigned RHS) { 145239310Sdim APInt res = getAPIntValue(); 146239310Sdim res <<= RHS; 147239310Sdim Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); 148239310Sdim ConstantIntVal = cast<ConstantInt>(NewVal); 149239310Sdim return *this; 150239310Sdim } 151239310Sdim 152239310Sdim INT_ITEM_DEFINE_UNARY_OP(-) 153239310Sdim INT_ITEM_DEFINE_UNARY_OP(~) 154239310Sdim 155239310Sdim INT_ITEM_DEFINE_PREINCDEC(++) 156239310Sdim INT_ITEM_DEFINE_PREINCDEC(--) 157239310Sdim 158239310Sdim // The set of workarounds, since currently we use ConstantInt implemented 159239310Sdim // integer. 160239310Sdim 161239310Sdim static IntItem fromConstantInt(const ConstantInt *V) { 162239310Sdim return IntItem(V); 163239310Sdim } 164239310Sdim static IntItem fromType(Type* Ty, const APInt& V) { 165239310Sdim ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V)); 166239310Sdim return fromConstantInt(C); 167239310Sdim } 168239310Sdim static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) { 169239310Sdim ConstantInt *C = cast<ConstantInt>(ConstantInt::get( 170239310Sdim LikeThis.ConstantIntVal->getContext(), V)); 171239310Sdim return fromConstantInt(C); 172239310Sdim } 173239310Sdim ConstantInt *toConstantInt() const { 174239310Sdim return ConstantIntVal; 175239310Sdim } 176239310Sdim}; 177239310Sdim 178239310Sdimtemplate<class IntType> 179239310Sdimclass IntRange { 180239310Sdimprotected: 181239310Sdim IntType Low; 182239310Sdim IntType High; 183239310Sdim bool IsEmpty : 1; 184239310Sdim bool IsSingleNumber : 1; 185239310Sdim 186239310Sdimpublic: 187239310Sdim typedef IntRange<IntType> self; 188239310Sdim typedef std::pair<self, self> SubRes; 189239310Sdim 190239310Sdim IntRange() : IsEmpty(true) {} 191239310Sdim IntRange(const self &RHS) : 192239310Sdim Low(RHS.Low), High(RHS.High), 193239310Sdim IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} 194239310Sdim IntRange(const IntType &C) : 195239310Sdim Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} 196239310Sdim 197239310Sdim IntRange(const IntType &L, const IntType &H) : Low(L), High(H), 198239310Sdim IsEmpty(false), IsSingleNumber(Low == High) {} 199239310Sdim 200239310Sdim bool isEmpty() const { return IsEmpty; } 201239310Sdim bool isSingleNumber() const { return IsSingleNumber; } 202239310Sdim 203239310Sdim const IntType& getLow() const { 204239310Sdim assert(!IsEmpty && "Range is empty."); 205239310Sdim return Low; 206239310Sdim } 207239310Sdim const IntType& getHigh() const { 208239310Sdim assert(!IsEmpty && "Range is empty."); 209239310Sdim return High; 210239310Sdim } 211239310Sdim 212239310Sdim bool operator<(const self &RHS) const { 213239310Sdim assert(!IsEmpty && "Left range is empty."); 214239310Sdim assert(!RHS.IsEmpty && "Right range is empty."); 215239310Sdim if (Low == RHS.Low) { 216239310Sdim if (High > RHS.High) 217239310Sdim return true; 218239310Sdim return false; 219239310Sdim } 220239310Sdim if (Low < RHS.Low) 221239310Sdim return true; 222239310Sdim return false; 223239310Sdim } 224239310Sdim 225239310Sdim bool operator==(const self &RHS) const { 226239310Sdim assert(!IsEmpty && "Left range is empty."); 227239310Sdim assert(!RHS.IsEmpty && "Right range is empty."); 228239310Sdim return Low == RHS.Low && High == RHS.High; 229239310Sdim } 230239310Sdim 231239310Sdim bool operator!=(const self &RHS) const { 232239310Sdim return !operator ==(RHS); 233239310Sdim } 234239310Sdim 235239310Sdim static bool LessBySize(const self &LHS, const self &RHS) { 236239310Sdim return (LHS.High - LHS.Low) < (RHS.High - RHS.Low); 237239310Sdim } 238239310Sdim 239239310Sdim bool isInRange(const IntType &IntVal) const { 240239310Sdim assert(!IsEmpty && "Range is empty."); 241239310Sdim return IntVal >= Low && IntVal <= High; 242239310Sdim } 243239310Sdim 244239310Sdim SubRes sub(const self &RHS) const { 245239310Sdim SubRes Res; 246239310Sdim 247239310Sdim // RHS is either more global and includes this range or 248239310Sdim // if it doesn't intersected with this range. 249239310Sdim if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { 250239310Sdim 251239310Sdim // If RHS more global (it is enough to check 252239310Sdim // only one border in this case. 253239310Sdim if (RHS.isInRange(Low)) 254239310Sdim return std::make_pair(self(Low, High), self()); 255239310Sdim 256239310Sdim return Res; 257239310Sdim } 258239310Sdim 259239310Sdim if (Low < RHS.Low) { 260239310Sdim Res.first.Low = Low; 261239310Sdim IntType NewHigh = RHS.Low; 262239310Sdim --NewHigh; 263239310Sdim Res.first.High = NewHigh; 264239310Sdim } 265239310Sdim if (High > RHS.High) { 266239310Sdim IntType NewLow = RHS.High; 267239310Sdim ++NewLow; 268239310Sdim Res.second.Low = NewLow; 269239310Sdim Res.second.High = High; 270239310Sdim } 271239310Sdim return Res; 272239310Sdim } 273239310Sdim }; 274239310Sdim 275239310Sdim//===----------------------------------------------------------------------===// 276239310Sdim/// IntegersSubsetGeneric - class that implements the subset of integers. It 277239310Sdim/// consists from ranges and single numbers. 278239310Sdimtemplate <class IntTy> 279239310Sdimclass IntegersSubsetGeneric { 280239310Sdimpublic: 281239310Sdim // Use Chris Lattner idea, that was initially described here: 282239310Sdim // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html 283239310Sdim // In short, for more compact memory consumption we can store flat 284239310Sdim // numbers collection, and define range as pair of indices. 285239310Sdim // In that case we can safe some memory on 32 bit machines. 286239310Sdim typedef std::vector<IntTy> FlatCollectionTy; 287239310Sdim typedef std::pair<IntTy*, IntTy*> RangeLinkTy; 288239310Sdim typedef std::vector<RangeLinkTy> RangeLinksTy; 289239310Sdim typedef typename RangeLinksTy::const_iterator RangeLinksConstIt; 290239310Sdim 291239310Sdim typedef IntegersSubsetGeneric<IntTy> self; 292239310Sdim 293239310Sdimprotected: 294239310Sdim 295239310Sdim FlatCollectionTy FlatCollection; 296239310Sdim RangeLinksTy RangeLinks; 297239310Sdim 298239310Sdim bool IsSingleNumber; 299239310Sdim bool IsSingleNumbersOnly; 300239310Sdim 301239310Sdimpublic: 302239310Sdim 303239310Sdim template<class RangesCollectionTy> 304239310Sdim explicit IntegersSubsetGeneric(const RangesCollectionTy& Links) { 305239310Sdim assert(Links.size() && "Empty ranges are not allowed."); 306239310Sdim 307239310Sdim // In case of big set of single numbers consumes additional RAM space, 308239310Sdim // but allows to avoid additional reallocation. 309239310Sdim FlatCollection.reserve(Links.size() * 2); 310239310Sdim RangeLinks.reserve(Links.size()); 311239310Sdim IsSingleNumbersOnly = true; 312239310Sdim for (typename RangesCollectionTy::const_iterator i = Links.begin(), 313239310Sdim e = Links.end(); i != e; ++i) { 314239310Sdim RangeLinkTy RangeLink; 315239310Sdim FlatCollection.push_back(i->getLow()); 316239310Sdim RangeLink.first = &FlatCollection.back(); 317239310Sdim if (i->getLow() != i->getHigh()) { 318239310Sdim FlatCollection.push_back(i->getHigh()); 319239310Sdim IsSingleNumbersOnly = false; 320239310Sdim } 321239310Sdim RangeLink.second = &FlatCollection.back(); 322239310Sdim RangeLinks.push_back(RangeLink); 323239310Sdim } 324239310Sdim IsSingleNumber = IsSingleNumbersOnly && RangeLinks.size() == 1; 325239310Sdim } 326239310Sdim 327239310Sdim IntegersSubsetGeneric(const self& RHS) { 328239310Sdim *this = RHS; 329239310Sdim } 330239310Sdim 331239310Sdim self& operator=(const self& RHS) { 332239310Sdim FlatCollection.clear(); 333239310Sdim RangeLinks.clear(); 334239310Sdim FlatCollection.reserve(RHS.RangeLinks.size() * 2); 335239310Sdim RangeLinks.reserve(RHS.RangeLinks.size()); 336239310Sdim for (RangeLinksConstIt i = RHS.RangeLinks.begin(), e = RHS.RangeLinks.end(); 337239310Sdim i != e; ++i) { 338239310Sdim RangeLinkTy RangeLink; 339239310Sdim FlatCollection.push_back(*(i->first)); 340239310Sdim RangeLink.first = &FlatCollection.back(); 341239310Sdim if (i->first != i->second) 342239310Sdim FlatCollection.push_back(*(i->second)); 343239310Sdim RangeLink.second = &FlatCollection.back(); 344239310Sdim RangeLinks.push_back(RangeLink); 345239310Sdim } 346239310Sdim IsSingleNumber = RHS.IsSingleNumber; 347239310Sdim IsSingleNumbersOnly = RHS.IsSingleNumbersOnly; 348239310Sdim return *this; 349239310Sdim } 350239310Sdim 351239310Sdim typedef IntRange<IntTy> Range; 352239310Sdim 353239310Sdim /// Checks is the given constant satisfies this case. Returns 354239310Sdim /// true if it equals to one of contained values or belongs to the one of 355239310Sdim /// contained ranges. 356239310Sdim bool isSatisfies(const IntTy &CheckingVal) const { 357239310Sdim if (IsSingleNumber) 358239310Sdim return FlatCollection.front() == CheckingVal; 359239310Sdim if (IsSingleNumbersOnly) 360239310Sdim return std::find(FlatCollection.begin(), 361239310Sdim FlatCollection.end(), 362239310Sdim CheckingVal) != FlatCollection.end(); 363239310Sdim 364239310Sdim for (unsigned i = 0, e = getNumItems(); i < e; ++i) { 365239310Sdim if (RangeLinks[i].first == RangeLinks[i].second) { 366239310Sdim if (*RangeLinks[i].first == CheckingVal) 367239310Sdim return true; 368239310Sdim } else if (*RangeLinks[i].first <= CheckingVal && 369239310Sdim *RangeLinks[i].second >= CheckingVal) 370239310Sdim return true; 371239310Sdim } 372239310Sdim return false; 373239310Sdim } 374239310Sdim 375239310Sdim /// Returns set's item with given index. 376239310Sdim Range getItem(unsigned idx) const { 377239310Sdim const RangeLinkTy &Link = RangeLinks[idx]; 378239310Sdim if (Link.first != Link.second) 379239310Sdim return Range(*Link.first, *Link.second); 380239310Sdim else 381239310Sdim return Range(*Link.first); 382239310Sdim } 383239310Sdim 384239310Sdim /// Return number of items (ranges) stored in set. 385239310Sdim unsigned getNumItems() const { 386239310Sdim return RangeLinks.size(); 387239310Sdim } 388239310Sdim 389239310Sdim /// Returns true if whole subset contains single element. 390239310Sdim bool isSingleNumber() const { 391239310Sdim return IsSingleNumber; 392239310Sdim } 393239310Sdim 394239310Sdim /// Returns true if whole subset contains only single numbers, no ranges. 395239310Sdim bool isSingleNumbersOnly() const { 396239310Sdim return IsSingleNumbersOnly; 397239310Sdim } 398239310Sdim 399239310Sdim /// Does the same like getItem(idx).isSingleNumber(), but 400239310Sdim /// works faster, since we avoid creation of temporary range object. 401239310Sdim bool isSingleNumber(unsigned idx) const { 402239310Sdim return RangeLinks[idx].first == RangeLinks[idx].second; 403239310Sdim } 404239310Sdim 405239310Sdim /// Returns set the size, that equals number of all values + sizes of all 406239310Sdim /// ranges. 407239310Sdim /// Ranges set is considered as flat numbers collection. 408239310Sdim /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; 409239310Sdim /// for range [<0>, <1>, <5>] the size will 3 410239310Sdim unsigned getSize() const { 411239310Sdim APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); 412239310Sdim for (unsigned i = 0, e = getNumItems(); i != e; ++i) { 413243830Sdim const APInt Low = getItem(i).getLow(); 414243830Sdim const APInt High = getItem(i).getHigh(); 415239310Sdim APInt S = High - Low + 1; 416239310Sdim sz += S; 417239310Sdim } 418239310Sdim return sz.getZExtValue(); 419239310Sdim } 420239310Sdim 421239310Sdim /// Allows to access single value even if it belongs to some range. 422239310Sdim /// Ranges set is considered as flat numbers collection. 423239310Sdim /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] 424239310Sdim /// For range [<1>, <4,8>] getSingleValue(3) returns 6. 425239310Sdim APInt getSingleValue(unsigned idx) const { 426239310Sdim APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); 427239310Sdim for (unsigned i = 0, e = getNumItems(); i != e; ++i) { 428243830Sdim const APInt Low = getItem(i).getLow(); 429243830Sdim const APInt High = getItem(i).getHigh(); 430239310Sdim APInt S = High - Low + 1; 431239310Sdim APInt oldSz = sz; 432239310Sdim sz += S; 433239310Sdim if (sz.ugt(idx)) { 434239310Sdim APInt Res = Low; 435239310Sdim APInt Offset(oldSz.getBitWidth(), idx); 436239310Sdim Offset -= oldSz; 437239310Sdim Res += Offset; 438239310Sdim return Res; 439239310Sdim } 440239310Sdim } 441239310Sdim assert(0 && "Index exceeds high border."); 442239310Sdim return sz; 443239310Sdim } 444239310Sdim 445239310Sdim /// Does the same as getSingleValue, but works only if subset contains 446239310Sdim /// single numbers only. 447239310Sdim const IntTy& getSingleNumber(unsigned idx) const { 448239310Sdim assert(IsSingleNumbersOnly && "This method works properly if subset " 449239310Sdim "contains single numbers only."); 450239310Sdim return FlatCollection[idx]; 451239310Sdim } 452239310Sdim}; 453239310Sdim 454239310Sdim//===----------------------------------------------------------------------===// 455239310Sdim/// IntegersSubset - currently is extension of IntegersSubsetGeneric 456239310Sdim/// that also supports conversion to/from Constant* object. 457239310Sdimclass IntegersSubset : public IntegersSubsetGeneric<IntItem> { 458239310Sdim 459239310Sdim typedef IntegersSubsetGeneric<IntItem> ParentTy; 460239310Sdim 461239310Sdim Constant *Holder; 462239310Sdim 463239310Sdim static unsigned getNumItemsFromConstant(Constant *C) { 464239310Sdim return cast<ArrayType>(C->getType())->getNumElements(); 465239310Sdim } 466239310Sdim 467239310Sdim static Range getItemFromConstant(Constant *C, unsigned idx) { 468239310Sdim const Constant *CV = C->getAggregateElement(idx); 469239310Sdim 470239310Sdim unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements(); 471239310Sdim switch (NumEls) { 472239310Sdim case 1: 473239310Sdim return Range(IntItem::fromConstantInt( 474239310Sdim cast<ConstantInt>(CV->getAggregateElement(0U))), 475239310Sdim IntItem::fromConstantInt(cast<ConstantInt>( 476239310Sdim cast<ConstantInt>(CV->getAggregateElement(0U))))); 477239310Sdim case 2: 478239310Sdim return Range(IntItem::fromConstantInt( 479239310Sdim cast<ConstantInt>(CV->getAggregateElement(0U))), 480239310Sdim IntItem::fromConstantInt( 481239310Sdim cast<ConstantInt>(CV->getAggregateElement(1)))); 482239310Sdim default: 483239310Sdim assert(0 && "Only pairs and single numbers are allowed here."); 484239310Sdim return Range(); 485239310Sdim } 486239310Sdim } 487239310Sdim 488239310Sdim std::vector<Range> rangesFromConstant(Constant *C) { 489239310Sdim unsigned NumItems = getNumItemsFromConstant(C); 490239310Sdim std::vector<Range> r; 491239310Sdim r.reserve(NumItems); 492239310Sdim for (unsigned i = 0, e = NumItems; i != e; ++i) 493239310Sdim r.push_back(getItemFromConstant(C, i)); 494239310Sdim return r; 495239310Sdim } 496239310Sdim 497239310Sdimpublic: 498239310Sdim 499239310Sdim explicit IntegersSubset(Constant *C) : ParentTy(rangesFromConstant(C)), 500239310Sdim Holder(C) {} 501239310Sdim 502239310Sdim IntegersSubset(const IntegersSubset& RHS) : 503239310Sdim ParentTy(*(const ParentTy *)&RHS), // FIXME: tweak for msvc. 504239310Sdim Holder(RHS.Holder) {} 505239310Sdim 506239310Sdim template<class RangesCollectionTy> 507239310Sdim explicit IntegersSubset(const RangesCollectionTy& Src) : ParentTy(Src) { 508239310Sdim std::vector<Constant*> Elts; 509239310Sdim Elts.reserve(Src.size()); 510239310Sdim for (typename RangesCollectionTy::const_iterator i = Src.begin(), 511239310Sdim e = Src.end(); i != e; ++i) { 512239310Sdim const Range &R = *i; 513239310Sdim std::vector<Constant*> r; 514239310Sdim if (R.isSingleNumber()) { 515239310Sdim r.reserve(2); 516239310Sdim // FIXME: Since currently we have ConstantInt based numbers 517239310Sdim // use hack-conversion of IntItem to ConstantInt 518239310Sdim r.push_back(R.getLow().toConstantInt()); 519239310Sdim r.push_back(R.getHigh().toConstantInt()); 520239310Sdim } else { 521239310Sdim r.reserve(1); 522239310Sdim r.push_back(R.getLow().toConstantInt()); 523239310Sdim } 524239310Sdim Constant *CV = ConstantVector::get(r); 525239310Sdim Elts.push_back(CV); 526239310Sdim } 527239310Sdim ArrayType *ArrTy = 528239310Sdim ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); 529239310Sdim Holder = ConstantArray::get(ArrTy, Elts); 530239310Sdim } 531239310Sdim 532239310Sdim operator Constant*() { return Holder; } 533239310Sdim operator const Constant*() const { return Holder; } 534239310Sdim Constant *operator->() { return Holder; } 535239310Sdim const Constant *operator->() const { return Holder; } 536239310Sdim}; 537239310Sdim 538239310Sdim} 539239310Sdim 540249423Sdim#endif /* CLLVM_SUPPORT_INTEGERSSUBSET_H */ 541