LLVM API Documentation
00001 //===- IntegersSubsetMapping.h - Mapping subset ==> Successor ---*- 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 /// IntegersSubsetMapping is mapping from A to B, where 00012 /// Items in A is subsets of integers, 00013 /// Items in B some pointers (Successors). 00014 /// If user which to add another subset for successor that is already 00015 /// exists in mapping, IntegersSubsetMapping merges existing subset with 00016 /// added one. 00017 // 00018 //===----------------------------------------------------------------------===// 00019 00020 #ifndef LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H 00021 #define LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H 00022 00023 #include "llvm/Support/IntegersSubset.h" 00024 #include <list> 00025 #include <map> 00026 #include <vector> 00027 00028 namespace llvm { 00029 00030 template <class SuccessorClass, 00031 class IntegersSubsetTy = IntegersSubset, 00032 class IntTy = IntItem> 00033 class IntegersSubsetMapping { 00034 // FIXME: To much similar iterators typedefs, similar names. 00035 // - Rename RangeIterator to the cluster iterator. 00036 // - Remove unused "add" methods. 00037 // - Class contents needs cleaning. 00038 public: 00039 00040 typedef IntRange<IntTy> RangeTy; 00041 00042 struct RangeEx : public RangeTy { 00043 RangeEx() : Weight(1) {} 00044 RangeEx(const RangeTy &R) : RangeTy(R), Weight(1) {} 00045 RangeEx(const RangeTy &R, unsigned W) : RangeTy(R), Weight(W) {} 00046 RangeEx(const IntTy &C) : RangeTy(C), Weight(1) {} 00047 RangeEx(const IntTy &L, const IntTy &H) : RangeTy(L, H), Weight(1) {} 00048 RangeEx(const IntTy &L, const IntTy &H, unsigned W) : 00049 RangeTy(L, H), Weight(W) {} 00050 unsigned Weight; 00051 }; 00052 00053 typedef std::pair<RangeEx, SuccessorClass*> Cluster; 00054 00055 typedef std::list<RangeTy> RangesCollection; 00056 typedef typename RangesCollection::iterator RangesCollectionIt; 00057 typedef typename RangesCollection::const_iterator RangesCollectionConstIt; 00058 typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> self; 00059 00060 protected: 00061 00062 typedef std::list<Cluster> CaseItems; 00063 typedef typename CaseItems::iterator CaseItemIt; 00064 typedef typename CaseItems::const_iterator CaseItemConstIt; 00065 00066 // TODO: Change unclean CRS prefixes to SubsetMap for example. 00067 typedef std::map<SuccessorClass*, RangesCollection > CRSMap; 00068 typedef typename CRSMap::iterator CRSMapIt; 00069 00070 struct ClustersCmp { 00071 bool operator()(const Cluster &C1, const Cluster &C2) { 00072 return C1.first < C2.first; 00073 } 00074 }; 00075 00076 CaseItems Items; 00077 bool Sorted; 00078 00079 bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { 00080 return LItem->first.getHigh() >= RItem->first.getLow(); 00081 } 00082 00083 bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { 00084 if (LItem->second != RItem->second) { 00085 assert(!isIntersected(LItem, RItem) && 00086 "Intersected items with different successors!"); 00087 return false; 00088 } 00089 APInt RLow = RItem->first.getLow(); 00090 if (RLow != APInt::getNullValue(RLow.getBitWidth())) 00091 --RLow; 00092 return LItem->first.getHigh() >= RLow; 00093 } 00094 00095 void sort() { 00096 if (!Sorted) { 00097 std::vector<Cluster> clustersVector; 00098 clustersVector.reserve(Items.size()); 00099 clustersVector.insert(clustersVector.begin(), Items.begin(), Items.end()); 00100 std::sort(clustersVector.begin(), clustersVector.end(), ClustersCmp()); 00101 Items.clear(); 00102 Items.insert(Items.begin(), clustersVector.begin(), clustersVector.end()); 00103 Sorted = true; 00104 } 00105 } 00106 00107 enum DiffProcessState { 00108 L_OPENED, 00109 INTERSECT_OPENED, 00110 R_OPENED, 00111 ALL_IS_CLOSED 00112 }; 00113 00114 class DiffStateMachine { 00115 00116 DiffProcessState State; 00117 IntTy OpenPt; 00118 SuccessorClass *CurrentLSuccessor; 00119 SuccessorClass *CurrentRSuccessor; 00120 00121 self *LeftMapping; 00122 self *IntersectionMapping; 00123 self *RightMapping; 00124 00125 public: 00126 00127 typedef 00128 IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> MappingTy; 00129 00130 DiffStateMachine(MappingTy *L, 00131 MappingTy *Intersection, 00132 MappingTy *R) : 00133 State(ALL_IS_CLOSED), 00134 LeftMapping(L), 00135 IntersectionMapping(Intersection), 00136 RightMapping(R) 00137 {} 00138 00139 void onLOpen(const IntTy &Pt, SuccessorClass *S) { 00140 switch (State) { 00141 case R_OPENED: 00142 if (Pt > OpenPt/*Don't add empty ranges.*/ && RightMapping) 00143 RightMapping->add(OpenPt, Pt-1, CurrentRSuccessor); 00144 State = INTERSECT_OPENED; 00145 break; 00146 case ALL_IS_CLOSED: 00147 State = L_OPENED; 00148 break; 00149 default: 00150 assert(0 && "Got unexpected point."); 00151 break; 00152 } 00153 CurrentLSuccessor = S; 00154 OpenPt = Pt; 00155 } 00156 00157 void onLClose(const IntTy &Pt) { 00158 switch (State) { 00159 case L_OPENED: 00160 assert(Pt >= OpenPt && 00161 "Subset is not sorted or contains overlapped ranges"); 00162 if (LeftMapping) 00163 LeftMapping->add(OpenPt, Pt, CurrentLSuccessor); 00164 State = ALL_IS_CLOSED; 00165 break; 00166 case INTERSECT_OPENED: 00167 if (IntersectionMapping) 00168 IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); 00169 OpenPt = Pt + 1; 00170 State = R_OPENED; 00171 break; 00172 default: 00173 assert(0 && "Got unexpected point."); 00174 break; 00175 } 00176 } 00177 00178 void onROpen(const IntTy &Pt, SuccessorClass *S) { 00179 switch (State) { 00180 case L_OPENED: 00181 if (Pt > OpenPt && LeftMapping) 00182 LeftMapping->add(OpenPt, Pt-1, CurrentLSuccessor); 00183 State = INTERSECT_OPENED; 00184 break; 00185 case ALL_IS_CLOSED: 00186 State = R_OPENED; 00187 break; 00188 default: 00189 assert(0 && "Got unexpected point."); 00190 break; 00191 } 00192 CurrentRSuccessor = S; 00193 OpenPt = Pt; 00194 } 00195 00196 void onRClose(const IntTy &Pt) { 00197 switch (State) { 00198 case R_OPENED: 00199 assert(Pt >= OpenPt && 00200 "Subset is not sorted or contains overlapped ranges"); 00201 if (RightMapping) 00202 RightMapping->add(OpenPt, Pt, CurrentRSuccessor); 00203 State = ALL_IS_CLOSED; 00204 break; 00205 case INTERSECT_OPENED: 00206 if (IntersectionMapping) 00207 IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); 00208 OpenPt = Pt + 1; 00209 State = L_OPENED; 00210 break; 00211 default: 00212 assert(0 && "Got unexpected point."); 00213 break; 00214 } 00215 } 00216 00217 void onLROpen(const IntTy &Pt, 00218 SuccessorClass *LS, 00219 SuccessorClass *RS) { 00220 switch (State) { 00221 case ALL_IS_CLOSED: 00222 State = INTERSECT_OPENED; 00223 break; 00224 default: 00225 assert(0 && "Got unexpected point."); 00226 break; 00227 } 00228 CurrentLSuccessor = LS; 00229 CurrentRSuccessor = RS; 00230 OpenPt = Pt; 00231 } 00232 00233 void onLRClose(const IntTy &Pt) { 00234 switch (State) { 00235 case INTERSECT_OPENED: 00236 if (IntersectionMapping) 00237 IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); 00238 State = ALL_IS_CLOSED; 00239 break; 00240 default: 00241 assert(0 && "Got unexpected point."); 00242 break; 00243 } 00244 } 00245 00246 bool isLOpened() { return State == L_OPENED; } 00247 bool isROpened() { return State == R_OPENED; } 00248 }; 00249 00250 public: 00251 00252 // Don't public CaseItems itself. Don't allow edit the Items directly. 00253 // Just present the user way to iterate over the internal collection 00254 // sharing iterator, begin() and end(). Editing should be controlled by 00255 // factory. 00256 typedef CaseItemIt RangeIterator; 00257 00258 typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; 00259 typedef std::list<Case> Cases; 00260 typedef typename Cases::iterator CasesIt; 00261 00262 IntegersSubsetMapping() { 00263 Sorted = false; 00264 } 00265 00266 bool verify() { 00267 RangeIterator DummyErrItem; 00268 return verify(DummyErrItem); 00269 } 00270 00271 bool verify(RangeIterator& errItem) { 00272 if (Items.empty()) 00273 return true; 00274 sort(); 00275 for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); 00276 j != e; i = j++) { 00277 if (isIntersected(i, j) && i->second != j->second) { 00278 errItem = j; 00279 return false; 00280 } 00281 } 00282 return true; 00283 } 00284 00285 bool isOverlapped(self &RHS) { 00286 if (Items.empty() || RHS.empty()) 00287 return true; 00288 00289 for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), 00290 el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { 00291 00292 const RangeTy &LRange = L->first; 00293 const RangeTy &RRange = R->first; 00294 00295 if (LRange.getLow() > RRange.getLow()) { 00296 if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) 00297 ++R; 00298 else 00299 return true; 00300 } else if (LRange.getLow() < RRange.getLow()) { 00301 if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) 00302 ++L; 00303 else 00304 return true; 00305 } else // iRange.getLow() == jRange.getLow() 00306 return true; 00307 } 00308 return false; 00309 } 00310 00311 00312 void optimize() { 00313 if (Items.size() < 2) 00314 return; 00315 sort(); 00316 CaseItems OldItems = Items; 00317 Items.clear(); 00318 const IntTy *Low = &OldItems.begin()->first.getLow(); 00319 const IntTy *High = &OldItems.begin()->first.getHigh(); 00320 unsigned Weight = OldItems.begin()->first.Weight; 00321 SuccessorClass *Successor = OldItems.begin()->second; 00322 for (CaseItemIt j = OldItems.begin(), i = j++, e = OldItems.end(); 00323 j != e; i = j++) { 00324 if (isJoinable(i, j)) { 00325 const IntTy *CurHigh = &j->first.getHigh(); 00326 Weight += j->first.Weight; 00327 if (*CurHigh > *High) 00328 High = CurHigh; 00329 } else { 00330 RangeEx R(*Low, *High, Weight); 00331 add(R, Successor); 00332 Low = &j->first.getLow(); 00333 High = &j->first.getHigh(); 00334 Weight = j->first.Weight; 00335 Successor = j->second; 00336 } 00337 } 00338 RangeEx R(*Low, *High, Weight); 00339 add(R, Successor); 00340 // We recollected the Items, but we kept it sorted. 00341 Sorted = true; 00342 } 00343 00344 /// Adds a constant value. 00345 void add(const IntTy &C, SuccessorClass *S = 0) { 00346 RangeTy R(C); 00347 add(R, S); 00348 } 00349 00350 /// Adds a range. 00351 void add(const IntTy &Low, const IntTy &High, SuccessorClass *S = 0) { 00352 RangeTy R(Low, High); 00353 add(R, S); 00354 } 00355 void add(const RangeTy &R, SuccessorClass *S = 0) { 00356 RangeEx REx = R; 00357 add(REx, S); 00358 } 00359 void add(const RangeEx &R, SuccessorClass *S = 0) { 00360 Items.push_back(std::make_pair(R, S)); 00361 Sorted = false; 00362 } 00363 00364 /// Adds all ranges and values from given ranges set to the current 00365 /// mapping. 00366 void add(const IntegersSubsetTy &CRS, SuccessorClass *S = 0, 00367 unsigned Weight = 0) { 00368 unsigned ItemWeight = 1; 00369 if (Weight) 00370 // Weight is associated with CRS, for now we perform a division to 00371 // get the weight for each item. 00372 ItemWeight = Weight / CRS.getNumItems(); 00373 for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { 00374 RangeTy R = CRS.getItem(i); 00375 RangeEx REx(R, ItemWeight); 00376 add(REx, S); 00377 } 00378 } 00379 00380 void add(self& RHS) { 00381 Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); 00382 } 00383 00384 void add(self& RHS, SuccessorClass *S) { 00385 for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) 00386 add(i->first, S); 00387 } 00388 00389 void add(const RangesCollection& RHS, SuccessorClass *S = 0) { 00390 for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) 00391 add(*i, S); 00392 } 00393 00394 /// Removes items from set. 00395 void removeItem(RangeIterator i) { Items.erase(i); } 00396 00397 /// Moves whole case from current mapping to the NewMapping object. 00398 void detachCase(self& NewMapping, SuccessorClass *Succ) { 00399 for (CaseItemIt i = Items.begin(); i != Items.end();) 00400 if (i->second == Succ) { 00401 NewMapping.add(i->first, i->second); 00402 Items.erase(i++); 00403 } else 00404 ++i; 00405 } 00406 00407 /// Removes all clusters for given successor. 00408 void removeCase(SuccessorClass *Succ) { 00409 for (CaseItemIt i = Items.begin(); i != Items.end();) 00410 if (i->second == Succ) { 00411 Items.erase(i++); 00412 } else 00413 ++i; 00414 } 00415 00416 /// Find successor that satisfies given value. 00417 SuccessorClass *findSuccessor(const IntTy& Val) { 00418 for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { 00419 if (i->first.isInRange(Val)) 00420 return i->second; 00421 } 00422 return 0; 00423 } 00424 00425 /// Calculates the difference between this mapping and RHS. 00426 /// THIS without RHS is placed into LExclude, 00427 /// RHS without THIS is placed into RExclude, 00428 /// THIS intersect RHS is placed into Intersection. 00429 void diff(self *LExclude, self *Intersection, self *RExclude, 00430 const self& RHS) { 00431 00432 DiffStateMachine Machine(LExclude, Intersection, RExclude); 00433 00434 CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); 00435 while (L != Items.end() && R != RHS.Items.end()) { 00436 const Cluster &LCluster = *L; 00437 const RangeEx &LRange = LCluster.first; 00438 const Cluster &RCluster = *R; 00439 const RangeEx &RRange = RCluster.first; 00440 00441 if (LRange.getHigh() < RRange.getLow()) { 00442 Machine.onLOpen(LRange.getLow(), LCluster.second); 00443 Machine.onLClose(LRange.getHigh()); 00444 ++L; 00445 continue; 00446 } 00447 00448 if (LRange.getLow() > RRange.getHigh()) { 00449 Machine.onROpen(RRange.getLow(), RCluster.second); 00450 Machine.onRClose(RRange.getHigh()); 00451 ++R; 00452 continue; 00453 } 00454 00455 if (LRange.getLow() < RRange.getLow()) { 00456 // May be opened in previous iteration. 00457 if (!Machine.isLOpened()) 00458 Machine.onLOpen(LRange.getLow(), LCluster.second); 00459 Machine.onROpen(RRange.getLow(), RCluster.second); 00460 } 00461 else if (RRange.getLow() < LRange.getLow()) { 00462 if (!Machine.isROpened()) 00463 Machine.onROpen(RRange.getLow(), RCluster.second); 00464 Machine.onLOpen(LRange.getLow(), LCluster.second); 00465 } 00466 else 00467 Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); 00468 00469 if (LRange.getHigh() < RRange.getHigh()) { 00470 Machine.onLClose(LRange.getHigh()); 00471 ++L; 00472 while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { 00473 Machine.onLOpen(L->first.getLow(), L->second); 00474 Machine.onLClose(L->first.getHigh()); 00475 ++L; 00476 } 00477 } 00478 else if (RRange.getHigh() < LRange.getHigh()) { 00479 Machine.onRClose(RRange.getHigh()); 00480 ++R; 00481 while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { 00482 Machine.onROpen(R->first.getLow(), R->second); 00483 Machine.onRClose(R->first.getHigh()); 00484 ++R; 00485 } 00486 } 00487 else { 00488 Machine.onLRClose(LRange.getHigh()); 00489 ++L; 00490 ++R; 00491 } 00492 } 00493 00494 if (L != Items.end()) { 00495 if (Machine.isLOpened()) { 00496 Machine.onLClose(L->first.getHigh()); 00497 ++L; 00498 } 00499 if (LExclude) 00500 while (L != Items.end()) { 00501 LExclude->add(L->first, L->second); 00502 ++L; 00503 } 00504 } else if (R != RHS.Items.end()) { 00505 if (Machine.isROpened()) { 00506 Machine.onRClose(R->first.getHigh()); 00507 ++R; 00508 } 00509 if (RExclude) 00510 while (R != RHS.Items.end()) { 00511 RExclude->add(R->first, R->second); 00512 ++R; 00513 } 00514 } 00515 } 00516 00517 /// Builds the finalized case objects. 00518 void getCases(Cases& TheCases, bool PreventMerging = false) { 00519 //FIXME: PreventMerging is a temporary parameter. 00520 //Currently a set of passes is still knows nothing about 00521 //switches with case ranges, and if these passes meet switch 00522 //with complex case that crashs the application. 00523 if (PreventMerging) { 00524 for (RangeIterator i = this->begin(); i != this->end(); ++i) { 00525 RangesCollection SingleRange; 00526 SingleRange.push_back(i->first); 00527 TheCases.push_back(std::make_pair(i->second, 00528 IntegersSubsetTy(SingleRange))); 00529 } 00530 return; 00531 } 00532 CRSMap TheCRSMap; 00533 for (RangeIterator i = this->begin(); i != this->end(); ++i) 00534 TheCRSMap[i->second].push_back(i->first); 00535 for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) 00536 TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); 00537 } 00538 00539 /// Builds the finalized case objects ignoring successor values, as though 00540 /// all ranges belongs to the same successor. 00541 IntegersSubsetTy getCase() { 00542 RangesCollection Ranges; 00543 for (RangeIterator i = this->begin(); i != this->end(); ++i) 00544 Ranges.push_back(i->first); 00545 return IntegersSubsetTy(Ranges); 00546 } 00547 00548 /// Returns pointer to value of case if it is single-numbered or 0 00549 /// in another case. 00550 const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { 00551 const IntTy* Res = 0; 00552 for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) 00553 if (i->second == Succ) { 00554 if (!i->first.isSingleNumber()) 00555 return 0; 00556 if (Res) 00557 return 0; 00558 else 00559 Res = &(i->first.getLow()); 00560 } 00561 return Res; 00562 } 00563 00564 /// Returns true if there is no ranges and values inside. 00565 bool empty() const { return Items.empty(); } 00566 00567 void clear() { 00568 Items.clear(); 00569 // Don't reset Sorted flag: 00570 // 1. For empty mapping it matters nothing. 00571 // 2. After first item will added Sorted flag will cleared. 00572 } 00573 00574 // Returns number of clusters 00575 unsigned size() const { 00576 return Items.size(); 00577 } 00578 00579 RangeIterator begin() { return Items.begin(); } 00580 RangeIterator end() { return Items.end(); } 00581 }; 00582 00583 class BasicBlock; 00584 typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; 00585 00586 } 00587 00588 #endif /* LLVM_SUPPORT_INTEGERSSUBSETMAPPING_CRSBUILDER_H */