1 //===-- AMDGPUISelLowering.cpp - AMDGPU Common DAG lowering functions -----===//
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 is the parent TargetLowering class for hardware code gen targets.
12 //===----------------------------------------------------------------------===//
14 #include "AMDGPUISelLowering.h"
15 #include "AMDILIntrinsicInfo.h"
16 #include "AMDGPUUtil.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine
&TM
) :
22 AMDILTargetLowering(TM
)
24 // We need to custom lower some of the intrinsics
25 setOperationAction(ISD::INTRINSIC_WO_CHAIN
, MVT::Other
, Custom
);
27 setOperationAction(ISD::SELECT_CC
, MVT::f32
, Custom
);
28 setOperationAction(ISD::SELECT_CC
, MVT::i32
, Custom
);
30 // Library functions. These default to Expand, but we have instructions
32 setOperationAction(ISD::FCEIL
, MVT::f32
, Legal
);
33 setOperationAction(ISD::FRINT
, MVT::f32
, Legal
);
37 SDValue
AMDGPUTargetLowering::LowerOperation(SDValue Op
, SelectionDAG
&DAG
)
40 switch (Op
.getOpcode()) {
41 default: return AMDILTargetLowering::LowerOperation(Op
, DAG
);
42 case ISD::INTRINSIC_WO_CHAIN
: return LowerINTRINSIC_WO_CHAIN(Op
, DAG
);
43 case ISD::SELECT_CC
: return LowerSELECT_CC(Op
, DAG
);
47 SDValue
AMDGPUTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op
,
48 SelectionDAG
&DAG
) const
50 unsigned IntrinsicID
= cast
<ConstantSDNode
>(Op
.getOperand(0))->getZExtValue();
51 DebugLoc DL
= Op
.getDebugLoc();
52 EVT VT
= Op
.getValueType();
54 switch (IntrinsicID
) {
56 case AMDGPUIntrinsic::AMDIL_abs
:
57 return LowerIntrinsicIABS(Op
, DAG
);
58 case AMDGPUIntrinsic::AMDGPU_lrp
:
59 return LowerIntrinsicLRP(Op
, DAG
);
60 case AMDGPUIntrinsic::AMDIL_fraction
:
61 return DAG
.getNode(AMDGPUISD::FRACT
, DL
, VT
, Op
.getOperand(1));
62 case AMDGPUIntrinsic::AMDIL_mad
:
63 return DAG
.getNode(AMDILISD::MAD
, DL
, VT
, Op
.getOperand(1),
64 Op
.getOperand(2), Op
.getOperand(3));
65 case AMDGPUIntrinsic::AMDIL_max
:
66 return DAG
.getNode(AMDGPUISD::FMAX
, DL
, VT
, Op
.getOperand(1),
68 case AMDGPUIntrinsic::AMDGPU_imax
:
69 return DAG
.getNode(AMDGPUISD::SMAX
, DL
, VT
, Op
.getOperand(1),
71 case AMDGPUIntrinsic::AMDGPU_umax
:
72 return DAG
.getNode(AMDGPUISD::UMAX
, DL
, VT
, Op
.getOperand(1),
74 case AMDGPUIntrinsic::AMDIL_min
:
75 return DAG
.getNode(AMDGPUISD::FMIN
, DL
, VT
, Op
.getOperand(1),
77 case AMDGPUIntrinsic::AMDGPU_imin
:
78 return DAG
.getNode(AMDGPUISD::SMIN
, DL
, VT
, Op
.getOperand(1),
80 case AMDGPUIntrinsic::AMDGPU_umin
:
81 return DAG
.getNode(AMDGPUISD::UMIN
, DL
, VT
, Op
.getOperand(1),
83 case AMDGPUIntrinsic::AMDIL_round_nearest
:
84 return DAG
.getNode(ISD::FRINT
, DL
, VT
, Op
.getOperand(1));
85 case AMDGPUIntrinsic::AMDIL_round_posinf
:
86 return DAG
.getNode(ISD::FCEIL
, DL
, VT
, Op
.getOperand(1));
90 ///IABS(a) = SMAX(sub(0, a), a)
91 SDValue
AMDGPUTargetLowering::LowerIntrinsicIABS(SDValue Op
,
92 SelectionDAG
&DAG
) const
95 DebugLoc DL
= Op
.getDebugLoc();
96 EVT VT
= Op
.getValueType();
97 SDValue Neg
= DAG
.getNode(ISD::SUB
, DL
, VT
, DAG
.getConstant(0, VT
),
100 return DAG
.getNode(AMDGPUISD::SMAX
, DL
, VT
, Neg
, Op
.getOperand(1));
103 /// Linear Interpolation
104 /// LRP(a, b, c) = muladd(a, b, (1 - a) * c)
105 SDValue
AMDGPUTargetLowering::LowerIntrinsicLRP(SDValue Op
,
106 SelectionDAG
&DAG
) const
108 DebugLoc DL
= Op
.getDebugLoc();
109 EVT VT
= Op
.getValueType();
110 SDValue OneSubA
= DAG
.getNode(ISD::FSUB
, DL
, VT
,
111 DAG
.getConstantFP(1.0f
, MVT::f32
),
113 SDValue OneSubAC
= DAG
.getNode(ISD::FMUL
, DL
, VT
, OneSubA
,
115 return DAG
.getNode(AMDILISD::MAD
, DL
, VT
, Op
.getOperand(1),
120 SDValue
AMDGPUTargetLowering::LowerSELECT_CC(SDValue Op
,
121 SelectionDAG
&DAG
) const
123 DebugLoc DL
= Op
.getDebugLoc();
124 EVT VT
= Op
.getValueType();
126 SDValue LHS
= Op
.getOperand(0);
127 SDValue RHS
= Op
.getOperand(1);
128 SDValue True
= Op
.getOperand(2);
129 SDValue False
= Op
.getOperand(3);
130 SDValue CC
= Op
.getOperand(4);
131 ISD::CondCode CCOpcode
= cast
<CondCodeSDNode
>(CC
)->get();
134 // LHS and RHS are guaranteed to be the same value type
135 EVT CompareVT
= LHS
.getValueType();
137 // We need all the operands of SELECT_CC to have the same value type, so if
138 // necessary we need to convert LHS and RHS to be the same type True and
139 // False. True and False are guaranteed to have the same type as this
142 if (CompareVT
!= VT
) {
143 ISD::NodeType ConversionOp
= ISD::DELETED_NODE
;
144 if (VT
== MVT::f32
&& CompareVT
== MVT::i32
) {
145 if (isUnsignedIntSetCC(CCOpcode
)) {
146 ConversionOp
= ISD::UINT_TO_FP
;
148 ConversionOp
= ISD::SINT_TO_FP
;
150 } else if (VT
== MVT::i32
&& CompareVT
== MVT::f32
) {
151 ConversionOp
= ISD::FP_TO_SINT
;
153 // I don't think there will be any other type pairings.
154 assert(!"Unhandled operand type parings in SELECT_CC");
156 // XXX Check the value of LHS and RHS and avoid creating sequences like
158 LHS
= DAG
.getNode(ConversionOp
, DL
, VT
, LHS
);
159 RHS
= DAG
.getNode(ConversionOp
, DL
, VT
, RHS
);
162 // If True is a hardware TRUE value and False is a hardware FALSE value or
163 // vice-versa we can handle this with a native instruction (SET* instructions).
164 if ((isHWTrueValue(True
) && isHWFalseValue(False
))) {
165 return DAG
.getNode(ISD::SELECT_CC
, DL
, VT
, LHS
, RHS
, True
, False
, CC
);
168 // XXX If True is a hardware TRUE value and False is a hardware FALSE value,
169 // we can handle this with a native instruction, but we need to swap true
170 // and false and change the conditional.
171 if (isHWTrueValue(False
) && isHWFalseValue(True
)) {
174 // XXX Check if we can lower this to a SELECT or if it is supported by a native
175 // operation. (The code below does this but we don't have the Instruction
176 // selection patterns to do this yet.
178 if (isZero(LHS
) || isZero(RHS
)) {
179 SDValue Cond
= (isZero(LHS
) ? RHS
: LHS
);
190 // We can lower to select
197 return DAG
.getNode(ISD::SELECT
, DL
, VT
, Cond
, True
, False
);
199 // Supported by a native operation (CNDGE, CNDGT)
200 return DAG
.getNode(ISD::SELECT_CC
, DL
, VT
, LHS
, RHS
, True
, False
, CC
);
205 // If we make it this for it means we have no native instructions to handle
206 // this SELECT_CC, so we must lower it.
207 SDValue HWTrue
, HWFalse
;
209 if (VT
== MVT::f32
) {
210 HWTrue
= DAG
.getConstantFP(1.0f
, VT
);
211 HWFalse
= DAG
.getConstantFP(0.0f
, VT
);
212 } else if (VT
== MVT::i32
) {
213 HWTrue
= DAG
.getConstant(-1, VT
);
214 HWFalse
= DAG
.getConstant(0, VT
);
217 assert(!"Unhandled value type in LowerSELECT_CC");
220 // Lower this unsupported SELECT_CC into a combination of two supported
221 // SELECT_CC operations.
222 SDValue Cond
= DAG
.getNode(ISD::SELECT_CC
, DL
, VT
, LHS
, RHS
, HWTrue
, HWFalse
, CC
);
224 return DAG
.getNode(ISD::SELECT
, DL
, VT
, Cond
, True
, False
);
227 //===----------------------------------------------------------------------===//
229 //===----------------------------------------------------------------------===//
231 bool AMDGPUTargetLowering::isHWTrueValue(SDValue Op
) const
233 if (ConstantFPSDNode
* CFP
= dyn_cast
<ConstantFPSDNode
>(Op
)) {
234 return CFP
->isExactlyValue(1.0);
236 if (ConstantSDNode
*C
= dyn_cast
<ConstantSDNode
>(Op
)) {
237 return C
->isAllOnesValue();
242 bool AMDGPUTargetLowering::isHWFalseValue(SDValue Op
) const
244 if (ConstantFPSDNode
* CFP
= dyn_cast
<ConstantFPSDNode
>(Op
)) {
245 return CFP
->getValueAPF().isZero();
247 if (ConstantSDNode
*C
= dyn_cast
<ConstantSDNode
>(Op
)) {
248 return C
->isNullValue();
253 void AMDGPUTargetLowering::addLiveIn(MachineInstr
* MI
,
254 MachineFunction
* MF
, MachineRegisterInfo
& MRI
,
255 const TargetInstrInfo
* TII
, unsigned reg
) const
257 AMDGPU::utilAddLiveIn(MF
, MRI
, TII
, reg
, MI
->getOperand(0).getReg());
260 #define NODE_NAME_CASE(node) case AMDGPUISD::node: return #node;
262 const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode
) const
265 default: return AMDILTargetLowering::getTargetNodeName(Opcode
);
267 NODE_NAME_CASE(FRACT
)