llvm.org GIT mirror
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).
 13 13 //===----------------------------------------------------------------------===// 14 14 15 15 #include "llvm/Transforms/Scalar.h" 16 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 16 17 #include "llvm/ADT/STLExtras.h" 17 18 #include "llvm/IR/Constants.h" 18 19 #include "llvm/IR/Function.h" 19 20 #include "llvm/IR/Instructions.h" 20 21 #include "llvm/IR/LLVMContext.h" 22 #include "llvm/IR/CFG.h" 21 23 #include "llvm/Pass.h" 22 24 #include "llvm/Support/Compiler.h" 23 25 #include "llvm/Support/Debug.h" 57 59 Low(low), High(high), BB(bb) { } 58 60 }; 59 61 60 typedef std::vector CaseVector;⏎ 62 typedef std::vector CaseVector;⏎ 61 63 typedef std::vector::iterator CaseItr; 62 64 private: 63 65 void processSwitchInst(SwitchInst *SI); 64 66 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); 70 74 }; 71 75 72 76 /// The comparison function for sorting the switch case values in the vector. 128 132 129 133 // switchConvert - Convert the switch statement into a binary lookup of 130 134 // 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) { 136 143 unsigned Size = End - Begin; 137 144 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 } 139 153 return newLeafBlock(*Begin, Val, OrigBlock, Default); 154 } 140 155 141 156 unsigned Mid = Size / 2; 142 157 std::vector LHS(Begin, Begin + Mid); 144 159 std::vector RHS(Begin + Mid, End); 145 160 DEBUG(dbgs() << "RHS: " << RHS << "\n"); 146 161 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); 156 206 157 207 // Create a new node that checks if the value is < pivot. Go to the 158 208 // left branch if it is and right branch if not. 290 340 return; 291 341 } 292 342 343 const bool DefaultIsUnreachable = 344 Default->size() == 1 && isa(Default->getTerminator()); 293 345 // Create a new, empty default block so that the new hierarchy of 294 346 // 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 } 300 356 // If there is an entry in any PHI nodes for the default edge, make sure 301 357 // to update them as well. 302 358 for (BasicBlock::iterator I = Default->begin(); isa(I); ++I) { 315 371 DEBUG(dbgs() << "Cases: " << Cases << "\n"); 316 372 (void)numCmps; 317 373 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); 320 389 321 390 // Branch to our shiny new if-then stuff... 322 391 BranchInst::Create(SwitchBlock, OrigBlock); 323 392 324 393 // We are now done with the switch instruction, delete it. 325 394 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 ; :4 27 store i32 10, i32* %1 28 br label %7 29 30 ; :5 31 store i32 3, i32* %1 32 br label %7 33 34 ; :6 35 unreachable 36 37 ; :7 38 %8 = load i32* %1 39 ret i32 %8 40 }
 2 2 ; We have switch on input. 3 3 ; On output we should got binary comparison tree. Check that all is fine. 4 4 5 ;CHECK: entry: 6 ;CHECK-NEXT: br label %NodeBlock37⏎ 5 ;CHECK: entry:⏎ 6 ;CHECK-NEXT: br label %NodeBlock19 7 7 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 11 11 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 15 15 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 19 19 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 23 23 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 27 27 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 31 31 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 35 35 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 39 39 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 43 43 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 47 47 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 51 51 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 92 56 93 57 define i32 @main(i32 %tmp158) { 94 58 entry: