//===- PreSelection.cpp - Specialize LLVM code for target machine ---------===//
+//
+// 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 file defines the PreSelection pass which specializes LLVM code for a
// target machine, while remaining in legal portable LLVM form and
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/PreSelection.h"
+#include "SparcInternals.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/MachineInstrInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Module.h"
#include "llvm/iOther.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
-#include "llvm/Annotation.h"
#include "Support/CommandLine.h"
-#include "Support/NonCopyable.h"
#include <algorithm>
-using namespace std;
namespace {
//===--------------------------------------------------------------------===//
// A single GlobalVariable is created for each constant in the pool
// representing the memory for that constant.
//
- static AnnotationID CPFM_AID(
+ AnnotationID CPFM_AID(
AnnotationManager::getID("CodeGen::ConstantPoolForModule"));
- class ConstantPoolForModule: private Annotation, public NonCopyable {
+ class ConstantPoolForModule : private Annotation {
Module* myModule;
std::map<const Constant*, GlobalVariable*> gvars;
std::map<const Constant*, GlobalVariable*> origGVars;
ConstantPoolForModule(Module* M); // called only by annotation builder
- ConstantPoolForModule(); // do not implement
+ ConstantPoolForModule(); // DO NOT IMPLEMENT
+ void operator=(const ConstantPoolForModule&); // DO NOT IMPLEMENT
public:
static ConstantPoolForModule& get(Module* M) {
ConstantPoolForModule* cpool =
GV = PI->second; // put in map
else
{
- GV = new GlobalVariable(CV->getType(), true,true,CV); //put in map
+ GV = new GlobalVariable(CV->getType(), true, //put in map
+ GlobalValue::InternalLinkage, CV);
myModule->getGlobalList().push_back(GV); // GV owned by module now
}
}
//===--------------------------------------------------------------------===//
// PreSelection Pass - Specialize LLVM code for the current target machine.
- // This was and will be a basicblock pass, but make it a FunctionPass until
- // BasicBlockPass ::doFinalization(Function&) is available.
//
class PreSelection : public BasicBlockPass, public InstVisitor<PreSelection>
{
const TargetMachine ⌖
+ const TargetInstrInfo &instrInfo;
Function* function;
GlobalVariable* getGlobalForConstant(Constant* CV) {
}
public:
- PreSelection (const TargetMachine &T): target(T), function(NULL) {}
+ PreSelection (const TargetMachine &T):
+ target(T), instrInfo(T.getInstrInfo()), function(NULL) {}
// runOnBasicBlock - apply this pass to each BB
bool runOnBasicBlock(BasicBlock &BB) {
bool doFinalization(Function &F) {
if (PreSelectDebugLevel >= PreSelect_PrintOutput)
- cerr << "\n\n*** LLVM code after pre-selection for function "
- << F.getName() << ":\n\n" << F;
+ std::cerr << "\n\n*** LLVM code after pre-selection for function "
+ << F.getName() << ":\n\n" << F;
return false;
}
// These methods do the actual work of specializing code
void visitInstruction(Instruction &I); // common work for every instr.
void visitGetElementPtrInst(GetElementPtrInst &I);
- void visitLoadInst(LoadInst &I);
- void visitCastInst(CastInst &I);
- void visitStoreInst(StoreInst &I);
+ void visitCallInst(CallInst &I);
// Helper functions for visiting operands of every instruction
- void visitOperands(Instruction &I); // work on all operands of instr.
- void visitOneOperand(Instruction &I, Constant* CV, unsigned opNum,
- Instruction& insertBefore); // iworks on one operand
+ //
+ // visitOperands() works on every operand in [firstOp, lastOp-1].
+ // If lastOp==0, lastOp defaults to #operands or #incoming Phi values.
+ //
+ // visitOneOperand() does all the work for one operand.
+ //
+ void visitOperands(Instruction &I, int firstOp=0, int lastOp=0);
+ void visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
+ Instruction& insertBefore);
};
-} // end anonymous namespace
+ // Register the pass...
+ RegisterOpt<PreSelection> X("preselect",
+ "Specialize LLVM code for a target machine",
+ createPreSelectionPass);
+} // end anonymous namespace
-// Register the pass...
-static RegisterOpt<PreSelection> X("preselect",
- "Specialize LLVM code for a target machine",
- createPreSelectionPass);
//------------------------------------------------------------------------------
// Helper functions used by methods of class PreSelection
if (isa<ConstantPointerRef>(ptr))
ptr = cast<ConstantPointerRef>(ptr)->getValue();
- return (isa<GlobalValue>(ptr))
+ return (isa<GlobalVariable>(ptr))
? new GetElementPtrInst(ptr,
std::vector<Value*>(1, ConstantSInt::get(Type::LongTy, 0U)),
"addrOfGlobal", &insertBefore)
//------------------------------------------------------------------------------
// Instruction visitor methods to perform instruction-specific operations
//------------------------------------------------------------------------------
-
-// Common work for *all* instructions. This needs to be called explicitly
-// by other visit<InstructionType> functions.
inline void
-PreSelection::visitInstruction(Instruction &I)
-{
- visitOperands(I); // Perform operand transformations
-}
-
-
-// GetElementPtr instructions: check if pointer is a global
-void
-PreSelection::visitGetElementPtrInst(GetElementPtrInst &I)
-{
- // Check for a global and put its address into a register before this instr
- if (GetElementPtrInst* gep = getGlobalAddr(I.getPointerOperand(), I))
- I.setOperand(I.getPointerOperandIndex(), gep); // replace pointer operand
-
- // Decompose multidimensional array references
- DecomposeArrayRef(&I);
-
- // Perform other transformations common to all instructions
- visitInstruction(I);
-}
-
-
-// Load instructions: check if pointer is a global
-void
-PreSelection::visitLoadInst(LoadInst &I)
-{
- // Check for a global and put its address into a register before this instr
- if (GetElementPtrInst* gep = getGlobalAddr(I.getPointerOperand(), I))
- I.setOperand(I.getPointerOperandIndex(), gep); // replace pointer operand
-
- // Perform other transformations common to all instructions
- visitInstruction(I);
-}
-
-
-// Store instructions: check if pointer is a global
-void
-PreSelection::visitStoreInst(StoreInst &I)
-{
- // Check for a global and put its address into a register before this instr
- if (GetElementPtrInst* gep = getGlobalAddr(I.getPointerOperand(), I))
- I.setOperand(I.getPointerOperandIndex(), gep); // replace pointer operand
-
- // Perform other transformations common to all instructions
- visitInstruction(I);
-}
+PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
+ Instruction& insertBefore)
+{
+ assert(&insertBefore != NULL && "Must have instruction to insert before.");
+ if (GetElementPtrInst* gep = getGlobalAddr(Op, insertBefore)) {
+ I.setOperand(opNum, gep); // replace global operand
+ return; // nothing more to do for this op.
+ }
-// Cast instructions:
-// -- check if argument is a global
-// -- make multi-step casts explicit:
-// -- float/double to uint32_t:
-// If target does not have a float-to-unsigned instruction, we
-// need to convert to uint64_t and then to uint32_t, or we may
-// overflow the signed int representation for legal uint32_t
-// values. Expand this without checking target.
-//
-void
-PreSelection::visitCastInst(CastInst &I)
-{
- CastInst* castI = NULL;
+ Constant* CV = dyn_cast<Constant>(Op);
+ if (CV == NULL)
+ return;
- // Check for a global and put its address into a register before this instr
- if (GetElementPtrInst* gep = getGlobalAddr(I.getOperand(0), I))
- {
- I.setOperand(0, gep); // replace pointer operand
+ if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV))
+ { // load-time constant: factor it out so we optimize as best we can
+ Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
+ I.setOperand(opNum, computeConst); // replace expr operand with result
+ }
+ else if (instrInfo.ConstantTypeMustBeLoaded(CV))
+ { // load address of constant into a register, then load the constant
+ GetElementPtrInst* gep = getGlobalAddr(getGlobalForConstant(CV),
+ insertBefore);
+ LoadInst* ldI = new LoadInst(gep, "loadConst", &insertBefore);
+ I.setOperand(opNum, ldI); // replace operand with copy in v.reg.
}
- else if (I.getType() == Type::UIntTy &&
- I.getOperand(0)->getType()->isFloatingPoint())
- { // insert a cast-fp-to-long before I, and then replace the operand of I
- castI = new CastInst(I.getOperand(0), Type::LongTy, "fp2Long2Uint", &I);
- I.setOperand(0, castI); // replace fp operand with long
+ else if (instrInfo.ConstantMayNotFitInImmedField(CV, &I))
+ { // put the constant into a virtual register using a cast
+ CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
+ &insertBefore);
+ I.setOperand(opNum, castI); // replace operand with copy in v.reg.
}
-
- // Perform other transformations common to all instructions
- visitInstruction(I);
- if (castI)
- visitInstruction(*castI);
}
-
// visitOperands() transforms individual operands of all instructions:
// -- Load "large" int constants into a virtual register. What is large
// depends on the type of instruction and on the target architecture.
// -- For any constants that cannot be put in an immediate field,
// load address into virtual register first, and then load the constant.
//
-void
-PreSelection::visitOperands(Instruction &I)
+// firstOp and lastOp can be used to skip leading and trailing operands.
+// If lastOp is 0, it defaults to #operands or #incoming Phi values.
+//
+inline void
+PreSelection::visitOperands(Instruction &I, int firstOp, int lastOp)
{
// For any instruction other than PHI, copies go just before the instr.
// For a PHI, operand copies must be before the terminator of the
//
if (PHINode* phi = dyn_cast<PHINode>(&I))
{
- for (unsigned i=0, N=phi->getNumIncomingValues(); i < N; ++i)
- if (Constant* CV = dyn_cast<Constant>(phi->getIncomingValue(i)))
- this->visitOneOperand(I, CV, phi->getOperandNumForIncomingValue(i),
- * phi->getIncomingBlock(i)->getTerminator());
+ if (lastOp == 0)
+ lastOp = phi->getNumIncomingValues();
+ for (unsigned i=firstOp, N=lastOp; i < N; ++i)
+ this->visitOneOperand(I, phi->getIncomingValue(i),
+ phi->getOperandNumForIncomingValue(i),
+ * phi->getIncomingBlock(i)->getTerminator());
}
else
- for (unsigned i=0, N=I.getNumOperands(); i < N; ++i)
- if (Constant* CV = dyn_cast<Constant>(I.getOperand(i)))
- this->visitOneOperand(I, CV, i, I);
+ {
+ if (lastOp == 0)
+ lastOp = I.getNumOperands();
+ for (unsigned i=firstOp, N=lastOp; i < N; ++i)
+ this->visitOneOperand(I, I.getOperand(i), i, I);
+ }
}
+
+
+// Common work for *all* instructions. This needs to be called explicitly
+// by other visit<InstructionType> functions.
+inline void
+PreSelection::visitInstruction(Instruction &I)
+{
+ visitOperands(I); // Perform operand transformations
+}
+
+
+// GetElementPtr instructions: check if pointer is a global
void
-PreSelection::visitOneOperand(Instruction &I, Constant* CV, unsigned opNum,
- Instruction& insertBefore)
+PreSelection::visitGetElementPtrInst(GetElementPtrInst &I)
+{
+ Instruction* curI = &I;
+
+ // Decompose multidimensional array references
+ if (I.getNumIndices() >= 2) {
+ // DecomposeArrayRef() replaces I and deletes it, if successful,
+ // so remember predecessor in order to find the replacement instruction.
+ // Also remember the basic block in case there is no predecessor.
+ Instruction* prevI = I.getPrev();
+ BasicBlock* bb = I.getParent();
+ if (DecomposeArrayRef(&I))
+ // first instr. replacing I
+ curI = cast<GetElementPtrInst>(prevI? prevI->getNext() : &bb->front());
+ }
+
+ // Perform other transformations common to all instructions
+ visitInstruction(*curI);
+}
+
+
+void
+PreSelection::visitCallInst(CallInst &I)
{
- if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV))
- { // load-time constant: factor it out so we optimize as best we can
- Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
- I.setOperand(opNum, computeConst); // replace expr operand with result
- }
- else if (target.getInstrInfo().ConstantTypeMustBeLoaded(CV))
- { // load address of constant into a register, then load the constant
- GetElementPtrInst* gep = getGlobalAddr(getGlobalForConstant(CV),
- insertBefore);
- LoadInst* ldI = new LoadInst(gep, "loadConst", &insertBefore);
- I.setOperand(opNum, ldI); // replace operand with copy in v.reg.
- }
- else if (target.getInstrInfo().ConstantMayNotFitInImmedField(CV, &I))
- { // put the constant into a virtual register using a cast
- CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
- &insertBefore);
- I.setOperand(opNum, castI); // replace operand with copy in v.reg.
- }
+ // Tell visitOperands to ignore the function name if this is a direct call.
+ visitOperands(I, (/*firstOp=*/ I.getCalledFunction()? 1 : 0));
}