1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-28 22:42:52 +01:00
llvm-mirror/lib/Transforms/Utils/LowerSelect.cpp
Reid Spencer 8749d297f5 Apply the VISIBILITY_HIDDEN field to the remaining anonymous classes in
the Transforms library. This reduces debug library size by 132 KB, debug
binary size by 376 KB, and reduces link time for llvm tools slightly.

llvm-svn: 33939
2007-02-05 23:32:05 +00:00

103 lines
4.0 KiB
C++

//===- 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/Transforms/Utils/UnifyFunctionExitNodes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/Support/Compiler.h"
using namespace llvm;
namespace {
/// LowerSelect - Turn select instructions into conditional branches.
///
class VISIBILITY_HIDDEN LowerSelect : public FunctionPass {
bool OnlyFP; // Only lower FP select instructions?
public:
LowerSelect(bool onlyfp = false) : OnlyFP(onlyfp) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
// This certainly destroys the CFG.
// This is a cluster of orthogonal Transforms:
AU.addPreserved<UnifyFunctionExitNodes>();
AU.addPreservedID(PromoteMemoryToRegisterID);
AU.addPreservedID(LowerSwitchID);
AU.addPreservedID(LowerInvokePassID);
AU.addPreservedID(LowerAllocationsID);
}
bool runOnFunction(Function &F);
};
RegisterPass<LowerSelect>
X("lowerselect", "Lower select instructions to branches");
}
// Publically exposed interface to pass...
const PassInfo *llvm::LowerSelectID = X.getPassInfo();
//===----------------------------------------------------------------------===//
// 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;
}