IntRange:

- Changed isSingleNumber method behaviour. Now this flag is calculated on demand.
IntegersSubsetMapping
  - Optimized diff operation.
  - Replaced type of Items field from std::list with std::map.
  - Added new methods:
    bool isOverlapped(self &RHS)
    void add(self& RHS, SuccessorClass *S)
    void detachCase(self& NewMapping, SuccessorClass *Succ)
    void removeCase(SuccessorClass *Succ)
    SuccessorClass *findSuccessor(const IntTy& Val)
    const IntTy* getCaseSingleNumber(SuccessorClass *Succ)
IntegersSubsetTest
  - DiffTest: Added checks for successors.
SimplifyCFG
  Updated SwitchInst usage (now it is case-ragnes compatible) for
    - SimplifyEqualityComparisonWithOnlyPredecessor
    - FoldValueComparisonIntoPredecessors



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159527 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Stepan Dyatkovskiy
2012-07-02 13:02:18 +00:00
parent 4177e6fff5
commit b2833d9dcb
7 changed files with 328 additions and 210 deletions

View File

@ -182,7 +182,12 @@ protected:
IntType Low;
IntType High;
bool IsEmpty : 1;
bool IsSingleNumber : 1;
enum Type {
SINGLE_NUMBER,
RANGE,
UNKNOWN
};
Type RangeType;
public:
typedef IntRange<IntType> self;
@ -191,15 +196,30 @@ public:
IntRange() : IsEmpty(true) {}
IntRange(const self &RHS) :
Low(RHS.Low), High(RHS.High),
IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {}
IsEmpty(RHS.IsEmpty), RangeType(RHS.RangeType) {}
IntRange(const IntType &C) :
Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {}
Low(C), High(C), IsEmpty(false), RangeType(SINGLE_NUMBER) {}
IntRange(const IntType &L, const IntType &H) : Low(L), High(H),
IsEmpty(false), IsSingleNumber(Low == High) {}
IsEmpty(false), RangeType(UNKNOWN) {}
bool isEmpty() const { return IsEmpty; }
bool isSingleNumber() const { return IsSingleNumber; }
bool isSingleNumber() const {
switch (RangeType) {
case SINGLE_NUMBER:
return true;
case RANGE:
return false;
case UNKNOWN:
default:
if (Low == High) {
const_cast<Type&>(RangeType) = SINGLE_NUMBER;
return true;
}
const_cast<Type&>(RangeType) = RANGE;
return false;
}
}
const IntType& getLow() const {
assert(!IsEmpty && "Range is empty.");
@ -213,13 +233,13 @@ public:
bool operator<(const self &RHS) const {
assert(!IsEmpty && "Left range is empty.");
assert(!RHS.IsEmpty && "Right range is empty.");
if (Low < RHS.Low)
return true;
if (Low == RHS.Low) {
if (High > RHS.High)
return true;
return false;
}
if (Low < RHS.Low)
return true;
return false;
}
@ -512,7 +532,7 @@ public:
e = Src.end(); i != e; ++i) {
const Range &R = *i;
std::vector<Constant*> r;
if (R.isSingleNumber()) {
if (!R.isSingleNumber()) {
r.reserve(2);
// FIXME: Since currently we have ConstantInt based numbers
// use hack-conversion of IntItem to ConstantInt

View File

@ -58,22 +58,16 @@ public:
protected:
typedef std::list<Cluster> CaseItems;
typedef std::map<RangeEx, SuccessorClass*> 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 SingleNumbersOnly;
bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
return LItem->first.getHigh() >= RItem->first.getLow();
@ -91,18 +85,6 @@ protected:
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,
@ -213,7 +195,7 @@ protected:
}
}
void onRLOpen(const IntTy &Pt,
void onLROpen(const IntTy &Pt,
SuccessorClass *LS,
SuccessorClass *RS) {
switch (State) {
@ -229,7 +211,7 @@ protected:
OpenPt = Pt;
}
void onRLClose(const IntTy &Pt) {
void onLRClose(const IntTy &Pt) {
switch (State) {
case INTERSECT_OPENED:
if (IntersectionMapping)
@ -245,6 +227,48 @@ protected:
bool isLOpened() { return State == L_OPENED; }
bool isROpened() { return State == R_OPENED; }
};
void diff_single_numbers(self *LExclude, self *Intersection, self *RExclude,
const self& RHS) {
CaseItemConstIt L = Items.begin(), R = RHS.Items.begin();
CaseItemConstIt el = Items.end(), er = RHS.Items.end();
while (L != el && R != er) {
const Cluster &LCluster = *L;
const RangeEx &LRange = LCluster.first;
const Cluster &RCluster = *R;
const RangeEx &RRange = RCluster.first;
if (LRange.getLow() < RRange.getLow()) {
if (LExclude)
LExclude->add(LRange.getLow(), LCluster.second);
++L;
} else if (LRange.getLow() > RRange.getLow()) {
if (RExclude)
RExclude->add(RRange.getLow(), RCluster.second);
++R;
} else {
if (Intersection)
Intersection->add(LRange.getLow(), LCluster.second);
++L;
++R;
}
}
if (L != Items.end()) {
if (LExclude)
do {
LExclude->add(L->first, L->second);
++L;
} while (L != Items.end());
} else if (R != RHS.Items.end()) {
if (RExclude)
do {
RExclude->add(R->first, R->second);
++R;
} while (R != RHS.Items.end());
}
}
public:
@ -256,15 +280,18 @@ public:
typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case;
typedef std::list<Case> Cases;
typedef typename Cases::iterator CasesIt;
IntegersSubsetMapping() {
Sorted = false;
IntegersSubsetMapping() : SingleNumbersOnly(true) {}
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) {
@ -275,10 +302,36 @@ public:
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();
@ -303,8 +356,6 @@ public:
}
RangeEx R(*Low, *High, Weight);
add(R, Successor);
// We recollected the Items, but we kept it sorted.
Sorted = true;
}
/// Adds a constant value.
@ -323,8 +374,10 @@ public:
add(REx, S);
}
void add(const RangeEx &R, SuccessorClass *S = 0) {
Items.push_back(std::make_pair(R, S));
Sorted = false;
//Items.push_back(std::make_pair(R, S));
Items.insert(std::make_pair(R, S));
if (!R.isSingleNumber())
SingleNumbersOnly = false;
}
/// Adds all ranges and values from given ranges set to the current
@ -337,9 +390,17 @@ public:
}
void add(self& RHS) {
Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end());
//Items.insert(Items.begin(), RHS.Items.begin(), RHS.Items.end());
Items.insert(RHS.Items.begin(), RHS.Items.end());
if (!RHS.SingleNumbersOnly)
SingleNumbersOnly = false;
}
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);
@ -348,6 +409,34 @@ public:
/// 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,
@ -355,10 +444,16 @@ public:
void diff(self *LExclude, self *Intersection, self *RExclude,
const self& RHS) {
if (SingleNumbersOnly && RHS.SingleNumbersOnly) {
diff_single_numbers(LExclude, Intersection, RExclude, RHS);
return;
}
DiffStateMachine Machine(LExclude, Intersection, RExclude);
CaseItemConstIt L = Items.begin(), R = RHS.Items.begin();
while (L != Items.end() && R != RHS.Items.end()) {
CaseItemConstIt el = Items.end(), er = RHS.Items.end();
while (L != el && R != er) {
const Cluster &LCluster = *L;
const RangeEx &LRange = LCluster.first;
const Cluster &RCluster = *R;
@ -377,7 +472,36 @@ public:
++R;
continue;
}
if (LRange.isSingleNumber() && RRange.isSingleNumber()) {
Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second);
Machine.onLRClose(LRange.getLow());
++L;
++R;
continue;
}
if (LRange.isSingleNumber()) {
Machine.onLOpen(LRange.getLow(), LCluster.second);
Machine.onLClose(LRange.getLow());
++L;
while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) {
Machine.onLOpen(LRange.getLow(), LCluster.second);
Machine.onLClose(LRange.getLow());
++L;
}
continue;
} else if (RRange.isSingleNumber()) {
Machine.onROpen(R->first.getLow(), R->second);
Machine.onRClose(R->first.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;
}
continue;
} else
if (LRange.getLow() < RRange.getLow()) {
// May be opened in previous iteration.
if (!Machine.isLOpened())
@ -390,7 +514,7 @@ public:
Machine.onLOpen(LRange.getLow(), LCluster.second);
}
else
Machine.onRLOpen(LRange.getLow(), LCluster.second, RCluster.second);
Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second);
if (LRange.getHigh() < RRange.getHigh()) {
Machine.onLClose(LRange.getHigh());
@ -411,7 +535,7 @@ public:
}
}
else {
Machine.onRLClose(LRange.getHigh());
Machine.onLRClose(LRange.getHigh());
++L;
++R;
}
@ -441,7 +565,20 @@ public:
}
/// Builds the finalized case objects.
void getCases(Cases& TheCases) {
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);
@ -458,6 +595,22 @@ public:
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(); }