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 (isUInt
<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);