OSDN Git Service

radeonsi: initial WIP SI code
[android-x86/external-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