r600g/llvm: Remove unnecessary dynamic casts
[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 "AMDILDevices.h"
14 #include "AMDILTargetMachine.h"
15 #include "AMDILUtilityFunctions.h"
16 #include "llvm/CodeGen/PseudoSourceValue.h"
17 #include "llvm/CodeGen/SelectionDAGISel.h"
18 #include "llvm/Support/Compiler.h"
19
20 using namespace llvm;
21
22 //===----------------------------------------------------------------------===//
23 // Instruction Selector Implementation
24 //===----------------------------------------------------------------------===//
25
26 //===----------------------------------------------------------------------===//
27 // AMDILDAGToDAGISel - AMDIL specific code to select AMDIL machine instructions
28 // //for SelectionDAG operations.
29 //
30 namespace {
31 class AMDILDAGToDAGISel : public SelectionDAGISel {
32 // Subtarget - Keep a pointer to the AMDIL Subtarget around so that we can
33 // make the right decision when generating code for different targets.
34 const AMDILSubtarget &Subtarget;
35 public:
36 AMDILDAGToDAGISel(AMDILTargetMachine &TM AMDIL_OPT_LEVEL_DECL);
37 virtual ~AMDILDAGToDAGISel();
38 inline SDValue getSmallIPtrImm(unsigned Imm);
39
40 SDNode *Select(SDNode *N);
41 // Complex pattern selectors
42 bool SelectADDRParam(SDValue Addr, SDValue& R1, SDValue& R2);
43 bool SelectADDR(SDValue N, SDValue &R1, SDValue &R2);
44 bool SelectADDR64(SDValue N, SDValue &R1, SDValue &R2);
45 static bool isGlobalStore(const StoreSDNode *N);
46 static bool isPrivateStore(const StoreSDNode *N);
47 static bool isLocalStore(const StoreSDNode *N);
48 static bool isRegionStore(const StoreSDNode *N);
49
50 static bool isCPLoad(const LoadSDNode *N);
51 static bool isConstantLoad(const LoadSDNode *N, int cbID);
52 static bool isGlobalLoad(const LoadSDNode *N);
53 static bool isPrivateLoad(const LoadSDNode *N);
54 static bool isLocalLoad(const LoadSDNode *N);
55 static bool isRegionLoad(const LoadSDNode *N);
56
57 virtual const char *getPassName() const;
58 private:
59 SDNode *xformAtomicInst(SDNode *N);
60
61 // Include the pieces autogenerated from the target description.
62 #include "AMDILGenDAGISel.inc"
63 };
64 } // end anonymous namespace
65
66 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
67 // DAG, ready for instruction scheduling.
68 //
69 FunctionPass *llvm::createAMDILISelDag(AMDILTargetMachine &TM
70 AMDIL_OPT_LEVEL_DECL) {
71 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR);
72 }
73
74 AMDILDAGToDAGISel::AMDILDAGToDAGISel(AMDILTargetMachine &TM
75 AMDIL_OPT_LEVEL_DECL)
76 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR), Subtarget(TM.getSubtarget<AMDILSubtarget>())
77 {
78 }
79
80 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
81 }
82
83 SDValue AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
84 return CurDAG->getTargetConstant(Imm, MVT::i32);
85 }
86
87 bool AMDILDAGToDAGISel::SelectADDRParam(
88 SDValue Addr, SDValue& R1, SDValue& R2) {
89
90 if (Addr.getOpcode() == ISD::FrameIndex) {
91 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
92 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
93 R2 = CurDAG->getTargetConstant(0, MVT::i32);
94 } else {
95 R1 = Addr;
96 R2 = CurDAG->getTargetConstant(0, MVT::i32);
97 }
98 } else if (Addr.getOpcode() == ISD::ADD) {
99 R1 = Addr.getOperand(0);
100 R2 = Addr.getOperand(1);
101 } else {
102 R1 = Addr;
103 R2 = CurDAG->getTargetConstant(0, MVT::i32);
104 }
105 return true;
106 }
107
108 bool AMDILDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
109 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
110 Addr.getOpcode() == ISD::TargetGlobalAddress) {
111 return false;
112 }
113 return SelectADDRParam(Addr, R1, R2);
114 }
115
116
117 bool AMDILDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
118 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
119 Addr.getOpcode() == ISD::TargetGlobalAddress) {
120 return false;
121 }
122
123 if (Addr.getOpcode() == ISD::FrameIndex) {
124 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
125 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
126 R2 = CurDAG->getTargetConstant(0, MVT::i64);
127 } else {
128 R1 = Addr;
129 R2 = CurDAG->getTargetConstant(0, MVT::i64);
130 }
131 } else if (Addr.getOpcode() == ISD::ADD) {
132 R1 = Addr.getOperand(0);
133 R2 = Addr.getOperand(1);
134 } else {
135 R1 = Addr;
136 R2 = CurDAG->getTargetConstant(0, MVT::i64);
137 }
138 return true;
139 }
140
141 SDNode *AMDILDAGToDAGISel::Select(SDNode *N) {
142 unsigned int Opc = N->getOpcode();
143 if (N->isMachineOpcode()) {
144 return NULL; // Already selected.
145 }
146 switch (Opc) {
147 default: break;
148 case ISD::FrameIndex:
149 {
150 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
151 unsigned int FI = FIN->getIndex();
152 EVT OpVT = N->getValueType(0);
153 unsigned int NewOpc = AMDIL::MOVE_i32;
154 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
155 return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
156 }
157 }
158 break;
159 }
160 // For all atomic instructions, we need to add a constant
161 // operand that stores the resource ID in the instruction
162 if (Opc > AMDILISD::ADDADDR && Opc < AMDILISD::APPEND_ALLOC) {
163 N = xformAtomicInst(N);
164 }
165 return SelectCode(N);
166 }
167
168 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
169 return check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
170 }
171
172 bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
173 return (!check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
174 && !check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
175 && !check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS));
176 }
177
178 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
179 return check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
180 }
181
182 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
183 return check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
184 }
185
186 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
187 if (check_type(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)) {
188 return true;
189 }
190 MachineMemOperand *MMO = N->getMemOperand();
191 const Value *V = MMO->getValue();
192 const Value *BV = getBasePointerValue(V);
193 if (MMO
194 && MMO->getValue()
195 && ((V && dyn_cast<GlobalValue>(V))
196 || (BV && dyn_cast<GlobalValue>(
197 getBasePointerValue(MMO->getValue()))))) {
198 return check_type(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS);
199 } else {
200 return false;
201 }
202 }
203
204 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
205 return check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
206 }
207
208 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode *N) {
209 return check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
210 }
211
212 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode *N) {
213 return check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
214 }
215
216 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
217 MachineMemOperand *MMO = N->getMemOperand();
218 if (check_type(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
219 if (MMO) {
220 const Value *V = MMO->getValue();
221 const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
222 if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
223 return true;
224 }
225 }
226 }
227 return false;
228 }
229
230 bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) {
231 if (check_type(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
232 // Check to make sure we are not a constant pool load or a constant load
233 // that is marked as a private load
234 if (isCPLoad(N) || isConstantLoad(N, -1)) {
235 return false;
236 }
237 }
238 if (!check_type(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
239 && !check_type(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
240 && !check_type(N->getSrcValue(), AMDILAS::REGION_ADDRESS)
241 && !check_type(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)
242 && !check_type(N->getSrcValue(), AMDILAS::PARAM_D_ADDRESS)
243 && !check_type(N->getSrcValue(), AMDILAS::PARAM_I_ADDRESS))
244 {
245 return true;
246 }
247 return false;
248 }
249
250 const char *AMDILDAGToDAGISel::getPassName() const {
251 return "AMDIL DAG->DAG Pattern Instruction Selection";
252 }
253
254 SDNode*
255 AMDILDAGToDAGISel::xformAtomicInst(SDNode *N)
256 {
257 uint32_t addVal = 1;
258 bool addOne = false;
259 // bool bitCastToInt = (N->getValueType(0) == MVT::f32);
260 unsigned opc = N->getOpcode();
261 switch (opc) {
262 default: return N;
263 case AMDILISD::ATOM_G_ADD:
264 case AMDILISD::ATOM_G_AND:
265 case AMDILISD::ATOM_G_MAX:
266 case AMDILISD::ATOM_G_UMAX:
267 case AMDILISD::ATOM_G_MIN:
268 case AMDILISD::ATOM_G_UMIN:
269 case AMDILISD::ATOM_G_OR:
270 case AMDILISD::ATOM_G_SUB:
271 case AMDILISD::ATOM_G_RSUB:
272 case AMDILISD::ATOM_G_XCHG:
273 case AMDILISD::ATOM_G_XOR:
274 case AMDILISD::ATOM_G_ADD_NORET:
275 case AMDILISD::ATOM_G_AND_NORET:
276 case AMDILISD::ATOM_G_MAX_NORET:
277 case AMDILISD::ATOM_G_UMAX_NORET:
278 case AMDILISD::ATOM_G_MIN_NORET:
279 case AMDILISD::ATOM_G_UMIN_NORET:
280 case AMDILISD::ATOM_G_OR_NORET:
281 case AMDILISD::ATOM_G_SUB_NORET:
282 case AMDILISD::ATOM_G_RSUB_NORET:
283 case AMDILISD::ATOM_G_XCHG_NORET:
284 case AMDILISD::ATOM_G_XOR_NORET:
285 case AMDILISD::ATOM_L_ADD:
286 case AMDILISD::ATOM_L_AND:
287 case AMDILISD::ATOM_L_MAX:
288 case AMDILISD::ATOM_L_UMAX:
289 case AMDILISD::ATOM_L_MIN:
290 case AMDILISD::ATOM_L_UMIN:
291 case AMDILISD::ATOM_L_OR:
292 case AMDILISD::ATOM_L_SUB:
293 case AMDILISD::ATOM_L_RSUB:
294 case AMDILISD::ATOM_L_XCHG:
295 case AMDILISD::ATOM_L_XOR:
296 case AMDILISD::ATOM_L_ADD_NORET:
297 case AMDILISD::ATOM_L_AND_NORET:
298 case AMDILISD::ATOM_L_MAX_NORET:
299 case AMDILISD::ATOM_L_UMAX_NORET:
300 case AMDILISD::ATOM_L_MIN_NORET:
301 case AMDILISD::ATOM_L_UMIN_NORET:
302 case AMDILISD::ATOM_L_OR_NORET:
303 case AMDILISD::ATOM_L_SUB_NORET:
304 case AMDILISD::ATOM_L_RSUB_NORET:
305 case AMDILISD::ATOM_L_XCHG_NORET:
306 case AMDILISD::ATOM_L_XOR_NORET:
307 case AMDILISD::ATOM_R_ADD:
308 case AMDILISD::ATOM_R_AND:
309 case AMDILISD::ATOM_R_MAX:
310 case AMDILISD::ATOM_R_UMAX:
311 case AMDILISD::ATOM_R_MIN:
312 case AMDILISD::ATOM_R_UMIN:
313 case AMDILISD::ATOM_R_OR:
314 case AMDILISD::ATOM_R_SUB:
315 case AMDILISD::ATOM_R_RSUB:
316 case AMDILISD::ATOM_R_XCHG:
317 case AMDILISD::ATOM_R_XOR:
318 case AMDILISD::ATOM_R_ADD_NORET:
319 case AMDILISD::ATOM_R_AND_NORET:
320 case AMDILISD::ATOM_R_MAX_NORET:
321 case AMDILISD::ATOM_R_UMAX_NORET:
322 case AMDILISD::ATOM_R_MIN_NORET:
323 case AMDILISD::ATOM_R_UMIN_NORET:
324 case AMDILISD::ATOM_R_OR_NORET:
325 case AMDILISD::ATOM_R_SUB_NORET:
326 case AMDILISD::ATOM_R_RSUB_NORET:
327 case AMDILISD::ATOM_R_XCHG_NORET:
328 case AMDILISD::ATOM_R_XOR_NORET:
329 case AMDILISD::ATOM_G_CMPXCHG:
330 case AMDILISD::ATOM_G_CMPXCHG_NORET:
331 case AMDILISD::ATOM_L_CMPXCHG:
332 case AMDILISD::ATOM_L_CMPXCHG_NORET:
333 case AMDILISD::ATOM_R_CMPXCHG:
334 case AMDILISD::ATOM_R_CMPXCHG_NORET:
335 break;
336 case AMDILISD::ATOM_G_DEC:
337 addOne = true;
338 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
339 addVal = (uint32_t)-1;
340 } else {
341 opc = AMDILISD::ATOM_G_SUB;
342 }
343 break;
344 case AMDILISD::ATOM_G_INC:
345 addOne = true;
346 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
347 addVal = (uint32_t)-1;
348 } else {
349 opc = AMDILISD::ATOM_G_ADD;
350 }
351 break;
352 case AMDILISD::ATOM_G_DEC_NORET:
353 addOne = true;
354 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
355 addVal = (uint32_t)-1;
356 } else {
357 opc = AMDILISD::ATOM_G_SUB_NORET;
358 }
359 break;
360 case AMDILISD::ATOM_G_INC_NORET:
361 addOne = true;
362 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
363 addVal = (uint32_t)-1;
364 } else {
365 opc = AMDILISD::ATOM_G_ADD_NORET;
366 }
367 break;
368 case AMDILISD::ATOM_L_DEC:
369 addOne = true;
370 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
371 addVal = (uint32_t)-1;
372 } else {
373 opc = AMDILISD::ATOM_L_SUB;
374 }
375 break;
376 case AMDILISD::ATOM_L_INC:
377 addOne = true;
378 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
379 addVal = (uint32_t)-1;
380 } else {
381 opc = AMDILISD::ATOM_L_ADD;
382 }
383 break;
384 case AMDILISD::ATOM_L_DEC_NORET:
385 addOne = true;
386 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
387 addVal = (uint32_t)-1;
388 } else {
389 opc = AMDILISD::ATOM_L_SUB_NORET;
390 }
391 break;
392 case AMDILISD::ATOM_L_INC_NORET:
393 addOne = true;
394 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
395 addVal = (uint32_t)-1;
396 } else {
397 opc = AMDILISD::ATOM_L_ADD_NORET;
398 }
399 break;
400 case AMDILISD::ATOM_R_DEC:
401 addOne = true;
402 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
403 addVal = (uint32_t)-1;
404 } else {
405 opc = AMDILISD::ATOM_R_SUB;
406 }
407 break;
408 case AMDILISD::ATOM_R_INC:
409 addOne = true;
410 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
411 addVal = (uint32_t)-1;
412 } else {
413 opc = AMDILISD::ATOM_R_ADD;
414 }
415 break;
416 case AMDILISD::ATOM_R_DEC_NORET:
417 addOne = true;
418 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
419 addVal = (uint32_t)-1;
420 } else {
421 opc = AMDILISD::ATOM_R_SUB;
422 }
423 break;
424 case AMDILISD::ATOM_R_INC_NORET:
425 addOne = true;
426 if (Subtarget.calVersion() >= CAL_VERSION_SC_136) {
427 addVal = (uint32_t)-1;
428 } else {
429 opc = AMDILISD::ATOM_R_ADD_NORET;
430 }
431 break;
432 }
433 // The largest we can have is a cmpxchg w/ a return value and an output chain.
434 // The cmpxchg function has 3 inputs and a single output along with an
435 // output change and a target constant, giving a total of 6.
436 SDValue Ops[12];
437 unsigned x = 0;
438 unsigned y = N->getNumOperands();
439 for (x = 0; x < y; ++x) {
440 Ops[x] = N->getOperand(x);
441 }
442 if (addOne) {
443 Ops[x++] = SDValue(SelectCode(CurDAG->getConstant(addVal, MVT::i32).getNode()), 0);
444 }
445 Ops[x++] = CurDAG->getTargetConstant(0, MVT::i32);
446 SDVTList Tys = N->getVTList();
447 MemSDNode *MemNode = dyn_cast<MemSDNode>(N);
448 assert(MemNode && "Atomic should be of MemSDNode type!");
449 N = CurDAG->getMemIntrinsicNode(opc, N->getDebugLoc(), Tys, Ops, x,
450 MemNode->getMemoryVT(), MemNode->getMemOperand()).getNode();
451 return N;
452 }
453
454 #ifdef DEBUGTMP
455 #undef INT64_C
456 #endif
457 #undef DEBUGTMP