llvm.org GIT mirror llvm / 0aa32d5
ConstantRangesSet renamed to IntegersSubset. CRSBuilder renamed to IntegersSubsetMapping. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157612 91177308-0d34-0410-b5e6-96231b3b80d8 Stepan Dyatkovskiy 8 years ago
15 changed file(s) with 660 addition(s) and 674 deletion(s). Raw diff Collapse all Expand all
1919 #include "llvm/DerivedTypes.h"
2020 #include "llvm/Attributes.h"
2121 #include "llvm/CallingConv.h"
22 #include "llvm/Support/ConstantRangesSet.h"
23 #include "llvm/Support/CRSBuilder.h"
22 #include "llvm/Support/IntegersSubset.h"
23 #include "llvm/Support/IntegersSubsetMapping.h"
2424 #include "llvm/ADT/ArrayRef.h"
2525 #include "llvm/ADT/SmallVector.h"
2626 #include "llvm/Support/ErrorHandling.h"
25882588 /// Note:
25892589 /// This action invalidates case_end(). Old case_end() iterator will
25902590 /// point to the added case.
2591 void addCase(ConstantRangesSet& OnVal, BasicBlock *Dest);
2591 void addCase(IntegersSubset& OnVal, BasicBlock *Dest);
25922592
25932593 /// removeCase - This method removes the specified case and its successor
25942594 /// from the switch instruction. Note that this operation may reorder the
26532653 /// @Deprecated
26542654 ConstantIntTy *getCaseValue() {
26552655 assert(Index < SI->getNumCases() && "Index out the number of cases.");
2656 ConstantRangesSet CRS =
2656 IntegersSubset CaseRanges =
26572657 reinterpret_cast(SI->getOperand(2 + Index*2));
2658 ConstantRangesSet::Range R = CRS.getItem(0);
2658 IntegersSubset::Range R = CaseRanges.getItem(0);
26592659
26602660 // FIXME: Currently we work with ConstantInt based cases.
26612661 // So return CaseValue as ConstantInt.
26632663 }
26642664
26652665 /// Resolves case value for current case.
2666 ConstantRangesSet getCaseValueEx() {
2666 IntegersSubset getCaseValueEx() {
26672667 assert(Index < SI->getNumCases() && "Index out the number of cases.");
26682668 return reinterpret_cast(SI->getOperand(2 + Index*2));
26692669 }
27352735 /// @Deprecated.
27362736 void setValue(ConstantInt *V) {
27372737 assert(Index < SI->getNumCases() && "Index out the number of cases.");
2738 CRSBuilder CB;
2738 IntegersSubsetToBB Mapping;
27392739 // FIXME: Currently we work with ConstantInt based cases.
27402740 // So inititalize IntItem container directly from ConstantInt.
2741 CB.add(IntItem::fromConstantInt(V));
2741 Mapping.add(IntItem::fromConstantInt(V));
27422742 SI->setOperand(2 + Index*2,
2743 reinterpret_cast((Constant*)CB.getCase()));
2743 reinterpret_cast((Constant*)Mapping.getCase()));
27442744 }
27452745
27462746 /// Sets the new value for current case.
2747 void setValueEx(ConstantRangesSet& V) {
2747 void setValueEx(IntegersSubset& V) {
27482748 assert(Index < SI->getNumCases() && "Index out the number of cases.");
27492749 SI->setOperand(2 + Index*2, reinterpret_cast((Constant*)V));
27502750 }
+0
-255
include/llvm/Support/CRSBuilder.h less more
None //===- CRSBuilder.h - ConstantRangesSet Builder -----------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// @file
10 /// CRSBuilder allows to build and parse ConstantRangesSet objects.
11 /// There is such features like add/remove range, or combine
12 /// Two ConstantRangesSet object with neighboring ranges merging.
13 /// Set IsReadonly=true if you want to operate with "const ConstantInt" and
14 /// "const ConstantRangesSet" objects.
15 //
16 //===----------------------------------------------------------------------===//
17
18 #ifndef CRSBUILDER_H_
19 #define CRSBUILDER_H_
20
21 #include "llvm/Support/ConstantRangesSet.h"
22 #include
23 #include
24 #include
25
26 namespace llvm {
27
28 template
29 class CRSBuilderBase {
30 public:
31
32 typedef ConstantRangesSet::Range RangeTy;
33
34 struct RangeEx : public RangeTy {
35 typedef ConstantRangesSet::Range RangeTy;
36 RangeEx() : Weight(1) {}
37 RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {}
38 RangeEx(const IntItem &C) : RangeTy(C), Weight(1) {}
39 RangeEx(const IntItem &L, const IntItem &H) : RangeTy(L, H), Weight(1) {}
40 RangeEx(const IntItem &L, const IntItem &H, unsigned W) :
41 RangeTy(L, H), Weight(W) {}
42 unsigned Weight;
43 };
44
45 typedef std::pair Cluster;
46
47 protected:
48
49 typedef std::vector CaseItems;
50 typedef typename CaseItems::iterator CaseItemIt;
51 typedef typename CaseItems::const_iterator CaseItemConstIt;
52
53 struct ClustersCmp {
54 bool operator()(const Cluster &C1, const Cluster &C2) {
55 return C1.first < C2.first;
56 }
57 };
58
59 CaseItems Items;
60 bool Sorted;
61
62 bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
63 return LItem->first.High->uge(RItem->first.Low);
64 }
65
66 bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) {
67 if (LItem->second != RItem->second) {
68 assert(!isIntersected(LItem, RItem) &&
69 "Intersected items with different successors!");
70 return false;
71 }
72 APInt RLow = RItem->first.Low;
73 if (RLow != APInt::getNullValue(RLow.getBitWidth()))
74 --RLow;
75 return LItem->first.High->uge(RLow);
76 }
77
78 void sort() {
79 if (!Sorted) {
80 std::sort(Items.begin(), Items.end(), ClustersCmp());
81 Sorted = true;
82 }
83 }
84
85 public:
86
87 // Don't public CaseItems itself. Don't allow edit the Items directly.
88 // Just present the user way to iterate over the internal collection
89 // sharing iterator, begin() and end(). Editing should be controlled by
90 // factory.
91 typedef CaseItemIt RangeIterator;
92
93 CRSBuilderBase() {
94 Items.reserve(32);
95 Sorted = false;
96 }
97
98 bool verify(RangeIterator& errItem) {
99 if (Items.empty())
100 return true;
101 sort();
102 for (CaseItemIt i = Items.begin(), j = i+1, e = Items.end();
103 j != e; i = j++) {
104 if (isIntersected(j, i) && j->second != i->second) {
105 errItem = j;
106 return false;
107 }
108 }
109 return true;
110 }
111
112 void optimize() {
113 if (Items.size() < 2)
114 return;
115 sort();
116 CaseItems OldItems = Items;
117 Items.clear();
118 IntItem *Low = &OldItems.begin()->first.Low;
119 IntItem *High = &OldItems.begin()->first.High;
120 unsigned Weight = 1;
121 SuccessorClass *Successor = OldItems.begin()->second;
122 for (CaseItemIt i = OldItems.begin(), j = i+1, e = OldItems.end();
123 j != e; i = j++) {
124 if (isJoinable(i, j)) {
125 IntItem *CurHigh = &j->first.High;
126 ++Weight;
127 if ((*CurHigh)->ugt(*High))
128 High = CurHigh;
129 } else {
130 RangeEx R(*Low, *High, Weight);
131 add(R, Successor);
132 Low = &j->first.Low;
133 High = &j->first.High;
134 Weight = 1;
135 Successor = j->second;
136 }
137 }
138 RangeEx R(*Low, *High, Weight);
139 add(R, Successor);
140 // We recollected the Items, but we kept it sorted.
141 Sorted = true;
142 }
143
144 /// Adds a constant value.
145 void add(const IntItem &C, SuccessorClass *S = 0) {
146 RangeTy R(C);
147 add(R, S);
148 }
149
150 /// Adds a range.
151 void add(const IntItem &Low, const IntItem &High, SuccessorClass *S = 0) {
152 RangeTy R(Low, High);
153 add(R, S);
154 }
155 void add(const RangeTy &R, SuccessorClass *S = 0) {
156 RangeEx REx = R;
157 add(REx, S);
158 }
159 void add(const RangeEx &R, SuccessorClass *S = 0) {
160 Items.push_back(std::make_pair(R, S));
161 Sorted = false;
162 }
163
164 /// Adds all ranges and values from given ranges set to the current
165 /// CRSBuilder object.
166 void add(const ConstantRangesSet &CRS, SuccessorClass *S = 0) {
167 for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) {
168 RangeTy R = CRS.getItem(i);
169 add(R, S);
170 }
171 }
172
173 /// Removes items from set.
174 void removeItem(RangeIterator i) { Items.erase(i); }
175
176 /// Returns true if there is no ranges and values inside.
177 bool empty() const { return Items.empty(); }
178
179 RangeIterator begin() { return Items.begin(); }
180 RangeIterator end() { return Items.end(); }
181 };
182
183 template
184 class CRSBuilderT : public CRSBuilderBase {
185 public:
186
187 typedef typename CRSBuilderBase::RangeTy RangeTy;
188 typedef typename CRSBuilderBase::RangeIterator
189 RangeIterator;
190
191 private:
192
193 typedef std::list RangesCollection;
194 typedef typename RangesCollection::iterator RangesCollectionIt;
195
196 typedef std::map CRSMap;
197 typedef typename CRSMap::iterator CRSMapIt;
198
199 ConstantRangesSet getCase(RangesCollection& Src) {
200 std::vector Elts;
201 Elts.reserve(Src.size());
202 for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) {
203 RangeTy &R = *i;
204 std::vector r;
205 if (R.isSingleNumber()) {
206 r.reserve(2);
207 // FIXME: Since currently we have ConstantInt based numbers
208 // use hack-conversion of IntItem to ConstantInt
209 r.push_back(R.Low.toConstantInt());
210 r.push_back(R.High.toConstantInt());
211 } else {
212 r.reserve(1);
213 r.push_back(R.Low.toConstantInt());
214 }
215 Constant *CV = ConstantVector::get(r);
216 Elts.push_back(CV);
217 }
218 ArrayType *ArrTy =
219 ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size());
220 Constant *Array = ConstantArray::get(ArrTy, Elts);
221 return ConstantRangesSet(Array);
222 }
223
224 public:
225
226 typedef std::pair Case;
227 typedef std::list Cases;
228
229 /// Builds the finalized case objects.
230 void getCases(Cases& TheCases) {
231 CRSMap TheCRSMap;
232 for (RangeIterator i = this->begin(); i != this->end(); ++i)
233 TheCRSMap[i->second].push_back(i->first);
234 for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i)
235 TheCases.push_back(std::make_pair(i->first, getCase(i->second)));
236 }
237
238 /// Builds the finalized case objects ignoring successor values, as though
239 /// all ranges belongs to the same successor.
240 ConstantRangesSet getCase() {
241 RangesCollection Ranges;
242 for (RangeIterator i = this->begin(); i != this->end(); ++i)
243 Ranges.push_back(i->first);
244 return getCase(Ranges);
245 }
246 };
247
248 class BasicBlock;
249 typedef CRSBuilderT CRSBuilder;
250 typedef CRSBuilderBase CRSBuilderConst;
251
252 }
253
254 #endif /* CRSBUILDER_H_ */
+0
-372
include/llvm/Support/ConstantRangesSet.h less more
None //===-- llvm/ConstantRangesSet.h - The constant set of ranges ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// @file
10 /// This file contains class that implements constant set of ranges:
11 /// [,...,]. Mainly, this set is used by SwitchInst and
12 /// represents case value that may contain multiple ranges for a single
13 /// successor.
14 ///
15 //
16 //===----------------------------------------------------------------------===//
17
18 #ifndef CONSTANTRANGESSET_H_
19 #define CONSTANTRANGESSET_H_
20
21 #include "llvm/Constants.h"
22 #include "llvm/DerivedTypes.h"
23 #include "llvm/LLVMContext.h"
24
25 namespace llvm {
26
27 template
28 class IntItemBase {
29 protected:
30 ImplTy Implementation;
31 typedef IntItemBase self;
32 public:
33
34 IntItemBase() {}
35
36 IntItemBase(const ImplTy &impl) : Implementation(impl) {}
37
38 // implicit
39 IntItemBase(const APInt& src) : Implementation(src) {}
40
41 operator const APInt&() const {
42 return (const APInt&)Implementation;
43 }
44 bool operator<(const self& RHS) const {
45 return ((const APInt&)*this).ult(RHS);
46 }
47 bool operator==(const self& RHS) const {
48 return (const APInt&)*this == (const APInt&)RHS;
49 }
50 bool operator!=(const self& RHS) const {
51 return (const APInt&)*this != (const APInt&)RHS;
52 }
53 self& operator=(const ImplTy& RHS) {
54 Implementation = RHS;
55 return *this;
56 }
57 const APInt* operator->() const {
58 return &((const APInt&)Implementation);
59 }
60 const APInt& operator*() const {
61 return ((const APInt&)Implementation);
62 }
63 // FIXME: Hack. Will removed.
64 ImplTy& getImplementation() {
65 return Implementation;
66 }
67 };
68
69 class IntItemConstantIntImpl {
70 const ConstantInt *ConstantIntVal;
71 public:
72 IntItemConstantIntImpl() : ConstantIntVal(0) {}
73 IntItemConstantIntImpl(const ConstantInt *Val) : ConstantIntVal(Val) {}
74 IntItemConstantIntImpl(LLVMContext &Ctx, const APInt& src) {
75 ConstantIntVal = cast(ConstantInt::get(Ctx, src));
76 }
77 explicit IntItemConstantIntImpl(const APInt& src) {
78 ConstantIntVal =
79 cast(ConstantInt::get(llvm::getGlobalContext(), src));
80 }
81 operator const APInt&() const {
82 return ConstantIntVal->getValue();
83 }
84 operator const ConstantInt*() {
85 return ConstantIntVal;
86 }
87 };
88
89 class IntItem : public IntItemBase {
90 typedef IntItemBase ParentTy;
91 IntItem(const IntItemConstantIntImpl& Impl) : ParentTy(Impl) {}
92 public:
93
94 IntItem() {}
95
96 // implicit
97 IntItem(const APInt& src) : ParentTy(src) {}
98
99 static IntItem fromConstantInt(const ConstantInt *V) {
100 IntItemConstantIntImpl Impl(V);
101 return IntItem(Impl);
102 }
103 static IntItem fromType(Type* Ty, const APInt& V) {
104 ConstantInt *C = cast(ConstantInt::get(Ty, V));
105 return fromConstantInt(C);
106 }
107 ConstantInt *toConstantInt() {
108 return const_cast((const ConstantInt*)Implementation);
109 }
110 };
111
112 // TODO: it should be a class in next commit.
113 struct IntRange {
114
115 IntItem Low;
116 IntItem High;
117 bool IsEmpty : 1;
118 bool IsSingleNumber : 1;
119 // TODO:
120 // public:
121
122 typedef std::pair SubRes;
123
124 IntRange() : IsEmpty(true) {}
125 IntRange(const IntRange &RHS) :
126 Low(RHS.Low), High(RHS.High), IsEmpty(false), IsSingleNumber(false) {}
127 IntRange(const IntItem &C) :
128 Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {}
129 IntRange(const IntItem &L, const IntItem &H) : Low(L), High(H),
130 IsEmpty(false), IsSingleNumber(false) {}
131
132 bool isEmpty() const { return IsEmpty; }
133 bool isSingleNumber() const { return IsSingleNumber; }
134
135 const IntItem& getLow() {
136 assert(!IsEmpty && "Range is empty.");
137 return Low;
138 }
139 const IntItem& getHigh() {
140 assert(!IsEmpty && "Range is empty.");
141 return High;
142 }
143
144 bool operator<(const IntRange &RHS) const {
145 assert(!IsEmpty && "Left range is empty.");
146 assert(!RHS.IsEmpty && "Right range is empty.");
147 if (Low->getBitWidth() == RHS.Low->getBitWidth()) {
148 if (Low->eq(RHS.Low)) {
149 if (High->ult(RHS.High))
150 return true;
151 return false;
152 }
153 if (Low->ult(RHS.Low))
154 return true;
155 return false;
156 } else
157 return Low->getBitWidth() < RHS.Low->getBitWidth();
158 }
159
160 bool operator==(const IntRange &RHS) const {
161 assert(!IsEmpty && "Left range is empty.");
162 assert(!RHS.IsEmpty && "Right range is empty.");
163 if (Low->getBitWidth() != RHS.Low->getBitWidth())
164 return false;
165 return Low == RHS.Low && High == RHS.High;
166 }
167
168 bool operator!=(const IntRange &RHS) const {
169 return !operator ==(RHS);
170 }
171
172 static bool LessBySize(const IntRange &LHS, const IntRange &RHS) {
173 assert(LHS.Low->getBitWidth() == RHS.Low->getBitWidth() &&
174 "This type of comparison requires equal bit width for LHS and RHS");
175 APInt LSize = *LHS.High - *LHS.Low;
176 APInt RSize = *RHS.High - *RHS.Low;
177 return LSize.ult(RSize);
178 }
179
180 bool isInRange(const APInt &IntVal) const {
181 assert(!IsEmpty && "Range is empty.");
182 if (IntVal.getBitWidth() != Low->getBitWidth())
183 return false;
184 return IntVal.uge(Low) && IntVal.ule(High);
185 }
186
187 SubRes sub(const IntRange &RHS) const {
188 SubRes Res;
189
190 // RHS is either more global and includes this range or
191 // if it doesn't intersected with this range.
192 if (!isInRange(RHS.Low) && !isInRange(RHS.High)) {
193
194 // If RHS more global (it is enough to check
195 // only one border in this case.
196 if (RHS.isInRange(Low))
197 return std::make_pair(IntRange(Low, High), IntRange());
198
199 return Res;
200 }
201
202 if (Low->ult(RHS.Low)) {
203 Res.first.Low = Low;
204 APInt NewHigh = RHS.Low;
205 --NewHigh;
206 Res.first.High = NewHigh;
207 }
208 if (High->ugt(RHS.High)) {
209 APInt NewLow = RHS.High;
210 ++NewLow;
211 Res.second.Low = NewLow;
212 Res.second.High = High;
213 }
214 return Res;
215 }
216 };
217
218 //===----------------------------------------------------------------------===//
219 /// ConstantRangesSet - class that implements constant set of ranges.
220 /// It is a wrapper for some real "holder" class (currently ConstantArray).
221 /// It contains functions, that allows to parse "holder" like a set of ranges.
222 /// Note: It is assumed that "holder" is inherited from Constant object.
223 /// ConstantRangesSet may be converted to and from Constant* pointer.
224 ///
225 class ConstantRangesSet {
226 Constant *Array;
227 public:
228
229 bool IsWide;
230
231 // implicit
232 ConstantRangesSet(Constant *V) : Array(V) {
233 ArrayType *ArrTy = cast(Array->getType());
234 VectorType *VecTy = cast(ArrTy->getElementType());
235 IntegerType *IntTy = cast(VecTy->getElementType());
236 IsWide = IntTy->getBitWidth() > 64;
237 }
238
239 operator Constant*() { return Array; }
240 operator const Constant*() const { return Array; }
241 Constant *operator->() { return Array; }
242 const Constant *operator->() const { return Array; }
243
244 typedef IntRange Range;
245
246 /// Checks is the given constant satisfies this case. Returns
247 /// true if it equals to one of contained values or belongs to the one of
248 /// contained ranges.
249 bool isSatisfies(const IntItem &CheckingVal) const {
250 for (unsigned i = 0, e = getNumItems(); i < e; ++i) {
251 const Constant *CV = Array->getAggregateElement(i);
252 unsigned VecSize = cast(CV->getType())->getNumElements();
253 switch (VecSize) {
254 case 1:
255 if (cast(CV->getAggregateElement(0U))->getValue() ==
256 CheckingVal)
257 return true;
258 break;
259 case 2: {
260 const APInt &Lo =
261 cast(CV->getAggregateElement(0U))->getValue();
262 const APInt &Hi =
263 cast(CV->getAggregateElement(1))->getValue();
264 if (Lo.uge(CheckingVal) && Hi.ule(CheckingVal))
265 return true;
266 }
267 break;
268 default:
269 assert(0 && "Only pairs and single numbers are allowed here.");
270 break;
271 }
272 }
273 return false;
274 }
275
276 /// Returns set's item with given index.
277 Range getItem(unsigned idx) {
278 Constant *CV = Array->getAggregateElement(idx);
279 unsigned NumEls = cast(CV->getType())->getNumElements();
280 switch (NumEls) {
281 case 1:
282 return Range(IntItem::fromConstantInt(
283 cast(CV->getAggregateElement(0U))));
284 case 2:
285 return Range(IntItem::fromConstantInt(
286 cast(CV->getAggregateElement(0U))),
287 IntItem::fromConstantInt(
288 cast(CV->getAggregateElement(1U))));
289 default:
290 assert(0 && "Only pairs and single numbers are allowed here.");
291 return Range();
292 }
293 }
294
295 const Range getItem(unsigned idx) const {
296 const Constant *CV = Array->getAggregateElement(idx);
297
298 unsigned NumEls = cast(CV->getType())->getNumElements();
299 switch (NumEls) {
300 case 1:
301 return Range(IntItem::fromConstantInt(
302 cast(CV->getAggregateElement(0U))),
303 IntItem::fromConstantInt(cast(
304 cast(CV->getAggregateElement(0U)))));
305 case 2:
306 return Range(IntItem::fromConstantInt(
307 cast(CV->getAggregateElement(0U))),
308 IntItem::fromConstantInt(
309 cast(CV->getAggregateElement(1))));
310 default:
311 assert(0 && "Only pairs and single numbers are allowed here.");
312 return Range();
313 }
314 }
315
316 /// Return number of items (ranges) stored in set.
317 unsigned getNumItems() const {
318 return cast(Array->getType())->getNumElements();
319 }
320
321 bool isWideNumberFormat() const { return IsWide; }
322
323 bool isSingleNumber(unsigned idx) const {
324 Constant *CV = Array->getAggregateElement(idx);
325 return cast(CV->getType())->getNumElements() == 1;
326 }
327
328 /// Returns set the size, that equals number of all values + sizes of all
329 /// ranges.
330 /// Ranges set is considered as flat numbers collection.
331 /// E.g.: for range [<0>, <1>, <4,8>] the size will 7;
332 /// for range [<0>, <1>, <5>] the size will 3
333 unsigned getSize() const {
334 APInt sz(getItem(0).Low->getBitWidth(), 0);
335 for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
336 const APInt &Low = getItem(i).Low;
337 const APInt &High = getItem(i).High;
338 const APInt &S = High - Low;
339 sz += S;
340 }
341 return sz.getZExtValue();
342 }
343
344 /// Allows to access single value even if it belongs to some range.
345 /// Ranges set is considered as flat numbers collection.
346 /// [<1>, <4,8>] is considered as [1,4,5,6,7,8]
347 /// For range [<1>, <4,8>] getSingleValue(3) returns 6.
348 APInt getSingleValue(unsigned idx) const {
349 APInt sz(getItem(0).Low->getBitWidth(), 0);
350 for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
351 const APInt &Low = getItem(i).Low;
352 const APInt &High = getItem(i).High;
353 const APInt& S = High - Low;
354 APInt oldSz = sz;
355 sz += S;
356 if (oldSz.uge(i) && sz.ult(i)) {
357 APInt Res = Low;
358 APInt Offset(oldSz.getBitWidth(), i);
359 Offset -= oldSz;
360 Res += Offset;
361 return Res;
362 }
363 }
364 assert(0 && "Index exceeds high border.");
365 return sz;
366 }
367 };
368
369 }
370
371 #endif /* CONSTANTRANGESSET_H_ */
0 //===-- llvm/ConstantRangesSet.h - The constant set of ranges ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// @file
10 /// This file contains class that implements constant set of ranges:
11 /// [,...,]. Mainly, this set is used by SwitchInst and
12 /// represents case value that may contain multiple ranges for a single
13 /// successor.
14 ///
15 //
16 //===----------------------------------------------------------------------===//
17
18 #ifndef CONSTANTRANGESSET_H_
19 #define CONSTANTRANGESSET_H_
20
21 #include "llvm/Constants.h"
22 #include "llvm/DerivedTypes.h"
23 #include "llvm/LLVMContext.h"
24
25 namespace llvm {
26
27 template
28 class IntItemBase {
29 protected:
30 ImplTy Implementation;
31 typedef IntItemBase self;
32 public:
33
34 IntItemBase() {}
35
36 IntItemBase(const ImplTy &impl) : Implementation(impl) {}
37
38 // implicit
39 IntItemBase(const APInt& src) : Implementation(src) {}
40
41 operator const APInt&() const {
42 return (const APInt&)Implementation;
43 }
44 bool operator<(const self& RHS) const {
45 return ((const APInt&)*this).ult(RHS);
46 }
47 bool operator==(const self& RHS) const {
48 return (const APInt&)*this == (const APInt&)RHS;
49 }
50 bool operator!=(const self& RHS) const {
51 return (const APInt&)*this != (const APInt&)RHS;
52 }
53 self& operator=(const ImplTy& RHS) {
54 Implementation = RHS;
55 return *this;
56 }
57 const APInt* operator->() const {
58 return &((const APInt&)Implementation);
59 }
60 const APInt& operator*() const {
61 return ((const APInt&)Implementation);
62 }
63 // FIXME: Hack. Will removed.
64 ImplTy& getImplementation() {
65 return Implementation;
66 }
67 };
68
69 class IntItemConstantIntImpl {
70 const ConstantInt *ConstantIntVal;
71 public:
72 IntItemConstantIntImpl() : ConstantIntVal(0) {}
73 IntItemConstantIntImpl(const ConstantInt *Val) : ConstantIntVal(Val) {}
74 IntItemConstantIntImpl(LLVMContext &Ctx, const APInt& src) {
75 ConstantIntVal = cast(ConstantInt::get(Ctx, src));
76 }
77 explicit IntItemConstantIntImpl(const APInt& src) {
78 ConstantIntVal =
79 cast(ConstantInt::get(llvm::getGlobalContext(), src));
80 }
81 operator const APInt&() const {
82 return ConstantIntVal->getValue();
83 }
84 operator const ConstantInt*() {
85 return ConstantIntVal;
86 }
87 };
88
89 class IntItem : public IntItemBase {
90 typedef IntItemBase ParentTy;
91 IntItem(const IntItemConstantIntImpl& Impl) : ParentTy(Impl) {}
92 public:
93
94 IntItem() {}
95
96 // implicit
97 IntItem(const APInt& src) : ParentTy(src) {}
98
99 static IntItem fromConstantInt(const ConstantInt *V) {
100 IntItemConstantIntImpl Impl(V);
101 return IntItem(Impl);
102 }
103 static IntItem fromType(Type* Ty, const APInt& V) {
104 ConstantInt *C = cast(ConstantInt::get(Ty, V));
105 return fromConstantInt(C);
106 }
107 ConstantInt *toConstantInt() {
108 return const_cast((const ConstantInt*)Implementation);
109 }
110 };
111
112 // TODO: it should be a class in next commit.
113 struct IntRange {
114
115 IntItem Low;
116 IntItem High;
117 bool IsEmpty : 1;
118 bool IsSingleNumber : 1;
119 // TODO:
120 // public:
121
122 typedef std::pair SubRes;
123
124 IntRange() : IsEmpty(true) {}
125 IntRange(const IntRange &RHS) :
126 Low(RHS.Low), High(RHS.High), IsEmpty(false), IsSingleNumber(false) {}
127 IntRange(const IntItem &C) :
128 Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {}
129 IntRange(const IntItem &L, const IntItem &H) : Low(L), High(H),
130 IsEmpty(false), IsSingleNumber(false) {}
131
132 bool isEmpty() const { return IsEmpty; }
133 bool isSingleNumber() const { return IsSingleNumber; }
134
135 const IntItem& getLow() {
136 assert(!IsEmpty && "Range is empty.");
137 return Low;
138 }
139 const IntItem& getHigh() {
140 assert(!IsEmpty && "Range is empty.");
141 return High;
142 }
143
144 bool operator<(const IntRange &RHS) const {
145 assert(!IsEmpty && "Left range is empty.");
146 assert(!RHS.IsEmpty && "Right range is empty.");
147 if (Low->getBitWidth() == RHS.Low->getBitWidth()) {
148 if (Low->eq(RHS.Low)) {
149 if (High->ult(RHS.High))
150 return true;
151 return false;
152 }
153 if (Low->ult(RHS.Low))
154 return true;
155 return false;
156 } else
157 return Low->getBitWidth() < RHS.Low->getBitWidth();
158 }
159
160 bool operator==(const IntRange &RHS) const {
161 assert(!IsEmpty && "Left range is empty.");
162 assert(!RHS.IsEmpty && "Right range is empty.");
163 if (Low->getBitWidth() != RHS.Low->getBitWidth())
164 return false;
165 return Low == RHS.Low && High == RHS.High;
166 }
167
168 bool operator!=(const IntRange &RHS) const {
169 return !operator ==(RHS);
170 }
171
172 static bool LessBySize(const IntRange &LHS, const IntRange &RHS) {
173 assert(LHS.Low->getBitWidth() == RHS.Low->getBitWidth() &&
174 "This type of comparison requires equal bit width for LHS and RHS");
175 APInt LSize = *LHS.High - *LHS.Low;
176 APInt RSize = *RHS.High - *RHS.Low;
177 return LSize.ult(RSize);
178 }
179
180 bool isInRange(const APInt &IntVal) const {
181 assert(!IsEmpty && "Range is empty.");
182 if (IntVal.getBitWidth() != Low->getBitWidth())
183 return false;
184 return IntVal.uge(Low) && IntVal.ule(High);
185 }
186
187 SubRes sub(const IntRange &RHS) const {
188 SubRes Res;
189
190 // RHS is either more global and includes this range or
191 // if it doesn't intersected with this range.
192 if (!isInRange(RHS.Low) && !isInRange(RHS.High)) {
193
194 // If RHS more global (it is enough to check
195 // only one border in this case.
196 if (RHS.isInRange(Low))
197 return std::make_pair(IntRange(Low, High), IntRange());
198
199 return Res;
200 }
201
202 if (Low->ult(RHS.Low)) {
203 Res.first.Low = Low;
204 APInt NewHigh = RHS.Low;
205 --NewHigh;
206 Res.first.High = NewHigh;
207 }
208 if (High->ugt(RHS.High)) {
209 APInt NewLow = RHS.High;
210 ++NewLow;
211 Res.second.Low = NewLow;
212 Res.second.High = High;
213 }
214 return Res;
215 }
216 };
217
218 //===----------------------------------------------------------------------===//
219 /// ConstantRangesSet - class that implements constant set of ranges.
220 /// It is a wrapper for some real "holder" class (currently ConstantArray).
221 /// It contains functions, that allows to parse "holder" like a set of ranges.
222 /// Note: It is assumed that "holder" is inherited from Constant object.
223 /// ConstantRangesSet may be converted to and from Constant* pointer.
224 ///
225 class IntegersSubset {
226 Constant *Array;
227 public:
228
229 bool IsWide;
230
231 // implicit
232 IntegersSubset(Constant *V) : Array(V) {
233 ArrayType *ArrTy = cast(Array->getType());
234 VectorType *VecTy = cast(ArrTy->getElementType());
235 IntegerType *IntTy = cast(VecTy->getElementType());
236 IsWide = IntTy->getBitWidth() > 64;
237 }
238
239 operator Constant*() { return Array; }
240 operator const Constant*() const { return Array; }
241 Constant *operator->() { return Array; }
242 const Constant *operator->() const { return Array; }
243
244 typedef IntRange Range;
245
246 /// Checks is the given constant satisfies this case. Returns
247 /// true if it equals to one of contained values or belongs to the one of
248 /// contained ranges.
249 bool isSatisfies(const IntItem &CheckingVal) const {
250 for (unsigned i = 0, e = getNumItems(); i < e; ++i) {
251 const Constant *CV = Array->getAggregateElement(i);
252 unsigned VecSize = cast(CV->getType())->getNumElements();
253 switch (VecSize) {
254 case 1:
255 if (cast(CV->getAggregateElement(0U))->getValue() ==
256 CheckingVal)
257 return true;
258 break;
259 case 2: {
260 const APInt &Lo =
261 cast(CV->getAggregateElement(0U))->getValue();
262 const APInt &Hi =
263 cast(CV->getAggregateElement(1))->getValue();
264 if (Lo.uge(CheckingVal) && Hi.ule(CheckingVal))
265 return true;
266 }
267 break;
268 default:
269 assert(0 && "Only pairs and single numbers are allowed here.");
270 break;
271 }
272 }
273 return false;
274 }
275
276 /// Returns set's item with given index.
277 Range getItem(unsigned idx) {
278 Constant *CV = Array->getAggregateElement(idx);
279 unsigned NumEls = cast(CV->getType())->getNumElements();
280 switch (NumEls) {
281 case 1:
282 return Range(IntItem::fromConstantInt(
283 cast(CV->getAggregateElement(0U))));
284 case 2:
285 return Range(IntItem::fromConstantInt(
286 cast(CV->getAggregateElement(0U))),
287 IntItem::fromConstantInt(
288 cast(CV->getAggregateElement(1U))));
289 default:
290 assert(0 && "Only pairs and single numbers are allowed here.");
291 return Range();
292 }
293 }
294
295 const Range getItem(unsigned idx) const {
296 const Constant *CV = Array->getAggregateElement(idx);
297
298 unsigned NumEls = cast(CV->getType())->getNumElements();
299 switch (NumEls) {
300 case 1:
301 return Range(IntItem::fromConstantInt(
302 cast(CV->getAggregateElement(0U))),
303 IntItem::fromConstantInt(cast(
304 cast(CV->getAggregateElement(0U)))));
305 case 2:
306 return Range(IntItem::fromConstantInt(
307 cast(CV->getAggregateElement(0U))),
308 IntItem::fromConstantInt(
309 cast(CV->getAggregateElement(1))));
310 default:
311 assert(0 && "Only pairs and single numbers are allowed here.");
312 return Range();
313 }
314 }
315
316 /// Return number of items (ranges) stored in set.
317 unsigned getNumItems() const {
318 return cast(Array->getType())->getNumElements();
319 }
320
321 bool isWideNumberFormat() const { return IsWide; }
322
323 bool isSingleNumber(unsigned idx) const {
324 Constant *CV = Array->getAggregateElement(idx);
325 return cast(CV->getType())->getNumElements() == 1;
326 }
327
328 /// Returns set the size, that equals number of all values + sizes of all
329 /// ranges.
330 /// Ranges set is considered as flat numbers collection.
331 /// E.g.: for range [<0>, <1>, <4,8>] the size will 7;
332 /// for range [<0>, <1>, <5>] the size will 3
333 unsigned getSize() const {
334 APInt sz(getItem(0).Low->getBitWidth(), 0);
335 for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
336 const APInt &Low = getItem(i).Low;
337 const APInt &High = getItem(i).High;
338 const APInt &S = High - Low;
339 sz += S;
340 }
341 return sz.getZExtValue();
342 }
343
344 /// Allows to access single value even if it belongs to some range.
345 /// Ranges set is considered as flat numbers collection.
346 /// [<1>, <4,8>] is considered as [1,4,5,6,7,8]
347 /// For range [<1>, <4,8>] getSingleValue(3) returns 6.
348 APInt getSingleValue(unsigned idx) const {
349 APInt sz(getItem(0).Low->getBitWidth(), 0);
350 for (unsigned i = 0, e = getNumItems(); i != e; ++i) {
351 const APInt &Low = getItem(i).Low;
352 const APInt &High = getItem(i).High;
353 const APInt& S = High - Low;
354 APInt oldSz = sz;
355 sz += S;
356 if (oldSz.uge(i) && sz.ult(i)) {
357 APInt Res = Low;
358 APInt Offset(oldSz.getBitWidth(), i);
359 Offset -= oldSz;
360 Res += Offset;
361 return Res;
362 }
363 }
364 assert(0 && "Index exceeds high border.");
365 return sz;
366 }
367 };
368
369 }
370
371 #endif /* CONSTANTRANGESSET_H_ */
0 //===- CRSBuilder.h - ConstantRangesSet Builder -----------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// @file
10 /// CRSBuilder allows to build and parse ConstantRangesSet objects.
11 /// There is such features like add/remove range, or combine
12 /// Two ConstantRangesSet object with neighboring ranges merging.
13 /// Set IsReadonly=true if you want to operate with "const ConstantInt" and
14 /// "const ConstantRangesSet" objects.
15 //
16 //===----------------------------------------------------------------------===//
17
18 #ifndef CRSBUILDER_H_
19 #define CRSBUILDER_H_
20
21 #include "llvm/Support/IntegersSubset.h"
22 #include
23 #include
24 #include
25
26 namespace llvm {
27
28 template
29 class IntegersSubsetMapping {
30 public:
31
32 typedef IntegersSubset::Range RangeTy;
33
34 struct RangeEx : public RangeTy {
35 typedef IntegersSubset::Range RangeTy;
36 RangeEx() : Weight(1) {}
37 RangeEx(const RangeTy &R) : RangeTy(R.Low, R.High), Weight(1) {}
38 RangeEx(const IntItem &C) : RangeTy(C), Weight(1) {}
39 RangeEx(const IntItem &L, const IntItem &H) : RangeTy(L, H), Weight(1) {}
40 RangeEx(const IntItem &L, const IntItem &H, unsigned W) :
41 RangeTy(L, H), Weight(W) {}
42 unsigned Weight;
43 };
44
45 typedef std::pair Cluster;
46
47 protected:
48
49 typedef std::vector CaseItems;
50 typedef typename CaseItems::iterator CaseItemIt;
51 typedef typename CaseItems::const_iterator CaseItemConstIt;
52
53 typedef std::list RangesCollection;
54 typedef typename RangesCollection::iterator RangesCollectionIt;
55
56 typedef std::map CRSMap;
57 typedef typename CRSMap::iterator CRSMapIt;
58
59 struct ClustersCmp {
60 bool operator()(const Cluster &C1, const Cluster &C2) {
61 return C1.first < C2.first;
62 }
63 };
64
65 CaseItems Items;
66 bool Sorted;
67
68 bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
69 return LItem->first.High->uge(RItem->first.Low);
70 }
71
72 bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) {
73 if (LItem->second != RItem->second) {
74 assert(!isIntersected(LItem, RItem) &&
75 "Intersected items with different successors!");
76 return false;
77 }
78 APInt RLow = RItem->first.Low;
79 if (RLow != APInt::getNullValue(RLow.getBitWidth()))
80 --RLow;
81 return LItem->first.High->uge(RLow);
82 }
83
84 void sort() {
85 if (!Sorted) {
86 std::sort(Items.begin(), Items.end(), ClustersCmp());
87 Sorted = true;
88 }
89 }
90
91 IntegersSubset getCase(RangesCollection& Src) {
92 std::vector Elts;
93 Elts.reserve(Src.size());
94 for (RangesCollectionIt i = Src.begin(), e = Src.end(); i != e; ++i) {
95 RangeTy &R = *i;
96 std::vector r;
97 if (R.isSingleNumber()) {
98 r.reserve(2);
99 // FIXME: Since currently we have ConstantInt based numbers
100 // use hack-conversion of IntItem to ConstantInt
101 r.push_back(R.Low.toConstantInt());
102 r.push_back(R.High.toConstantInt());
103 } else {
104 r.reserve(1);
105 r.push_back(R.Low.toConstantInt());
106 }
107 Constant *CV = ConstantVector::get(r);
108 Elts.push_back(CV);
109 }
110 ArrayType *ArrTy =
111 ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size());
112 Constant *Array = ConstantArray::get(ArrTy, Elts);
113 return IntegersSubset(Array);
114 }
115
116 public:
117
118 // Don't public CaseItems itself. Don't allow edit the Items directly.
119 // Just present the user way to iterate over the internal collection
120 // sharing iterator, begin() and end(). Editing should be controlled by
121 // factory.
122 typedef CaseItemIt RangeIterator;
123
124 typedef std::pair Case;
125 typedef std::list Cases;
126
127 IntegersSubsetMapping() {
128 Items.reserve(32);
129 Sorted = false;
130 }
131
132 bool verify(RangeIterator& errItem) {
133 if (Items.empty())
134 return true;
135 sort();
136 for (CaseItemIt i = Items.begin(), j = i+1, e = Items.end();
137 j != e; i = j++) {
138 if (isIntersected(j, i) && j->second != i->second) {
139 errItem = j;
140 return false;
141 }
142 }
143 return true;
144 }
145
146 void optimize() {
147 if (Items.size() < 2)
148 return;
149 sort();
150 CaseItems OldItems = Items;
151 Items.clear();
152 IntItem *Low = &OldItems.begin()->first.Low;
153 IntItem *High = &OldItems.begin()->first.High;
154 unsigned Weight = 1;
155 SuccessorClass *Successor = OldItems.begin()->second;
156 for (CaseItemIt i = OldItems.begin(), j = i+1, e = OldItems.end();
157 j != e; i = j++) {
158 if (isJoinable(i, j)) {
159 IntItem *CurHigh = &j->first.High;
160 ++Weight;
161 if ((*CurHigh)->ugt(*High))
162 High = CurHigh;
163 } else {
164 RangeEx R(*Low, *High, Weight);
165 add(R, Successor);
166 Low = &j->first.Low;
167 High = &j->first.High;
168 Weight = 1;
169 Successor = j->second;
170 }
171 }
172 RangeEx R(*Low, *High, Weight);
173 add(R, Successor);
174 // We recollected the Items, but we kept it sorted.
175 Sorted = true;
176 }
177
178 /// Adds a constant value.
179 void add(const IntItem &C, SuccessorClass *S = 0) {
180 RangeTy R(C);
181 add(R, S);
182 }
183
184 /// Adds a range.
185 void add(const IntItem &Low, const IntItem &High, SuccessorClass *S = 0) {
186 RangeTy R(Low, High);
187 add(R, S);
188 }
189 void add(const RangeTy &R, SuccessorClass *S = 0) {
190 RangeEx REx = R;
191 add(REx, S);
192 }
193 void add(const RangeEx &R, SuccessorClass *S = 0) {
194 Items.push_back(std::make_pair(R, S));
195 Sorted = false;
196 }
197
198 /// Adds all ranges and values from given ranges set to the current
199 /// CRSBuilder object.
200 void add(const IntegersSubset &CRS, SuccessorClass *S = 0) {
201 for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) {
202 RangeTy R = CRS.getItem(i);
203 add(R, S);
204 }
205 }
206
207 /// Removes items from set.
208 void removeItem(RangeIterator i) { Items.erase(i); }
209
210 /// Builds the finalized case objects.
211 void getCases(Cases& TheCases) {
212 CRSMap TheCRSMap;
213 for (RangeIterator i = this->begin(); i != this->end(); ++i)
214 TheCRSMap[i->second].push_back(i->first);
215 for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i)
216 TheCases.push_back(std::make_pair(i->first, getCase(i->second)));
217 }
218
219 /// Builds the finalized case objects ignoring successor values, as though
220 /// all ranges belongs to the same successor.
221 IntegersSubset getCase() {
222 RangesCollection Ranges;
223 for (RangeIterator i = this->begin(); i != this->end(); ++i)
224 Ranges.push_back(i->first);
225 return getCase(Ranges);
226 }
227
228 /// Returns true if there is no ranges and values inside.
229 bool empty() const { return Items.empty(); }
230
231 RangeIterator begin() { return Items.begin(); }
232 RangeIterator end() { return Items.end(); }
233 };
234
235 class BasicBlock;
236 typedef IntegersSubsetMapping IntegersSubsetToBB;
237
238 }
239
240 #endif /* CRSBUILDER_H_ */
22332233
22342234 unsigned CurIdx = 5;
22352235 for (unsigned i = 0; i != NumCases; ++i) {
2236 CRSBuilder CaseBuilder;
2236 IntegersSubsetToBB CaseBuilder;
22372237 unsigned NumItems = Record[CurIdx++];
22382238 for (unsigned ci = 0; ci != NumItems; ++ci) {
22392239 bool isSingleNumber = Record[CurIdx++];
22612261 CaseBuilder.add(IntItem::fromType(OpTy, Low));
22622262 }
22632263 BasicBlock *DestBB = getBasicBlock(Record[CurIdx++]);
2264 ConstantRangesSet Case = CaseBuilder.getCase();
2264 IntegersSubset Case = CaseBuilder.getCase();
22652265 SI->addCase(Case, DestBB);
22662266 }
22672267 uint16_t Hash = SI->hash();
11561156 Vals64.push_back(SI.getNumCases());
11571157 for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end();
11581158 i != e; ++i) {
1159 ConstantRangesSet CRS = i.getCaseValueEx();
1160 Vals64.push_back(CRS.getNumItems());
1161 for (unsigned ri = 0, rn = CRS.getNumItems(); ri != rn; ++ri) {
1162 ConstantRangesSet::Range r = CRS.getItem(ri);
1163
1164 Vals64.push_back(CRS.isSingleNumber(ri));
1159 IntegersSubset CaseRanges = i.getCaseValueEx();
1160 Vals64.push_back(CaseRanges.getNumItems());
1161 for (unsigned ri = 0, rn = CaseRanges.getNumItems(); ri != rn; ++ri) {
1162 IntegersSubset::Range r = CaseRanges.getItem(ri);
1163
1164 Vals64.push_back(CaseRanges.isSingleNumber(ri));
11651165
11661166 const APInt &Low = r.Low;
11671167 const APInt &High = r.High;
5050 #include "llvm/Target/TargetLowering.h"
5151 #include "llvm/Target/TargetOptions.h"
5252 #include "llvm/Support/CommandLine.h"
53 #include "llvm/Support/CRSBuilder.h"
53 #include "llvm/Support/IntegersSubsetMapping.h"
5454 #include "llvm/Support/Debug.h"
5555 #include "llvm/Support/ErrorHandling.h"
5656 #include "llvm/Support/MathExtras.h"
24262426
24272427 /// Use a shorter form of declaration, and also
24282428 /// show the we want to use CRSBuilder as Clusterifier.
2429 typedef CRSBuilderBase Clusterifier;
2429 typedef IntegersSubsetMapping Clusterifier;
24302430
24312431 Clusterifier TheClusterifier;
24322432
650650 // Check to see if any of the cases match...
651651 BasicBlock *Dest = 0;
652652 for (SwitchInst::CaseIt i = I.case_begin(), e = I.case_end(); i != e; ++i) {
653 ConstantRangesSet Case = i.getCaseValueEx();
653 IntegersSubset Case = i.getCaseValueEx();
654654 for (unsigned n = 0, en = Case.getNumItems(); n != en; ++n) {
655 ConstantRangesSet::Range r = Case.getItem(n);
655 IntegersSubset::Range r = Case.getItem(n);
656656 // FIXME: Currently work with ConstantInt based numbers.
657657 const ConstantInt *LowCI = r.Low.getImplementation();
658658 const ConstantInt *HighCI = r.High.getImplementation();
11041104 nl(Out);
11051105 for (SwitchInst::ConstCaseIt i = SI->case_begin(), e = SI->case_end();
11061106 i != e; ++i) {
1107 const ConstantRangesSet CaseVal = i.getCaseValueEx();
1107 const IntegersSubset CaseVal = i.getCaseValueEx();
11081108 const BasicBlock *BB = i.getCaseSuccessor();
11091109 Out << iName << "->addCase("
11101110 << getOpName(CaseVal) << ", "
168168 // Otherwise, we can fold this switch into a conditional branch
169169 // instruction if it has only one non-default destination.
170170 SwitchInst::CaseIt FirstCase = SI->case_begin();
171 ConstantRangesSet CRS = FirstCase.getCaseValueEx();
172 if (CRS.getNumItems() == 1 && CRS.isSingleNumber(0)) {
171 IntegersSubset CaseRanges = FirstCase.getCaseValueEx();
172 if (CaseRanges.getNumItems() == 1 && CaseRanges.isSingleNumber(0)) {
173173 // FIXME: Currently work with ConstantInt based numbers.
174174 Value *Cond = Builder.CreateICmpEQ(SI->getCondition(),
175 CRS.getItem(0).Low.toConstantInt(),
175 CaseRanges.getItem(0).Low.toConstantInt(),
176176 "cond");
177177
178178 // Insert the new branch.
222222 // Clusterify - Transform simple list of Cases into list of CaseRange's
223223 unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) {
224224
225 CRSBuilder TheClusterifier;
225 IntegersSubsetToBB TheClusterifier;
226226
227227 // Start with "simple" cases
228228 for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
229229 i != e; ++i) {
230230 BasicBlock *SuccBB = i.getCaseSuccessor();
231 ConstantRangesSet CRS = i.getCaseValueEx();
232 TheClusterifier.add(CRS, SuccBB);
231 IntegersSubset CaseRanges = i.getCaseValueEx();
232 TheClusterifier.add(CaseRanges, SuccBB);
233233 }
234234
235235 TheClusterifier.optimize();
236236
237237 size_t numCmps = 0;
238 for (CRSBuilder::RangeIterator i = TheClusterifier.begin(),
238 for (IntegersSubsetToBB::RangeIterator i = TheClusterifier.begin(),
239239 e = TheClusterifier.end(); i != e; ++i, ++numCmps) {
240 CRSBuilder::Cluster &C = *i;
240 IntegersSubsetToBB::Cluster &C = *i;
241241
242242 // FIXME: Currently work with ConstantInt based numbers.
243243 // Changing it to APInt based is a pretty heavy for this commit.
31683168 /// addCase - Add an entry to the switch instruction...
31693169 ///
31703170 void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
3171 CRSBuilder CB;
3171 IntegersSubsetToBB Mapping;
31723172
31733173 // FIXME: Currently we work with ConstantInt based cases.
31743174 // So inititalize IntItem container directly from ConstantInt.
3175 CB.add(IntItem::fromConstantInt(OnVal));
3176 ConstantRangesSet CRS = CB.getCase();
3177 addCase(CRS, Dest);
3178 }
3179
3180 void SwitchInst::addCase(ConstantRangesSet& OnVal, BasicBlock *Dest) {
3175 Mapping.add(IntItem::fromConstantInt(OnVal));
3176 IntegersSubset CaseRanges = Mapping.getCase();
3177 addCase(CaseRanges, Dest);
3178 }
3179
3180 void SwitchInst::addCase(IntegersSubset& OnVal, BasicBlock *Dest) {
31813181 unsigned NewCaseIdx = getNumCases();
31823182 unsigned OpNo = NumOperands;
31833183 if (OpNo+2 > ReservedSpace)
805805 // have the same type as the switched-on value.
806806 Type *SwitchTy = SI.getCondition()->getType();
807807 IntegerType *IntTy = cast(SwitchTy);
808 CRSBuilder Builder;
809 std::map RangeSetMap;
808 IntegersSubsetToBB Mapping;
809 std::map RangeSetMap;
810810 for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) {
811 ConstantRangesSet RS = i.getCaseValueEx();
812 for (unsigned ri = 0, rie = RS.getNumItems(); ri < rie; ++ri) {
813 ConstantRangesSet::Range r = RS.getItem(ri);
811 IntegersSubset CaseRanges = i.getCaseValueEx();
812 for (unsigned ri = 0, rie = CaseRanges.getNumItems(); ri < rie; ++ri) {
813 IntegersSubset::Range r = CaseRanges.getItem(ri);
814814 Assert1(r.Low->getBitWidth() == IntTy->getBitWidth(),
815815 "Switch constants must all be same type as switch value!", &SI);
816816 Assert1(r.High->getBitWidth() == IntTy->getBitWidth(),
817817 "Switch constants must all be same type as switch value!", &SI);
818 Builder.add(r);
818 Mapping.add(r);
819819 RangeSetMap[r] = i.getCaseIndex();
820820 }
821821 }
822822
823 CRSBuilder::RangeIterator errItem;
824 if (!Builder.verify(errItem)) {
823 IntegersSubsetToBB::RangeIterator errItem;
824 if (!Mapping.verify(errItem)) {
825825 unsigned CaseIndex = RangeSetMap[errItem->first];
826826 SwitchInst::CaseIt i(&SI, CaseIndex);
827827 Assert2(false, "Duplicate integer as switch case", &SI, i.getCaseValueEx());
325325
326326 for (SwitchInst::CaseIt I = RI->case_begin(), E = RI->case_end();
327327 I != E; ++I) {
328 ConstantRangesSet CaseValue = I.getCaseValueEx();
328 IntegersSubset CaseValue = I.getCaseValueEx();
329329 BasicBlock *LCase = LCases[CaseValue];
330330 if (LCase) {
331331 if (TryUnify) tryUnify(LCase, I.getCaseSuccessor());