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 "AMDILDevices.h"
14 #include "AMDILTargetMachine.h"
15 #include "AMDILUtilityFunctions.h"
16 #include "llvm/CodeGen/PseudoSourceValue.h"
17 #include "llvm/CodeGen/SelectionDAGISel.h"
18 #include "llvm/Support/Compiler.h"
22 //===----------------------------------------------------------------------===//
23 // Instruction Selector Implementation
24 //===----------------------------------------------------------------------===//
26 //===----------------------------------------------------------------------===//
27 // AMDILDAGToDAGISel - AMDIL specific code to select AMDIL machine instructions
28 // //for SelectionDAG operations.
31 class AMDILDAGToDAGISel
: public SelectionDAGISel
{
32 // Subtarget - Keep a pointer to the AMDIL Subtarget around so that we can
33 // make the right decision when generating code for different targets.
34 const AMDILSubtarget
&Subtarget
;
36 AMDILDAGToDAGISel(AMDILTargetMachine
&TM AMDIL_OPT_LEVEL_DECL
);
37 virtual ~AMDILDAGToDAGISel();
38 inline SDValue
getSmallIPtrImm(unsigned Imm
);
40 SDNode
*Select(SDNode
*N
);
41 // Complex pattern selectors
42 bool SelectADDRParam(SDValue Addr
, SDValue
& R1
, SDValue
& R2
);
43 bool SelectADDR(SDValue N
, SDValue
&R1
, SDValue
&R2
);
44 bool SelectADDR64(SDValue N
, SDValue
&R1
, SDValue
&R2
);
45 static bool isGlobalStore(const StoreSDNode
*N
);
46 static bool isPrivateStore(const StoreSDNode
*N
);
47 static bool isLocalStore(const StoreSDNode
*N
);
48 static bool isRegionStore(const StoreSDNode
*N
);
50 static bool isCPLoad(const LoadSDNode
*N
);
51 static bool isConstantLoad(const LoadSDNode
*N
, int cbID
);
52 static bool isGlobalLoad(const LoadSDNode
*N
);
53 static bool isPrivateLoad(const LoadSDNode
*N
);
54 static bool isLocalLoad(const LoadSDNode
*N
);
55 static bool isRegionLoad(const LoadSDNode
*N
);
57 virtual const char *getPassName() const;
59 SDNode
*xformAtomicInst(SDNode
*N
);
61 // Include the pieces autogenerated from the target description.
62 #include "AMDILGenDAGISel.inc"
64 } // end anonymous namespace
66 // createAMDILISelDag - This pass converts a legalized DAG into a AMDIL-specific
67 // DAG, ready for instruction scheduling.
69 FunctionPass
*llvm::createAMDILISelDag(AMDILTargetMachine
&TM
70 AMDIL_OPT_LEVEL_DECL
) {
71 return new AMDILDAGToDAGISel(TM AMDIL_OPT_LEVEL_VAR
);
74 AMDILDAGToDAGISel::AMDILDAGToDAGISel(AMDILTargetMachine
&TM
76 : SelectionDAGISel(TM AMDIL_OPT_LEVEL_VAR
), Subtarget(TM
.getSubtarget
<AMDILSubtarget
>())
80 AMDILDAGToDAGISel::~AMDILDAGToDAGISel() {
83 SDValue
AMDILDAGToDAGISel::getSmallIPtrImm(unsigned int Imm
) {
84 return CurDAG
->getTargetConstant(Imm
, MVT::i32
);
87 bool AMDILDAGToDAGISel::SelectADDRParam(
88 SDValue Addr
, SDValue
& R1
, SDValue
& R2
) {
90 if (Addr
.getOpcode() == ISD::FrameIndex
) {
91 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
92 R1
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
93 R2
= CurDAG
->getTargetConstant(0, MVT::i32
);
96 R2
= CurDAG
->getTargetConstant(0, MVT::i32
);
98 } else if (Addr
.getOpcode() == ISD::ADD
) {
99 R1
= Addr
.getOperand(0);
100 R2
= Addr
.getOperand(1);
103 R2
= CurDAG
->getTargetConstant(0, MVT::i32
);
108 bool AMDILDAGToDAGISel::SelectADDR(SDValue Addr
, SDValue
& R1
, SDValue
& R2
) {
109 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
110 Addr
.getOpcode() == ISD::TargetGlobalAddress
) {
113 return SelectADDRParam(Addr
, R1
, R2
);
117 bool AMDILDAGToDAGISel::SelectADDR64(SDValue Addr
, SDValue
& R1
, SDValue
& R2
) {
118 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
119 Addr
.getOpcode() == ISD::TargetGlobalAddress
) {
123 if (Addr
.getOpcode() == ISD::FrameIndex
) {
124 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
125 R1
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i64
);
126 R2
= CurDAG
->getTargetConstant(0, MVT::i64
);
129 R2
= CurDAG
->getTargetConstant(0, MVT::i64
);
131 } else if (Addr
.getOpcode() == ISD::ADD
) {
132 R1
= Addr
.getOperand(0);
133 R2
= Addr
.getOperand(1);
136 R2
= CurDAG
->getTargetConstant(0, MVT::i64
);
141 SDNode
*AMDILDAGToDAGISel::Select(SDNode
*N
) {
142 unsigned int Opc
= N
->getOpcode();
143 if (N
->isMachineOpcode()) {
144 return NULL
; // Already selected.
148 case ISD::FrameIndex
:
150 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(N
)) {
151 unsigned int FI
= FIN
->getIndex();
152 EVT OpVT
= N
->getValueType(0);
153 unsigned int NewOpc
= AMDIL::MOVE_i32
;
154 SDValue TFI
= CurDAG
->getTargetFrameIndex(FI
, MVT::i32
);
155 return CurDAG
->SelectNodeTo(N
, NewOpc
, OpVT
, TFI
);
160 // For all atomic instructions, we need to add a constant
161 // operand that stores the resource ID in the instruction
162 if (Opc
> AMDILISD::ADDADDR
&& Opc
< AMDILISD::APPEND_ALLOC
) {
163 N
= xformAtomicInst(N
);
165 return SelectCode(N
);
168 bool AMDILDAGToDAGISel::isGlobalStore(const StoreSDNode
*N
) {
169 return check_type(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
);
172 bool AMDILDAGToDAGISel::isPrivateStore(const StoreSDNode
*N
) {
173 return (!check_type(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
)
174 && !check_type(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
)
175 && !check_type(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
));
178 bool AMDILDAGToDAGISel::isLocalStore(const StoreSDNode
*N
) {
179 return check_type(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
);
182 bool AMDILDAGToDAGISel::isRegionStore(const StoreSDNode
*N
) {
183 return check_type(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
);
186 bool AMDILDAGToDAGISel::isConstantLoad(const LoadSDNode
*N
, int cbID
) {
187 if (check_type(N
->getSrcValue(), AMDILAS::CONSTANT_ADDRESS
)) {
190 MachineMemOperand
*MMO
= N
->getMemOperand();
191 const Value
*V
= MMO
->getValue();
192 const Value
*BV
= getBasePointerValue(V
);
195 && ((V
&& dyn_cast
<GlobalValue
>(V
))
196 || (BV
&& dyn_cast
<GlobalValue
>(
197 getBasePointerValue(MMO
->getValue()))))) {
198 return check_type(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
);
204 bool AMDILDAGToDAGISel::isGlobalLoad(const LoadSDNode
*N
) {
205 return check_type(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
);
208 bool AMDILDAGToDAGISel::isLocalLoad(const LoadSDNode
*N
) {
209 return check_type(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
);
212 bool AMDILDAGToDAGISel::isRegionLoad(const LoadSDNode
*N
) {
213 return check_type(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
);
216 bool AMDILDAGToDAGISel::isCPLoad(const LoadSDNode
*N
) {
217 MachineMemOperand
*MMO
= N
->getMemOperand();
218 if (check_type(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
)) {
220 const Value
*V
= MMO
->getValue();
221 const PseudoSourceValue
*PSV
= dyn_cast
<PseudoSourceValue
>(V
);
222 if (PSV
&& PSV
== PseudoSourceValue::getConstantPool()) {
230 bool AMDILDAGToDAGISel::isPrivateLoad(const LoadSDNode
*N
) {
231 if (check_type(N
->getSrcValue(), AMDILAS::PRIVATE_ADDRESS
)) {
232 // Check to make sure we are not a constant pool load or a constant load
233 // that is marked as a private load
234 if (isCPLoad(N
) || isConstantLoad(N
, -1)) {
238 if (!check_type(N
->getSrcValue(), AMDILAS::LOCAL_ADDRESS
)
239 && !check_type(N
->getSrcValue(), AMDILAS::GLOBAL_ADDRESS
)
240 && !check_type(N
->getSrcValue(), AMDILAS::REGION_ADDRESS
)
241 && !check_type(N
->getSrcValue(), AMDILAS::CONSTANT_ADDRESS
)
242 && !check_type(N
->getSrcValue(), AMDILAS::PARAM_D_ADDRESS
)
243 && !check_type(N
->getSrcValue(), AMDILAS::PARAM_I_ADDRESS
))
250 const char *AMDILDAGToDAGISel::getPassName() const {
251 return "AMDIL DAG->DAG Pattern Instruction Selection";
255 AMDILDAGToDAGISel::xformAtomicInst(SDNode
*N
)
259 // bool bitCastToInt = (N->getValueType(0) == MVT::f32);
260 unsigned opc
= N
->getOpcode();
263 case AMDILISD::ATOM_G_ADD
:
264 case AMDILISD::ATOM_G_AND
:
265 case AMDILISD::ATOM_G_MAX
:
266 case AMDILISD::ATOM_G_UMAX
:
267 case AMDILISD::ATOM_G_MIN
:
268 case AMDILISD::ATOM_G_UMIN
:
269 case AMDILISD::ATOM_G_OR
:
270 case AMDILISD::ATOM_G_SUB
:
271 case AMDILISD::ATOM_G_RSUB
:
272 case AMDILISD::ATOM_G_XCHG
:
273 case AMDILISD::ATOM_G_XOR
:
274 case AMDILISD::ATOM_G_ADD_NORET
:
275 case AMDILISD::ATOM_G_AND_NORET
:
276 case AMDILISD::ATOM_G_MAX_NORET
:
277 case AMDILISD::ATOM_G_UMAX_NORET
:
278 case AMDILISD::ATOM_G_MIN_NORET
:
279 case AMDILISD::ATOM_G_UMIN_NORET
:
280 case AMDILISD::ATOM_G_OR_NORET
:
281 case AMDILISD::ATOM_G_SUB_NORET
:
282 case AMDILISD::ATOM_G_RSUB_NORET
:
283 case AMDILISD::ATOM_G_XCHG_NORET
:
284 case AMDILISD::ATOM_G_XOR_NORET
:
285 case AMDILISD::ATOM_L_ADD
:
286 case AMDILISD::ATOM_L_AND
:
287 case AMDILISD::ATOM_L_MAX
:
288 case AMDILISD::ATOM_L_UMAX
:
289 case AMDILISD::ATOM_L_MIN
:
290 case AMDILISD::ATOM_L_UMIN
:
291 case AMDILISD::ATOM_L_OR
:
292 case AMDILISD::ATOM_L_SUB
:
293 case AMDILISD::ATOM_L_RSUB
:
294 case AMDILISD::ATOM_L_XCHG
:
295 case AMDILISD::ATOM_L_XOR
:
296 case AMDILISD::ATOM_L_ADD_NORET
:
297 case AMDILISD::ATOM_L_AND_NORET
:
298 case AMDILISD::ATOM_L_MAX_NORET
:
299 case AMDILISD::ATOM_L_UMAX_NORET
:
300 case AMDILISD::ATOM_L_MIN_NORET
:
301 case AMDILISD::ATOM_L_UMIN_NORET
:
302 case AMDILISD::ATOM_L_OR_NORET
:
303 case AMDILISD::ATOM_L_SUB_NORET
:
304 case AMDILISD::ATOM_L_RSUB_NORET
:
305 case AMDILISD::ATOM_L_XCHG_NORET
:
306 case AMDILISD::ATOM_L_XOR_NORET
:
307 case AMDILISD::ATOM_R_ADD
:
308 case AMDILISD::ATOM_R_AND
:
309 case AMDILISD::ATOM_R_MAX
:
310 case AMDILISD::ATOM_R_UMAX
:
311 case AMDILISD::ATOM_R_MIN
:
312 case AMDILISD::ATOM_R_UMIN
:
313 case AMDILISD::ATOM_R_OR
:
314 case AMDILISD::ATOM_R_SUB
:
315 case AMDILISD::ATOM_R_RSUB
:
316 case AMDILISD::ATOM_R_XCHG
:
317 case AMDILISD::ATOM_R_XOR
:
318 case AMDILISD::ATOM_R_ADD_NORET
:
319 case AMDILISD::ATOM_R_AND_NORET
:
320 case AMDILISD::ATOM_R_MAX_NORET
:
321 case AMDILISD::ATOM_R_UMAX_NORET
:
322 case AMDILISD::ATOM_R_MIN_NORET
:
323 case AMDILISD::ATOM_R_UMIN_NORET
:
324 case AMDILISD::ATOM_R_OR_NORET
:
325 case AMDILISD::ATOM_R_SUB_NORET
:
326 case AMDILISD::ATOM_R_RSUB_NORET
:
327 case AMDILISD::ATOM_R_XCHG_NORET
:
328 case AMDILISD::ATOM_R_XOR_NORET
:
329 case AMDILISD::ATOM_G_CMPXCHG
:
330 case AMDILISD::ATOM_G_CMPXCHG_NORET
:
331 case AMDILISD::ATOM_L_CMPXCHG
:
332 case AMDILISD::ATOM_L_CMPXCHG_NORET
:
333 case AMDILISD::ATOM_R_CMPXCHG
:
334 case AMDILISD::ATOM_R_CMPXCHG_NORET
:
336 case AMDILISD::ATOM_G_DEC
:
338 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
339 addVal
= (uint32_t)-1;
341 opc
= AMDILISD::ATOM_G_SUB
;
344 case AMDILISD::ATOM_G_INC
:
346 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
347 addVal
= (uint32_t)-1;
349 opc
= AMDILISD::ATOM_G_ADD
;
352 case AMDILISD::ATOM_G_DEC_NORET
:
354 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
355 addVal
= (uint32_t)-1;
357 opc
= AMDILISD::ATOM_G_SUB_NORET
;
360 case AMDILISD::ATOM_G_INC_NORET
:
362 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
363 addVal
= (uint32_t)-1;
365 opc
= AMDILISD::ATOM_G_ADD_NORET
;
368 case AMDILISD::ATOM_L_DEC
:
370 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
371 addVal
= (uint32_t)-1;
373 opc
= AMDILISD::ATOM_L_SUB
;
376 case AMDILISD::ATOM_L_INC
:
378 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
379 addVal
= (uint32_t)-1;
381 opc
= AMDILISD::ATOM_L_ADD
;
384 case AMDILISD::ATOM_L_DEC_NORET
:
386 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
387 addVal
= (uint32_t)-1;
389 opc
= AMDILISD::ATOM_L_SUB_NORET
;
392 case AMDILISD::ATOM_L_INC_NORET
:
394 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
395 addVal
= (uint32_t)-1;
397 opc
= AMDILISD::ATOM_L_ADD_NORET
;
400 case AMDILISD::ATOM_R_DEC
:
402 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
403 addVal
= (uint32_t)-1;
405 opc
= AMDILISD::ATOM_R_SUB
;
408 case AMDILISD::ATOM_R_INC
:
410 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
411 addVal
= (uint32_t)-1;
413 opc
= AMDILISD::ATOM_R_ADD
;
416 case AMDILISD::ATOM_R_DEC_NORET
:
418 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
419 addVal
= (uint32_t)-1;
421 opc
= AMDILISD::ATOM_R_SUB
;
424 case AMDILISD::ATOM_R_INC_NORET
:
426 if (Subtarget
.calVersion() >= CAL_VERSION_SC_136
) {
427 addVal
= (uint32_t)-1;
429 opc
= AMDILISD::ATOM_R_ADD_NORET
;
433 // The largest we can have is a cmpxchg w/ a return value and an output chain.
434 // The cmpxchg function has 3 inputs and a single output along with an
435 // output change and a target constant, giving a total of 6.
438 unsigned y
= N
->getNumOperands();
439 for (x
= 0; x
< y
; ++x
) {
440 Ops
[x
] = N
->getOperand(x
);
443 Ops
[x
++] = SDValue(SelectCode(CurDAG
->getConstant(addVal
, MVT::i32
).getNode()), 0);
445 Ops
[x
++] = CurDAG
->getTargetConstant(0, MVT::i32
);
446 SDVTList Tys
= N
->getVTList();
447 MemSDNode
*MemNode
= dyn_cast
<MemSDNode
>(N
);
448 assert(MemNode
&& "Atomic should be of MemSDNode type!");
449 N
= CurDAG
->getMemIntrinsicNode(opc
, N
->getDebugLoc(), Tys
, Ops
, x
,
450 MemNode
->getMemoryVT(), MemNode
->getMemOperand()).getNode();