radeon/llvm: Remove AMDIL MOVE* instructions
[mesa.git] / src / gallium / drivers / radeon / AMDILISelDAGToDAG.cpp
1 //===-- AMDILISelDAGToDAG.cpp - A dag to dag inst selector for AMDIL ------===//
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 AMDIL target.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "AMDGPUISelLowering.h" // For AMDGPUISD
14 #include "AMDILDevices.h"
15 #include "AMDILUtilityFunctions.h"
16 #include "llvm/ADT/ValueMap.h"
17 #include "llvm/CodeGen/PseudoSourceValue.h"
18 #include "llvm/CodeGen/SelectionDAGISel.h"
19 #include "llvm/Support/Compiler.h"
20 #include <list>
21 #include <queue>
22
23 using namespace llvm;
24
25 //===----------------------------------------------------------------------===//
26 // Instruction Selector Implementation
27 //===----------------------------------------------------------------------===//
28
29 //===----------------------------------------------------------------------===//
30 // AMDILDAGToDAGISel - AMDIL specific code to select AMDIL machine instructions
31 // //for SelectionDAG operations.
32 //
33 namespace {
34 class AMDILDAGToDAGISel : public SelectionDAGISel {
35 // Subtarget - Keep a pointer to the AMDIL Subtarget around so that we can
36 // make the right decision when generating code for different targets.
37 const AMDILSubtarget &Subtarget;
38 public:
39 AMDILDAGToDAGISel(TargetMachine &TM AMDIL_OPT_LEVEL_DECL);
40 virtual ~AMDILDAGToDAGISel();
41
42 SDNode *Select(SDNode *N);
43 virtual const char *getPassName() const;
44
45 private:
46 inline SDValue getSmallIPtrImm(unsigned Imm);
47
48 // Complex pattern selectors
49 bool SelectADDRParam(SDValue Addr, SDValue& R1, SDValue& R2);
50 bool SelectADDR(SDValue N, SDValue &R1, SDValue &R2);
51 bool SelectADDR64(SDValue N, SDValue &R1, SDValue &R2);
52
53 static bool checkType(const Value *ptr, unsigned int addrspace);
54 static const Value *getBasePointerValue(const Value *V);
55
56 static bool isGlobalStore(const StoreSDNode *N);
57 static bool isPrivateStore(const StoreSDNode *N);
58 static bool isLocalStore(const StoreSDNode *N);
59 static bool isRegionStore(const StoreSDNode *N);
60
61 static bool isCPLoad(const LoadSDNode *N);
62 static bool isConstantLoad(const LoadSDNode *N, int cbID);
63 static bool isGlobalLoad(const LoadSDNode *N);
64 static bool isPrivateLoad(const LoadSDNode *N);
65 static bool isLocalLoad(const LoadSDNode *N);
66 static bool isRegionLoad(const LoadSDNode *N);
67
68 SDNode *xformAtomicInst(SDNode *N);
69
70 bool SelectADDR8BitOffset(SDValue Addr, SDValue& Base, SDValue& Offset);
71 bool SelectADDRReg(SDValue Addr, SDValue& Base, SDValue& Offset);
72 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
73
74 // Include the pieces autogenerated from the target description.
75 #include "AMDGPUGenDAGISel.inc"
76 };
77 } // end anonymous namespace
78
79 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
80 // DAG, ready for instruction scheduling.
81 //
82 FunctionPass *llvm::createAMDILISelDag(TargetMachine &TM
83 AMDIL_OPT_LEVEL_DECL) {
84 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR);
85 }
86
87 AMDILDAGToDAGISel::AMDILDAGToDAGISel(TargetMachine &TM
88 AMDIL_OPT_LEVEL_DECL)
89 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR), Subtarget(TM.getSubtarget<AMDILSubtarget>())
90 {
91 }
92
93 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
94 }
95
96 SDValue AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
97 return CurDAG->getTargetConstant(Imm, MVT::i32);
98 }
99
100 bool AMDILDAGToDAGISel::SelectADDRParam(
101 SDValue Addr, SDValue& R1, SDValue& R2) {
102
103 if (Addr.getOpcode() == ISD::FrameIndex) {
104 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
105 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
106 R2 = CurDAG->getTargetConstant(0, MVT::i32);
107 } else {
108 R1 = Addr;
109 R2 = CurDAG->getTargetConstant(0, MVT::i32);
110 }
111 } else if (Addr.getOpcode() == ISD::ADD) {
112 R1 = Addr.getOperand(0);
113 R2 = Addr.getOperand(1);
114 } else {
115 R1 = Addr;
116 R2 = CurDAG->getTargetConstant(0, MVT::i32);
117 }
118 return true;
119 }
120
121 bool AMDILDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
122 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
123 Addr.getOpcode() == ISD::TargetGlobalAddress) {
124 return false;
125 }
126 return SelectADDRParam(Addr, R1, R2);
127 }
128
129
130 bool AMDILDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
131 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
132 Addr.getOpcode() == ISD::TargetGlobalAddress) {
133 return false;
134 }
135
136 if (Addr.getOpcode() == ISD::FrameIndex) {
137 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
138 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
139 R2 = CurDAG->getTargetConstant(0, MVT::i64);
140 } else {
141 R1 = Addr;
142 R2 = CurDAG->getTargetConstant(0, MVT::i64);
143 }
144 } else if (Addr.getOpcode() == ISD::ADD) {
145 R1 = Addr.getOperand(0);
146 R2 = Addr.getOperand(1);
147 } else {
148 R1 = Addr;
149 R2 = CurDAG->getTargetConstant(0, MVT::i64);
150 }
151 return true;
152 }
153
154 SDNode *AMDILDAGToDAGISel::Select(SDNode *N) {
155 unsigned int Opc = N->getOpcode();
156 if (N->isMachineOpcode()) {
157 return NULL; // Already selected.
158 }
159 switch (Opc) {
160 default: break;
161 case ISD::FrameIndex:
162 {
163 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
164 unsigned int FI = FIN->getIndex();
165 EVT OpVT = N->getValueType(0);
166 unsigned int NewOpc = AMDIL::COPY;
167 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
168 return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
169 }
170 }
171 break;
172 }
173 // For all atomic instructions, we need to add a constant
174 // operand that stores the resource ID in the instruction
175 if (Opc > AMDILISD::ADDADDR && Opc < AMDILISD::APPEND_ALLOC) {
176 N = xformAtomicInst(N);
177 }
178 return SelectCode(N);
179 }
180
181 bool AMDILDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) {
182 if (!ptr) {
183 return false;
184 }
185 Type *ptrType = ptr->getType();
186 return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace;
187 }
188
189 const Value * AMDILDAGToDAGISel::getBasePointerValue(const Value *V)
190 {
191 if (!V) {
192 return NULL;
193 }
194 const Value *ret = NULL;
195 ValueMap<const Value *, bool> ValueBitMap;
196 std::queue<const Value *, std::list<const Value *> > ValueQueue;
197 ValueQueue.push(V);
198 while (!ValueQueue.empty()) {
199 V = ValueQueue.front();
200 if (ValueBitMap.find(V) == ValueBitMap.end()) {
201 ValueBitMap[V] = true;
202 if (dyn_cast<Argument>(V) && dyn_cast<PointerType>(V->getType())) {
203 ret = V;
204 break;
205 } else if (dyn_cast<GlobalVariable>(V)) {
206 ret = V;
207 break;
208 } else if (dyn_cast<Constant>(V)) {
209 const ConstantExpr *CE = dyn_cast<ConstantExpr>(V);
210 if (CE) {
211 ValueQueue.push(CE->getOperand(0));
212 }
213 } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
214 ret = AI;
215 break;
216 } else if (const Instruction *I = dyn_cast<Instruction>(V)) {
217 uint32_t numOps = I->getNumOperands();
218 for (uint32_t x = 0; x < numOps; ++x) {
219 ValueQueue.push(I->getOperand(x));
220 }
221 } else {
222 // assert(0 && "Found a Value that we didn't know how to handle!");
223 }
224 }
225 ValueQueue.pop();
226 }
227 return ret;
228 }
229
230 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
231 return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
232 }
233
234 bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
235 return (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
236 && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
237 && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS));
238 }
239
240 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
241 return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
242 }
243
244 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
245 return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
246 }
247
248 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
249 if (checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)) {
250 return true;
251 }
252 MachineMemOperand *MMO = N->getMemOperand();
253 const Value *V = MMO->getValue();
254 const Value *BV = getBasePointerValue(V);
255 if (MMO
256 && MMO->getValue()
257 && ((V && dyn_cast<GlobalValue>(V))
258 || (BV && dyn_cast<GlobalValue>(
259 getBasePointerValue(MMO->getValue()))))) {
260 return checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS);
261 } else {
262 return false;
263 }
264 }
265
266 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
267 return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
268 }
269
270 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode *N) {
271 return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
272 }
273
274 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode *N) {
275 return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
276 }
277
278 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
279 MachineMemOperand *MMO = N->getMemOperand();
280 if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
281 if (MMO) {
282 const Value *V = MMO->getValue();
283 const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
284 if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
285 return true;
286 }
287 }
288 }
289 return false;
290 }
291
292 bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) {
293 if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
294 // Check to make sure we are not a constant pool load or a constant load
295 // that is marked as a private load
296 if (isCPLoad(N) || isConstantLoad(N, -1)) {
297 return false;
298 }
299 }
300 if (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
301 && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
302 && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS)
303 && !checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)
304 && !checkType(N->getSrcValue(), AMDILAS::PARAM_D_ADDRESS)
305 && !checkType(N->getSrcValue(), AMDILAS::PARAM_I_ADDRESS))
306 {
307 return true;
308 }
309 return false;
310 }
311
312 const char *AMDILDAGToDAGISel::getPassName() const {
313 return "AMDIL DAG->DAG Pattern Instruction Selection";
314 }
315
316 SDNode*
317 AMDILDAGToDAGISel::xformAtomicInst(SDNode *N)
318 {
319 uint32_t addVal = 1;
320 bool addOne = false;
321 // bool bitCastToInt = (N->getValueType(0) == MVT::f32);
322 unsigned opc = N->getOpcode();
323 switch (opc) {
324 default: return N;
325 case AMDILISD::ATOM_G_ADD:
326 case AMDILISD::ATOM_G_AND:
327 case AMDILISD::ATOM_G_MAX:
328 case AMDILISD::ATOM_G_UMAX:
329 case AMDILISD::ATOM_G_MIN:
330 case AMDILISD::ATOM_G_UMIN:
331 case AMDILISD::ATOM_G_OR:
332 case AMDILISD::ATOM_G_SUB:
333 case AMDILISD::ATOM_G_RSUB:
334 case AMDILISD::ATOM_G_XCHG:
335 case AMDILISD::ATOM_G_XOR:
336 case AMDILISD::ATOM_G_ADD_NORET:
337 case AMDILISD::ATOM_G_AND_NORET:
338 case AMDILISD::ATOM_G_MAX_NORET:
339 case AMDILISD::ATOM_G_UMAX_NORET:
340 case AMDILISD::ATOM_G_MIN_NORET:
341 case AMDILISD::ATOM_G_UMIN_NORET:
342 case AMDILISD::ATOM_G_OR_NORET:
343 case AMDILISD::ATOM_G_SUB_NORET:
344 case AMDILISD::ATOM_G_RSUB_NORET:
345 case AMDILISD::ATOM_G_XCHG_NORET:
346 case AMDILISD::ATOM_G_XOR_NORET:
347 case AMDILISD::ATOM_L_ADD:
348 case AMDILISD::ATOM_L_AND:
349 case AMDILISD::ATOM_L_MAX:
350 case AMDILISD::ATOM_L_UMAX:
351 case AMDILISD::ATOM_L_MIN:
352 case AMDILISD::ATOM_L_UMIN:
353 case AMDILISD::ATOM_L_OR:
354 case AMDILISD::ATOM_L_SUB:
355 case AMDILISD::ATOM_L_RSUB:
356 case AMDILISD::ATOM_L_XCHG:
357 case AMDILISD::ATOM_L_XOR:
358 case AMDILISD::ATOM_L_ADD_NORET:
359 case AMDILISD::ATOM_L_AND_NORET:
360 case AMDILISD::ATOM_L_MAX_NORET:
361 case AMDILISD::ATOM_L_UMAX_NORET:
362 case AMDILISD::ATOM_L_MIN_NORET:
363 case AMDILISD::ATOM_L_UMIN_NORET:
364 case AMDILISD::ATOM_L_OR_NORET:
365 case AMDILISD::ATOM_L_SUB_NORET:
366 case AMDILISD::ATOM_L_RSUB_NORET:
367 case AMDILISD::ATOM_L_XCHG_NORET:
368 case AMDILISD::ATOM_L_XOR_NORET:
369 case AMDILISD::ATOM_R_ADD:
370 case AMDILISD::ATOM_R_AND:
371 case AMDILISD::ATOM_R_MAX:
372 case AMDILISD::ATOM_R_UMAX:
373 case AMDILISD::ATOM_R_MIN:
374 case AMDILISD::ATOM_R_UMIN:
375 case AMDILISD::ATOM_R_OR:
376 case AMDILISD::ATOM_R_SUB:
377 case AMDILISD::ATOM_R_RSUB:
378 case AMDILISD::ATOM_R_XCHG:
379 case AMDILISD::ATOM_R_XOR:
380 case AMDILISD::ATOM_R_ADD_NORET:
381 case AMDILISD::ATOM_R_AND_NORET:
382 case AMDILISD::ATOM_R_MAX_NORET:
383 case AMDILISD::ATOM_R_UMAX_NORET:
384 case AMDILISD::ATOM_R_MIN_NORET:
385 case AMDILISD::ATOM_R_UMIN_NORET:
386 case AMDILISD::ATOM_R_OR_NORET:
387 case AMDILISD::ATOM_R_SUB_NORET:
388 case AMDILISD::ATOM_R_RSUB_NORET:
389 case AMDILISD::ATOM_R_XCHG_NORET:
390 case AMDILISD::ATOM_R_XOR_NORET:
391 case AMDILISD::ATOM_G_CMPXCHG:
392 case AMDILISD::ATOM_G_CMPXCHG_NORET:
393 case AMDILISD::ATOM_L_CMPXCHG:
394 case AMDILISD::ATOM_L_CMPXCHG_NORET:
395 case AMDILISD::ATOM_R_CMPXCHG:
396 case AMDILISD::ATOM_R_CMPXCHG_NORET:
397 break;
398 case AMDILISD::ATOM_G_DEC:
399 addOne = true;
400 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
401 addVal = (uint32_t)-1;
402 } else {
403 opc = AMDILISD::ATOM_G_SUB;
404 }
405 break;
406 case AMDILISD::ATOM_G_INC:
407 addOne = true;
408 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
409 addVal = (uint32_t)-1;
410 } else {
411 opc = AMDILISD::ATOM_G_ADD;
412 }
413 break;
414 case AMDILISD::ATOM_G_DEC_NORET:
415 addOne = true;
416 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
417 addVal = (uint32_t)-1;
418 } else {
419 opc = AMDILISD::ATOM_G_SUB_NORET;
420 }
421 break;
422 case AMDILISD::ATOM_G_INC_NORET:
423 addOne = true;
424 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
425 addVal = (uint32_t)-1;
426 } else {
427 opc = AMDILISD::ATOM_G_ADD_NORET;
428 }
429 break;
430 case AMDILISD::ATOM_L_DEC:
431 addOne = true;
432 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
433 addVal = (uint32_t)-1;
434 } else {
435 opc = AMDILISD::ATOM_L_SUB;
436 }
437 break;
438 case AMDILISD::ATOM_L_INC:
439 addOne = true;
440 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
441 addVal = (uint32_t)-1;
442 } else {
443 opc = AMDILISD::ATOM_L_ADD;
444 }
445 break;
446 case AMDILISD::ATOM_L_DEC_NORET:
447 addOne = true;
448 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
449 addVal = (uint32_t)-1;
450 } else {
451 opc = AMDILISD::ATOM_L_SUB_NORET;
452 }
453 break;
454 case AMDILISD::ATOM_L_INC_NORET:
455 addOne = true;
456 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
457 addVal = (uint32_t)-1;
458 } else {
459 opc = AMDILISD::ATOM_L_ADD_NORET;
460 }
461 break;
462 case AMDILISD::ATOM_R_DEC:
463 addOne = true;
464 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
465 addVal = (uint32_t)-1;
466 } else {
467 opc = AMDILISD::ATOM_R_SUB;
468 }
469 break;
470 case AMDILISD::ATOM_R_INC:
471 addOne = true;
472 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
473 addVal = (uint32_t)-1;
474 } else {
475 opc = AMDILISD::ATOM_R_ADD;
476 }
477 break;
478 case AMDILISD::ATOM_R_DEC_NORET:
479 addOne = true;
480 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
481 addVal = (uint32_t)-1;
482 } else {
483 opc = AMDILISD::ATOM_R_SUB;
484 }
485 break;
486 case AMDILISD::ATOM_R_INC_NORET:
487 addOne = true;
488 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
489 addVal = (uint32_t)-1;
490 } else {
491 opc = AMDILISD::ATOM_R_ADD_NORET;
492 }
493 break;
494 }
495 // The largest we can have is a cmpxchg w/ a return value and an output chain.
496 // The cmpxchg function has 3 inputs and a single output along with an
497 // output change and a target constant, giving a total of 6.
498 SDValue Ops[12];
499 unsigned x = 0;
500 unsigned y = N->getNumOperands();
501 for (x = 0; x < y; ++x) {
502 Ops[x] = N->getOperand(x);
503 }
504 if (addOne) {
505 Ops[x++] = SDValue(SelectCode(CurDAG->getConstant(addVal, MVT::i32).getNode()), 0);
506 }
507 Ops[x++] = CurDAG->getTargetConstant(0, MVT::i32);
508 SDVTList Tys = N->getVTList();
509 MemSDNode *MemNode = dyn_cast<MemSDNode>(N);
510 assert(MemNode && "Atomic should be of MemSDNode type!");
511 N = CurDAG->getMemIntrinsicNode(opc, N->getDebugLoc(), Tys, Ops, x,
512 MemNode->getMemoryVT(), MemNode->getMemOperand()).getNode();
513 return N;
514 }
515
516 #ifdef DEBUGTMP
517 #undef INT64_C
518 #endif
519 #undef DEBUGTMP
520
521 ///==== AMDGPU Functions ====///
522
523 bool AMDILDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
524 SDValue& Offset) {
525 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
526 Addr.getOpcode() == ISD::TargetGlobalAddress) {
527 return false;
528 }
529
530
531 if (Addr.getOpcode() == ISD::ADD) {
532 bool Match = false;
533
534 // Find the base ptr and the offset
535 for (unsigned i = 0; i < Addr.getNumOperands(); i++) {
536 SDValue Arg = Addr.getOperand(i);
537 ConstantSDNode * OffsetNode = dyn_cast<ConstantSDNode>(Arg);
538 // This arg isn't a constant so it must be the base PTR.
539 if (!OffsetNode) {
540 Base = Addr.getOperand(i);
541 continue;
542 }
543 // Check if the constant argument fits in 8-bits. The offset is in bytes
544 // so we need to convert it to dwords.
545 if (isInt<8>(OffsetNode->getZExtValue() >> 2)) {
546 Match = true;
547 Offset = CurDAG->getTargetConstant(OffsetNode->getZExtValue() >> 2,
548 MVT::i32);
549 }
550 }
551 return Match;
552 }
553
554 // Default case, no offset
555 Base = Addr;
556 Offset = CurDAG->getTargetConstant(0, MVT::i32);
557 return true;
558 }
559
560 bool AMDILDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
561 SDValue &Offset)
562 {
563 ConstantSDNode * IMMOffset;
564
565 if (Addr.getOpcode() == ISD::ADD
566 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
567 && isInt<16>(IMMOffset->getZExtValue())) {
568
569 Base = Addr.getOperand(0);
570 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
571 return true;
572 // If the pointer address is constant, we can move it to the offset field.
573 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
574 && isInt<16>(IMMOffset->getZExtValue())) {
575 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
576 CurDAG->getEntryNode().getDebugLoc(),
577 AMDIL::ZERO, MVT::i32);
578 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
579 return true;
580 }
581
582 // Default case, no offset
583 Base = Addr;
584 Offset = CurDAG->getTargetConstant(0, MVT::i32);
585 return true;
586 }
587
588 bool AMDILDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
589 SDValue& Offset) {
590 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
591 Addr.getOpcode() == ISD::TargetGlobalAddress ||
592 Addr.getOpcode() != ISD::ADD) {
593 return false;
594 }
595
596 Base = Addr.getOperand(0);
597 Offset = Addr.getOperand(1);
598
599 return false;
600 }