43 #define DEBUG_TYPE "lower-switch" 55 const std::vector<IntRange> &Ranges) {
62 Ranges.begin(), Ranges.end(), R,
63 [](
const IntRange &A,
const IntRange &
B) {
return A.High <
B.High; });
64 return I != Ranges.end() &&
I->Low <= R.Low;
87 : Low(low),
High(high), BB(bb) {}
90 using CaseVector = std::vector<CaseRange>;
91 using CaseItr = std::vector<CaseRange>::iterator;
96 BasicBlock *switchConvert(CaseItr Begin, CaseItr End,
100 const std::vector<IntRange> &UnreachableRanges);
103 unsigned Clusterify(CaseVector &Cases,
SwitchInst *SI);
109 bool operator()(
const LowerSwitch::CaseRange& C1,
110 const LowerSwitch::CaseRange& C2) {
111 const ConstantInt* CI1 = cast<const ConstantInt>(C1.Low);
112 const ConstantInt* CI2 = cast<const ConstantInt>(C2.High);
125 "Lower SwitchInst's to branches",
false,
false)
129 return new LowerSwitch();
133 bool Changed =
false;
141 if (DeleteList.
count(Cur))
146 processSwitchInst(
SI, DeleteList);
160 const LowerSwitch::CaseVector &
C) {
163 for (LowerSwitch::CaseVector::const_iterator
B = C.begin(),
164 E = C.end();
B !=
E; ) {
165 O << *
B->Low <<
" -" << *
B->High;
166 if (++
B !=
E) O <<
", ";
183 unsigned NumMergedCases) {
191 unsigned LocalNumMergedCases = NumMergedCases;
192 for (; Idx !=
E; ++Idx) {
202 for (++Idx; LocalNumMergedCases > 0 && Idx <
E; ++Idx)
205 LocalNumMergedCases--;
220 LowerSwitch::switchConvert(CaseItr Begin, CaseItr End,
ConstantInt *LowerBound,
224 const std::vector<IntRange> &UnreachableRanges) {
225 unsigned Size = End - Begin;
232 if (Begin->Low == LowerBound && Begin->High == UpperBound) {
233 unsigned NumMergedCases = 0;
234 if (LowerBound && UpperBound)
237 fixPhis(Begin->BB, OrigBlock, Predecessor, NumMergedCases);
240 return newLeafBlock(*Begin, Val, OrigBlock, Default);
243 unsigned Mid = Size / 2;
244 std::vector<CaseRange> LHS(Begin, Begin + Mid);
246 std::vector<CaseRange> RHS(Begin + Mid, End);
249 CaseRange &Pivot = *(Begin + Mid);
250 LLVM_DEBUG(
dbgs() <<
"Pivot ==> " << Pivot.Low->getValue() <<
" -" 251 << Pivot.High->getValue() <<
"\n");
262 NewLowerBound->getValue() - 1);
264 if (!UnreachableRanges.empty()) {
266 int64_t GapLow = LHS.back().High->getSExtValue() + 1;
267 int64_t GapHigh = NewLowerBound->getSExtValue() - 1;
268 IntRange Gap = { GapLow, GapHigh };
269 if (GapHigh >= GapLow &&
IsInRanges(Gap, UnreachableRanges))
270 NewUpperBound = LHS.back().High;
275 }
else {
dbgs() <<
"NONE"; }
dbgs() <<
" - " 277 dbgs() <<
"RHS Bounds ==> ";
278 dbgs() << NewLowerBound->getSExtValue() <<
" - ";
if (UpperBound) {
280 }
else {
dbgs() <<
"NONE\n"; });
288 Val, Pivot.Low,
"Pivot");
290 BasicBlock *LBranch = switchConvert(LHS.begin(), LHS.end(), LowerBound,
291 NewUpperBound, Val, NewNode, OrigBlock,
293 BasicBlock *RBranch = switchConvert(RHS.begin(), RHS.end(), NewLowerBound,
294 UpperBound, Val, NewNode, OrigBlock,
297 F->getBasicBlockList().insert(++OrigBlock->getIterator(), NewNode);
317 if (Leaf.Low == Leaf.High) {
320 Leaf.Low,
"SwitchLeaf");
323 if (Leaf.Low->isMinValue(
true )) {
327 }
else if (Leaf.Low->isZero()) {
352 uint64_t Range = Leaf.High->getSExtValue() -
353 Leaf.Low->getSExtValue();
354 for (uint64_t j = 0; j < Range; ++j) {
359 assert(BlockIdx != -1 &&
"Switch didn't go to this successor??");
367 unsigned LowerSwitch::Clusterify(CaseVector& Cases,
SwitchInst *
SI) {
368 unsigned numCmps = 0;
371 for (
auto Case : SI->
cases())
372 Cases.push_back(CaseRange(Case.getCaseValue(), Case.getCaseValue(),
373 Case.getCaseSuccessor()));
378 if (Cases.size() >= 2) {
379 CaseItr
I = Cases.begin();
380 for (CaseItr J = std::next(I),
E = Cases.end(); J !=
E; ++J) {
381 int64_t nextValue = J->Low->getSExtValue();
382 int64_t currentValue = I->High->getSExtValue();
388 assert(nextValue > currentValue &&
"Cases should be strictly ascending");
389 if ((nextValue == currentValue + 1) && (currentBB == nextBB)) {
392 }
else if (++I != J) {
396 Cases.erase(std::next(I), Cases.end());
399 for (CaseItr
I=Cases.begin(),
E=Cases.end();
I!=
E; ++
I, ++numCmps) {
400 if (
I->Low !=
I->High)
410 void LowerSwitch::processSwitchInst(
SwitchInst *SI,
422 DeleteList.
insert(CurBlock);
435 unsigned numCmps = Clusterify(Cases, SI);
436 LLVM_DEBUG(
dbgs() <<
"Clusterify finished. Total clusters: " << Cases.size()
437 <<
". Total compares: " << numCmps <<
"\n");
443 std::vector<IntRange> UnreachableRanges;
450 LowerBound = Cases.front().Low;
451 UpperBound = Cases.back().High;
457 IntRange R = {std::numeric_limits<int64_t>::min(),
459 UnreachableRanges.push_back(R);
460 for (
const auto &
I : Cases) {
461 int64_t Low =
I.Low->getSExtValue();
462 int64_t
High =
I.High->getSExtValue();
464 IntRange &LastRange = UnreachableRanges.back();
465 if (LastRange.Low == Low) {
467 UnreachableRanges.pop_back();
470 assert(Low > LastRange.Low);
471 LastRange.High = Low - 1;
475 UnreachableRanges.push_back(R);
479 int64_t
N = High - Low + 1;
480 unsigned &Pop = Popularity[
I.BB];
481 if ((Pop += N) > MaxPop) {
488 for (
auto I = UnreachableRanges.begin(),
E = UnreachableRanges.end();
504 assert(MaxPop > 0 && PopSucc);
508 Cases, [PopSucc](
const CaseRange &R) {
return R.BB == PopSucc; }),
517 for (
unsigned I = 0 ;
I < (MaxPop - 1) ; ++
I)
524 for (
const auto &Case : SI->
cases())
525 if (Case.getCaseSuccessor() ==
Default)
535 switchConvert(Cases.begin(), Cases.end(), LowerBound, UpperBound, Val,
536 OrigBlock, OrigBlock, NewDefault, UnreachableRanges);
540 fixPhis(Default, OrigBlock, NewDefault, NrOfDefaults);
551 DeleteList.
insert(OldDefault);
unsigned getNumCases() const
Return the number of 'cases' in this switch instruction, excluding the default case.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs=false)
Notify the BasicBlock that the predecessor Pred is no longer able to reach it.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
iterator_range< CaseIt > cases()
Iteration adapter for range-for loops.
iterator erase(iterator where)
This class represents lattice values for constants.
FunctionPass * createLowerSwitchPass()
void push_back(const T &Elt)
bool slt(const APInt &RHS) const
Signed less than comparison.
Value * getCondition() const
static bool IsInRanges(const IntRange &R, const std::vector< IntRange > &Ranges)
void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU=nullptr)
Delete the specified block, which must have no predecessors.
LLVMContext & getContext() const
All values hold a context through their type.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
iterator begin()
Instruction iterator methods.
static Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
Value * removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty=true)
Remove an incoming value.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
const APInt & getValue() const
Return the constant as an APInt value reference.
auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
static BinaryOperator * CreateAdd(Value *S1, Value *S2, const Twine &Name, Instruction *InsertBefore, Value *FlagsOp)
#define LLVM_ATTRIBUTE_USED
const BasicBlock & getEntryBlock() const
static bool runOnFunction(Function &F, bool PostInlining)
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM Basic Block Representation.
INITIALIZE_PASS(LowerSwitch, "lowerswitch", "Lower SwitchInst's to branches", false, false) FunctionPass *llvm
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
BasicBlock * getDefaultDest() const
static void fixPhis(BasicBlock *SuccBB, BasicBlock *OrigBB, BasicBlock *NewBB, unsigned NumMergedCases)
Update the first occurrence of the "switch statement" BB in the PHI node with the "new" BB...
This instruction compares its operands according to the predicate given to the constructor.
FunctionPass class - This class is used to implement most global optimizations.
Interval::pred_iterator pred_end(Interval *I)
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
self_iterator getIterator()
bool pred_empty(const BasicBlock *BB)
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
void sort(IteratorTy Start, IteratorTy End)
const InstListType & getInstList() const
Return the underlying instruction list container.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
void setIncomingBlock(unsigned i, BasicBlock *BB)
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
unsigned getNumIncomingValues() const
Return the number of incoming edges.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void push_back(pointer val)
static Constant * getNeg(Constant *C, bool HasNUW=false, bool HasNSW=false)
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
iterator insert(iterator where, pointer New)
StringRef getName() const
Return a constant reference to the value's name.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
const Function * getParent() const
Return the enclosing method, or null if none.
const BasicBlockListType & getBasicBlockList() const
Get the underlying elements of the Function...
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
void initializeLowerSwitchPass(PassRegistry &)
This class implements an extremely fast bulk output stream that can only output to a stream...
const Instruction * getFirstNonPHIOrDbg() const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic...
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
const BasicBlock * getParent() const