// processSwitchInst - Replace the specified switch instruction with a sequence // of chained if-then instructions. // void LowerSwitchPass::processSwitchInst(SwitchInst *SI) { BasicBlock *origBlock = SI->getParent(); BasicBlock *defaultBlock = SI->getDefaultDest(); Function *F = origBlock->getParent(); Value *switchValue = SI->getCondition(); // Create a new, empty default block so that the new hierarchy of // if-then statements go to this and the PHI nodes are happy. BasicBlock* newDefault = BasicBlock::Create(getGlobalContext(), "newDefault"); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8) F->getBasicBlockList().insert(defaultBlock->getIterator(), newDefault); #else F->getBasicBlockList().insert(defaultBlock, newDefault); #endif BranchInst::Create(defaultBlock, newDefault); // If there is an entry in any PHI nodes for the default edge, make sure // to update them as well. for (BasicBlock::iterator I = defaultBlock->begin(); isa<PHINode>(I); ++I) { PHINode *PN = cast<PHINode>(I); int BlockIdx = PN->getBasicBlockIndex(origBlock); assert(BlockIdx != -1 && "Switch didn't go to this successor??"); PN->setIncomingBlock((unsigned)BlockIdx, newDefault); } CaseVector cases; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 1) for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) cases.push_back(SwitchCase(i.getCaseValue(), i.getCaseSuccessor())); #else for (unsigned i = 1; i < SI->getNumSuccessors(); ++i) cases.push_back(SwitchCase(SI->getSuccessorValue(i), SI->getSuccessor(i))); #endif // reverse cases, as switchConvert constructs a chain of // basic blocks by appending to the front. if we reverse, // the if comparisons will happen in the same order // as the cases appear in the switch std::reverse(cases.begin(), cases.end()); switchConvert(cases.begin(), cases.end(), switchValue, origBlock, newDefault); // We are now done with the switch instruction, so delete it origBlock->getInstList().erase(SI); }
// Clusterify - Transform simple list of Cases into list of CaseRange's unsigned LowerSwitch::Clusterify(CaseVector& Cases, SwitchInst *SI) { unsigned numCmps = 0; // Start with "simple" cases for (unsigned i = 1; i < SI->getNumSuccessors(); ++i) Cases.push_back(CaseRange(SI->getSuccessorValue(i), SI->getSuccessorValue(i), SI->getSuccessor(i))); std::sort(Cases.begin(), Cases.end(), CaseCmp()); // Merge case into clusters if (Cases.size()>=2) for (CaseItr I=Cases.begin(), J=llvm::next(Cases.begin()); J!=Cases.end(); ) { int64_t nextValue = cast<ConstantInt>(J->Low)->getSExtValue(); int64_t currentValue = cast<ConstantInt>(I->High)->getSExtValue(); BasicBlock* nextBB = J->BB; BasicBlock* currentBB = I->BB; // If the two neighboring cases go to the same destination, merge them // into a single case. if ((nextValue-currentValue==1) && (currentBB == nextBB)) { I->High = J->High; J = Cases.erase(J); } else { I = J++; } } for (CaseItr I=Cases.begin(), E=Cases.end(); I!=E; ++I, ++numCmps) { if (I->Low != I->High) // A range counts double, since it requires two compares. ++numCmps; } return numCmps; }
// processSwitchInst - Replace the specified switch instruction with a sequence // of chained if-then insts in a balanced binary search. // void LowerSwitch::processSwitchInst(SwitchInst *SI) { BasicBlock *CurBlock = SI->getParent(); BasicBlock *OrigBlock = CurBlock; Function *F = CurBlock->getParent(); Value *Val = SI->getOperand(0); // The value we are switching on... BasicBlock* Default = SI->getDefaultDest(); // If there is only the default destination, don't bother with the code below. if (SI->getNumOperands() == 2) { BranchInst::Create(SI->getDefaultDest(), CurBlock); CurBlock->getInstList().erase(SI); return; } // Create a new, empty default block so that the new hierarchy of // if-then statements go to this and the PHI nodes are happy. BasicBlock* NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault"); F->getBasicBlockList().insert(Default, NewDefault); BranchInst::Create(Default, NewDefault); // If there is an entry in any PHI nodes for the default edge, make sure // to update them as well. for (BasicBlock::iterator I = Default->begin(); isa<PHINode>(I); ++I) { PHINode *PN = cast<PHINode>(I); int BlockIdx = PN->getBasicBlockIndex(OrigBlock); assert(BlockIdx != -1 && "Switch didn't go to this successor??"); PN->setIncomingBlock((unsigned)BlockIdx, NewDefault); } // Prepare cases vector. CaseVector Cases; unsigned numCmps = Clusterify(Cases, SI); DEBUG(dbgs() << "Clusterify finished. Total clusters: " << Cases.size() << ". Total compares: " << numCmps << "\n"); DEBUG(dbgs() << "Cases: " << Cases << "\n"); (void)numCmps; BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val, OrigBlock, NewDefault); // Branch to our shiny new if-then stuff... BranchInst::Create(SwitchBlock, OrigBlock); // We are now done with the switch instruction, delete it. CurBlock->getInstList().erase(SI); }