mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-15 19:24:33 +00:00
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:
@@ -182,7 +182,12 @@ protected:
|
|||||||
IntType Low;
|
IntType Low;
|
||||||
IntType High;
|
IntType High;
|
||||||
bool IsEmpty : 1;
|
bool IsEmpty : 1;
|
||||||
bool IsSingleNumber : 1;
|
enum Type {
|
||||||
|
SINGLE_NUMBER,
|
||||||
|
RANGE,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
Type RangeType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef IntRange<IntType> self;
|
typedef IntRange<IntType> self;
|
||||||
@@ -191,15 +196,30 @@ public:
|
|||||||
IntRange() : IsEmpty(true) {}
|
IntRange() : IsEmpty(true) {}
|
||||||
IntRange(const self &RHS) :
|
IntRange(const self &RHS) :
|
||||||
Low(RHS.Low), High(RHS.High),
|
Low(RHS.Low), High(RHS.High),
|
||||||
IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {}
|
IsEmpty(RHS.IsEmpty), RangeType(RHS.RangeType) {}
|
||||||
IntRange(const IntType &C) :
|
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),
|
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 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 {
|
const IntType& getLow() const {
|
||||||
assert(!IsEmpty && "Range is empty.");
|
assert(!IsEmpty && "Range is empty.");
|
||||||
@@ -213,13 +233,13 @@ public:
|
|||||||
bool operator<(const self &RHS) const {
|
bool operator<(const self &RHS) const {
|
||||||
assert(!IsEmpty && "Left range is empty.");
|
assert(!IsEmpty && "Left range is empty.");
|
||||||
assert(!RHS.IsEmpty && "Right range is empty.");
|
assert(!RHS.IsEmpty && "Right range is empty.");
|
||||||
|
if (Low < RHS.Low)
|
||||||
|
return true;
|
||||||
if (Low == RHS.Low) {
|
if (Low == RHS.Low) {
|
||||||
if (High > RHS.High)
|
if (High > RHS.High)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Low < RHS.Low)
|
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,7 +532,7 @@ public:
|
|||||||
e = Src.end(); i != e; ++i) {
|
e = Src.end(); i != e; ++i) {
|
||||||
const Range &R = *i;
|
const Range &R = *i;
|
||||||
std::vector<Constant*> r;
|
std::vector<Constant*> r;
|
||||||
if (R.isSingleNumber()) {
|
if (!R.isSingleNumber()) {
|
||||||
r.reserve(2);
|
r.reserve(2);
|
||||||
// FIXME: Since currently we have ConstantInt based numbers
|
// FIXME: Since currently we have ConstantInt based numbers
|
||||||
// use hack-conversion of IntItem to ConstantInt
|
// use hack-conversion of IntItem to ConstantInt
|
||||||
|
@@ -58,22 +58,16 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::list<Cluster> CaseItems;
|
typedef std::map<RangeEx, SuccessorClass*> CaseItems;
|
||||||
typedef typename CaseItems::iterator CaseItemIt;
|
typedef typename CaseItems::iterator CaseItemIt;
|
||||||
typedef typename CaseItems::const_iterator CaseItemConstIt;
|
typedef typename CaseItems::const_iterator CaseItemConstIt;
|
||||||
|
|
||||||
// TODO: Change unclean CRS prefixes to SubsetMap for example.
|
// TODO: Change unclean CRS prefixes to SubsetMap for example.
|
||||||
typedef std::map<SuccessorClass*, RangesCollection > CRSMap;
|
typedef std::map<SuccessorClass*, RangesCollection > CRSMap;
|
||||||
typedef typename CRSMap::iterator CRSMapIt;
|
typedef typename CRSMap::iterator CRSMapIt;
|
||||||
|
|
||||||
struct ClustersCmp {
|
|
||||||
bool operator()(const Cluster &C1, const Cluster &C2) {
|
|
||||||
return C1.first < C2.first;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CaseItems Items;
|
CaseItems Items;
|
||||||
bool Sorted;
|
bool SingleNumbersOnly;
|
||||||
|
|
||||||
bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
|
bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) {
|
||||||
return LItem->first.getHigh() >= RItem->first.getLow();
|
return LItem->first.getHigh() >= RItem->first.getLow();
|
||||||
@@ -91,18 +85,6 @@ protected:
|
|||||||
return LItem->first.getHigh() >= 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 {
|
enum DiffProcessState {
|
||||||
L_OPENED,
|
L_OPENED,
|
||||||
INTERSECT_OPENED,
|
INTERSECT_OPENED,
|
||||||
@@ -213,7 +195,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRLOpen(const IntTy &Pt,
|
void onLROpen(const IntTy &Pt,
|
||||||
SuccessorClass *LS,
|
SuccessorClass *LS,
|
||||||
SuccessorClass *RS) {
|
SuccessorClass *RS) {
|
||||||
switch (State) {
|
switch (State) {
|
||||||
@@ -229,7 +211,7 @@ protected:
|
|||||||
OpenPt = Pt;
|
OpenPt = Pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRLClose(const IntTy &Pt) {
|
void onLRClose(const IntTy &Pt) {
|
||||||
switch (State) {
|
switch (State) {
|
||||||
case INTERSECT_OPENED:
|
case INTERSECT_OPENED:
|
||||||
if (IntersectionMapping)
|
if (IntersectionMapping)
|
||||||
@@ -245,6 +227,48 @@ protected:
|
|||||||
bool isLOpened() { return State == L_OPENED; }
|
bool isLOpened() { return State == L_OPENED; }
|
||||||
bool isROpened() { return State == R_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:
|
public:
|
||||||
|
|
||||||
@@ -256,15 +280,18 @@ public:
|
|||||||
|
|
||||||
typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case;
|
typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case;
|
||||||
typedef std::list<Case> Cases;
|
typedef std::list<Case> Cases;
|
||||||
|
typedef typename Cases::iterator CasesIt;
|
||||||
|
|
||||||
IntegersSubsetMapping() {
|
IntegersSubsetMapping() : SingleNumbersOnly(true) {}
|
||||||
Sorted = false;
|
|
||||||
|
bool verify() {
|
||||||
|
RangeIterator DummyErrItem;
|
||||||
|
return verify(DummyErrItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verify(RangeIterator& errItem) {
|
bool verify(RangeIterator& errItem) {
|
||||||
if (Items.empty())
|
if (Items.empty())
|
||||||
return true;
|
return true;
|
||||||
sort();
|
|
||||||
for (CaseItemIt j = Items.begin(), i = j++, e = Items.end();
|
for (CaseItemIt j = Items.begin(), i = j++, e = Items.end();
|
||||||
j != e; i = j++) {
|
j != e; i = j++) {
|
||||||
if (isIntersected(i, j) && i->second != j->second) {
|
if (isIntersected(i, j) && i->second != j->second) {
|
||||||
@@ -275,10 +302,36 @@ public:
|
|||||||
return true;
|
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() {
|
void optimize() {
|
||||||
if (Items.size() < 2)
|
if (Items.size() < 2)
|
||||||
return;
|
return;
|
||||||
sort();
|
|
||||||
CaseItems OldItems = Items;
|
CaseItems OldItems = Items;
|
||||||
Items.clear();
|
Items.clear();
|
||||||
const IntTy *Low = &OldItems.begin()->first.getLow();
|
const IntTy *Low = &OldItems.begin()->first.getLow();
|
||||||
@@ -303,8 +356,6 @@ public:
|
|||||||
}
|
}
|
||||||
RangeEx R(*Low, *High, Weight);
|
RangeEx R(*Low, *High, Weight);
|
||||||
add(R, Successor);
|
add(R, Successor);
|
||||||
// We recollected the Items, but we kept it sorted.
|
|
||||||
Sorted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a constant value.
|
/// Adds a constant value.
|
||||||
@@ -323,8 +374,10 @@ public:
|
|||||||
add(REx, S);
|
add(REx, S);
|
||||||
}
|
}
|
||||||
void add(const RangeEx &R, SuccessorClass *S = 0) {
|
void add(const RangeEx &R, SuccessorClass *S = 0) {
|
||||||
Items.push_back(std::make_pair(R, S));
|
//Items.push_back(std::make_pair(R, S));
|
||||||
Sorted = false;
|
Items.insert(std::make_pair(R, S));
|
||||||
|
if (!R.isSingleNumber())
|
||||||
|
SingleNumbersOnly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds all ranges and values from given ranges set to the current
|
/// Adds all ranges and values from given ranges set to the current
|
||||||
@@ -337,9 +390,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add(self& RHS) {
|
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) {
|
void add(const RangesCollection& RHS, SuccessorClass *S = 0) {
|
||||||
for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i)
|
for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i)
|
||||||
add(*i, S);
|
add(*i, S);
|
||||||
@@ -348,6 +409,34 @@ public:
|
|||||||
/// Removes items from set.
|
/// Removes items from set.
|
||||||
void removeItem(RangeIterator i) { Items.erase(i); }
|
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.
|
/// Calculates the difference between this mapping and RHS.
|
||||||
/// THIS without RHS is placed into LExclude,
|
/// THIS without RHS is placed into LExclude,
|
||||||
/// RHS without THIS is placed into RExclude,
|
/// RHS without THIS is placed into RExclude,
|
||||||
@@ -355,10 +444,16 @@ public:
|
|||||||
void diff(self *LExclude, self *Intersection, self *RExclude,
|
void diff(self *LExclude, self *Intersection, self *RExclude,
|
||||||
const self& RHS) {
|
const self& RHS) {
|
||||||
|
|
||||||
|
if (SingleNumbersOnly && RHS.SingleNumbersOnly) {
|
||||||
|
diff_single_numbers(LExclude, Intersection, RExclude, RHS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DiffStateMachine Machine(LExclude, Intersection, RExclude);
|
DiffStateMachine Machine(LExclude, Intersection, RExclude);
|
||||||
|
|
||||||
CaseItemConstIt L = Items.begin(), R = RHS.Items.begin();
|
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 Cluster &LCluster = *L;
|
||||||
const RangeEx &LRange = LCluster.first;
|
const RangeEx &LRange = LCluster.first;
|
||||||
const Cluster &RCluster = *R;
|
const Cluster &RCluster = *R;
|
||||||
@@ -377,7 +472,36 @@ public:
|
|||||||
++R;
|
++R;
|
||||||
continue;
|
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()) {
|
if (LRange.getLow() < RRange.getLow()) {
|
||||||
// May be opened in previous iteration.
|
// May be opened in previous iteration.
|
||||||
if (!Machine.isLOpened())
|
if (!Machine.isLOpened())
|
||||||
@@ -390,7 +514,7 @@ public:
|
|||||||
Machine.onLOpen(LRange.getLow(), LCluster.second);
|
Machine.onLOpen(LRange.getLow(), LCluster.second);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Machine.onRLOpen(LRange.getLow(), LCluster.second, RCluster.second);
|
Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second);
|
||||||
|
|
||||||
if (LRange.getHigh() < RRange.getHigh()) {
|
if (LRange.getHigh() < RRange.getHigh()) {
|
||||||
Machine.onLClose(LRange.getHigh());
|
Machine.onLClose(LRange.getHigh());
|
||||||
@@ -411,7 +535,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Machine.onRLClose(LRange.getHigh());
|
Machine.onLRClose(LRange.getHigh());
|
||||||
++L;
|
++L;
|
||||||
++R;
|
++R;
|
||||||
}
|
}
|
||||||
@@ -441,7 +565,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the finalized case objects.
|
/// 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;
|
CRSMap TheCRSMap;
|
||||||
for (RangeIterator i = this->begin(); i != this->end(); ++i)
|
for (RangeIterator i = this->begin(); i != this->end(); ++i)
|
||||||
TheCRSMap[i->second].push_back(i->first);
|
TheCRSMap[i->second].push_back(i->first);
|
||||||
@@ -458,6 +595,22 @@ public:
|
|||||||
return IntegersSubsetTy(Ranges);
|
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.
|
/// Returns true if there is no ranges and values inside.
|
||||||
bool empty() const { return Items.empty(); }
|
bool empty() const { return Items.empty(); }
|
||||||
|
|
||||||
|
@@ -2450,22 +2450,23 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases,
|
|||||||
size_t numCmps = 0;
|
size_t numCmps = 0;
|
||||||
for (Clusterifier::RangeIterator i = TheClusterifier.begin(),
|
for (Clusterifier::RangeIterator i = TheClusterifier.begin(),
|
||||||
e = TheClusterifier.end(); i != e; ++i, ++numCmps) {
|
e = TheClusterifier.end(); i != e; ++i, ++numCmps) {
|
||||||
Clusterifier::Cluster &C = *i;
|
const Clusterifier::RangeEx &R = i->first;
|
||||||
|
MachineBasicBlock *MBB = i->second;
|
||||||
unsigned W = 0;
|
unsigned W = 0;
|
||||||
if (BPI) {
|
if (BPI) {
|
||||||
W = BPI->getEdgeWeight(SI.getParent(), C.second->getBasicBlock());
|
W = BPI->getEdgeWeight(SI.getParent(), MBB->getBasicBlock());
|
||||||
if (!W)
|
if (!W)
|
||||||
W = 16;
|
W = 16;
|
||||||
W *= C.first.Weight;
|
W *= R.Weight;
|
||||||
BPI->setEdgeWeight(SI.getParent(), C.second->getBasicBlock(), W);
|
BPI->setEdgeWeight(SI.getParent(), MBB->getBasicBlock(), W);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Currently work with ConstantInt based numbers.
|
// FIXME: Currently work with ConstantInt based numbers.
|
||||||
// Changing it to APInt based is a pretty heavy for this commit.
|
// Changing it to APInt based is a pretty heavy for this commit.
|
||||||
Cases.push_back(Case(C.first.getLow().toConstantInt(),
|
Cases.push_back(Case(R.getLow().toConstantInt(),
|
||||||
C.first.getHigh().toConstantInt(), C.second, W));
|
R.getHigh().toConstantInt(), MBB, W));
|
||||||
|
|
||||||
if (C.first.getLow() != C.first.getHigh())
|
if (R.getLow() != R.getHigh())
|
||||||
// A range counts double, since it requires two compares.
|
// A range counts double, since it requires two compares.
|
||||||
++numCmps;
|
++numCmps;
|
||||||
}
|
}
|
||||||
|
@@ -238,13 +238,14 @@ unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) {
|
|||||||
size_t numCmps = 0;
|
size_t numCmps = 0;
|
||||||
for (IntegersSubsetToBB::RangeIterator i = TheClusterifier.begin(),
|
for (IntegersSubsetToBB::RangeIterator i = TheClusterifier.begin(),
|
||||||
e = TheClusterifier.end(); i != e; ++i, ++numCmps) {
|
e = TheClusterifier.end(); i != e; ++i, ++numCmps) {
|
||||||
IntegersSubsetToBB::Cluster &C = *i;
|
const IntegersSubsetToBB::RangeTy &R = i->first;
|
||||||
|
BasicBlock *S = i->second;
|
||||||
|
|
||||||
// FIXME: Currently work with ConstantInt based numbers.
|
// FIXME: Currently work with ConstantInt based numbers.
|
||||||
// Changing it to APInt based is a pretty heavy for this commit.
|
// Changing it to APInt based is a pretty heavy for this commit.
|
||||||
Cases.push_back(CaseRange(C.first.getLow().toConstantInt(),
|
Cases.push_back(CaseRange(R.getLow().toConstantInt(),
|
||||||
C.first.getHigh().toConstantInt(), C.second));
|
R.getHigh().toConstantInt(), S));
|
||||||
if (C.first.isSingleNumber())
|
if (R.isSingleNumber())
|
||||||
// A range counts double, since it requires two compares.
|
// A range counts double, since it requires two compares.
|
||||||
++numCmps;
|
++numCmps;
|
||||||
}
|
}
|
||||||
|
@@ -56,26 +56,12 @@ DupRet("simplifycfg-dup-ret", cl::Hidden, cl::init(false),
|
|||||||
STATISTIC(NumSpeculations, "Number of speculative executed instructions");
|
STATISTIC(NumSpeculations, "Number of speculative executed instructions");
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// ValueEqualityComparisonCase - Represents a case of a switch.
|
|
||||||
struct ValueEqualityComparisonCase {
|
|
||||||
ConstantInt *Value;
|
|
||||||
BasicBlock *Dest;
|
|
||||||
|
|
||||||
ValueEqualityComparisonCase(ConstantInt *Value, BasicBlock *Dest)
|
|
||||||
: Value(Value), Dest(Dest) {}
|
|
||||||
|
|
||||||
bool operator<(ValueEqualityComparisonCase RHS) const {
|
|
||||||
// Comparing pointers is ok as we only rely on the order for uniquing.
|
|
||||||
return Value < RHS.Value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SimplifyCFGOpt {
|
class SimplifyCFGOpt {
|
||||||
const TargetData *const TD;
|
const TargetData *const TD;
|
||||||
|
|
||||||
Value *isValueEqualityComparison(TerminatorInst *TI);
|
Value *isValueEqualityComparison(TerminatorInst *TI);
|
||||||
BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,
|
BasicBlock *GetValueEqualityComparisonCases(TerminatorInst *TI,
|
||||||
std::vector<ValueEqualityComparisonCase> &Cases);
|
IntegersSubsetToBB &Mapping);
|
||||||
bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
||||||
BasicBlock *Pred,
|
BasicBlock *Pred,
|
||||||
IRBuilder<> &Builder);
|
IRBuilder<> &Builder);
|
||||||
@@ -532,72 +518,25 @@ Value *SimplifyCFGOpt::isValueEqualityComparison(TerminatorInst *TI) {
|
|||||||
/// decode all of the 'cases' that it represents and return the 'default' block.
|
/// decode all of the 'cases' that it represents and return the 'default' block.
|
||||||
BasicBlock *SimplifyCFGOpt::
|
BasicBlock *SimplifyCFGOpt::
|
||||||
GetValueEqualityComparisonCases(TerminatorInst *TI,
|
GetValueEqualityComparisonCases(TerminatorInst *TI,
|
||||||
std::vector<ValueEqualityComparisonCase>
|
IntegersSubsetToBB &Mapping) {
|
||||||
&Cases) {
|
|
||||||
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
|
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
|
||||||
Cases.reserve(SI->getNumCases());
|
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
|
||||||
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i)
|
i != e; ++i)
|
||||||
Cases.push_back(ValueEqualityComparisonCase(i.getCaseValue(),
|
Mapping.add(i.getCaseValueEx(), i.getCaseSuccessor());
|
||||||
i.getCaseSuccessor()));
|
|
||||||
return SI->getDefaultDest();
|
return SI->getDefaultDest();
|
||||||
}
|
}
|
||||||
|
|
||||||
BranchInst *BI = cast<BranchInst>(TI);
|
BranchInst *BI = cast<BranchInst>(TI);
|
||||||
ICmpInst *ICI = cast<ICmpInst>(BI->getCondition());
|
ICmpInst *ICI = cast<ICmpInst>(BI->getCondition());
|
||||||
BasicBlock *Succ = BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE);
|
IntegersSubsetToBB Builder;
|
||||||
Cases.push_back(ValueEqualityComparisonCase(GetConstantInt(ICI->getOperand(1),
|
|
||||||
TD),
|
Mapping.add(
|
||||||
Succ));
|
IntItem::fromConstantInt(GetConstantInt(ICI->getOperand(1), TD)),
|
||||||
|
BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE));
|
||||||
|
|
||||||
return BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_EQ);
|
return BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_EQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// EliminateBlockCases - Given a vector of bb/value pairs, remove any entries
|
|
||||||
/// in the list that match the specified block.
|
|
||||||
static void EliminateBlockCases(BasicBlock *BB,
|
|
||||||
std::vector<ValueEqualityComparisonCase> &Cases) {
|
|
||||||
for (unsigned i = 0, e = Cases.size(); i != e; ++i)
|
|
||||||
if (Cases[i].Dest == BB) {
|
|
||||||
Cases.erase(Cases.begin()+i);
|
|
||||||
--i; --e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ValuesOverlap - Return true if there are any keys in C1 that exist in C2 as
|
|
||||||
/// well.
|
|
||||||
static bool
|
|
||||||
ValuesOverlap(std::vector<ValueEqualityComparisonCase> &C1,
|
|
||||||
std::vector<ValueEqualityComparisonCase > &C2) {
|
|
||||||
std::vector<ValueEqualityComparisonCase> *V1 = &C1, *V2 = &C2;
|
|
||||||
|
|
||||||
// Make V1 be smaller than V2.
|
|
||||||
if (V1->size() > V2->size())
|
|
||||||
std::swap(V1, V2);
|
|
||||||
|
|
||||||
if (V1->size() == 0) return false;
|
|
||||||
if (V1->size() == 1) {
|
|
||||||
// Just scan V2.
|
|
||||||
ConstantInt *TheVal = (*V1)[0].Value;
|
|
||||||
for (unsigned i = 0, e = V2->size(); i != e; ++i)
|
|
||||||
if (TheVal == (*V2)[i].Value)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, just sort both lists and compare element by element.
|
|
||||||
array_pod_sort(V1->begin(), V1->end());
|
|
||||||
array_pod_sort(V2->begin(), V2->end());
|
|
||||||
unsigned i1 = 0, i2 = 0, e1 = V1->size(), e2 = V2->size();
|
|
||||||
while (i1 != e1 && i2 != e2) {
|
|
||||||
if ((*V1)[i1].Value == (*V2)[i2].Value)
|
|
||||||
return true;
|
|
||||||
if ((*V1)[i1].Value < (*V2)[i2].Value)
|
|
||||||
++i1;
|
|
||||||
else
|
|
||||||
++i2;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SimplifyEqualityComparisonWithOnlyPredecessor - If TI is known to be a
|
/// SimplifyEqualityComparisonWithOnlyPredecessor - If TI is known to be a
|
||||||
/// terminator instruction and its block is known to only have a single
|
/// terminator instruction and its block is known to only have a single
|
||||||
/// predecessor block, check to see if that predecessor is also a value
|
/// predecessor block, check to see if that predecessor is also a value
|
||||||
@@ -616,23 +555,27 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
|||||||
if (ThisVal != PredVal) return false; // Different predicates.
|
if (ThisVal != PredVal) return false; // Different predicates.
|
||||||
|
|
||||||
// Find out information about when control will move from Pred to TI's block.
|
// Find out information about when control will move from Pred to TI's block.
|
||||||
std::vector<ValueEqualityComparisonCase> PredCases;
|
IntegersSubsetToBB PredCases;
|
||||||
BasicBlock *PredDef = GetValueEqualityComparisonCases(Pred->getTerminator(),
|
BasicBlock *PredDef = GetValueEqualityComparisonCases(Pred->getTerminator(),
|
||||||
PredCases);
|
PredCases);
|
||||||
EliminateBlockCases(PredDef, PredCases); // Remove default from cases.
|
|
||||||
|
|
||||||
|
// Remove default from cases.
|
||||||
|
PredCases.removeCase(PredDef);
|
||||||
|
|
||||||
// Find information about how control leaves this block.
|
// Find information about how control leaves this block.
|
||||||
std::vector<ValueEqualityComparisonCase> ThisCases;
|
IntegersSubsetToBB ThisCases;
|
||||||
BasicBlock *ThisDef = GetValueEqualityComparisonCases(TI, ThisCases);
|
BasicBlock *ThisDef = GetValueEqualityComparisonCases(TI, ThisCases);
|
||||||
EliminateBlockCases(ThisDef, ThisCases); // Remove default from cases.
|
|
||||||
|
|
||||||
|
// Remove default from cases.
|
||||||
|
ThisCases.removeCase(ThisDef);
|
||||||
|
|
||||||
// If TI's block is the default block from Pred's comparison, potentially
|
// If TI's block is the default block from Pred's comparison, potentially
|
||||||
// simplify TI based on this knowledge.
|
// simplify TI based on this knowledge.
|
||||||
if (PredDef == TI->getParent()) {
|
if (PredDef == TI->getParent()) {
|
||||||
// If we are here, we know that the value is none of those cases listed in
|
// If we are here, we know that the value is none of those cases listed in
|
||||||
// PredCases. If there are any cases in ThisCases that are in PredCases, we
|
// PredCases. If there are any cases in ThisCases that are in PredCases, we
|
||||||
// can simplify TI.
|
// can simplify TI.
|
||||||
if (!ValuesOverlap(PredCases, ThisCases))
|
if (!PredCases.isOverlapped(ThisCases))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (isa<BranchInst>(TI)) {
|
if (isa<BranchInst>(TI)) {
|
||||||
@@ -644,7 +587,7 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
|||||||
(void) NI;
|
(void) NI;
|
||||||
|
|
||||||
// Remove PHI node entries for the dead edge.
|
// Remove PHI node entries for the dead edge.
|
||||||
ThisCases[0].Dest->removePredecessor(TI->getParent());
|
ThisCases.begin()->second->removePredecessor(TI->getParent());
|
||||||
|
|
||||||
DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
|
DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
|
||||||
<< "Through successor TI: " << *TI << "Leaving: " << *NI << "\n");
|
<< "Through successor TI: " << *TI << "Leaving: " << *NI << "\n");
|
||||||
@@ -655,45 +598,45 @@ SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
|
|||||||
|
|
||||||
SwitchInst *SI = cast<SwitchInst>(TI);
|
SwitchInst *SI = cast<SwitchInst>(TI);
|
||||||
// Okay, TI has cases that are statically dead, prune them away.
|
// Okay, TI has cases that are statically dead, prune them away.
|
||||||
SmallPtrSet<Constant*, 16> DeadCases;
|
IRBuilder<> CodeBuilder(SI);
|
||||||
for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
|
CodeBuilder.SetCurrentDebugLocation(SI->getDebugLoc());
|
||||||
DeadCases.insert(PredCases[i].Value);
|
|
||||||
|
|
||||||
DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
|
DEBUG(dbgs() << "Threading pred instr: " << *Pred->getTerminator()
|
||||||
<< "Through successor TI: " << *TI);
|
<< "Through successor TI: " << *TI);
|
||||||
|
|
||||||
for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) {
|
// Okay, TI has cases that are statically dead, prune them away.
|
||||||
--i;
|
IntegersSubsetToBB NewThisCases;
|
||||||
if (DeadCases.count(i.getCaseValue())) {
|
IntegersSubsetToBB WastedCases;
|
||||||
i.getCaseSuccessor()->removePredecessor(TI->getParent());
|
ThisCases.diff(&NewThisCases, &WastedCases, 0, PredCases);
|
||||||
SI->removeCase(i);
|
|
||||||
}
|
IntegersSubsetToBB::Cases Cases;
|
||||||
}
|
NewThisCases.getCases(Cases, true/*temporary prevent complex cases*/);
|
||||||
|
|
||||||
DEBUG(dbgs() << "Leaving: " << *TI << "\n");
|
SwitchInst *NewSI =
|
||||||
|
CodeBuilder.CreateSwitch(ThisVal, SI->getDefaultDest(), Cases.size());
|
||||||
|
|
||||||
|
for (IntegersSubsetToBB::RangeIterator i = WastedCases.begin(),
|
||||||
|
e = WastedCases.end(); i != e; ++i)
|
||||||
|
i->second->removePredecessor(TI->getParent());
|
||||||
|
|
||||||
|
for (IntegersSubsetToBB::CasesIt i = Cases.begin(), e = Cases.end();
|
||||||
|
i != e; ++i)
|
||||||
|
NewSI->addCase(i->second, i->first);
|
||||||
|
|
||||||
|
EraseTerminatorInstAndDCECond(SI);
|
||||||
|
DEBUG(dbgs() << "Leaving: " << *NewSI << "\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, TI's block must correspond to some matched value. Find out
|
// Otherwise, TI's block must correspond to some matched value. Find out
|
||||||
// which value (or set of values) this is.
|
// which value (or set of values) this is.
|
||||||
ConstantInt *TIV = 0;
|
|
||||||
BasicBlock *TIBB = TI->getParent();
|
BasicBlock *TIBB = TI->getParent();
|
||||||
for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
|
const IntItem* TIVIntITem = PredCases.getCaseSingleNumber(TIBB);
|
||||||
if (PredCases[i].Dest == TIBB) {
|
assert(TIVIntITem && "No edge from pred to succ?");
|
||||||
if (TIV != 0)
|
|
||||||
return false; // Cannot handle multiple values coming to this block.
|
|
||||||
TIV = PredCases[i].Value;
|
|
||||||
}
|
|
||||||
assert(TIV && "No edge from pred to succ?");
|
|
||||||
|
|
||||||
// Okay, we found the one constant that our value can be if we get into TI's
|
// Okay, we found the one constant that our value can be if we get into TI's
|
||||||
// BB. Find out which successor will unconditionally be branched to.
|
// BB. Find out which successor will unconditionally be branched to.
|
||||||
BasicBlock *TheRealDest = 0;
|
BasicBlock *TheRealDest = ThisCases.findSuccessor(*TIVIntITem);
|
||||||
for (unsigned i = 0, e = ThisCases.size(); i != e; ++i)
|
|
||||||
if (ThisCases[i].Value == TIV) {
|
|
||||||
TheRealDest = ThisCases[i].Dest;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not handled by any explicit cases, it is handled by the default case.
|
// If not handled by any explicit cases, it is handled by the default case.
|
||||||
if (TheRealDest == 0) TheRealDest = ThisDef;
|
if (TheRealDest == 0) TheRealDest = ThisDef;
|
||||||
@@ -759,10 +702,10 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
|
|||||||
|
|
||||||
if (PCV == CV && SafeToMergeTerminators(TI, PTI)) {
|
if (PCV == CV && SafeToMergeTerminators(TI, PTI)) {
|
||||||
// Figure out which 'cases' to copy from SI to PSI.
|
// Figure out which 'cases' to copy from SI to PSI.
|
||||||
std::vector<ValueEqualityComparisonCase> BBCases;
|
IntegersSubsetToBB BBCases;
|
||||||
BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases);
|
BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases);
|
||||||
|
|
||||||
std::vector<ValueEqualityComparisonCase> PredCases;
|
IntegersSubsetToBB PredCases;
|
||||||
BasicBlock *PredDefault = GetValueEqualityComparisonCases(PTI, PredCases);
|
BasicBlock *PredDefault = GetValueEqualityComparisonCases(PTI, PredCases);
|
||||||
|
|
||||||
// Based on whether the default edge from PTI goes to BB or not, fill in
|
// Based on whether the default edge from PTI goes to BB or not, fill in
|
||||||
@@ -773,61 +716,51 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
|
|||||||
if (PredDefault == BB) {
|
if (PredDefault == BB) {
|
||||||
// If this is the default destination from PTI, only the edges in TI
|
// If this is the default destination from PTI, only the edges in TI
|
||||||
// that don't occur in PTI, or that branch to BB will be activated.
|
// that don't occur in PTI, or that branch to BB will be activated.
|
||||||
std::set<ConstantInt*, ConstantIntOrdering> PTIHandled;
|
|
||||||
for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
|
PredCases.removeCase(BB);
|
||||||
if (PredCases[i].Dest != BB)
|
IntegersSubsetToBB NewBBCases;
|
||||||
PTIHandled.insert(PredCases[i].Value);
|
BBCases.diff(&NewBBCases, 0, 0, PredCases);
|
||||||
else {
|
PredCases.add(NewBBCases);
|
||||||
// The default destination is BB, we don't need explicit targets.
|
for (IntegersSubsetToBB::RangeIterator i = NewBBCases.begin(),
|
||||||
std::swap(PredCases[i], PredCases.back());
|
e = NewBBCases.end(); i != e; ++i)
|
||||||
PredCases.pop_back();
|
NewSuccessors.push_back(i->second);
|
||||||
--i; --e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconstruct the new switch statement we will be building.
|
// Replace the default if needed.
|
||||||
if (PredDefault != BBDefault) {
|
if (PredDefault != BBDefault) {
|
||||||
PredDefault->removePredecessor(Pred);
|
PredDefault->removePredecessor(Pred);
|
||||||
PredDefault = BBDefault;
|
PredDefault = BBDefault;
|
||||||
NewSuccessors.push_back(BBDefault);
|
NewSuccessors.push_back(BBDefault);
|
||||||
}
|
}
|
||||||
for (unsigned i = 0, e = BBCases.size(); i != e; ++i)
|
|
||||||
if (!PTIHandled.count(BBCases[i].Value) &&
|
|
||||||
BBCases[i].Dest != BBDefault) {
|
|
||||||
PredCases.push_back(BBCases[i]);
|
|
||||||
NewSuccessors.push_back(BBCases[i].Dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// If this is not the default destination from PSI, only the edges
|
// If this is not the default destination from PSI, only the edges
|
||||||
// in SI that occur in PSI with a destination of BB will be
|
// in SI that occur in PSI with a destination of BB will be
|
||||||
// activated.
|
// activated.
|
||||||
std::set<ConstantInt*, ConstantIntOrdering> PTIHandled;
|
IntegersSubsetToBB BBPredCase;
|
||||||
for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
|
PredCases.detachCase(BBPredCase, BB);
|
||||||
if (PredCases[i].Dest == BB) {
|
IntegersSubsetToBB CasesWithBBDef;
|
||||||
PTIHandled.insert(PredCases[i].Value);
|
IntegersSubsetToBB InharitedCases;
|
||||||
std::swap(PredCases[i], PredCases.back());
|
|
||||||
PredCases.pop_back();
|
|
||||||
--i; --e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Okay, now we know which constants were sent to BB from the
|
// Okay, now we know which constants were sent to BB from the
|
||||||
// predecessor. Figure out where they will all go now.
|
// predecessor. Figure out where they will all go now.
|
||||||
for (unsigned i = 0, e = BBCases.size(); i != e; ++i)
|
if (!BBPredCase.empty()) {
|
||||||
if (PTIHandled.count(BBCases[i].Value)) {
|
BBCases.diff(
|
||||||
// If this is one we are capable of getting...
|
0, // LHS excl RHS
|
||||||
PredCases.push_back(BBCases[i]);
|
&InharitedCases, // intersection
|
||||||
NewSuccessors.push_back(BBCases[i].Dest);
|
&CasesWithBBDef, // RHS excl LHS
|
||||||
PTIHandled.erase(BBCases[i].Value);// This constant is taken care of
|
BBPredCase); // RHS.
|
||||||
}
|
}
|
||||||
|
PredCases.add(InharitedCases);
|
||||||
|
for (IntegersSubsetToBB::RangeIterator i = InharitedCases.begin(),
|
||||||
|
e = InharitedCases.end();
|
||||||
|
i != e; ++i)
|
||||||
|
NewSuccessors.push_back(i->second);
|
||||||
|
|
||||||
// If there are any constants vectored to BB that TI doesn't handle,
|
// If there are any constants vectored to BB that TI doesn't handle,
|
||||||
// they must go to the default destination of TI.
|
// they must go to the default destination of TI.
|
||||||
for (std::set<ConstantInt*, ConstantIntOrdering>::iterator I =
|
PredCases.add(CasesWithBBDef, BBDefault);
|
||||||
PTIHandled.begin(),
|
for (unsigned i = 0, e = CasesWithBBDef.size(); i != e; ++i)
|
||||||
E = PTIHandled.end(); I != E; ++I) {
|
|
||||||
PredCases.push_back(ValueEqualityComparisonCase(*I, BBDefault));
|
|
||||||
NewSuccessors.push_back(BBDefault);
|
NewSuccessors.push_back(BBDefault);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, at this point, we know which new successor Pred will get. Make
|
// Okay, at this point, we know which new successor Pred will get. Make
|
||||||
@@ -848,8 +781,12 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI,
|
|||||||
SwitchInst *NewSI = Builder.CreateSwitch(CV, PredDefault,
|
SwitchInst *NewSI = Builder.CreateSwitch(CV, PredDefault,
|
||||||
PredCases.size());
|
PredCases.size());
|
||||||
NewSI->setDebugLoc(PTI->getDebugLoc());
|
NewSI->setDebugLoc(PTI->getDebugLoc());
|
||||||
for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
|
IntegersSubsetToBB::Cases Cases;
|
||||||
NewSI->addCase(PredCases[i].Value, PredCases[i].Dest);
|
PredCases.getCases(Cases, true/*temporary prevent complex case*/);
|
||||||
|
|
||||||
|
for (IntegersSubsetToBB::CasesIt i = Cases.begin(), e = Cases.end();
|
||||||
|
i != e; ++i)
|
||||||
|
NewSI->addCase(i->second, i->first);
|
||||||
|
|
||||||
EraseTerminatorInstAndDCECond(PTI);
|
EraseTerminatorInstAndDCECond(PTI);
|
||||||
|
|
||||||
|
@@ -82,8 +82,8 @@ lor.end: ; preds = %lor.rhs, %lor.lhs.f
|
|||||||
|
|
||||||
; CHECK: @test4
|
; CHECK: @test4
|
||||||
; CHECK: switch i8 %c, label %lor.rhs [
|
; CHECK: switch i8 %c, label %lor.rhs [
|
||||||
; CHECK: i8 62, label %lor.end
|
|
||||||
; CHECK: i8 34, label %lor.end
|
; CHECK: i8 34, label %lor.end
|
||||||
|
; CHECK: i8 62, label %lor.end
|
||||||
; CHECK: i8 92, label %lor.end
|
; CHECK: i8 92, label %lor.end
|
||||||
; CHECK: ]
|
; CHECK: ]
|
||||||
}
|
}
|
||||||
|
@@ -193,20 +193,20 @@ namespace {
|
|||||||
const unsigned_ranges IntersectRes,
|
const unsigned_ranges IntersectRes,
|
||||||
unsigned IntersectResSize
|
unsigned IntersectResSize
|
||||||
) {
|
) {
|
||||||
|
unsigned successors[2] = {0, 1};
|
||||||
Mapping::RangesCollection Ranges;
|
Mapping::RangesCollection Ranges;
|
||||||
|
|
||||||
Mapping LHSMapping;
|
Mapping LHSMapping;
|
||||||
for (unsigned i = 0; i < LSize; ++i)
|
for (unsigned i = 0; i < LSize; ++i)
|
||||||
Ranges.push_back(Range(Int(LHS[i][0]), Int(LHS[i][1])));
|
Ranges.push_back(Range(Int(LHS[i][0]), Int(LHS[i][1])));
|
||||||
LHSMapping.add(Ranges);
|
LHSMapping.add(Ranges, &successors[0]);
|
||||||
|
|
||||||
Ranges.clear();
|
Ranges.clear();
|
||||||
|
|
||||||
Mapping RHSMapping;
|
Mapping RHSMapping;
|
||||||
for (unsigned i = 0; i < RSize; ++i)
|
for (unsigned i = 0; i < RSize; ++i)
|
||||||
Ranges.push_back(Range(Int(RHS[i][0]), Int(RHS[i][1])));
|
Ranges.push_back(Range(Int(RHS[i][0]), Int(RHS[i][1])));
|
||||||
RHSMapping.add(Ranges);
|
RHSMapping.add(Ranges, &successors[1]);
|
||||||
|
|
||||||
Mapping LExclude, Intersection;
|
Mapping LExclude, Intersection;
|
||||||
|
|
||||||
@@ -217,8 +217,10 @@ namespace {
|
|||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (Mapping::RangeIterator rei = LExclude.begin(),
|
for (Mapping::RangeIterator rei = LExclude.begin(),
|
||||||
e = LExclude.end(); rei != e; ++rei, ++i)
|
e = LExclude.end(); rei != e; ++rei, ++i) {
|
||||||
EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
|
EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
|
||||||
|
EXPECT_EQ(rei->second, &successors[0]);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
EXPECT_TRUE(LExclude.empty());
|
EXPECT_TRUE(LExclude.empty());
|
||||||
|
|
||||||
@@ -227,8 +229,10 @@ namespace {
|
|||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (Mapping::RangeIterator ii = Intersection.begin(),
|
for (Mapping::RangeIterator ii = Intersection.begin(),
|
||||||
e = Intersection.end(); ii != e; ++ii, ++i)
|
e = Intersection.end(); ii != e; ++ii, ++i) {
|
||||||
EXPECT_EQ(ii->first, Range(IntersectRes[i][0], IntersectRes[i][1]));
|
EXPECT_EQ(ii->first, Range(IntersectRes[i][0], IntersectRes[i][1]));
|
||||||
|
EXPECT_EQ(ii->second, &successors[0]);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
EXPECT_TRUE(Intersection.empty());
|
EXPECT_TRUE(Intersection.empty());
|
||||||
|
|
||||||
@@ -241,9 +245,11 @@ namespace {
|
|||||||
EXPECT_EQ(LExclude.size(), ExcludeResSize);
|
EXPECT_EQ(LExclude.size(), ExcludeResSize);
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (Mapping::RangeIterator rei = LExclude.begin(),
|
for (Mapping::RangeIterator lei = LExclude.begin(),
|
||||||
e = LExclude.end(); rei != e; ++rei, ++i)
|
e = LExclude.end(); lei != e; ++lei, ++i) {
|
||||||
EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
|
EXPECT_EQ(lei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
|
||||||
|
EXPECT_EQ(lei->second, &successors[0]);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
EXPECT_TRUE(LExclude.empty());
|
EXPECT_TRUE(LExclude.empty());
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user