LowerSwitch.cpp

Go to the documentation of this file.
00001 //===-- LowerSwitch.cpp - Eliminate Switch instructions -------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Derived from LowerSwitch.cpp in LLVM, heavily modified by piotrek
00011 // to get rid of the binary search transform, as it was creating
00012 // multiple paths through the program (i.e., extra paths that didn't
00013 // exist in the original program).
00014 //
00015 //===----------------------------------------------------------------------===//
00016 
00017 #include "Passes.h"
00018 #include <algorithm>
00019 
00020 using namespace llvm;
00021 
00022 namespace klee {
00023 
00024 char LowerSwitchPass::ID = 0;
00025 
00026 // The comparison function for sorting the switch case values in the vector.
00027 struct SwitchCaseCmp {
00028   bool operator () (const LowerSwitchPass::SwitchCase& C1,
00029                     const LowerSwitchPass::SwitchCase& C2) {
00030     
00031     const ConstantInt* CI1 = cast<const ConstantInt>(C1.value);
00032     const ConstantInt* CI2 = cast<const ConstantInt>(C2.value);
00033     return CI1->getValue().slt(CI2->getValue());
00034   }
00035 };
00036 
00037 bool LowerSwitchPass::runOnFunction(Function &F) {
00038   bool changed = false;
00039 
00040   for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
00041     BasicBlock *cur = I++; // Advance over block so we don't traverse new blocks
00042 
00043     if (SwitchInst *SI = dyn_cast<SwitchInst>(cur->getTerminator())) {
00044       changed = true;
00045       processSwitchInst(SI);
00046     }
00047   }
00048 
00049   return changed;
00050 }
00051 
00052 // switchConvert - Convert the switch statement into a linear scan
00053 // through all the case values
00054 void LowerSwitchPass::switchConvert(CaseItr begin, CaseItr end,
00055                                     Value* value, BasicBlock* origBlock,
00056                                     BasicBlock* defaultBlock)
00057 {
00058   BasicBlock *curHead = defaultBlock;
00059   Function *F = origBlock->getParent();
00060   
00061   // iterate through all the cases, creating a new BasicBlock for each
00062   for (CaseItr it = begin; it < end; ++it) {
00063     BasicBlock *newBlock = BasicBlock::Create("NodeBlock");
00064     Function::iterator FI = origBlock;
00065     F->getBasicBlockList().insert(++FI, newBlock);
00066     
00067     ICmpInst *cmpInst = new ICmpInst(ICmpInst::ICMP_EQ,
00068                                      value,
00069                                      it->value,
00070                                      "Case Comparison");
00071     
00072     newBlock->getInstList().push_back(cmpInst);
00073     BranchInst::Create(it->block, curHead, cmpInst, newBlock);
00074 
00075     // If there were any PHI nodes in this successor, rewrite one entry
00076     // from origBlock to come from newBlock.
00077     for (BasicBlock::iterator bi = it->block->begin(); isa<PHINode>(bi); ++bi) {
00078       PHINode* PN = cast<PHINode>(bi);
00079 
00080       int blockIndex = PN->getBasicBlockIndex(origBlock);
00081       assert(blockIndex != -1 && "Switch didn't go to this successor??");
00082       PN->setIncomingBlock((unsigned)blockIndex, newBlock);
00083     }
00084     
00085     curHead = newBlock;
00086   }
00087 
00088   // Branch to our shiny new if-then stuff...
00089   BranchInst::Create(curHead, origBlock);
00090 }
00091 
00092 // processSwitchInst - Replace the specified switch instruction with a sequence
00093 // of chained if-then instructions.
00094 //
00095 void LowerSwitchPass::processSwitchInst(SwitchInst *SI) {
00096   BasicBlock *origBlock = SI->getParent();
00097   BasicBlock *defaultBlock = SI->getDefaultDest();
00098   Function *F = origBlock->getParent();
00099   Value *switchValue = SI->getOperand(0);
00100 
00101   // Create a new, empty default block so that the new hierarchy of
00102   // if-then statements go to this and the PHI nodes are happy.
00103   BasicBlock* newDefault = BasicBlock::Create("newDefault");
00104 
00105   F->getBasicBlockList().insert(defaultBlock, newDefault);
00106   BranchInst::Create(defaultBlock, newDefault);
00107 
00108   // If there is an entry in any PHI nodes for the default edge, make sure
00109   // to update them as well.
00110   for (BasicBlock::iterator I = defaultBlock->begin(); isa<PHINode>(I); ++I) {
00111     PHINode *PN = cast<PHINode>(I);
00112     int BlockIdx = PN->getBasicBlockIndex(origBlock);
00113     assert(BlockIdx != -1 && "Switch didn't go to this successor??");
00114     PN->setIncomingBlock((unsigned)BlockIdx, newDefault);
00115   }
00116   
00117   CaseVector cases;
00118   for (unsigned i = 1; i < SI->getNumSuccessors(); ++i)
00119     cases.push_back(SwitchCase(SI->getSuccessorValue(i),
00120                                SI->getSuccessor(i)));
00121   
00122   // reverse cases, as switchConvert constructs a chain of
00123   //   basic blocks by appending to the front. if we reverse,
00124   //   the if comparisons will happen in the same order
00125   //   as the cases appear in the switch
00126   std::reverse(cases.begin(), cases.end());
00127   
00128   switchConvert(cases.begin(), cases.end(), switchValue, origBlock, newDefault);
00129 
00130   // We are now done with the switch instruction, so delete it
00131   origBlock->getInstList().erase(SI);
00132 }
00133 
00134 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8