blob: f22c2716987d3685f906dca78e8a901653dfa994 [file] [log] [blame]
Eric Christopher50880d02010-09-18 18:52:28 +00001//===-- PTXISelLowering.cpp - PTX DAG Lowering Implementation -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the PTXTargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000014#include "PTX.h"
Eric Christopher50880d02010-09-18 18:52:28 +000015#include "PTXISelLowering.h"
Che-Liang Chiou3278c422010-11-08 03:00:52 +000016#include "PTXMachineFunctionInfo.h"
Eric Christopher50880d02010-09-18 18:52:28 +000017#include "PTXRegisterInfo.h"
Justin Holewinski67a91842011-06-23 18:10:03 +000018#include "PTXSubtarget.h"
Justin Holewinski75d80952011-09-23 16:48:41 +000019#include "llvm/Function.h"
Eric Christopher50880d02010-09-18 18:52:28 +000020#include "llvm/Support/ErrorHandling.h"
Justin Holewinskie0aef2d2011-06-16 17:50:00 +000021#include "llvm/CodeGen/CallingConvLower.h"
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000022#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
Eric Christopher50880d02010-09-18 18:52:28 +000024#include "llvm/CodeGen/SelectionDAG.h"
25#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +000026#include "llvm/Support/Debug.h"
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000027#include "llvm/Support/raw_ostream.h"
Eric Christopher50880d02010-09-18 18:52:28 +000028
29using namespace llvm;
30
Justin Holewinskie0aef2d2011-06-16 17:50:00 +000031//===----------------------------------------------------------------------===//
Justin Holewinskie0aef2d2011-06-16 17:50:00 +000032// TargetLowering Implementation
33//===----------------------------------------------------------------------===//
34
Eric Christopher50880d02010-09-18 18:52:28 +000035PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
36 : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
37 // Set up the register classes.
Justin Holewinski1b91bcd2011-06-16 17:49:58 +000038 addRegisterClass(MVT::i1, PTX::RegPredRegisterClass);
39 addRegisterClass(MVT::i16, PTX::RegI16RegisterClass);
40 addRegisterClass(MVT::i32, PTX::RegI32RegisterClass);
41 addRegisterClass(MVT::i64, PTX::RegI64RegisterClass);
42 addRegisterClass(MVT::f32, PTX::RegF32RegisterClass);
43 addRegisterClass(MVT::f64, PTX::RegF64RegisterClass);
Che-Liang Chioufd8978b2011-03-02 03:20:28 +000044
Justin Holewinski4fea05a2011-04-28 00:19:52 +000045 setBooleanContents(ZeroOrOneBooleanContent);
Duncan Sands28b77e92011-09-06 19:07:46 +000046 setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
Dan Bailey84149462011-06-25 18:16:28 +000047 setMinFunctionAlignment(2);
Justin Holewinski05591be2011-09-22 16:45:43 +000048
Dan Bailey84149462011-06-25 18:16:28 +000049 ////////////////////////////////////
50 /////////// Expansion //////////////
51 ////////////////////////////////////
Justin Holewinski05591be2011-09-22 16:45:43 +000052
Dan Bailey84149462011-06-25 18:16:28 +000053 // (any/zero/sign) extload => load + (any/zero/sign) extend
Justin Holewinski05591be2011-09-22 16:45:43 +000054
Justin Holewinski4fea05a2011-04-28 00:19:52 +000055 setLoadExtAction(ISD::EXTLOAD, MVT::i16, Expand);
56 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand);
Dan Baileyb05a8a82011-06-24 19:27:10 +000057 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand);
Justin Holewinski05591be2011-09-22 16:45:43 +000058
Dan Bailey84149462011-06-25 18:16:28 +000059 // f32 extload => load + fextend
Justin Holewinski05591be2011-09-22 16:45:43 +000060
61 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
62
Dan Bailey84149462011-06-25 18:16:28 +000063 // f64 truncstore => trunc + store
Justin Holewinski05591be2011-09-22 16:45:43 +000064
65 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
66
Dan Bailey84149462011-06-25 18:16:28 +000067 // sign_extend_inreg => sign_extend
Justin Holewinski05591be2011-09-22 16:45:43 +000068
Dan Bailey84149462011-06-25 18:16:28 +000069 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Justin Holewinski05591be2011-09-22 16:45:43 +000070
Dan Bailey84149462011-06-25 18:16:28 +000071 // br_cc => brcond
Justin Holewinski05591be2011-09-22 16:45:43 +000072
Che-Liang Chiou88d33672011-03-18 11:08:52 +000073 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
74
Dan Bailey84149462011-06-25 18:16:28 +000075 // select_cc => setcc
Justin Holewinski05591be2011-09-22 16:45:43 +000076
Justin Holewinski2d525c52011-04-28 00:19:56 +000077 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
78 setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
79 setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
Justin Holewinski05591be2011-09-22 16:45:43 +000080
Dan Bailey84149462011-06-25 18:16:28 +000081 ////////////////////////////////////
82 //////////// Legal /////////////////
83 ////////////////////////////////////
Justin Holewinski05591be2011-09-22 16:45:43 +000084
Dan Bailey84149462011-06-25 18:16:28 +000085 setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
86 setOperationAction(ISD::ConstantFP, MVT::f64, Legal);
Justin Holewinski05591be2011-09-22 16:45:43 +000087
Dan Bailey84149462011-06-25 18:16:28 +000088 ////////////////////////////////////
89 //////////// Custom ////////////////
90 ////////////////////////////////////
Justin Holewinski05591be2011-09-22 16:45:43 +000091
Dan Bailey84149462011-06-25 18:16:28 +000092 // customise setcc to use bitwise logic if possible
Justin Holewinski05591be2011-09-22 16:45:43 +000093
Justin Holewinski2d525c52011-04-28 00:19:56 +000094 setOperationAction(ISD::SETCC, MVT::i1, Custom);
Eli Friedmanfc5d3052011-05-06 20:34:06 +000095
Dan Bailey84149462011-06-25 18:16:28 +000096 // customize translation of memory addresses
Justin Holewinski05591be2011-09-22 16:45:43 +000097
Dan Bailey84149462011-06-25 18:16:28 +000098 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
99 setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
Eli Friedmanfc5d3052011-05-06 20:34:06 +0000100
Eric Christopher50880d02010-09-18 18:52:28 +0000101 // Compute derived properties from the register classes
102 computeRegisterProperties();
103}
104
Duncan Sands28b77e92011-09-06 19:07:46 +0000105EVT PTXTargetLowering::getSetCCResultType(EVT VT) const {
Justin Holewinski2d525c52011-04-28 00:19:56 +0000106 return MVT::i1;
107}
108
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000109SDValue PTXTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
110 switch (Op.getOpcode()) {
Che-Liang Chiou88d33672011-03-18 11:08:52 +0000111 default:
112 llvm_unreachable("Unimplemented operand");
Justin Holewinski2d525c52011-04-28 00:19:56 +0000113 case ISD::SETCC:
114 return LowerSETCC(Op, DAG);
Che-Liang Chiou88d33672011-03-18 11:08:52 +0000115 case ISD::GlobalAddress:
116 return LowerGlobalAddress(Op, DAG);
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000117 }
118}
119
Eric Christopher50880d02010-09-18 18:52:28 +0000120const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const {
121 switch (Opcode) {
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +0000122 default:
123 llvm_unreachable("Unknown opcode");
Justin Holewinski8af78c92011-03-18 19:24:28 +0000124 case PTXISD::COPY_ADDRESS:
125 return "PTXISD::COPY_ADDRESS";
Justin Holewinskia5ccb4e2011-06-23 18:10:05 +0000126 case PTXISD::LOAD_PARAM:
127 return "PTXISD::LOAD_PARAM";
Justin Holewinski67a91842011-06-23 18:10:03 +0000128 case PTXISD::STORE_PARAM:
129 return "PTXISD::STORE_PARAM";
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000130 case PTXISD::READ_PARAM:
131 return "PTXISD::READ_PARAM";
132 case PTXISD::WRITE_PARAM:
133 return "PTXISD::WRITE_PARAM";
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +0000134 case PTXISD::EXIT:
135 return "PTXISD::EXIT";
136 case PTXISD::RET:
137 return "PTXISD::RET";
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000138 case PTXISD::CALL:
139 return "PTXISD::CALL";
Eric Christopher50880d02010-09-18 18:52:28 +0000140 }
141}
142
143//===----------------------------------------------------------------------===//
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000144// Custom Lower Operation
145//===----------------------------------------------------------------------===//
146
Justin Holewinski2d525c52011-04-28 00:19:56 +0000147SDValue PTXTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
148 assert(Op.getValueType() == MVT::i1 && "SetCC type must be 1-bit integer");
149 SDValue Op0 = Op.getOperand(0);
150 SDValue Op1 = Op.getOperand(1);
151 SDValue Op2 = Op.getOperand(2);
152 DebugLoc dl = Op.getDebugLoc();
153 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
Justin Holewinskiec3141b2011-06-16 15:17:11 +0000154
Justin Holewinski05591be2011-09-22 16:45:43 +0000155 // Look for X == 0, X == 1, X != 0, or X != 1
Justin Holewinski2d525c52011-04-28 00:19:56 +0000156 // We can simplify these to bitwise logic
Justin Holewinskiec3141b2011-06-16 15:17:11 +0000157
Justin Holewinski2d525c52011-04-28 00:19:56 +0000158 if (Op1.getOpcode() == ISD::Constant &&
159 (cast<ConstantSDNode>(Op1)->getZExtValue() == 1 ||
160 cast<ConstantSDNode>(Op1)->isNullValue()) &&
161 (CC == ISD::SETEQ || CC == ISD::SETNE)) {
162
Justin Holewinskiec3141b2011-06-16 15:17:11 +0000163 return DAG.getNode(ISD::AND, dl, MVT::i1, Op0, Op1);
Justin Holewinski2d525c52011-04-28 00:19:56 +0000164 }
Justin Holewinskiec3141b2011-06-16 15:17:11 +0000165
Justin Holewinski2d525c52011-04-28 00:19:56 +0000166 return DAG.getNode(ISD::SETCC, dl, MVT::i1, Op0, Op1, Op2);
167}
168
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000169SDValue PTXTargetLowering::
170LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const {
171 EVT PtrVT = getPointerTy();
172 DebugLoc dl = Op.getDebugLoc();
173 const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
Justin Holewinski8af78c92011-03-18 19:24:28 +0000174
Justin Holewinskid6625762011-03-23 16:58:51 +0000175 assert(PtrVT.isSimple() && "Pointer must be to primitive type.");
176
Justin Holewinski8af78c92011-03-18 19:24:28 +0000177 SDValue targetGlobal = DAG.getTargetGlobalAddress(GV, dl, PtrVT);
178 SDValue movInstr = DAG.getNode(PTXISD::COPY_ADDRESS,
179 dl,
Justin Holewinskid6625762011-03-23 16:58:51 +0000180 PtrVT.getSimpleVT(),
Justin Holewinski8af78c92011-03-18 19:24:28 +0000181 targetGlobal);
182
183 return movInstr;
Che-Liang Chioufc7072c2010-12-22 10:38:51 +0000184}
185
186//===----------------------------------------------------------------------===//
Eric Christopher50880d02010-09-18 18:52:28 +0000187// Calling Convention Implementation
188//===----------------------------------------------------------------------===//
189
190SDValue PTXTargetLowering::
191 LowerFormalArguments(SDValue Chain,
192 CallingConv::ID CallConv,
193 bool isVarArg,
194 const SmallVectorImpl<ISD::InputArg> &Ins,
195 DebugLoc dl,
196 SelectionDAG &DAG,
197 SmallVectorImpl<SDValue> &InVals) const {
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000198 if (isVarArg) llvm_unreachable("PTX does not support varargs");
199
Che-Liang Chiou3278c422010-11-08 03:00:52 +0000200 MachineFunction &MF = DAG.getMachineFunction();
Justin Holewinski67a91842011-06-23 18:10:03 +0000201 const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>();
Che-Liang Chiou3278c422010-11-08 03:00:52 +0000202 PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000203 PTXParamManager &PM = MFI->getParamManager();
Che-Liang Chiou3278c422010-11-08 03:00:52 +0000204
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000205 switch (CallConv) {
206 default:
207 llvm_unreachable("Unsupported calling convention");
208 break;
209 case CallingConv::PTX_Kernel:
Che-Liang Chiou8e5d01c2011-02-10 12:01:24 +0000210 MFI->setKernel(true);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000211 break;
212 case CallingConv::PTX_Device:
Che-Liang Chiou3278c422010-11-08 03:00:52 +0000213 MFI->setKernel(false);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000214 break;
215 }
216
Justin Holewinski67a91842011-06-23 18:10:03 +0000217 // We do one of two things here:
218 // IsKernel || SM >= 2.0 -> Use param space for arguments
219 // SM < 2.0 -> Use registers for arguments
Justin Holewinski35f4fb32011-06-24 16:27:49 +0000220 if (MFI->isKernel() || ST.useParamSpaceForDeviceArgs()) {
Justin Holewinskia5ccb4e2011-06-23 18:10:05 +0000221 // We just need to emit the proper LOAD_PARAM ISDs
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000222 for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
Justin Holewinski67a91842011-06-23 18:10:03 +0000223 assert((!MFI->isKernel() || Ins[i].VT != MVT::i1) &&
224 "Kernels cannot take pred operands");
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000225
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000226 unsigned ParamSize = Ins[i].VT.getStoreSizeInBits();
227 unsigned Param = PM.addArgumentParam(ParamSize);
Justin Holewinskia5ccb4e2011-06-23 18:10:05 +0000228 SDValue ArgValue = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain,
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000229 DAG.getTargetConstant(Param, MVT::i32));
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000230 InVals.push_back(ArgValue);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000231 }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000232 }
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000233 else {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000234 for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000235 EVT RegVT = Ins[i].VT;
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000236 TargetRegisterClass* TRC = 0;
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000237 int OpCode;
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000238
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000239 // Determine which register class we need
240 if (RegVT == MVT::i1) {
241 TRC = PTX::RegPredRegisterClass;
242 OpCode = PTX::READPARAMPRED;
243 }
244 else if (RegVT == MVT::i16) {
245 TRC = PTX::RegI16RegisterClass;
246 OpCode = PTX::READPARAMI16;
247 }
248 else if (RegVT == MVT::i32) {
249 TRC = PTX::RegI32RegisterClass;
250 OpCode = PTX::READPARAMI32;
251 }
252 else if (RegVT == MVT::i64) {
253 TRC = PTX::RegI64RegisterClass;
254 OpCode = PTX::READPARAMI64;
255 }
256 else if (RegVT == MVT::f32) {
257 TRC = PTX::RegF32RegisterClass;
258 OpCode = PTX::READPARAMF32;
259 }
260 else if (RegVT == MVT::f64) {
261 TRC = PTX::RegF64RegisterClass;
262 OpCode = PTX::READPARAMF64;
263 }
264 else {
265 llvm_unreachable("Unknown parameter type");
266 }
267
268 // Use a unique index in the instruction to prevent instruction folding.
269 // Yes, this is a hack.
270 SDValue Index = DAG.getTargetConstant(i, MVT::i32);
271 unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
272 SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, RegVT, Chain,
273 Index);
274
275 SDValue Flag = ArgValue.getValue(1);
276
277 SDValue Copy = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
278 SDValue RegValue = DAG.getRegister(Reg, RegVT);
279 InVals.push_back(ArgValue);
280
281 MFI->addArgReg(Reg);
282 }
283 }
284
285 return Chain;
286}
287
288SDValue PTXTargetLowering::
289 LowerReturn(SDValue Chain,
290 CallingConv::ID CallConv,
291 bool isVarArg,
292 const SmallVectorImpl<ISD::OutputArg> &Outs,
293 const SmallVectorImpl<SDValue> &OutVals,
294 DebugLoc dl,
295 SelectionDAG &DAG) const {
296 if (isVarArg) llvm_unreachable("PTX does not support varargs");
297
298 switch (CallConv) {
299 default:
300 llvm_unreachable("Unsupported calling convention.");
301 case CallingConv::PTX_Kernel:
302 assert(Outs.size() == 0 && "Kernel must return void.");
303 return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
304 case CallingConv::PTX_Device:
305 assert(Outs.size() <= 1 && "Can at most return one value.");
306 break;
307 }
308
309 MachineFunction& MF = DAG.getMachineFunction();
310 PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000311 PTXParamManager &PM = MFI->getParamManager();
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000312
313 SDValue Flag;
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000314 const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>();
315
316 if (ST.useParamSpaceForDeviceArgs()) {
317 assert(Outs.size() < 2 && "Device functions can return at most one value");
318
319 if (Outs.size() == 1) {
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000320 unsigned ParamSize = OutVals[0].getValueType().getSizeInBits();
321 unsigned Param = PM.addReturnParam(ParamSize);
322 SDValue ParamIndex = DAG.getTargetConstant(Param, MVT::i32);
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000323 Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain,
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000324 ParamIndex, OutVals[0]);
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000325 }
326 } else {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000327 for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000328 EVT RegVT = Outs[i].VT;
329 TargetRegisterClass* TRC = 0;
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000330
331 // Determine which register class we need
332 if (RegVT == MVT::i1) {
333 TRC = PTX::RegPredRegisterClass;
334 }
335 else if (RegVT == MVT::i16) {
336 TRC = PTX::RegI16RegisterClass;
337 }
338 else if (RegVT == MVT::i32) {
339 TRC = PTX::RegI32RegisterClass;
340 }
341 else if (RegVT == MVT::i64) {
342 TRC = PTX::RegI64RegisterClass;
343 }
344 else if (RegVT == MVT::f32) {
345 TRC = PTX::RegF32RegisterClass;
346 }
347 else if (RegVT == MVT::f64) {
348 TRC = PTX::RegF64RegisterClass;
349 }
350 else {
351 llvm_unreachable("Unknown parameter type");
352 }
353
354 unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000355
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000356 SDValue Copy = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i]/*, Flag*/);
357 SDValue OutReg = DAG.getRegister(Reg, RegVT);
358
359 Chain = DAG.getNode(PTXISD::WRITE_PARAM, dl, MVT::Other, Copy, OutReg);
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000360
361 MFI->addRetReg(Reg);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000362 }
363 }
Che-Liang Chiou3278c422010-11-08 03:00:52 +0000364
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000365 if (Flag.getNode() == 0) {
366 return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
Che-Liang Chiouf7172022011-02-28 06:34:09 +0000367 }
368 else {
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000369 return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
Che-Liang Chiouf7172022011-02-28 06:34:09 +0000370 }
Eric Christopher50880d02010-09-18 18:52:28 +0000371}
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000372
373SDValue
374PTXTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
375 CallingConv::ID CallConv, bool isVarArg,
376 bool &isTailCall,
377 const SmallVectorImpl<ISD::OutputArg> &Outs,
378 const SmallVectorImpl<SDValue> &OutVals,
379 const SmallVectorImpl<ISD::InputArg> &Ins,
380 DebugLoc dl, SelectionDAG &DAG,
381 SmallVectorImpl<SDValue> &InVals) const {
382
383 MachineFunction& MF = DAG.getMachineFunction();
384 PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
Justin Holewinskie953a642011-09-23 14:31:12 +0000385 PTXParamManager &PM = MFI->getParamManager();
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000386
Duncan Sands1f6a3292011-08-12 14:54:45 +0000387 assert(getTargetMachine().getSubtarget<PTXSubtarget>().callsAreHandled() &&
388 "Calls are not handled for the target device");
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000389
Justin Holewinski75d80952011-09-23 16:48:41 +0000390 std::vector<SDValue> Ops;
391 // The layout of the ops will be [Chain, Ins, Callee, Outs]
392 Ops.resize(Outs.size() + Ins.size() + 2);
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000393
Justin Holewinski75d80952011-09-23 16:48:41 +0000394 Ops[0] = Chain;
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000395
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000396 // Identify the callee function
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000397 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
398 const GlobalValue *GV = G->getGlobal();
Justin Holewinski75d80952011-09-23 16:48:41 +0000399 if (const Function *F = dyn_cast<Function>(GV)) {
400 assert(F->getCallingConv() == CallingConv::PTX_Device &&
401 "PTX function calls must be to PTX device functions");
402 Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy());
403 Ops[Ins.size()+1] = Callee;
404 } else {
405 assert(false && "GlobalValue is not a function");
406 }
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000407 } else {
408 assert(false && "Function must be a GlobalAddressSDNode");
409 }
410
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000411 // Generate STORE_PARAM nodes for each function argument. In PTX, function
412 // arguments are explicitly stored into .param variables and passed as
413 // arguments. There is no register/stack-based calling convention in PTX.
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000414 for (unsigned i = 0; i != OutVals.size(); ++i) {
415 unsigned Size = OutVals[i].getValueType().getSizeInBits();
Justin Holewinskie953a642011-09-23 14:31:12 +0000416 unsigned Param = PM.addLocalParam(Size);
417 SDValue Index = DAG.getTargetConstant(Param, MVT::i32);
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000418 Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain,
419 Index, OutVals[i]);
Justin Holewinski75d80952011-09-23 16:48:41 +0000420 Ops[i+Ins.size()+2] = Index;
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000421 }
422
Justin Holewinski75d80952011-09-23 16:48:41 +0000423 std::vector<unsigned> InParams;
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000424
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000425 // Generate list of .param variables to hold the return value(s).
Justin Holewinski75d80952011-09-23 16:48:41 +0000426 for (unsigned i = 0; i < Ins.size(); ++i) {
427 unsigned Size = Ins[i].VT.getStoreSizeInBits();
428 unsigned Param = PM.addLocalParam(Size);
429 SDValue Index = DAG.getTargetConstant(Param, MVT::i32);
430 Ops[i+1] = Index;
431 InParams.push_back(Param);
432 }
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000433
Justin Holewinski75d80952011-09-23 16:48:41 +0000434 Ops[0] = Chain;
435
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000436 // Create the CALL node.
Justin Holewinski75d80952011-09-23 16:48:41 +0000437 Chain = DAG.getNode(PTXISD::CALL, dl, MVT::Other, &Ops[0], Ops.size());
438
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000439 // Create the LOAD_PARAM nodes that retrieve the function return value(s).
Justin Holewinski75d80952011-09-23 16:48:41 +0000440 for (unsigned i = 0; i < Ins.size(); ++i) {
441 SDValue Index = DAG.getTargetConstant(InParams[i], MVT::i32);
442 SDValue Load = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain, Index);
443 InVals.push_back(Load);
444 }
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000445
446 return Chain;
447}