//===- 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 // 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 "SparcV9Internals.h" #include "SparcV9InstrSelectionSupport.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/iMemory.h" #include "llvm/iPHINode.h" #include "llvm/iOther.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 SparcV9 instr. selector. // class PreSelection : public FunctionPass, public InstVisitor { const TargetInstrInfo &instrInfo; public: PreSelection(const TargetMachine &T) : instrInfo(*T.getInstrInfo()) {} // 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 visitGetElementPtrInst(GetElementPtrInst &I); void visitCallInst(CallInst &I); void visitPHINode(PHINode &PN); // 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... RegisterPass X("preselect", "Specialize LLVM code for a target machine" createPreselectionPass); #endif } // end anonymous namespace //------------------------------------------------------------------------------ // Helper functions used by methods of class PreSelection //------------------------------------------------------------------------------ // getGlobalAddr(): Put address of a global into a v. register. static GetElementPtrInst* getGlobalAddr(Value* ptr, Instruction& insertBefore) { return (isa(ptr)) ? new GetElementPtrInst(ptr, std::vector(1, ConstantSInt::get(Type::LongTy, 0U)), "addrOfGlobal:" + ptr->getName(), &insertBefore) : NULL; } // 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) { Value *getArg1, *getArg2; switch(CE->getOpcode()) { case Instruction::Cast: getArg1 = CE->getOperand(0); if (ConstantExpr* CEarg = dyn_cast(getArg1)) getArg1 = DecomposeConstantExpr(CEarg, insertBefore); 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() && "All indices in ConstantExpr getelementptr must be constant!"); getArg1 = CE->getOperand(0); if (ConstantExpr* CEarg = dyn_cast(getArg1)) getArg1 = DecomposeConstantExpr(CEarg, insertBefore); else if (GetElementPtrInst* gep = getGlobalAddr(getArg1, insertBefore)) getArg1 = gep; return new GetElementPtrInst(getArg1, std::vector(CE->op_begin()+1, CE->op_end()), "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); } default: // must be a binary operator assert(CE->getOpcode() >= Instruction::BinaryOpsBegin && CE->getOpcode() < Instruction::BinaryOpsEnd && "Unhandled opcode in ConstantExpr"); 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 BinaryOperator::create((Instruction::BinaryOps) CE->getOpcode(), getArg1, getArg2, "constantBinaryOp", &insertBefore); } } 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 //------------------------------------------------------------------------------ inline void 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. } Constant* CV = dyn_cast(Op); 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 (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 - 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. // 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) { visitOperands(I); // Perform operand transformations } // GetElementPtr instructions: check if pointer is a global 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, // 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(prevI? prevI->getNext() : &bb->front()); } // Perform other transformations common to all instructions visitInstruction(*curI); } 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 entry point for the PreSelection pass /// FunctionPass* llvm::createPreSelectionPass(const TargetMachine &TM) { return new PreSelection(TM); }