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 "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"
25 //===----------------------------------------------------------------------===//
26 // Instruction Selector Implementation
27 //===----------------------------------------------------------------------===//
29 //===----------------------------------------------------------------------===//
30 // AMDILDAGToDAGISel - AMDIL specific code to select AMDIL machine instructions
31 // //for SelectionDAG operations.
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
;
39 AMDILDAGToDAGISel(TargetMachine
&TM AMDIL_OPT_LEVEL_DECL
);
40 virtual ~AMDILDAGToDAGISel();
42 SDNode
*Select(SDNode
*N
);
43 virtual const char *getPassName() const;
46 inline SDValue
getSmallIPtrImm(unsigned Imm
);
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
);
53 static bool checkType(const Value
*ptr
, unsigned int addrspace
);
54 static const Value
*getBasePointerValue(const Value
*V
);
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
);
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
);
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
);
72 // Include the pieces autogenerated from the target description.
73 #include "AMDGPUGenDAGISel.inc"
75 } // end anonymous namespace
77 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
78 // DAG, ready for instruction scheduling.
80 FunctionPass
*llvm::createAMDILISelDag(TargetMachine
&TM
81 AMDIL_OPT_LEVEL_DECL
) {
82 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR
);
85 AMDILDAGToDAGISel::AMDILDAGToDAGISel(TargetMachine
&TM
87 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR
), Subtarget(TM
.getSubtarget
<AMDILSubtarget
>())
91 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
94 SDValue
AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm
) {
95 return CurDAG
->getTargetConstant(Imm
, MVT::i32
);
98 bool AMDILDAGToDAGISel::SelectADDRParam(
99 SDValue Addr
, SDValue
& R1
, SDValue
& R2
) {
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
);
107 R2
= CurDAG
->getTargetConstant(0, MVT::i32
);
109 } else if (Addr
.getOpcode() == ISD::ADD
) {
110 R1
= Addr
.getOperand(0);
111 R2
= Addr
.getOperand(1);
114 R2
= CurDAG
->getTargetConstant(0, MVT::i32
);
119 bool AMDILDAGToDAGISel::SelectADDR(SDValue Addr
, SDValue
& R1
, SDValue
& R2
) {
120 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
121 Addr
.getOpcode() == ISD::TargetGlobalAddress
) {
124 return SelectADDRParam(Addr
, R1
, R2
);
128 bool AMDILDAGToDAGISel::SelectADDR64(SDValue Addr
, SDValue
& R1
, SDValue
& R2
) {
129 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
130 Addr
.getOpcode() == ISD::TargetGlobalAddress
) {
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
);
140 R2
= CurDAG
->getTargetConstant(0, MVT::i64
);
142 } else if (Addr
.getOpcode() == ISD::ADD
) {
143 R1
= Addr
.getOperand(0);
144 R2
= Addr
.getOperand(1);
147 R2
= CurDAG
->getTargetConstant(0, MVT::i64
);
152 SDNode
*AMDILDAGToDAGISel::Select(SDNode
*N
) {
153 unsigned int Opc
= N
->getOpcode();
154 if (N
->isMachineOpcode()) {
155 return NULL
; // Already selected.
159 case ISD::FrameIndex
:
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
);
171 return SelectCode(N
);
174 bool AMDILDAGToDAGISel::checkType(const Value
*ptr
, unsigned int addrspace
) {
178 Type
*ptrType
= ptr
->getType();
179 return dyn_cast
<PointerType
>(ptrType
)->getAddressSpace() == addrspace
;
182 const Value
* AMDILDAGToDAGISel::getBasePointerValue(const Value
*V
)
187 const Value
*ret
= NULL
;
188 ValueMap
<const Value
*, bool> ValueBitMap
;
189 std::queue
<const Value
*, std::list
<const Value
*> > ValueQueue
;
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())) {
198 } else if (dyn_cast
<GlobalVariable
>(V
)) {
201 } else if (dyn_cast
<Constant
>(V
)) {
202 const ConstantExpr
*CE
= dyn_cast
<ConstantExpr
>(V
);
204 ValueQueue
.push(CE
->getOperand(0));
206 } else if (const AllocaInst
*AI
= dyn_cast
<AllocaInst
>(V
)) {
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
));
215 // assert(0 && "Found a Value that we didn't know how to handle!");
223 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode
*N
) {
224 return checkType(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
);
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
));
233 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode
*N
) {
234 return checkType(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
);
237 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode
*N
) {
238 return checkType(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
);
241 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode
*N
, int cbID
) {
242 if (checkType(N
->getSrcValue(), AMDILAS::CONSTANT_ADDRESS
)) {
245 MachineMemOperand
*MMO
= N
->getMemOperand();
246 const Value
*V
= MMO
->getValue();
247 const Value
*BV
= getBasePointerValue(V
);
250 && ((V
&& dyn_cast
<GlobalValue
>(V
))
251 || (BV
&& dyn_cast
<GlobalValue
>(
252 getBasePointerValue(MMO
->getValue()))))) {
253 return checkType(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
);
259 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode
*N
) {
260 return checkType(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
);
263 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode
*N
) {
264 return checkType(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
);
267 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode
*N
) {
268 return checkType(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
);
271 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode
*N
) {
272 MachineMemOperand
*MMO
= N
->getMemOperand();
273 if (checkType(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
)) {
275 const Value
*V
= MMO
->getValue();
276 const PseudoSourceValue
*PSV
= dyn_cast
<PseudoSourceValue
>(V
);
277 if (PSV
&& PSV
== PseudoSourceValue::getConstantPool()) {
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)) {
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
))
305 const char *AMDILDAGToDAGISel::getPassName() const {
306 return "AMDIL DAG->DAG Pattern Instruction Selection";
314 ///==== AMDGPU Functions ====///
316 bool AMDILDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr
, SDValue
& Base
,
318 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
319 Addr
.getOpcode() == ISD::TargetGlobalAddress
) {
324 if (Addr
.getOpcode() == ISD::ADD
) {
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.
333 Base
= Addr
.getOperand(i
);
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)) {
340 Offset
= CurDAG
->getTargetConstant(OffsetNode
->getZExtValue() >> 2,
347 // Default case, no offset
349 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
353 bool AMDILDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr
, SDValue
&Base
,
356 ConstantSDNode
* IMMOffset
;
358 if (Addr
.getOpcode() == ISD::ADD
359 && (IMMOffset
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
360 && isInt
<16>(IMMOffset
->getZExtValue())) {
362 Base
= Addr
.getOperand(0);
363 Offset
= CurDAG
->getTargetConstant(IMMOffset
->getZExtValue(), MVT::i32
);
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
);
375 // Default case, no offset
377 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
381 bool AMDILDAGToDAGISel::SelectADDRReg(SDValue Addr
, SDValue
& Base
,
383 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
384 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
385 Addr
.getOpcode() != ISD::ADD
) {
389 Base
= Addr
.getOperand(0);
390 Offset
= Addr
.getOperand(1);