|
|
//===- IntegersSubsetMapping.h - Mapping subset ==> Successor ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// @file
/// IntegersSubsetMapping is mapping from A to B, where
/// Items in A is subsets of integers,
/// Items in B some pointers (Successors).
/// If user which to add another subset for successor that is already
/// exists in mapping, IntegersSubsetMapping merges existing subset with
/// added one.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H
#define LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H
#include "llvm/Support/IntegersSubset.h"
#include <list>
#include <map>
#include <vector>
namespace llvm {
template <class SuccessorClass, class IntegersSubsetTy = IntegersSubset, class IntTy = IntItem> class IntegersSubsetMapping { // FIXME: To much similar iterators typedefs, similar names.
// - Rename RangeIterator to the cluster iterator.
// - Remove unused "add" methods.
// - Class contents needs cleaning.
public: typedef IntRange<IntTy> RangeTy; struct RangeEx : public RangeTy { RangeEx() : Weight(1) {} RangeEx(const RangeTy &R) : RangeTy(R), Weight(1) {} RangeEx(const RangeTy &R, unsigned W) : RangeTy(R), Weight(W) {} RangeEx(const IntTy &C) : RangeTy(C), Weight(1) {} RangeEx(const IntTy &L, const IntTy &H) : RangeTy(L, H), Weight(1) {} RangeEx(const IntTy &L, const IntTy &H, unsigned W) : RangeTy(L, H), Weight(W) {} unsigned Weight; };
typedef std::pair<RangeEx, SuccessorClass*> Cluster;
typedef std::list<RangeTy> RangesCollection; typedef typename RangesCollection::iterator RangesCollectionIt; typedef typename RangesCollection::const_iterator RangesCollectionConstIt; typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> self; protected:
typedef std::list<Cluster> CaseItems; typedef typename CaseItems::iterator CaseItemIt; typedef typename CaseItems::const_iterator CaseItemConstIt; // TODO: Change unclean CRS prefixes to SubsetMap for example.
typedef std::map<SuccessorClass*, RangesCollection > CRSMap; typedef typename CRSMap::iterator CRSMapIt;
struct ClustersCmp { bool operator()(const Cluster &C1, const Cluster &C2) { return C1.first < C2.first; } }; CaseItems Items; bool Sorted; bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { return LItem->first.getHigh() >= RItem->first.getLow(); }
bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { if (LItem->second != RItem->second) { assert(!isIntersected(LItem, RItem) && "Intersected items with different successors!"); return false; } APInt RLow = RItem->first.getLow(); if (RLow != APInt::getNullValue(RLow.getBitWidth())) --RLow; return LItem->first.getHigh() >= RLow; } void sort() { if (!Sorted) { std::vector<Cluster> clustersVector; clustersVector.reserve(Items.size()); clustersVector.insert(clustersVector.begin(), Items.begin(), Items.end()); std::sort(clustersVector.begin(), clustersVector.end(), ClustersCmp()); Items.clear(); Items.insert(Items.begin(), clustersVector.begin(), clustersVector.end()); Sorted = true; } } enum DiffProcessState { L_OPENED, INTERSECT_OPENED, R_OPENED, ALL_IS_CLOSED }; class DiffStateMachine { DiffProcessState State; IntTy OpenPt; SuccessorClass *CurrentLSuccessor; SuccessorClass *CurrentRSuccessor; self *LeftMapping; self *IntersectionMapping; self *RightMapping;
public: typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> MappingTy; DiffStateMachine(MappingTy *L, MappingTy *Intersection, MappingTy *R) : State(ALL_IS_CLOSED), LeftMapping(L), IntersectionMapping(Intersection), RightMapping(R) {} void onLOpen(const IntTy &Pt, SuccessorClass *S) { switch (State) { case R_OPENED: if (Pt > OpenPt/*Don't add empty ranges.*/ && RightMapping) RightMapping->add(OpenPt, Pt-1, CurrentRSuccessor); State = INTERSECT_OPENED; break; case ALL_IS_CLOSED: State = L_OPENED; break; default: assert(0 && "Got unexpected point."); break; } CurrentLSuccessor = S; OpenPt = Pt; } void onLClose(const IntTy &Pt) { switch (State) { case L_OPENED: assert(Pt >= OpenPt && "Subset is not sorted or contains overlapped ranges"); if (LeftMapping) LeftMapping->add(OpenPt, Pt, CurrentLSuccessor); State = ALL_IS_CLOSED; break; case INTERSECT_OPENED: if (IntersectionMapping) IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); OpenPt = Pt + 1; State = R_OPENED; break; default: assert(0 && "Got unexpected point."); break; } } void onROpen(const IntTy &Pt, SuccessorClass *S) { switch (State) { case L_OPENED: if (Pt > OpenPt && LeftMapping) LeftMapping->add(OpenPt, Pt-1, CurrentLSuccessor); State = INTERSECT_OPENED; break; case ALL_IS_CLOSED: State = R_OPENED; break; default: assert(0 && "Got unexpected point."); break; } CurrentRSuccessor = S; OpenPt = Pt; } void onRClose(const IntTy &Pt) { switch (State) { case R_OPENED: assert(Pt >= OpenPt && "Subset is not sorted or contains overlapped ranges"); if (RightMapping) RightMapping->add(OpenPt, Pt, CurrentRSuccessor); State = ALL_IS_CLOSED; break; case INTERSECT_OPENED: if (IntersectionMapping) IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); OpenPt = Pt + 1; State = L_OPENED; break; default: assert(0 && "Got unexpected point."); break; } } void onLROpen(const IntTy &Pt, SuccessorClass *LS, SuccessorClass *RS) { switch (State) { case ALL_IS_CLOSED: State = INTERSECT_OPENED; break; default: assert(0 && "Got unexpected point."); break; } CurrentLSuccessor = LS; CurrentRSuccessor = RS; OpenPt = Pt; } void onLRClose(const IntTy &Pt) { switch (State) { case INTERSECT_OPENED: if (IntersectionMapping) IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); State = ALL_IS_CLOSED; break; default: assert(0 && "Got unexpected point."); break; } } bool isLOpened() { return State == L_OPENED; } bool isROpened() { return State == R_OPENED; } };
public: // Don't public CaseItems itself. Don't allow edit the Items directly.
// Just present the user way to iterate over the internal collection
// sharing iterator, begin() and end(). Editing should be controlled by
// factory.
typedef CaseItemIt RangeIterator; typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; typedef std::list<Case> Cases; typedef typename Cases::iterator CasesIt; IntegersSubsetMapping() { Sorted = false; } bool verify() { RangeIterator DummyErrItem; return verify(DummyErrItem); } bool verify(RangeIterator& errItem) { if (Items.empty()) return true; sort(); for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); j != e; i = j++) { if (isIntersected(i, j) && i->second != j->second) { errItem = j; return false; } } return true; }
bool isOverlapped(self &RHS) { if (Items.empty() || RHS.empty()) return true; for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { const RangeTy &LRange = L->first; const RangeTy &RRange = R->first; if (LRange.getLow() > RRange.getLow()) { if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) ++R; else return true; } else if (LRange.getLow() < RRange.getLow()) { if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) ++L; else return true; } else // iRange.getLow() == jRange.getLow()
return true; } return false; } void optimize() { if (Items.size() < 2) return; sort(); CaseItems OldItems = Items; Items.clear(); const IntTy *Low = &OldItems.begin()->first.getLow(); const IntTy *High = &OldItems.begin()->first.getHigh(); unsigned Weight = OldItems.begin()->first.Weight; SuccessorClass *Successor = OldItems.begin()->second; for (CaseItemIt j = OldItems.begin(), i = j++, e = OldItems.end(); j != e; i = j++) { if (isJoinable(i, j)) { const IntTy *CurHigh = &j->first.getHigh(); Weight += j->first.Weight; if (*CurHigh > *High) High = CurHigh; } else { RangeEx R(*Low, *High, Weight); add(R, Successor); Low = &j->first.getLow(); High = &j->first.getHigh(); Weight = j->first.Weight; Successor = j->second; } } RangeEx R(*Low, *High, Weight); add(R, Successor); // We recollected the Items, but we kept it sorted.
Sorted = true; } /// Adds a constant value.
void add(const IntTy &C, SuccessorClass *S = 0) { RangeTy R(C); add(R, S); } /// Adds a range.
void add(const IntTy &Low, const IntTy &High, SuccessorClass *S = 0) { RangeTy R(Low, High); add(R, S); } void add(const RangeTy &R, SuccessorClass *S = 0) { RangeEx REx = R; add(REx, S); } void add(const RangeEx &R, SuccessorClass *S = 0) { Items.push_back(std::make_pair(R, S)); Sorted = false; } /// Adds all ranges and values from given ranges set to the current
/// mapping.
void add(const IntegersSubsetTy &CRS, SuccessorClass *S = 0, unsigned Weight = 0) { unsigned ItemWeight = 1; if (Weight) // Weight is associated with CRS, for now we perform a division to
// get the weight for each item.
ItemWeight = Weight / CRS.getNumItems(); for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { RangeTy R = CRS.getItem(i); RangeEx REx(R, ItemWeight); add(REx, S); } } void add(self& RHS) { Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); } void add(self& RHS, SuccessorClass *S) { for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) add(i->first, S); } void add(const RangesCollection& RHS, SuccessorClass *S = 0) { for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) add(*i, S); } /// Removes items from set.
void removeItem(RangeIterator i) { Items.erase(i); } /// Moves whole case from current mapping to the NewMapping object.
void detachCase(self& NewMapping, SuccessorClass *Succ) { for (CaseItemIt i = Items.begin(); i != Items.end();) if (i->second == Succ) { NewMapping.add(i->first, i->second); Items.erase(i++); } else ++i; } /// Removes all clusters for given successor.
void removeCase(SuccessorClass *Succ) { for (CaseItemIt i = Items.begin(); i != Items.end();) if (i->second == Succ) { Items.erase(i++); } else ++i; } /// Find successor that satisfies given value.
SuccessorClass *findSuccessor(const IntTy& Val) { for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { if (i->first.isInRange(Val)) return i->second; } return 0; } /// Calculates the difference between this mapping and RHS.
/// THIS without RHS is placed into LExclude,
/// RHS without THIS is placed into RExclude,
/// THIS intersect RHS is placed into Intersection.
void diff(self *LExclude, self *Intersection, self *RExclude, const self& RHS) { DiffStateMachine Machine(LExclude, Intersection, RExclude); CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); while (L != Items.end() && R != RHS.Items.end()) { const Cluster &LCluster = *L; const RangeEx &LRange = LCluster.first; const Cluster &RCluster = *R; const RangeEx &RRange = RCluster.first; if (LRange.getHigh() < RRange.getLow()) { Machine.onLOpen(LRange.getLow(), LCluster.second); Machine.onLClose(LRange.getHigh()); ++L; continue; } if (LRange.getLow() > RRange.getHigh()) { Machine.onROpen(RRange.getLow(), RCluster.second); Machine.onRClose(RRange.getHigh()); ++R; continue; }
if (LRange.getLow() < RRange.getLow()) { // May be opened in previous iteration.
if (!Machine.isLOpened()) Machine.onLOpen(LRange.getLow(), LCluster.second); Machine.onROpen(RRange.getLow(), RCluster.second); } else if (RRange.getLow() < LRange.getLow()) { if (!Machine.isROpened()) Machine.onROpen(RRange.getLow(), RCluster.second); Machine.onLOpen(LRange.getLow(), LCluster.second); } else Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); if (LRange.getHigh() < RRange.getHigh()) { Machine.onLClose(LRange.getHigh()); ++L; while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { Machine.onLOpen(L->first.getLow(), L->second); Machine.onLClose(L->first.getHigh()); ++L; } } else if (RRange.getHigh() < LRange.getHigh()) { Machine.onRClose(RRange.getHigh()); ++R; while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { Machine.onROpen(R->first.getLow(), R->second); Machine.onRClose(R->first.getHigh()); ++R; } } else { Machine.onLRClose(LRange.getHigh()); ++L; ++R; } } if (L != Items.end()) { if (Machine.isLOpened()) { Machine.onLClose(L->first.getHigh()); ++L; } if (LExclude) while (L != Items.end()) { LExclude->add(L->first, L->second); ++L; } } else if (R != RHS.Items.end()) { if (Machine.isROpened()) { Machine.onRClose(R->first.getHigh()); ++R; } if (RExclude) while (R != RHS.Items.end()) { RExclude->add(R->first, R->second); ++R; } } } /// Builds the finalized case objects.
void getCases(Cases& TheCases, bool PreventMerging = false) { //FIXME: PreventMerging is a temporary parameter.
//Currently a set of passes is still knows nothing about
//switches with case ranges, and if these passes meet switch
//with complex case that crashs the application.
if (PreventMerging) { for (RangeIterator i = this->begin(); i != this->end(); ++i) { RangesCollection SingleRange; SingleRange.push_back(i->first); TheCases.push_back(std::make_pair(i->second, IntegersSubsetTy(SingleRange))); } return; } CRSMap TheCRSMap; for (RangeIterator i = this->begin(); i != this->end(); ++i) TheCRSMap[i->second].push_back(i->first); for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); } /// Builds the finalized case objects ignoring successor values, as though
/// all ranges belongs to the same successor.
IntegersSubsetTy getCase() { RangesCollection Ranges; for (RangeIterator i = this->begin(); i != this->end(); ++i) Ranges.push_back(i->first); return IntegersSubsetTy(Ranges); } /// Returns pointer to value of case if it is single-numbered or 0
/// in another case.
const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { const IntTy* Res = 0; for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) if (i->second == Succ) { if (!i->first.isSingleNumber()) return 0; if (Res) return 0; else Res = &(i->first.getLow()); } return Res; } /// Returns true if there is no ranges and values inside.
bool empty() const { return Items.empty(); } void clear() { Items.clear(); // Don't reset Sorted flag:
// 1. For empty mapping it matters nothing.
// 2. After first item will added Sorted flag will cleared.
} // Returns number of clusters
unsigned size() const { return Items.size(); } RangeIterator begin() { return Items.begin(); } RangeIterator end() { return Items.end(); } };
class BasicBlock; typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB;
}
#endif /* LLVM_SUPPORT_INTEGERSSUBSETMAPPING_CRSBUILDER_H */
|