IntegersSubsetMapping.h revision 9ccc83e7f70e63b746cbc7eef9fb06022e758677
1//===- IntegersSubsetMapping.h - Mapping subset ==> Successor ---*- 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/// IntegersSubsetMapping is mapping from A to B, where 12/// Items in A is subsets of integers, 13/// Items in B some pointers (Successors). 14/// If user which to add another subset for successor that is already 15/// exists in mapping, IntegersSubsetMapping merges existing subset with 16/// added one. 17// 18//===----------------------------------------------------------------------===// 19 20#ifndef CRSBUILDER_H_ 21#define CRSBUILDER_H_ 22 23#include "llvm/Support/IntegersSubset.h" 24#include <list> 25#include <map> 26#include <vector> 27 28namespace llvm { 29 30template <class SuccessorClass, 31 class IntegersSubsetTy = IntegersSubset, 32 class IntTy = IntItem> 33class IntegersSubsetMapping { 34 // FIXME: To much similar iterators typedefs, similar names. 35 // - Rename RangeIterator to the cluster iterator. 36 // - Remove unused "add" methods. 37 // - Class contents needs cleaning. 38public: 39 40 typedef IntRange<IntTy> RangeTy; 41 42 struct RangeEx : public RangeTy { 43 RangeEx() : Weight(1) {} 44 RangeEx(const RangeTy &R) : RangeTy(R), Weight(1) {} 45 RangeEx(const IntTy &C) : RangeTy(C), Weight(1) {} 46 RangeEx(const IntTy &L, const IntTy &H) : RangeTy(L, H), Weight(1) {} 47 RangeEx(const IntTy &L, const IntTy &H, unsigned W) : 48 RangeTy(L, H), Weight(W) {} 49 unsigned Weight; 50 }; 51 52 typedef std::pair<RangeEx, SuccessorClass*> Cluster; 53 54 typedef std::list<RangeTy> RangesCollection; 55 typedef typename RangesCollection::iterator RangesCollectionIt; 56 typedef typename RangesCollection::const_iterator RangesCollectionConstIt; 57 typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> self; 58 59protected: 60 61 typedef std::map<RangeEx, SuccessorClass*> CaseItems; 62 typedef typename CaseItems::iterator CaseItemIt; 63 typedef typename CaseItems::const_iterator CaseItemConstIt; 64 65 // TODO: Change unclean CRS prefixes to SubsetMap for example. 66 typedef std::map<SuccessorClass*, RangesCollection > CRSMap; 67 typedef typename CRSMap::iterator CRSMapIt; 68 69 CaseItems Items; 70 bool SingleNumbersOnly; 71 72 bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { 73 return LItem->first.getHigh() >= RItem->first.getLow(); 74 } 75 76 bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { 77 if (LItem->second != RItem->second) { 78 assert(!isIntersected(LItem, RItem) && 79 "Intersected items with different successors!"); 80 return false; 81 } 82 APInt RLow = RItem->first.getLow(); 83 if (RLow != APInt::getNullValue(RLow.getBitWidth())) 84 --RLow; 85 return LItem->first.getHigh() >= RLow; 86 } 87 88 enum DiffProcessState { 89 L_OPENED, 90 INTERSECT_OPENED, 91 R_OPENED, 92 ALL_IS_CLOSED 93 }; 94 95 class DiffStateMachine { 96 97 DiffProcessState State; 98 IntTy OpenPt; 99 SuccessorClass *CurrentLSuccessor; 100 SuccessorClass *CurrentRSuccessor; 101 102 self *LeftMapping; 103 self *IntersectionMapping; 104 self *RightMapping; 105 106 public: 107 108 typedef 109 IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> MappingTy; 110 111 DiffStateMachine(MappingTy *L, 112 MappingTy *Intersection, 113 MappingTy *R) : 114 State(ALL_IS_CLOSED), 115 LeftMapping(L), 116 IntersectionMapping(Intersection), 117 RightMapping(R) 118 {} 119 120 void onLOpen(const IntTy &Pt, SuccessorClass *S) { 121 switch (State) { 122 case R_OPENED: 123 if (Pt > OpenPt/*Don't add empty ranges.*/ && RightMapping) 124 RightMapping->add(OpenPt, Pt-1, CurrentRSuccessor); 125 State = INTERSECT_OPENED; 126 break; 127 case ALL_IS_CLOSED: 128 State = L_OPENED; 129 break; 130 default: 131 assert(0 && "Got unexpected point."); 132 break; 133 } 134 CurrentLSuccessor = S; 135 OpenPt = Pt; 136 } 137 138 void onLClose(const IntTy &Pt) { 139 switch (State) { 140 case L_OPENED: 141 assert(Pt >= OpenPt && 142 "Subset is not sorted or contains overlapped ranges"); 143 if (LeftMapping) 144 LeftMapping->add(OpenPt, Pt, CurrentLSuccessor); 145 State = ALL_IS_CLOSED; 146 break; 147 case INTERSECT_OPENED: 148 if (IntersectionMapping) 149 IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); 150 OpenPt = Pt + 1; 151 State = R_OPENED; 152 break; 153 default: 154 assert(0 && "Got unexpected point."); 155 break; 156 } 157 } 158 159 void onROpen(const IntTy &Pt, SuccessorClass *S) { 160 switch (State) { 161 case L_OPENED: 162 if (Pt > OpenPt && LeftMapping) 163 LeftMapping->add(OpenPt, Pt-1, CurrentLSuccessor); 164 State = INTERSECT_OPENED; 165 break; 166 case ALL_IS_CLOSED: 167 State = R_OPENED; 168 break; 169 default: 170 assert(0 && "Got unexpected point."); 171 break; 172 } 173 CurrentRSuccessor = S; 174 OpenPt = Pt; 175 } 176 177 void onRClose(const IntTy &Pt) { 178 switch (State) { 179 case R_OPENED: 180 assert(Pt >= OpenPt && 181 "Subset is not sorted or contains overlapped ranges"); 182 if (RightMapping) 183 RightMapping->add(OpenPt, Pt, CurrentRSuccessor); 184 State = ALL_IS_CLOSED; 185 break; 186 case INTERSECT_OPENED: 187 if (IntersectionMapping) 188 IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); 189 OpenPt = Pt + 1; 190 State = L_OPENED; 191 break; 192 default: 193 assert(0 && "Got unexpected point."); 194 break; 195 } 196 } 197 198 void onLROpen(const IntTy &Pt, 199 SuccessorClass *LS, 200 SuccessorClass *RS) { 201 switch (State) { 202 case ALL_IS_CLOSED: 203 State = INTERSECT_OPENED; 204 break; 205 default: 206 assert(0 && "Got unexpected point."); 207 break; 208 } 209 CurrentLSuccessor = LS; 210 CurrentRSuccessor = RS; 211 OpenPt = Pt; 212 } 213 214 void onLRClose(const IntTy &Pt) { 215 switch (State) { 216 case INTERSECT_OPENED: 217 if (IntersectionMapping) 218 IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); 219 State = ALL_IS_CLOSED; 220 break; 221 default: 222 assert(0 && "Got unexpected point."); 223 break; 224 } 225 } 226 227 bool isLOpened() { return State == L_OPENED; } 228 bool isROpened() { return State == R_OPENED; } 229 }; 230 231 void diff_single_numbers(self *LExclude, self *Intersection, self *RExclude, 232 const self& RHS) { 233 234 CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); 235 CaseItemConstIt el = Items.end(), er = RHS.Items.end(); 236 while (L != el && R != er) { 237 const Cluster &LCluster = *L; 238 const RangeEx &LRange = LCluster.first; 239 const Cluster &RCluster = *R; 240 const RangeEx &RRange = RCluster.first; 241 242 if (LRange.getLow() < RRange.getLow()) { 243 if (LExclude) 244 LExclude->add(LRange.getLow(), LCluster.second); 245 ++L; 246 } else if (LRange.getLow() > RRange.getLow()) { 247 if (RExclude) 248 RExclude->add(RRange.getLow(), RCluster.second); 249 ++R; 250 } else { 251 if (Intersection) 252 Intersection->add(LRange.getLow(), LCluster.second); 253 ++L; 254 ++R; 255 } 256 } 257 258 if (L != Items.end()) { 259 if (LExclude) 260 do { 261 LExclude->add(L->first, L->second); 262 ++L; 263 } while (L != Items.end()); 264 } else if (R != RHS.Items.end()) { 265 if (RExclude) 266 do { 267 RExclude->add(R->first, R->second); 268 ++R; 269 } while (R != RHS.Items.end()); 270 } 271 } 272 273public: 274 275 // Don't public CaseItems itself. Don't allow edit the Items directly. 276 // Just present the user way to iterate over the internal collection 277 // sharing iterator, begin() and end(). Editing should be controlled by 278 // factory. 279 typedef CaseItemIt RangeIterator; 280 281 typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; 282 typedef std::list<Case> Cases; 283 typedef typename Cases::iterator CasesIt; 284 285 IntegersSubsetMapping() : SingleNumbersOnly(true) {} 286 287 bool verify() { 288 RangeIterator DummyErrItem; 289 return verify(DummyErrItem); 290 } 291 292 bool verify(RangeIterator& errItem) { 293 if (Items.empty()) 294 return true; 295 for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); 296 j != e; i = j++) { 297 if (isIntersected(i, j) && i->second != j->second) { 298 errItem = j; 299 return false; 300 } 301 } 302 return true; 303 } 304 305 bool isOverlapped(self &RHS) { 306 if (Items.empty() || RHS.empty()) 307 return true; 308 309 for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), 310 el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { 311 312 const RangeTy &LRange = L->first; 313 const RangeTy &RRange = R->first; 314 315 if (LRange.getLow() > RRange.getLow()) { 316 if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) 317 ++R; 318 else 319 return true; 320 } else if (LRange.getLow() < RRange.getLow()) { 321 if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) 322 ++L; 323 else 324 return true; 325 } else // iRange.getLow() == jRange.getLow() 326 return true; 327 } 328 return false; 329 } 330 331 332 void optimize() { 333 if (Items.size() < 2) 334 return; 335 CaseItems OldItems = Items; 336 Items.clear(); 337 const IntTy *Low = &OldItems.begin()->first.getLow(); 338 const IntTy *High = &OldItems.begin()->first.getHigh(); 339 unsigned Weight = 1; 340 SuccessorClass *Successor = OldItems.begin()->second; 341 for (CaseItemIt j = OldItems.begin(), i = j++, e = OldItems.end(); 342 j != e; i = j++) { 343 if (isJoinable(i, j)) { 344 const IntTy *CurHigh = &j->first.getHigh(); 345 ++Weight; 346 if (*CurHigh > *High) 347 High = CurHigh; 348 } else { 349 RangeEx R(*Low, *High, Weight); 350 add(R, Successor); 351 Low = &j->first.getLow(); 352 High = &j->first.getHigh(); 353 Weight = 1; 354 Successor = j->second; 355 } 356 } 357 RangeEx R(*Low, *High, Weight); 358 add(R, Successor); 359 } 360 361 /// Adds a constant value. 362 void add(const IntTy &C, SuccessorClass *S = 0) { 363 RangeTy R(C); 364 add(R, S); 365 } 366 367 /// Adds a range. 368 void add(const IntTy &Low, const IntTy &High, SuccessorClass *S = 0) { 369 RangeTy R(Low, High); 370 add(R, S); 371 } 372 void add(const RangeTy &R, SuccessorClass *S = 0) { 373 RangeEx REx = R; 374 add(REx, S); 375 } 376 void add(const RangeEx &R, SuccessorClass *S = 0) { 377 Items.insert(std::make_pair(R, S)); 378 if (!R.isSingleNumber()) 379 SingleNumbersOnly = false; 380 } 381 382 /// Adds all ranges and values from given ranges set to the current 383 /// mapping. 384 void add(const IntegersSubsetTy &CRS, SuccessorClass *S = 0) { 385 for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { 386 RangeTy R = CRS.getItem(i); 387 add(R, S); 388 } 389 } 390 391 void add(self& RHS) { 392 Items.insert(RHS.Items.begin(), RHS.Items.end()); 393 if (!RHS.SingleNumbersOnly) 394 SingleNumbersOnly = false; 395 } 396 397 void add(self& RHS, SuccessorClass *S) { 398 for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) 399 add(i->first, S); 400 } 401 402 void add(const RangesCollection& RHS, SuccessorClass *S = 0) { 403 for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) 404 add(*i, S); 405 } 406 407 /// Removes items from set. 408 void removeItem(RangeIterator i) { Items.erase(i); } 409 410 /// Moves whole case from current mapping to the NewMapping object. 411 void detachCase(self& NewMapping, SuccessorClass *Succ) { 412 for (CaseItemIt i = Items.begin(); i != Items.end();) 413 if (i->second == Succ) { 414 NewMapping.add(i->first, i->second); 415 Items.erase(i++); 416 } else 417 ++i; 418 } 419 420 /// Removes all clusters for given successor. 421 void removeCase(SuccessorClass *Succ) { 422 for (CaseItemIt i = Items.begin(); i != Items.end();) 423 if (i->second == Succ) { 424 Items.erase(i++); 425 } else 426 ++i; 427 } 428 429 /// Find successor that satisfies given value. 430 SuccessorClass *findSuccessor(const IntTy& Val) { 431 for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { 432 if (i->first.isInRange(Val)) 433 return i->second; 434 } 435 return 0; 436 } 437 438 /// Calculates the difference between this mapping and RHS. 439 /// THIS without RHS is placed into LExclude, 440 /// RHS without THIS is placed into RExclude, 441 /// THIS intersect RHS is placed into Intersection. 442 void diff(self *LExclude, self *Intersection, self *RExclude, 443 const self& RHS) { 444 445 if (SingleNumbersOnly && RHS.SingleNumbersOnly) { 446 diff_single_numbers(LExclude, Intersection, RExclude, RHS); 447 return; 448 } 449 450 DiffStateMachine Machine(LExclude, Intersection, RExclude); 451 452 CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); 453 CaseItemConstIt el = Items.end(), er = RHS.Items.end(); 454 while (L != el && R != er) { 455 const Cluster &LCluster = *L; 456 const RangeEx &LRange = LCluster.first; 457 const Cluster &RCluster = *R; 458 const RangeEx &RRange = RCluster.first; 459 460 if (LRange.getHigh() < RRange.getLow()) { 461 Machine.onLOpen(LRange.getLow(), LCluster.second); 462 Machine.onLClose(LRange.getHigh()); 463 ++L; 464 continue; 465 } 466 467 if (LRange.getLow() > RRange.getHigh()) { 468 Machine.onROpen(RRange.getLow(), RCluster.second); 469 Machine.onRClose(RRange.getHigh()); 470 ++R; 471 continue; 472 } 473 474 if (LRange.isSingleNumber() && RRange.isSingleNumber()) { 475 Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); 476 Machine.onLRClose(LRange.getLow()); 477 ++L; 478 ++R; 479 continue; 480 } 481 482 if (LRange.isSingleNumber()) { 483 Machine.onLOpen(LRange.getLow(), LCluster.second); 484 Machine.onLClose(LRange.getLow()); 485 ++L; 486 while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { 487 Machine.onLOpen(LRange.getLow(), LCluster.second); 488 Machine.onLClose(LRange.getLow()); 489 ++L; 490 } 491 continue; 492 } else if (RRange.isSingleNumber()) { 493 Machine.onROpen(R->first.getLow(), R->second); 494 Machine.onRClose(R->first.getHigh()); 495 ++R; 496 while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { 497 Machine.onROpen(R->first.getLow(), R->second); 498 Machine.onRClose(R->first.getHigh()); 499 ++R; 500 } 501 continue; 502 } else 503 if (LRange.getLow() < RRange.getLow()) { 504 // May be opened in previous iteration. 505 if (!Machine.isLOpened()) 506 Machine.onLOpen(LRange.getLow(), LCluster.second); 507 Machine.onROpen(RRange.getLow(), RCluster.second); 508 } 509 else if (RRange.getLow() < LRange.getLow()) { 510 if (!Machine.isROpened()) 511 Machine.onROpen(RRange.getLow(), RCluster.second); 512 Machine.onLOpen(LRange.getLow(), LCluster.second); 513 } 514 else 515 Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); 516 517 if (LRange.getHigh() < RRange.getHigh()) { 518 Machine.onLClose(LRange.getHigh()); 519 ++L; 520 while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { 521 Machine.onLOpen(L->first.getLow(), L->second); 522 Machine.onLClose(L->first.getHigh()); 523 ++L; 524 } 525 } 526 else if (RRange.getHigh() < LRange.getHigh()) { 527 Machine.onRClose(RRange.getHigh()); 528 ++R; 529 while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { 530 Machine.onROpen(R->first.getLow(), R->second); 531 Machine.onRClose(R->first.getHigh()); 532 ++R; 533 } 534 } 535 else { 536 Machine.onLRClose(LRange.getHigh()); 537 ++L; 538 ++R; 539 } 540 } 541 542 if (L != Items.end()) { 543 if (Machine.isLOpened()) { 544 Machine.onLClose(L->first.getHigh()); 545 ++L; 546 } 547 if (LExclude) 548 while (L != Items.end()) { 549 LExclude->add(L->first, L->second); 550 ++L; 551 } 552 } else if (R != RHS.Items.end()) { 553 if (Machine.isROpened()) { 554 Machine.onRClose(R->first.getHigh()); 555 ++R; 556 } 557 if (RExclude) 558 while (R != RHS.Items.end()) { 559 RExclude->add(R->first, R->second); 560 ++R; 561 } 562 } 563 } 564 565 /// Builds the finalized case objects. 566 void getCases(Cases& TheCases, bool PreventMerging = false) { 567 //FIXME: PreventMerging is a temporary parameter. 568 //Currently a set of passes is still knows nothing about 569 //switches with case ranges, and if these passes meet switch 570 //with complex case that crashs the application. 571 if (PreventMerging) { 572 for (RangeIterator i = this->begin(); i != this->end(); ++i) { 573 RangesCollection SingleRange; 574 SingleRange.push_back(i->first); 575 TheCases.push_back(std::make_pair(i->second, 576 IntegersSubsetTy(SingleRange))); 577 } 578 return; 579 } 580 CRSMap TheCRSMap; 581 for (RangeIterator i = this->begin(); i != this->end(); ++i) 582 TheCRSMap[i->second].push_back(i->first); 583 for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) 584 TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); 585 } 586 587 /// Builds the finalized case objects ignoring successor values, as though 588 /// all ranges belongs to the same successor. 589 IntegersSubsetTy getCase() { 590 RangesCollection Ranges; 591 for (RangeIterator i = this->begin(); i != this->end(); ++i) 592 Ranges.push_back(i->first); 593 return IntegersSubsetTy(Ranges); 594 } 595 596 /// Returns pointer to value of case if it is single-numbered or 0 597 /// in another case. 598 const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { 599 const IntTy* Res = 0; 600 for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) 601 if (i->second == Succ) { 602 if (!i->first.isSingleNumber()) 603 return 0; 604 if (Res) 605 return 0; 606 else 607 Res = &(i->first.getLow()); 608 } 609 return Res; 610 } 611 612 /// Returns true if there is no ranges and values inside. 613 bool empty() const { return Items.empty(); } 614 615 void clear() { 616 Items.clear(); 617 // Don't reset Sorted flag: 618 // 1. For empty mapping it matters nothing. 619 // 2. After first item will added Sorted flag will cleared. 620 } 621 622 // Returns number of clusters 623 unsigned size() const { 624 return Items.size(); 625 } 626 627 RangeIterator begin() { return Items.begin(); } 628 RangeIterator end() { return Items.end(); } 629}; 630 631class BasicBlock; 632typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; 633 634} 635 636#endif /* CRSBUILDER_H_ */ 637