radeon/llvm: Remove unused AMDIL TableGen definitons
[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 bool SelectADDR8BitOffset(SDValue Addr, SDValue& Base, SDValue& Offset);
69 bool SelectADDRReg(SDValue Addr, SDValue& Base, SDValue& Offset);
70 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
71
72 // Include the pieces autogenerated from the target description.
73 #include "AMDGPUGenDAGISel.inc"
74 };
75 } // end anonymous namespace
76
77 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
78 // DAG, ready for instruction scheduling.
79 //
80 FunctionPass *llvm::createAMDILISelDag(TargetMachine &TM
81 AMDIL_OPT_LEVEL_DECL) {
82 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR);
83 }
84
85 AMDILDAGToDAGISel::AMDILDAGToDAGISel(TargetMachine &TM
86 AMDIL_OPT_LEVEL_DECL)
87 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR), Subtarget(TM.getSubtarget<AMDILSubtarget>())
88 {
89 }
90
91 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
92 }
93
94 SDValue AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
95 return CurDAG->getTargetConstant(Imm, MVT::i32);
96 }
97
98 bool AMDILDAGToDAGISel::SelectADDRParam(
99 SDValue Addr, SDValue& R1, SDValue& R2) {
100
101 if (Addr.getOpcode() == ISD::FrameIndex) {
102 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
103 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
104 R2 = CurDAG->getTargetConstant(0, MVT::i32);
105 } else {
106 R1 = Addr;
107 R2 = CurDAG->getTargetConstant(0, MVT::i32);
108 }
109 } else if (Addr.getOpcode() == ISD::ADD) {
110 R1 = Addr.getOperand(0);
111 R2 = Addr.getOperand(1);
112 } else {
113 R1 = Addr;
114 R2 = CurDAG->getTargetConstant(0, MVT::i32);
115 }
116 return true;
117 }
118
119 bool AMDILDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
120 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
121 Addr.getOpcode() == ISD::TargetGlobalAddress) {
122 return false;
123 }
124 return SelectADDRParam(Addr, R1, R2);
125 }
126
127
128 bool AMDILDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
129 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
130 Addr.getOpcode() == ISD::TargetGlobalAddress) {
131 return false;
132 }
133
134 if (Addr.getOpcode() == ISD::FrameIndex) {
135 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
136 R1 = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
137 R2 = CurDAG->getTargetConstant(0, MVT::i64);
138 } else {
139 R1 = Addr;
140 R2 = CurDAG->getTargetConstant(0, MVT::i64);
141 }
142 } else if (Addr.getOpcode() == ISD::ADD) {
143 R1 = Addr.getOperand(0);
144 R2 = Addr.getOperand(1);
145 } else {
146 R1 = Addr;
147 R2 = CurDAG->getTargetConstant(0, MVT::i64);
148 }
149 return true;
150 }
151
152 SDNode *AMDILDAGToDAGISel::Select(SDNode *N) {
153 unsigned int Opc = N->getOpcode();
154 if (N->isMachineOpcode()) {
155 return NULL; // Already selected.
156 }
157 switch (Opc) {
158 default: break;
159 case ISD::FrameIndex:
160 {
161 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
162 unsigned int FI = FIN->getIndex();
163 EVT OpVT = N->getValueType(0);
164 unsigned int NewOpc = AMDIL::COPY;
165 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
166 return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
167 }
168 }
169 break;
170 }
171 return SelectCode(N);
172 }
173
174 bool AMDILDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) {
175 if (!ptr) {
176 return false;
177 }
178 Type *ptrType = ptr->getType();
179 return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace;
180 }
181
182 const Value * AMDILDAGToDAGISel::getBasePointerValue(const Value *V)
183 {
184 if (!V) {
185 return NULL;
186 }
187 const Value *ret = NULL;
188 ValueMap<const Value *, bool> ValueBitMap;
189 std::queue<const Value *, std::list<const Value *> > ValueQueue;
190 ValueQueue.push(V);
191 while (!ValueQueue.empty()) {
192 V = ValueQueue.front();
193 if (ValueBitMap.find(V) == ValueBitMap.end()) {
194 ValueBitMap[V] = true;
195 if (dyn_cast<Argument>(V) && dyn_cast<PointerType>(V->getType())) {
196 ret = V;
197 break;
198 } else if (dyn_cast<GlobalVariable>(V)) {
199 ret = V;
200 break;
201 } else if (dyn_cast<Constant>(V)) {
202 const ConstantExpr *CE = dyn_cast<ConstantExpr>(V);
203 if (CE) {
204 ValueQueue.push(CE->getOperand(0));
205 }
206 } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
207 ret = AI;
208 break;
209 } else if (const Instruction *I = dyn_cast<Instruction>(V)) {
210 uint32_t numOps = I->getNumOperands();
211 for (uint32_t x = 0; x < numOps; ++x) {
212 ValueQueue.push(I->getOperand(x));
213 }
214 } else {
215 // assert(0 && "Found a Value that we didn't know how to handle!");
216 }
217 }
218 ValueQueue.pop();
219 }
220 return ret;
221 }
222
223 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
224 return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
225 }
226
227 bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
228 return (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
229 && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
230 && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS));
231 }
232
233 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
234 return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
235 }
236
237 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
238 return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
239 }
240
241 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
242 if (checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)) {
243 return true;
244 }
245 MachineMemOperand *MMO = N->getMemOperand();
246 const Value *V = MMO->getValue();
247 const Value *BV = getBasePointerValue(V);
248 if (MMO
249 && MMO->getValue()
250 && ((V && dyn_cast<GlobalValue>(V))
251 || (BV && dyn_cast<GlobalValue>(
252 getBasePointerValue(MMO->getValue()))))) {
253 return checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS);
254 } else {
255 return false;
256 }
257 }
258
259 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
260 return checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS);
261 }
262
263 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode *N) {
264 return checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS);
265 }
266
267 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode *N) {
268 return checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS);
269 }
270
271 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
272 MachineMemOperand *MMO = N->getMemOperand();
273 if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
274 if (MMO) {
275 const Value *V = MMO->getValue();
276 const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
277 if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
278 return true;
279 }
280 }
281 }
282 return false;
283 }
284
285 bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) {
286 if (checkType(N->getSrcValue(), AMDILAS::PRIVATE_ADDRESS)) {
287 // Check to make sure we are not a constant pool load or a constant load
288 // that is marked as a private load
289 if (isCPLoad(N) || isConstantLoad(N, -1)) {
290 return false;
291 }
292 }
293 if (!checkType(N->getSrcValue(), AMDILAS::LOCAL_ADDRESS)
294 && !checkType(N->getSrcValue(), AMDILAS::GLOBAL_ADDRESS)
295 && !checkType(N->getSrcValue(), AMDILAS::REGION_ADDRESS)
296 && !checkType(N->getSrcValue(), AMDILAS::CONSTANT_ADDRESS)
297 && !checkType(N->getSrcValue(), AMDILAS::PARAM_D_ADDRESS)
298 && !checkType(N->getSrcValue(), AMDILAS::PARAM_I_ADDRESS))
299 {
300 return true;
301 }
302 return false;
303 }
304
305 const char *AMDILDAGToDAGISel::getPassName() const {
306 return "AMDIL DAG->DAG Pattern Instruction Selection";
307 }
308
309 #ifdef DEBUGTMP
310 #undef INT64_C
311 #endif
312 #undef DEBUGTMP
313
314 ///==== AMDGPU Functions ====///
315
316 bool AMDILDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
317 SDValue& Offset) {
318 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
319 Addr.getOpcode() == ISD::TargetGlobalAddress) {
320 return false;
321 }
322
323
324 if (Addr.getOpcode() == ISD::ADD) {
325 bool Match = false;
326
327 // Find the base ptr and the offset
328 for (unsigned i = 0; i < Addr.getNumOperands(); i++) {
329 SDValue Arg = Addr.getOperand(i);
330 ConstantSDNode * OffsetNode = dyn_cast<ConstantSDNode>(Arg);
331 // This arg isn't a constant so it must be the base PTR.
332 if (!OffsetNode) {
333 Base = Addr.getOperand(i);
334 continue;
335 }
336 // Check if the constant argument fits in 8-bits. The offset is in bytes
337 // so we need to convert it to dwords.
338 if (isInt<8>(OffsetNode->getZExtValue() >> 2)) {
339 Match = true;
340 Offset = CurDAG->getTargetConstant(OffsetNode->getZExtValue() >> 2,
341 MVT::i32);
342 }
343 }
344 return Match;
345 }
346
347 // Default case, no offset
348 Base = Addr;
349 Offset = CurDAG->getTargetConstant(0, MVT::i32);
350 return true;
351 }
352
353 bool AMDILDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
354 SDValue &Offset)
355 {
356 ConstantSDNode * IMMOffset;
357
358 if (Addr.getOpcode() == ISD::ADD
359 && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
360 && isInt<16>(IMMOffset->getZExtValue())) {
361
362 Base = Addr.getOperand(0);
363 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
364 return true;
365 // If the pointer address is constant, we can move it to the offset field.
366 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
367 && isInt<16>(IMMOffset->getZExtValue())) {
368 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
369 CurDAG->getEntryNode().getDebugLoc(),
370 AMDIL::ZERO, MVT::i32);
371 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
372 return true;
373 }
374
375 // Default case, no offset
376 Base = Addr;
377 Offset = CurDAG->getTargetConstant(0, MVT::i32);
378 return true;
379 }
380
381 bool AMDILDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
382 SDValue& Offset) {
383 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
384 Addr.getOpcode() == ISD::TargetGlobalAddress ||
385 Addr.getOpcode() != ISD::ADD) {
386 return false;
387 }
388
389 Base = Addr.getOperand(0);
390 Offset = Addr.getOperand(1);
391
392 return false;
393 }