diff options
author | Chris Lattner <sabre@nondot.org> | 2004-03-30 18:41:10 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-03-30 18:41:10 +0000 |
commit | 18bdbc3dda73081193fa1070021558ea0c79691d (patch) | |
tree | 979e944eae16675bff62a9b60834c55d47043b4f /lib/Transforms/Utils | |
parent | fc33d30446843009b0eadf63c0bfca35ae2baac6 (diff) | |
download | external_llvm-18bdbc3dda73081193fa1070021558ea0c79691d.zip external_llvm-18bdbc3dda73081193fa1070021558ea0c79691d.tar.gz external_llvm-18bdbc3dda73081193fa1070021558ea0c79691d.tar.bz2 |
Add a simple select instruction lowering pass
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12540 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils')
-rw-r--r-- | lib/Transforms/Utils/LowerSelect.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/Transforms/Utils/LowerSelect.cpp b/lib/Transforms/Utils/LowerSelect.cpp new file mode 100644 index 0000000..647658e --- /dev/null +++ b/lib/Transforms/Utils/LowerSelect.cpp @@ -0,0 +1,95 @@ +//===- LowerSelect.cpp - Transform select insts to branches ---------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// +// This pass lowers select instructions into conditional branches for targets +// that do not have conditional moves or that have not implemented the select +// instruction yet. +// +// Note that this pass could be improved. In particular it turns every select +// instruction into a new conditional branch, even though some common cases have +// select instructions on the same predicate next to each other. It would be +// better to use the same branch for the whole group of selects. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "Support/Statistic.h" +using namespace llvm; + +namespace { + Statistic<> NumLowered("lowerselect","Number of select instructions lowered"); + + /// LowerSelect - Turn select instructions into conditional branches. + /// + class LowerSelect : public FunctionPass { + bool OnlyFP; // Only lower FP select instructions? + public: + LowerSelect(bool onlyfp = false) : OnlyFP(onlyfp) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + // Doesn't really preserve anything. It can certainly destroy the CFG. + } + + bool runOnFunction(Function &F); + }; + + RegisterOpt<LowerSelect> + X("lowerselect", "Lower select instructions to branches"); +} + +//===----------------------------------------------------------------------===// +// This pass converts SelectInst instructions into conditional branch and PHI +// instructions. If the OnlyFP flag is set to true, then only floating point +// select instructions are lowered. +// +FunctionPass *llvm::createLowerSelectPass(bool OnlyFP) { + return new LowerSelect(OnlyFP); +} + + +bool LowerSelect::runOnFunction(Function &F) { + bool Changed = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + if (SelectInst *SI = dyn_cast<SelectInst>(I)) + if (!OnlyFP || SI->getType()->isFloatingPoint()) { + // Split this basic block in half right before the select instruction. + BasicBlock *NewCont = + BB->splitBasicBlock(I, BB->getName()+".selectcont"); + + // Make the true block, and make it branch to the continue block. + BasicBlock *NewTrue = new BasicBlock(BB->getName()+".selecttrue", + BB->getParent(), NewCont); + new BranchInst(NewCont, NewTrue); + + // Make the unconditional branch in the incoming block be a + // conditional branch on the select predicate. + BB->getInstList().erase(BB->getTerminator()); + new BranchInst(NewTrue, NewCont, SI->getCondition(), BB); + + // Create a new PHI node in the cont block with the entries we need. + std::string Name = SI->getName(); SI->setName(""); + PHINode *PN = new PHINode(SI->getType(), Name, NewCont->begin()); + PN->addIncoming(SI->getTrueValue(), NewTrue); + PN->addIncoming(SI->getFalseValue(), BB); + + // Use the PHI instead of the select. + SI->replaceAllUsesWith(PN); + NewCont->getInstList().erase(SI); + + Changed = true; + break; // This block is done with. + } + } + return Changed; +} |