1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[IR] Redesign the case iterator in SwitchInst to actually be an iterator

and to expose a handle to represent the actual case rather than having
the iterator return a reference to itself.

All of this allows the iterator to be used with common STL facilities,
standard algorithms, etc.

Doing this exposed some missing facilities in the iterator facade that
I've fixed and required some work to the actual iterator to fully
support the necessary API.

Differential Revision: https://reviews.llvm.org/D31548

llvm-svn: 300032
This commit is contained in:
Chandler Carruth 2017-04-12 07:27:28 +00:00
parent 26a389508c
commit 853f402d9c
28 changed files with 296 additions and 198 deletions

View File

@ -165,9 +165,15 @@ public:
return !static_cast<const DerivedT *>(this)->operator<(RHS); return !static_cast<const DerivedT *>(this)->operator<(RHS);
} }
PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
PointerT operator->() const { PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*(); return &static_cast<const DerivedT *>(this)->operator*();
} }
ReferenceProxy operator[](DifferenceTypeT n) {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
}
ReferenceProxy operator[](DifferenceTypeT n) const { ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess, static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators."); "Subscripting is only defined for random access iterators.");

View File

@ -140,8 +140,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
std::string Str; std::string Str;
raw_string_ostream OS(Str); raw_string_ostream OS(Str);
SwitchInst::ConstCaseIt Case = auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
OS << Case.getCaseValue()->getValue(); OS << Case.getCaseValue()->getValue();
return OS.str(); return OS.str();
} }

View File

@ -3096,49 +3096,39 @@ public:
// -2 // -2
static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1); static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1);
template <class SwitchInstT, class ConstantIntT, class BasicBlockT> template <typename CaseHandleT> class CaseIteratorT;
class CaseIteratorT
: public iterator_facade_base< /// A handle to a particular switch case. It exposes a convenient interface
CaseIteratorT<SwitchInstT, ConstantIntT, BasicBlockT>, /// to both the case value and the successor block.
std::random_access_iterator_tag, ///
CaseIteratorT<SwitchInstT, ConstantIntT, BasicBlockT>> { /// We define this as a template and instantiate it to form both a const and
/// non-const handle.
template <typename SwitchInstT, typename ConstantIntT, typename BasicBlockT>
class CaseHandleT {
// Directly befriend both const and non-const iterators.
friend class SwitchInst::CaseIteratorT<
CaseHandleT<SwitchInstT, ConstantIntT, BasicBlockT>>;
protected: protected:
// Expose the switch type we're parameterized with to the iterator.
typedef SwitchInstT SwitchInstType;
SwitchInstT *SI; SwitchInstT *SI;
ptrdiff_t Index; ptrdiff_t Index;
CaseHandleT() = default;
CaseHandleT(SwitchInstT *SI, ptrdiff_t Index) : SI(SI), Index(Index) {}
public: public:
typedef CaseIteratorT<SwitchInstT, ConstantIntT, BasicBlockT> Self;
/// Default constructed iterator is in an invalid state until assigned to
/// a case for a particular switch.
CaseIteratorT() : SI(nullptr) {}
/// Initializes case iterator for given SwitchInst and for given
/// case number.
CaseIteratorT(SwitchInstT *SI, unsigned CaseNum) {
this->SI = SI;
Index = CaseNum;
}
/// Initializes case iterator for given SwitchInst and for given
/// TerminatorInst's successor index.
static Self fromSuccessorIndex(SwitchInstT *SI, unsigned SuccessorIndex) {
assert(SuccessorIndex < SI->getNumSuccessors() &&
"Successor index # out of range!");
return SuccessorIndex != 0 ?
Self(SI, SuccessorIndex - 1) :
Self(SI, DefaultPseudoIndex);
}
/// Resolves case value for current case. /// Resolves case value for current case.
ConstantIntT *getCaseValue() { ConstantIntT *getCaseValue() const {
assert((unsigned)Index < SI->getNumCases() && assert((unsigned)Index < SI->getNumCases() &&
"Index out the number of cases."); "Index out the number of cases.");
return reinterpret_cast<ConstantIntT *>(SI->getOperand(2 + Index * 2)); return reinterpret_cast<ConstantIntT *>(SI->getOperand(2 + Index * 2));
} }
/// Resolves successor for current case. /// Resolves successor for current case.
BasicBlockT *getCaseSuccessor() { BasicBlockT *getCaseSuccessor() const {
assert(((unsigned)Index < SI->getNumCases() || assert(((unsigned)Index < SI->getNumCases() ||
(unsigned)Index == DefaultPseudoIndex) && (unsigned)Index == DefaultPseudoIndex) &&
"Index out the number of cases."); "Index out the number of cases.");
@ -3156,43 +3146,20 @@ public:
return (unsigned)Index != DefaultPseudoIndex ? Index + 1 : 0; return (unsigned)Index != DefaultPseudoIndex ? Index + 1 : 0;
} }
Self &operator+=(ptrdiff_t N) { bool operator==(const CaseHandleT &RHS) const {
// Check index correctness after addition.
// Note: Index == getNumCases() means end().
assert(Index + N >= 0 && (unsigned)(Index + N) <= SI->getNumCases() &&
"Index out the number of cases.");
Index += N;
return *this;
}
Self &operator-=(ptrdiff_t N) {
// Check index correctness after subtraction.
// Note: Index == getNumCases() means end().
assert(Index - N >= 0 && (unsigned)(Index - N) <= SI->getNumCases() &&
"Index out the number of cases.");
Index -= N;
return *this;
}
bool operator==(const Self& RHS) const {
assert(SI == RHS.SI && "Incompatible operators."); assert(SI == RHS.SI && "Incompatible operators.");
return Index == RHS.Index; return Index == RHS.Index;
} }
bool operator<(const Self& RHS) const {
assert(SI == RHS.SI && "Incompatible operators.");
return Index < RHS.Index;
}
Self &operator*() { return *this; }
const Self &operator*() const { return *this; }
}; };
typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock> typedef CaseHandleT<const SwitchInst, const ConstantInt, const BasicBlock>
ConstCaseIt; ConstCaseHandle;
class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> { class CaseHandle : public CaseHandleT<SwitchInst, ConstantInt, BasicBlock> {
typedef CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> ParentTy; friend class SwitchInst::CaseIteratorT<CaseHandle>;
public: public:
CaseIt(const ParentTy &Src) : ParentTy(Src) {} CaseHandle(SwitchInst *SI, ptrdiff_t Index) : CaseHandleT(SI, Index) {}
CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {}
/// Sets the new value for current case. /// Sets the new value for current case.
void setValue(ConstantInt *V) { void setValue(ConstantInt *V) {
@ -3207,6 +3174,74 @@ public:
} }
}; };
template <typename CaseHandleT>
class CaseIteratorT
: public iterator_facade_base<CaseIteratorT<CaseHandleT>,
std::random_access_iterator_tag,
CaseHandleT> {
typedef typename CaseHandleT::SwitchInstType SwitchInstT;
CaseHandleT Case;
public:
/// Default constructed iterator is in an invalid state until assigned to
/// a case for a particular switch.
CaseIteratorT() = default;
/// Initializes case iterator for given SwitchInst and for given
/// case number.
CaseIteratorT(SwitchInstT *SI, unsigned CaseNum) : Case(SI, CaseNum) {}
/// Initializes case iterator for given SwitchInst and for given
/// TerminatorInst's successor index.
static CaseIteratorT fromSuccessorIndex(SwitchInstT *SI,
unsigned SuccessorIndex) {
assert(SuccessorIndex < SI->getNumSuccessors() &&
"Successor index # out of range!");
return SuccessorIndex != 0 ? CaseIteratorT(SI, SuccessorIndex - 1)
: CaseIteratorT(SI, DefaultPseudoIndex);
}
/// Support converting to the const variant. This will be a no-op for const
/// variant.
operator CaseIteratorT<ConstCaseHandle>() const {
return CaseIteratorT<ConstCaseHandle>(Case.SI, Case.Index);
}
CaseIteratorT &operator+=(ptrdiff_t N) {
// Check index correctness after addition.
// Note: Index == getNumCases() means end().
assert(Case.Index + N >= 0 &&
(unsigned)(Case.Index + N) <= Case.SI->getNumCases() &&
"Case.Index out the number of cases.");
Case.Index += N;
return *this;
}
CaseIteratorT &operator-=(ptrdiff_t N) {
// Check index correctness after subtraction.
// Note: Case.Index == getNumCases() means end().
assert(Case.Index - N >= 0 &&
(unsigned)(Case.Index - N) <= Case.SI->getNumCases() &&
"Case.Index out the number of cases.");
Case.Index -= N;
return *this;
}
ptrdiff_t operator-(const CaseIteratorT &RHS) const {
assert(Case.SI == RHS.Case.SI && "Incompatible operators.");
return Case.Index - RHS.Case.Index;
}
bool operator==(const CaseIteratorT &RHS) const { return Case == RHS.Case; }
bool operator<(const CaseIteratorT &RHS) const {
assert(Case.SI == RHS.Case.SI && "Incompatible operators.");
return Case.Index < RHS.Case.Index;
}
CaseHandleT &operator*() { return Case; }
const CaseHandleT &operator*() const { return Case; }
};
typedef CaseIteratorT<CaseHandle> CaseIt;
typedef CaseIteratorT<ConstCaseHandle> ConstCaseIt;
static SwitchInst *Create(Value *Value, BasicBlock *Default, static SwitchInst *Create(Value *Value, BasicBlock *Default,
unsigned NumCases, unsigned NumCases,
Instruction *InsertBefore = nullptr) { Instruction *InsertBefore = nullptr) {
@ -3290,30 +3325,40 @@ public:
/// default case iterator to indicate that it is handled by the default /// default case iterator to indicate that it is handled by the default
/// handler. /// handler.
CaseIt findCaseValue(const ConstantInt *C) { CaseIt findCaseValue(const ConstantInt *C) {
for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) CaseIt I = llvm::find_if(
if (i.getCaseValue() == C) cases(), [C](CaseHandle &Case) { return Case.getCaseValue() == C; });
return i; if (I != case_end())
return I;
return case_default(); return case_default();
} }
ConstCaseIt findCaseValue(const ConstantInt *C) const { ConstCaseIt findCaseValue(const ConstantInt *C) const {
for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i) ConstCaseIt I = llvm::find_if(cases(), [C](ConstCaseHandle &Case) {
if (i.getCaseValue() == C) return Case.getCaseValue() == C;
return i; });
if (I != case_end())
return I;
return case_default(); return case_default();
} }
/// Finds the unique case value for a given successor. Returns null if the /// Finds the unique case value for a given successor. Returns null if the
/// successor is not found, not unique, or is the default case. /// successor is not found, not unique, or is the default case.
ConstantInt *findCaseDest(BasicBlock *BB) { ConstantInt *findCaseDest(BasicBlock *BB) {
if (BB == getDefaultDest()) return nullptr; if (BB == getDefaultDest())
return nullptr;
ConstantInt *CI = nullptr; ConstantInt *CI = nullptr;
for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) { for (auto Case : cases()) {
if (i.getCaseSuccessor() == BB) { if (Case.getCaseSuccessor() != BB)
if (CI) return nullptr; // Multiple cases lead to BB. continue;
else CI = i.getCaseValue();
} if (CI)
return nullptr; // Multiple cases lead to BB.
CI = Case.getCaseValue();
} }
return CI; return CI;
} }
@ -3330,7 +3375,7 @@ public:
/// This action invalidates iterators for all cases following the one removed, /// This action invalidates iterators for all cases following the one removed,
/// including the case_end() iterator. It returns an iterator for the next /// including the case_end() iterator. It returns an iterator for the next
/// case. /// case.
CaseIt removeCase(CaseIt i); CaseIt removeCase(CaseIt I);
unsigned getNumSuccessors() const { return getNumOperands()/2; } unsigned getNumSuccessors() const { return getNumOperands()/2; }
BasicBlock *getSuccessor(unsigned idx) const { BasicBlock *getSuccessor(unsigned idx) const {

View File

@ -1014,8 +1014,8 @@ bool CallAnalyzer::visitSwitchInst(SwitchInst &SI) {
// does not (yet) fire. // does not (yet) fire.
SmallPtrSet<BasicBlock *, 8> SuccessorBlocks; SmallPtrSet<BasicBlock *, 8> SuccessorBlocks;
SuccessorBlocks.insert(SI.getDefaultDest()); SuccessorBlocks.insert(SI.getDefaultDest());
for (auto I = SI.case_begin(), E = SI.case_end(); I != E; ++I) for (auto Case : SI.cases())
SuccessorBlocks.insert(I.getCaseSuccessor()); SuccessorBlocks.insert(Case.getCaseSuccessor());
// Add cost corresponding to the number of distinct destinations. The first // Add cost corresponding to the number of distinct destinations. The first
// we model as free because of fallthrough. // we model as free because of fallthrough.
Cost += (SuccessorBlocks.size() - 1) * InlineConstants::InstrCost; Cost += (SuccessorBlocks.size() - 1) * InlineConstants::InstrCost;
@ -1379,7 +1379,7 @@ bool CallAnalyzer::analyzeCall(CallSite CS) {
Value *Cond = SI->getCondition(); Value *Cond = SI->getCondition();
if (ConstantInt *SimpleCond = if (ConstantInt *SimpleCond =
dyn_cast_or_null<ConstantInt>(SimplifiedValues.lookup(Cond))) { dyn_cast_or_null<ConstantInt>(SimplifiedValues.lookup(Cond))) {
BBWorklist.insert(SI->findCaseValue(SimpleCond).getCaseSuccessor()); BBWorklist.insert(SI->findCaseValue(SimpleCond)->getCaseSuccessor());
continue; continue;
} }
} }

View File

@ -1430,14 +1430,14 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom,
unsigned BitWidth = Val->getType()->getIntegerBitWidth(); unsigned BitWidth = Val->getType()->getIntegerBitWidth();
ConstantRange EdgesVals(BitWidth, DefaultCase/*isFullSet*/); ConstantRange EdgesVals(BitWidth, DefaultCase/*isFullSet*/);
for (SwitchInst::CaseIt i : SI->cases()) { for (auto Case : SI->cases()) {
ConstantRange EdgeVal(i.getCaseValue()->getValue()); ConstantRange EdgeVal(Case.getCaseValue()->getValue());
if (DefaultCase) { if (DefaultCase) {
// It is possible that the default destination is the destination of // It is possible that the default destination is the destination of
// some cases. There is no need to perform difference for those cases. // some cases. There is no need to perform difference for those cases.
if (i.getCaseSuccessor() != BBTo) if (Case.getCaseSuccessor() != BBTo)
EdgesVals = EdgesVals.difference(EdgeVal); EdgesVals = EdgesVals.difference(EdgeVal);
} else if (i.getCaseSuccessor() == BBTo) } else if (Case.getCaseSuccessor() == BBTo)
EdgesVals = EdgesVals.unionWith(EdgeVal); EdgesVals = EdgesVals.unionWith(EdgeVal);
} }
Result = LVILatticeVal::getRange(std::move(EdgesVals)); Result = LVILatticeVal::getRange(std::move(EdgesVals));

View File

@ -195,7 +195,7 @@ void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI,
Succs.assign(TI.getNumSuccessors(), true); Succs.assign(TI.getNumSuccessors(), true);
return; return;
} }
SwitchInst::CaseIt Case = SI.findCaseValue(cast<ConstantInt>(C)); SwitchInst::CaseHandle Case = *SI.findCaseValue(cast<ConstantInt>(C));
Succs[Case.getSuccessorIndex()] = true; Succs[Case.getSuccessorIndex()] = true;
} }

View File

@ -2578,7 +2578,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
Vals.push_back(VE.getTypeID(SI.getCondition()->getType())); Vals.push_back(VE.getTypeID(SI.getCondition()->getType()));
pushValue(SI.getCondition(), InstID, Vals); pushValue(SI.getCondition(), InstID, Vals);
Vals.push_back(VE.getValueID(SI.getDefaultDest())); Vals.push_back(VE.getValueID(SI.getDefaultDest()));
for (SwitchInst::ConstCaseIt Case : SI.cases()) { for (auto Case : SI.cases()) {
Vals.push_back(VE.getValueID(Case.getCaseValue())); Vals.push_back(VE.getValueID(Case.getCaseValue()));
Vals.push_back(VE.getValueID(Case.getCaseSuccessor())); Vals.push_back(VE.getValueID(Case.getCaseSuccessor()));
} }

View File

@ -5457,7 +5457,7 @@ bool CodeGenPrepare::optimizeSwitchInst(SwitchInst *SI) {
auto *ExtInst = CastInst::Create(ExtType, Cond, NewType); auto *ExtInst = CastInst::Create(ExtType, Cond, NewType);
ExtInst->insertBefore(SI); ExtInst->insertBefore(SI);
SI->setCondition(ExtInst); SI->setCondition(ExtInst);
for (SwitchInst::CaseIt Case : SI->cases()) { for (auto Case : SI->cases()) {
APInt NarrowConst = Case.getCaseValue()->getValue(); APInt NarrowConst = Case.getCaseValue()->getValue();
APInt WideConst = (ExtType == Instruction::ZExt) ? APInt WideConst = (ExtType == Instruction::ZExt) ?
NarrowConst.zext(RegWidth) : NarrowConst.sext(RegWidth); NarrowConst.zext(RegWidth) : NarrowConst.sext(RegWidth);

View File

@ -899,10 +899,10 @@ void Interpreter::visitSwitchInst(SwitchInst &I) {
// Check to see if any of the cases match... // Check to see if any of the cases match...
BasicBlock *Dest = nullptr; BasicBlock *Dest = nullptr;
for (SwitchInst::CaseIt i = I.case_begin(), e = I.case_end(); i != e; ++i) { for (auto Case : I.cases()) {
GenericValue CaseVal = getOperandValue(i.getCaseValue(), SF); GenericValue CaseVal = getOperandValue(Case.getCaseValue(), SF);
if (executeICMP_EQ(CondVal, CaseVal, ElTy).IntVal != 0) { if (executeICMP_EQ(CondVal, CaseVal, ElTy).IntVal != 0) {
Dest = cast<BasicBlock>(i.getCaseSuccessor()); Dest = cast<BasicBlock>(Case.getCaseSuccessor());
break; break;
} }
} }

View File

@ -2897,12 +2897,11 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << ", "; Out << ", ";
writeOperand(SI.getDefaultDest(), true); writeOperand(SI.getDefaultDest(), true);
Out << " ["; Out << " [";
for (SwitchInst::ConstCaseIt i = SI.case_begin(), e = SI.case_end(); for (auto Case : SI.cases()) {
i != e; ++i) {
Out << "\n "; Out << "\n ";
writeOperand(i.getCaseValue(), true); writeOperand(Case.getCaseValue(), true);
Out << ", "; Out << ", ";
writeOperand(i.getCaseSuccessor(), true); writeOperand(Case.getCaseSuccessor(), true);
} }
Out << "\n ]"; Out << "\n ]";
} else if (isa<IndirectBrInst>(I)) { } else if (isa<IndirectBrInst>(I)) {

View File

@ -3659,16 +3659,16 @@ void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
// Initialize some new operands. // Initialize some new operands.
assert(OpNo+1 < ReservedSpace && "Growing didn't work!"); assert(OpNo+1 < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(OpNo+2); setNumHungOffUseOperands(OpNo+2);
CaseIt Case(this, NewCaseIdx); CaseHandle Case(this, NewCaseIdx);
Case.setValue(OnVal); Case.setValue(OnVal);
Case.setSuccessor(Dest); Case.setSuccessor(Dest);
} }
/// removeCase - This method removes the specified case and its successor /// removeCase - This method removes the specified case and its successor
/// from the switch instruction. /// from the switch instruction.
SwitchInst::CaseIt SwitchInst::removeCase(CaseIt i) { SwitchInst::CaseIt SwitchInst::removeCase(CaseIt I) {
unsigned idx = i.getCaseIndex(); unsigned idx = I->getCaseIndex();
assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!"); assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!");
unsigned NumOps = getNumOperands(); unsigned NumOps = getNumOperands();

View File

@ -185,9 +185,9 @@ static void handleFinalSuspend(IRBuilder<> &Builder, Value *FramePtr,
coro::Shape &Shape, SwitchInst *Switch, coro::Shape &Shape, SwitchInst *Switch,
bool IsDestroy) { bool IsDestroy) {
assert(Shape.HasFinalSuspend); assert(Shape.HasFinalSuspend);
auto FinalCase = --Switch->case_end(); auto FinalCaseIt = std::prev(Switch->case_end());
BasicBlock *ResumeBB = FinalCase.getCaseSuccessor(); BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
Switch->removeCase(FinalCase); Switch->removeCase(FinalCaseIt);
if (IsDestroy) { if (IsDestroy) {
BasicBlock *OldSwitchBB = Switch->getParent(); BasicBlock *OldSwitchBB = Switch->getParent();
auto *NewSwitchBB = OldSwitchBB->splitBasicBlock(Switch, "Switch"); auto *NewSwitchBB = OldSwitchBB->splitBasicBlock(Switch, "Switch");

View File

@ -2254,11 +2254,11 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
ConstantInt *AddRHS; ConstantInt *AddRHS;
if (match(Cond, m_Add(m_Value(Op0), m_ConstantInt(AddRHS)))) { if (match(Cond, m_Add(m_Value(Op0), m_ConstantInt(AddRHS)))) {
// Change 'switch (X+4) case 1:' into 'switch (X) case -3'. // Change 'switch (X+4) case 1:' into 'switch (X) case -3'.
for (SwitchInst::CaseIt CaseIter : SI.cases()) { for (auto Case : SI.cases()) {
Constant *NewCase = ConstantExpr::getSub(CaseIter.getCaseValue(), AddRHS); Constant *NewCase = ConstantExpr::getSub(Case.getCaseValue(), AddRHS);
assert(isa<ConstantInt>(NewCase) && assert(isa<ConstantInt>(NewCase) &&
"Result of expression should be constant"); "Result of expression should be constant");
CaseIter.setValue(cast<ConstantInt>(NewCase)); Case.setValue(cast<ConstantInt>(NewCase));
} }
SI.setCondition(Op0); SI.setCondition(Op0);
return &SI; return &SI;
@ -2290,9 +2290,9 @@ Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) {
Value *NewCond = Builder->CreateTrunc(Cond, Ty, "trunc"); Value *NewCond = Builder->CreateTrunc(Cond, Ty, "trunc");
SI.setCondition(NewCond); SI.setCondition(NewCond);
for (SwitchInst::CaseIt CaseIter : SI.cases()) { for (auto Case : SI.cases()) {
APInt TruncatedCase = CaseIter.getCaseValue()->getValue().trunc(NewWidth); APInt TruncatedCase = Case.getCaseValue()->getValue().trunc(NewWidth);
CaseIter.setValue(ConstantInt::get(SI.getContext(), TruncatedCase)); Case.setValue(ConstantInt::get(SI.getContext(), TruncatedCase));
} }
return &SI; return &SI;
} }
@ -3072,17 +3072,7 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB, const DataLayout &DL,
} }
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
if (ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition())) { if (ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition())) {
// See if this is an explicit destination. Worklist.push_back(SI->findCaseValue(Cond)->getCaseSuccessor());
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
i != e; ++i)
if (i.getCaseValue() == Cond) {
BasicBlock *ReachableBB = i.getCaseSuccessor();
Worklist.push_back(ReachableBB);
continue;
}
// Otherwise it is the default destination.
Worklist.push_back(SI->getDefaultDest());
continue; continue;
} }
} }

View File

@ -236,7 +236,7 @@ static bool processSwitch(SwitchInst *SI, LazyValueInfo *LVI) {
// removing a case doesn't cause trouble for the iteration. // removing a case doesn't cause trouble for the iteration.
bool Changed = false; bool Changed = false;
for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) { for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
ConstantInt *Case = CI.getCaseValue(); ConstantInt *Case = CI->getCaseValue();
// Check to see if the switch condition is equal to/not equal to the case // Check to see if the switch condition is equal to/not equal to the case
// value on every incoming edge, equal/not equal being the same each time. // value on every incoming edge, equal/not equal being the same each time.
@ -269,7 +269,7 @@ static bool processSwitch(SwitchInst *SI, LazyValueInfo *LVI) {
if (State == LazyValueInfo::False) { if (State == LazyValueInfo::False) {
// This case never fires - remove it. // This case never fires - remove it.
CI.getCaseSuccessor()->removePredecessor(BB); CI->getCaseSuccessor()->removePredecessor(BB);
CI = SI->removeCase(CI); CI = SI->removeCase(CI);
CE = SI->case_end(); CE = SI->case_end();

View File

@ -1761,11 +1761,11 @@ bool GVN::processInstruction(Instruction *I) {
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) {
BasicBlock *Dst = i.getCaseSuccessor(); BasicBlock *Dst = i->getCaseSuccessor();
// If there is only a single edge, propagate the case value into it. // If there is only a single edge, propagate the case value into it.
if (SwitchEdges.lookup(Dst) == 1) { if (SwitchEdges.lookup(Dst) == 1) {
BasicBlockEdge E(Parent, Dst); BasicBlockEdge E(Parent, Dst);
Changed |= propagateEquality(SwitchCond, i.getCaseValue(), E, true); Changed |= propagateEquality(SwitchCond, i->getCaseValue(), E, true);
} }
} }
return Changed; return Changed;

View File

@ -1269,7 +1269,7 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB,
else if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) else if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator()))
DestBB = BI->getSuccessor(cast<ConstantInt>(Val)->isZero()); DestBB = BI->getSuccessor(cast<ConstantInt>(Val)->isZero());
else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) { else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator())) {
DestBB = SI->findCaseValue(cast<ConstantInt>(Val)).getCaseSuccessor(); DestBB = SI->findCaseValue(cast<ConstantInt>(Val))->getCaseSuccessor();
} else { } else {
assert(isa<IndirectBrInst>(BB->getTerminator()) assert(isa<IndirectBrInst>(BB->getTerminator())
&& "Unexpected terminator"); && "Unexpected terminator");

View File

@ -509,7 +509,7 @@ analyzeLoopUnrollCost(const Loop *L, unsigned TripCount, DominatorTree &DT,
KnownSucc = SI->getSuccessor(0); KnownSucc = SI->getSuccessor(0);
else if (ConstantInt *SimpleCondVal = else if (ConstantInt *SimpleCondVal =
dyn_cast<ConstantInt>(SimpleCond)) dyn_cast<ConstantInt>(SimpleCond))
KnownSucc = SI->findCaseValue(SimpleCondVal).getCaseSuccessor(); KnownSucc = SI->findCaseValue(SimpleCondVal)->getCaseSuccessor();
} }
} }
if (KnownSucc) { if (KnownSucc) {

View File

@ -709,9 +709,8 @@ bool LoopUnswitch::processCurrentLoop() {
// Do not process same value again and again. // Do not process same value again and again.
// At this point we have some cases already unswitched and // At this point we have some cases already unswitched and
// some not yet unswitched. Let's find the first not yet unswitched one. // some not yet unswitched. Let's find the first not yet unswitched one.
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); for (auto Case : SI->cases()) {
i != e; ++i) { Constant *UnswitchValCandidate = Case.getCaseValue();
Constant *UnswitchValCandidate = i.getCaseValue();
if (!BranchesInfo.isUnswitched(SI, UnswitchValCandidate)) { if (!BranchesInfo.isUnswitched(SI, UnswitchValCandidate)) {
UnswitchVal = UnswitchValCandidate; UnswitchVal = UnswitchValCandidate;
break; break;
@ -987,7 +986,7 @@ bool LoopUnswitch::TryTrivialLoopUnswitch(bool &Changed) {
if (!Cond) if (!Cond)
break; break;
// Find the target block we are definitely going to. // Find the target block we are definitely going to.
CurrentBB = SI->findCaseValue(Cond).getCaseSuccessor(); CurrentBB = SI->findCaseValue(Cond)->getCaseSuccessor();
} else { } else {
// We do not understand these terminator instructions. // We do not understand these terminator instructions.
break; break;
@ -1051,13 +1050,12 @@ bool LoopUnswitch::TryTrivialLoopUnswitch(bool &Changed) {
// this. // this.
// Note that we can't trivially unswitch on the default case or // Note that we can't trivially unswitch on the default case or
// on already unswitched cases. // on already unswitched cases.
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); for (auto Case : SI->cases()) {
i != e; ++i) {
BasicBlock *LoopExitCandidate; BasicBlock *LoopExitCandidate;
if ((LoopExitCandidate = isTrivialLoopExitBlock(currentLoop, if ((LoopExitCandidate =
i.getCaseSuccessor()))) { isTrivialLoopExitBlock(currentLoop, Case.getCaseSuccessor()))) {
// Okay, we found a trivial case, remember the value that is trivial. // Okay, we found a trivial case, remember the value that is trivial.
ConstantInt *CaseVal = i.getCaseValue(); ConstantInt *CaseVal = Case.getCaseValue();
// Check that it was not unswitched before, since already unswitched // Check that it was not unswitched before, since already unswitched
// trivial vals are looks trivial too. // trivial vals are looks trivial too.
@ -1361,9 +1359,11 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
// NOTE: if a case value for the switch is unswitched out, we record it // NOTE: if a case value for the switch is unswitched out, we record it
// after the unswitch finishes. We can not record it here as the switch // after the unswitch finishes. We can not record it here as the switch
// is not a direct user of the partial LIV. // is not a direct user of the partial LIV.
SwitchInst::CaseIt DeadCase = SI->findCaseValue(cast<ConstantInt>(Val)); SwitchInst::CaseHandle DeadCase =
*SI->findCaseValue(cast<ConstantInt>(Val));
// Default case is live for multiple values. // Default case is live for multiple values.
if (DeadCase == SI->case_default()) continue; if (DeadCase == *SI->case_default())
continue;
// Found a dead case value. Don't remove PHI nodes in the // Found a dead case value. Don't remove PHI nodes in the
// successor if they become single-entry, those PHI nodes may // successor if they become single-entry, those PHI nodes may

View File

@ -67,11 +67,11 @@ static bool handleSwitchExpect(SwitchInst &SI) {
if (!ExpectedValue) if (!ExpectedValue)
return false; return false;
SwitchInst::CaseIt Case = SI.findCaseValue(ExpectedValue); SwitchInst::CaseHandle Case = *SI.findCaseValue(ExpectedValue);
unsigned n = SI.getNumCases(); // +1 for default case. unsigned n = SI.getNumCases(); // +1 for default case.
SmallVector<uint32_t, 16> Weights(n + 1, UnlikelyBranchWeight); SmallVector<uint32_t, 16> Weights(n + 1, UnlikelyBranchWeight);
if (Case == SI.case_default()) if (Case == *SI.case_default())
Weights[0] = LikelyBranchWeight; Weights[0] = LikelyBranchWeight;
else else
Weights[Case.getCaseIndex() + 1] = LikelyBranchWeight; Weights[Case.getCaseIndex() + 1] = LikelyBranchWeight;

View File

@ -2054,8 +2054,8 @@ void NewGVN::processOutgoingEdges(TerminatorInst *TI, BasicBlock *B) {
if (CondEvaluated && isa<ConstantInt>(CondEvaluated)) { if (CondEvaluated && isa<ConstantInt>(CondEvaluated)) {
auto *CondVal = cast<ConstantInt>(CondEvaluated); auto *CondVal = cast<ConstantInt>(CondEvaluated);
// We should be able to get case value for this. // We should be able to get case value for this.
auto CaseVal = SI->findCaseValue(CondVal); auto Case = *SI->findCaseValue(CondVal);
if (CaseVal.getCaseSuccessor() == SI->getDefaultDest()) { if (Case.getCaseSuccessor() == SI->getDefaultDest()) {
// We proved the value is outside of the range of the case. // We proved the value is outside of the range of the case.
// We can't do anything other than mark the default dest as reachable, // We can't do anything other than mark the default dest as reachable,
// and go home. // and go home.
@ -2063,7 +2063,7 @@ void NewGVN::processOutgoingEdges(TerminatorInst *TI, BasicBlock *B) {
return; return;
} }
// Now get where it goes and mark it reachable. // Now get where it goes and mark it reachable.
BasicBlock *TargetBlock = CaseVal.getCaseSuccessor(); BasicBlock *TargetBlock = Case.getCaseSuccessor();
updateReachableEdge(B, TargetBlock); updateReachableEdge(B, TargetBlock);
} else { } else {
for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) { for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) {

View File

@ -604,7 +604,7 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
return; return;
} }
Succs[SI->findCaseValue(CI).getSuccessorIndex()] = true; Succs[SI->findCaseValue(CI)->getSuccessorIndex()] = true;
return; return;
} }
@ -683,7 +683,7 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
if (!CI) if (!CI)
return !SCValue.isUnknown(); return !SCValue.isUnknown();
return SI->findCaseValue(CI).getCaseSuccessor() == To; return SI->findCaseValue(CI)->getCaseSuccessor() == To;
} }
// In case of indirect branch and its address is a blockaddress, we mark // In case of indirect branch and its address is a blockaddress, we mark
@ -1554,12 +1554,12 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// If the input to SCCP is actually switch on undef, fix the undef to // If the input to SCCP is actually switch on undef, fix the undef to
// the first constant. // the first constant.
if (isa<UndefValue>(SI->getCondition())) { if (isa<UndefValue>(SI->getCondition())) {
SI->setCondition(SI->case_begin().getCaseValue()); SI->setCondition(SI->case_begin()->getCaseValue());
markEdgeExecutable(&BB, SI->case_begin().getCaseSuccessor()); markEdgeExecutable(&BB, SI->case_begin()->getCaseSuccessor());
return true; return true;
} }
markForcedConstant(SI->getCondition(), SI->case_begin().getCaseValue()); markForcedConstant(SI->getCondition(), SI->case_begin()->getCaseValue());
return true; return true;
} }
} }

View File

@ -354,7 +354,7 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB,
Cond = dyn_cast_or_null<ConstantInt>(V); Cond = dyn_cast_or_null<ConstantInt>(V);
} }
if (Cond) { // Constant fold to uncond branch! if (Cond) { // Constant fold to uncond branch!
SwitchInst::ConstCaseIt Case = SI->findCaseValue(Cond); SwitchInst::ConstCaseHandle Case = *SI->findCaseValue(Cond);
BasicBlock *Dest = const_cast<BasicBlock*>(Case.getCaseSuccessor()); BasicBlock *Dest = const_cast<BasicBlock*>(Case.getCaseSuccessor());
VMap[OldTI] = BranchInst::Create(Dest, NewBB); VMap[OldTI] = BranchInst::Create(Dest, NewBB);
ToClone.push_back(Dest); ToClone.push_back(Dest);

View File

@ -487,7 +487,7 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst,
ConstantInt *Val = ConstantInt *Val =
dyn_cast<ConstantInt>(getVal(SI->getCondition())); dyn_cast<ConstantInt>(getVal(SI->getCondition()));
if (!Val) return false; // Cannot determine. if (!Val) return false; // Cannot determine.
NextBB = SI->findCaseValue(Val).getCaseSuccessor(); NextBB = SI->findCaseValue(Val)->getCaseSuccessor();
} else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) { } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) {
Value *Val = getVal(IBI->getAddress())->stripPointerCasts(); Value *Val = getVal(IBI->getAddress())->stripPointerCasts();
if (BlockAddress *BA = dyn_cast<BlockAddress>(Val)) if (BlockAddress *BA = dyn_cast<BlockAddress>(Val))

View File

@ -126,20 +126,20 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
// If the default is unreachable, ignore it when searching for TheOnlyDest. // If the default is unreachable, ignore it when searching for TheOnlyDest.
if (isa<UnreachableInst>(DefaultDest->getFirstNonPHIOrDbg()) && if (isa<UnreachableInst>(DefaultDest->getFirstNonPHIOrDbg()) &&
SI->getNumCases() > 0) { SI->getNumCases() > 0) {
TheOnlyDest = SI->case_begin().getCaseSuccessor(); TheOnlyDest = SI->case_begin()->getCaseSuccessor();
} }
// Figure out which case it goes to. // Figure out which case it goes to.
for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) { for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
// Found case matching a constant operand? // Found case matching a constant operand?
if (i.getCaseValue() == CI) { if (i->getCaseValue() == CI) {
TheOnlyDest = i.getCaseSuccessor(); TheOnlyDest = i->getCaseSuccessor();
break; break;
} }
// Check to see if this branch is going to the same place as the default // Check to see if this branch is going to the same place as the default
// dest. If so, eliminate it as an explicit compare. // dest. If so, eliminate it as an explicit compare.
if (i.getCaseSuccessor() == DefaultDest) { if (i->getCaseSuccessor() == DefaultDest) {
MDNode *MD = SI->getMetadata(LLVMContext::MD_prof); MDNode *MD = SI->getMetadata(LLVMContext::MD_prof);
unsigned NCases = SI->getNumCases(); unsigned NCases = SI->getNumCases();
// Fold the case metadata into the default if there will be any branches // Fold the case metadata into the default if there will be any branches
@ -153,7 +153,7 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
Weights.push_back(CI->getValue().getZExtValue()); Weights.push_back(CI->getValue().getZExtValue());
} }
// Merge weight of this case to the default weight. // Merge weight of this case to the default weight.
unsigned idx = i.getCaseIndex(); unsigned idx = i->getCaseIndex();
Weights[0] += Weights[idx+1]; Weights[0] += Weights[idx+1];
// Remove weight for this case. // Remove weight for this case.
std::swap(Weights[idx+1], Weights.back()); std::swap(Weights[idx+1], Weights.back());
@ -172,7 +172,8 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
// Otherwise, check to see if the switch only branches to one destination. // Otherwise, check to see if the switch only branches to one destination.
// We do this by reseting "TheOnlyDest" to null when we find two non-equal // We do this by reseting "TheOnlyDest" to null when we find two non-equal
// destinations. // destinations.
if (i.getCaseSuccessor() != TheOnlyDest) TheOnlyDest = nullptr; if (i->getCaseSuccessor() != TheOnlyDest)
TheOnlyDest = nullptr;
// Increment this iterator as we haven't removed the case. // Increment this iterator as we haven't removed the case.
++i; ++i;
@ -211,7 +212,7 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
if (SI->getNumCases() == 1) { if (SI->getNumCases() == 1) {
// Otherwise, we can fold this switch into a conditional branch // Otherwise, we can fold this switch into a conditional branch
// instruction if it has only one non-default destination. // instruction if it has only one non-default destination.
SwitchInst::CaseIt FirstCase = SI->case_begin(); auto FirstCase = *SI->case_begin();
Value *Cond = Builder.CreateICmpEQ(SI->getCondition(), Value *Cond = Builder.CreateICmpEQ(SI->getCondition(),
FirstCase.getCaseValue(), "cond"); FirstCase.getCaseValue(), "cond");

View File

@ -356,10 +356,10 @@ unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) {
unsigned numCmps = 0; unsigned numCmps = 0;
// Start with "simple" cases // Start with "simple" cases
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) for (auto Case : SI->cases())
Cases.push_back(CaseRange(i.getCaseValue(), i.getCaseValue(), Cases.push_back(CaseRange(Case.getCaseValue(), Case.getCaseValue(),
i.getCaseSuccessor())); Case.getCaseSuccessor()));
std::sort(Cases.begin(), Cases.end(), CaseCmp()); std::sort(Cases.begin(), Cases.end(), CaseCmp());
// Merge case into clusters // Merge case into clusters

View File

@ -714,10 +714,9 @@ BasicBlock *SimplifyCFGOpt::GetValueEqualityComparisonCases(
TerminatorInst *TI, std::vector<ValueEqualityComparisonCase> &Cases) { TerminatorInst *TI, std::vector<ValueEqualityComparisonCase> &Cases) {
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) { if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
Cases.reserve(SI->getNumCases()); Cases.reserve(SI->getNumCases());
for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; for (auto Case : SI->cases())
++i) Cases.push_back(ValueEqualityComparisonCase(Case.getCaseValue(),
Cases.push_back( Case.getCaseSuccessor()));
ValueEqualityComparisonCase(i.getCaseValue(), i.getCaseSuccessor()));
return SI->getDefaultDest(); return SI->getDefaultDest();
} }
@ -850,12 +849,12 @@ bool SimplifyCFGOpt::SimplifyEqualityComparisonWithOnlyPredecessor(
} }
for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) { for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) {
--i; --i;
if (DeadCases.count(i.getCaseValue())) { if (DeadCases.count(i->getCaseValue())) {
if (HasWeight) { if (HasWeight) {
std::swap(Weights[i.getCaseIndex() + 1], Weights.back()); std::swap(Weights[i->getCaseIndex() + 1], Weights.back());
Weights.pop_back(); Weights.pop_back();
} }
i.getCaseSuccessor()->removePredecessor(TI->getParent()); i->getCaseSuccessor()->removePredecessor(TI->getParent());
SI->removeCase(i); SI->removeCase(i);
} }
} }
@ -3444,8 +3443,8 @@ static bool SimplifySwitchOnSelect(SwitchInst *SI, SelectInst *Select) {
// Find the relevant condition and destinations. // Find the relevant condition and destinations.
Value *Condition = Select->getCondition(); Value *Condition = Select->getCondition();
BasicBlock *TrueBB = SI->findCaseValue(TrueVal).getCaseSuccessor(); BasicBlock *TrueBB = SI->findCaseValue(TrueVal)->getCaseSuccessor();
BasicBlock *FalseBB = SI->findCaseValue(FalseVal).getCaseSuccessor(); BasicBlock *FalseBB = SI->findCaseValue(FalseVal)->getCaseSuccessor();
// Get weight for TrueBB and FalseBB. // Get weight for TrueBB and FalseBB.
uint32_t TrueWeight = 0, FalseWeight = 0; uint32_t TrueWeight = 0, FalseWeight = 0;
@ -3455,9 +3454,9 @@ static bool SimplifySwitchOnSelect(SwitchInst *SI, SelectInst *Select) {
GetBranchWeights(SI, Weights); GetBranchWeights(SI, Weights);
if (Weights.size() == 1 + SI->getNumCases()) { if (Weights.size() == 1 + SI->getNumCases()) {
TrueWeight = TrueWeight =
(uint32_t)Weights[SI->findCaseValue(TrueVal).getSuccessorIndex()]; (uint32_t)Weights[SI->findCaseValue(TrueVal)->getSuccessorIndex()];
FalseWeight = FalseWeight =
(uint32_t)Weights[SI->findCaseValue(FalseVal).getSuccessorIndex()]; (uint32_t)Weights[SI->findCaseValue(FalseVal)->getSuccessorIndex()];
} }
} }
@ -4160,7 +4159,7 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) {
} }
} else if (auto *SI = dyn_cast<SwitchInst>(TI)) { } else if (auto *SI = dyn_cast<SwitchInst>(TI)) {
for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) { for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
if (i.getCaseSuccessor() != BB) { if (i->getCaseSuccessor() != BB) {
++i; ++i;
continue; continue;
} }
@ -4251,18 +4250,18 @@ static bool TurnSwitchRangeIntoICmp(SwitchInst *SI, IRBuilder<> &Builder) {
SmallVector<ConstantInt *, 16> CasesA; SmallVector<ConstantInt *, 16> CasesA;
SmallVector<ConstantInt *, 16> CasesB; SmallVector<ConstantInt *, 16> CasesB;
for (SwitchInst::CaseIt I : SI->cases()) { for (auto Case : SI->cases()) {
BasicBlock *Dest = I.getCaseSuccessor(); BasicBlock *Dest = Case.getCaseSuccessor();
if (!DestA) if (!DestA)
DestA = Dest; DestA = Dest;
if (Dest == DestA) { if (Dest == DestA) {
CasesA.push_back(I.getCaseValue()); CasesA.push_back(Case.getCaseValue());
continue; continue;
} }
if (!DestB) if (!DestB)
DestB = Dest; DestB = Dest;
if (Dest == DestB) { if (Dest == DestB) {
CasesB.push_back(I.getCaseValue()); CasesB.push_back(Case.getCaseValue());
continue; continue;
} }
return false; // More than two destinations. return false; // More than two destinations.
@ -4412,17 +4411,17 @@ static bool EliminateDeadSwitchCases(SwitchInst *SI, AssumptionCache *AC,
// Remove dead cases from the switch. // Remove dead cases from the switch.
for (ConstantInt *DeadCase : DeadCases) { for (ConstantInt *DeadCase : DeadCases) {
SwitchInst::CaseIt Case = SI->findCaseValue(DeadCase); SwitchInst::CaseIt CaseI = SI->findCaseValue(DeadCase);
assert(Case != SI->case_default() && assert(CaseI != SI->case_default() &&
"Case was not found. Probably mistake in DeadCases forming."); "Case was not found. Probably mistake in DeadCases forming.");
if (HasWeight) { if (HasWeight) {
std::swap(Weights[Case.getCaseIndex() + 1], Weights.back()); std::swap(Weights[CaseI->getCaseIndex() + 1], Weights.back());
Weights.pop_back(); Weights.pop_back();
} }
// Prune unused values from PHI nodes. // Prune unused values from PHI nodes.
Case.getCaseSuccessor()->removePredecessor(SI->getParent()); CaseI->getCaseSuccessor()->removePredecessor(SI->getParent());
SI->removeCase(Case); SI->removeCase(CaseI);
} }
if (HasWeight && Weights.size() >= 2) { if (HasWeight && Weights.size() >= 2) {
SmallVector<uint32_t, 8> MDWeights(Weights.begin(), Weights.end()); SmallVector<uint32_t, 8> MDWeights(Weights.begin(), Weights.end());
@ -4476,10 +4475,9 @@ static bool ForwardSwitchConditionToPHI(SwitchInst *SI) {
typedef DenseMap<PHINode *, SmallVector<int, 4>> ForwardingNodesMap; typedef DenseMap<PHINode *, SmallVector<int, 4>> ForwardingNodesMap;
ForwardingNodesMap ForwardingNodes; ForwardingNodesMap ForwardingNodes;
for (SwitchInst::CaseIt I = SI->case_begin(), E = SI->case_end(); I != E; for (auto Case : SI->cases()) {
++I) { ConstantInt *CaseValue = Case.getCaseValue();
ConstantInt *CaseValue = I.getCaseValue(); BasicBlock *CaseDest = Case.getCaseSuccessor();
BasicBlock *CaseDest = I.getCaseSuccessor();
int PhiIndex; int PhiIndex;
PHINode *PHI = PHINode *PHI =
@ -5214,8 +5212,8 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
// common destination, as well as the min and max case values. // common destination, as well as the min and max case values.
assert(SI->case_begin() != SI->case_end()); assert(SI->case_begin() != SI->case_end());
SwitchInst::CaseIt CI = SI->case_begin(); SwitchInst::CaseIt CI = SI->case_begin();
ConstantInt *MinCaseVal = CI.getCaseValue(); ConstantInt *MinCaseVal = CI->getCaseValue();
ConstantInt *MaxCaseVal = CI.getCaseValue(); ConstantInt *MaxCaseVal = CI->getCaseValue();
BasicBlock *CommonDest = nullptr; BasicBlock *CommonDest = nullptr;
typedef SmallVector<std::pair<ConstantInt *, Constant *>, 4> ResultListTy; typedef SmallVector<std::pair<ConstantInt *, Constant *>, 4> ResultListTy;
@ -5225,7 +5223,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
SmallVector<PHINode *, 4> PHIs; SmallVector<PHINode *, 4> PHIs;
for (SwitchInst::CaseIt E = SI->case_end(); CI != E; ++CI) { for (SwitchInst::CaseIt E = SI->case_end(); CI != E; ++CI) {
ConstantInt *CaseVal = CI.getCaseValue(); ConstantInt *CaseVal = CI->getCaseValue();
if (CaseVal->getValue().slt(MinCaseVal->getValue())) if (CaseVal->getValue().slt(MinCaseVal->getValue()))
MinCaseVal = CaseVal; MinCaseVal = CaseVal;
if (CaseVal->getValue().sgt(MaxCaseVal->getValue())) if (CaseVal->getValue().sgt(MaxCaseVal->getValue()))
@ -5234,7 +5232,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
// Resulting value at phi nodes for this case value. // Resulting value at phi nodes for this case value.
typedef SmallVector<std::pair<PHINode *, Constant *>, 4> ResultsTy; typedef SmallVector<std::pair<PHINode *, Constant *>, 4> ResultsTy;
ResultsTy Results; ResultsTy Results;
if (!GetCaseResults(SI, CaseVal, CI.getCaseSuccessor(), &CommonDest, if (!GetCaseResults(SI, CaseVal, CI->getCaseSuccessor(), &CommonDest,
Results, DL, TTI)) Results, DL, TTI))
return false; return false;
@ -5515,11 +5513,10 @@ static bool ReduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder,
auto *Rot = Builder.CreateOr(LShr, Shl); auto *Rot = Builder.CreateOr(LShr, Shl);
SI->replaceUsesOfWith(SI->getCondition(), Rot); SI->replaceUsesOfWith(SI->getCondition(), Rot);
for (SwitchInst::CaseIt C = SI->case_begin(), E = SI->case_end(); C != E; for (auto Case : SI->cases()) {
++C) { auto *Orig = Case.getCaseValue();
auto *Orig = C.getCaseValue();
auto Sub = Orig->getValue() - APInt(Ty->getBitWidth(), Base); auto Sub = Orig->getValue() - APInt(Ty->getBitWidth(), Base);
C.setValue( Case.setValue(
cast<ConstantInt>(ConstantInt::get(Ty, Sub.lshr(ShiftC->getValue())))); cast<ConstantInt>(ConstantInt::get(Ty, Sub.lshr(ShiftC->getValue()))));
} }
return true; return true;

View File

@ -315,17 +315,15 @@ class FunctionDifferenceEngine {
bool Difference = false; bool Difference = false;
DenseMap<ConstantInt*,BasicBlock*> LCases; DenseMap<ConstantInt*,BasicBlock*> LCases;
for (auto Case : LI->cases())
for (SwitchInst::CaseIt I = LI->case_begin(), E = LI->case_end(); LCases[Case.getCaseValue()] = Case.getCaseSuccessor();
I != E; ++I)
LCases[I.getCaseValue()] = I.getCaseSuccessor(); for (auto Case : RI->cases()) {
ConstantInt *CaseValue = Case.getCaseValue();
for (SwitchInst::CaseIt I = RI->case_begin(), E = RI->case_end();
I != E; ++I) {
ConstantInt *CaseValue = I.getCaseValue();
BasicBlock *LCase = LCases[CaseValue]; BasicBlock *LCase = LCases[CaseValue];
if (LCase) { if (LCase) {
if (TryUnify) tryUnify(LCase, I.getCaseSuccessor()); if (TryUnify)
tryUnify(LCase, Case.getCaseSuccessor());
LCases.erase(CaseValue); LCases.erase(CaseValue);
} else if (Complain || !Difference) { } else if (Complain || !Difference) {
if (Complain) if (Complain)

View File

@ -677,5 +677,68 @@ TEST(InstructionsTest, GEPIndices) {
delete GEPI; delete GEPI;
} }
TEST(InstructionsTest, SwitchInst) {
LLVMContext C;
std::unique_ptr<BasicBlock> BB1, BB2, BB3;
BB1.reset(BasicBlock::Create(C));
BB2.reset(BasicBlock::Create(C));
BB3.reset(BasicBlock::Create(C));
// We create block 0 after the others so that it gets destroyed first and
// clears the uses of the other basic blocks.
std::unique_ptr<BasicBlock> BB0(BasicBlock::Create(C));
auto *Int32Ty = Type::getInt32Ty(C);
SwitchInst *SI =
SwitchInst::Create(UndefValue::get(Int32Ty), BB0.get(), 3, BB0.get());
SI->addCase(ConstantInt::get(Int32Ty, 1), BB1.get());
SI->addCase(ConstantInt::get(Int32Ty, 2), BB2.get());
SI->addCase(ConstantInt::get(Int32Ty, 3), BB3.get());
auto CI = SI->case_begin();
ASSERT_NE(CI, SI->case_end());
EXPECT_EQ(1, CI->getCaseValue()->getSExtValue());
EXPECT_EQ(BB1.get(), CI->getCaseSuccessor());
EXPECT_EQ(2, (CI + 1)->getCaseValue()->getSExtValue());
EXPECT_EQ(BB2.get(), (CI + 1)->getCaseSuccessor());
EXPECT_EQ(3, (CI + 2)->getCaseValue()->getSExtValue());
EXPECT_EQ(BB3.get(), (CI + 2)->getCaseSuccessor());
EXPECT_EQ(CI + 1, std::next(CI));
EXPECT_EQ(CI + 2, std::next(CI, 2));
EXPECT_EQ(CI + 3, std::next(CI, 3));
EXPECT_EQ(SI->case_end(), CI + 3);
EXPECT_EQ(0, CI - CI);
EXPECT_EQ(1, (CI + 1) - CI);
EXPECT_EQ(2, (CI + 2) - CI);
EXPECT_EQ(3, SI->case_end() - CI);
EXPECT_EQ(3, std::distance(CI, SI->case_end()));
auto CCI = const_cast<const SwitchInst *>(SI)->case_begin();
SwitchInst::ConstCaseIt CCE = SI->case_end();
ASSERT_NE(CCI, SI->case_end());
EXPECT_EQ(1, CCI->getCaseValue()->getSExtValue());
EXPECT_EQ(BB1.get(), CCI->getCaseSuccessor());
EXPECT_EQ(2, (CCI + 1)->getCaseValue()->getSExtValue());
EXPECT_EQ(BB2.get(), (CCI + 1)->getCaseSuccessor());
EXPECT_EQ(3, (CCI + 2)->getCaseValue()->getSExtValue());
EXPECT_EQ(BB3.get(), (CCI + 2)->getCaseSuccessor());
EXPECT_EQ(CCI + 1, std::next(CCI));
EXPECT_EQ(CCI + 2, std::next(CCI, 2));
EXPECT_EQ(CCI + 3, std::next(CCI, 3));
EXPECT_EQ(CCE, CCI + 3);
EXPECT_EQ(0, CCI - CCI);
EXPECT_EQ(1, (CCI + 1) - CCI);
EXPECT_EQ(2, (CCI + 2) - CCI);
EXPECT_EQ(3, CCE - CCI);
EXPECT_EQ(3, std::distance(CCI, CCE));
// Make sure that the const iterator is compatible with a const auto ref.
const auto &Handle = *CCI;
EXPECT_EQ(1, Handle.getCaseValue()->getSExtValue());
EXPECT_EQ(BB1.get(), Handle.getCaseSuccessor());
}
} // end anonymous namespace } // end anonymous namespace
} // end namespace llvm } // end namespace llvm