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 SDNode
*xformAtomicInst(SDNode
*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 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
80 // DAG, ready for instruction scheduling.
82 FunctionPass
*llvm::createAMDILISelDag(TargetMachine
&TM
83 AMDIL_OPT_LEVEL_DECL
) {
84 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR
);
87 AMDILDAGToDAGISel::AMDILDAGToDAGISel(TargetMachine
&TM
89 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR
), Subtarget(TM
.getSubtarget
<AMDILSubtarget
>())
93 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
96 SDValue
AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm
) {
97 return CurDAG
->getTargetConstant(Imm
, MVT::i32
);
100 bool AMDILDAGToDAGISel::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 AMDILDAGToDAGISel::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 AMDILDAGToDAGISel::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
*AMDILDAGToDAGISel::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
= AMDIL::COPY
;
167 SDValue TFI
= CurDAG
->getTargetFrameIndex(FI
, MVT::i32
);
168 return CurDAG
->SelectNodeTo(N
, NewOpc
, OpVT
, TFI
);
173 // For all atomic instructions, we need to add a constant
174 // operand that stores the resource ID in the instruction
175 if (Opc
> AMDILISD::ADDADDR
&& Opc
< AMDILISD::APPEND_ALLOC
) {
176 N
= xformAtomicInst(N
);
178 return SelectCode(N
);
181 bool AMDILDAGToDAGISel::checkType(const Value
*ptr
, unsigned int addrspace
) {
185 Type
*ptrType
= ptr
->getType();
186 return dyn_cast
<PointerType
>(ptrType
)->getAddressSpace() == addrspace
;
189 const Value
* AMDILDAGToDAGISel::getBasePointerValue(const Value
*V
)
194 const Value
*ret
= NULL
;
195 ValueMap
<const Value
*, bool> ValueBitMap
;
196 std::queue
<const Value
*, std::list
<const Value
*> > ValueQueue
;
198 while (!ValueQueue
.empty()) {
199 V
= ValueQueue
.front();
200 if (ValueBitMap
.find(V
) == ValueBitMap
.end()) {
201 ValueBitMap
[V
] = true;
202 if (dyn_cast
<Argument
>(V
) && dyn_cast
<PointerType
>(V
->getType())) {
205 } else if (dyn_cast
<GlobalVariable
>(V
)) {
208 } else if (dyn_cast
<Constant
>(V
)) {
209 const ConstantExpr
*CE
= dyn_cast
<ConstantExpr
>(V
);
211 ValueQueue
.push(CE
->getOperand(0));
213 } else if (const AllocaInst
*AI
= dyn_cast
<AllocaInst
>(V
)) {
216 } else if (const Instruction
*I
= dyn_cast
<Instruction
>(V
)) {
217 uint32_t numOps
= I
->getNumOperands();
218 for (uint32_t x
= 0; x
< numOps
; ++x
) {
219 ValueQueue
.push(I
->getOperand(x
));
222 // assert(0 && "Found a Value that we didn't know how to handle!");
230 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode
*N
) {
231 return checkType(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
);
234 bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode
*N
) {
235 return (!checkType(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
)
236 && !checkType(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
)
237 && !checkType(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
));
240 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode
*N
) {
241 return checkType(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
);
244 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode
*N
) {
245 return checkType(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
);
248 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode
*N
, int cbID
) {
249 if (checkType(N
->getSrcValue(), AMDILAS::CONSTANT_ADDRESS
)) {
252 MachineMemOperand
*MMO
= N
->getMemOperand();
253 const Value
*V
= MMO
->getValue();
254 const Value
*BV
= getBasePointerValue(V
);
257 && ((V
&& dyn_cast
<GlobalValue
>(V
))
258 || (BV
&& dyn_cast
<GlobalValue
>(
259 getBasePointerValue(MMO
->getValue()))))) {
260 return checkType(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
);
266 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode
*N
) {
267 return checkType(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
);
270 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode
*N
) {
271 return checkType(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
);
274 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode
*N
) {
275 return checkType(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
);
278 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode
*N
) {
279 MachineMemOperand
*MMO
= N
->getMemOperand();
280 if (checkType(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
)) {
282 const Value
*V
= MMO
->getValue();
283 const PseudoSourceValue
*PSV
= dyn_cast
<PseudoSourceValue
>(V
);
284 if (PSV
&& PSV
== PseudoSourceValue::getConstantPool()) {
292 bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode
*N
) {
293 if (checkType(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
)) {
294 // Check to make sure we are not a constant pool load or a constant load
295 // that is marked as a private load
296 if (isCPLoad(N
) || isConstantLoad(N
, -1)) {
300 if (!checkType(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
)
301 && !checkType(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
)
302 && !checkType(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
)
303 && !checkType(N
->getSrcValue(), AMDILAS::CONSTANT_ADDRESS
)
304 && !checkType(N
->getSrcValue(), AMDILAS::PARAM_D_ADDRESS
)
305 && !checkType(N
->getSrcValue(), AMDILAS::PARAM_I_ADDRESS
))
312 const char *AMDILDAGToDAGISel::getPassName() const {
313 return "AMDIL DAG->DAG Pattern Instruction Selection";
317 AMDILDAGToDAGISel::xformAtomicInst(SDNode
*N
)
321 // bool bitCastToInt = (N->getValueType(0) == MVT::f32);
322 unsigned opc
= N
->getOpcode();
325 case AMDILISD::ATOM_G_ADD
:
326 case AMDILISD::ATOM_G_AND
:
327 case AMDILISD::ATOM_G_MAX
:
328 case AMDILISD::ATOM_G_UMAX
:
329 case AMDILISD::ATOM_G_MIN
:
330 case AMDILISD::ATOM_G_UMIN
:
331 case AMDILISD::ATOM_G_OR
:
332 case AMDILISD::ATOM_G_SUB
:
333 case AMDILISD::ATOM_G_RSUB
:
334 case AMDILISD::ATOM_G_XCHG
:
335 case AMDILISD::ATOM_G_XOR
:
336 case AMDILISD::ATOM_G_ADD_NORET
:
337 case AMDILISD::ATOM_G_AND_NORET
:
338 case AMDILISD::ATOM_G_MAX_NORET
:
339 case AMDILISD::ATOM_G_UMAX_NORET
:
340 case AMDILISD::ATOM_G_MIN_NORET
:
341 case AMDILISD::ATOM_G_UMIN_NORET
:
342 case AMDILISD::ATOM_G_OR_NORET
:
343 case AMDILISD::ATOM_G_SUB_NORET
:
344 case AMDILISD::ATOM_G_RSUB_NORET
:
345 case AMDILISD::ATOM_G_XCHG_NORET
:
346 case AMDILISD::ATOM_G_XOR_NORET
:
347 case AMDILISD::ATOM_L_ADD
:
348 case AMDILISD::ATOM_L_AND
:
349 case AMDILISD::ATOM_L_MAX
:
350 case AMDILISD::ATOM_L_UMAX
:
351 case AMDILISD::ATOM_L_MIN
:
352 case AMDILISD::ATOM_L_UMIN
:
353 case AMDILISD::ATOM_L_OR
:
354 case AMDILISD::ATOM_L_SUB
:
355 case AMDILISD::ATOM_L_RSUB
:
356 case AMDILISD::ATOM_L_XCHG
:
357 case AMDILISD::ATOM_L_XOR
:
358 case AMDILISD::ATOM_L_ADD_NORET
:
359 case AMDILISD::ATOM_L_AND_NORET
:
360 case AMDILISD::ATOM_L_MAX_NORET
:
361 case AMDILISD::ATOM_L_UMAX_NORET
:
362 case AMDILISD::ATOM_L_MIN_NORET
:
363 case AMDILISD::ATOM_L_UMIN_NORET
:
364 case AMDILISD::ATOM_L_OR_NORET
:
365 case AMDILISD::ATOM_L_SUB_NORET
:
366 case AMDILISD::ATOM_L_RSUB_NORET
:
367 case AMDILISD::ATOM_L_XCHG_NORET
:
368 case AMDILISD::ATOM_L_XOR_NORET
:
369 case AMDILISD::ATOM_R_ADD
:
370 case AMDILISD::ATOM_R_AND
:
371 case AMDILISD::ATOM_R_MAX
:
372 case AMDILISD::ATOM_R_UMAX
:
373 case AMDILISD::ATOM_R_MIN
:
374 case AMDILISD::ATOM_R_UMIN
:
375 case AMDILISD::ATOM_R_OR
:
376 case AMDILISD::ATOM_R_SUB
:
377 case AMDILISD::ATOM_R_RSUB
:
378 case AMDILISD::ATOM_R_XCHG
:
379 case AMDILISD::ATOM_R_XOR
:
380 case AMDILISD::ATOM_R_ADD_NORET
:
381 case AMDILISD::ATOM_R_AND_NORET
:
382 case AMDILISD::ATOM_R_MAX_NORET
:
383 case AMDILISD::ATOM_R_UMAX_NORET
:
384 case AMDILISD::ATOM_R_MIN_NORET
:
385 case AMDILISD::ATOM_R_UMIN_NORET
:
386 case AMDILISD::ATOM_R_OR_NORET
:
387 case AMDILISD::ATOM_R_SUB_NORET
:
388 case AMDILISD::ATOM_R_RSUB_NORET
:
389 case AMDILISD::ATOM_R_XCHG_NORET
:
390 case AMDILISD::ATOM_R_XOR_NORET
:
391 case AMDILISD::ATOM_G_CMPXCHG
:
392 case AMDILISD::ATOM_G_CMPXCHG_NORET
:
393 case AMDILISD::ATOM_L_CMPXCHG
:
394 case AMDILISD::ATOM_L_CMPXCHG_NORET
:
395 case AMDILISD::ATOM_R_CMPXCHG
:
396 case AMDILISD::ATOM_R_CMPXCHG_NORET
:
398 case AMDILISD::ATOM_G_DEC
:
400 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
401 addVal
= (uint32_t)-1;
403 opc
= AMDILISD::ATOM_G_SUB
;
406 case AMDILISD::ATOM_G_INC
:
408 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
409 addVal
= (uint32_t)-1;
411 opc
= AMDILISD::ATOM_G_ADD
;
414 case AMDILISD::ATOM_G_DEC_NORET
:
416 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
417 addVal
= (uint32_t)-1;
419 opc
= AMDILISD::ATOM_G_SUB_NORET
;
422 case AMDILISD::ATOM_G_INC_NORET
:
424 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
425 addVal
= (uint32_t)-1;
427 opc
= AMDILISD::ATOM_G_ADD_NORET
;
430 case AMDILISD::ATOM_L_DEC
:
432 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
433 addVal
= (uint32_t)-1;
435 opc
= AMDILISD::ATOM_L_SUB
;
438 case AMDILISD::ATOM_L_INC
:
440 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
441 addVal
= (uint32_t)-1;
443 opc
= AMDILISD::ATOM_L_ADD
;
446 case AMDILISD::ATOM_L_DEC_NORET
:
448 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
449 addVal
= (uint32_t)-1;
451 opc
= AMDILISD::ATOM_L_SUB_NORET
;
454 case AMDILISD::ATOM_L_INC_NORET
:
456 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
457 addVal
= (uint32_t)-1;
459 opc
= AMDILISD::ATOM_L_ADD_NORET
;
462 case AMDILISD::ATOM_R_DEC
:
464 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
465 addVal
= (uint32_t)-1;
467 opc
= AMDILISD::ATOM_R_SUB
;
470 case AMDILISD::ATOM_R_INC
:
472 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
473 addVal
= (uint32_t)-1;
475 opc
= AMDILISD::ATOM_R_ADD
;
478 case AMDILISD::ATOM_R_DEC_NORET
:
480 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
481 addVal
= (uint32_t)-1;
483 opc
= AMDILISD::ATOM_R_SUB
;
486 case AMDILISD::ATOM_R_INC_NORET
:
488 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
489 addVal
= (uint32_t)-1;
491 opc
= AMDILISD::ATOM_R_ADD_NORET
;
495 // The largest we can have is a cmpxchg w/ a return value and an output chain.
496 // The cmpxchg function has 3 inputs and a single output along with an
497 // output change and a target constant, giving a total of 6.
500 unsigned y
= N
->getNumOperands();
501 for (x
= 0; x
< y
; ++x
) {
502 Ops
[x
] = N
->getOperand(x
);
505 Ops
[x
++] = SDValue(SelectCode(CurDAG
->getConstant(addVal
, MVT::i32
).getNode()), 0);
507 Ops
[x
++] = CurDAG
->getTargetConstant(0, MVT::i32
);
508 SDVTList Tys
= N
->getVTList();
509 MemSDNode
*MemNode
= dyn_cast
<MemSDNode
>(N
);
510 assert(MemNode
&& "Atomic should be of MemSDNode type!");
511 N
= CurDAG
->getMemIntrinsicNode(opc
, N
->getDebugLoc(), Tys
, Ops
, x
,
512 MemNode
->getMemoryVT(), MemNode
->getMemOperand()).getNode();
521 ///==== AMDGPU Functions ====///
523 bool AMDILDAGToDAGISel::SelectADDR8BitOffset(SDValue Addr
, SDValue
& Base
,
525 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
526 Addr
.getOpcode() == ISD::TargetGlobalAddress
) {
531 if (Addr
.getOpcode() == ISD::ADD
) {
534 // Find the base ptr and the offset
535 for (unsigned i
= 0; i
< Addr
.getNumOperands(); i
++) {
536 SDValue Arg
= Addr
.getOperand(i
);
537 ConstantSDNode
* OffsetNode
= dyn_cast
<ConstantSDNode
>(Arg
);
538 // This arg isn't a constant so it must be the base PTR.
540 Base
= Addr
.getOperand(i
);
543 // Check if the constant argument fits in 8-bits. The offset is in bytes
544 // so we need to convert it to dwords.
545 if (isInt
<8>(OffsetNode
->getZExtValue() >> 2)) {
547 Offset
= CurDAG
->getTargetConstant(OffsetNode
->getZExtValue() >> 2,
554 // Default case, no offset
556 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
560 bool AMDILDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr
, SDValue
&Base
,
563 ConstantSDNode
* IMMOffset
;
565 if (Addr
.getOpcode() == ISD::ADD
566 && (IMMOffset
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
567 && isInt
<16>(IMMOffset
->getZExtValue())) {
569 Base
= Addr
.getOperand(0);
570 Offset
= CurDAG
->getTargetConstant(IMMOffset
->getZExtValue(), MVT::i32
);
572 // If the pointer address is constant, we can move it to the offset field.
573 } else if ((IMMOffset
= dyn_cast
<ConstantSDNode
>(Addr
))
574 && isInt
<16>(IMMOffset
->getZExtValue())) {
575 Base
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(),
576 CurDAG
->getEntryNode().getDebugLoc(),
577 AMDIL::ZERO
, MVT::i32
);
578 Offset
= CurDAG
->getTargetConstant(IMMOffset
->getZExtValue(), MVT::i32
);
582 // Default case, no offset
584 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
588 bool AMDILDAGToDAGISel::SelectADDRReg(SDValue Addr
, SDValue
& Base
,
590 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
591 Addr
.getOpcode() == ISD::TargetGlobalAddress
||
592 Addr
.getOpcode() != ISD::ADD
) {
596 Base
= Addr
.getOperand(0);
597 Offset
= Addr
.getOperand(1);