radeon/llvm: Remove AMDILTargetMachine
[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 // Include the pieces autogenerated from the target description.
71 #include "AMDILGenDAGISel.inc"
72 };
73 } // end anonymous namespace
74
75 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
76 // DAG, ready for instruction scheduling.
77 //
78 FunctionPass *llvm::createAMDILISelDag(TargetMachine &TM
79 AMDIL_OPT_LEVEL_DECL) {
80 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR);
81 }
82
83 AMDILDAGToDAGISel::AMDILDAGToDAGISel(TargetMachine &TM
84 AMDIL_OPT_LEVEL_DECL)
85 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR), Subtarget(TM.getSubtarget<AMDILSubtarget>())
86 {
87 }
88
89 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
90 }
91
92 SDValue AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
93 return CurDAG->getTargetConstant(Imm, MVT::i32);
94 }
95
96 bool AMDILDAGToDAGISel::SelectADDRParam(
97 SDValue Addr, SDValue& R1, SDValue& R2) {
98
99 if (Addr.getOpcode() == ISD::FrameIndex) {
100 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
101 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
102 R2 = CurDAG->getTargetConstant(0, MVT::i32);
103 } else {
104 R1 = Addr;
105 R2 = CurDAG->getTargetConstant(0, MVT::i32);
106 }
107 } else if (Addr.getOpcode() == ISD::ADD) {
108 R1 = Addr.getOperand(0);
109 R2 = Addr.getOperand(1);
110 } else {
111 R1 = Addr;
112 R2 = CurDAG->getTargetConstant(0, MVT::i32);
113 }
114 return true;
115 }
116
117 bool AMDILDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
118 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
119 Addr.getOpcode() == ISD::TargetGlobalAddress) {
120 return false;
121 }
122 return SelectADDRParam(Addr, R1, R2);
123 }
124
125
126 bool AMDILDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
127 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
128 Addr.getOpcode() == ISD::TargetGlobalAddress) {
129 return false;
130 }
131
132 if (Addr.getOpcode() == ISD::FrameIndex) {
133 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
134 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
135 R2 = CurDAG->getTargetConstant(0, MVT::i64);
136 } else {
137 R1 = Addr;
138 R2 = CurDAG->getTargetConstant(0, MVT::i64);
139 }
140 } else if (Addr.getOpcode() == ISD::ADD) {
141 R1 = Addr.getOperand(0);
142 R2 = Addr.getOperand(1);
143 } else {
144 R1 = Addr;
145 R2 = CurDAG->getTargetConstant(0, MVT::i64);
146 }
147 return true;
148 }
149
150 SDNode *AMDILDAGToDAGISel::Select(SDNode *N) {
151 unsigned int Opc = N->getOpcode();
152 if (N->isMachineOpcode()) {
153 return NULL; // Already selected.
154 }
155 switch (Opc) {
156 default: break;
157 case ISD::FrameIndex:
158 {
159 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
160 unsigned int FI = FIN->getIndex();
161 EVT OpVT = N->getValueType(0);
162 unsigned int NewOpc = AMDIL::MOVE_i32;
163 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
164 return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
165 }
166 }
167 break;
168 }
169 // For all atomic instructions, we need to add a constant
170 // operand that stores the resource ID in the instruction
171 if (Opc > AMDILISD::ADDADDR && Opc < AMDILISD::APPEND_ALLOC) {
172 N = xformAtomicInst(N);
173 }
174 return SelectCode(N);
175 }
176
177 bool AMDILDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) {
178 if (!ptr) {
179 return false;
180 }
181 Type *ptrType = ptr->getType();
182 return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace;
183 }
184
185 const Value * AMDILDAGToDAGISel::getBasePointerValue(const Value *V)
186 {
187 if (!V) {
188 return NULL;
189 }
190 const Value *ret = NULL;
191 ValueMap<const Value *, bool> ValueBitMap;
192 std::queue<const Value *, std::list<const Value *> > ValueQueue;
193 ValueQueue.push(V);
194 while (!ValueQueue.empty()) {
195 V = ValueQueue.front();
196 if (ValueBitMap.find(V) == ValueBitMap.end()) {
197 ValueBitMap[V] = true;
198 if (dyn_cast<Argument>(V) && dyn_cast<PointerType>(V->getType())) {
199 ret = V;
200 break;
201 } else if (dyn_cast<GlobalVariable>(V)) {
202 ret = V;
203 break;
204 } else if (dyn_cast<Constant>(V)) {
205 const ConstantExpr *CE = dyn_cast<ConstantExpr>(V);
206 if (CE) {
207 ValueQueue.push(CE->getOperand(0));
208 }
209 } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
210 ret = AI;
211 break;
212 } else if (const Instruction *I = dyn_cast<Instruction>(V)) {
213 uint32_t numOps = I->getNumOperands();
214 for (uint32_t x = 0; x < numOps; ++x) {
215 ValueQueue.push(I->getOperand(x));
216 }
217 } else {
218 // assert(0 && "Found a Value that we didn't know how to handle!");
219 }
220 }
221 ValueQueue.pop();
222 }
223 return ret;
224 }
225
226 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
227 return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
228 }
229
230 bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
231 return (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
232 && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
233 && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS));
234 }
235
236 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
237 return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
238 }
239
240 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
241 return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
242 }
243
244 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
245 if (checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)) {
246 return true;
247 }
248 MachineMemOperand *MMO = N->getMemOperand();
249 const Value *V = MMO->getValue();
250 const Value *BV = getBasePointerValue(V);
251 if (MMO
252 && MMO->getValue()
253 && ((V && dyn_cast<GlobalValue>(V))
254 || (BV && dyn_cast<GlobalValue>(
255 getBasePointerValue(MMO->getValue()))))) {
256 return checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS);
257 } else {
258 return false;
259 }
260 }
261
262 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
263 return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
264 }
265
266 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode *N) {
267 return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
268 }
269
270 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode *N) {
271 return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
272 }
273
274 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
275 MachineMemOperand *MMO = N->getMemOperand();
276 if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
277 if (MMO) {
278 const Value *V = MMO->getValue();
279 const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
280 if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
281 return true;
282 }
283 }
284 }
285 return false;
286 }
287
288 bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) {
289 if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
290 // Check to make sure we are not a constant pool load or a constant load
291 // that is marked as a private load
292 if (isCPLoad(N) || isConstantLoad(N, -1)) {
293 return false;
294 }
295 }
296 if (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
297 && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
298 && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS)
299 && !checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)
300 && !checkType(N->getSrcValue(), AMDILAS::PARAM_D_ADDRESS)
301 && !checkType(N->getSrcValue(), AMDILAS::PARAM_I_ADDRESS))
302 {
303 return true;
304 }
305 return false;
306 }
307
308 const char *AMDILDAGToDAGISel::getPassName() const {
309 return "AMDIL DAG->DAG Pattern Instruction Selection";
310 }
311
312 SDNode*
313 AMDILDAGToDAGISel::xformAtomicInst(SDNode *N)
314 {
315 uint32_t addVal = 1;
316 bool addOne = false;
317 // bool bitCastToInt = (N->getValueType(0) == MVT::f32);
318 unsigned opc = N->getOpcode();
319 switch (opc) {
320 default: return N;
321 case AMDILISD::ATOM_G_ADD:
322 case AMDILISD::ATOM_G_AND:
323 case AMDILISD::ATOM_G_MAX:
324 case AMDILISD::ATOM_G_UMAX:
325 case AMDILISD::ATOM_G_MIN:
326 case AMDILISD::ATOM_G_UMIN:
327 case AMDILISD::ATOM_G_OR:
328 case AMDILISD::ATOM_G_SUB:
329 case AMDILISD::ATOM_G_RSUB:
330 case AMDILISD::ATOM_G_XCHG:
331 case AMDILISD::ATOM_G_XOR:
332 case AMDILISD::ATOM_G_ADD_NORET:
333 case AMDILISD::ATOM_G_AND_NORET:
334 case AMDILISD::ATOM_G_MAX_NORET:
335 case AMDILISD::ATOM_G_UMAX_NORET:
336 case AMDILISD::ATOM_G_MIN_NORET:
337 case AMDILISD::ATOM_G_UMIN_NORET:
338 case AMDILISD::ATOM_G_OR_NORET:
339 case AMDILISD::ATOM_G_SUB_NORET:
340 case AMDILISD::ATOM_G_RSUB_NORET:
341 case AMDILISD::ATOM_G_XCHG_NORET:
342 case AMDILISD::ATOM_G_XOR_NORET:
343 case AMDILISD::ATOM_L_ADD:
344 case AMDILISD::ATOM_L_AND:
345 case AMDILISD::ATOM_L_MAX:
346 case AMDILISD::ATOM_L_UMAX:
347 case AMDILISD::ATOM_L_MIN:
348 case AMDILISD::ATOM_L_UMIN:
349 case AMDILISD::ATOM_L_OR:
350 case AMDILISD::ATOM_L_SUB:
351 case AMDILISD::ATOM_L_RSUB:
352 case AMDILISD::ATOM_L_XCHG:
353 case AMDILISD::ATOM_L_XOR:
354 case AMDILISD::ATOM_L_ADD_NORET:
355 case AMDILISD::ATOM_L_AND_NORET:
356 case AMDILISD::ATOM_L_MAX_NORET:
357 case AMDILISD::ATOM_L_UMAX_NORET:
358 case AMDILISD::ATOM_L_MIN_NORET:
359 case AMDILISD::ATOM_L_UMIN_NORET:
360 case AMDILISD::ATOM_L_OR_NORET:
361 case AMDILISD::ATOM_L_SUB_NORET:
362 case AMDILISD::ATOM_L_RSUB_NORET:
363 case AMDILISD::ATOM_L_XCHG_NORET:
364 case AMDILISD::ATOM_L_XOR_NORET:
365 case AMDILISD::ATOM_R_ADD:
366 case AMDILISD::ATOM_R_AND:
367 case AMDILISD::ATOM_R_MAX:
368 case AMDILISD::ATOM_R_UMAX:
369 case AMDILISD::ATOM_R_MIN:
370 case AMDILISD::ATOM_R_UMIN:
371 case AMDILISD::ATOM_R_OR:
372 case AMDILISD::ATOM_R_SUB:
373 case AMDILISD::ATOM_R_RSUB:
374 case AMDILISD::ATOM_R_XCHG:
375 case AMDILISD::ATOM_R_XOR:
376 case AMDILISD::ATOM_R_ADD_NORET:
377 case AMDILISD::ATOM_R_AND_NORET:
378 case AMDILISD::ATOM_R_MAX_NORET:
379 case AMDILISD::ATOM_R_UMAX_NORET:
380 case AMDILISD::ATOM_R_MIN_NORET:
381 case AMDILISD::ATOM_R_UMIN_NORET:
382 case AMDILISD::ATOM_R_OR_NORET:
383 case AMDILISD::ATOM_R_SUB_NORET:
384 case AMDILISD::ATOM_R_RSUB_NORET:
385 case AMDILISD::ATOM_R_XCHG_NORET:
386 case AMDILISD::ATOM_R_XOR_NORET:
387 case AMDILISD::ATOM_G_CMPXCHG:
388 case AMDILISD::ATOM_G_CMPXCHG_NORET:
389 case AMDILISD::ATOM_L_CMPXCHG:
390 case AMDILISD::ATOM_L_CMPXCHG_NORET:
391 case AMDILISD::ATOM_R_CMPXCHG:
392 case AMDILISD::ATOM_R_CMPXCHG_NORET:
393 break;
394 case AMDILISD::ATOM_G_DEC:
395 addOne = true;
396 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
397 addVal = (uint32_t)-1;
398 } else {
399 opc = AMDILISD::ATOM_G_SUB;
400 }
401 break;
402 case AMDILISD::ATOM_G_INC:
403 addOne = true;
404 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
405 addVal = (uint32_t)-1;
406 } else {
407 opc = AMDILISD::ATOM_G_ADD;
408 }
409 break;
410 case AMDILISD::ATOM_G_DEC_NORET:
411 addOne = true;
412 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
413 addVal = (uint32_t)-1;
414 } else {
415 opc = AMDILISD::ATOM_G_SUB_NORET;
416 }
417 break;
418 case AMDILISD::ATOM_G_INC_NORET:
419 addOne = true;
420 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
421 addVal = (uint32_t)-1;
422 } else {
423 opc = AMDILISD::ATOM_G_ADD_NORET;
424 }
425 break;
426 case AMDILISD::ATOM_L_DEC:
427 addOne = true;
428 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
429 addVal = (uint32_t)-1;
430 } else {
431 opc = AMDILISD::ATOM_L_SUB;
432 }
433 break;
434 case AMDILISD::ATOM_L_INC:
435 addOne = true;
436 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
437 addVal = (uint32_t)-1;
438 } else {
439 opc = AMDILISD::ATOM_L_ADD;
440 }
441 break;
442 case AMDILISD::ATOM_L_DEC_NORET:
443 addOne = true;
444 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
445 addVal = (uint32_t)-1;
446 } else {
447 opc = AMDILISD::ATOM_L_SUB_NORET;
448 }
449 break;
450 case AMDILISD::ATOM_L_INC_NORET:
451 addOne = true;
452 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
453 addVal = (uint32_t)-1;
454 } else {
455 opc = AMDILISD::ATOM_L_ADD_NORET;
456 }
457 break;
458 case AMDILISD::ATOM_R_DEC:
459 addOne = true;
460 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
461 addVal = (uint32_t)-1;
462 } else {
463 opc = AMDILISD::ATOM_R_SUB;
464 }
465 break;
466 case AMDILISD::ATOM_R_INC:
467 addOne = true;
468 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
469 addVal = (uint32_t)-1;
470 } else {
471 opc = AMDILISD::ATOM_R_ADD;
472 }
473 break;
474 case AMDILISD::ATOM_R_DEC_NORET:
475 addOne = true;
476 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
477 addVal = (uint32_t)-1;
478 } else {
479 opc = AMDILISD::ATOM_R_SUB;
480 }
481 break;
482 case AMDILISD::ATOM_R_INC_NORET:
483 addOne = true;
484 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
485 addVal = (uint32_t)-1;
486 } else {
487 opc = AMDILISD::ATOM_R_ADD_NORET;
488 }
489 break;
490 }
491 // The largest we can have is a cmpxchg w/ a return value and an output chain.
492 // The cmpxchg function has 3 inputs and a single output along with an
493 // output change and a target constant, giving a total of 6.
494 SDValue Ops[12];
495 unsigned x = 0;
496 unsigned y = N->getNumOperands();
497 for (x = 0; x < y; ++x) {
498 Ops[x] = N->getOperand(x);
499 }
500 if (addOne) {
501 Ops[x++] = SDValue(SelectCode(CurDAG->getConstant(addVal, MVT::i32).getNode()), 0);
502 }
503 Ops[x++] = CurDAG->getTargetConstant(0, MVT::i32);
504 SDVTList Tys = N->getVTList();
505 MemSDNode *MemNode = dyn_cast<MemSDNode>(N);
506 assert(MemNode && "Atomic should be of MemSDNode type!");
507 N = CurDAG->getMemIntrinsicNode(opc, N->getDebugLoc(), Tys, Ops, x,
508 MemNode->getMemoryVT(), MemNode->getMemOperand()).getNode();
509 return N;
510 }
511
512 #ifdef DEBUGTMP
513 #undef INT64_C
514 #endif
515 #undef DEBUGTMP