llvm.org GIT mirror llvm / e2ff29c
Use range tests in LowerSwitch, where possible git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35057 91177308-0d34-0410-b5e6-96231b3b80d8 Anton Korobeynikov 12 years ago
2 changed file(s) with 166 addition(s) and 33 deletion(s). Raw diff Collapse all Expand all
3939 AU.addPreservedID(LowerInvokePassID);
4040 AU.addPreservedID(LowerAllocationsID);
4141 }
42
43 typedef std::pair Case;
44 typedef std::vector::iterator CaseItr;
42
43 struct CaseRange {
44 Constant* Low;
45 Constant* High;
46 BasicBlock* BB;
47
48 CaseRange(Constant* _Low = NULL, Constant* _High = NULL,
49 BasicBlock* _BB = NULL):
50 Low(_Low), High(_High), BB(_BB) { }
51 };
52
53 typedef std::vector CaseVector;
54 typedef std::vector::iterator CaseItr;
4555 private:
4656 void processSwitchInst(SwitchInst *SI);
4757
4858 BasicBlock* switchConvert(CaseItr Begin, CaseItr End, Value* Val,
4959 BasicBlock* OrigBlock, BasicBlock* Default);
50 BasicBlock* newLeafBlock(Case& Leaf, Value* Val,
60 BasicBlock* newLeafBlock(CaseRange& Leaf, Value* Val,
5161 BasicBlock* OrigBlock, BasicBlock* Default);
62 unsigned Clusterify(CaseVector& Cases, SwitchInst *SI);
5263 };
5364
5465 /// The comparison function for sorting the switch case values in the vector.
66 /// WARNING: Case ranges should be disjoint!
5567 struct CaseCmp {
56 bool operator () (const LowerSwitch::Case& C1,
57 const LowerSwitch::Case& C2) {
58
59 const ConstantInt* CI1 = cast(C1.first);
60 const ConstantInt* CI2 = cast(C2.first);
61 return CI1->getValue().ult(CI2->getValue());
68 bool operator () (const LowerSwitch::CaseRange& C1,
69 const LowerSwitch::CaseRange& C2) {
70
71 const ConstantInt* CI1 = cast(C1.Low);
72 const ConstantInt* CI2 = cast(C2.High);
73 return CI1->getValue().slt(CI2->getValue());
6274 }
6375 };
6476
90102
91103 // operator<< - Used for debugging purposes.
92104 //
93 std::ostream& operator<<(std::ostream &O,
94 const std::vector &C) {
105 static std::ostream& operator<<(std::ostream &O,
106 const LowerSwitch::CaseVector &C) {
95107 O << "[";
96108
97 for (std::vector::const_iterator B = C.begin(),
109 for (LowerSwitch::CaseVector::const_iterator B = C.begin(),
98110 E = C.end(); B != E; ) {
99 O << *B->first;
111 O << *B->Low << " -" << *B->High;
100112 if (++B != E) O << ", ";
101113 }
102114
103115 return O << "]";
104116 }
105 OStream& operator<<(OStream &O, const std::vector &C) {
117
118 static OStream& operator<<(OStream &O, const LowerSwitch::CaseVector &C) {
106119 if (O.stream()) *O.stream() << C;
107120 return O;
108121 }
120133 return newLeafBlock(*Begin, Val, OrigBlock, Default);
121134
122135 unsigned Mid = Size / 2;
123 std::vector> LHS(Begin, Begin + Mid);
136 std::vectorRange> LHS(Begin, Begin + Mid);
124137 DOUT << "LHS: " << LHS << "\n";
125 std::vector> RHS(Begin + Mid, End);
138 std::vectorRange> RHS(Begin + Mid, End);
126139 DOUT << "RHS: " << RHS << "\n";
127140
128 Case& Pivot = *(Begin + Mid);
141 CaseRange& Pivot = *(Begin + Mid);
129142 DEBUG( DOUT << "Pivot ==> "
130 << cast(Pivot.first)->getValue().toStringSigned(10)
143 << cast(Pivot.Low)->getValue().toStringSigned(10)
144 << " -"
145 << cast(Pivot.High)->getValue().toStringSigned(10)
131146 << "\n");
132147
133148 BasicBlock* LBranch = switchConvert(LHS.begin(), LHS.end(), Val,
141156 BasicBlock* NewNode = new BasicBlock("NodeBlock");
142157 F->getBasicBlockList().insert(OrigBlock->getNext(), NewNode);
143158
144 ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_ULT, Val, Pivot.first, "Pivot");
159 ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_SLT, Val, Pivot.Low, "Pivot");
145160 NewNode->getInstList().push_back(Comp);
146161 new BranchInst(LBranch, RBranch, Comp, NewNode);
147162 return NewNode;
153168 // can't be another valid case value, so the jump to the "default" branch
154169 // is warranted.
155170 //
156 BasicBlock* LowerSwitch::newLeafBlock(Case& Leaf, Value* Val,
171 BasicBlock* LowerSwitch::newLeafBlock(CaseRange& Leaf, Value* Val,
157172 BasicBlock* OrigBlock,
158173 BasicBlock* Default)
159174 {
161176 BasicBlock* NewLeaf = new BasicBlock("LeafBlock");
162177 F->getBasicBlockList().insert(OrigBlock->getNext(), NewLeaf);
163178
164 // Make the seteq instruction...
165 ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_EQ, Val,
166 Leaf.first, "SwitchLeaf");
167 NewLeaf->getInstList().push_back(Comp);
179 // Emit comparison
180 ICmpInst* Comp = NULL;
181 if (Leaf.Low == Leaf.High) {
182 // Make the seteq instruction...
183 Comp = new ICmpInst(ICmpInst::ICMP_EQ, Val, Leaf.Low,
184 "SwitchLeaf", NewLeaf);
185 } else {
186 // Make range comparison
187 if (cast(Leaf.Low)->isMinValue(true /*isSigned*/)) {
188 // Val >= Min && Val <= Hi --> Val <= Hi
189 Comp = new ICmpInst(ICmpInst::ICMP_SLE, Val, Leaf.High,
190 "SwitchLeaf", NewLeaf);
191 } else if (cast(Leaf.Low)->isZero()) {
192 // Val >= 0 && Val <= Hi --> Val <=u Hi
193 Comp = new ICmpInst(ICmpInst::ICMP_ULE, Val, Leaf.High,
194 "SwitchLeaf", NewLeaf);
195 } else {
196 // Emit V-Lo <=u Hi-Lo
197 Constant* NegLo = ConstantExpr::getNeg(Leaf.Low);
198 Instruction* Add = BinaryOperator::createAdd(Val, NegLo,
199 Val->getName()+".off",
200 NewLeaf);
201 Constant *UpperBound = ConstantExpr::getAdd(NegLo, Leaf.High);
202 Comp = new ICmpInst(ICmpInst::ICMP_ULE, Add, UpperBound,
203 "SwitchLeaf", NewLeaf);
204 }
205 }
168206
169207 // Make the conditional branch...
170 BasicBlock* Succ = Leaf.second;
208 BasicBlock* Succ = Leaf.BB;
171209 new BranchInst(Succ, Default, Comp, NewLeaf);
172210
173211 // If there were any PHI nodes in this successor, rewrite one entry
174212 // from OrigBlock to come from NewLeaf.
175213 for (BasicBlock::iterator I = Succ->begin(); isa(I); ++I) {
176214 PHINode* PN = cast(I);
215 // Remove all but one incoming entries from the cluster
216 uint64_t Range = cast(Leaf.High)->getSExtValue() -
217 cast(Leaf.Low)->getSExtValue();
218 for (uint64_t j = 0; j < Range; ++j) {
219 PN->removeIncomingValue(OrigBlock);
220 }
221
177222 int BlockIdx = PN->getBasicBlockIndex(OrigBlock);
178223 assert(BlockIdx != -1 && "Switch didn't go to this successor??");
179224 PN->setIncomingBlock((unsigned)BlockIdx, NewLeaf);
180225 }
181226
182227 return NewLeaf;
228 }
229
230 // Clusterify - Transform simple list of Cases into list of CaseRange's
231 unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) {
232 unsigned numCmps = 0;
233
234 // Start with "simple" cases
235 for (unsigned i = 1; i < SI->getNumSuccessors(); ++i)
236 Cases.push_back(CaseRange(SI->getSuccessorValue(i),
237 SI->getSuccessorValue(i),
238 SI->getSuccessor(i)));
239 sort(Cases.begin(), Cases.end(), CaseCmp());
240
241 // Merge case into clusters
242 if (Cases.size()>=2)
243 for (CaseItr I=Cases.begin(), J=++(Cases.begin()), E=Cases.end(); J!=E; ) {
244 int64_t nextValue = cast(J->Low)->getSExtValue();
245 int64_t currentValue = cast(I->High)->getSExtValue();
246 BasicBlock* nextBB = J->BB;
247 BasicBlock* currentBB = I->BB;
248
249 // If the two neighboring cases go to the same destination, merge them
250 // into a single case.
251 if ((nextValue-currentValue==1) && (currentBB == nextBB)) {
252 I->High = J->High;
253 J = Cases.erase(J);
254 } else {
255 I = J++;
256 }
257 }
258
259 for (CaseItr I=Cases.begin(), E=Cases.end(); I!=E; ++I, ++numCmps) {
260 if (I->Low != I->High)
261 // A range counts double, since it requires two compares.
262 ++numCmps;
263 }
264
265 return numCmps;
183266 }
184267
185268 // processSwitchInst - Replace the specified switch instruction with a sequence
215298 PN->setIncomingBlock((unsigned)BlockIdx, NewDefault);
216299 }
217300
218 std::vector Cases;
219
220 // Expand comparisons for all of the non-default cases...
221 for (unsigned i = 1; i < SI->getNumSuccessors(); ++i)
222 Cases.push_back(Case(SI->getSuccessorValue(i), SI->getSuccessor(i)));
223
224 std::sort(Cases.begin(), Cases.end(), CaseCmp());
301 // Prepare cases vector.
302 CaseVector Cases;
303 unsigned numCmps = Clusterify(Cases, SI);
304
305 DOUT << "Clusterify finished. Total clusters: " << Cases.size()
306 << ". Total compares: " << numCmps << "\n";
225307 DOUT << "Cases: " << Cases << "\n";
308
226309 BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val,
227310 OrigBlock, NewDefault);
228311
0 ; RUN: llvm-as %s -o - | opt -lowerswitch | llvm-dis | grep slt | wc -l | grep 10 &&
1 ; RUN: llvm-as %s -o - | opt -lowerswitch | llvm-dis | grep ule | wc -l | grep 3 &&
2 ; RUN: llvm-as %s -o - | opt -lowerswitch | llvm-dis | grep eq | wc -l | grep 9
3
4 define i32 @main(i32 %tmp158) {
5 entry:
6 switch i32 %tmp158, label %bb336 [
7 i32 -2, label %bb338
8 i32 -3, label %bb338
9 i32 -4, label %bb338
10 i32 -5, label %bb338
11 i32 -6, label %bb338
12 i32 0, label %bb338
13 i32 1, label %bb338
14 i32 2, label %bb338
15 i32 3, label %bb338
16 i32 4, label %bb338
17 i32 5, label %bb338
18 i32 6, label %bb338
19 i32 7, label %bb
20 i32 8, label %bb338
21 i32 9, label %bb322
22 i32 10, label %bb324
23 i32 11, label %bb326
24 i32 12, label %bb328
25 i32 13, label %bb330
26 i32 14, label %bb332
27 i32 15, label %bb334
28 ]
29 bb:
30 ret i32 2
31 bb322:
32 ret i32 3
33 bb324:
34 ret i32 4
35 bb326:
36 ret i32 5
37 bb328:
38 ret i32 6
39 bb330:
40 ret i32 7
41 bb332:
42 ret i32 8
43 bb334:
44 ret i32 9
45 bb336:
46 ret i32 10
47 bb338:
48 ret i32 11
49 }