llvm.org GIT mirror llvm / dc2dc39
LowerSwitch: track bounding range for the condition tree. When LowerSwitch transforms a switch instruction into a tree of ifs it is actually performing a binary search into the various case ranges, to see if the current value falls into one cases range of values. So, if we have a program with something like this: switch (a) { case 0: do0(); break; case 1: do1(); break; case 2: do2(); break; default: break; } the code produced is something like this: if (a < 1) { if (a == 0) { do0(); } } else { if (a < 2) { if (a == 1) { do1(); } } else { if (a == 2) { do2(); } } } This code is inefficient because the check (a == 1) to execute do1() is not needed. The reason is that because we already checked that (a >= 1) initially by checking that also (a < 2) we basically already inferred that (a == 1) without the need of an extra basic block spawned to check if actually (a == 1). The patch addresses this problem by keeping track of already checked bounds in the LowerSwitch algorithm, so that when the time arrives to produce a Leaf Block that checks the equality with the case value / range the algorithm can decide if that block is really needed depending on the already checked bounds . For example, the above with "a = 1" would work like this: the bounds start as LB: NONE , UB: NONE as (a < 1) is emitted the bounds for the else path become LB: 1 UB: NONE. This happens because by failing the test (a < 1) we know that the value "a" cannot be smaller than 1 if we enter the else branch. After the emitting the check (a < 2) the bounds in the if branch become LB: 1 UB: 1. This is because by checking that "a" is smaller than 2 then the upper bound becomes 2 - 1 = 1. When it is time to emit the leaf block for "case 1:" we notice that 1 can be squeezed exactly in between the LB and UB, which means that if we arrived to that block there is no need to emit a block that checks if (a == 1). Patch by: Marcello Maggioni <hayarms@gmail.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211038 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 5 years ago
4 changed file(s) with 211 addition(s) and 104 deletion(s). Raw diff Collapse all Expand all
1313 //===----------------------------------------------------------------------===//
1414
1515 #include "llvm/Transforms/Scalar.h"
16 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
1617 #include "llvm/ADT/STLExtras.h"
1718 #include "llvm/IR/Constants.h"
1819 #include "llvm/IR/Function.h"
1920 #include "llvm/IR/Instructions.h"
2021 #include "llvm/IR/LLVMContext.h"
22 #include "llvm/IR/CFG.h"
2123 #include "llvm/Pass.h"
2224 #include "llvm/Support/Compiler.h"
2325 #include "llvm/Support/Debug.h"
5759 Low(low), High(high), BB(bb) { }
5860 };
5961
60 typedef std::vector CaseVector;
62 typedef std::vector CaseVector;
6163 typedef std::vector::iterator CaseItr;
6264 private:
6365 void processSwitchInst(SwitchInst *SI);
6466
65 BasicBlock* switchConvert(CaseItr Begin, CaseItr End, Value* Val,
66 BasicBlock* OrigBlock, BasicBlock* Default);
67 BasicBlock* newLeafBlock(CaseRange& Leaf, Value* Val,
68 BasicBlock* OrigBlock, BasicBlock* Default);
69 unsigned Clusterify(CaseVector& Cases, SwitchInst *SI);
67 BasicBlock *switchConvert(CaseItr Begin, CaseItr End,
68 ConstantInt *LowerBound, ConstantInt *UpperBound,
69 Value *Val, BasicBlock *OrigBlock,
70 BasicBlock *Default);
71 BasicBlock *newLeafBlock(CaseRange &Leaf, Value *Val, BasicBlock *OrigBlock,
72 BasicBlock *Default);
73 unsigned Clusterify(CaseVector &Cases, SwitchInst *SI);
7074 };
7175
7276 /// The comparison function for sorting the switch case values in the vector.
128132
129133 // switchConvert - Convert the switch statement into a binary lookup of
130134 // the case values. The function recursively builds this tree.
131 //
132 BasicBlock* LowerSwitch::switchConvert(CaseItr Begin, CaseItr End,
133 Value* Val, BasicBlock* OrigBlock,
134 BasicBlock* Default)
135 {
135 // LowerBound and UpperBound are used to keep track of the bounds for Val
136 // that have already been checked by a block emitted by one of the previous
137 // calls to switchConvert in the call stack.
138 BasicBlock *LowerSwitch::switchConvert(CaseItr Begin, CaseItr End,
139 ConstantInt *LowerBound,
140 ConstantInt *UpperBound, Value *Val,
141 BasicBlock *OrigBlock,
142 BasicBlock *Default) {
136143 unsigned Size = End - Begin;
137144
138 if (Size == 1)
145 if (Size == 1) {
146 // Check if the Case Range is perfectly squeezed in between
147 // already checked Upper and Lower bounds. If it is then we can avoid
148 // emitting the code that checks if the value actually falls in the range
149 // because the bounds already tell us so.
150 if (Begin->Low == LowerBound && Begin->High == UpperBound) {
151 return Begin->BB;
152 }
139153 return newLeafBlock(*Begin, Val, OrigBlock, Default);
154 }
140155
141156 unsigned Mid = Size / 2;
142157 std::vector LHS(Begin, Begin + Mid);
144159 std::vector RHS(Begin + Mid, End);
145160 DEBUG(dbgs() << "RHS: " << RHS << "\n");
146161
147 CaseRange& Pivot = *(Begin + Mid);
148 DEBUG(dbgs() << "Pivot ==> "
149 << cast(Pivot.Low)->getValue() << " -"
150 << cast(Pivot.High)->getValue() << "\n");
151
152 BasicBlock* LBranch = switchConvert(LHS.begin(), LHS.end(), Val,
153 OrigBlock, Default);
154 BasicBlock* RBranch = switchConvert(RHS.begin(), RHS.end(), Val,
155 OrigBlock, Default);
162 CaseRange &Pivot = *(Begin + Mid);
163 DEBUG(dbgs() << "Pivot ==> "
164 << cast(Pivot.Low)->getValue()
165 << " -" << cast(Pivot.High)->getValue() << "\n");
166
167 // NewLowerBound here should never be the integer minimal value.
168 // This is because it is computed from a case range that is never
169 // the smallest, so there is always a case range that has at least
170 // a smaller value.
171 ConstantInt *NewLowerBound = cast(Pivot.Low);
172 ConstantInt *NewUpperBound;
173
174 // If we don't have a Default block then it means that we can never
175 // have a value outside of a case range, so set the UpperBound to the highest
176 // value in the LHS part of the case ranges.
177 if (Default != nullptr) {
178 // Because NewLowerBound is never the smallest representable integer
179 // it is safe here to subtract one.
180 NewUpperBound = ConstantInt::get(NewLowerBound->getContext(),
181 NewLowerBound->getValue() - 1);
182 } else {
183 CaseItr LastLHS = LHS.begin() + LHS.size() - 1;
184 NewUpperBound = cast(LastLHS->High);
185 }
186
187 DEBUG(dbgs() << "LHS Bounds ==> ";
188 if (LowerBound) {
189 dbgs() << cast(LowerBound)->getSExtValue();
190 } else {
191 dbgs() << "NONE";
192 }
193 dbgs() << " - " << NewUpperBound->getSExtValue() << "\n";
194 dbgs() << "RHS Bounds ==> ";
195 dbgs() << NewLowerBound->getSExtValue() << " - ";
196 if (UpperBound) {
197 dbgs() << cast(UpperBound)->getSExtValue() << "\n";
198 } else {
199 dbgs() << "NONE\n";
200 });
201
202 BasicBlock *LBranch = switchConvert(LHS.begin(), LHS.end(), LowerBound,
203 NewUpperBound, Val, OrigBlock, Default);
204 BasicBlock *RBranch = switchConvert(RHS.begin(), RHS.end(), NewLowerBound,
205 UpperBound, Val, OrigBlock, Default);
156206
157207 // Create a new node that checks if the value is < pivot. Go to the
158208 // left branch if it is and right branch if not.
290340 return;
291341 }
292342
343 const bool DefaultIsUnreachable =
344 Default->size() == 1 && isa(Default->getTerminator());
293345 // Create a new, empty default block so that the new hierarchy of
294346 // if-then statements go to this and the PHI nodes are happy.
295 BasicBlock* NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault");
296 F->getBasicBlockList().insert(Default, NewDefault);
297
298 BranchInst::Create(Default, NewDefault);
299
347 // if the default block is set as an unreachable we avoid creating one
348 // because will never be a valid target.
349 BasicBlock *NewDefault = nullptr;
350 if (!DefaultIsUnreachable) {
351 NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault");
352 F->getBasicBlockList().insert(Default, NewDefault);
353
354 BranchInst::Create(Default, NewDefault);
355 }
300356 // If there is an entry in any PHI nodes for the default edge, make sure
301357 // to update them as well.
302358 for (BasicBlock::iterator I = Default->begin(); isa(I); ++I) {
315371 DEBUG(dbgs() << "Cases: " << Cases << "\n");
316372 (void)numCmps;
317373
318 BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val,
319 OrigBlock, NewDefault);
374 ConstantInt *UpperBound = nullptr;
375 ConstantInt *LowerBound = nullptr;
376
377 // Optimize the condition where Default is an unreachable block. In this case
378 // we can make the bounds tightly fitted around the case value ranges,
379 // because we know that the value passed to the switch should always be
380 // exactly one of the case values.
381 if (DefaultIsUnreachable) {
382 CaseItr LastCase = Cases.begin() + Cases.size() - 1;
383 UpperBound = cast(LastCase->High);
384 LowerBound = cast(Cases.begin()->Low);
385 }
386 BasicBlock *SwitchBlock =
387 switchConvert(Cases.begin(), Cases.end(), LowerBound, UpperBound, Val,
388 OrigBlock, NewDefault);
320389
321390 // Branch to our shiny new if-then stuff...
322391 BranchInst::Create(SwitchBlock, OrigBlock);
323392
324393 // We are now done with the switch instruction, delete it.
325394 CurBlock->getInstList().erase(SI);
326 }
395
396 pred_iterator PI = pred_begin(Default), E = pred_end(Default);
397 // If the Default block has no more predecessors just remove it
398 if (PI == E) {
399 DeleteDeadBlock(Default);
400 }
401 }
0 ; RUN: opt < %s -lowerswitch -S | FileCheck %s
1 ; CHECK-NOT: icmp eq i32 %0, 1
2
3 define i32 @foo(i32 %a) #0 {
4 entry:
5 %retval = alloca i32, align 4
6 %a.addr = alloca i32, align 4
7 store i32 %a, i32* %a.addr, align 4
8 %0 = load i32* %a.addr, align 4
9 switch i32 %0, label %sw.default [
10 i32 0, label %sw.bb
11 i32 1, label %sw.bb1
12 i32 2, label %sw.bb2
13 ]
14
15 sw.bb:
16 ret i32 12
17
18 sw.bb1:
19 ret i32 4
20
21 sw.bb2:
22 ret i32 2
23
24 sw.default:
25 ret i32 9
26 }
0 ; RUN: opt < %s -lowerswitch -S | FileCheck %s
1 ; CHECK-NOT: {{.*}}icmp eq{{.*}}
2 ;
3 ;int foo(int a) {
4 ;
5 ; switch (a) {
6 ; case 0:
7 ; return 10;
8 ; case 1:
9 ; return 3;
10 ; default:
11 ; __builtin_unreachable();
12 ; }
13 ;
14 ;}
15
16 define i32 @foo(i32 %a) nounwind ssp uwtable {
17 %1 = alloca i32, align 4
18 %2 = alloca i32, align 4
19 store i32 %a, i32* %2, align 4
20 %3 = load i32* %2, align 4
21 switch i32 %3, label %6 [
22 i32 0, label %4
23 i32 1, label %5
24 ]
25
26 ;
27 store i32 10, i32* %1
28 br label %7
29
30 ;
31 store i32 3, i32* %1
32 br label %7
33
34 ;
35 unreachable
36
37 ;
38 %8 = load i32* %1
39 ret i32 %8
40 }
22 ; We have switch on input.
33 ; On output we should got binary comparison tree. Check that all is fine.
44
5 ;CHECK: entry:
6 ;CHECK-NEXT: br label %NodeBlock37
5 ;CHECK: entry:
6 ;CHECK-NEXT: br label %NodeBlock19
77
8 ;CHECK: NodeBlock37: ; preds = %entry
9 ;CHECK-NEXT: %Pivot38 = icmp slt i32 %tmp158, 10
10 ;CHECK-NEXT: br i1 %Pivot38, label %NodeBlock13, label %NodeBlock35
8 ;CHECK: NodeBlock19: ; preds = %entry
9 ;CHECK-NEXT: %Pivot20 = icmp slt i32 %tmp158, 10
10 ;CHECK-NEXT: br i1 %Pivot20, label %NodeBlock5, label %NodeBlock17
1111
12 ;CHECK: NodeBlock35: ; preds = %NodeBlock37
13 ;CHECK-NEXT: %Pivot36 = icmp slt i32 %tmp158, 13
14 ;CHECK-NEXT: br i1 %Pivot36, label %NodeBlock23, label %NodeBlock33
12 ;CHECK: NodeBlock17: ; preds = %NodeBlock19
13 ;CHECK-NEXT: %Pivot18 = icmp slt i32 %tmp158, 13
14 ;CHECK-NEXT: br i1 %Pivot18, label %NodeBlock9, label %NodeBlock15
1515
16 ;CHECK: NodeBlock33: ; preds = %NodeBlock35
17 ;CHECK-NEXT: %Pivot34 = icmp slt i32 %tmp158, 14
18 ;CHECK-NEXT: br i1 %Pivot34, label %LeafBlock25, label %NodeBlock31
16 ;CHECK: NodeBlock15: ; preds = %NodeBlock17
17 ;CHECK-NEXT: %Pivot16 = icmp slt i32 %tmp158, 14
18 ;CHECK-NEXT: br i1 %Pivot16, label %bb330, label %NodeBlock13
1919
20 ;CHECK: NodeBlock31: ; preds = %NodeBlock33
21 ;CHECK-NEXT: %Pivot32 = icmp slt i32 %tmp158, 15
22 ;CHECK-NEXT: br i1 %Pivot32, label %LeafBlock27, label %LeafBlock29
20 ;CHECK: NodeBlock13: ; preds = %NodeBlock15
21 ;CHECK-NEXT: %Pivot14 = icmp slt i32 %tmp158, 15
22 ;CHECK-NEXT: br i1 %Pivot14, label %bb332, label %LeafBlock11
2323
24 ;CHECK: LeafBlock29: ; preds = %NodeBlock31
25 ;CHECK-NEXT: %SwitchLeaf30 = icmp eq i32 %tmp158, 15
26 ;CHECK-NEXT: br i1 %SwitchLeaf30, label %bb334, label %NewDefault
24 ;CHECK: LeafBlock11: ; preds = %NodeBlock13
25 ;CHECK-NEXT: %SwitchLeaf12 = icmp eq i32 %tmp158, 15
26 ;CHECK-NEXT: br i1 %SwitchLeaf12, label %bb334, label %NewDefault
2727
28 ;CHECK: LeafBlock27: ; preds = %NodeBlock31
29 ;CHECK-NEXT: %SwitchLeaf28 = icmp eq i32 %tmp158, 14
30 ;CHECK-NEXT: br i1 %SwitchLeaf28, label %bb332, label %NewDefault
28 ;CHECK: NodeBlock9: ; preds = %NodeBlock17
29 ;CHECK-NEXT: %Pivot10 = icmp slt i32 %tmp158, 11
30 ;CHECK-NEXT: br i1 %Pivot10, label %bb324, label %NodeBlock7
3131
32 ;CHECK: LeafBlock25: ; preds = %NodeBlock33
33 ;CHECK-NEXT: %SwitchLeaf26 = icmp eq i32 %tmp158, 13
34 ;CHECK-NEXT: br i1 %SwitchLeaf26, label %bb330, label %NewDefault
32 ;CHECK: NodeBlock7: ; preds = %NodeBlock9
33 ;CHECK-NEXT: %Pivot8 = icmp slt i32 %tmp158, 12
34 ;CHECK-NEXT: br i1 %Pivot8, label %bb326, label %bb328
3535
36 ;CHECK: NodeBlock23: ; preds = %NodeBlock35
37 ;CHECK-NEXT: %Pivot24 = icmp slt i32 %tmp158, 11
38 ;CHECK-NEXT: br i1 %Pivot24, label %LeafBlock15, label %NodeBlock21
36 ;CHECK: NodeBlock5: ; preds = %NodeBlock19
37 ;CHECK-NEXT: %Pivot6 = icmp slt i32 %tmp158, 7
38 ;CHECK-NEXT: br i1 %Pivot6, label %NodeBlock, label %NodeBlock3
3939
40 ;CHECK: NodeBlock21: ; preds = %NodeBlock23
41 ;CHECK-NEXT: %Pivot22 = icmp slt i32 %tmp158, 12
42 ;CHECK-NEXT: br i1 %Pivot22, label %LeafBlock17, label %LeafBlock19
40 ;CHECK: NodeBlock3: ; preds = %NodeBlock5
41 ;CHECK-NEXT: %Pivot4 = icmp slt i32 %tmp158, 8
42 ;CHECK-NEXT: br i1 %Pivot4, label %bb, label %NodeBlock1
4343
44 ;CHECK: LeafBlock19: ; preds = %NodeBlock21
45 ;CHECK-NEXT: %SwitchLeaf20 = icmp eq i32 %tmp158, 12
46 ;CHECK-NEXT: br i1 %SwitchLeaf20, label %bb328, label %NewDefault
44 ;CHECK: NodeBlock1: ; preds = %NodeBlock3
45 ;CHECK-NEXT: %Pivot2 = icmp slt i32 %tmp158, 9
46 ;CHECK-NEXT: br i1 %Pivot2, label %bb338, label %bb322
4747
48 ;CHECK: LeafBlock17: ; preds = %NodeBlock21
49 ;CHECK-NEXT: %SwitchLeaf18 = icmp eq i32 %tmp158, 11
50 ;CHECK-NEXT: br i1 %SwitchLeaf18, label %bb326, label %NewDefault
48 ;CHECK: NodeBlock: ; preds = %NodeBlock5
49 ;CHECK-NEXT: %Pivot = icmp slt i32 %tmp158, 0
50 ;CHECK-NEXT: br i1 %Pivot, label %LeafBlock, label %bb338
5151
52 ;CHECK: LeafBlock15: ; preds = %NodeBlock23
53 ;CHECK-NEXT: %SwitchLeaf16 = icmp eq i32 %tmp158, 10
54 ;CHECK-NEXT: br i1 %SwitchLeaf16, label %bb324, label %NewDefault
55
56 ;CHECK: NodeBlock13: ; preds = %NodeBlock37
57 ;CHECK-NEXT: %Pivot14 = icmp slt i32 %tmp158, 7
58 ;CHECK-NEXT: br i1 %Pivot14, label %NodeBlock, label %NodeBlock11
59
60 ;CHECK: NodeBlock11: ; preds = %NodeBlock13
61 ;CHECK-NEXT: %Pivot12 = icmp slt i32 %tmp158, 8
62 ;CHECK-NEXT: br i1 %Pivot12, label %LeafBlock3, label %NodeBlock9
63
64 ;CHECK: NodeBlock9: ; preds = %NodeBlock11
65 ;CHECK-NEXT: %Pivot10 = icmp slt i32 %tmp158, 9
66 ;CHECK-NEXT: br i1 %Pivot10, label %LeafBlock5, label %LeafBlock7
67
68 ;CHECK: LeafBlock7: ; preds = %NodeBlock9
69 ;CHECK-NEXT: %SwitchLeaf8 = icmp eq i32 %tmp158, 9
70 ;CHECK-NEXT: br i1 %SwitchLeaf8, label %bb322, label %NewDefault
71
72 ;CHECK: LeafBlock5: ; preds = %NodeBlock9
73 ;CHECK-NEXT: %SwitchLeaf6 = icmp eq i32 %tmp158, 8
74 ;CHECK-NEXT: br i1 %SwitchLeaf6, label %bb338, label %NewDefault
75
76 ;CHECK: LeafBlock3: ; preds = %NodeBlock11
77 ;CHECK-NEXT: %SwitchLeaf4 = icmp eq i32 %tmp158, 7
78 ;CHECK-NEXT: br i1 %SwitchLeaf4, label %bb, label %NewDefault
79
80 ;CHECK: NodeBlock: ; preds = %NodeBlock13
81 ;CHECK-NEXT: %Pivot = icmp slt i32 %tmp158, 0
82 ;CHECK-NEXT: br i1 %Pivot, label %LeafBlock, label %LeafBlock1
83
84 ;CHECK: LeafBlock1: ; preds = %NodeBlock
85 ;CHECK-NEXT: %SwitchLeaf2 = icmp ule i32 %tmp158, 6
86 ;CHECK-NEXT: br i1 %SwitchLeaf2, label %bb338, label %NewDefault
87
88 ;CHECK: LeafBlock: ; preds = %NodeBlock
89 ;CHECK-NEXT: %tmp158.off = add i32 %tmp158, 6
90 ;CHECK-NEXT: %SwitchLeaf = icmp ule i32 %tmp158.off, 4
91 ;CHECK-NEXT: br i1 %SwitchLeaf, label %bb338, label %NewDefault
52 ;CHECK: LeafBlock: ; preds = %NodeBlock
53 ;CHECK-NEXT: %tmp158.off = add i32 %tmp158, 6
54 ;CHECK-NEXT: %SwitchLeaf = icmp ule i32 %tmp158.off, 4
55 ;CHECK-NEXT: br i1 %SwitchLeaf, label %bb338, label %NewDefault
9256
9357 define i32 @main(i32 %tmp158) {
9458 entry: