1
//===-- AMDILISelDAGToDAG.cpp - A dag to dag inst selector for AMDIL ------===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//==-----------------------------------------------------------------------===//
10
// This file defines an instruction selector for the AMDIL target.
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"
27
//===----------------------------------------------------------------------===//
28
// Instruction Selector Implementation
29
//===----------------------------------------------------------------------===//
31
//===----------------------------------------------------------------------===//
32
// AMDGPUDAGToDAGISel - AMDGPU specific code to select AMDGPU machine instructions
33
// //for SelectionDAG operations.
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;
41
AMDGPUDAGToDAGISel(TargetMachine &TM);
42
virtual ~AMDGPUDAGToDAGISel();
44
SDNode *Select(SDNode *N);
45
virtual const char *getPassName() const;
48
inline SDValue getSmallIPtrImm(unsigned Imm);
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);
55
static bool checkType(const Value *ptr, unsigned int addrspace);
56
static const Value *getBasePointerValue(const Value *V);
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);
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);
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);
74
// Include the pieces autogenerated from the target description.
75
#include "AMDGPUGenDAGISel.inc"
77
} // end anonymous namespace
79
// createAMDGPUISelDag - This pass converts a legalized DAG into a AMDGPU-specific
80
// DAG, ready for instruction scheduling.
82
FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM
84
return new AMDGPUDAGToDAGISel(TM);
87
AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM
89
: SelectionDAGISel(TM), Subtarget(TM.getSubtarget<AMDGPUSubtarget>())
93
AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() {
96
SDValue AMDGPUDAGToDAGISel::getSmallIPtrImm(unsigned int Imm) {
97
return CurDAG->getTargetConstant(Imm, MVT::i32);
100
bool AMDGPUDAGToDAGISel::SelectADDRParam(
101
SDValue Addr, SDValue& R1, SDValue& R2) {
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);
109
R2 = CurDAG->getTargetConstant(0, MVT::i32);
111
} else if (Addr.getOpcode() == ISD::ADD) {
112
R1 = Addr.getOperand(0);
113
R2 = Addr.getOperand(1);
116
R2 = CurDAG->getTargetConstant(0, MVT::i32);
121
bool AMDGPUDAGToDAGISel::SelectADDR(SDValue Addr, SDValue& R1, SDValue& R2) {
122
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
123
Addr.getOpcode() == ISD::TargetGlobalAddress) {
126
return SelectADDRParam(Addr, R1, R2);
130
bool AMDGPUDAGToDAGISel::SelectADDR64(SDValue Addr, SDValue& R1, SDValue& R2) {
131
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
132
Addr.getOpcode() == ISD::TargetGlobalAddress) {
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);
142
R2 = CurDAG->getTargetConstant(0, MVT::i64);
144
} else if (Addr.getOpcode() == ISD::ADD) {
145
R1 = Addr.getOperand(0);
146
R2 = Addr.getOperand(1);
149
R2 = CurDAG->getTargetConstant(0, MVT::i64);
154
SDNode *AMDGPUDAGToDAGISel::Select(SDNode *N) {
155
unsigned int Opc = N->getOpcode();
156
if (N->isMachineOpcode()) {
157
return NULL; // Already selected.
161
case ISD::FrameIndex:
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);
173
return SelectCode(N);
176
bool AMDGPUDAGToDAGISel::checkType(const Value *ptr, unsigned int addrspace) {
180
Type *ptrType = ptr->getType();
181
return dyn_cast<PointerType>(ptrType)->getAddressSpace() == addrspace;
184
const Value * AMDGPUDAGToDAGISel::getBasePointerValue(const Value *V)
189
const Value *ret = NULL;
190
ValueMap<const Value *, bool> ValueBitMap;
191
std::queue<const Value *, std::list<const Value *> > ValueQueue;
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())) {
200
} else if (dyn_cast<GlobalVariable>(V)) {
203
} else if (dyn_cast<Constant>(V)) {
204
const ConstantExpr *CE = dyn_cast<ConstantExpr>(V);
206
ValueQueue.push(CE->getOperand(0));
208
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
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));
217
// assert(0 && "Found a Value that we didn't know how to handle!");
225
bool AMDGPUDAGToDAGISel::isGlobalStore(const StoreSDNode *N) {
226
return checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS);
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));
235
bool AMDGPUDAGToDAGISel::isLocalStore(const StoreSDNode *N) {
236
return checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS);
239
bool AMDGPUDAGToDAGISel::isRegionStore(const StoreSDNode *N) {
240
return checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS);
243
bool AMDGPUDAGToDAGISel::isConstantLoad(const LoadSDNode *N, int cbID) {
244
if (checkType(N->getSrcValue(), AMDGPUAS::CONSTANT_ADDRESS)) {
247
MachineMemOperand *MMO = N->getMemOperand();
248
const Value *V = MMO->getValue();
249
const Value *BV = getBasePointerValue(V);
252
&& ((V && dyn_cast<GlobalValue>(V))
253
|| (BV && dyn_cast<GlobalValue>(
254
getBasePointerValue(MMO->getValue()))))) {
255
return checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS);
261
bool AMDGPUDAGToDAGISel::isGlobalLoad(const LoadSDNode *N) {
262
return checkType(N->getSrcValue(), AMDGPUAS::GLOBAL_ADDRESS);
265
bool AMDGPUDAGToDAGISel::isLocalLoad(const LoadSDNode *N) {
266
return checkType(N->getSrcValue(), AMDGPUAS::LOCAL_ADDRESS);
269
bool AMDGPUDAGToDAGISel::isRegionLoad(const LoadSDNode *N) {
270
return checkType(N->getSrcValue(), AMDGPUAS::REGION_ADDRESS);
273
bool AMDGPUDAGToDAGISel::isCPLoad(const LoadSDNode *N) {
274
MachineMemOperand *MMO = N->getMemOperand();
275
if (checkType(N->getSrcValue(), AMDGPUAS::PRIVATE_ADDRESS)) {
277
const Value *V = MMO->getValue();
278
const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V);
279
if (PSV && PSV == PseudoSourceValue::getConstantPool()) {
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)) {
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))
307
const char *AMDGPUDAGToDAGISel::getPassName() const {
308
return "AMDGPU DAG->DAG Pattern Instruction Selection";
316
///==== AMDGPU Functions ====///
318
bool AMDGPUDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr, SDValue& Base,
320
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
321
Addr.getOpcode() == ISD::TargetGlobalAddress) {
326
if (Addr.getOpcode() == ISD::ADD) {
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.
335
Base = Addr.getOperand(i);
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)) {
342
Offset = CurDAG->getTargetConstant(OffsetNode->getZExtValue() >> 2,
349
// Default case, no offset
351
Offset = CurDAG->getTargetConstant(0, MVT::i32);
355
bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
358
ConstantSDNode * IMMOffset;
360
if (Addr.getOpcode() == ISD::ADD
361
&& (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
362
&& isInt<16>(IMMOffset->getZExtValue())) {
364
Base = Addr.getOperand(0);
365
Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), MVT::i32);
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);
377
// Default case, no offset
379
Offset = CurDAG->getTargetConstant(0, MVT::i32);
383
bool AMDGPUDAGToDAGISel::SelectADDRReg(SDValue Addr, SDValue& Base,
385
if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
386
Addr.getOpcode() == ISD::TargetGlobalAddress ||
387
Addr.getOpcode() != ISD::ADD) {
391
Base = Addr.getOperand(0);
392
Offset = Addr.getOperand(1);