diff options
Diffstat (limited to 'lib/Target/PTX/PTXISelLowering.cpp')
-rw-r--r-- | lib/Target/PTX/PTXISelLowering.cpp | 522 |
1 files changed, 0 insertions, 522 deletions
diff --git a/lib/Target/PTX/PTXISelLowering.cpp b/lib/Target/PTX/PTXISelLowering.cpp deleted file mode 100644 index ef4455b..0000000 --- a/lib/Target/PTX/PTXISelLowering.cpp +++ /dev/null @@ -1,522 +0,0 @@ -//===-- PTXISelLowering.cpp - PTX DAG Lowering Implementation -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the PTXTargetLowering class. -// -//===----------------------------------------------------------------------===// - -#include "PTXISelLowering.h" -#include "PTX.h" -#include "PTXMachineFunctionInfo.h" -#include "PTXRegisterInfo.h" -#include "PTXSubtarget.h" -#include "llvm/Function.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -//===----------------------------------------------------------------------===// -// TargetLowering Implementation -//===----------------------------------------------------------------------===// - -PTXTargetLowering::PTXTargetLowering(TargetMachine &TM) - : TargetLowering(TM, new TargetLoweringObjectFileELF()) { - // Set up the register classes. - addRegisterClass(MVT::i1, PTX::RegPredRegisterClass); - addRegisterClass(MVT::i16, PTX::RegI16RegisterClass); - addRegisterClass(MVT::i32, PTX::RegI32RegisterClass); - addRegisterClass(MVT::i64, PTX::RegI64RegisterClass); - addRegisterClass(MVT::f32, PTX::RegF32RegisterClass); - addRegisterClass(MVT::f64, PTX::RegF64RegisterClass); - - setBooleanContents(ZeroOrOneBooleanContent); - setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? - setMinFunctionAlignment(2); - - // Let LLVM use loads/stores for all mem* operations - maxStoresPerMemcpy = 4096; - maxStoresPerMemmove = 4096; - maxStoresPerMemset = 4096; - - //////////////////////////////////// - /////////// Expansion ////////////// - //////////////////////////////////// - - // (any/zero/sign) extload => load + (any/zero/sign) extend - - setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand); - setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); - setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); - - // f32 extload => load + fextend - - setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); - - // f64 truncstore => trunc + store - - setTruncStoreAction(MVT::f64, MVT::f32, Expand); - - // sign_extend_inreg => sign_extend - - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); - - // br_cc => brcond - - setOperationAction(ISD::BR_CC, MVT::Other, Expand); - - // select_cc => setcc - - setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); - setOperationAction(ISD::SELECT_CC, MVT::f32, Expand); - setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); - - //////////////////////////////////// - //////////// Legal ///////////////// - //////////////////////////////////// - - setOperationAction(ISD::ConstantFP, MVT::f32, Legal); - setOperationAction(ISD::ConstantFP, MVT::f64, Legal); - - //////////////////////////////////// - //////////// Custom //////////////// - //////////////////////////////////// - - // customise setcc to use bitwise logic if possible - - //setOperationAction(ISD::SETCC, MVT::i1, Custom); - setOperationAction(ISD::SETCC, MVT::i1, Legal); - - // customize translation of memory addresses - - setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); - setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); - - // Compute derived properties from the register classes - computeRegisterProperties(); -} - -EVT PTXTargetLowering::getSetCCResultType(EVT VT) const { - return MVT::i1; -} - -SDValue PTXTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { - switch (Op.getOpcode()) { - default: - llvm_unreachable("Unimplemented operand"); - case ISD::SETCC: - return LowerSETCC(Op, DAG); - case ISD::GlobalAddress: - return LowerGlobalAddress(Op, DAG); - } -} - -const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch (Opcode) { - default: - llvm_unreachable("Unknown opcode"); - case PTXISD::COPY_ADDRESS: - return "PTXISD::COPY_ADDRESS"; - case PTXISD::LOAD_PARAM: - return "PTXISD::LOAD_PARAM"; - case PTXISD::STORE_PARAM: - return "PTXISD::STORE_PARAM"; - case PTXISD::READ_PARAM: - return "PTXISD::READ_PARAM"; - case PTXISD::WRITE_PARAM: - return "PTXISD::WRITE_PARAM"; - case PTXISD::EXIT: - return "PTXISD::EXIT"; - case PTXISD::RET: - return "PTXISD::RET"; - case PTXISD::CALL: - return "PTXISD::CALL"; - } -} - -//===----------------------------------------------------------------------===// -// Custom Lower Operation -//===----------------------------------------------------------------------===// - -SDValue PTXTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { - assert(Op.getValueType() == MVT::i1 && "SetCC type must be 1-bit integer"); - SDValue Op0 = Op.getOperand(0); - SDValue Op1 = Op.getOperand(1); - SDValue Op2 = Op.getOperand(2); - DebugLoc dl = Op.getDebugLoc(); - //ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); - - // Look for X == 0, X == 1, X != 0, or X != 1 - // We can simplify these to bitwise logic - - //if (Op1.getOpcode() == ISD::Constant && - // (cast<ConstantSDNode>(Op1)->getZExtValue() == 1 || - // cast<ConstantSDNode>(Op1)->isNullValue()) && - // (CC == ISD::SETEQ || CC == ISD::SETNE)) { - // - // return DAG.getNode(ISD::AND, dl, MVT::i1, Op0, Op1); - //} - - //ConstantSDNode* COp1 = cast<ConstantSDNode>(Op1); - //if(COp1 && COp1->getZExtValue() == 1) { - // if(CC == ISD::SETNE) { - // return DAG.getNode(PTX::XORripreds, dl, MVT::i1, Op0); - // } - //} - - llvm_unreachable("setcc was not matched by a pattern!"); - - return DAG.getNode(ISD::SETCC, dl, MVT::i1, Op0, Op1, Op2); -} - -SDValue PTXTargetLowering:: -LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { - EVT PtrVT = getPointerTy(); - DebugLoc dl = Op.getDebugLoc(); - const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); - - assert(PtrVT.isSimple() && "Pointer must be to primitive type."); - - SDValue targetGlobal = DAG.getTargetGlobalAddress(GV, dl, PtrVT); - SDValue movInstr = DAG.getNode(PTXISD::COPY_ADDRESS, - dl, - PtrVT.getSimpleVT(), - targetGlobal); - - return movInstr; -} - -//===----------------------------------------------------------------------===// -// Calling Convention Implementation -//===----------------------------------------------------------------------===// - -SDValue PTXTargetLowering:: - LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, - SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { - if (isVarArg) llvm_unreachable("PTX does not support varargs"); - - MachineFunction &MF = DAG.getMachineFunction(); - const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>(); - PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>(); - PTXParamManager &PM = MFI->getParamManager(); - - switch (CallConv) { - default: - llvm_unreachable("Unsupported calling convention"); - case CallingConv::PTX_Kernel: - MFI->setKernel(true); - break; - case CallingConv::PTX_Device: - MFI->setKernel(false); - break; - } - - // We do one of two things here: - // IsKernel || SM >= 2.0 -> Use param space for arguments - // SM < 2.0 -> Use registers for arguments - if (MFI->isKernel() || ST.useParamSpaceForDeviceArgs()) { - // We just need to emit the proper LOAD_PARAM ISDs - for (unsigned i = 0, e = Ins.size(); i != e; ++i) { - assert((!MFI->isKernel() || Ins[i].VT != MVT::i1) && - "Kernels cannot take pred operands"); - - unsigned ParamSize = Ins[i].VT.getStoreSizeInBits(); - unsigned Param = PM.addArgumentParam(ParamSize); - const std::string &ParamName = PM.getParamName(Param); - SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(), - MVT::Other); - SDValue ArgValue = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain, - ParamValue); - InVals.push_back(ArgValue); - } - } - else { - for (unsigned i = 0, e = Ins.size(); i != e; ++i) { - EVT RegVT = Ins[i].VT; - const TargetRegisterClass* TRC = getRegClassFor(RegVT); - unsigned RegType; - - // Determine which register class we need - if (RegVT == MVT::i1) - RegType = PTXRegisterType::Pred; - else if (RegVT == MVT::i16) - RegType = PTXRegisterType::B16; - else if (RegVT == MVT::i32) - RegType = PTXRegisterType::B32; - else if (RegVT == MVT::i64) - RegType = PTXRegisterType::B64; - else if (RegVT == MVT::f32) - RegType = PTXRegisterType::F32; - else if (RegVT == MVT::f64) - RegType = PTXRegisterType::F64; - else - llvm_unreachable("Unknown parameter type"); - - // Use a unique index in the instruction to prevent instruction folding. - // Yes, this is a hack. - SDValue Index = DAG.getTargetConstant(i, MVT::i32); - unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC); - SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, RegVT, Chain, - Index); - - InVals.push_back(ArgValue); - - MFI->addRegister(Reg, RegType, PTXRegisterSpace::Argument); - } - } - - return Chain; -} - -SDValue PTXTargetLowering:: - LowerReturn(SDValue Chain, - CallingConv::ID CallConv, - bool isVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - DebugLoc dl, - SelectionDAG &DAG) const { - if (isVarArg) llvm_unreachable("PTX does not support varargs"); - - switch (CallConv) { - default: - llvm_unreachable("Unsupported calling convention."); - case CallingConv::PTX_Kernel: - assert(Outs.size() == 0 && "Kernel must return void."); - return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain); - case CallingConv::PTX_Device: - assert(Outs.size() <= 1 && "Can at most return one value."); - break; - } - - MachineFunction& MF = DAG.getMachineFunction(); - PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>(); - PTXParamManager &PM = MFI->getParamManager(); - - SDValue Flag; - const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>(); - - if (ST.useParamSpaceForDeviceArgs()) { - assert(Outs.size() < 2 && "Device functions can return at most one value"); - - if (Outs.size() == 1) { - unsigned ParamSize = OutVals[0].getValueType().getSizeInBits(); - unsigned Param = PM.addReturnParam(ParamSize); - const std::string &ParamName = PM.getParamName(Param); - SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(), - MVT::Other); - Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain, - ParamValue, OutVals[0]); - } - } else { - for (unsigned i = 0, e = Outs.size(); i != e; ++i) { - EVT RegVT = Outs[i].VT; - const TargetRegisterClass* TRC; - unsigned RegType; - - // Determine which register class we need - if (RegVT == MVT::i1) { - TRC = PTX::RegPredRegisterClass; - RegType = PTXRegisterType::Pred; - } - else if (RegVT == MVT::i16) { - TRC = PTX::RegI16RegisterClass; - RegType = PTXRegisterType::B16; - } - else if (RegVT == MVT::i32) { - TRC = PTX::RegI32RegisterClass; - RegType = PTXRegisterType::B32; - } - else if (RegVT == MVT::i64) { - TRC = PTX::RegI64RegisterClass; - RegType = PTXRegisterType::B64; - } - else if (RegVT == MVT::f32) { - TRC = PTX::RegF32RegisterClass; - RegType = PTXRegisterType::F32; - } - else if (RegVT == MVT::f64) { - TRC = PTX::RegF64RegisterClass; - RegType = PTXRegisterType::F64; - } - else { - llvm_unreachable("Unknown parameter type"); - } - - unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC); - - SDValue Copy = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i]/*, Flag*/); - SDValue OutReg = DAG.getRegister(Reg, RegVT); - - Chain = DAG.getNode(PTXISD::WRITE_PARAM, dl, MVT::Other, Copy, OutReg); - - MFI->addRegister(Reg, RegType, PTXRegisterSpace::Return); - } - } - - if (Flag.getNode() == 0) { - return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain); - } - else { - return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag); - } -} - -SDValue -PTXTargetLowering::LowerCall(SDValue Chain, SDValue Callee, - CallingConv::ID CallConv, bool isVarArg, - bool doesNotRet, bool &isTailCall, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - const SmallVectorImpl<ISD::InputArg> &Ins, - DebugLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const { - - MachineFunction& MF = DAG.getMachineFunction(); - PTXMachineFunctionInfo *PTXMFI = MF.getInfo<PTXMachineFunctionInfo>(); - PTXParamManager &PM = PTXMFI->getParamManager(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - - assert(getTargetMachine().getSubtarget<PTXSubtarget>().callsAreHandled() && - "Calls are not handled for the target device"); - - // Identify the callee function - const GlobalValue *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal(); - const Function *function = cast<Function>(GV); - - // allow non-device calls only for printf - bool isPrintf = function->getName() == "printf" || function->getName() == "puts"; - - assert((isPrintf || function->getCallingConv() == CallingConv::PTX_Device) && - "PTX function calls must be to PTX device functions"); - - unsigned outSize = isPrintf ? 2 : Outs.size(); - - std::vector<SDValue> Ops; - // The layout of the ops will be [Chain, #Ins, Ins, Callee, #Outs, Outs] - Ops.resize(outSize + Ins.size() + 4); - - Ops[0] = Chain; - - // Identify the callee function - Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy()); - Ops[Ins.size()+2] = Callee; - - // #Outs - Ops[Ins.size()+3] = DAG.getTargetConstant(outSize, MVT::i32); - - if (isPrintf) { - // first argument is the address of the global string variable in memory - unsigned Param0 = PM.addLocalParam(getPointerTy().getSizeInBits()); - SDValue ParamValue0 = DAG.getTargetExternalSymbol(PM.getParamName(Param0).c_str(), - MVT::Other); - Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain, - ParamValue0, OutVals[0]); - Ops[Ins.size()+4] = ParamValue0; - - // alignment is the maximum size of all the arguments - unsigned alignment = 0; - for (unsigned i = 1; i < OutVals.size(); ++i) { - alignment = std::max(alignment, - OutVals[i].getValueType().getSizeInBits()); - } - - // size is the alignment multiplied by the number of arguments - unsigned size = alignment * (OutVals.size() - 1); - - // second argument is the address of the stack object (unless no arguments) - unsigned Param1 = PM.addLocalParam(getPointerTy().getSizeInBits()); - SDValue ParamValue1 = DAG.getTargetExternalSymbol(PM.getParamName(Param1).c_str(), - MVT::Other); - Ops[Ins.size()+5] = ParamValue1; - - if (size > 0) - { - // create a local stack object to store the arguments - unsigned StackObject = MFI->CreateStackObject(size / 8, alignment / 8, false); - SDValue FrameIndex = DAG.getFrameIndex(StackObject, getPointerTy()); - - // store each of the arguments to the stack in turn - for (unsigned int i = 1; i != OutVals.size(); i++) { - SDValue FrameAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(), FrameIndex, DAG.getTargetConstant((i - 1) * 8, getPointerTy())); - Chain = DAG.getStore(Chain, dl, OutVals[i], FrameAddr, - MachinePointerInfo(), - false, false, 0); - } - - // copy the address of the local frame index to get the address in non-local space - SDValue genericAddr = DAG.getNode(PTXISD::COPY_ADDRESS, dl, getPointerTy(), FrameIndex); - - // store this address in the second argument - Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain, ParamValue1, genericAddr); - } - } - else - { - // Generate STORE_PARAM nodes for each function argument. In PTX, function - // arguments are explicitly stored into .param variables and passed as - // arguments. There is no register/stack-based calling convention in PTX. - for (unsigned i = 0; i != OutVals.size(); ++i) { - unsigned Size = OutVals[i].getValueType().getSizeInBits(); - unsigned Param = PM.addLocalParam(Size); - const std::string &ParamName = PM.getParamName(Param); - SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(), - MVT::Other); - Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain, - ParamValue, OutVals[i]); - Ops[i+Ins.size()+4] = ParamValue; - } - } - - std::vector<SDValue> InParams; - - // Generate list of .param variables to hold the return value(s). - Ops[1] = DAG.getTargetConstant(Ins.size(), MVT::i32); - for (unsigned i = 0; i < Ins.size(); ++i) { - unsigned Size = Ins[i].VT.getStoreSizeInBits(); - unsigned Param = PM.addLocalParam(Size); - const std::string &ParamName = PM.getParamName(Param); - SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(), - MVT::Other); - Ops[i+2] = ParamValue; - InParams.push_back(ParamValue); - } - - Ops[0] = Chain; - - // Create the CALL node. - Chain = DAG.getNode(PTXISD::CALL, dl, MVT::Other, &Ops[0], Ops.size()); - - // Create the LOAD_PARAM nodes that retrieve the function return value(s). - for (unsigned i = 0; i < Ins.size(); ++i) { - SDValue Load = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain, - InParams[i]); - InVals.push_back(Load); - } - - return Chain; -} - -unsigned PTXTargetLowering::getNumRegisters(LLVMContext &Context, EVT VT) { - // All arguments consist of one "register," regardless of the type. - return 1; -} - |