~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/gallium/drivers/radeon/AMDILISelDAGToDAG.cpp

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
ImportĀ upstreamĀ versionĀ 9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "AMDGPUInstrInfo.h"
 
14
#include "AMDGPUISelLowering.h" // For AMDGPUISD
 
15
#include "AMDGPURegisterInfo.h"
 
16
#include "AMDILDevices.h"
 
17
#include "AMDILUtilityFunctions.h"
 
18
#include "llvm/ADT/ValueMap.h"
 
19
#include "llvm/CodeGen/PseudoSourceValue.h"
 
20
#include "llvm/CodeGen/SelectionDAGISel.h"
 
21
#include "llvm/Support/Compiler.h"
 
22
#include <list>
 
23
#include <queue>
 
24
 
 
25
using namespace llvm;
 
26
 
 
27
//===----------------------------------------------------------------------===//
 
28
// Instruction Selector Implementation
 
29
//===----------------------------------------------------------------------===//
 
30
 
 
31
//===----------------------------------------------------------------------===//
 
32
// AMDGPUDAGToDAGISel - AMDGPU specific code to select AMDGPU machine instructions
 
33
// //for SelectionDAG operations.
 
34
//
 
35
namespace {
 
36
class AMDGPUDAGToDAGISel : public SelectionDAGISel {
 
37
  // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can
 
38
  // make the right decision when generating code for different targets.
 
39
  const AMDGPUSubtarget &Subtarget;
 
40
public:
 
41
  AMDGPUDAGToDAGISel(TargetMachine &TM);
 
42
  virtual ~AMDGPUDAGToDAGISel();
 
43
 
 
44
  SDNode *Select(SDNode *N);
 
45
  virtual const char *getPassName() const;
 
46
 
 
47
private:
 
48
  inline SDValue getSmallIPtrImm(unsigned Imm);
 
49
 
 
50
  // Complex pattern selectors
 
51
  bool SelectADDRParam(SDValue Addr, SDValue& R1, SDValue& R2);
 
52
  bool SelectADDR(SDValue N, SDValue &R1, SDValue &R2);
 
53
  bool SelectADDR64(SDValue N, SDValue &R1, SDValue &R2);
 
54
 
 
55
  static bool checkType(const Value *ptr, unsigned int addrspace);
 
56
  static const Value *getBasePointerValue(const Value *V);
 
57
 
 
58
  static bool isGlobalStore(const StoreSDNode *N);
 
59
  static bool isPrivateStore(const StoreSDNode *N);
 
60
  static bool isLocalStore(const StoreSDNode *N);
 
61
  static bool isRegionStore(const StoreSDNode *N);
 
62
 
 
63
  static bool isCPLoad(const LoadSDNode *N);
 
64
  static bool isConstantLoad(const LoadSDNode *N, int cbID);
 
65
  static bool isGlobalLoad(const LoadSDNode *N);
 
66
  static bool isPrivateLoad(const LoadSDNode *N);
 
67
  static bool isLocalLoad(const LoadSDNode *N);
 
68
  static bool isRegionLoad(const LoadSDNode *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
// createAMDGPUISelDag - This pass converts a legalized DAG into a AMDGPU-specific
 
80
// DAG, ready for instruction scheduling.
 
81
//
 
82
FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM
 
83
                                       ) {
 
84
  return new AMDGPUDAGToDAGISel(TM);
 
85
}
 
86
 
 
87
AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM
 
88
                                     )
 
89
  : SelectionDAGISel(TM), Subtarget(TM.getSubtarget<AMDGPUSubtarget>())
 
90
{
 
91
}
 
92
 
 
93
AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() {
 
94
}
 
95
 
 
96
SDValue AMDGPUDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
 
97
  return CurDAG->getTargetConstant(Imm, MVT::i32);
 
98
}
 
99
 
 
100
bool AMDGPUDAGToDAGISel::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 AMDGPUDAGToDAGISel::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 AMDGPUDAGToDAGISel::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 *AMDGPUDAGToDAGISel::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 = AMDGPU::COPY;
 
167
        SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
 
168
        return CurDAG->SelectNodeTo(N, NewOpc, OpVT, TFI);
 
169
      }
 
170
    }
 
171
    break;
 
172
  }
 
173
  return SelectCode(N);
 
174
}
 
175
 
 
176
bool AMDGPUDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) {
 
177
  if (!ptr) {
 
178
    return false;
 
179
  }
 
180
  Type *ptrType = ptr->getType();
 
181
  return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace;
 
182
}
 
183
 
 
184
const Value * AMDGPUDAGToDAGISel::getBasePointerValue(const Value *V)
 
185
{
 
186
  if (!V) {
 
187
    return NULL;
 
188
  }
 
189
  const Value *ret = NULL;
 
190
  ValueMap<const Value *, bool> ValueBitMap;
 
191
  std::queue<const Value *, std::list<const Value *> > ValueQueue;
 
192
  ValueQueue.push(V);
 
193
  while (!ValueQueue.empty()) {
 
194
    V = ValueQueue.front();
 
195
    if (ValueBitMap.find(V) == ValueBitMap.end()) {
 
196
      ValueBitMap[V] = true;
 
197
      if (dyn_cast<Argument>(V) && dyn_cast<PointerType>(V->getType())) {
 
198
        ret = V;
 
199
        break;
 
200
      } else if (dyn_cast<GlobalVariable>(V)) {
 
201
        ret = V;
 
202
        break;
 
203
      } else if (dyn_cast<Constant>(V)) {
 
204
        const ConstantExpr *CE = dyn_cast<ConstantExpr>(V);
 
205
        if (CE) {
 
206
          ValueQueue.push(CE->getOperand(0));
 
207
        }
 
208
      } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
 
209
        ret = AI;
 
210
        break;
 
211
      } else if (const Instruction *I = dyn_cast<Instruction>(V)) {
 
212
        uint32_t numOps = I->getNumOperands();
 
213
        for (uint32_t x = 0; x < numOps; ++x) {
 
214
          ValueQueue.push(I->getOperand(x));
 
215
        }
 
216
      } else {
 
217
        // assert(0 && "Found a Value that we didn't know how to handle!");
 
218
      }
 
219
    }
 
220
    ValueQueue.pop();
 
221
  }
 
222
  return ret;
 
223
}
 
224
 
 
225
bool AMDGPUDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
 
226
  return checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS);
 
227
}
 
228
 
 
229
bool AMDGPUDAGToDAGISel::isPrivateStore(const StoreSDNode *N) {
 
230
  return (!checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS)
 
231
          && !checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS)
 
232
          && !checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS));
 
233
}
 
234
 
 
235
bool AMDGPUDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
 
236
  return checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS);
 
237
}
 
238
 
 
239
bool AMDGPUDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
 
240
  return checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS);
 
241
}
 
242
 
 
243
bool AMDGPUDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
 
244
  if (checkType(N->getSrcValue(), AMDGPUAS::CONSTANT_ADDRESS)) {
 
245
    return true;
 
246
  }
 
247
  MachineMemOperand *MMO = N->getMemOperand();
 
248
  const Value *V = MMO->getValue();
 
249
  const Value *BV = getBasePointerValue(V);
 
250
  if (MMO
 
251
      && MMO->getValue()
 
252
      && ((V && dyn_cast<GlobalValue>(V))
 
253
          || (BV && dyn_cast<GlobalValue>(
 
254
                        getBasePointerValue(MMO->getValue()))))) {
 
255
    return checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS);
 
256
  } else {
 
257
    return false;
 
258
  }
 
259
}
 
260
 
 
261
bool AMDGPUDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
 
262
  return checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS);
 
263
}
 
264
 
 
265
bool AMDGPUDAGToDAGISel::isLocalLoad(const  LoadSDNode *N) {
 
266
  return checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS);
 
267
}
 
268
 
 
269
bool AMDGPUDAGToDAGISel::isRegionLoad(const  LoadSDNode *N) {
 
270
  return checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS);
 
271
}
 
272
 
 
273
bool AMDGPUDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
 
274
  MachineMemOperand *MMO = N->getMemOperand();
 
275
  if (checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS)) {
 
276
    if (MMO) {
 
277
      const Value *V = MMO->getValue();
 
278
      const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
 
279
      if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
 
280
        return true;
 
281
      }
 
282
    }
 
283
  }
 
284
  return false;
 
285
}
 
286
 
 
287
bool AMDGPUDAGToDAGISel::isPrivateLoad(const LoadSDNode *N) {
 
288
  if (checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS)) {
 
289
    // Check to make sure we are not a constant pool load or a constant load
 
290
    // that is marked as a private load
 
291
    if (isCPLoad(N) || isConstantLoad(N, -1)) {
 
292
      return false;
 
293
    }
 
294
  }
 
295
  if (!checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS)
 
296
      && !checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS)
 
297
      && !checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS)
 
298
      && !checkType(N->getSrcValue(), AMDGPUAS::CONSTANT_ADDRESS)
 
299
      && !checkType(N->getSrcValue(), AMDGPUAS::PARAM_D_ADDRESS)
 
300
      && !checkType(N->getSrcValue(), AMDGPUAS::PARAM_I_ADDRESS))
 
301
  {
 
302
    return true;
 
303
  }
 
304
  return false;
 
305
}
 
306
 
 
307
const char *AMDGPUDAGToDAGISel::getPassName() const {
 
308
  return "AMDGPU DAG->DAG Pattern Instruction Selection";
 
309
}
 
310
 
 
311
#ifdef DEBUGTMP
 
312
#undef INT64_C
 
313
#endif
 
314
#undef DEBUGTMP
 
315
 
 
316
///==== AMDGPU Functions ====///
 
317
 
 
318
bool AMDGPUDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
 
319
                                             SDValue& Offset) {
 
320
  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
 
321
      Addr.getOpcode() == ISD::TargetGlobalAddress) {
 
322
    return false;
 
323
  }
 
324
 
 
325
 
 
326
  if (Addr.getOpcode() == ISD::ADD) {
 
327
    bool Match = false;
 
328
 
 
329
    // Find the base ptr and the offset
 
330
    for (unsigned i = 0; i < Addr.getNumOperands(); i++) {
 
331
      SDValue Arg = Addr.getOperand(i);
 
332
      ConstantSDNode * OffsetNode = dyn_cast<ConstantSDNode>(Arg);
 
333
      // This arg isn't a constant so it must be the base PTR.
 
334
      if (!OffsetNode) {
 
335
        Base = Addr.getOperand(i);
 
336
        continue;
 
337
      }
 
338
      // Check if the constant argument fits in 8-bits.  The offset is in bytes
 
339
      // so we need to convert it to dwords.
 
340
      if (isInt<8>(OffsetNode->getZExtValue() >> 2)) {
 
341
        Match = true;
 
342
        Offset = CurDAG->getTargetConstant(OffsetNode->getZExtValue() >> 2,
 
343
                                           MVT::i32);
 
344
      }
 
345
    }
 
346
    return Match;
 
347
  }
 
348
 
 
349
  // Default case, no offset
 
350
  Base = Addr;
 
351
  Offset = CurDAG->getTargetConstant(0, MVT::i32);
 
352
  return true;
 
353
}
 
354
 
 
355
bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
 
356
                                           SDValue &Offset)
 
357
{
 
358
  ConstantSDNode * IMMOffset;
 
359
 
 
360
  if (Addr.getOpcode() == ISD::ADD
 
361
      && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
 
362
      && isInt<16>(IMMOffset->getZExtValue())) {
 
363
 
 
364
      Base = Addr.getOperand(0);
 
365
      Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
 
366
      return true;
 
367
  // If the pointer address is constant, we can move it to the offset field.
 
368
  } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
 
369
             && isInt<16>(IMMOffset->getZExtValue())) {
 
370
    Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
 
371
                                  CurDAG->getEntryNode().getDebugLoc(),
 
372
                                  AMDGPU::ZERO, MVT::i32);
 
373
    Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
 
374
    return true;
 
375
  }
 
376
 
 
377
  // Default case, no offset
 
378
  Base = Addr;
 
379
  Offset = CurDAG->getTargetConstant(0, MVT::i32);
 
380
  return true;
 
381
}
 
382
 
 
383
bool AMDGPUDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
 
384
                                      SDValue& Offset) {
 
385
  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
 
386
      Addr.getOpcode() == ISD::TargetGlobalAddress  ||
 
387
      Addr.getOpcode() != ISD::ADD) {
 
388
    return false;
 
389
  }
 
390
 
 
391
  Base = Addr.getOperand(0);
 
392
  Offset = Addr.getOperand(1);
 
393
 
 
394
  return true;
 
395
}