Revert "IntRange:" as it appears to be breaking self hosting.

This reverts commit b2833d9dcb.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@159618 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher
2012-07-02 23:22:21 +00:00
parent 3aaefc12bb
commit c723eb1aef
7 changed files with 210 additions and 328 deletions

View File

@@ -182,12 +182,7 @@ protected:
IntType Low; IntType Low;
IntType High; IntType High;
bool IsEmpty : 1; bool IsEmpty : 1;
enum Type { bool IsSingleNumber : 1;
SINGLE_NUMBER,
RANGE,
UNKNOWN
};
Type RangeType;
public: public:
typedef IntRange<IntType> self; typedef IntRange<IntType> self;
@@ -196,30 +191,15 @@ 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), RangeType(RHS.RangeType) {} IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {}
IntRange(const IntType &C) : IntRange(const IntType &C) :
Low(C), High(C), IsEmpty(false), RangeType(SINGLE_NUMBER) {} Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {}
IntRange(const IntType &L, const IntType &H) : Low(L), High(H), IntRange(const IntType &L, const IntType &H) : Low(L), High(H),
IsEmpty(false), RangeType(UNKNOWN) {} IsEmpty(false), IsSingleNumber(Low == High) {}
bool isEmpty() const { return IsEmpty; } bool isEmpty() const { return IsEmpty; }
bool isSingleNumber() const { bool isSingleNumber() const { return IsSingleNumber; }
switch (RangeType) {
case SINGLE_NUMBER:
return true;
case RANGE:
return false;
case UNKNOWN:
if (Low == High) {
const_cast<Type&>(RangeType) = SINGLE_NUMBER;
return true;
}
const_cast<Type&>(RangeType) = RANGE;
return false;
}
llvm_unreachable("Unknown state?!");
}
const IntType& getLow() const { const IntType& getLow() const {
assert(!IsEmpty && "Range is empty."); assert(!IsEmpty && "Range is empty.");
@@ -233,13 +213,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;
} }
@@ -532,7 +512,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

View File

@@ -58,16 +58,22 @@ public:
protected: protected:
typedef std::map<RangeEx, SuccessorClass*> CaseItems; typedef std::list<Cluster> 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 SingleNumbersOnly; bool Sorted;
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();
@@ -85,6 +91,18 @@ 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,
@@ -195,7 +213,7 @@ protected:
} }
} }
void onLROpen(const IntTy &Pt, void onRLOpen(const IntTy &Pt,
SuccessorClass *LS, SuccessorClass *LS,
SuccessorClass *RS) { SuccessorClass *RS) {
switch (State) { switch (State) {
@@ -211,7 +229,7 @@ protected:
OpenPt = Pt; OpenPt = Pt;
} }
void onLRClose(const IntTy &Pt) { void onRLClose(const IntTy &Pt) {
switch (State) { switch (State) {
case INTERSECT_OPENED: case INTERSECT_OPENED:
if (IntersectionMapping) if (IntersectionMapping)
@@ -227,48 +245,6 @@ 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:
@@ -280,18 +256,15 @@ 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() : SingleNumbersOnly(true) {} IntegersSubsetMapping() {
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) {
@@ -302,36 +275,10 @@ 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();
@@ -356,6 +303,8 @@ 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.
@@ -374,10 +323,8 @@ 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));
Items.insert(std::make_pair(R, S)); Sorted = false;
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
@@ -390,17 +337,9 @@ public:
} }
void add(self& RHS) { void add(self& RHS) {
//Items.insert(Items.begin(), RHS.Items.begin(), RHS.Items.end()); Items.insert(Items.end(), 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);
@@ -409,34 +348,6 @@ 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,
@@ -444,16 +355,10 @@ 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();
CaseItemConstIt el = Items.end(), er = RHS.Items.end(); while (L != Items.end() && R != 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;
@@ -472,36 +377,7 @@ 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())
@@ -514,7 +390,7 @@ public:
Machine.onLOpen(LRange.getLow(), LCluster.second); Machine.onLOpen(LRange.getLow(), LCluster.second);
} }
else else
Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); Machine.onRLOpen(LRange.getLow(), LCluster.second, RCluster.second);
if (LRange.getHigh() < RRange.getHigh()) { if (LRange.getHigh() < RRange.getHigh()) {
Machine.onLClose(LRange.getHigh()); Machine.onLClose(LRange.getHigh());
@@ -535,7 +411,7 @@ public:
} }
} }
else { else {
Machine.onLRClose(LRange.getHigh()); Machine.onRLClose(LRange.getHigh());
++L; ++L;
++R; ++R;
} }
@@ -565,20 +441,7 @@ public:
} }
/// Builds the finalized case objects. /// Builds the finalized case objects.
void getCases(Cases& TheCases, bool PreventMerging = false) { void getCases(Cases& TheCases) {
//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);
@@ -595,22 +458,6 @@ 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(); }

View File

@@ -2450,23 +2450,22 @@ 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) {
const Clusterifier::RangeEx &R = i->first; Clusterifier::Cluster &C = *i;
MachineBasicBlock *MBB = i->second;
unsigned W = 0; unsigned W = 0;
if (BPI) { if (BPI) {
W = BPI->getEdgeWeight(SI.getParent(), MBB->getBasicBlock()); W = BPI->getEdgeWeight(SI.getParent(), C.second->getBasicBlock());
if (!W) if (!W)
W = 16; W = 16;
W *= R.Weight; W *= C.first.Weight;
BPI->setEdgeWeight(SI.getParent(), MBB->getBasicBlock(), W); BPI->setEdgeWeight(SI.getParent(), C.second->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(R.getLow().toConstantInt(), Cases.push_back(Case(C.first.getLow().toConstantInt(),
R.getHigh().toConstantInt(), MBB, W)); C.first.getHigh().toConstantInt(), C.second, W));
if (R.getLow() != R.getHigh()) if (C.first.getLow() != C.first.getHigh())
// A range counts double, since it requires two compares. // A range counts double, since it requires two compares.
++numCmps; ++numCmps;
} }

View File

@@ -238,14 +238,13 @@ 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) {
const IntegersSubsetToBB::RangeTy &R = i->first; IntegersSubsetToBB::Cluster &C = *i;
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(R.getLow().toConstantInt(), Cases.push_back(CaseRange(C.first.getLow().toConstantInt(),
R.getHigh().toConstantInt(), S)); C.first.getHigh().toConstantInt(), C.second));
if (R.isSingleNumber()) if (C.first.isSingleNumber())
// A range counts double, since it requires two compares. // A range counts double, since it requires two compares.
++numCmps; ++numCmps;
} }

View File

@@ -56,12 +56,26 @@ 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,
IntegersSubsetToBB &Mapping); std::vector<ValueEqualityComparisonCase> &Cases);
bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI, bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
BasicBlock *Pred, BasicBlock *Pred,
IRBuilder<> &Builder); IRBuilder<> &Builder);
@@ -518,25 +532,72 @@ 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,
IntegersSubsetToBB &Mapping) { std::vector<ValueEqualityComparisonCase>
&Cases) {
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); Cases.reserve(SI->getNumCases());
i != e; ++i) for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i)
Mapping.add(i.getCaseValueEx(), i.getCaseSuccessor()); Cases.push_back(ValueEqualityComparisonCase(i.getCaseValue(),
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());
IntegersSubsetToBB Builder; BasicBlock *Succ = BI->getSuccessor(ICI->getPredicate() == ICmpInst::ICMP_NE);
Cases.push_back(ValueEqualityComparisonCase(GetConstantInt(ICI->getOperand(1),
Mapping.add( TD),
IntItem::fromConstantInt(GetConstantInt(ICI->getOperand(1), TD)), Succ));
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
@@ -555,27 +616,23 @@ 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.
IntegersSubsetToBB PredCases; std::vector<ValueEqualityComparisonCase> 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.
IntegersSubsetToBB ThisCases; std::vector<ValueEqualityComparisonCase> 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 (!PredCases.isOverlapped(ThisCases)) if (!ValuesOverlap(PredCases, ThisCases))
return false; return false;
if (isa<BranchInst>(TI)) { if (isa<BranchInst>(TI)) {
@@ -587,7 +644,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.begin()->second->removePredecessor(TI->getParent()); ThisCases[0].Dest->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");
@@ -598,45 +655,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.
IRBuilder<> CodeBuilder(SI); SmallPtrSet<Constant*, 16> DeadCases;
CodeBuilder.SetCurrentDebugLocation(SI->getDebugLoc()); for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
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);
// Okay, TI has cases that are statically dead, prune them away. for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) {
IntegersSubsetToBB NewThisCases; --i;
IntegersSubsetToBB WastedCases; if (DeadCases.count(i.getCaseValue())) {
ThisCases.diff(&NewThisCases, &WastedCases, 0, PredCases); i.getCaseSuccessor()->removePredecessor(TI->getParent());
SI->removeCase(i);
IntegersSubsetToBB::Cases Cases; }
NewThisCases.getCases(Cases, true/*temporary prevent complex cases*/); }
SwitchInst *NewSI = DEBUG(dbgs() << "Leaving: " << *TI << "\n");
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();
const IntItem* TIVIntITem = PredCases.getCaseSingleNumber(TIBB); for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
assert(TIVIntITem && "No edge from pred to succ?"); if (PredCases[i].Dest == TIBB) {
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 = ThisCases.findSuccessor(*TIVIntITem); BasicBlock *TheRealDest = 0;
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;
@@ -702,10 +759,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.
IntegersSubsetToBB BBCases; std::vector<ValueEqualityComparisonCase> BBCases;
BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases); BasicBlock *BBDefault = GetValueEqualityComparisonCases(TI, BBCases);
IntegersSubsetToBB PredCases; std::vector<ValueEqualityComparisonCase> 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
@@ -716,51 +773,61 @@ 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;
PredCases.removeCase(BB); for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
IntegersSubsetToBB NewBBCases; if (PredCases[i].Dest != BB)
BBCases.diff(&NewBBCases, 0, 0, PredCases); PTIHandled.insert(PredCases[i].Value);
PredCases.add(NewBBCases); else {
for (IntegersSubsetToBB::RangeIterator i = NewBBCases.begin(), // The default destination is BB, we don't need explicit targets.
e = NewBBCases.end(); i != e; ++i) std::swap(PredCases[i], PredCases.back());
NewSuccessors.push_back(i->second); PredCases.pop_back();
--i; --e;
}
// Replace the default if needed. // Reconstruct the new switch statement we will be building.
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.
IntegersSubsetToBB BBPredCase; std::set<ConstantInt*, ConstantIntOrdering> PTIHandled;
PredCases.detachCase(BBPredCase, BB); for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
IntegersSubsetToBB CasesWithBBDef; if (PredCases[i].Dest == BB) {
IntegersSubsetToBB InharitedCases; PTIHandled.insert(PredCases[i].Value);
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.
if (!BBPredCase.empty()) { for (unsigned i = 0, e = BBCases.size(); i != e; ++i)
BBCases.diff( if (PTIHandled.count(BBCases[i].Value)) {
0, // LHS excl RHS // If this is one we are capable of getting...
&InharitedCases, // intersection PredCases.push_back(BBCases[i]);
&CasesWithBBDef, // RHS excl LHS NewSuccessors.push_back(BBCases[i].Dest);
BBPredCase); // RHS. PTIHandled.erase(BBCases[i].Value);// This constant is taken care of
} }
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.
PredCases.add(CasesWithBBDef, BBDefault); for (std::set<ConstantInt*, ConstantIntOrdering>::iterator I =
for (unsigned i = 0, e = CasesWithBBDef.size(); i != e; ++i) PTIHandled.begin(),
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
@@ -781,12 +848,8 @@ 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());
IntegersSubsetToBB::Cases Cases; for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
PredCases.getCases(Cases, true/*temporary prevent complex case*/); NewSI->addCase(PredCases[i].Value, PredCases[i].Dest);
for (IntegersSubsetToBB::CasesIt i = Cases.begin(), e = Cases.end();
i != e; ++i)
NewSI->addCase(i->second, i->first);
EraseTerminatorInstAndDCECond(PTI); EraseTerminatorInstAndDCECond(PTI);

View File

@@ -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 34, label %lor.end
; CHECK: i8 62, label %lor.end ; CHECK: i8 62, label %lor.end
; CHECK: i8 34, label %lor.end
; CHECK: i8 92, label %lor.end ; CHECK: i8 92, label %lor.end
; CHECK: ] ; CHECK: ]
} }

View File

@@ -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, &successors[0]); LHSMapping.add(Ranges);
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, &successors[1]); RHSMapping.add(Ranges);
Mapping LExclude, Intersection; Mapping LExclude, Intersection;
@@ -217,10 +217,8 @@ 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());
@@ -229,10 +227,8 @@ 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());
@@ -245,11 +241,9 @@ namespace {
EXPECT_EQ(LExclude.size(), ExcludeResSize); EXPECT_EQ(LExclude.size(), ExcludeResSize);
unsigned i = 0; unsigned i = 0;
for (Mapping::RangeIterator lei = LExclude.begin(), for (Mapping::RangeIterator rei = LExclude.begin(),
e = LExclude.end(); lei != e; ++lei, ++i) { e = LExclude.end(); rei != e; ++rei, ++i)
EXPECT_EQ(lei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1])); EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
EXPECT_EQ(lei->second, &successors[0]);
}
} else } else
EXPECT_TRUE(LExclude.empty()); EXPECT_TRUE(LExclude.empty());
} }