radeon/llvm: Use a custom inserter to lower CLAMP
[mesa.git] / src / gallium / drivers / radeon / SIISelLowering.cpp
1 //===-- SIISelLowering.cpp - SI DAG Lowering Implementation ---------------===//
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 // Most of the DAG lowering is handled in AMDILISelLowering.cpp. This file is
11 // mostly EmitInstrWithCustomInserter().
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "SIISelLowering.h"
16 #include "SIInstrInfo.h"
17 #include "SIRegisterInfo.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19
20 using namespace llvm;
21
22 SITargetLowering::SITargetLowering(TargetMachine &TM) :
23 AMDGPUTargetLowering(TM),
24 TII(static_cast<const SIInstrInfo*>(TM.getInstrInfo()))
25 {
26 addRegisterClass(MVT::v4f32, &AMDIL::VReg_128RegClass);
27 addRegisterClass(MVT::f32, &AMDIL::VReg_32RegClass);
28
29 setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Legal);
30 setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Legal);
31 }
32
33 MachineBasicBlock * SITargetLowering::EmitInstrWithCustomInserter(
34 MachineInstr * MI, MachineBasicBlock * BB) const
35 {
36 const TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
37 MachineRegisterInfo & MRI = BB->getParent()->getRegInfo();
38 MachineBasicBlock::iterator I = MI;
39
40 if (TII->get(MI->getOpcode()).TSFlags & SIInstrFlags::NEED_WAIT) {
41 AppendS_WAITCNT(MI, *BB, llvm::next(I));
42 return BB;
43 }
44
45 switch (MI->getOpcode()) {
46 default:
47 return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB);
48
49 case AMDIL::CLAMP_SI:
50 BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDIL::V_MOV_B32_e64))
51 .addOperand(MI->getOperand(0))
52 .addOperand(MI->getOperand(1))
53 /* VSRC1-2 are unused, but we still need to fill all the
54 * operand slots, so we just reuse the VSRC0 operand */
55 .addOperand(MI->getOperand(1))
56 .addOperand(MI->getOperand(1))
57 .addImm(0) // ABS
58 .addImm(1) // CLAMP
59 .addImm(0) // OMOD
60 .addImm(0); // NEG
61 MI->eraseFromParent();
62 break;
63
64 case AMDIL::FABS_SI:
65 BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDIL::V_MOV_B32_e64))
66 .addOperand(MI->getOperand(0))
67 .addOperand(MI->getOperand(1))
68 /* VSRC1-2 are unused, but we still need to fill all the
69 * operand slots, so we just reuse the VSRC0 operand */
70 .addOperand(MI->getOperand(1))
71 .addOperand(MI->getOperand(1))
72 .addImm(1) // ABS
73 .addImm(0) // CLAMP
74 .addImm(0) // OMOD
75 .addImm(0); // NEG
76 MI->eraseFromParent();
77 break;
78
79 case AMDIL::SI_INTERP:
80 LowerSI_INTERP(MI, *BB, I, MRI);
81 break;
82 case AMDIL::SI_INTERP_CONST:
83 LowerSI_INTERP_CONST(MI, *BB, I);
84 break;
85 case AMDIL::SI_V_CNDLT:
86 LowerSI_V_CNDLT(MI, *BB, I, MRI);
87 break;
88 case AMDIL::USE_SGPR_32:
89 case AMDIL::USE_SGPR_64:
90 lowerUSE_SGPR(MI, BB->getParent(), MRI);
91 MI->eraseFromParent();
92 break;
93 case AMDIL::VS_LOAD_BUFFER_INDEX:
94 addLiveIn(MI, BB->getParent(), MRI, TII, AMDIL::VGPR0);
95 MI->eraseFromParent();
96 break;
97 }
98 return BB;
99 }
100
101 void SITargetLowering::AppendS_WAITCNT(MachineInstr *MI, MachineBasicBlock &BB,
102 MachineBasicBlock::iterator I) const
103 {
104 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_WAITCNT))
105 .addImm(0);
106 }
107
108 void SITargetLowering::LowerSI_INTERP(MachineInstr *MI, MachineBasicBlock &BB,
109 MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
110 {
111 unsigned tmp = MRI.createVirtualRegister(&AMDIL::VReg_32RegClass);
112 MachineOperand dst = MI->getOperand(0);
113 MachineOperand iReg = MI->getOperand(1);
114 MachineOperand jReg = MI->getOperand(2);
115 MachineOperand attr_chan = MI->getOperand(3);
116 MachineOperand attr = MI->getOperand(4);
117 MachineOperand params = MI->getOperand(5);
118
119 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
120 .addReg(AMDIL::M0)
121 .addOperand(params);
122
123 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P1_F32), tmp)
124 .addOperand(iReg)
125 .addOperand(attr_chan)
126 .addOperand(attr);
127
128 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P2_F32))
129 .addOperand(dst)
130 .addReg(tmp)
131 .addOperand(jReg)
132 .addOperand(attr_chan)
133 .addOperand(attr);
134
135 MI->eraseFromParent();
136 }
137
138 void SITargetLowering::LowerSI_INTERP_CONST(MachineInstr *MI,
139 MachineBasicBlock &BB, MachineBasicBlock::iterator I) const
140 {
141 MachineOperand dst = MI->getOperand(0);
142 MachineOperand attr_chan = MI->getOperand(1);
143 MachineOperand attr = MI->getOperand(2);
144 MachineOperand params = MI->getOperand(3);
145
146 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
147 .addReg(AMDIL::M0)
148 .addOperand(params);
149
150 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_MOV_F32))
151 .addOperand(dst)
152 .addOperand(attr_chan)
153 .addOperand(attr);
154
155 MI->eraseFromParent();
156 }
157
158 void SITargetLowering::LowerSI_V_CNDLT(MachineInstr *MI, MachineBasicBlock &BB,
159 MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
160 {
161 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CMP_LT_F32_e32))
162 .addOperand(MI->getOperand(1))
163 .addReg(AMDIL::SREG_LIT_0);
164
165 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CNDMASK_B32))
166 .addOperand(MI->getOperand(0))
167 .addOperand(MI->getOperand(2))
168 .addOperand(MI->getOperand(3));
169
170 MI->eraseFromParent();
171 }
172
173 void SITargetLowering::lowerUSE_SGPR(MachineInstr *MI,
174 MachineFunction * MF, MachineRegisterInfo & MRI) const
175 {
176 const TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
177 unsigned dstReg = MI->getOperand(0).getReg();
178 int64_t newIndex = MI->getOperand(1).getImm();
179 const TargetRegisterClass * dstClass = MRI.getRegClass(dstReg);
180
181 unsigned newReg = dstClass->getRegister(newIndex);
182 addLiveIn(MI, MF, MRI, TII, newReg);
183 }
184