| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 1 | //===- LowerSwitch.cpp - Eliminate Switch instructions --------------------===// | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 2 | // | 
| John Criswell | 482202a | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Misha Brukman | b1c9317 | 2005-04-21 23:48:37 +0000 | [diff] [blame] | 7 | // | 
| John Criswell | 482202a | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 9 | // | 
| Gordon Henriksen | d568767 | 2007-11-04 16:15:04 +0000 | [diff] [blame] | 10 | // The LowerSwitch transformation rewrites switch instructions with a sequence | 
|  | 11 | // of branches, which allows targets to get away with not implementing the | 
|  | 12 | // switch instruction until it is convenient. | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 13 | // | 
|  | 14 | //===----------------------------------------------------------------------===// | 
|  | 15 |  | 
|  | 16 | #include "llvm/Transforms/Scalar.h" | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 17 | #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 18 | #include "llvm/Constants.h" | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 19 | #include "llvm/Function.h" | 
| Misha Brukman | 2b3387a | 2004-07-29 17:05:13 +0000 | [diff] [blame] | 20 | #include "llvm/Instructions.h" | 
| Owen Anderson | e70b637 | 2009-07-05 22:41:43 +0000 | [diff] [blame] | 21 | #include "llvm/LLVMContext.h" | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 22 | #include "llvm/Pass.h" | 
| Dan Gohman | c981d72 | 2007-11-02 22:22:02 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/STLExtras.h" | 
| Chris Lattner | 3d27be1 | 2006-08-27 12:54:02 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Compiler.h" | 
| Nick Lewycky | 974e12b | 2009-10-25 06:57:41 +0000 | [diff] [blame] | 25 | #include "llvm/Support/Debug.h" | 
| Chris Lattner | 0c19df4 | 2008-08-23 22:23:09 +0000 | [diff] [blame] | 26 | #include "llvm/Support/raw_ostream.h" | 
| Alkis Evlogimenos | a5c04ee | 2004-09-03 18:19:51 +0000 | [diff] [blame] | 27 | #include <algorithm> | 
| Chris Lattner | 49525f8 | 2004-01-09 06:02:20 +0000 | [diff] [blame] | 28 | using namespace llvm; | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 29 |  | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 30 | namespace { | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 31 | /// LowerSwitch Pass - Replace all SwitchInst instructions with chained branch | 
| Chris Lattner | b45de95 | 2010-08-18 02:41:56 +0000 | [diff] [blame] | 32 | /// instructions. | 
| Nick Lewycky | 02d5f77 | 2009-10-25 06:33:48 +0000 | [diff] [blame] | 33 | class LowerSwitch : public FunctionPass { | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 34 | public: | 
| Nick Lewycky | e7da2d6 | 2007-05-06 13:37:16 +0000 | [diff] [blame] | 35 | static char ID; // Pass identification, replacement for typeid | 
| Owen Anderson | 6c18d1a | 2010-10-19 17:21:58 +0000 | [diff] [blame] | 36 | LowerSwitch() : FunctionPass(ID) { | 
|  | 37 | initializeLowerSwitchPass(*PassRegistry::getPassRegistry()); | 
|  | 38 | } | 
| Devang Patel | 09f162c | 2007-05-01 21:15:47 +0000 | [diff] [blame] | 39 |  | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 40 | virtual bool runOnFunction(Function &F); | 
| Chris Lattner | e4cb476 | 2006-05-17 21:05:27 +0000 | [diff] [blame] | 41 |  | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 42 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
| Anton Korobeynikov | fb80151 | 2007-04-16 18:10:23 +0000 | [diff] [blame] | 43 | // This is a cluster of orthogonal Transforms | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 44 | AU.addPreserved<UnifyFunctionExitNodes>(); | 
| Dan Gohman | 0f7892b | 2010-08-06 21:48:06 +0000 | [diff] [blame] | 45 | AU.addPreserved("mem2reg"); | 
| Chris Lattner | e4cb476 | 2006-05-17 21:05:27 +0000 | [diff] [blame] | 46 | AU.addPreservedID(LowerInvokePassID); | 
| Chris Lattner | 4fe87d6 | 2006-05-09 04:13:41 +0000 | [diff] [blame] | 47 | } | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 48 |  | 
|  | 49 | struct CaseRange { | 
|  | 50 | Constant* Low; | 
|  | 51 | Constant* High; | 
|  | 52 | BasicBlock* BB; | 
|  | 53 |  | 
| Chris Lattner | b45de95 | 2010-08-18 02:41:56 +0000 | [diff] [blame] | 54 | CaseRange(Constant *low = 0, Constant *high = 0, BasicBlock *bb = 0) : | 
| Jeff Cohen | 0022741 | 2007-03-12 17:56:27 +0000 | [diff] [blame] | 55 | Low(low), High(high), BB(bb) { } | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 56 | }; | 
|  | 57 |  | 
|  | 58 | typedef std::vector<CaseRange>           CaseVector; | 
|  | 59 | typedef std::vector<CaseRange>::iterator CaseItr; | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 60 | private: | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 61 | void processSwitchInst(SwitchInst *SI); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 62 |  | 
|  | 63 | BasicBlock* switchConvert(CaseItr Begin, CaseItr End, Value* Val, | 
|  | 64 | BasicBlock* OrigBlock, BasicBlock* Default); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 65 | BasicBlock* newLeafBlock(CaseRange& Leaf, Value* Val, | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 66 | BasicBlock* OrigBlock, BasicBlock* Default); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 67 | unsigned Clusterify(CaseVector& Cases, SwitchInst *SI); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 68 | }; | 
|  | 69 |  | 
|  | 70 | /// The comparison function for sorting the switch case values in the vector. | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 71 | /// WARNING: Case ranges should be disjoint! | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 72 | struct CaseCmp { | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 73 | bool operator () (const LowerSwitch::CaseRange& C1, | 
|  | 74 | const LowerSwitch::CaseRange& C2) { | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 75 |  | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 76 | const ConstantInt* CI1 = cast<const ConstantInt>(C1.Low); | 
|  | 77 | const ConstantInt* CI2 = cast<const ConstantInt>(C2.High); | 
|  | 78 | return CI1->getValue().slt(CI2->getValue()); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 79 | } | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 80 | }; | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 81 | } | 
|  | 82 |  | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 83 | char LowerSwitch::ID = 0; | 
| Owen Anderson | d31d82d | 2010-08-23 17:52:01 +0000 | [diff] [blame] | 84 | INITIALIZE_PASS(LowerSwitch, "lowerswitch", | 
| Owen Anderson | df7a4f2 | 2010-10-07 22:25:06 +0000 | [diff] [blame] | 85 | "Lower SwitchInst's to branches", false, false) | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 86 |  | 
| Chris Lattner | 0ab5e2c | 2011-04-15 05:18:47 +0000 | [diff] [blame] | 87 | // Publicly exposed interface to pass... | 
| Owen Anderson | a7aed18 | 2010-08-06 18:33:48 +0000 | [diff] [blame] | 88 | char &llvm::LowerSwitchID = LowerSwitch::ID; | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 89 | // createLowerSwitchPass - Interface to this file... | 
| Chris Lattner | 49525f8 | 2004-01-09 06:02:20 +0000 | [diff] [blame] | 90 | FunctionPass *llvm::createLowerSwitchPass() { | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 91 | return new LowerSwitch(); | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | bool LowerSwitch::runOnFunction(Function &F) { | 
|  | 95 | bool Changed = false; | 
|  | 96 |  | 
|  | 97 | for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { | 
|  | 98 | BasicBlock *Cur = I++; // Advance over block so we don't traverse new blocks | 
|  | 99 |  | 
|  | 100 | if (SwitchInst *SI = dyn_cast<SwitchInst>(Cur->getTerminator())) { | 
|  | 101 | Changed = true; | 
|  | 102 | processSwitchInst(SI); | 
|  | 103 | } | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | return Changed; | 
|  | 107 | } | 
|  | 108 |  | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 109 | // operator<< - Used for debugging purposes. | 
|  | 110 | // | 
| Daniel Dunbar | 796e43e | 2009-07-24 10:36:58 +0000 | [diff] [blame] | 111 | static raw_ostream& operator<<(raw_ostream &O, | 
| Chandler Carruth | 88c54b8 | 2010-10-23 08:10:43 +0000 | [diff] [blame] | 112 | const LowerSwitch::CaseVector &C) | 
|  | 113 | LLVM_ATTRIBUTE_USED; | 
| Mike Stump | 4798763 | 2009-07-27 23:33:34 +0000 | [diff] [blame] | 114 | static raw_ostream& operator<<(raw_ostream &O, | 
| Daniel Dunbar | 796e43e | 2009-07-24 10:36:58 +0000 | [diff] [blame] | 115 | const LowerSwitch::CaseVector &C) { | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 116 | O << "["; | 
|  | 117 |  | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 118 | for (LowerSwitch::CaseVector::const_iterator B = C.begin(), | 
| Chris Lattner | 49525f8 | 2004-01-09 06:02:20 +0000 | [diff] [blame] | 119 | E = C.end(); B != E; ) { | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 120 | O << *B->Low << " -" << *B->High; | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 121 | if (++B != E) O << ", "; | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | return O << "]"; | 
|  | 125 | } | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 126 |  | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 127 | // switchConvert - Convert the switch statement into a binary lookup of | 
|  | 128 | // the case values. The function recursively builds this tree. | 
|  | 129 | // | 
|  | 130 | BasicBlock* LowerSwitch::switchConvert(CaseItr Begin, CaseItr End, | 
|  | 131 | Value* Val, BasicBlock* OrigBlock, | 
|  | 132 | BasicBlock* Default) | 
|  | 133 | { | 
|  | 134 | unsigned Size = End - Begin; | 
|  | 135 |  | 
|  | 136 | if (Size == 1) | 
|  | 137 | return newLeafBlock(*Begin, Val, OrigBlock, Default); | 
|  | 138 |  | 
|  | 139 | unsigned Mid = Size / 2; | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 140 | std::vector<CaseRange> LHS(Begin, Begin + Mid); | 
| David Greene | 50c5423 | 2010-01-05 01:26:45 +0000 | [diff] [blame] | 141 | DEBUG(dbgs() << "LHS: " << LHS << "\n"); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 142 | std::vector<CaseRange> RHS(Begin + Mid, End); | 
| David Greene | 50c5423 | 2010-01-05 01:26:45 +0000 | [diff] [blame] | 143 | DEBUG(dbgs() << "RHS: " << RHS << "\n"); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 144 |  | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 145 | CaseRange& Pivot = *(Begin + Mid); | 
| David Greene | 50c5423 | 2010-01-05 01:26:45 +0000 | [diff] [blame] | 146 | DEBUG(dbgs() << "Pivot ==> " | 
| Chris Lattner | 0c19df4 | 2008-08-23 22:23:09 +0000 | [diff] [blame] | 147 | << cast<ConstantInt>(Pivot.Low)->getValue() << " -" | 
| Dan Gohman | 4f2fea1 | 2009-03-23 15:57:19 +0000 | [diff] [blame] | 148 | << cast<ConstantInt>(Pivot.High)->getValue() << "\n"); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 149 |  | 
|  | 150 | BasicBlock* LBranch = switchConvert(LHS.begin(), LHS.end(), Val, | 
|  | 151 | OrigBlock, Default); | 
|  | 152 | BasicBlock* RBranch = switchConvert(RHS.begin(), RHS.end(), Val, | 
|  | 153 | OrigBlock, Default); | 
|  | 154 |  | 
|  | 155 | // Create a new node that checks if the value is < pivot. Go to the | 
|  | 156 | // left branch if it is and right branch if not. | 
|  | 157 | Function* F = OrigBlock->getParent(); | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 158 | BasicBlock* NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock"); | 
| Chris Lattner | 233f97a | 2007-04-17 18:09:47 +0000 | [diff] [blame] | 159 | Function::iterator FI = OrigBlock; | 
|  | 160 | F->getBasicBlockList().insert(++FI, NewNode); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 161 |  | 
| Dan Gohman | ad1f0a1 | 2009-08-25 23:17:54 +0000 | [diff] [blame] | 162 | ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_SLT, | 
| Owen Anderson | 1e5f00e | 2009-07-09 23:48:35 +0000 | [diff] [blame] | 163 | Val, Pivot.Low, "Pivot"); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 164 | NewNode->getInstList().push_back(Comp); | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 165 | BranchInst::Create(LBranch, RBranch, Comp, NewNode); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 166 | return NewNode; | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | // newLeafBlock - Create a new leaf block for the binary lookup tree. It | 
|  | 170 | // checks if the switch's value == the case's value. If not, then it | 
|  | 171 | // jumps to the default branch. At this point in the tree, the value | 
|  | 172 | // can't be another valid case value, so the jump to the "default" branch | 
|  | 173 | // is warranted. | 
|  | 174 | // | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 175 | BasicBlock* LowerSwitch::newLeafBlock(CaseRange& Leaf, Value* Val, | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 176 | BasicBlock* OrigBlock, | 
|  | 177 | BasicBlock* Default) | 
|  | 178 | { | 
|  | 179 | Function* F = OrigBlock->getParent(); | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 180 | BasicBlock* NewLeaf = BasicBlock::Create(Val->getContext(), "LeafBlock"); | 
| Chris Lattner | 233f97a | 2007-04-17 18:09:47 +0000 | [diff] [blame] | 181 | Function::iterator FI = OrigBlock; | 
|  | 182 | F->getBasicBlockList().insert(++FI, NewLeaf); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 183 |  | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 184 | // Emit comparison | 
|  | 185 | ICmpInst* Comp = NULL; | 
|  | 186 | if (Leaf.Low == Leaf.High) { | 
|  | 187 | // Make the seteq instruction... | 
| Owen Anderson | 1e5f00e | 2009-07-09 23:48:35 +0000 | [diff] [blame] | 188 | Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_EQ, Val, | 
|  | 189 | Leaf.Low, "SwitchLeaf"); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 190 | } else { | 
|  | 191 | // Make range comparison | 
|  | 192 | if (cast<ConstantInt>(Leaf.Low)->isMinValue(true /*isSigned*/)) { | 
|  | 193 | // Val >= Min && Val <= Hi --> Val <= Hi | 
| Owen Anderson | 1e5f00e | 2009-07-09 23:48:35 +0000 | [diff] [blame] | 194 | Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_SLE, Val, Leaf.High, | 
|  | 195 | "SwitchLeaf"); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 196 | } else if (cast<ConstantInt>(Leaf.Low)->isZero()) { | 
|  | 197 | // Val >= 0 && Val <= Hi --> Val <=u Hi | 
| Owen Anderson | 1e5f00e | 2009-07-09 23:48:35 +0000 | [diff] [blame] | 198 | Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_ULE, Val, Leaf.High, | 
|  | 199 | "SwitchLeaf"); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 200 | } else { | 
|  | 201 | // Emit V-Lo <=u Hi-Lo | 
| Owen Anderson | 487375e | 2009-07-29 18:55:55 +0000 | [diff] [blame] | 202 | Constant* NegLo = ConstantExpr::getNeg(Leaf.Low); | 
| Gabor Greif | e1f6e4b | 2008-05-16 19:29:10 +0000 | [diff] [blame] | 203 | Instruction* Add = BinaryOperator::CreateAdd(Val, NegLo, | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 204 | Val->getName()+".off", | 
|  | 205 | NewLeaf); | 
| Owen Anderson | 487375e | 2009-07-29 18:55:55 +0000 | [diff] [blame] | 206 | Constant *UpperBound = ConstantExpr::getAdd(NegLo, Leaf.High); | 
| Owen Anderson | 1e5f00e | 2009-07-09 23:48:35 +0000 | [diff] [blame] | 207 | Comp = new ICmpInst(*NewLeaf, ICmpInst::ICMP_ULE, Add, UpperBound, | 
|  | 208 | "SwitchLeaf"); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 209 | } | 
|  | 210 | } | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 211 |  | 
|  | 212 | // Make the conditional branch... | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 213 | BasicBlock* Succ = Leaf.BB; | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 214 | BranchInst::Create(Succ, Default, Comp, NewLeaf); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 215 |  | 
|  | 216 | // If there were any PHI nodes in this successor, rewrite one entry | 
|  | 217 | // from OrigBlock to come from NewLeaf. | 
| Reid Spencer | 6614946 | 2004-09-15 17:06:42 +0000 | [diff] [blame] | 218 | for (BasicBlock::iterator I = Succ->begin(); isa<PHINode>(I); ++I) { | 
|  | 219 | PHINode* PN = cast<PHINode>(I); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 220 | // Remove all but one incoming entries from the cluster | 
|  | 221 | uint64_t Range = cast<ConstantInt>(Leaf.High)->getSExtValue() - | 
|  | 222 | cast<ConstantInt>(Leaf.Low)->getSExtValue(); | 
|  | 223 | for (uint64_t j = 0; j < Range; ++j) { | 
|  | 224 | PN->removeIncomingValue(OrigBlock); | 
|  | 225 | } | 
|  | 226 |  | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 227 | int BlockIdx = PN->getBasicBlockIndex(OrigBlock); | 
|  | 228 | assert(BlockIdx != -1 && "Switch didn't go to this successor??"); | 
|  | 229 | PN->setIncomingBlock((unsigned)BlockIdx, NewLeaf); | 
|  | 230 | } | 
|  | 231 |  | 
|  | 232 | return NewLeaf; | 
|  | 233 | } | 
|  | 234 |  | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 235 | // Clusterify - Transform simple list of Cases into list of CaseRange's | 
|  | 236 | unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) { | 
|  | 237 | unsigned numCmps = 0; | 
|  | 238 |  | 
|  | 239 | // Start with "simple" cases | 
|  | 240 | for (unsigned i = 1; i < SI->getNumSuccessors(); ++i) | 
|  | 241 | Cases.push_back(CaseRange(SI->getSuccessorValue(i), | 
|  | 242 | SI->getSuccessorValue(i), | 
|  | 243 | SI->getSuccessor(i))); | 
| Dan Gohman | d7917b6 | 2007-11-02 22:24:01 +0000 | [diff] [blame] | 244 | std::sort(Cases.begin(), Cases.end(), CaseCmp()); | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 245 |  | 
|  | 246 | // Merge case into clusters | 
|  | 247 | if (Cases.size()>=2) | 
| Chris Lattner | a48f44d | 2009-12-03 00:50:42 +0000 | [diff] [blame] | 248 | for (CaseItr I=Cases.begin(), J=llvm::next(Cases.begin()); J!=Cases.end(); ) { | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 249 | int64_t nextValue = cast<ConstantInt>(J->Low)->getSExtValue(); | 
|  | 250 | int64_t currentValue = cast<ConstantInt>(I->High)->getSExtValue(); | 
|  | 251 | BasicBlock* nextBB = J->BB; | 
|  | 252 | BasicBlock* currentBB = I->BB; | 
|  | 253 |  | 
|  | 254 | // If the two neighboring cases go to the same destination, merge them | 
|  | 255 | // into a single case. | 
|  | 256 | if ((nextValue-currentValue==1) && (currentBB == nextBB)) { | 
|  | 257 | I->High = J->High; | 
|  | 258 | J = Cases.erase(J); | 
|  | 259 | } else { | 
|  | 260 | I = J++; | 
|  | 261 | } | 
|  | 262 | } | 
|  | 263 |  | 
|  | 264 | for (CaseItr I=Cases.begin(), E=Cases.end(); I!=E; ++I, ++numCmps) { | 
|  | 265 | if (I->Low != I->High) | 
|  | 266 | // A range counts double, since it requires two compares. | 
|  | 267 | ++numCmps; | 
|  | 268 | } | 
|  | 269 |  | 
|  | 270 | return numCmps; | 
|  | 271 | } | 
|  | 272 |  | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 273 | // processSwitchInst - Replace the specified switch instruction with a sequence | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 274 | // of chained if-then insts in a balanced binary search. | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 275 | // | 
|  | 276 | void LowerSwitch::processSwitchInst(SwitchInst *SI) { | 
|  | 277 | BasicBlock *CurBlock = SI->getParent(); | 
|  | 278 | BasicBlock *OrigBlock = CurBlock; | 
|  | 279 | Function *F = CurBlock->getParent(); | 
|  | 280 | Value *Val = SI->getOperand(0);  // The value we are switching on... | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 281 | BasicBlock* Default = SI->getDefaultDest(); | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 282 |  | 
| Chris Lattner | f1b1c5e | 2003-08-23 22:54:34 +0000 | [diff] [blame] | 283 | // If there is only the default destination, don't bother with the code below. | 
|  | 284 | if (SI->getNumOperands() == 2) { | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 285 | BranchInst::Create(SI->getDefaultDest(), CurBlock); | 
| Chris Lattner | b686595 | 2004-03-14 04:14:31 +0000 | [diff] [blame] | 286 | CurBlock->getInstList().erase(SI); | 
| Chris Lattner | f1b1c5e | 2003-08-23 22:54:34 +0000 | [diff] [blame] | 287 | return; | 
|  | 288 | } | 
|  | 289 |  | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 290 | // Create a new, empty default block so that the new hierarchy of | 
|  | 291 | // if-then statements go to this and the PHI nodes are happy. | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 292 | BasicBlock* NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault"); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 293 | F->getBasicBlockList().insert(Default, NewDefault); | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 294 |  | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 295 | BranchInst::Create(Default, NewDefault); | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 296 |  | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 297 | // If there is an entry in any PHI nodes for the default edge, make sure | 
|  | 298 | // to update them as well. | 
| Reid Spencer | 6614946 | 2004-09-15 17:06:42 +0000 | [diff] [blame] | 299 | for (BasicBlock::iterator I = Default->begin(); isa<PHINode>(I); ++I) { | 
|  | 300 | PHINode *PN = cast<PHINode>(I); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 301 | int BlockIdx = PN->getBasicBlockIndex(OrigBlock); | 
|  | 302 | assert(BlockIdx != -1 && "Switch didn't go to this successor??"); | 
|  | 303 | PN->setIncomingBlock((unsigned)BlockIdx, NewDefault); | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 304 | } | 
|  | 305 |  | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 306 | // Prepare cases vector. | 
|  | 307 | CaseVector Cases; | 
|  | 308 | unsigned numCmps = Clusterify(Cases, SI); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 309 |  | 
| David Greene | 50c5423 | 2010-01-05 01:26:45 +0000 | [diff] [blame] | 310 | DEBUG(dbgs() << "Clusterify finished. Total clusters: " << Cases.size() | 
| Dan Gohman | 29f2baf | 2009-07-25 01:13:51 +0000 | [diff] [blame] | 311 | << ". Total compares: " << numCmps << "\n"); | 
| David Greene | 50c5423 | 2010-01-05 01:26:45 +0000 | [diff] [blame] | 312 | DEBUG(dbgs() << "Cases: " << Cases << "\n"); | 
| Mike Stump | d934cc0 | 2009-07-27 23:14:11 +0000 | [diff] [blame] | 313 | (void)numCmps; | 
| Anton Korobeynikov | 8a6dc10 | 2007-03-10 16:46:28 +0000 | [diff] [blame] | 314 |  | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 315 | BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val, | 
|  | 316 | OrigBlock, NewDefault); | 
|  | 317 |  | 
|  | 318 | // Branch to our shiny new if-then stuff... | 
| Gabor Greif | e9ecc68 | 2008-04-06 20:25:17 +0000 | [diff] [blame] | 319 | BranchInst::Create(SwitchBlock, OrigBlock); | 
| Chris Lattner | ed92216 | 2003-10-07 18:46:23 +0000 | [diff] [blame] | 320 |  | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 321 | // We are now done with the switch instruction, delete it. | 
| Chris Lattner | b686595 | 2004-03-14 04:14:31 +0000 | [diff] [blame] | 322 | CurBlock->getInstList().erase(SI); | 
| Chris Lattner | 1b094a0 | 2003-04-23 16:23:59 +0000 | [diff] [blame] | 323 | } |