blob: ce8cd7cdbe662fc9329e9aefd77f6b186619af05 [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);
Benjamin Kramer8adae0c2011-09-28 04:08:02 +0000228 const std::string &ParamName = PM.getParamName(Param);
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000229 SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
230 MVT::Other);
Justin Holewinskia5ccb4e2011-06-23 18:10:05 +0000231 SDValue ArgValue = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain,
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000232 ParamValue);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000233 InVals.push_back(ArgValue);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000234 }
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000235 }
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000236 else {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000237 for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000238 EVT RegVT = Ins[i].VT;
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000239 TargetRegisterClass* TRC = 0;
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000240 int OpCode;
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000241
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000242 // Determine which register class we need
243 if (RegVT == MVT::i1) {
244 TRC = PTX::RegPredRegisterClass;
245 OpCode = PTX::READPARAMPRED;
246 }
247 else if (RegVT == MVT::i16) {
248 TRC = PTX::RegI16RegisterClass;
249 OpCode = PTX::READPARAMI16;
250 }
251 else if (RegVT == MVT::i32) {
252 TRC = PTX::RegI32RegisterClass;
253 OpCode = PTX::READPARAMI32;
254 }
255 else if (RegVT == MVT::i64) {
256 TRC = PTX::RegI64RegisterClass;
257 OpCode = PTX::READPARAMI64;
258 }
259 else if (RegVT == MVT::f32) {
260 TRC = PTX::RegF32RegisterClass;
261 OpCode = PTX::READPARAMF32;
262 }
263 else if (RegVT == MVT::f64) {
264 TRC = PTX::RegF64RegisterClass;
265 OpCode = PTX::READPARAMF64;
266 }
267 else {
268 llvm_unreachable("Unknown parameter type");
269 }
270
271 // Use a unique index in the instruction to prevent instruction folding.
272 // Yes, this is a hack.
273 SDValue Index = DAG.getTargetConstant(i, MVT::i32);
274 unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
275 SDValue ArgValue = DAG.getNode(PTXISD::READ_PARAM, dl, RegVT, Chain,
276 Index);
277
278 SDValue Flag = ArgValue.getValue(1);
279
280 SDValue Copy = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
281 SDValue RegValue = DAG.getRegister(Reg, RegVT);
282 InVals.push_back(ArgValue);
283
284 MFI->addArgReg(Reg);
285 }
286 }
287
288 return Chain;
289}
290
291SDValue PTXTargetLowering::
292 LowerReturn(SDValue Chain,
293 CallingConv::ID CallConv,
294 bool isVarArg,
295 const SmallVectorImpl<ISD::OutputArg> &Outs,
296 const SmallVectorImpl<SDValue> &OutVals,
297 DebugLoc dl,
298 SelectionDAG &DAG) const {
299 if (isVarArg) llvm_unreachable("PTX does not support varargs");
300
301 switch (CallConv) {
302 default:
303 llvm_unreachable("Unsupported calling convention.");
304 case CallingConv::PTX_Kernel:
305 assert(Outs.size() == 0 && "Kernel must return void.");
306 return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
307 case CallingConv::PTX_Device:
308 assert(Outs.size() <= 1 && "Can at most return one value.");
309 break;
310 }
311
312 MachineFunction& MF = DAG.getMachineFunction();
313 PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000314 PTXParamManager &PM = MFI->getParamManager();
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000315
316 SDValue Flag;
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000317 const PTXSubtarget& ST = getTargetMachine().getSubtarget<PTXSubtarget>();
318
319 if (ST.useParamSpaceForDeviceArgs()) {
320 assert(Outs.size() < 2 && "Device functions can return at most one value");
321
322 if (Outs.size() == 1) {
Justin Holewinski27f08fc2011-09-23 14:18:22 +0000323 unsigned ParamSize = OutVals[0].getValueType().getSizeInBits();
324 unsigned Param = PM.addReturnParam(ParamSize);
Benjamin Kramer8adae0c2011-09-28 04:08:02 +0000325 const std::string &ParamName = PM.getParamName(Param);
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000326 SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
327 MVT::Other);
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000328 Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain,
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000329 ParamValue, OutVals[0]);
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000330 }
331 } else {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000332 for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000333 EVT RegVT = Outs[i].VT;
334 TargetRegisterClass* TRC = 0;
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000335
336 // Determine which register class we need
337 if (RegVT == MVT::i1) {
338 TRC = PTX::RegPredRegisterClass;
339 }
340 else if (RegVT == MVT::i16) {
341 TRC = PTX::RegI16RegisterClass;
342 }
343 else if (RegVT == MVT::i32) {
344 TRC = PTX::RegI32RegisterClass;
345 }
346 else if (RegVT == MVT::i64) {
347 TRC = PTX::RegI64RegisterClass;
348 }
349 else if (RegVT == MVT::f32) {
350 TRC = PTX::RegF32RegisterClass;
351 }
352 else if (RegVT == MVT::f64) {
353 TRC = PTX::RegF64RegisterClass;
354 }
355 else {
356 llvm_unreachable("Unknown parameter type");
357 }
358
359 unsigned Reg = MF.getRegInfo().createVirtualRegister(TRC);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000360
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000361 SDValue Copy = DAG.getCopyToReg(Chain, dl, Reg, OutVals[i]/*, Flag*/);
362 SDValue OutReg = DAG.getRegister(Reg, RegVT);
363
364 Chain = DAG.getNode(PTXISD::WRITE_PARAM, dl, MVT::Other, Copy, OutReg);
Justin Holewinski5422a0f2011-09-22 16:45:46 +0000365
366 MFI->addRetReg(Reg);
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000367 }
368 }
Che-Liang Chiou3278c422010-11-08 03:00:52 +0000369
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000370 if (Flag.getNode() == 0) {
371 return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
Che-Liang Chiouf7172022011-02-28 06:34:09 +0000372 }
373 else {
Justin Holewinskie0aef2d2011-06-16 17:50:00 +0000374 return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
Che-Liang Chiouf7172022011-02-28 06:34:09 +0000375 }
Eric Christopher50880d02010-09-18 18:52:28 +0000376}
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000377
378SDValue
379PTXTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
380 CallingConv::ID CallConv, bool isVarArg,
381 bool &isTailCall,
382 const SmallVectorImpl<ISD::OutputArg> &Outs,
383 const SmallVectorImpl<SDValue> &OutVals,
384 const SmallVectorImpl<ISD::InputArg> &Ins,
385 DebugLoc dl, SelectionDAG &DAG,
386 SmallVectorImpl<SDValue> &InVals) const {
387
388 MachineFunction& MF = DAG.getMachineFunction();
389 PTXMachineFunctionInfo *MFI = MF.getInfo<PTXMachineFunctionInfo>();
Justin Holewinskie953a642011-09-23 14:31:12 +0000390 PTXParamManager &PM = MFI->getParamManager();
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000391
Duncan Sands1f6a3292011-08-12 14:54:45 +0000392 assert(getTargetMachine().getSubtarget<PTXSubtarget>().callsAreHandled() &&
393 "Calls are not handled for the target device");
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000394
Justin Holewinski75d80952011-09-23 16:48:41 +0000395 std::vector<SDValue> Ops;
Justin Holewinskid8e4ed22011-09-28 14:32:04 +0000396 // The layout of the ops will be [Chain, #Ins, Ins, Callee, #Outs, Outs]
397 Ops.resize(Outs.size() + Ins.size() + 4);
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000398
Justin Holewinski75d80952011-09-23 16:48:41 +0000399 Ops[0] = Chain;
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000400
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000401 // Identify the callee function
Benjamin Kramerca921592011-09-28 04:32:36 +0000402 const GlobalValue *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal();
403 assert(cast<Function>(GV)->getCallingConv() == CallingConv::PTX_Device &&
404 "PTX function calls must be to PTX device functions");
405 Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy());
Justin Holewinskid8e4ed22011-09-28 14:32:04 +0000406 Ops[Ins.size()+2] = Callee;
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000407
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000408 // Generate STORE_PARAM nodes for each function argument. In PTX, function
409 // arguments are explicitly stored into .param variables and passed as
410 // arguments. There is no register/stack-based calling convention in PTX.
Justin Holewinskid8e4ed22011-09-28 14:32:04 +0000411 Ops[Ins.size()+3] = DAG.getTargetConstant(OutVals.size(), MVT::i32);
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000412 for (unsigned i = 0; i != OutVals.size(); ++i) {
413 unsigned Size = OutVals[i].getValueType().getSizeInBits();
Justin Holewinskie953a642011-09-23 14:31:12 +0000414 unsigned Param = PM.addLocalParam(Size);
Benjamin Kramer8adae0c2011-09-28 04:08:02 +0000415 const std::string &ParamName = PM.getParamName(Param);
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000416 SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
417 MVT::Other);
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000418 Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain,
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000419 ParamValue, OutVals[i]);
Justin Holewinskid8e4ed22011-09-28 14:32:04 +0000420 Ops[i+Ins.size()+4] = ParamValue;
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000421 }
422
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000423 std::vector<SDValue> 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 Holewinskid8e4ed22011-09-28 14:32:04 +0000426 Ops[1] = DAG.getTargetConstant(Ins.size(), MVT::i32);
Justin Holewinski75d80952011-09-23 16:48:41 +0000427 for (unsigned i = 0; i < Ins.size(); ++i) {
428 unsigned Size = Ins[i].VT.getStoreSizeInBits();
429 unsigned Param = PM.addLocalParam(Size);
Benjamin Kramer8adae0c2011-09-28 04:08:02 +0000430 const std::string &ParamName = PM.getParamName(Param);
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000431 SDValue ParamValue = DAG.getTargetExternalSymbol(ParamName.c_str(),
432 MVT::Other);
Justin Holewinskid8e4ed22011-09-28 14:32:04 +0000433 Ops[i+2] = ParamValue;
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000434 InParams.push_back(ParamValue);
Justin Holewinski75d80952011-09-23 16:48:41 +0000435 }
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000436
Justin Holewinski75d80952011-09-23 16:48:41 +0000437 Ops[0] = Chain;
438
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000439 // Create the CALL node.
Justin Holewinski75d80952011-09-23 16:48:41 +0000440 Chain = DAG.getNode(PTXISD::CALL, dl, MVT::Other, &Ops[0], Ops.size());
441
Justin Holewinskidc0baf92011-09-23 17:15:53 +0000442 // Create the LOAD_PARAM nodes that retrieve the function return value(s).
Justin Holewinski75d80952011-09-23 16:48:41 +0000443 for (unsigned i = 0; i < Ins.size(); ++i) {
Justin Holewinskif47dfba2011-09-27 18:12:55 +0000444 SDValue Load = DAG.getNode(PTXISD::LOAD_PARAM, dl, Ins[i].VT, Chain,
445 InParams[i]);
Justin Holewinski75d80952011-09-23 16:48:41 +0000446 InVals.push_back(Load);
447 }
Justin Holewinski4bdd4ed2011-08-09 17:36:31 +0000448
449 return Chain;
450}