LLVM API Documentation

IntegersSubsetMapping.h
Go to the documentation of this file.
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 */