blob: 40871d6d2d45afd63961fef1f52f181f450732ea [file] [log] [blame]
Justin Holewinskiae556d32012-05-04 20:18:50 +00001//===-- NVPTXISelDAGToDAG.cpp - A dag to dag inst selector for NVPTX ------===//
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 defines an instruction selector for the NVPTX target.
11//
12//===----------------------------------------------------------------------===//
13
Justin Holewinskiae556d32012-05-04 20:18:50 +000014#include "NVPTXISelDAGToDAG.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000015#include "llvm/IR/GlobalValue.h"
16#include "llvm/IR/Instructions.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000017#include "llvm/Support/CommandLine.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000018#include "llvm/Support/Debug.h"
19#include "llvm/Support/ErrorHandling.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/Support/raw_ostream.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000021#include "llvm/Target/TargetIntrinsicInfo.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000022
23#undef DEBUG_TYPE
24#define DEBUG_TYPE "nvptx-isel"
25
26using namespace llvm;
27
Justin Holewinski0497ab12013-03-30 14:29:21 +000028static cl::opt<bool> UseFMADInstruction(
29 "nvptx-mad-enable", cl::ZeroOrMore,
30 cl::desc("NVPTX Specific: Enable generating FMAD instructions"),
31 cl::init(false));
Justin Holewinskiae556d32012-05-04 20:18:50 +000032
33static cl::opt<int>
Justin Holewinski0497ab12013-03-30 14:29:21 +000034FMAContractLevel("nvptx-fma-level", cl::ZeroOrMore,
Justin Holewinskiae556d32012-05-04 20:18:50 +000035 cl::desc("NVPTX Specific: FMA contraction (0: don't do it"
Justin Holewinski0497ab12013-03-30 14:29:21 +000036 " 1: do it 2: do it aggressively"),
37 cl::init(2));
Justin Holewinskiae556d32012-05-04 20:18:50 +000038
Justin Holewinski0497ab12013-03-30 14:29:21 +000039static cl::opt<int> UsePrecDivF32(
40 "nvptx-prec-divf32", cl::ZeroOrMore,
41 cl::desc("NVPTX Specifies: 0 use div.approx, 1 use div.full, 2 use"
42 " IEEE Compliant F32 div.rnd if avaiable."),
43 cl::init(2));
Justin Holewinskiae556d32012-05-04 20:18:50 +000044
Justin Holewinski48f4ad32013-05-21 16:51:30 +000045static cl::opt<bool>
46UsePrecSqrtF32("nvptx-prec-sqrtf32",
47 cl::desc("NVPTX Specific: 0 use sqrt.approx, 1 use sqrt.rn."),
48 cl::init(true));
49
Justin Holewinskiae556d32012-05-04 20:18:50 +000050/// createNVPTXISelDag - This pass converts a legalized DAG into a
51/// NVPTX-specific DAG, ready for instruction scheduling.
52FunctionPass *llvm::createNVPTXISelDag(NVPTXTargetMachine &TM,
53 llvm::CodeGenOpt::Level OptLevel) {
54 return new NVPTXDAGToDAGISel(TM, OptLevel);
55}
56
Justin Holewinskiae556d32012-05-04 20:18:50 +000057NVPTXDAGToDAGISel::NVPTXDAGToDAGISel(NVPTXTargetMachine &tm,
58 CodeGenOpt::Level OptLevel)
Justin Holewinski0497ab12013-03-30 14:29:21 +000059 : SelectionDAGISel(tm, OptLevel),
60 Subtarget(tm.getSubtarget<NVPTXSubtarget>()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +000061 // Always do fma.f32 fpcontract if the target supports the instruction.
62 // Always do fma.f64 fpcontract if the target supports the instruction.
63 // Do mad.f32 is nvptx-mad-enable is specified and the target does not
64 // support fma.f32.
65
66 doFMADF32 = (OptLevel > 0) && UseFMADInstruction && !Subtarget.hasFMAF32();
Justin Holewinski0497ab12013-03-30 14:29:21 +000067 doFMAF32 = (OptLevel > 0) && Subtarget.hasFMAF32() && (FMAContractLevel >= 1);
68 doFMAF64 = (OptLevel > 0) && Subtarget.hasFMAF64() && (FMAContractLevel >= 1);
69 doFMAF32AGG =
70 (OptLevel > 0) && Subtarget.hasFMAF32() && (FMAContractLevel == 2);
71 doFMAF64AGG =
72 (OptLevel > 0) && Subtarget.hasFMAF64() && (FMAContractLevel == 2);
Justin Holewinskiae556d32012-05-04 20:18:50 +000073
74 allowFMA = (FMAContractLevel >= 1) || UseFMADInstruction;
75
Benjamin Kramera25a61b2012-05-05 11:22:02 +000076 UseF32FTZ = false;
77
Justin Holewinskiae556d32012-05-04 20:18:50 +000078 doMulWide = (OptLevel > 0);
79
80 // Decide how to translate f32 div
81 do_DIVF32_PREC = UsePrecDivF32;
Justin Holewinski48f4ad32013-05-21 16:51:30 +000082 // Decide how to translate f32 sqrt
83 do_SQRTF32_PREC = UsePrecSqrtF32;
Justin Holewinskiae556d32012-05-04 20:18:50 +000084 // sm less than sm_20 does not support div.rnd. Use div.full.
85 if (do_DIVF32_PREC == 2 && !Subtarget.reqPTX20())
86 do_DIVF32_PREC = 1;
87
88}
89
90/// Select - Select instructions not customized! Used for
91/// expanded, promoted and normal instructions.
Justin Holewinski0497ab12013-03-30 14:29:21 +000092SDNode *NVPTXDAGToDAGISel::Select(SDNode *N) {
Justin Holewinskiae556d32012-05-04 20:18:50 +000093
94 if (N->isMachineOpcode())
Justin Holewinski0497ab12013-03-30 14:29:21 +000095 return NULL; // Already selected.
Justin Holewinskiae556d32012-05-04 20:18:50 +000096
97 SDNode *ResNode = NULL;
98 switch (N->getOpcode()) {
99 case ISD::LOAD:
100 ResNode = SelectLoad(N);
101 break;
102 case ISD::STORE:
103 ResNode = SelectStore(N);
104 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000105 case NVPTXISD::LoadV2:
106 case NVPTXISD::LoadV4:
107 ResNode = SelectLoadVector(N);
108 break;
109 case NVPTXISD::LDGV2:
110 case NVPTXISD::LDGV4:
111 case NVPTXISD::LDUV2:
112 case NVPTXISD::LDUV4:
113 ResNode = SelectLDGLDUVector(N);
114 break;
115 case NVPTXISD::StoreV2:
116 case NVPTXISD::StoreV4:
117 ResNode = SelectStoreVector(N);
118 break;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000119 default:
120 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000121 }
122 if (ResNode)
123 return ResNode;
124 return SelectCode(N);
125}
126
Justin Holewinski0497ab12013-03-30 14:29:21 +0000127static unsigned int getCodeAddrSpace(MemSDNode *N,
128 const NVPTXSubtarget &Subtarget) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000129 const Value *Src = N->getSrcValue();
130 if (!Src)
131 return NVPTX::PTXLdStInstCode::LOCAL;
132
133 if (const PointerType *PT = dyn_cast<PointerType>(Src->getType())) {
134 switch (PT->getAddressSpace()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000135 case llvm::ADDRESS_SPACE_LOCAL:
136 return NVPTX::PTXLdStInstCode::LOCAL;
137 case llvm::ADDRESS_SPACE_GLOBAL:
138 return NVPTX::PTXLdStInstCode::GLOBAL;
139 case llvm::ADDRESS_SPACE_SHARED:
140 return NVPTX::PTXLdStInstCode::SHARED;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000141 case llvm::ADDRESS_SPACE_CONST_NOT_GEN:
142 return NVPTX::PTXLdStInstCode::CONSTANT;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000143 case llvm::ADDRESS_SPACE_GENERIC:
144 return NVPTX::PTXLdStInstCode::GENERIC;
145 case llvm::ADDRESS_SPACE_PARAM:
146 return NVPTX::PTXLdStInstCode::PARAM;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000147 case llvm::ADDRESS_SPACE_CONST:
148 // If the arch supports generic address space, translate it to GLOBAL
149 // for correctness.
150 // If the arch does not support generic address space, then the arch
151 // does not really support ADDRESS_SPACE_CONST, translate it to
152 // to CONSTANT for better performance.
153 if (Subtarget.hasGenericLdSt())
154 return NVPTX::PTXLdStInstCode::GLOBAL;
155 else
156 return NVPTX::PTXLdStInstCode::CONSTANT;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000157 default:
158 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000159 }
160 }
161 return NVPTX::PTXLdStInstCode::LOCAL;
162}
163
Justin Holewinski0497ab12013-03-30 14:29:21 +0000164SDNode *NVPTXDAGToDAGISel::SelectLoad(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000165 SDLoc dl(N);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000166 LoadSDNode *LD = cast<LoadSDNode>(N);
167 EVT LoadedVT = LD->getMemoryVT();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000168 SDNode *NVPTXLD = NULL;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000169
170 // do not support pre/post inc/dec
171 if (LD->isIndexed())
172 return NULL;
173
174 if (!LoadedVT.isSimple())
175 return NULL;
176
177 // Address Space Setting
178 unsigned int codeAddrSpace = getCodeAddrSpace(LD, Subtarget);
179
180 // Volatile Setting
181 // - .volatile is only availalble for .global and .shared
182 bool isVolatile = LD->isVolatile();
183 if (codeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
184 codeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
185 codeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
186 isVolatile = false;
187
188 // Vector Setting
189 MVT SimpleVT = LoadedVT.getSimpleVT();
190 unsigned vecType = NVPTX::PTXLdStInstCode::Scalar;
191 if (SimpleVT.isVector()) {
192 unsigned num = SimpleVT.getVectorNumElements();
193 if (num == 2)
194 vecType = NVPTX::PTXLdStInstCode::V2;
195 else if (num == 4)
196 vecType = NVPTX::PTXLdStInstCode::V4;
197 else
198 return NULL;
199 }
200
201 // Type Setting: fromType + fromTypeWidth
202 //
203 // Sign : ISD::SEXTLOAD
204 // Unsign : ISD::ZEXTLOAD, ISD::NON_EXTLOAD or ISD::EXTLOAD and the
205 // type is integer
206 // Float : ISD::NON_EXTLOAD or ISD::EXTLOAD and the type is float
207 MVT ScalarVT = SimpleVT.getScalarType();
Justin Holewinski994d66a2013-05-30 12:22:39 +0000208 // Read at least 8 bits (predicates are stored as 8-bit values)
209 unsigned fromTypeWidth = std::max(8U, ScalarVT.getSizeInBits());
Justin Holewinskiae556d32012-05-04 20:18:50 +0000210 unsigned int fromType;
211 if ((LD->getExtensionType() == ISD::SEXTLOAD))
212 fromType = NVPTX::PTXLdStInstCode::Signed;
213 else if (ScalarVT.isFloatingPoint())
214 fromType = NVPTX::PTXLdStInstCode::Float;
215 else
216 fromType = NVPTX::PTXLdStInstCode::Unsigned;
217
218 // Create the machine instruction DAG
219 SDValue Chain = N->getOperand(0);
220 SDValue N1 = N->getOperand(1);
221 SDValue Addr;
222 SDValue Offset, Base;
223 unsigned Opcode;
224 MVT::SimpleValueType TargetVT = LD->getValueType(0).getSimpleVT().SimpleTy;
225
226 if (SelectDirectAddr(N1, Addr)) {
227 switch (TargetVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000228 case MVT::i8:
229 Opcode = NVPTX::LD_i8_avar;
230 break;
231 case MVT::i16:
232 Opcode = NVPTX::LD_i16_avar;
233 break;
234 case MVT::i32:
235 Opcode = NVPTX::LD_i32_avar;
236 break;
237 case MVT::i64:
238 Opcode = NVPTX::LD_i64_avar;
239 break;
240 case MVT::f32:
241 Opcode = NVPTX::LD_f32_avar;
242 break;
243 case MVT::f64:
244 Opcode = NVPTX::LD_f64_avar;
245 break;
246 default:
247 return NULL;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000248 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000249 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
250 getI32Imm(vecType), getI32Imm(fromType),
251 getI32Imm(fromTypeWidth), Addr, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000252 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000253 } else if (Subtarget.is64Bit()
254 ? SelectADDRsi64(N1.getNode(), N1, Base, Offset)
255 : SelectADDRsi(N1.getNode(), N1, Base, Offset)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000256 switch (TargetVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000257 case MVT::i8:
258 Opcode = NVPTX::LD_i8_asi;
259 break;
260 case MVT::i16:
261 Opcode = NVPTX::LD_i16_asi;
262 break;
263 case MVT::i32:
264 Opcode = NVPTX::LD_i32_asi;
265 break;
266 case MVT::i64:
267 Opcode = NVPTX::LD_i64_asi;
268 break;
269 case MVT::f32:
270 Opcode = NVPTX::LD_f32_asi;
271 break;
272 case MVT::f64:
273 Opcode = NVPTX::LD_f64_asi;
274 break;
275 default:
276 return NULL;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000277 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000278 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
279 getI32Imm(vecType), getI32Imm(fromType),
280 getI32Imm(fromTypeWidth), Base, Offset, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000281 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000282 } else if (Subtarget.is64Bit()
283 ? SelectADDRri64(N1.getNode(), N1, Base, Offset)
284 : SelectADDRri(N1.getNode(), N1, Base, Offset)) {
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000285 if (Subtarget.is64Bit()) {
286 switch (TargetVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000287 case MVT::i8:
288 Opcode = NVPTX::LD_i8_ari_64;
289 break;
290 case MVT::i16:
291 Opcode = NVPTX::LD_i16_ari_64;
292 break;
293 case MVT::i32:
294 Opcode = NVPTX::LD_i32_ari_64;
295 break;
296 case MVT::i64:
297 Opcode = NVPTX::LD_i64_ari_64;
298 break;
299 case MVT::f32:
300 Opcode = NVPTX::LD_f32_ari_64;
301 break;
302 case MVT::f64:
303 Opcode = NVPTX::LD_f64_ari_64;
304 break;
305 default:
306 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000307 }
308 } else {
309 switch (TargetVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000310 case MVT::i8:
311 Opcode = NVPTX::LD_i8_ari;
312 break;
313 case MVT::i16:
314 Opcode = NVPTX::LD_i16_ari;
315 break;
316 case MVT::i32:
317 Opcode = NVPTX::LD_i32_ari;
318 break;
319 case MVT::i64:
320 Opcode = NVPTX::LD_i64_ari;
321 break;
322 case MVT::f32:
323 Opcode = NVPTX::LD_f32_ari;
324 break;
325 case MVT::f64:
326 Opcode = NVPTX::LD_f64_ari;
327 break;
328 default:
329 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000330 }
Justin Holewinskiae556d32012-05-04 20:18:50 +0000331 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000332 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
333 getI32Imm(vecType), getI32Imm(fromType),
334 getI32Imm(fromTypeWidth), Base, Offset, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000335 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000336 } else {
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000337 if (Subtarget.is64Bit()) {
338 switch (TargetVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000339 case MVT::i8:
340 Opcode = NVPTX::LD_i8_areg_64;
341 break;
342 case MVT::i16:
343 Opcode = NVPTX::LD_i16_areg_64;
344 break;
345 case MVT::i32:
346 Opcode = NVPTX::LD_i32_areg_64;
347 break;
348 case MVT::i64:
349 Opcode = NVPTX::LD_i64_areg_64;
350 break;
351 case MVT::f32:
352 Opcode = NVPTX::LD_f32_areg_64;
353 break;
354 case MVT::f64:
355 Opcode = NVPTX::LD_f64_areg_64;
356 break;
357 default:
358 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000359 }
360 } else {
361 switch (TargetVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000362 case MVT::i8:
363 Opcode = NVPTX::LD_i8_areg;
364 break;
365 case MVT::i16:
366 Opcode = NVPTX::LD_i16_areg;
367 break;
368 case MVT::i32:
369 Opcode = NVPTX::LD_i32_areg;
370 break;
371 case MVT::i64:
372 Opcode = NVPTX::LD_i64_areg;
373 break;
374 case MVT::f32:
375 Opcode = NVPTX::LD_f32_areg;
376 break;
377 case MVT::f64:
378 Opcode = NVPTX::LD_f64_areg;
379 break;
380 default:
381 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000382 }
Justin Holewinskiae556d32012-05-04 20:18:50 +0000383 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000384 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
385 getI32Imm(vecType), getI32Imm(fromType),
386 getI32Imm(fromTypeWidth), N1, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000387 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000388 }
389
390 if (NVPTXLD != NULL) {
391 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
392 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
393 cast<MachineSDNode>(NVPTXLD)->setMemRefs(MemRefs0, MemRefs0 + 1);
394 }
395
396 return NVPTXLD;
397}
398
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000399SDNode *NVPTXDAGToDAGISel::SelectLoadVector(SDNode *N) {
400
401 SDValue Chain = N->getOperand(0);
402 SDValue Op1 = N->getOperand(1);
403 SDValue Addr, Offset, Base;
404 unsigned Opcode;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000405 SDLoc DL(N);
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000406 SDNode *LD;
407 MemSDNode *MemSD = cast<MemSDNode>(N);
408 EVT LoadedVT = MemSD->getMemoryVT();
409
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000410 if (!LoadedVT.isSimple())
Justin Holewinski0497ab12013-03-30 14:29:21 +0000411 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000412
413 // Address Space Setting
414 unsigned int CodeAddrSpace = getCodeAddrSpace(MemSD, Subtarget);
415
416 // Volatile Setting
417 // - .volatile is only availalble for .global and .shared
418 bool IsVolatile = MemSD->isVolatile();
419 if (CodeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
420 CodeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
421 CodeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
422 IsVolatile = false;
423
424 // Vector Setting
425 MVT SimpleVT = LoadedVT.getSimpleVT();
426
427 // Type Setting: fromType + fromTypeWidth
428 //
429 // Sign : ISD::SEXTLOAD
430 // Unsign : ISD::ZEXTLOAD, ISD::NON_EXTLOAD or ISD::EXTLOAD and the
431 // type is integer
432 // Float : ISD::NON_EXTLOAD or ISD::EXTLOAD and the type is float
433 MVT ScalarVT = SimpleVT.getScalarType();
Justin Holewinski994d66a2013-05-30 12:22:39 +0000434 // Read at least 8 bits (predicates are stored as 8-bit values)
435 unsigned FromTypeWidth = std::max(8U, ScalarVT.getSizeInBits());
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000436 unsigned int FromType;
437 // The last operand holds the original LoadSDNode::getExtensionType() value
Justin Holewinski0497ab12013-03-30 14:29:21 +0000438 unsigned ExtensionType = cast<ConstantSDNode>(
439 N->getOperand(N->getNumOperands() - 1))->getZExtValue();
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000440 if (ExtensionType == ISD::SEXTLOAD)
441 FromType = NVPTX::PTXLdStInstCode::Signed;
442 else if (ScalarVT.isFloatingPoint())
443 FromType = NVPTX::PTXLdStInstCode::Float;
444 else
445 FromType = NVPTX::PTXLdStInstCode::Unsigned;
446
447 unsigned VecType;
448
449 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000450 case NVPTXISD::LoadV2:
451 VecType = NVPTX::PTXLdStInstCode::V2;
452 break;
453 case NVPTXISD::LoadV4:
454 VecType = NVPTX::PTXLdStInstCode::V4;
455 break;
456 default:
457 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000458 }
459
460 EVT EltVT = N->getValueType(0);
461
462 if (SelectDirectAddr(Op1, Addr)) {
463 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000464 default:
465 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000466 case NVPTXISD::LoadV2:
467 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000468 default:
469 return NULL;
470 case MVT::i8:
471 Opcode = NVPTX::LDV_i8_v2_avar;
472 break;
473 case MVT::i16:
474 Opcode = NVPTX::LDV_i16_v2_avar;
475 break;
476 case MVT::i32:
477 Opcode = NVPTX::LDV_i32_v2_avar;
478 break;
479 case MVT::i64:
480 Opcode = NVPTX::LDV_i64_v2_avar;
481 break;
482 case MVT::f32:
483 Opcode = NVPTX::LDV_f32_v2_avar;
484 break;
485 case MVT::f64:
486 Opcode = NVPTX::LDV_f64_v2_avar;
487 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000488 }
489 break;
490 case NVPTXISD::LoadV4:
491 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000492 default:
493 return NULL;
494 case MVT::i8:
495 Opcode = NVPTX::LDV_i8_v4_avar;
496 break;
497 case MVT::i16:
498 Opcode = NVPTX::LDV_i16_v4_avar;
499 break;
500 case MVT::i32:
501 Opcode = NVPTX::LDV_i32_v4_avar;
502 break;
503 case MVT::f32:
504 Opcode = NVPTX::LDV_f32_v4_avar;
505 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000506 }
507 break;
508 }
509
Justin Holewinski0497ab12013-03-30 14:29:21 +0000510 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
511 getI32Imm(VecType), getI32Imm(FromType),
512 getI32Imm(FromTypeWidth), Addr, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000513 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000514 } else if (Subtarget.is64Bit()
515 ? SelectADDRsi64(Op1.getNode(), Op1, Base, Offset)
516 : SelectADDRsi(Op1.getNode(), Op1, Base, Offset)) {
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000517 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000518 default:
519 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000520 case NVPTXISD::LoadV2:
521 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000522 default:
523 return NULL;
524 case MVT::i8:
525 Opcode = NVPTX::LDV_i8_v2_asi;
526 break;
527 case MVT::i16:
528 Opcode = NVPTX::LDV_i16_v2_asi;
529 break;
530 case MVT::i32:
531 Opcode = NVPTX::LDV_i32_v2_asi;
532 break;
533 case MVT::i64:
534 Opcode = NVPTX::LDV_i64_v2_asi;
535 break;
536 case MVT::f32:
537 Opcode = NVPTX::LDV_f32_v2_asi;
538 break;
539 case MVT::f64:
540 Opcode = NVPTX::LDV_f64_v2_asi;
541 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000542 }
543 break;
544 case NVPTXISD::LoadV4:
545 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000546 default:
547 return NULL;
548 case MVT::i8:
549 Opcode = NVPTX::LDV_i8_v4_asi;
550 break;
551 case MVT::i16:
552 Opcode = NVPTX::LDV_i16_v4_asi;
553 break;
554 case MVT::i32:
555 Opcode = NVPTX::LDV_i32_v4_asi;
556 break;
557 case MVT::f32:
558 Opcode = NVPTX::LDV_f32_v4_asi;
559 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000560 }
561 break;
562 }
563
Justin Holewinski0497ab12013-03-30 14:29:21 +0000564 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
565 getI32Imm(VecType), getI32Imm(FromType),
566 getI32Imm(FromTypeWidth), Base, Offset, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000567 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000568 } else if (Subtarget.is64Bit()
569 ? SelectADDRri64(Op1.getNode(), Op1, Base, Offset)
570 : SelectADDRri(Op1.getNode(), Op1, Base, Offset)) {
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000571 if (Subtarget.is64Bit()) {
572 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000573 default:
574 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000575 case NVPTXISD::LoadV2:
576 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000577 default:
578 return NULL;
579 case MVT::i8:
580 Opcode = NVPTX::LDV_i8_v2_ari_64;
581 break;
582 case MVT::i16:
583 Opcode = NVPTX::LDV_i16_v2_ari_64;
584 break;
585 case MVT::i32:
586 Opcode = NVPTX::LDV_i32_v2_ari_64;
587 break;
588 case MVT::i64:
589 Opcode = NVPTX::LDV_i64_v2_ari_64;
590 break;
591 case MVT::f32:
592 Opcode = NVPTX::LDV_f32_v2_ari_64;
593 break;
594 case MVT::f64:
595 Opcode = NVPTX::LDV_f64_v2_ari_64;
596 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000597 }
598 break;
599 case NVPTXISD::LoadV4:
600 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000601 default:
602 return NULL;
603 case MVT::i8:
604 Opcode = NVPTX::LDV_i8_v4_ari_64;
605 break;
606 case MVT::i16:
607 Opcode = NVPTX::LDV_i16_v4_ari_64;
608 break;
609 case MVT::i32:
610 Opcode = NVPTX::LDV_i32_v4_ari_64;
611 break;
612 case MVT::f32:
613 Opcode = NVPTX::LDV_f32_v4_ari_64;
614 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000615 }
616 break;
617 }
618 } else {
619 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000620 default:
621 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000622 case NVPTXISD::LoadV2:
623 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000624 default:
625 return NULL;
626 case MVT::i8:
627 Opcode = NVPTX::LDV_i8_v2_ari;
628 break;
629 case MVT::i16:
630 Opcode = NVPTX::LDV_i16_v2_ari;
631 break;
632 case MVT::i32:
633 Opcode = NVPTX::LDV_i32_v2_ari;
634 break;
635 case MVT::i64:
636 Opcode = NVPTX::LDV_i64_v2_ari;
637 break;
638 case MVT::f32:
639 Opcode = NVPTX::LDV_f32_v2_ari;
640 break;
641 case MVT::f64:
642 Opcode = NVPTX::LDV_f64_v2_ari;
643 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000644 }
645 break;
646 case NVPTXISD::LoadV4:
647 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000648 default:
649 return NULL;
650 case MVT::i8:
651 Opcode = NVPTX::LDV_i8_v4_ari;
652 break;
653 case MVT::i16:
654 Opcode = NVPTX::LDV_i16_v4_ari;
655 break;
656 case MVT::i32:
657 Opcode = NVPTX::LDV_i32_v4_ari;
658 break;
659 case MVT::f32:
660 Opcode = NVPTX::LDV_f32_v4_ari;
661 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000662 }
663 break;
664 }
665 }
666
Justin Holewinski0497ab12013-03-30 14:29:21 +0000667 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
668 getI32Imm(VecType), getI32Imm(FromType),
669 getI32Imm(FromTypeWidth), Base, Offset, Chain };
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000670
Michael Liaob53d8962013-04-19 22:22:57 +0000671 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops);
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000672 } else {
673 if (Subtarget.is64Bit()) {
674 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000675 default:
676 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000677 case NVPTXISD::LoadV2:
678 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000679 default:
680 return NULL;
681 case MVT::i8:
682 Opcode = NVPTX::LDV_i8_v2_areg_64;
683 break;
684 case MVT::i16:
685 Opcode = NVPTX::LDV_i16_v2_areg_64;
686 break;
687 case MVT::i32:
688 Opcode = NVPTX::LDV_i32_v2_areg_64;
689 break;
690 case MVT::i64:
691 Opcode = NVPTX::LDV_i64_v2_areg_64;
692 break;
693 case MVT::f32:
694 Opcode = NVPTX::LDV_f32_v2_areg_64;
695 break;
696 case MVT::f64:
697 Opcode = NVPTX::LDV_f64_v2_areg_64;
698 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000699 }
700 break;
701 case NVPTXISD::LoadV4:
702 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000703 default:
704 return NULL;
705 case MVT::i8:
706 Opcode = NVPTX::LDV_i8_v4_areg_64;
707 break;
708 case MVT::i16:
709 Opcode = NVPTX::LDV_i16_v4_areg_64;
710 break;
711 case MVT::i32:
712 Opcode = NVPTX::LDV_i32_v4_areg_64;
713 break;
714 case MVT::f32:
715 Opcode = NVPTX::LDV_f32_v4_areg_64;
716 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000717 }
718 break;
719 }
720 } else {
721 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000722 default:
723 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000724 case NVPTXISD::LoadV2:
725 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000726 default:
727 return NULL;
728 case MVT::i8:
729 Opcode = NVPTX::LDV_i8_v2_areg;
730 break;
731 case MVT::i16:
732 Opcode = NVPTX::LDV_i16_v2_areg;
733 break;
734 case MVT::i32:
735 Opcode = NVPTX::LDV_i32_v2_areg;
736 break;
737 case MVT::i64:
738 Opcode = NVPTX::LDV_i64_v2_areg;
739 break;
740 case MVT::f32:
741 Opcode = NVPTX::LDV_f32_v2_areg;
742 break;
743 case MVT::f64:
744 Opcode = NVPTX::LDV_f64_v2_areg;
745 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000746 }
747 break;
748 case NVPTXISD::LoadV4:
749 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000750 default:
751 return NULL;
752 case MVT::i8:
753 Opcode = NVPTX::LDV_i8_v4_areg;
754 break;
755 case MVT::i16:
756 Opcode = NVPTX::LDV_i16_v4_areg;
757 break;
758 case MVT::i32:
759 Opcode = NVPTX::LDV_i32_v4_areg;
760 break;
761 case MVT::f32:
762 Opcode = NVPTX::LDV_f32_v4_areg;
763 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000764 }
765 break;
766 }
767 }
768
Justin Holewinski0497ab12013-03-30 14:29:21 +0000769 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
770 getI32Imm(VecType), getI32Imm(FromType),
771 getI32Imm(FromTypeWidth), Op1, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000772 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops);
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000773 }
774
775 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
776 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
777 cast<MachineSDNode>(LD)->setMemRefs(MemRefs0, MemRefs0 + 1);
778
779 return LD;
780}
781
782SDNode *NVPTXDAGToDAGISel::SelectLDGLDUVector(SDNode *N) {
783
784 SDValue Chain = N->getOperand(0);
785 SDValue Op1 = N->getOperand(1);
786 unsigned Opcode;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000787 SDLoc DL(N);
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000788 SDNode *LD;
789
790 EVT RetVT = N->getValueType(0);
791
792 // Select opcode
793 if (Subtarget.is64Bit()) {
794 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000795 default:
796 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000797 case NVPTXISD::LDGV2:
798 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000799 default:
800 return NULL;
801 case MVT::i8:
802 Opcode = NVPTX::INT_PTX_LDG_G_v2i8_ELE_64;
803 break;
804 case MVT::i16:
805 Opcode = NVPTX::INT_PTX_LDG_G_v2i16_ELE_64;
806 break;
807 case MVT::i32:
808 Opcode = NVPTX::INT_PTX_LDG_G_v2i32_ELE_64;
809 break;
810 case MVT::i64:
811 Opcode = NVPTX::INT_PTX_LDG_G_v2i64_ELE_64;
812 break;
813 case MVT::f32:
814 Opcode = NVPTX::INT_PTX_LDG_G_v2f32_ELE_64;
815 break;
816 case MVT::f64:
817 Opcode = NVPTX::INT_PTX_LDG_G_v2f64_ELE_64;
818 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000819 }
820 break;
821 case NVPTXISD::LDGV4:
822 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000823 default:
824 return NULL;
825 case MVT::i8:
826 Opcode = NVPTX::INT_PTX_LDG_G_v4i8_ELE_64;
827 break;
828 case MVT::i16:
829 Opcode = NVPTX::INT_PTX_LDG_G_v4i16_ELE_64;
830 break;
831 case MVT::i32:
832 Opcode = NVPTX::INT_PTX_LDG_G_v4i32_ELE_64;
833 break;
834 case MVT::f32:
835 Opcode = NVPTX::INT_PTX_LDG_G_v4f32_ELE_64;
836 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000837 }
838 break;
839 case NVPTXISD::LDUV2:
840 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000841 default:
842 return NULL;
843 case MVT::i8:
844 Opcode = NVPTX::INT_PTX_LDU_G_v2i8_ELE_64;
845 break;
846 case MVT::i16:
847 Opcode = NVPTX::INT_PTX_LDU_G_v2i16_ELE_64;
848 break;
849 case MVT::i32:
850 Opcode = NVPTX::INT_PTX_LDU_G_v2i32_ELE_64;
851 break;
852 case MVT::i64:
853 Opcode = NVPTX::INT_PTX_LDU_G_v2i64_ELE_64;
854 break;
855 case MVT::f32:
856 Opcode = NVPTX::INT_PTX_LDU_G_v2f32_ELE_64;
857 break;
858 case MVT::f64:
859 Opcode = NVPTX::INT_PTX_LDU_G_v2f64_ELE_64;
860 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000861 }
862 break;
863 case NVPTXISD::LDUV4:
864 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000865 default:
866 return NULL;
867 case MVT::i8:
868 Opcode = NVPTX::INT_PTX_LDU_G_v4i8_ELE_64;
869 break;
870 case MVT::i16:
871 Opcode = NVPTX::INT_PTX_LDU_G_v4i16_ELE_64;
872 break;
873 case MVT::i32:
874 Opcode = NVPTX::INT_PTX_LDU_G_v4i32_ELE_64;
875 break;
876 case MVT::f32:
877 Opcode = NVPTX::INT_PTX_LDU_G_v4f32_ELE_64;
878 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000879 }
880 break;
881 }
882 } else {
883 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000884 default:
885 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000886 case NVPTXISD::LDGV2:
887 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000888 default:
889 return NULL;
890 case MVT::i8:
891 Opcode = NVPTX::INT_PTX_LDG_G_v2i8_ELE_32;
892 break;
893 case MVT::i16:
894 Opcode = NVPTX::INT_PTX_LDG_G_v2i16_ELE_32;
895 break;
896 case MVT::i32:
897 Opcode = NVPTX::INT_PTX_LDG_G_v2i32_ELE_32;
898 break;
899 case MVT::i64:
900 Opcode = NVPTX::INT_PTX_LDG_G_v2i64_ELE_32;
901 break;
902 case MVT::f32:
903 Opcode = NVPTX::INT_PTX_LDG_G_v2f32_ELE_32;
904 break;
905 case MVT::f64:
906 Opcode = NVPTX::INT_PTX_LDG_G_v2f64_ELE_32;
907 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000908 }
909 break;
910 case NVPTXISD::LDGV4:
911 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000912 default:
913 return NULL;
914 case MVT::i8:
915 Opcode = NVPTX::INT_PTX_LDG_G_v4i8_ELE_32;
916 break;
917 case MVT::i16:
918 Opcode = NVPTX::INT_PTX_LDG_G_v4i16_ELE_32;
919 break;
920 case MVT::i32:
921 Opcode = NVPTX::INT_PTX_LDG_G_v4i32_ELE_32;
922 break;
923 case MVT::f32:
924 Opcode = NVPTX::INT_PTX_LDG_G_v4f32_ELE_32;
925 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000926 }
927 break;
928 case NVPTXISD::LDUV2:
929 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000930 default:
931 return NULL;
932 case MVT::i8:
933 Opcode = NVPTX::INT_PTX_LDU_G_v2i8_ELE_32;
934 break;
935 case MVT::i16:
936 Opcode = NVPTX::INT_PTX_LDU_G_v2i16_ELE_32;
937 break;
938 case MVT::i32:
939 Opcode = NVPTX::INT_PTX_LDU_G_v2i32_ELE_32;
940 break;
941 case MVT::i64:
942 Opcode = NVPTX::INT_PTX_LDU_G_v2i64_ELE_32;
943 break;
944 case MVT::f32:
945 Opcode = NVPTX::INT_PTX_LDU_G_v2f32_ELE_32;
946 break;
947 case MVT::f64:
948 Opcode = NVPTX::INT_PTX_LDU_G_v2f64_ELE_32;
949 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000950 }
951 break;
952 case NVPTXISD::LDUV4:
953 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000954 default:
955 return NULL;
956 case MVT::i8:
957 Opcode = NVPTX::INT_PTX_LDU_G_v4i8_ELE_32;
958 break;
959 case MVT::i16:
960 Opcode = NVPTX::INT_PTX_LDU_G_v4i16_ELE_32;
961 break;
962 case MVT::i32:
963 Opcode = NVPTX::INT_PTX_LDU_G_v4i32_ELE_32;
964 break;
965 case MVT::f32:
966 Opcode = NVPTX::INT_PTX_LDU_G_v4f32_ELE_32;
967 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000968 }
969 break;
970 }
971 }
972
973 SDValue Ops[] = { Op1, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +0000974 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops);
Justin Holewinskibe8dc642013-02-12 14:18:49 +0000975
976 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
977 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
978 cast<MachineSDNode>(LD)->setMemRefs(MemRefs0, MemRefs0 + 1);
979
980 return LD;
981}
982
Justin Holewinski0497ab12013-03-30 14:29:21 +0000983SDNode *NVPTXDAGToDAGISel::SelectStore(SDNode *N) {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000984 SDLoc dl(N);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000985 StoreSDNode *ST = cast<StoreSDNode>(N);
986 EVT StoreVT = ST->getMemoryVT();
987 SDNode *NVPTXST = NULL;
988
989 // do not support pre/post inc/dec
990 if (ST->isIndexed())
991 return NULL;
992
993 if (!StoreVT.isSimple())
994 return NULL;
995
996 // Address Space Setting
997 unsigned int codeAddrSpace = getCodeAddrSpace(ST, Subtarget);
998
999 // Volatile Setting
1000 // - .volatile is only availalble for .global and .shared
1001 bool isVolatile = ST->isVolatile();
1002 if (codeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
1003 codeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
1004 codeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
1005 isVolatile = false;
1006
1007 // Vector Setting
1008 MVT SimpleVT = StoreVT.getSimpleVT();
1009 unsigned vecType = NVPTX::PTXLdStInstCode::Scalar;
1010 if (SimpleVT.isVector()) {
1011 unsigned num = SimpleVT.getVectorNumElements();
1012 if (num == 2)
1013 vecType = NVPTX::PTXLdStInstCode::V2;
1014 else if (num == 4)
1015 vecType = NVPTX::PTXLdStInstCode::V4;
1016 else
1017 return NULL;
1018 }
1019
1020 // Type Setting: toType + toTypeWidth
1021 // - for integer type, always use 'u'
1022 //
1023 MVT ScalarVT = SimpleVT.getScalarType();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001024 unsigned toTypeWidth = ScalarVT.getSizeInBits();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001025 unsigned int toType;
1026 if (ScalarVT.isFloatingPoint())
1027 toType = NVPTX::PTXLdStInstCode::Float;
1028 else
1029 toType = NVPTX::PTXLdStInstCode::Unsigned;
1030
1031 // Create the machine instruction DAG
1032 SDValue Chain = N->getOperand(0);
1033 SDValue N1 = N->getOperand(1);
1034 SDValue N2 = N->getOperand(2);
1035 SDValue Addr;
1036 SDValue Offset, Base;
1037 unsigned Opcode;
1038 MVT::SimpleValueType SourceVT =
1039 N1.getNode()->getValueType(0).getSimpleVT().SimpleTy;
1040
1041 if (SelectDirectAddr(N2, Addr)) {
1042 switch (SourceVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001043 case MVT::i8:
1044 Opcode = NVPTX::ST_i8_avar;
1045 break;
1046 case MVT::i16:
1047 Opcode = NVPTX::ST_i16_avar;
1048 break;
1049 case MVT::i32:
1050 Opcode = NVPTX::ST_i32_avar;
1051 break;
1052 case MVT::i64:
1053 Opcode = NVPTX::ST_i64_avar;
1054 break;
1055 case MVT::f32:
1056 Opcode = NVPTX::ST_f32_avar;
1057 break;
1058 case MVT::f64:
1059 Opcode = NVPTX::ST_f64_avar;
1060 break;
1061 default:
1062 return NULL;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001063 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001064 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1065 getI32Imm(vecType), getI32Imm(toType),
1066 getI32Imm(toTypeWidth), Addr, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +00001067 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001068 } else if (Subtarget.is64Bit()
1069 ? SelectADDRsi64(N2.getNode(), N2, Base, Offset)
1070 : SelectADDRsi(N2.getNode(), N2, Base, Offset)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001071 switch (SourceVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001072 case MVT::i8:
1073 Opcode = NVPTX::ST_i8_asi;
1074 break;
1075 case MVT::i16:
1076 Opcode = NVPTX::ST_i16_asi;
1077 break;
1078 case MVT::i32:
1079 Opcode = NVPTX::ST_i32_asi;
1080 break;
1081 case MVT::i64:
1082 Opcode = NVPTX::ST_i64_asi;
1083 break;
1084 case MVT::f32:
1085 Opcode = NVPTX::ST_f32_asi;
1086 break;
1087 case MVT::f64:
1088 Opcode = NVPTX::ST_f64_asi;
1089 break;
1090 default:
1091 return NULL;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001092 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001093 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1094 getI32Imm(vecType), getI32Imm(toType),
1095 getI32Imm(toTypeWidth), Base, Offset, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +00001096 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001097 } else if (Subtarget.is64Bit()
1098 ? SelectADDRri64(N2.getNode(), N2, Base, Offset)
1099 : SelectADDRri(N2.getNode(), N2, Base, Offset)) {
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001100 if (Subtarget.is64Bit()) {
1101 switch (SourceVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001102 case MVT::i8:
1103 Opcode = NVPTX::ST_i8_ari_64;
1104 break;
1105 case MVT::i16:
1106 Opcode = NVPTX::ST_i16_ari_64;
1107 break;
1108 case MVT::i32:
1109 Opcode = NVPTX::ST_i32_ari_64;
1110 break;
1111 case MVT::i64:
1112 Opcode = NVPTX::ST_i64_ari_64;
1113 break;
1114 case MVT::f32:
1115 Opcode = NVPTX::ST_f32_ari_64;
1116 break;
1117 case MVT::f64:
1118 Opcode = NVPTX::ST_f64_ari_64;
1119 break;
1120 default:
1121 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001122 }
1123 } else {
1124 switch (SourceVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001125 case MVT::i8:
1126 Opcode = NVPTX::ST_i8_ari;
1127 break;
1128 case MVT::i16:
1129 Opcode = NVPTX::ST_i16_ari;
1130 break;
1131 case MVT::i32:
1132 Opcode = NVPTX::ST_i32_ari;
1133 break;
1134 case MVT::i64:
1135 Opcode = NVPTX::ST_i64_ari;
1136 break;
1137 case MVT::f32:
1138 Opcode = NVPTX::ST_f32_ari;
1139 break;
1140 case MVT::f64:
1141 Opcode = NVPTX::ST_f64_ari;
1142 break;
1143 default:
1144 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001145 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001146 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001147 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1148 getI32Imm(vecType), getI32Imm(toType),
1149 getI32Imm(toTypeWidth), Base, Offset, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +00001150 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001151 } else {
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001152 if (Subtarget.is64Bit()) {
1153 switch (SourceVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001154 case MVT::i8:
1155 Opcode = NVPTX::ST_i8_areg_64;
1156 break;
1157 case MVT::i16:
1158 Opcode = NVPTX::ST_i16_areg_64;
1159 break;
1160 case MVT::i32:
1161 Opcode = NVPTX::ST_i32_areg_64;
1162 break;
1163 case MVT::i64:
1164 Opcode = NVPTX::ST_i64_areg_64;
1165 break;
1166 case MVT::f32:
1167 Opcode = NVPTX::ST_f32_areg_64;
1168 break;
1169 case MVT::f64:
1170 Opcode = NVPTX::ST_f64_areg_64;
1171 break;
1172 default:
1173 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001174 }
1175 } else {
1176 switch (SourceVT) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001177 case MVT::i8:
1178 Opcode = NVPTX::ST_i8_areg;
1179 break;
1180 case MVT::i16:
1181 Opcode = NVPTX::ST_i16_areg;
1182 break;
1183 case MVT::i32:
1184 Opcode = NVPTX::ST_i32_areg;
1185 break;
1186 case MVT::i64:
1187 Opcode = NVPTX::ST_i64_areg;
1188 break;
1189 case MVT::f32:
1190 Opcode = NVPTX::ST_f32_areg;
1191 break;
1192 case MVT::f64:
1193 Opcode = NVPTX::ST_f64_areg;
1194 break;
1195 default:
1196 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001197 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001198 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001199 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1200 getI32Imm(vecType), getI32Imm(toType),
1201 getI32Imm(toTypeWidth), N2, Chain };
Michael Liaob53d8962013-04-19 22:22:57 +00001202 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001203 }
1204
1205 if (NVPTXST != NULL) {
1206 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
1207 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
1208 cast<MachineSDNode>(NVPTXST)->setMemRefs(MemRefs0, MemRefs0 + 1);
1209 }
1210
1211 return NVPTXST;
1212}
1213
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001214SDNode *NVPTXDAGToDAGISel::SelectStoreVector(SDNode *N) {
1215 SDValue Chain = N->getOperand(0);
1216 SDValue Op1 = N->getOperand(1);
1217 SDValue Addr, Offset, Base;
1218 unsigned Opcode;
Andrew Trickef9de2a2013-05-25 02:42:55 +00001219 SDLoc DL(N);
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001220 SDNode *ST;
1221 EVT EltVT = Op1.getValueType();
1222 MemSDNode *MemSD = cast<MemSDNode>(N);
1223 EVT StoreVT = MemSD->getMemoryVT();
1224
1225 // Address Space Setting
1226 unsigned CodeAddrSpace = getCodeAddrSpace(MemSD, Subtarget);
1227
1228 if (CodeAddrSpace == NVPTX::PTXLdStInstCode::CONSTANT) {
1229 report_fatal_error("Cannot store to pointer that points to constant "
1230 "memory space");
1231 }
1232
1233 // Volatile Setting
1234 // - .volatile is only availalble for .global and .shared
1235 bool IsVolatile = MemSD->isVolatile();
1236 if (CodeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
1237 CodeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
1238 CodeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
1239 IsVolatile = false;
1240
1241 // Type Setting: toType + toTypeWidth
1242 // - for integer type, always use 'u'
1243 assert(StoreVT.isSimple() && "Store value is not simple");
1244 MVT ScalarVT = StoreVT.getSimpleVT().getScalarType();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001245 unsigned ToTypeWidth = ScalarVT.getSizeInBits();
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001246 unsigned ToType;
1247 if (ScalarVT.isFloatingPoint())
1248 ToType = NVPTX::PTXLdStInstCode::Float;
1249 else
1250 ToType = NVPTX::PTXLdStInstCode::Unsigned;
1251
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001252 SmallVector<SDValue, 12> StOps;
1253 SDValue N2;
1254 unsigned VecType;
1255
1256 switch (N->getOpcode()) {
1257 case NVPTXISD::StoreV2:
1258 VecType = NVPTX::PTXLdStInstCode::V2;
1259 StOps.push_back(N->getOperand(1));
1260 StOps.push_back(N->getOperand(2));
1261 N2 = N->getOperand(3);
1262 break;
1263 case NVPTXISD::StoreV4:
1264 VecType = NVPTX::PTXLdStInstCode::V4;
1265 StOps.push_back(N->getOperand(1));
1266 StOps.push_back(N->getOperand(2));
1267 StOps.push_back(N->getOperand(3));
1268 StOps.push_back(N->getOperand(4));
1269 N2 = N->getOperand(5);
1270 break;
Justin Holewinski0497ab12013-03-30 14:29:21 +00001271 default:
1272 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001273 }
1274
1275 StOps.push_back(getI32Imm(IsVolatile));
1276 StOps.push_back(getI32Imm(CodeAddrSpace));
1277 StOps.push_back(getI32Imm(VecType));
1278 StOps.push_back(getI32Imm(ToType));
1279 StOps.push_back(getI32Imm(ToTypeWidth));
1280
1281 if (SelectDirectAddr(N2, Addr)) {
1282 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001283 default:
1284 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001285 case NVPTXISD::StoreV2:
1286 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001287 default:
1288 return NULL;
1289 case MVT::i8:
1290 Opcode = NVPTX::STV_i8_v2_avar;
1291 break;
1292 case MVT::i16:
1293 Opcode = NVPTX::STV_i16_v2_avar;
1294 break;
1295 case MVT::i32:
1296 Opcode = NVPTX::STV_i32_v2_avar;
1297 break;
1298 case MVT::i64:
1299 Opcode = NVPTX::STV_i64_v2_avar;
1300 break;
1301 case MVT::f32:
1302 Opcode = NVPTX::STV_f32_v2_avar;
1303 break;
1304 case MVT::f64:
1305 Opcode = NVPTX::STV_f64_v2_avar;
1306 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001307 }
1308 break;
1309 case NVPTXISD::StoreV4:
1310 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001311 default:
1312 return NULL;
1313 case MVT::i8:
1314 Opcode = NVPTX::STV_i8_v4_avar;
1315 break;
1316 case MVT::i16:
1317 Opcode = NVPTX::STV_i16_v4_avar;
1318 break;
1319 case MVT::i32:
1320 Opcode = NVPTX::STV_i32_v4_avar;
1321 break;
1322 case MVT::f32:
1323 Opcode = NVPTX::STV_f32_v4_avar;
1324 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001325 }
1326 break;
1327 }
1328 StOps.push_back(Addr);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001329 } else if (Subtarget.is64Bit()
1330 ? SelectADDRsi64(N2.getNode(), N2, Base, Offset)
1331 : SelectADDRsi(N2.getNode(), N2, Base, Offset)) {
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001332 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001333 default:
1334 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001335 case NVPTXISD::StoreV2:
1336 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001337 default:
1338 return NULL;
1339 case MVT::i8:
1340 Opcode = NVPTX::STV_i8_v2_asi;
1341 break;
1342 case MVT::i16:
1343 Opcode = NVPTX::STV_i16_v2_asi;
1344 break;
1345 case MVT::i32:
1346 Opcode = NVPTX::STV_i32_v2_asi;
1347 break;
1348 case MVT::i64:
1349 Opcode = NVPTX::STV_i64_v2_asi;
1350 break;
1351 case MVT::f32:
1352 Opcode = NVPTX::STV_f32_v2_asi;
1353 break;
1354 case MVT::f64:
1355 Opcode = NVPTX::STV_f64_v2_asi;
1356 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001357 }
1358 break;
1359 case NVPTXISD::StoreV4:
1360 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001361 default:
1362 return NULL;
1363 case MVT::i8:
1364 Opcode = NVPTX::STV_i8_v4_asi;
1365 break;
1366 case MVT::i16:
1367 Opcode = NVPTX::STV_i16_v4_asi;
1368 break;
1369 case MVT::i32:
1370 Opcode = NVPTX::STV_i32_v4_asi;
1371 break;
1372 case MVT::f32:
1373 Opcode = NVPTX::STV_f32_v4_asi;
1374 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001375 }
1376 break;
1377 }
1378 StOps.push_back(Base);
1379 StOps.push_back(Offset);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001380 } else if (Subtarget.is64Bit()
1381 ? SelectADDRri64(N2.getNode(), N2, Base, Offset)
1382 : SelectADDRri(N2.getNode(), N2, Base, Offset)) {
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001383 if (Subtarget.is64Bit()) {
1384 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001385 default:
1386 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001387 case NVPTXISD::StoreV2:
1388 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001389 default:
1390 return NULL;
1391 case MVT::i8:
1392 Opcode = NVPTX::STV_i8_v2_ari_64;
1393 break;
1394 case MVT::i16:
1395 Opcode = NVPTX::STV_i16_v2_ari_64;
1396 break;
1397 case MVT::i32:
1398 Opcode = NVPTX::STV_i32_v2_ari_64;
1399 break;
1400 case MVT::i64:
1401 Opcode = NVPTX::STV_i64_v2_ari_64;
1402 break;
1403 case MVT::f32:
1404 Opcode = NVPTX::STV_f32_v2_ari_64;
1405 break;
1406 case MVT::f64:
1407 Opcode = NVPTX::STV_f64_v2_ari_64;
1408 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001409 }
1410 break;
1411 case NVPTXISD::StoreV4:
1412 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001413 default:
1414 return NULL;
1415 case MVT::i8:
1416 Opcode = NVPTX::STV_i8_v4_ari_64;
1417 break;
1418 case MVT::i16:
1419 Opcode = NVPTX::STV_i16_v4_ari_64;
1420 break;
1421 case MVT::i32:
1422 Opcode = NVPTX::STV_i32_v4_ari_64;
1423 break;
1424 case MVT::f32:
1425 Opcode = NVPTX::STV_f32_v4_ari_64;
1426 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001427 }
1428 break;
1429 }
1430 } else {
1431 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001432 default:
1433 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001434 case NVPTXISD::StoreV2:
1435 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001436 default:
1437 return NULL;
1438 case MVT::i8:
1439 Opcode = NVPTX::STV_i8_v2_ari;
1440 break;
1441 case MVT::i16:
1442 Opcode = NVPTX::STV_i16_v2_ari;
1443 break;
1444 case MVT::i32:
1445 Opcode = NVPTX::STV_i32_v2_ari;
1446 break;
1447 case MVT::i64:
1448 Opcode = NVPTX::STV_i64_v2_ari;
1449 break;
1450 case MVT::f32:
1451 Opcode = NVPTX::STV_f32_v2_ari;
1452 break;
1453 case MVT::f64:
1454 Opcode = NVPTX::STV_f64_v2_ari;
1455 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001456 }
1457 break;
1458 case NVPTXISD::StoreV4:
1459 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001460 default:
1461 return NULL;
1462 case MVT::i8:
1463 Opcode = NVPTX::STV_i8_v4_ari;
1464 break;
1465 case MVT::i16:
1466 Opcode = NVPTX::STV_i16_v4_ari;
1467 break;
1468 case MVT::i32:
1469 Opcode = NVPTX::STV_i32_v4_ari;
1470 break;
1471 case MVT::f32:
1472 Opcode = NVPTX::STV_f32_v4_ari;
1473 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001474 }
1475 break;
1476 }
1477 }
1478 StOps.push_back(Base);
1479 StOps.push_back(Offset);
1480 } else {
1481 if (Subtarget.is64Bit()) {
1482 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001483 default:
1484 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001485 case NVPTXISD::StoreV2:
1486 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001487 default:
1488 return NULL;
1489 case MVT::i8:
1490 Opcode = NVPTX::STV_i8_v2_areg_64;
1491 break;
1492 case MVT::i16:
1493 Opcode = NVPTX::STV_i16_v2_areg_64;
1494 break;
1495 case MVT::i32:
1496 Opcode = NVPTX::STV_i32_v2_areg_64;
1497 break;
1498 case MVT::i64:
1499 Opcode = NVPTX::STV_i64_v2_areg_64;
1500 break;
1501 case MVT::f32:
1502 Opcode = NVPTX::STV_f32_v2_areg_64;
1503 break;
1504 case MVT::f64:
1505 Opcode = NVPTX::STV_f64_v2_areg_64;
1506 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001507 }
1508 break;
1509 case NVPTXISD::StoreV4:
1510 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001511 default:
1512 return NULL;
1513 case MVT::i8:
1514 Opcode = NVPTX::STV_i8_v4_areg_64;
1515 break;
1516 case MVT::i16:
1517 Opcode = NVPTX::STV_i16_v4_areg_64;
1518 break;
1519 case MVT::i32:
1520 Opcode = NVPTX::STV_i32_v4_areg_64;
1521 break;
1522 case MVT::f32:
1523 Opcode = NVPTX::STV_f32_v4_areg_64;
1524 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001525 }
1526 break;
1527 }
1528 } else {
1529 switch (N->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001530 default:
1531 return NULL;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001532 case NVPTXISD::StoreV2:
1533 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001534 default:
1535 return NULL;
1536 case MVT::i8:
1537 Opcode = NVPTX::STV_i8_v2_areg;
1538 break;
1539 case MVT::i16:
1540 Opcode = NVPTX::STV_i16_v2_areg;
1541 break;
1542 case MVT::i32:
1543 Opcode = NVPTX::STV_i32_v2_areg;
1544 break;
1545 case MVT::i64:
1546 Opcode = NVPTX::STV_i64_v2_areg;
1547 break;
1548 case MVT::f32:
1549 Opcode = NVPTX::STV_f32_v2_areg;
1550 break;
1551 case MVT::f64:
1552 Opcode = NVPTX::STV_f64_v2_areg;
1553 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001554 }
1555 break;
1556 case NVPTXISD::StoreV4:
1557 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001558 default:
1559 return NULL;
1560 case MVT::i8:
1561 Opcode = NVPTX::STV_i8_v4_areg;
1562 break;
1563 case MVT::i16:
1564 Opcode = NVPTX::STV_i16_v4_areg;
1565 break;
1566 case MVT::i32:
1567 Opcode = NVPTX::STV_i32_v4_areg;
1568 break;
1569 case MVT::f32:
1570 Opcode = NVPTX::STV_f32_v4_areg;
1571 break;
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001572 }
1573 break;
1574 }
1575 }
1576 StOps.push_back(N2);
1577 }
1578
1579 StOps.push_back(Chain);
1580
Michael Liaob53d8962013-04-19 22:22:57 +00001581 ST = CurDAG->getMachineNode(Opcode, DL, MVT::Other, StOps);
Justin Holewinskibe8dc642013-02-12 14:18:49 +00001582
1583 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
1584 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
1585 cast<MachineSDNode>(ST)->setMemRefs(MemRefs0, MemRefs0 + 1);
1586
1587 return ST;
1588}
1589
Justin Holewinskiae556d32012-05-04 20:18:50 +00001590// SelectDirectAddr - Match a direct address for DAG.
1591// A direct address could be a globaladdress or externalsymbol.
1592bool NVPTXDAGToDAGISel::SelectDirectAddr(SDValue N, SDValue &Address) {
1593 // Return true if TGA or ES.
Justin Holewinski0497ab12013-03-30 14:29:21 +00001594 if (N.getOpcode() == ISD::TargetGlobalAddress ||
1595 N.getOpcode() == ISD::TargetExternalSymbol) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001596 Address = N;
1597 return true;
1598 }
1599 if (N.getOpcode() == NVPTXISD::Wrapper) {
1600 Address = N.getOperand(0);
1601 return true;
1602 }
1603 if (N.getOpcode() == ISD::INTRINSIC_WO_CHAIN) {
1604 unsigned IID = cast<ConstantSDNode>(N.getOperand(0))->getZExtValue();
1605 if (IID == Intrinsic::nvvm_ptr_gen_to_param)
1606 if (N.getOperand(1).getOpcode() == NVPTXISD::MoveParam)
1607 return (SelectDirectAddr(N.getOperand(1).getOperand(0), Address));
1608 }
1609 return false;
1610}
1611
1612// symbol+offset
Justin Holewinski0497ab12013-03-30 14:29:21 +00001613bool NVPTXDAGToDAGISel::SelectADDRsi_imp(
1614 SDNode *OpNode, SDValue Addr, SDValue &Base, SDValue &Offset, MVT mvt) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001615 if (Addr.getOpcode() == ISD::ADD) {
1616 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001617 SDValue base = Addr.getOperand(0);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001618 if (SelectDirectAddr(base, Base)) {
1619 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), mvt);
1620 return true;
1621 }
1622 }
1623 }
1624 return false;
1625}
1626
1627// symbol+offset
1628bool NVPTXDAGToDAGISel::SelectADDRsi(SDNode *OpNode, SDValue Addr,
1629 SDValue &Base, SDValue &Offset) {
1630 return SelectADDRsi_imp(OpNode, Addr, Base, Offset, MVT::i32);
1631}
1632
1633// symbol+offset
1634bool NVPTXDAGToDAGISel::SelectADDRsi64(SDNode *OpNode, SDValue Addr,
1635 SDValue &Base, SDValue &Offset) {
1636 return SelectADDRsi_imp(OpNode, Addr, Base, Offset, MVT::i64);
1637}
1638
1639// register+offset
Justin Holewinski0497ab12013-03-30 14:29:21 +00001640bool NVPTXDAGToDAGISel::SelectADDRri_imp(
1641 SDNode *OpNode, SDValue Addr, SDValue &Base, SDValue &Offset, MVT mvt) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001642 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1643 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), mvt);
1644 Offset = CurDAG->getTargetConstant(0, mvt);
1645 return true;
1646 }
1647 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1648 Addr.getOpcode() == ISD::TargetGlobalAddress)
Justin Holewinski0497ab12013-03-30 14:29:21 +00001649 return false; // direct calls.
Justin Holewinskiae556d32012-05-04 20:18:50 +00001650
1651 if (Addr.getOpcode() == ISD::ADD) {
1652 if (SelectDirectAddr(Addr.getOperand(0), Addr)) {
1653 return false;
1654 }
1655 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
1656 if (FrameIndexSDNode *FIN =
Justin Holewinski0497ab12013-03-30 14:29:21 +00001657 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001658 // Constant offset from frame ref.
1659 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), mvt);
1660 else
1661 Base = Addr.getOperand(0);
1662 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), mvt);
1663 return true;
1664 }
1665 }
1666 return false;
1667}
1668
1669// register+offset
1670bool NVPTXDAGToDAGISel::SelectADDRri(SDNode *OpNode, SDValue Addr,
1671 SDValue &Base, SDValue &Offset) {
1672 return SelectADDRri_imp(OpNode, Addr, Base, Offset, MVT::i32);
1673}
1674
1675// register+offset
1676bool NVPTXDAGToDAGISel::SelectADDRri64(SDNode *OpNode, SDValue Addr,
1677 SDValue &Base, SDValue &Offset) {
1678 return SelectADDRri_imp(OpNode, Addr, Base, Offset, MVT::i64);
1679}
1680
1681bool NVPTXDAGToDAGISel::ChkMemSDNodeAddressSpace(SDNode *N,
1682 unsigned int spN) const {
1683 const Value *Src = NULL;
1684 // Even though MemIntrinsicSDNode is a subclas of MemSDNode,
1685 // the classof() for MemSDNode does not include MemIntrinsicSDNode
1686 // (See SelectionDAGNodes.h). So we need to check for both.
1687 if (MemSDNode *mN = dyn_cast<MemSDNode>(N)) {
1688 Src = mN->getSrcValue();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001689 } else if (MemSDNode *mN = dyn_cast<MemIntrinsicSDNode>(N)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001690 Src = mN->getSrcValue();
1691 }
1692 if (!Src)
1693 return false;
1694 if (const PointerType *PT = dyn_cast<PointerType>(Src->getType()))
1695 return (PT->getAddressSpace() == spN);
1696 return false;
1697}
1698
1699/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
1700/// inline asm expressions.
Justin Holewinski0497ab12013-03-30 14:29:21 +00001701bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
1702 const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001703 SDValue Op0, Op1;
1704 switch (ConstraintCode) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001705 default:
1706 return true;
1707 case 'm': // memory
Justin Holewinskiae556d32012-05-04 20:18:50 +00001708 if (SelectDirectAddr(Op, Op0)) {
1709 OutOps.push_back(Op0);
1710 OutOps.push_back(CurDAG->getTargetConstant(0, MVT::i32));
1711 return false;
1712 }
1713 if (SelectADDRri(Op.getNode(), Op, Op0, Op1)) {
1714 OutOps.push_back(Op0);
1715 OutOps.push_back(Op1);
1716 return false;
1717 }
1718 break;
1719 }
1720 return true;
1721}
1722
1723// Return true if N is a undef or a constant.
1724// If N was undef, return a (i8imm 0) in Retval
1725// If N was imm, convert it to i8imm and return in Retval
1726// Note: The convert to i8imm is required, otherwise the
1727// pattern matcher inserts a bunch of IMOVi8rr to convert
1728// the imm to i8imm, and this causes instruction selection
1729// to fail.
Justin Holewinski0497ab12013-03-30 14:29:21 +00001730bool NVPTXDAGToDAGISel::UndefOrImm(SDValue Op, SDValue N, SDValue &Retval) {
1731 if (!(N.getOpcode() == ISD::UNDEF) && !(N.getOpcode() == ISD::Constant))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001732 return false;
1733
1734 if (N.getOpcode() == ISD::UNDEF)
1735 Retval = CurDAG->getTargetConstant(0, MVT::i8);
1736 else {
1737 ConstantSDNode *cn = cast<ConstantSDNode>(N.getNode());
1738 unsigned retval = cn->getZExtValue();
1739 Retval = CurDAG->getTargetConstant(retval, MVT::i8);
1740 }
1741 return true;
1742}