X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparcV9%2FSparcV9PreSelection.cpp;h=a13019e20613143b568713c483973a8a169d8cf7;hb=4548a0ed32949ab38310e103af5d85650ecd2a5d;hp=014725a73f159e9f9c9231c5436523e01c607427;hpb=d48a1d797ff7b69e4e348c56c158a95538eefce8;p=oota-llvm.git diff --git a/lib/Target/SparcV9/SparcV9PreSelection.cpp b/lib/Target/SparcV9/SparcV9PreSelection.cpp index 014725a73f1..a13019e2061 100644 --- a/lib/Target/SparcV9/SparcV9PreSelection.cpp +++ b/lib/Target/SparcV9/SparcV9PreSelection.cpp @@ -1,95 +1,88 @@ -//===- PreSelection.cpp - Specialize LLVM code for target machine ---------===// -// +//===- SparcV9PreSelection.cpp - Specialize LLVM code for SparcV9 ---------===// +// // 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 -// preserving type information and type safety. This is meant to enable -// dataflow optimizations on target-specific operations such as accesses to +// This file defines the PreSelection pass which specializes LLVM code for +// the SparcV9 instruction selector, while remaining in legal portable LLVM +// form and preserving type information and type safety. This is meant to enable +// dataflow optimizations on SparcV9-specific operations such as accesses to // constants, globals, and array indexing. // //===----------------------------------------------------------------------===// -#include "SparcInternals.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Support/InstVisitor.h" -#include "llvm/Module.h" +#include "SparcV9Internals.h" +#include "SparcV9BurgISel.h" #include "llvm/Constants.h" -#include "llvm/iMemory.h" -#include "llvm/iPHINode.h" -#include "llvm/iOther.h" #include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Scalar.h" #include +using namespace llvm; namespace { //===--------------------------------------------------------------------===// - // PreSelection Pass - Specialize LLVM code for the current target machine. - // - class PreSelection : public Pass, public InstVisitor { + // PreSelection Pass - Specialize LLVM code for the SparcV9 instr. selector. + // + class PreSelection : public FunctionPass, public InstVisitor { const TargetInstrInfo &instrInfo; - Module *TheModule; - - std::map gvars; - - GlobalVariable* getGlobalForConstant(Constant* CV) { - std::map::iterator I = gvars.find(CV); - if (I != gvars.end()) return I->second; // global exists so return it - - return I->second = new GlobalVariable(CV->getType(), true, - GlobalValue::InternalLinkage, CV, - "immcst", TheModule); - } public: PreSelection(const TargetMachine &T) - : instrInfo(T.getInstrInfo()), TheModule(0) {} + : instrInfo(*T.getInstrInfo()) {} - // runOnBasicBlock - apply this pass to each BB - bool run(Module &M) { - TheModule = &M; - - // Build reverse map for pre-existing global constants so we can find them - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) - if (I->hasInitializer() && I->isConstant()) - gvars[I->getInitializer()] = I; - - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - visit(*I); - - gvars.clear(); + // runOnFunction - apply this pass to each Function + bool runOnFunction(Function &F) { + visit(F); return true; } + const char *getPassName() const { return "SparcV9 Instr. Pre-selection"; } // These methods do the actual work of specializing code - void visitInstruction(Instruction &I); // common work for every instr. + void visitInstruction(Instruction &I); // common work for every instr. void visitGetElementPtrInst(GetElementPtrInst &I); void visitCallInst(CallInst &I); + void visitPHINode(PHINode &PN); + + void visitBasicBlock(BasicBlock &BB) { + if (isa(BB.getTerminator())) { + BB.getInstList().pop_back(); + const Type *RetTy = BB.getParent()->getReturnType(); + Value *RetVal = RetTy == Type::VoidTy ? 0 : UndefValue::get(RetTy); + new ReturnInst(RetVal, &BB); + } + } // Helper functions for visiting operands of every instruction - // + // // 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); void visitOneOperand(Instruction &I, Value* Op, unsigned opNum, Instruction& insertBefore); }; +#if 0 // Register the pass... - RegisterOpt X("preselect", - "Specialize LLVM code for a target machine", - createPreSelectionPass); + RegisterPass X("preselect", + "Specialize LLVM code for a target machine" + createPreselectionPass); +#endif + } // end anonymous namespace @@ -99,26 +92,20 @@ namespace { // getGlobalAddr(): Put address of a global into a v. register. -static GetElementPtrInst* getGlobalAddr(Value* ptr, Instruction& insertBefore) -{ - if (isa(ptr)) - ptr = cast(ptr)->getValue(); +static GetElementPtrInst* getGlobalAddr(Value* ptr, Instruction& insertBefore) { return (isa(ptr)) ? new GetElementPtrInst(ptr, std::vector(1, ConstantSInt::get(Type::LongTy, 0U)), - "addrOfGlobal", &insertBefore) + "addrOfGlobal:" + ptr->getName(), &insertBefore) : NULL; } - -// Wrapper on Constant::classof to use in find_if :-( -inline static bool nonConstant(const Use& U) -{ +// Wrapper on Constant::classof to use in find_if +inline static bool nonConstant(const Use& U) { return ! isa(U); } - static Instruction* DecomposeConstantExpr(ConstantExpr* CE, Instruction& insertBefore) { @@ -133,7 +120,8 @@ static Instruction* DecomposeConstantExpr(ConstantExpr* CE, return new CastInst(getArg1, CE->getType(), "constantCast",&insertBefore); case Instruction::GetElementPtr: - assert(find_if(CE->op_begin()+1, CE->op_end(),nonConstant) == CE->op_end() + assert(std::find_if(CE->op_begin()+1, CE->op_end(), + nonConstant) == CE->op_end() && "All indices in ConstantExpr getelementptr must be constant!"); getArg1 = CE->getOperand(0); if (ConstantExpr* CEarg = dyn_cast(getArg1)) @@ -142,12 +130,50 @@ static Instruction* DecomposeConstantExpr(ConstantExpr* CE, getArg1 = gep; return new GetElementPtrInst(getArg1, std::vector(CE->op_begin()+1, CE->op_end()), - "constantGEP", &insertBefore); + "constantGEP:" + getArg1->getName(), &insertBefore); + + case Instruction::Select: { + Value *C, *S1, *S2; + C = CE->getOperand (0); + if (ConstantExpr* CEarg = dyn_cast (C)) + C = DecomposeConstantExpr (CEarg, insertBefore); + S1 = CE->getOperand (1); + if (ConstantExpr* CEarg = dyn_cast (S1)) + S1 = DecomposeConstantExpr (CEarg, insertBefore); + S2 = CE->getOperand (2); + if (ConstantExpr* CEarg = dyn_cast (S2)) + S2 = DecomposeConstantExpr (CEarg, insertBefore); + return new SelectInst (C, S1, S2, "constantSelect", &insertBefore); + } + + case Instruction::Shr: { + getArg1 = CE->getOperand(0); + if (ConstantExpr* CEarg = dyn_cast(getArg1)) + getArg1 = DecomposeConstantExpr(CEarg, insertBefore); + getArg2 = CE->getOperand(1); + if (ConstantExpr* CEarg = dyn_cast(getArg2)) + getArg2 = DecomposeConstantExpr(CEarg, insertBefore); + return new ShiftInst (static_cast(CE->getOpcode()), + getArg1, getArg2, + "constantShr:" + getArg1->getName(), &insertBefore); + } + + case Instruction::Shl: { + getArg1 = CE->getOperand(0); + if (ConstantExpr* CEarg = dyn_cast(getArg1)) + getArg1 = DecomposeConstantExpr(CEarg, insertBefore); + getArg2 = CE->getOperand(1); + if (ConstantExpr* CEarg = dyn_cast(getArg2)) + getArg2 = DecomposeConstantExpr(CEarg, insertBefore); + return new ShiftInst (static_cast(CE->getOpcode()), + getArg1, getArg2, + "constantShl:" + getArg1->getName(), &insertBefore); + } default: // must be a binary operator assert(CE->getOpcode() >= Instruction::BinaryOpsBegin && CE->getOpcode() < Instruction::BinaryOpsEnd && - "Unrecognized opcode in ConstantExpr"); + "Unhandled opcode in ConstantExpr"); getArg1 = CE->getOperand(0); if (ConstantExpr* CEarg = dyn_cast(getArg1)) getArg1 = DecomposeConstantExpr(CEarg, insertBefore); @@ -160,6 +186,10 @@ static Instruction* DecomposeConstantExpr(ConstantExpr* CE, } } +static inline bool ConstantTypeMustBeLoaded(const Type* CVT) { + assert(CVT->isPrimitiveType() || isa(CVT)); + return !(CVT->isIntegral() || isa(CVT)); +} //------------------------------------------------------------------------------ // Instruction visitor methods to perform instruction-specific operations @@ -179,69 +209,77 @@ PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum, if (CV == NULL) return; - if (ConstantExpr* CE = dyn_cast(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 (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. - } + if (ConstantExpr* CE = dyn_cast(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 (ConstantTypeMustBeLoaded(CV->getType())) { + // load address of constant into a register, then load the constant + // this is now done during instruction selection + // the constant will live in the MachineConstantPool later on + } else if (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. + } } -// 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. -// -// firstOp and lastOp can be used to skip leading and trailing operands. -// If lastOp is 0, it defaults to #operands or #incoming Phi values. -// +/// visitOperands - transform 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. +/// +/// 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) { // For any instruction other than PHI, copies go just before the instr. + for (unsigned i = firstOp, e = I.getNumOperands(); i != e; ++i) + visitOneOperand(I, I.getOperand(i), i, I); +} + + +void PreSelection::visitPHINode(PHINode &PN) { // For a PHI, operand copies must be before the terminator of the // appropriate predecessor basic block. Remaining logic is simple // so just handle PHIs and other instructions separately. - // - if (PHINode* phi = dyn_cast(&I)) { - for (unsigned i=firstOp, N=phi->getNumIncomingValues(); i != N; ++i) - visitOneOperand(I, phi->getIncomingValue(i), - phi->getOperandNumForIncomingValue(i), - * phi->getIncomingBlock(i)->getTerminator()); - } else { - for (unsigned i=firstOp, N=lastOp; i != I.getNumOperands(); ++i) - visitOneOperand(I, I.getOperand(i), i, I); - } + // + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) + visitOneOperand(PN, PN.getIncomingValue(i), + PN.getOperandNumForIncomingValue(i), + *PN.getIncomingBlock(i)->getTerminator()); + // do not call visitOperands! } - - // Common work for *all* instructions. This needs to be called explicitly // by other visit functions. -inline void -PreSelection::visitInstruction(Instruction &I) -{ +inline void PreSelection::visitInstruction(Instruction &I) { visitOperands(I); // Perform operand transformations } - // GetElementPtr instructions: check if pointer is a global -void -PreSelection::visitGetElementPtrInst(GetElementPtrInst &I) -{ +void PreSelection::visitGetElementPtrInst(GetElementPtrInst &I) { Instruction* curI = &I; + // The Sparc backend doesn't handle array indexes that are not long types, so + // insert a cast from whatever it is to long, if the sequential type index is + // not a long already. + unsigned Idx = 1; + for (gep_type_iterator TI = gep_type_begin(I), E = gep_type_end(I); TI != E; + ++TI, ++Idx) + if (isa(*TI) && + I.getOperand(Idx)->getType() != Type::LongTy) { + Value *Op = I.getOperand(Idx); + if (Op->getType()->isUnsigned()) // Must sign extend! + Op = new CastInst(Op, Op->getType()->getSignedVersion(), "v9", &I); + if (Op->getType() != Type::LongTy) + Op = new CastInst(Op, Type::LongTy, "v9", &I); + I.setOperand(Idx, Op); + } + + // Decompose multidimensional array references if (I.getNumIndices() >= 2) { // DecomposeArrayRef() replaces I and deletes it, if successful, @@ -258,20 +296,13 @@ PreSelection::visitGetElementPtrInst(GetElementPtrInst &I) visitInstruction(*curI); } - -void -PreSelection::visitCallInst(CallInst &I) -{ +void PreSelection::visitCallInst(CallInst &I) { // Tell visitOperands to ignore the function name if this is a direct call. visitOperands(I, (/*firstOp=*/ I.getCalledFunction()? 1 : 0)); } - -//===----------------------------------------------------------------------===// -// createPreSelectionPass - Public entrypoint for pre-selection pass -// and this file as a whole... -// -Pass* createPreSelectionPass(TargetMachine &T) { - return new PreSelection(T); +/// createPreSelectionPass - Public entry point for the PreSelection pass +/// +FunctionPass* llvm::createPreSelectionPass(const TargetMachine &TM) { + return new PreSelection(TM); } -