blob: e862988c85d139594d8d5314b5983b3a633932ea [file] [log] [blame]
Justin Holewinski49683f32012-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 Holewinski49683f32012-05-04 20:18:50 +000014#include "NVPTXISelDAGToDAG.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000015#include "llvm/IR/GlobalValue.h"
16#include "llvm/IR/Instructions.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000017#include "llvm/Support/CommandLine.h"
Justin Holewinski49683f32012-05-04 20:18:50 +000018#include "llvm/Support/Debug.h"
19#include "llvm/Support/ErrorHandling.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000020#include "llvm/Support/raw_ostream.h"
Justin Holewinski49683f32012-05-04 20:18:50 +000021#include "llvm/Target/TargetIntrinsicInfo.h"
Justin Holewinski49683f32012-05-04 20:18:50 +000022
23#undef DEBUG_TYPE
24#define DEBUG_TYPE "nvptx-isel"
25
26using namespace llvm;
27
Justin Holewinski3639ce22013-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 Holewinski49683f32012-05-04 20:18:50 +000032
33static cl::opt<int>
Justin Holewinski3639ce22013-03-30 14:29:21 +000034FMAContractLevel("nvptx-fma-level", cl::ZeroOrMore,
Justin Holewinski49683f32012-05-04 20:18:50 +000035 cl::desc("NVPTX Specific: FMA contraction (0: don't do it"
Justin Holewinski3639ce22013-03-30 14:29:21 +000036 " 1: do it 2: do it aggressively"),
37 cl::init(2));
Justin Holewinski49683f32012-05-04 20:18:50 +000038
Justin Holewinski3639ce22013-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 Holewinski49683f32012-05-04 20:18:50 +000044
45/// createNVPTXISelDag - This pass converts a legalized DAG into a
46/// NVPTX-specific DAG, ready for instruction scheduling.
47FunctionPass *llvm::createNVPTXISelDag(NVPTXTargetMachine &TM,
48 llvm::CodeGenOpt::Level OptLevel) {
49 return new NVPTXDAGToDAGISel(TM, OptLevel);
50}
51
Justin Holewinski49683f32012-05-04 20:18:50 +000052NVPTXDAGToDAGISel::NVPTXDAGToDAGISel(NVPTXTargetMachine &tm,
53 CodeGenOpt::Level OptLevel)
Justin Holewinski3639ce22013-03-30 14:29:21 +000054 : SelectionDAGISel(tm, OptLevel),
55 Subtarget(tm.getSubtarget<NVPTXSubtarget>()) {
Justin Holewinski49683f32012-05-04 20:18:50 +000056 // Always do fma.f32 fpcontract if the target supports the instruction.
57 // Always do fma.f64 fpcontract if the target supports the instruction.
58 // Do mad.f32 is nvptx-mad-enable is specified and the target does not
59 // support fma.f32.
60
61 doFMADF32 = (OptLevel > 0) && UseFMADInstruction && !Subtarget.hasFMAF32();
Justin Holewinski3639ce22013-03-30 14:29:21 +000062 doFMAF32 = (OptLevel > 0) && Subtarget.hasFMAF32() && (FMAContractLevel >= 1);
63 doFMAF64 = (OptLevel > 0) && Subtarget.hasFMAF64() && (FMAContractLevel >= 1);
64 doFMAF32AGG =
65 (OptLevel > 0) && Subtarget.hasFMAF32() && (FMAContractLevel == 2);
66 doFMAF64AGG =
67 (OptLevel > 0) && Subtarget.hasFMAF64() && (FMAContractLevel == 2);
Justin Holewinski49683f32012-05-04 20:18:50 +000068
69 allowFMA = (FMAContractLevel >= 1) || UseFMADInstruction;
70
Benjamin Krameraf878312012-05-05 11:22:02 +000071 UseF32FTZ = false;
72
Justin Holewinski49683f32012-05-04 20:18:50 +000073 doMulWide = (OptLevel > 0);
74
75 // Decide how to translate f32 div
76 do_DIVF32_PREC = UsePrecDivF32;
77 // sm less than sm_20 does not support div.rnd. Use div.full.
78 if (do_DIVF32_PREC == 2 && !Subtarget.reqPTX20())
79 do_DIVF32_PREC = 1;
80
81}
82
83/// Select - Select instructions not customized! Used for
84/// expanded, promoted and normal instructions.
Justin Holewinski3639ce22013-03-30 14:29:21 +000085SDNode *NVPTXDAGToDAGISel::Select(SDNode *N) {
Justin Holewinski49683f32012-05-04 20:18:50 +000086
87 if (N->isMachineOpcode())
Justin Holewinski3639ce22013-03-30 14:29:21 +000088 return NULL; // Already selected.
Justin Holewinski49683f32012-05-04 20:18:50 +000089
90 SDNode *ResNode = NULL;
91 switch (N->getOpcode()) {
92 case ISD::LOAD:
93 ResNode = SelectLoad(N);
94 break;
95 case ISD::STORE:
96 ResNode = SelectStore(N);
97 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +000098 case NVPTXISD::LoadV2:
99 case NVPTXISD::LoadV4:
100 ResNode = SelectLoadVector(N);
101 break;
102 case NVPTXISD::LDGV2:
103 case NVPTXISD::LDGV4:
104 case NVPTXISD::LDUV2:
105 case NVPTXISD::LDUV4:
106 ResNode = SelectLDGLDUVector(N);
107 break;
108 case NVPTXISD::StoreV2:
109 case NVPTXISD::StoreV4:
110 ResNode = SelectStoreVector(N);
111 break;
Justin Holewinski3639ce22013-03-30 14:29:21 +0000112 default:
113 break;
Justin Holewinski49683f32012-05-04 20:18:50 +0000114 }
115 if (ResNode)
116 return ResNode;
117 return SelectCode(N);
118}
119
Justin Holewinski3639ce22013-03-30 14:29:21 +0000120static unsigned int getCodeAddrSpace(MemSDNode *N,
121 const NVPTXSubtarget &Subtarget) {
Justin Holewinski49683f32012-05-04 20:18:50 +0000122 const Value *Src = N->getSrcValue();
123 if (!Src)
124 return NVPTX::PTXLdStInstCode::LOCAL;
125
126 if (const PointerType *PT = dyn_cast<PointerType>(Src->getType())) {
127 switch (PT->getAddressSpace()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000128 case llvm::ADDRESS_SPACE_LOCAL:
129 return NVPTX::PTXLdStInstCode::LOCAL;
130 case llvm::ADDRESS_SPACE_GLOBAL:
131 return NVPTX::PTXLdStInstCode::GLOBAL;
132 case llvm::ADDRESS_SPACE_SHARED:
133 return NVPTX::PTXLdStInstCode::SHARED;
Justin Holewinski49683f32012-05-04 20:18:50 +0000134 case llvm::ADDRESS_SPACE_CONST_NOT_GEN:
135 return NVPTX::PTXLdStInstCode::CONSTANT;
Justin Holewinski3639ce22013-03-30 14:29:21 +0000136 case llvm::ADDRESS_SPACE_GENERIC:
137 return NVPTX::PTXLdStInstCode::GENERIC;
138 case llvm::ADDRESS_SPACE_PARAM:
139 return NVPTX::PTXLdStInstCode::PARAM;
Justin Holewinski49683f32012-05-04 20:18:50 +0000140 case llvm::ADDRESS_SPACE_CONST:
141 // If the arch supports generic address space, translate it to GLOBAL
142 // for correctness.
143 // If the arch does not support generic address space, then the arch
144 // does not really support ADDRESS_SPACE_CONST, translate it to
145 // to CONSTANT for better performance.
146 if (Subtarget.hasGenericLdSt())
147 return NVPTX::PTXLdStInstCode::GLOBAL;
148 else
149 return NVPTX::PTXLdStInstCode::CONSTANT;
Justin Holewinski3639ce22013-03-30 14:29:21 +0000150 default:
151 break;
Justin Holewinski49683f32012-05-04 20:18:50 +0000152 }
153 }
154 return NVPTX::PTXLdStInstCode::LOCAL;
155}
156
Justin Holewinski3639ce22013-03-30 14:29:21 +0000157SDNode *NVPTXDAGToDAGISel::SelectLoad(SDNode *N) {
Justin Holewinski49683f32012-05-04 20:18:50 +0000158 DebugLoc dl = N->getDebugLoc();
159 LoadSDNode *LD = cast<LoadSDNode>(N);
160 EVT LoadedVT = LD->getMemoryVT();
Justin Holewinski3639ce22013-03-30 14:29:21 +0000161 SDNode *NVPTXLD = NULL;
Justin Holewinski49683f32012-05-04 20:18:50 +0000162
163 // do not support pre/post inc/dec
164 if (LD->isIndexed())
165 return NULL;
166
167 if (!LoadedVT.isSimple())
168 return NULL;
169
170 // Address Space Setting
171 unsigned int codeAddrSpace = getCodeAddrSpace(LD, Subtarget);
172
173 // Volatile Setting
174 // - .volatile is only availalble for .global and .shared
175 bool isVolatile = LD->isVolatile();
176 if (codeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
177 codeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
178 codeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
179 isVolatile = false;
180
181 // Vector Setting
182 MVT SimpleVT = LoadedVT.getSimpleVT();
183 unsigned vecType = NVPTX::PTXLdStInstCode::Scalar;
184 if (SimpleVT.isVector()) {
185 unsigned num = SimpleVT.getVectorNumElements();
186 if (num == 2)
187 vecType = NVPTX::PTXLdStInstCode::V2;
188 else if (num == 4)
189 vecType = NVPTX::PTXLdStInstCode::V4;
190 else
191 return NULL;
192 }
193
194 // Type Setting: fromType + fromTypeWidth
195 //
196 // Sign : ISD::SEXTLOAD
197 // Unsign : ISD::ZEXTLOAD, ISD::NON_EXTLOAD or ISD::EXTLOAD and the
198 // type is integer
199 // Float : ISD::NON_EXTLOAD or ISD::EXTLOAD and the type is float
200 MVT ScalarVT = SimpleVT.getScalarType();
Justin Holewinski3639ce22013-03-30 14:29:21 +0000201 unsigned fromTypeWidth = ScalarVT.getSizeInBits();
Justin Holewinski49683f32012-05-04 20:18:50 +0000202 unsigned int fromType;
203 if ((LD->getExtensionType() == ISD::SEXTLOAD))
204 fromType = NVPTX::PTXLdStInstCode::Signed;
205 else if (ScalarVT.isFloatingPoint())
206 fromType = NVPTX::PTXLdStInstCode::Float;
207 else
208 fromType = NVPTX::PTXLdStInstCode::Unsigned;
209
210 // Create the machine instruction DAG
211 SDValue Chain = N->getOperand(0);
212 SDValue N1 = N->getOperand(1);
213 SDValue Addr;
214 SDValue Offset, Base;
215 unsigned Opcode;
216 MVT::SimpleValueType TargetVT = LD->getValueType(0).getSimpleVT().SimpleTy;
217
218 if (SelectDirectAddr(N1, Addr)) {
219 switch (TargetVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000220 case MVT::i8:
221 Opcode = NVPTX::LD_i8_avar;
222 break;
223 case MVT::i16:
224 Opcode = NVPTX::LD_i16_avar;
225 break;
226 case MVT::i32:
227 Opcode = NVPTX::LD_i32_avar;
228 break;
229 case MVT::i64:
230 Opcode = NVPTX::LD_i64_avar;
231 break;
232 case MVT::f32:
233 Opcode = NVPTX::LD_f32_avar;
234 break;
235 case MVT::f64:
236 Opcode = NVPTX::LD_f64_avar;
237 break;
238 default:
239 return NULL;
Justin Holewinski49683f32012-05-04 20:18:50 +0000240 }
Justin Holewinski3639ce22013-03-30 14:29:21 +0000241 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
242 getI32Imm(vecType), getI32Imm(fromType),
243 getI32Imm(fromTypeWidth), Addr, Chain };
244 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops, 7);
245 } else if (Subtarget.is64Bit()
246 ? SelectADDRsi64(N1.getNode(), N1, Base, Offset)
247 : SelectADDRsi(N1.getNode(), N1, Base, Offset)) {
Justin Holewinski49683f32012-05-04 20:18:50 +0000248 switch (TargetVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000249 case MVT::i8:
250 Opcode = NVPTX::LD_i8_asi;
251 break;
252 case MVT::i16:
253 Opcode = NVPTX::LD_i16_asi;
254 break;
255 case MVT::i32:
256 Opcode = NVPTX::LD_i32_asi;
257 break;
258 case MVT::i64:
259 Opcode = NVPTX::LD_i64_asi;
260 break;
261 case MVT::f32:
262 Opcode = NVPTX::LD_f32_asi;
263 break;
264 case MVT::f64:
265 Opcode = NVPTX::LD_f64_asi;
266 break;
267 default:
268 return NULL;
Justin Holewinski49683f32012-05-04 20:18:50 +0000269 }
Justin Holewinski3639ce22013-03-30 14:29:21 +0000270 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
271 getI32Imm(vecType), getI32Imm(fromType),
272 getI32Imm(fromTypeWidth), Base, Offset, Chain };
273 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops, 8);
274 } else if (Subtarget.is64Bit()
275 ? SelectADDRri64(N1.getNode(), N1, Base, Offset)
276 : SelectADDRri(N1.getNode(), N1, Base, Offset)) {
Justin Holewinski7eacad02013-02-12 14:18:49 +0000277 if (Subtarget.is64Bit()) {
278 switch (TargetVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000279 case MVT::i8:
280 Opcode = NVPTX::LD_i8_ari_64;
281 break;
282 case MVT::i16:
283 Opcode = NVPTX::LD_i16_ari_64;
284 break;
285 case MVT::i32:
286 Opcode = NVPTX::LD_i32_ari_64;
287 break;
288 case MVT::i64:
289 Opcode = NVPTX::LD_i64_ari_64;
290 break;
291 case MVT::f32:
292 Opcode = NVPTX::LD_f32_ari_64;
293 break;
294 case MVT::f64:
295 Opcode = NVPTX::LD_f64_ari_64;
296 break;
297 default:
298 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000299 }
300 } else {
301 switch (TargetVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000302 case MVT::i8:
303 Opcode = NVPTX::LD_i8_ari;
304 break;
305 case MVT::i16:
306 Opcode = NVPTX::LD_i16_ari;
307 break;
308 case MVT::i32:
309 Opcode = NVPTX::LD_i32_ari;
310 break;
311 case MVT::i64:
312 Opcode = NVPTX::LD_i64_ari;
313 break;
314 case MVT::f32:
315 Opcode = NVPTX::LD_f32_ari;
316 break;
317 case MVT::f64:
318 Opcode = NVPTX::LD_f64_ari;
319 break;
320 default:
321 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000322 }
Justin Holewinski49683f32012-05-04 20:18:50 +0000323 }
Justin Holewinski3639ce22013-03-30 14:29:21 +0000324 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
325 getI32Imm(vecType), getI32Imm(fromType),
326 getI32Imm(fromTypeWidth), Base, Offset, Chain };
327 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops, 8);
328 } else {
Justin Holewinski7eacad02013-02-12 14:18:49 +0000329 if (Subtarget.is64Bit()) {
330 switch (TargetVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000331 case MVT::i8:
332 Opcode = NVPTX::LD_i8_areg_64;
333 break;
334 case MVT::i16:
335 Opcode = NVPTX::LD_i16_areg_64;
336 break;
337 case MVT::i32:
338 Opcode = NVPTX::LD_i32_areg_64;
339 break;
340 case MVT::i64:
341 Opcode = NVPTX::LD_i64_areg_64;
342 break;
343 case MVT::f32:
344 Opcode = NVPTX::LD_f32_areg_64;
345 break;
346 case MVT::f64:
347 Opcode = NVPTX::LD_f64_areg_64;
348 break;
349 default:
350 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000351 }
352 } else {
353 switch (TargetVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000354 case MVT::i8:
355 Opcode = NVPTX::LD_i8_areg;
356 break;
357 case MVT::i16:
358 Opcode = NVPTX::LD_i16_areg;
359 break;
360 case MVT::i32:
361 Opcode = NVPTX::LD_i32_areg;
362 break;
363 case MVT::i64:
364 Opcode = NVPTX::LD_i64_areg;
365 break;
366 case MVT::f32:
367 Opcode = NVPTX::LD_f32_areg;
368 break;
369 case MVT::f64:
370 Opcode = NVPTX::LD_f64_areg;
371 break;
372 default:
373 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000374 }
Justin Holewinski49683f32012-05-04 20:18:50 +0000375 }
Justin Holewinski3639ce22013-03-30 14:29:21 +0000376 SDValue Ops[] = { getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
377 getI32Imm(vecType), getI32Imm(fromType),
378 getI32Imm(fromTypeWidth), N1, Chain };
379 NVPTXLD = CurDAG->getMachineNode(Opcode, dl, TargetVT, MVT::Other, Ops, 7);
Justin Holewinski49683f32012-05-04 20:18:50 +0000380 }
381
382 if (NVPTXLD != NULL) {
383 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
384 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
385 cast<MachineSDNode>(NVPTXLD)->setMemRefs(MemRefs0, MemRefs0 + 1);
386 }
387
388 return NVPTXLD;
389}
390
Justin Holewinski7eacad02013-02-12 14:18:49 +0000391SDNode *NVPTXDAGToDAGISel::SelectLoadVector(SDNode *N) {
392
393 SDValue Chain = N->getOperand(0);
394 SDValue Op1 = N->getOperand(1);
395 SDValue Addr, Offset, Base;
396 unsigned Opcode;
397 DebugLoc DL = N->getDebugLoc();
398 SDNode *LD;
399 MemSDNode *MemSD = cast<MemSDNode>(N);
400 EVT LoadedVT = MemSD->getMemoryVT();
401
Justin Holewinski7eacad02013-02-12 14:18:49 +0000402 if (!LoadedVT.isSimple())
Justin Holewinski3639ce22013-03-30 14:29:21 +0000403 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000404
405 // Address Space Setting
406 unsigned int CodeAddrSpace = getCodeAddrSpace(MemSD, Subtarget);
407
408 // Volatile Setting
409 // - .volatile is only availalble for .global and .shared
410 bool IsVolatile = MemSD->isVolatile();
411 if (CodeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
412 CodeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
413 CodeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
414 IsVolatile = false;
415
416 // Vector Setting
417 MVT SimpleVT = LoadedVT.getSimpleVT();
418
419 // Type Setting: fromType + fromTypeWidth
420 //
421 // Sign : ISD::SEXTLOAD
422 // Unsign : ISD::ZEXTLOAD, ISD::NON_EXTLOAD or ISD::EXTLOAD and the
423 // type is integer
424 // Float : ISD::NON_EXTLOAD or ISD::EXTLOAD and the type is float
425 MVT ScalarVT = SimpleVT.getScalarType();
Justin Holewinski3639ce22013-03-30 14:29:21 +0000426 unsigned FromTypeWidth = ScalarVT.getSizeInBits();
Justin Holewinski7eacad02013-02-12 14:18:49 +0000427 unsigned int FromType;
428 // The last operand holds the original LoadSDNode::getExtensionType() value
Justin Holewinski3639ce22013-03-30 14:29:21 +0000429 unsigned ExtensionType = cast<ConstantSDNode>(
430 N->getOperand(N->getNumOperands() - 1))->getZExtValue();
Justin Holewinski7eacad02013-02-12 14:18:49 +0000431 if (ExtensionType == ISD::SEXTLOAD)
432 FromType = NVPTX::PTXLdStInstCode::Signed;
433 else if (ScalarVT.isFloatingPoint())
434 FromType = NVPTX::PTXLdStInstCode::Float;
435 else
436 FromType = NVPTX::PTXLdStInstCode::Unsigned;
437
438 unsigned VecType;
439
440 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000441 case NVPTXISD::LoadV2:
442 VecType = NVPTX::PTXLdStInstCode::V2;
443 break;
444 case NVPTXISD::LoadV4:
445 VecType = NVPTX::PTXLdStInstCode::V4;
446 break;
447 default:
448 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000449 }
450
451 EVT EltVT = N->getValueType(0);
452
453 if (SelectDirectAddr(Op1, Addr)) {
454 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000455 default:
456 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000457 case NVPTXISD::LoadV2:
458 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000459 default:
460 return NULL;
461 case MVT::i8:
462 Opcode = NVPTX::LDV_i8_v2_avar;
463 break;
464 case MVT::i16:
465 Opcode = NVPTX::LDV_i16_v2_avar;
466 break;
467 case MVT::i32:
468 Opcode = NVPTX::LDV_i32_v2_avar;
469 break;
470 case MVT::i64:
471 Opcode = NVPTX::LDV_i64_v2_avar;
472 break;
473 case MVT::f32:
474 Opcode = NVPTX::LDV_f32_v2_avar;
475 break;
476 case MVT::f64:
477 Opcode = NVPTX::LDV_f64_v2_avar;
478 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000479 }
480 break;
481 case NVPTXISD::LoadV4:
482 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000483 default:
484 return NULL;
485 case MVT::i8:
486 Opcode = NVPTX::LDV_i8_v4_avar;
487 break;
488 case MVT::i16:
489 Opcode = NVPTX::LDV_i16_v4_avar;
490 break;
491 case MVT::i32:
492 Opcode = NVPTX::LDV_i32_v4_avar;
493 break;
494 case MVT::f32:
495 Opcode = NVPTX::LDV_f32_v4_avar;
496 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000497 }
498 break;
499 }
500
Justin Holewinski3639ce22013-03-30 14:29:21 +0000501 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
502 getI32Imm(VecType), getI32Imm(FromType),
503 getI32Imm(FromTypeWidth), Addr, Chain };
Justin Holewinski7eacad02013-02-12 14:18:49 +0000504 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops, 7);
Justin Holewinski3639ce22013-03-30 14:29:21 +0000505 } else if (Subtarget.is64Bit()
506 ? SelectADDRsi64(Op1.getNode(), Op1, Base, Offset)
507 : SelectADDRsi(Op1.getNode(), Op1, Base, Offset)) {
Justin Holewinski7eacad02013-02-12 14:18:49 +0000508 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000509 default:
510 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000511 case NVPTXISD::LoadV2:
512 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000513 default:
514 return NULL;
515 case MVT::i8:
516 Opcode = NVPTX::LDV_i8_v2_asi;
517 break;
518 case MVT::i16:
519 Opcode = NVPTX::LDV_i16_v2_asi;
520 break;
521 case MVT::i32:
522 Opcode = NVPTX::LDV_i32_v2_asi;
523 break;
524 case MVT::i64:
525 Opcode = NVPTX::LDV_i64_v2_asi;
526 break;
527 case MVT::f32:
528 Opcode = NVPTX::LDV_f32_v2_asi;
529 break;
530 case MVT::f64:
531 Opcode = NVPTX::LDV_f64_v2_asi;
532 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000533 }
534 break;
535 case NVPTXISD::LoadV4:
536 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000537 default:
538 return NULL;
539 case MVT::i8:
540 Opcode = NVPTX::LDV_i8_v4_asi;
541 break;
542 case MVT::i16:
543 Opcode = NVPTX::LDV_i16_v4_asi;
544 break;
545 case MVT::i32:
546 Opcode = NVPTX::LDV_i32_v4_asi;
547 break;
548 case MVT::f32:
549 Opcode = NVPTX::LDV_f32_v4_asi;
550 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000551 }
552 break;
553 }
554
Justin Holewinski3639ce22013-03-30 14:29:21 +0000555 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
556 getI32Imm(VecType), getI32Imm(FromType),
557 getI32Imm(FromTypeWidth), Base, Offset, Chain };
Justin Holewinski7eacad02013-02-12 14:18:49 +0000558 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops, 8);
Justin Holewinski3639ce22013-03-30 14:29:21 +0000559 } else if (Subtarget.is64Bit()
560 ? SelectADDRri64(Op1.getNode(), Op1, Base, Offset)
561 : SelectADDRri(Op1.getNode(), Op1, Base, Offset)) {
Justin Holewinski7eacad02013-02-12 14:18:49 +0000562 if (Subtarget.is64Bit()) {
563 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000564 default:
565 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000566 case NVPTXISD::LoadV2:
567 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000568 default:
569 return NULL;
570 case MVT::i8:
571 Opcode = NVPTX::LDV_i8_v2_ari_64;
572 break;
573 case MVT::i16:
574 Opcode = NVPTX::LDV_i16_v2_ari_64;
575 break;
576 case MVT::i32:
577 Opcode = NVPTX::LDV_i32_v2_ari_64;
578 break;
579 case MVT::i64:
580 Opcode = NVPTX::LDV_i64_v2_ari_64;
581 break;
582 case MVT::f32:
583 Opcode = NVPTX::LDV_f32_v2_ari_64;
584 break;
585 case MVT::f64:
586 Opcode = NVPTX::LDV_f64_v2_ari_64;
587 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000588 }
589 break;
590 case NVPTXISD::LoadV4:
591 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000592 default:
593 return NULL;
594 case MVT::i8:
595 Opcode = NVPTX::LDV_i8_v4_ari_64;
596 break;
597 case MVT::i16:
598 Opcode = NVPTX::LDV_i16_v4_ari_64;
599 break;
600 case MVT::i32:
601 Opcode = NVPTX::LDV_i32_v4_ari_64;
602 break;
603 case MVT::f32:
604 Opcode = NVPTX::LDV_f32_v4_ari_64;
605 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000606 }
607 break;
608 }
609 } else {
610 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000611 default:
612 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000613 case NVPTXISD::LoadV2:
614 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000615 default:
616 return NULL;
617 case MVT::i8:
618 Opcode = NVPTX::LDV_i8_v2_ari;
619 break;
620 case MVT::i16:
621 Opcode = NVPTX::LDV_i16_v2_ari;
622 break;
623 case MVT::i32:
624 Opcode = NVPTX::LDV_i32_v2_ari;
625 break;
626 case MVT::i64:
627 Opcode = NVPTX::LDV_i64_v2_ari;
628 break;
629 case MVT::f32:
630 Opcode = NVPTX::LDV_f32_v2_ari;
631 break;
632 case MVT::f64:
633 Opcode = NVPTX::LDV_f64_v2_ari;
634 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000635 }
636 break;
637 case NVPTXISD::LoadV4:
638 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000639 default:
640 return NULL;
641 case MVT::i8:
642 Opcode = NVPTX::LDV_i8_v4_ari;
643 break;
644 case MVT::i16:
645 Opcode = NVPTX::LDV_i16_v4_ari;
646 break;
647 case MVT::i32:
648 Opcode = NVPTX::LDV_i32_v4_ari;
649 break;
650 case MVT::f32:
651 Opcode = NVPTX::LDV_f32_v4_ari;
652 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000653 }
654 break;
655 }
656 }
657
Justin Holewinski3639ce22013-03-30 14:29:21 +0000658 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
659 getI32Imm(VecType), getI32Imm(FromType),
660 getI32Imm(FromTypeWidth), Base, Offset, Chain };
Justin Holewinski7eacad02013-02-12 14:18:49 +0000661
662 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops, 8);
663 } else {
664 if (Subtarget.is64Bit()) {
665 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000666 default:
667 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000668 case NVPTXISD::LoadV2:
669 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000670 default:
671 return NULL;
672 case MVT::i8:
673 Opcode = NVPTX::LDV_i8_v2_areg_64;
674 break;
675 case MVT::i16:
676 Opcode = NVPTX::LDV_i16_v2_areg_64;
677 break;
678 case MVT::i32:
679 Opcode = NVPTX::LDV_i32_v2_areg_64;
680 break;
681 case MVT::i64:
682 Opcode = NVPTX::LDV_i64_v2_areg_64;
683 break;
684 case MVT::f32:
685 Opcode = NVPTX::LDV_f32_v2_areg_64;
686 break;
687 case MVT::f64:
688 Opcode = NVPTX::LDV_f64_v2_areg_64;
689 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000690 }
691 break;
692 case NVPTXISD::LoadV4:
693 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000694 default:
695 return NULL;
696 case MVT::i8:
697 Opcode = NVPTX::LDV_i8_v4_areg_64;
698 break;
699 case MVT::i16:
700 Opcode = NVPTX::LDV_i16_v4_areg_64;
701 break;
702 case MVT::i32:
703 Opcode = NVPTX::LDV_i32_v4_areg_64;
704 break;
705 case MVT::f32:
706 Opcode = NVPTX::LDV_f32_v4_areg_64;
707 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000708 }
709 break;
710 }
711 } else {
712 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000713 default:
714 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000715 case NVPTXISD::LoadV2:
716 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000717 default:
718 return NULL;
719 case MVT::i8:
720 Opcode = NVPTX::LDV_i8_v2_areg;
721 break;
722 case MVT::i16:
723 Opcode = NVPTX::LDV_i16_v2_areg;
724 break;
725 case MVT::i32:
726 Opcode = NVPTX::LDV_i32_v2_areg;
727 break;
728 case MVT::i64:
729 Opcode = NVPTX::LDV_i64_v2_areg;
730 break;
731 case MVT::f32:
732 Opcode = NVPTX::LDV_f32_v2_areg;
733 break;
734 case MVT::f64:
735 Opcode = NVPTX::LDV_f64_v2_areg;
736 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000737 }
738 break;
739 case NVPTXISD::LoadV4:
740 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000741 default:
742 return NULL;
743 case MVT::i8:
744 Opcode = NVPTX::LDV_i8_v4_areg;
745 break;
746 case MVT::i16:
747 Opcode = NVPTX::LDV_i16_v4_areg;
748 break;
749 case MVT::i32:
750 Opcode = NVPTX::LDV_i32_v4_areg;
751 break;
752 case MVT::f32:
753 Opcode = NVPTX::LDV_f32_v4_areg;
754 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000755 }
756 break;
757 }
758 }
759
Justin Holewinski3639ce22013-03-30 14:29:21 +0000760 SDValue Ops[] = { getI32Imm(IsVolatile), getI32Imm(CodeAddrSpace),
761 getI32Imm(VecType), getI32Imm(FromType),
762 getI32Imm(FromTypeWidth), Op1, Chain };
Justin Holewinski7eacad02013-02-12 14:18:49 +0000763 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), Ops, 7);
764 }
765
766 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
767 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
768 cast<MachineSDNode>(LD)->setMemRefs(MemRefs0, MemRefs0 + 1);
769
770 return LD;
771}
772
773SDNode *NVPTXDAGToDAGISel::SelectLDGLDUVector(SDNode *N) {
774
775 SDValue Chain = N->getOperand(0);
776 SDValue Op1 = N->getOperand(1);
777 unsigned Opcode;
778 DebugLoc DL = N->getDebugLoc();
779 SDNode *LD;
780
781 EVT RetVT = N->getValueType(0);
782
783 // Select opcode
784 if (Subtarget.is64Bit()) {
785 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000786 default:
787 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000788 case NVPTXISD::LDGV2:
789 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000790 default:
791 return NULL;
792 case MVT::i8:
793 Opcode = NVPTX::INT_PTX_LDG_G_v2i8_ELE_64;
794 break;
795 case MVT::i16:
796 Opcode = NVPTX::INT_PTX_LDG_G_v2i16_ELE_64;
797 break;
798 case MVT::i32:
799 Opcode = NVPTX::INT_PTX_LDG_G_v2i32_ELE_64;
800 break;
801 case MVT::i64:
802 Opcode = NVPTX::INT_PTX_LDG_G_v2i64_ELE_64;
803 break;
804 case MVT::f32:
805 Opcode = NVPTX::INT_PTX_LDG_G_v2f32_ELE_64;
806 break;
807 case MVT::f64:
808 Opcode = NVPTX::INT_PTX_LDG_G_v2f64_ELE_64;
809 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000810 }
811 break;
812 case NVPTXISD::LDGV4:
813 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000814 default:
815 return NULL;
816 case MVT::i8:
817 Opcode = NVPTX::INT_PTX_LDG_G_v4i8_ELE_64;
818 break;
819 case MVT::i16:
820 Opcode = NVPTX::INT_PTX_LDG_G_v4i16_ELE_64;
821 break;
822 case MVT::i32:
823 Opcode = NVPTX::INT_PTX_LDG_G_v4i32_ELE_64;
824 break;
825 case MVT::f32:
826 Opcode = NVPTX::INT_PTX_LDG_G_v4f32_ELE_64;
827 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000828 }
829 break;
830 case NVPTXISD::LDUV2:
831 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000832 default:
833 return NULL;
834 case MVT::i8:
835 Opcode = NVPTX::INT_PTX_LDU_G_v2i8_ELE_64;
836 break;
837 case MVT::i16:
838 Opcode = NVPTX::INT_PTX_LDU_G_v2i16_ELE_64;
839 break;
840 case MVT::i32:
841 Opcode = NVPTX::INT_PTX_LDU_G_v2i32_ELE_64;
842 break;
843 case MVT::i64:
844 Opcode = NVPTX::INT_PTX_LDU_G_v2i64_ELE_64;
845 break;
846 case MVT::f32:
847 Opcode = NVPTX::INT_PTX_LDU_G_v2f32_ELE_64;
848 break;
849 case MVT::f64:
850 Opcode = NVPTX::INT_PTX_LDU_G_v2f64_ELE_64;
851 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000852 }
853 break;
854 case NVPTXISD::LDUV4:
855 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000856 default:
857 return NULL;
858 case MVT::i8:
859 Opcode = NVPTX::INT_PTX_LDU_G_v4i8_ELE_64;
860 break;
861 case MVT::i16:
862 Opcode = NVPTX::INT_PTX_LDU_G_v4i16_ELE_64;
863 break;
864 case MVT::i32:
865 Opcode = NVPTX::INT_PTX_LDU_G_v4i32_ELE_64;
866 break;
867 case MVT::f32:
868 Opcode = NVPTX::INT_PTX_LDU_G_v4f32_ELE_64;
869 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000870 }
871 break;
872 }
873 } else {
874 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000875 default:
876 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000877 case NVPTXISD::LDGV2:
878 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000879 default:
880 return NULL;
881 case MVT::i8:
882 Opcode = NVPTX::INT_PTX_LDG_G_v2i8_ELE_32;
883 break;
884 case MVT::i16:
885 Opcode = NVPTX::INT_PTX_LDG_G_v2i16_ELE_32;
886 break;
887 case MVT::i32:
888 Opcode = NVPTX::INT_PTX_LDG_G_v2i32_ELE_32;
889 break;
890 case MVT::i64:
891 Opcode = NVPTX::INT_PTX_LDG_G_v2i64_ELE_32;
892 break;
893 case MVT::f32:
894 Opcode = NVPTX::INT_PTX_LDG_G_v2f32_ELE_32;
895 break;
896 case MVT::f64:
897 Opcode = NVPTX::INT_PTX_LDG_G_v2f64_ELE_32;
898 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000899 }
900 break;
901 case NVPTXISD::LDGV4:
902 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000903 default:
904 return NULL;
905 case MVT::i8:
906 Opcode = NVPTX::INT_PTX_LDG_G_v4i8_ELE_32;
907 break;
908 case MVT::i16:
909 Opcode = NVPTX::INT_PTX_LDG_G_v4i16_ELE_32;
910 break;
911 case MVT::i32:
912 Opcode = NVPTX::INT_PTX_LDG_G_v4i32_ELE_32;
913 break;
914 case MVT::f32:
915 Opcode = NVPTX::INT_PTX_LDG_G_v4f32_ELE_32;
916 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000917 }
918 break;
919 case NVPTXISD::LDUV2:
920 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000921 default:
922 return NULL;
923 case MVT::i8:
924 Opcode = NVPTX::INT_PTX_LDU_G_v2i8_ELE_32;
925 break;
926 case MVT::i16:
927 Opcode = NVPTX::INT_PTX_LDU_G_v2i16_ELE_32;
928 break;
929 case MVT::i32:
930 Opcode = NVPTX::INT_PTX_LDU_G_v2i32_ELE_32;
931 break;
932 case MVT::i64:
933 Opcode = NVPTX::INT_PTX_LDU_G_v2i64_ELE_32;
934 break;
935 case MVT::f32:
936 Opcode = NVPTX::INT_PTX_LDU_G_v2f32_ELE_32;
937 break;
938 case MVT::f64:
939 Opcode = NVPTX::INT_PTX_LDU_G_v2f64_ELE_32;
940 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000941 }
942 break;
943 case NVPTXISD::LDUV4:
944 switch (RetVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +0000945 default:
946 return NULL;
947 case MVT::i8:
948 Opcode = NVPTX::INT_PTX_LDU_G_v4i8_ELE_32;
949 break;
950 case MVT::i16:
951 Opcode = NVPTX::INT_PTX_LDU_G_v4i16_ELE_32;
952 break;
953 case MVT::i32:
954 Opcode = NVPTX::INT_PTX_LDU_G_v4i32_ELE_32;
955 break;
956 case MVT::f32:
957 Opcode = NVPTX::INT_PTX_LDU_G_v4f32_ELE_32;
958 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +0000959 }
960 break;
961 }
962 }
963
964 SDValue Ops[] = { Op1, Chain };
965 LD = CurDAG->getMachineNode(Opcode, DL, N->getVTList(), &Ops[0], 2);
966
967 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
968 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
969 cast<MachineSDNode>(LD)->setMemRefs(MemRefs0, MemRefs0 + 1);
970
971 return LD;
972}
973
Justin Holewinski3639ce22013-03-30 14:29:21 +0000974SDNode *NVPTXDAGToDAGISel::SelectStore(SDNode *N) {
Justin Holewinski49683f32012-05-04 20:18:50 +0000975 DebugLoc dl = N->getDebugLoc();
976 StoreSDNode *ST = cast<StoreSDNode>(N);
977 EVT StoreVT = ST->getMemoryVT();
978 SDNode *NVPTXST = NULL;
979
980 // do not support pre/post inc/dec
981 if (ST->isIndexed())
982 return NULL;
983
984 if (!StoreVT.isSimple())
985 return NULL;
986
987 // Address Space Setting
988 unsigned int codeAddrSpace = getCodeAddrSpace(ST, Subtarget);
989
990 // Volatile Setting
991 // - .volatile is only availalble for .global and .shared
992 bool isVolatile = ST->isVolatile();
993 if (codeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
994 codeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
995 codeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
996 isVolatile = false;
997
998 // Vector Setting
999 MVT SimpleVT = StoreVT.getSimpleVT();
1000 unsigned vecType = NVPTX::PTXLdStInstCode::Scalar;
1001 if (SimpleVT.isVector()) {
1002 unsigned num = SimpleVT.getVectorNumElements();
1003 if (num == 2)
1004 vecType = NVPTX::PTXLdStInstCode::V2;
1005 else if (num == 4)
1006 vecType = NVPTX::PTXLdStInstCode::V4;
1007 else
1008 return NULL;
1009 }
1010
1011 // Type Setting: toType + toTypeWidth
1012 // - for integer type, always use 'u'
1013 //
1014 MVT ScalarVT = SimpleVT.getScalarType();
Justin Holewinski3639ce22013-03-30 14:29:21 +00001015 unsigned toTypeWidth = ScalarVT.getSizeInBits();
Justin Holewinski49683f32012-05-04 20:18:50 +00001016 unsigned int toType;
1017 if (ScalarVT.isFloatingPoint())
1018 toType = NVPTX::PTXLdStInstCode::Float;
1019 else
1020 toType = NVPTX::PTXLdStInstCode::Unsigned;
1021
1022 // Create the machine instruction DAG
1023 SDValue Chain = N->getOperand(0);
1024 SDValue N1 = N->getOperand(1);
1025 SDValue N2 = N->getOperand(2);
1026 SDValue Addr;
1027 SDValue Offset, Base;
1028 unsigned Opcode;
1029 MVT::SimpleValueType SourceVT =
1030 N1.getNode()->getValueType(0).getSimpleVT().SimpleTy;
1031
1032 if (SelectDirectAddr(N2, Addr)) {
1033 switch (SourceVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001034 case MVT::i8:
1035 Opcode = NVPTX::ST_i8_avar;
1036 break;
1037 case MVT::i16:
1038 Opcode = NVPTX::ST_i16_avar;
1039 break;
1040 case MVT::i32:
1041 Opcode = NVPTX::ST_i32_avar;
1042 break;
1043 case MVT::i64:
1044 Opcode = NVPTX::ST_i64_avar;
1045 break;
1046 case MVT::f32:
1047 Opcode = NVPTX::ST_f32_avar;
1048 break;
1049 case MVT::f64:
1050 Opcode = NVPTX::ST_f64_avar;
1051 break;
1052 default:
1053 return NULL;
Justin Holewinski49683f32012-05-04 20:18:50 +00001054 }
Justin Holewinski3639ce22013-03-30 14:29:21 +00001055 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1056 getI32Imm(vecType), getI32Imm(toType),
1057 getI32Imm(toTypeWidth), Addr, Chain };
1058 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, 8);
1059 } else if (Subtarget.is64Bit()
1060 ? SelectADDRsi64(N2.getNode(), N2, Base, Offset)
1061 : SelectADDRsi(N2.getNode(), N2, Base, Offset)) {
Justin Holewinski49683f32012-05-04 20:18:50 +00001062 switch (SourceVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001063 case MVT::i8:
1064 Opcode = NVPTX::ST_i8_asi;
1065 break;
1066 case MVT::i16:
1067 Opcode = NVPTX::ST_i16_asi;
1068 break;
1069 case MVT::i32:
1070 Opcode = NVPTX::ST_i32_asi;
1071 break;
1072 case MVT::i64:
1073 Opcode = NVPTX::ST_i64_asi;
1074 break;
1075 case MVT::f32:
1076 Opcode = NVPTX::ST_f32_asi;
1077 break;
1078 case MVT::f64:
1079 Opcode = NVPTX::ST_f64_asi;
1080 break;
1081 default:
1082 return NULL;
Justin Holewinski49683f32012-05-04 20:18:50 +00001083 }
Justin Holewinski3639ce22013-03-30 14:29:21 +00001084 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1085 getI32Imm(vecType), getI32Imm(toType),
1086 getI32Imm(toTypeWidth), Base, Offset, Chain };
1087 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, 9);
1088 } else if (Subtarget.is64Bit()
1089 ? SelectADDRri64(N2.getNode(), N2, Base, Offset)
1090 : SelectADDRri(N2.getNode(), N2, Base, Offset)) {
Justin Holewinski7eacad02013-02-12 14:18:49 +00001091 if (Subtarget.is64Bit()) {
1092 switch (SourceVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001093 case MVT::i8:
1094 Opcode = NVPTX::ST_i8_ari_64;
1095 break;
1096 case MVT::i16:
1097 Opcode = NVPTX::ST_i16_ari_64;
1098 break;
1099 case MVT::i32:
1100 Opcode = NVPTX::ST_i32_ari_64;
1101 break;
1102 case MVT::i64:
1103 Opcode = NVPTX::ST_i64_ari_64;
1104 break;
1105 case MVT::f32:
1106 Opcode = NVPTX::ST_f32_ari_64;
1107 break;
1108 case MVT::f64:
1109 Opcode = NVPTX::ST_f64_ari_64;
1110 break;
1111 default:
1112 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001113 }
1114 } else {
1115 switch (SourceVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001116 case MVT::i8:
1117 Opcode = NVPTX::ST_i8_ari;
1118 break;
1119 case MVT::i16:
1120 Opcode = NVPTX::ST_i16_ari;
1121 break;
1122 case MVT::i32:
1123 Opcode = NVPTX::ST_i32_ari;
1124 break;
1125 case MVT::i64:
1126 Opcode = NVPTX::ST_i64_ari;
1127 break;
1128 case MVT::f32:
1129 Opcode = NVPTX::ST_f32_ari;
1130 break;
1131 case MVT::f64:
1132 Opcode = NVPTX::ST_f64_ari;
1133 break;
1134 default:
1135 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001136 }
Justin Holewinski49683f32012-05-04 20:18:50 +00001137 }
Justin Holewinski3639ce22013-03-30 14:29:21 +00001138 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1139 getI32Imm(vecType), getI32Imm(toType),
1140 getI32Imm(toTypeWidth), Base, Offset, Chain };
1141 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, 9);
Justin Holewinski49683f32012-05-04 20:18:50 +00001142 } else {
Justin Holewinski7eacad02013-02-12 14:18:49 +00001143 if (Subtarget.is64Bit()) {
1144 switch (SourceVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001145 case MVT::i8:
1146 Opcode = NVPTX::ST_i8_areg_64;
1147 break;
1148 case MVT::i16:
1149 Opcode = NVPTX::ST_i16_areg_64;
1150 break;
1151 case MVT::i32:
1152 Opcode = NVPTX::ST_i32_areg_64;
1153 break;
1154 case MVT::i64:
1155 Opcode = NVPTX::ST_i64_areg_64;
1156 break;
1157 case MVT::f32:
1158 Opcode = NVPTX::ST_f32_areg_64;
1159 break;
1160 case MVT::f64:
1161 Opcode = NVPTX::ST_f64_areg_64;
1162 break;
1163 default:
1164 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001165 }
1166 } else {
1167 switch (SourceVT) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001168 case MVT::i8:
1169 Opcode = NVPTX::ST_i8_areg;
1170 break;
1171 case MVT::i16:
1172 Opcode = NVPTX::ST_i16_areg;
1173 break;
1174 case MVT::i32:
1175 Opcode = NVPTX::ST_i32_areg;
1176 break;
1177 case MVT::i64:
1178 Opcode = NVPTX::ST_i64_areg;
1179 break;
1180 case MVT::f32:
1181 Opcode = NVPTX::ST_f32_areg;
1182 break;
1183 case MVT::f64:
1184 Opcode = NVPTX::ST_f64_areg;
1185 break;
1186 default:
1187 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001188 }
Justin Holewinski49683f32012-05-04 20:18:50 +00001189 }
Justin Holewinski3639ce22013-03-30 14:29:21 +00001190 SDValue Ops[] = { N1, getI32Imm(isVolatile), getI32Imm(codeAddrSpace),
1191 getI32Imm(vecType), getI32Imm(toType),
1192 getI32Imm(toTypeWidth), N2, Chain };
1193 NVPTXST = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, 8);
Justin Holewinski49683f32012-05-04 20:18:50 +00001194 }
1195
1196 if (NVPTXST != NULL) {
1197 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
1198 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
1199 cast<MachineSDNode>(NVPTXST)->setMemRefs(MemRefs0, MemRefs0 + 1);
1200 }
1201
1202 return NVPTXST;
1203}
1204
Justin Holewinski7eacad02013-02-12 14:18:49 +00001205SDNode *NVPTXDAGToDAGISel::SelectStoreVector(SDNode *N) {
1206 SDValue Chain = N->getOperand(0);
1207 SDValue Op1 = N->getOperand(1);
1208 SDValue Addr, Offset, Base;
1209 unsigned Opcode;
1210 DebugLoc DL = N->getDebugLoc();
1211 SDNode *ST;
1212 EVT EltVT = Op1.getValueType();
1213 MemSDNode *MemSD = cast<MemSDNode>(N);
1214 EVT StoreVT = MemSD->getMemoryVT();
1215
1216 // Address Space Setting
1217 unsigned CodeAddrSpace = getCodeAddrSpace(MemSD, Subtarget);
1218
1219 if (CodeAddrSpace == NVPTX::PTXLdStInstCode::CONSTANT) {
1220 report_fatal_error("Cannot store to pointer that points to constant "
1221 "memory space");
1222 }
1223
1224 // Volatile Setting
1225 // - .volatile is only availalble for .global and .shared
1226 bool IsVolatile = MemSD->isVolatile();
1227 if (CodeAddrSpace != NVPTX::PTXLdStInstCode::GLOBAL &&
1228 CodeAddrSpace != NVPTX::PTXLdStInstCode::SHARED &&
1229 CodeAddrSpace != NVPTX::PTXLdStInstCode::GENERIC)
1230 IsVolatile = false;
1231
1232 // Type Setting: toType + toTypeWidth
1233 // - for integer type, always use 'u'
1234 assert(StoreVT.isSimple() && "Store value is not simple");
1235 MVT ScalarVT = StoreVT.getSimpleVT().getScalarType();
Justin Holewinski3639ce22013-03-30 14:29:21 +00001236 unsigned ToTypeWidth = ScalarVT.getSizeInBits();
Justin Holewinski7eacad02013-02-12 14:18:49 +00001237 unsigned ToType;
1238 if (ScalarVT.isFloatingPoint())
1239 ToType = NVPTX::PTXLdStInstCode::Float;
1240 else
1241 ToType = NVPTX::PTXLdStInstCode::Unsigned;
1242
Justin Holewinski7eacad02013-02-12 14:18:49 +00001243 SmallVector<SDValue, 12> StOps;
1244 SDValue N2;
1245 unsigned VecType;
1246
1247 switch (N->getOpcode()) {
1248 case NVPTXISD::StoreV2:
1249 VecType = NVPTX::PTXLdStInstCode::V2;
1250 StOps.push_back(N->getOperand(1));
1251 StOps.push_back(N->getOperand(2));
1252 N2 = N->getOperand(3);
1253 break;
1254 case NVPTXISD::StoreV4:
1255 VecType = NVPTX::PTXLdStInstCode::V4;
1256 StOps.push_back(N->getOperand(1));
1257 StOps.push_back(N->getOperand(2));
1258 StOps.push_back(N->getOperand(3));
1259 StOps.push_back(N->getOperand(4));
1260 N2 = N->getOperand(5);
1261 break;
Justin Holewinski3639ce22013-03-30 14:29:21 +00001262 default:
1263 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001264 }
1265
1266 StOps.push_back(getI32Imm(IsVolatile));
1267 StOps.push_back(getI32Imm(CodeAddrSpace));
1268 StOps.push_back(getI32Imm(VecType));
1269 StOps.push_back(getI32Imm(ToType));
1270 StOps.push_back(getI32Imm(ToTypeWidth));
1271
1272 if (SelectDirectAddr(N2, Addr)) {
1273 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001274 default:
1275 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001276 case NVPTXISD::StoreV2:
1277 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001278 default:
1279 return NULL;
1280 case MVT::i8:
1281 Opcode = NVPTX::STV_i8_v2_avar;
1282 break;
1283 case MVT::i16:
1284 Opcode = NVPTX::STV_i16_v2_avar;
1285 break;
1286 case MVT::i32:
1287 Opcode = NVPTX::STV_i32_v2_avar;
1288 break;
1289 case MVT::i64:
1290 Opcode = NVPTX::STV_i64_v2_avar;
1291 break;
1292 case MVT::f32:
1293 Opcode = NVPTX::STV_f32_v2_avar;
1294 break;
1295 case MVT::f64:
1296 Opcode = NVPTX::STV_f64_v2_avar;
1297 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001298 }
1299 break;
1300 case NVPTXISD::StoreV4:
1301 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001302 default:
1303 return NULL;
1304 case MVT::i8:
1305 Opcode = NVPTX::STV_i8_v4_avar;
1306 break;
1307 case MVT::i16:
1308 Opcode = NVPTX::STV_i16_v4_avar;
1309 break;
1310 case MVT::i32:
1311 Opcode = NVPTX::STV_i32_v4_avar;
1312 break;
1313 case MVT::f32:
1314 Opcode = NVPTX::STV_f32_v4_avar;
1315 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001316 }
1317 break;
1318 }
1319 StOps.push_back(Addr);
Justin Holewinski3639ce22013-03-30 14:29:21 +00001320 } else if (Subtarget.is64Bit()
1321 ? SelectADDRsi64(N2.getNode(), N2, Base, Offset)
1322 : SelectADDRsi(N2.getNode(), N2, Base, Offset)) {
Justin Holewinski7eacad02013-02-12 14:18:49 +00001323 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001324 default:
1325 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001326 case NVPTXISD::StoreV2:
1327 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001328 default:
1329 return NULL;
1330 case MVT::i8:
1331 Opcode = NVPTX::STV_i8_v2_asi;
1332 break;
1333 case MVT::i16:
1334 Opcode = NVPTX::STV_i16_v2_asi;
1335 break;
1336 case MVT::i32:
1337 Opcode = NVPTX::STV_i32_v2_asi;
1338 break;
1339 case MVT::i64:
1340 Opcode = NVPTX::STV_i64_v2_asi;
1341 break;
1342 case MVT::f32:
1343 Opcode = NVPTX::STV_f32_v2_asi;
1344 break;
1345 case MVT::f64:
1346 Opcode = NVPTX::STV_f64_v2_asi;
1347 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001348 }
1349 break;
1350 case NVPTXISD::StoreV4:
1351 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001352 default:
1353 return NULL;
1354 case MVT::i8:
1355 Opcode = NVPTX::STV_i8_v4_asi;
1356 break;
1357 case MVT::i16:
1358 Opcode = NVPTX::STV_i16_v4_asi;
1359 break;
1360 case MVT::i32:
1361 Opcode = NVPTX::STV_i32_v4_asi;
1362 break;
1363 case MVT::f32:
1364 Opcode = NVPTX::STV_f32_v4_asi;
1365 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001366 }
1367 break;
1368 }
1369 StOps.push_back(Base);
1370 StOps.push_back(Offset);
Justin Holewinski3639ce22013-03-30 14:29:21 +00001371 } else if (Subtarget.is64Bit()
1372 ? SelectADDRri64(N2.getNode(), N2, Base, Offset)
1373 : SelectADDRri(N2.getNode(), N2, Base, Offset)) {
Justin Holewinski7eacad02013-02-12 14:18:49 +00001374 if (Subtarget.is64Bit()) {
1375 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001376 default:
1377 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001378 case NVPTXISD::StoreV2:
1379 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001380 default:
1381 return NULL;
1382 case MVT::i8:
1383 Opcode = NVPTX::STV_i8_v2_ari_64;
1384 break;
1385 case MVT::i16:
1386 Opcode = NVPTX::STV_i16_v2_ari_64;
1387 break;
1388 case MVT::i32:
1389 Opcode = NVPTX::STV_i32_v2_ari_64;
1390 break;
1391 case MVT::i64:
1392 Opcode = NVPTX::STV_i64_v2_ari_64;
1393 break;
1394 case MVT::f32:
1395 Opcode = NVPTX::STV_f32_v2_ari_64;
1396 break;
1397 case MVT::f64:
1398 Opcode = NVPTX::STV_f64_v2_ari_64;
1399 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001400 }
1401 break;
1402 case NVPTXISD::StoreV4:
1403 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001404 default:
1405 return NULL;
1406 case MVT::i8:
1407 Opcode = NVPTX::STV_i8_v4_ari_64;
1408 break;
1409 case MVT::i16:
1410 Opcode = NVPTX::STV_i16_v4_ari_64;
1411 break;
1412 case MVT::i32:
1413 Opcode = NVPTX::STV_i32_v4_ari_64;
1414 break;
1415 case MVT::f32:
1416 Opcode = NVPTX::STV_f32_v4_ari_64;
1417 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001418 }
1419 break;
1420 }
1421 } else {
1422 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001423 default:
1424 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001425 case NVPTXISD::StoreV2:
1426 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001427 default:
1428 return NULL;
1429 case MVT::i8:
1430 Opcode = NVPTX::STV_i8_v2_ari;
1431 break;
1432 case MVT::i16:
1433 Opcode = NVPTX::STV_i16_v2_ari;
1434 break;
1435 case MVT::i32:
1436 Opcode = NVPTX::STV_i32_v2_ari;
1437 break;
1438 case MVT::i64:
1439 Opcode = NVPTX::STV_i64_v2_ari;
1440 break;
1441 case MVT::f32:
1442 Opcode = NVPTX::STV_f32_v2_ari;
1443 break;
1444 case MVT::f64:
1445 Opcode = NVPTX::STV_f64_v2_ari;
1446 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001447 }
1448 break;
1449 case NVPTXISD::StoreV4:
1450 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001451 default:
1452 return NULL;
1453 case MVT::i8:
1454 Opcode = NVPTX::STV_i8_v4_ari;
1455 break;
1456 case MVT::i16:
1457 Opcode = NVPTX::STV_i16_v4_ari;
1458 break;
1459 case MVT::i32:
1460 Opcode = NVPTX::STV_i32_v4_ari;
1461 break;
1462 case MVT::f32:
1463 Opcode = NVPTX::STV_f32_v4_ari;
1464 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001465 }
1466 break;
1467 }
1468 }
1469 StOps.push_back(Base);
1470 StOps.push_back(Offset);
1471 } else {
1472 if (Subtarget.is64Bit()) {
1473 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001474 default:
1475 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001476 case NVPTXISD::StoreV2:
1477 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001478 default:
1479 return NULL;
1480 case MVT::i8:
1481 Opcode = NVPTX::STV_i8_v2_areg_64;
1482 break;
1483 case MVT::i16:
1484 Opcode = NVPTX::STV_i16_v2_areg_64;
1485 break;
1486 case MVT::i32:
1487 Opcode = NVPTX::STV_i32_v2_areg_64;
1488 break;
1489 case MVT::i64:
1490 Opcode = NVPTX::STV_i64_v2_areg_64;
1491 break;
1492 case MVT::f32:
1493 Opcode = NVPTX::STV_f32_v2_areg_64;
1494 break;
1495 case MVT::f64:
1496 Opcode = NVPTX::STV_f64_v2_areg_64;
1497 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001498 }
1499 break;
1500 case NVPTXISD::StoreV4:
1501 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001502 default:
1503 return NULL;
1504 case MVT::i8:
1505 Opcode = NVPTX::STV_i8_v4_areg_64;
1506 break;
1507 case MVT::i16:
1508 Opcode = NVPTX::STV_i16_v4_areg_64;
1509 break;
1510 case MVT::i32:
1511 Opcode = NVPTX::STV_i32_v4_areg_64;
1512 break;
1513 case MVT::f32:
1514 Opcode = NVPTX::STV_f32_v4_areg_64;
1515 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001516 }
1517 break;
1518 }
1519 } else {
1520 switch (N->getOpcode()) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001521 default:
1522 return NULL;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001523 case NVPTXISD::StoreV2:
1524 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001525 default:
1526 return NULL;
1527 case MVT::i8:
1528 Opcode = NVPTX::STV_i8_v2_areg;
1529 break;
1530 case MVT::i16:
1531 Opcode = NVPTX::STV_i16_v2_areg;
1532 break;
1533 case MVT::i32:
1534 Opcode = NVPTX::STV_i32_v2_areg;
1535 break;
1536 case MVT::i64:
1537 Opcode = NVPTX::STV_i64_v2_areg;
1538 break;
1539 case MVT::f32:
1540 Opcode = NVPTX::STV_f32_v2_areg;
1541 break;
1542 case MVT::f64:
1543 Opcode = NVPTX::STV_f64_v2_areg;
1544 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001545 }
1546 break;
1547 case NVPTXISD::StoreV4:
1548 switch (EltVT.getSimpleVT().SimpleTy) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001549 default:
1550 return NULL;
1551 case MVT::i8:
1552 Opcode = NVPTX::STV_i8_v4_areg;
1553 break;
1554 case MVT::i16:
1555 Opcode = NVPTX::STV_i16_v4_areg;
1556 break;
1557 case MVT::i32:
1558 Opcode = NVPTX::STV_i32_v4_areg;
1559 break;
1560 case MVT::f32:
1561 Opcode = NVPTX::STV_f32_v4_areg;
1562 break;
Justin Holewinski7eacad02013-02-12 14:18:49 +00001563 }
1564 break;
1565 }
1566 }
1567 StOps.push_back(N2);
1568 }
1569
1570 StOps.push_back(Chain);
1571
1572 ST = CurDAG->getMachineNode(Opcode, DL, MVT::Other, &StOps[0], StOps.size());
1573
1574 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
1575 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
1576 cast<MachineSDNode>(ST)->setMemRefs(MemRefs0, MemRefs0 + 1);
1577
1578 return ST;
1579}
1580
Justin Holewinski49683f32012-05-04 20:18:50 +00001581// SelectDirectAddr - Match a direct address for DAG.
1582// A direct address could be a globaladdress or externalsymbol.
1583bool NVPTXDAGToDAGISel::SelectDirectAddr(SDValue N, SDValue &Address) {
1584 // Return true if TGA or ES.
Justin Holewinski3639ce22013-03-30 14:29:21 +00001585 if (N.getOpcode() == ISD::TargetGlobalAddress ||
1586 N.getOpcode() == ISD::TargetExternalSymbol) {
Justin Holewinski49683f32012-05-04 20:18:50 +00001587 Address = N;
1588 return true;
1589 }
1590 if (N.getOpcode() == NVPTXISD::Wrapper) {
1591 Address = N.getOperand(0);
1592 return true;
1593 }
1594 if (N.getOpcode() == ISD::INTRINSIC_WO_CHAIN) {
1595 unsigned IID = cast<ConstantSDNode>(N.getOperand(0))->getZExtValue();
1596 if (IID == Intrinsic::nvvm_ptr_gen_to_param)
1597 if (N.getOperand(1).getOpcode() == NVPTXISD::MoveParam)
1598 return (SelectDirectAddr(N.getOperand(1).getOperand(0), Address));
1599 }
1600 return false;
1601}
1602
1603// symbol+offset
Justin Holewinski3639ce22013-03-30 14:29:21 +00001604bool NVPTXDAGToDAGISel::SelectADDRsi_imp(
1605 SDNode *OpNode, SDValue Addr, SDValue &Base, SDValue &Offset, MVT mvt) {
Justin Holewinski49683f32012-05-04 20:18:50 +00001606 if (Addr.getOpcode() == ISD::ADD) {
1607 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001608 SDValue base = Addr.getOperand(0);
Justin Holewinski49683f32012-05-04 20:18:50 +00001609 if (SelectDirectAddr(base, Base)) {
1610 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), mvt);
1611 return true;
1612 }
1613 }
1614 }
1615 return false;
1616}
1617
1618// symbol+offset
1619bool NVPTXDAGToDAGISel::SelectADDRsi(SDNode *OpNode, SDValue Addr,
1620 SDValue &Base, SDValue &Offset) {
1621 return SelectADDRsi_imp(OpNode, Addr, Base, Offset, MVT::i32);
1622}
1623
1624// symbol+offset
1625bool NVPTXDAGToDAGISel::SelectADDRsi64(SDNode *OpNode, SDValue Addr,
1626 SDValue &Base, SDValue &Offset) {
1627 return SelectADDRsi_imp(OpNode, Addr, Base, Offset, MVT::i64);
1628}
1629
1630// register+offset
Justin Holewinski3639ce22013-03-30 14:29:21 +00001631bool NVPTXDAGToDAGISel::SelectADDRri_imp(
1632 SDNode *OpNode, SDValue Addr, SDValue &Base, SDValue &Offset, MVT mvt) {
Justin Holewinski49683f32012-05-04 20:18:50 +00001633 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
1634 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), mvt);
1635 Offset = CurDAG->getTargetConstant(0, mvt);
1636 return true;
1637 }
1638 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1639 Addr.getOpcode() == ISD::TargetGlobalAddress)
Justin Holewinski3639ce22013-03-30 14:29:21 +00001640 return false; // direct calls.
Justin Holewinski49683f32012-05-04 20:18:50 +00001641
1642 if (Addr.getOpcode() == ISD::ADD) {
1643 if (SelectDirectAddr(Addr.getOperand(0), Addr)) {
1644 return false;
1645 }
1646 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
1647 if (FrameIndexSDNode *FIN =
Justin Holewinski3639ce22013-03-30 14:29:21 +00001648 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
Justin Holewinski49683f32012-05-04 20:18:50 +00001649 // Constant offset from frame ref.
1650 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), mvt);
1651 else
1652 Base = Addr.getOperand(0);
1653 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), mvt);
1654 return true;
1655 }
1656 }
1657 return false;
1658}
1659
1660// register+offset
1661bool NVPTXDAGToDAGISel::SelectADDRri(SDNode *OpNode, SDValue Addr,
1662 SDValue &Base, SDValue &Offset) {
1663 return SelectADDRri_imp(OpNode, Addr, Base, Offset, MVT::i32);
1664}
1665
1666// register+offset
1667bool NVPTXDAGToDAGISel::SelectADDRri64(SDNode *OpNode, SDValue Addr,
1668 SDValue &Base, SDValue &Offset) {
1669 return SelectADDRri_imp(OpNode, Addr, Base, Offset, MVT::i64);
1670}
1671
1672bool NVPTXDAGToDAGISel::ChkMemSDNodeAddressSpace(SDNode *N,
1673 unsigned int spN) const {
1674 const Value *Src = NULL;
1675 // Even though MemIntrinsicSDNode is a subclas of MemSDNode,
1676 // the classof() for MemSDNode does not include MemIntrinsicSDNode
1677 // (See SelectionDAGNodes.h). So we need to check for both.
1678 if (MemSDNode *mN = dyn_cast<MemSDNode>(N)) {
1679 Src = mN->getSrcValue();
Justin Holewinski3639ce22013-03-30 14:29:21 +00001680 } else if (MemSDNode *mN = dyn_cast<MemIntrinsicSDNode>(N)) {
Justin Holewinski49683f32012-05-04 20:18:50 +00001681 Src = mN->getSrcValue();
1682 }
1683 if (!Src)
1684 return false;
1685 if (const PointerType *PT = dyn_cast<PointerType>(Src->getType()))
1686 return (PT->getAddressSpace() == spN);
1687 return false;
1688}
1689
1690/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
1691/// inline asm expressions.
Justin Holewinski3639ce22013-03-30 14:29:21 +00001692bool NVPTXDAGToDAGISel::SelectInlineAsmMemoryOperand(
1693 const SDValue &Op, char ConstraintCode, std::vector<SDValue> &OutOps) {
Justin Holewinski49683f32012-05-04 20:18:50 +00001694 SDValue Op0, Op1;
1695 switch (ConstraintCode) {
Justin Holewinski3639ce22013-03-30 14:29:21 +00001696 default:
1697 return true;
1698 case 'm': // memory
Justin Holewinski49683f32012-05-04 20:18:50 +00001699 if (SelectDirectAddr(Op, Op0)) {
1700 OutOps.push_back(Op0);
1701 OutOps.push_back(CurDAG->getTargetConstant(0, MVT::i32));
1702 return false;
1703 }
1704 if (SelectADDRri(Op.getNode(), Op, Op0, Op1)) {
1705 OutOps.push_back(Op0);
1706 OutOps.push_back(Op1);
1707 return false;
1708 }
1709 break;
1710 }
1711 return true;
1712}
1713
1714// Return true if N is a undef or a constant.
1715// If N was undef, return a (i8imm 0) in Retval
1716// If N was imm, convert it to i8imm and return in Retval
1717// Note: The convert to i8imm is required, otherwise the
1718// pattern matcher inserts a bunch of IMOVi8rr to convert
1719// the imm to i8imm, and this causes instruction selection
1720// to fail.
Justin Holewinski3639ce22013-03-30 14:29:21 +00001721bool NVPTXDAGToDAGISel::UndefOrImm(SDValue Op, SDValue N, SDValue &Retval) {
1722 if (!(N.getOpcode() == ISD::UNDEF) && !(N.getOpcode() == ISD::Constant))
Justin Holewinski49683f32012-05-04 20:18:50 +00001723 return false;
1724
1725 if (N.getOpcode() == ISD::UNDEF)
1726 Retval = CurDAG->getTargetConstant(0, MVT::i8);
1727 else {
1728 ConstantSDNode *cn = cast<ConstantSDNode>(N.getNode());
1729 unsigned retval = cn->getZExtValue();
1730 Retval = CurDAG->getTargetConstant(retval, MVT::i8);
1731 }
1732 return true;
1733}