radeon/llvm: Add DAG nodes for MIN instructions
[mesa.git] / src / gallium / drivers / radeon / AMDGPUISelLowering.cpp
1 //===-- AMDGPUISelLowering.cpp - AMDGPU Common DAG lowering functions -----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This is the parent TargetLowering class for hardware code gen targets.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "AMDGPUISelLowering.h"
15 #include "AMDILIntrinsicInfo.h"
16 #include "AMDGPUUtil.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18
19 using namespace llvm;
20
21 AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) :
22 AMDILTargetLowering(TM)
23 {
24 // We need to custom lower some of the intrinsics
25 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
26 }
27
28 SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
29 const
30 {
31 switch (Op.getOpcode()) {
32 default: return AMDILTargetLowering::LowerOperation(Op, DAG);
33 case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
34 }
35 }
36
37 SDValue AMDGPUTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
38 SelectionDAG &DAG) const
39 {
40 unsigned IntrinsicID = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
41 DebugLoc DL = Op.getDebugLoc();
42 EVT VT = Op.getValueType();
43
44 switch (IntrinsicID) {
45 default: return Op;
46 case AMDGPUIntrinsic::AMDIL_abs:
47 return LowerIntrinsicIABS(Op, DAG);
48 case AMDGPUIntrinsic::AMDGPU_lrp:
49 return LowerIntrinsicLRP(Op, DAG);
50 case AMDGPUIntrinsic::AMDIL_mad:
51 return DAG.getNode(AMDILISD::MAD, DL, VT, Op.getOperand(1),
52 Op.getOperand(2), Op.getOperand(3));
53 case AMDGPUIntrinsic::AMDIL_max:
54 return DAG.getNode(AMDGPUISD::FMAX, DL, VT, Op.getOperand(1),
55 Op.getOperand(2));
56 case AMDGPUIntrinsic::AMDGPU_imax:
57 return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Op.getOperand(1),
58 Op.getOperand(2));
59 case AMDGPUIntrinsic::AMDGPU_umax:
60 return DAG.getNode(AMDGPUISD::UMAX, DL, VT, Op.getOperand(1),
61 Op.getOperand(2));
62 case AMDGPUIntrinsic::AMDIL_min:
63 return DAG.getNode(AMDGPUISD::FMIN, DL, VT, Op.getOperand(1),
64 Op.getOperand(2));
65 case AMDGPUIntrinsic::AMDGPU_imin:
66 return DAG.getNode(AMDGPUISD::SMIN, DL, VT, Op.getOperand(1),
67 Op.getOperand(2));
68 case AMDGPUIntrinsic::AMDGPU_umin:
69 return DAG.getNode(AMDGPUISD::UMIN, DL, VT, Op.getOperand(1),
70 Op.getOperand(2));
71 }
72 }
73
74 ///IABS(a) = SMAX(sub(0, a), a)
75 SDValue AMDGPUTargetLowering::LowerIntrinsicIABS(SDValue Op,
76 SelectionDAG &DAG) const
77 {
78
79 DebugLoc DL = Op.getDebugLoc();
80 EVT VT = Op.getValueType();
81 SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, VT),
82 Op.getOperand(1));
83
84 return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Neg, Op.getOperand(1));
85 }
86
87 /// Linear Interpolation
88 /// LRP(a, b, c) = muladd(a, b, (1 - a) * c)
89 SDValue AMDGPUTargetLowering::LowerIntrinsicLRP(SDValue Op,
90 SelectionDAG &DAG) const
91 {
92 DebugLoc DL = Op.getDebugLoc();
93 EVT VT = Op.getValueType();
94 SDValue OneSubA = DAG.getNode(ISD::FSUB, DL, VT, DAG.getConstant(1, VT),
95 Op.getOperand(1));
96 SDValue OneSubAC = DAG.getNode(ISD::FMUL, DL, VT, OneSubA,
97 Op.getOperand(3));
98 return DAG.getNode(AMDILISD::MAD, DL, VT, Op.getOperand(1),
99 Op.getOperand(2),
100 OneSubAC);
101 }
102
103 void AMDGPUTargetLowering::addLiveIn(MachineInstr * MI,
104 MachineFunction * MF, MachineRegisterInfo & MRI,
105 const TargetInstrInfo * TII, unsigned reg) const
106 {
107 AMDGPU::utilAddLiveIn(MF, MRI, TII, reg, MI->getOperand(0).getReg());
108 }
109
110 #define NODE_NAME_CASE(node) case AMDGPUISD::node: return #node;
111
112 const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const
113 {
114 switch (Opcode) {
115 default: return AMDILTargetLowering::getTargetNodeName(Opcode);
116
117 NODE_NAME_CASE(FMAX)
118 NODE_NAME_CASE(SMAX)
119 NODE_NAME_CASE(UMAX)
120 NODE_NAME_CASE(FMIN)
121 NODE_NAME_CASE(SMIN)
122 NODE_NAME_CASE(UMIN)
123 }
124 }