summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/LowerSwitch.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-07-27 04:24:14 +0000
committerChris Lattner <sabre@nondot.org>2006-07-27 04:24:14 +0000
commit85ea83e821e9e0f7fa242e793aa9e919eae6b828 (patch)
tree112867f6466f467ff37cb2cbdd3183659ac60498 /llvm/lib/Transforms/Scalar/LowerSwitch.cpp
parent4da479b02bd2734bb19a802b22621ad5b195ee81 (diff)
downloadbcm5719-llvm-85ea83e821e9e0f7fa242e793aa9e919eae6b828.tar.gz
bcm5719-llvm-85ea83e821e9e0f7fa242e793aa9e919eae6b828.zip
Add some advice
llvm-svn: 29324
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LowerSwitch.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/LowerSwitch.cpp237
1 files changed, 0 insertions, 237 deletions
diff --git a/llvm/lib/Transforms/Scalar/LowerSwitch.cpp b/llvm/lib/Transforms/Scalar/LowerSwitch.cpp
deleted file mode 100644
index 396b507bbd1..00000000000
--- a/llvm/lib/Transforms/Scalar/LowerSwitch.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-//===- 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
-// branches, which allows targets to get away with not implementing the switch
-// statement until it is convenient.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
-#include "llvm/Constants.h"
-#include "llvm/Function.h"
-#include "llvm/Instructions.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Visibility.h"
-#include "llvm/ADT/Statistic.h"
-#include <algorithm>
-#include <iostream>
-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 VISIBILITY_HIDDEN LowerSwitch : public FunctionPass {
- public:
- 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:
- void processSwitchInst(SwitchInst *SI);
-
- BasicBlock* switchConvert(CaseItr Begin, CaseItr End, Value* Val,
- BasicBlock* OrigBlock, BasicBlock* Default);
- BasicBlock* newLeafBlock(Case& Leaf, Value* Val,
- BasicBlock* OrigBlock, BasicBlock* Default);
- };
-
- /// The comparison function for sorting the switch case values in the vector.
- 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();
- }
- };
-
- RegisterOpt<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 *llvm::createLowerSwitchPass() {
- return new LowerSwitch();
-}
-
-bool LowerSwitch::runOnFunction(Function &F) {
- bool Changed = false;
-
- for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
- BasicBlock *Cur = I++; // Advance over block so we don't traverse new blocks
-
- if (SwitchInst *SI = dyn_cast<SwitchInst>(Cur->getTerminator())) {
- Changed = true;
- processSwitchInst(SI);
- }
- }
-
- return Changed;
-}
-
-// operator<< - Used for debugging purposes.
-//
-std::ostream& operator<<(std::ostream &O,
- const std::vector<LowerSwitch::Case> &C) {
- O << "[";
-
- for (std::vector<LowerSwitch::Case>::const_iterator B = C.begin(),
- E = C.end(); B != E; ) {
- O << *B->first;
- if (++B != E) O << ", ";
- }
-
- return O << "]";
-}
-
-// switchConvert - Convert the switch statement into a binary lookup of
-// the case values. The function recursively builds this tree.
-//
-BasicBlock* LowerSwitch::switchConvert(CaseItr Begin, CaseItr End,
- Value* Val, BasicBlock* OrigBlock,
- BasicBlock* Default)
-{
- unsigned Size = End - Begin;
-
- if (Size == 1)
- return newLeafBlock(*Begin, Val, OrigBlock, Default);
-
- unsigned Mid = Size / 2;
- std::vector<Case> LHS(Begin, Begin + Mid);
- DEBUG(std::cerr << "LHS: " << LHS << "\n");
- std::vector<Case> RHS(Begin + Mid, End);
- DEBUG(std::cerr << "RHS: " << RHS << "\n");
-
- Case& Pivot = *(Begin + Mid);
- DEBUG(std::cerr << "Pivot ==> "
- << (int64_t)cast<ConstantInt>(Pivot.first)->getRawValue()
- << "\n");
-
- BasicBlock* LBranch = switchConvert(LHS.begin(), LHS.end(), Val,
- OrigBlock, Default);
- BasicBlock* RBranch = switchConvert(RHS.begin(), RHS.end(), Val,
- OrigBlock, Default);
-
- // Create a new node that checks if the value is < pivot. Go to the
- // left branch if it is and right branch if not.
- Function* F = OrigBlock->getParent();
- BasicBlock* NewNode = new BasicBlock("NodeBlock");
- F->getBasicBlockList().insert(OrigBlock->getNext(), NewNode);
-
- SetCondInst* Comp = new SetCondInst(Instruction::SetLT, Val, Pivot.first,
- "Pivot");
- NewNode->getInstList().push_back(Comp);
- new BranchInst(LBranch, RBranch, Comp, NewNode);
- return NewNode;
-}
-
-// newLeafBlock - Create a new leaf block for the binary lookup tree. It
-// checks if the switch's value == the case's value. If not, then it
-// jumps to the default branch. At this point in the tree, the value
-// can't be another valid case value, so the jump to the "default" branch
-// is warranted.
-//
-BasicBlock* LowerSwitch::newLeafBlock(Case& Leaf, Value* Val,
- BasicBlock* OrigBlock,
- BasicBlock* Default)
-{
- Function* F = OrigBlock->getParent();
- BasicBlock* NewLeaf = new BasicBlock("LeafBlock");
- F->getBasicBlockList().insert(OrigBlock->getNext(), NewLeaf);
-
- // Make the seteq instruction...
- SetCondInst* Comp = new SetCondInst(Instruction::SetEQ, Val,
- Leaf.first, "SwitchLeaf");
- NewLeaf->getInstList().push_back(Comp);
-
- // Make the conditional branch...
- BasicBlock* Succ = Leaf.second;
- new BranchInst(Succ, Default, Comp, NewLeaf);
-
- // If there were any PHI nodes in this successor, rewrite one entry
- // from OrigBlock to come from NewLeaf.
- 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);
- }
-
- return NewLeaf;
-}
-
-// 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) {
- new BranchInst(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 = new BasicBlock("NewDefault");
- F->getBasicBlockList().insert(Default, 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(); 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);
- }
-
- std::vector<Case> Cases;
-
- // Expand comparisons for all of the non-default cases...
- for (unsigned i = 1; i < SI->getNumSuccessors(); ++i)
- Cases.push_back(Case(SI->getSuccessorValue(i), SI->getSuccessor(i)));
-
- std::sort(Cases.begin(), Cases.end(), CaseCmp());
- DEBUG(std::cerr << "Cases: " << Cases << "\n");
- BasicBlock* SwitchBlock = switchConvert(Cases.begin(), Cases.end(), Val,
- OrigBlock, NewDefault);
-
- // Branch to our shiny new if-then stuff...
- new BranchInst(SwitchBlock, OrigBlock);
-
- // We are now done with the switch instruction, delete it.
- CurBlock->getInstList().erase(SI);
-}
OpenPOWER on IntegriCloud