//===- LowerSwitch.cpp - Eliminate Switch instructions --------------------===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// The LowerSwitch transformation rewrites switch statements with a sequence of
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iOperators.h"
-#include "llvm/iPHINode.h"
+#include "llvm/Instructions.h"
#include "llvm/Pass.h"
-#include "Support/Debug.h"
-#include "Support/Statistic.h"
-
-namespace llvm {
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
+using namespace llvm;
namespace {
- Statistic<> NumLowered("lowerswitch", "Number of SwitchInst's replaced");
-
/// LowerSwitch Pass - Replace all SwitchInst instructions with chained branch
/// instructions. Note that this cannot be a BasicBlock pass because it
/// modifies the CFG!
- class LowerSwitch : public FunctionPass {
+ class VISIBILITY_HIDDEN LowerSwitch : public FunctionPass {
public:
- bool runOnFunction(Function &F);
+ virtual bool runOnFunction(Function &F);
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ // This is a cluster of orthogonal Transforms
+ AU.addPreserved<UnifyFunctionExitNodes>();
+ AU.addPreservedID(PromoteMemoryToRegisterID);
+ AU.addPreservedID(LowerSelectID);
+ AU.addPreservedID(LowerInvokePassID);
+ AU.addPreservedID(LowerAllocationsID);
+ }
+
typedef std::pair<Constant*, BasicBlock*> Case;
typedef std::vector<Case>::iterator CaseItr;
private:
struct CaseCmp {
bool operator () (const LowerSwitch::Case& C1,
const LowerSwitch::Case& C2) {
- if (const ConstantUInt* U1 = dyn_cast<const ConstantUInt>(C1.first))
- return U1->getValue() < cast<const ConstantUInt>(C2.first)->getValue();
- const ConstantSInt* S1 = dyn_cast<const ConstantSInt>(C1.first);
- return S1->getValue() < cast<const ConstantSInt>(C2.first)->getValue();
+ const ConstantInt* CI1 = cast<const ConstantInt>(C1.first);
+ const ConstantInt* CI2 = cast<const ConstantInt>(C2.first);
+ if (CI1->getType()->isUnsigned())
+ return CI1->getZExtValue() < CI2->getZExtValue();
+ return CI1->getSExtValue() < CI2->getSExtValue();
}
};
- RegisterOpt<LowerSwitch>
+ RegisterPass<LowerSwitch>
X("lowerswitch", "Lower SwitchInst's to branches");
}
+// Publically exposed interface to pass...
+const PassInfo *llvm::LowerSwitchID = X.getPassInfo();
// createLowerSwitchPass - Interface to this file...
-FunctionPass *createLowerSwitchPass() {
+FunctionPass *llvm::createLowerSwitchPass() {
return new LowerSwitch();
}
// operator<< - Used for debugging purposes.
//
-std::ostream& operator << (std::ostream& O, std::vector<LowerSwitch::Case>& C)
-{
+std::ostream& operator<<(std::ostream &O,
+ const std::vector<LowerSwitch::Case> &C) {
O << "[";
- for (std::vector<LowerSwitch::Case>::iterator B = C.begin(), E = C.end();
- B != E; ) {
+ for (std::vector<LowerSwitch::Case>::const_iterator B = C.begin(),
+ E = C.end(); B != E; ) {
O << *B->first;
if (++B != E) O << ", ";
}
return O << "]";
}
+OStream& operator<<(OStream &O, const std::vector<LowerSwitch::Case> &C) {
+ if (O.stream()) *O.stream() << C;
+ return O;
+}
// switchConvert - Convert the switch statement into a binary lookup of
// the case values. The function recursively builds this tree.
unsigned Mid = Size / 2;
std::vector<Case> LHS(Begin, Begin + Mid);
- DEBUG(std::cerr << "LHS: " << LHS << "\n");
+ DOUT << "LHS: " << LHS << "\n";
std::vector<Case> RHS(Begin + Mid, End);
- DEBUG(std::cerr << "RHS: " << RHS << "\n");
+ DOUT << "RHS: " << RHS << "\n";
Case& Pivot = *(Begin + Mid);
- DEBUG(std::cerr << "Pivot ==> "
- << cast<ConstantUInt>(Pivot.first)->getValue() << "\n");
+ DOUT << "Pivot ==> "
+ << cast<ConstantInt>(Pivot.first)->getSExtValue() << "\n";
BasicBlock* LBranch = switchConvert(LHS.begin(), LHS.end(), Val,
OrigBlock, Default);
BasicBlock* NewNode = new BasicBlock("NodeBlock");
F->getBasicBlockList().insert(OrigBlock->getNext(), NewNode);
- SetCondInst* Comp = new SetCondInst(Instruction::SetLT, Val, Pivot.first,
- "Pivot");
+ ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_ULT, Val, Pivot.first, "Pivot");
NewNode->getInstList().push_back(Comp);
new BranchInst(LBranch, RBranch, Comp, NewNode);
return NewNode;
F->getBasicBlockList().insert(OrigBlock->getNext(), NewLeaf);
// Make the seteq instruction...
- SetCondInst* Comp = new SetCondInst(Instruction::SetEQ, Val,
- Leaf.first, "SwitchLeaf");
+ ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_EQ, Val,
+ Leaf.first, "SwitchLeaf");
NewLeaf->getInstList().push_back(Comp);
// Make the conditional branch...
// If there were any PHI nodes in this successor, rewrite one entry
// from OrigBlock to come from NewLeaf.
- for (BasicBlock::iterator I = Succ->begin();
- PHINode* PN = dyn_cast<PHINode>(I); ++I) {
+ for (BasicBlock::iterator I = Succ->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, NewLeaf);
Value *Val = SI->getOperand(0); // The value we are switching on...
BasicBlock* Default = SI->getDefaultDest();
- // Unlink the switch instruction from it's block.
- CurBlock->getInstList().remove(SI);
-
// If there is only the default destination, don't bother with the code below.
if (SI->getNumOperands() == 2) {
- new BranchInst(SI->getDefaultDest(), 0, 0, CurBlock);
- delete SI;
+ new BranchInst(SI->getDefaultDest(), CurBlock);
+ CurBlock->getInstList().erase(SI);
return;
}
BasicBlock* NewDefault = new BasicBlock("NewDefault");
F->getBasicBlockList().insert(Default, NewDefault);
- new BranchInst(Default, 0, 0, NewDefault);
+ new BranchInst(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();
- PHINode *PN = dyn_cast<PHINode>(I); ++I) {
+ 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);
Cases.push_back(Case(SI->getSuccessorValue(i), SI->getSuccessor(i)));
std::sort(Cases.begin(), Cases.end(), CaseCmp());
- DEBUG(std::cerr << "Cases: " << Cases << "\n");
+ DOUT << "Cases: " << Cases << "\n";
BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val,
OrigBlock, NewDefault);
// Branch to our shiny new if-then stuff...
- new BranchInst(SwitchBlock, 0, 0, OrigBlock);
+ new BranchInst(SwitchBlock, OrigBlock);
// We are now done with the switch instruction, delete it.
- delete SI;
+ CurBlock->getInstList().erase(SI);
}
-
-} // End llvm namespace