radeon/llvm: Lower lrp intrinsic during ISel
[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 }
63 }
64
65 ///IABS(a) = SMAX(sub(0, a), a)
66 SDValue AMDGPUTargetLowering::LowerIntrinsicIABS(SDValue Op,
67 SelectionDAG &DAG) const
68 {
69
70 DebugLoc DL = Op.getDebugLoc();
71 EVT VT = Op.getValueType();
72 SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, VT),
73 Op.getOperand(1));
74
75 return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Neg, Op.getOperand(1));
76 }
77
78 /// Linear Interpolation
79 /// LRP(a, b, c) = muladd(a, b, (1 - a) * c)
80 SDValue AMDGPUTargetLowering::LowerIntrinsicLRP(SDValue Op,
81 SelectionDAG &DAG) const
82 {
83 DebugLoc DL = Op.getDebugLoc();
84 EVT VT = Op.getValueType();
85 SDValue OneSubA = DAG.getNode(ISD::FSUB, DL, VT, DAG.getConstant(1, VT),
86 Op.getOperand(1));
87 SDValue OneSubAC = DAG.getNode(ISD::FMUL, DL, VT, OneSubA,
88 Op.getOperand(3));
89 return DAG.getNode(AMDILISD::MAD, DL, VT, Op.getOperand(1),
90 Op.getOperand(2),
91 OneSubAC);
92 }
93
94 void AMDGPUTargetLowering::addLiveIn(MachineInstr * MI,
95 MachineFunction * MF, MachineRegisterInfo & MRI,
96 const TargetInstrInfo * TII, unsigned reg) const
97 {
98 AMDGPU::utilAddLiveIn(MF, MRI, TII, reg, MI->getOperand(0).getReg());
99 }
100
101 #define NODE_NAME_CASE(node) case AMDGPUISD::node: return #node;
102
103 const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const
104 {
105 switch (Opcode) {
106 default: return AMDILTargetLowering::getTargetNodeName(Opcode);
107
108 NODE_NAME_CASE(FMAX)
109 NODE_NAME_CASE(SMAX)
110 NODE_NAME_CASE(UMAX)
111 }
112 }