LLVM: lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
22
23using namespace llvm;
24
25#define DEBUG_TYPE "r600-expand-special-instrs"
26
27namespace {
28
30private:
32
34 R600::OpName Op);
35
36public:
37 static char ID;
38
40
42
43 StringRef getPassName() const override {
44 return "R600 Expand special instructions pass";
45 }
46};
47
48}
49
51 "R600 Expand Special Instrs", false, false)
54
55char R600ExpandSpecialInstrsPass::ID = 0;
56
58
60 return new R600ExpandSpecialInstrsPass();
61}
62
63void R600ExpandSpecialInstrsPass::SetFlagInNewMI(MachineInstr *NewMI,
65 R600::OpName Op) {
66 int OpIdx = TII->getOperandIdx(*OldMI, Op);
69 TII->setImmOperand(*NewMI, Op, Val);
70 }
71}
72
73bool R600ExpandSpecialInstrsPass::runOnMachineFunction(MachineFunction &MF) {
74 const R600Subtarget &ST = MF.getSubtarget();
76
78
79 for (MachineBasicBlock &MBB : MF) {
84
85
86 if (TII->isLDSRetInstr(MI.getOpcode())) {
87 int DstIdx = TII->getOperandIdx(MI.getOpcode(), R600::OpName::dst);
89 MachineOperand &DstOp = MI.getOperand(DstIdx);
90 MachineInstr *Mov = TII->buildMovInstr(&MBB, I,
91 DstOp.getReg(), R600::OQAP);
92 DstOp.setReg(R600::OQAP);
93 int LDSPredSelIdx = TII->getOperandIdx(MI.getOpcode(),
94 R600::OpName::pred_sel);
95 int MovPredSelIdx = TII->getOperandIdx(Mov->getOpcode(),
96 R600::OpName::pred_sel);
97
99 MI.getOperand(LDSPredSelIdx).getReg());
100 }
101
102 switch (MI.getOpcode()) {
103 default: break;
104
105 case R600::PRED_X: {
106 uint64_t Flags = MI.getOperand(3).getImm();
107
108
109 MachineInstr *PredSet = TII->buildDefaultInstruction(MBB, I,
110 MI.getOperand(2).getImm(),
111 MI.getOperand(0).getReg(),
112 MI.getOperand(1).getReg(),
113 R600::ZERO);
116 TII->setImmOperand(*PredSet, R600::OpName::update_exec_mask, 1);
117 } else {
118 TII->setImmOperand(*PredSet, R600::OpName::update_pred, 1);
119 }
120 MI.eraseFromParent();
121 continue;
122 }
123 case R600::DOT_4: {
124
126
127 Register DstReg = MI.getOperand(0).getReg();
128 unsigned DstBase = TRI.getEncodingValue(DstReg) & HW_REG_MASK;
129
130 for (unsigned Chan = 0; Chan < 4; ++Chan) {
131 bool Mask = (Chan != TRI.getHWRegChan(DstReg));
132 unsigned SubDstReg =
133 R600::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan);
134 MachineInstr *BMI =
135 TII->buildSlotOfVectorInstruction(MBB, &MI, Chan, SubDstReg);
136 if (Chan > 0) {
138 }
139 if (Mask) {
141 }
142 if (Chan != 3)
144 unsigned Opcode = BMI->getOpcode();
145
146
148 BMI->getOperand(TII->getOperandIdx(Opcode, R600::OpName::src0))
151 BMI->getOperand(TII->getOperandIdx(Opcode, R600::OpName::src1))
153 (void) Src0;
154 (void) Src1;
155 if ((TRI.getEncodingValue(Src0) & 0xff) < 127 &&
156 (TRI.getEncodingValue(Src1) & 0xff) < 127)
157 assert(TRI.getHWRegChan(Src0) == TRI.getHWRegChan(Src1));
158 }
159 MI.eraseFromParent();
160 continue;
161 }
162 }
163
164 bool IsReduction = TII->isReductionOp(MI.getOpcode());
165 bool IsVector = TII->isVector(MI);
166 bool IsCube = TII->isCubeOp(MI.getOpcode());
167 if (!IsReduction && !IsVector && !IsCube) {
168 continue;
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 for (unsigned Chan = 0; Chan < 4; Chan++) {
198 MI.getOperand(TII->getOperandIdx(MI, R600::OpName::dst)).getReg();
200 MI.getOperand(TII->getOperandIdx(MI, R600::OpName::src0)).getReg();
201 unsigned Src1 = 0;
202
203
204 if (!IsCube) {
205 int Src1Idx = TII->getOperandIdx(MI, R600::OpName::src1);
206 if (Src1Idx != -1) {
207 Src1 = MI.getOperand(Src1Idx).getReg();
208 }
209 }
210 if (IsReduction) {
212 Src0 = TRI.getSubReg(Src0, SubRegIndex);
213 Src1 = TRI.getSubReg(Src1, SubRegIndex);
214 } else if (IsCube) {
215 static const int CubeSrcSwz[] = {2, 2, 0, 1};
218 Src1 = TRI.getSubReg(Src0, SubRegIndex1);
219 Src0 = TRI.getSubReg(Src0, SubRegIndex0);
220 }
221
222
223 bool Mask = false;
224 bool NotLast = true;
225 if (IsCube) {
227 DstReg = TRI.getSubReg(DstReg, SubRegIndex);
228 } else {
229
230
231 Mask = (Chan != TRI.getHWRegChan(DstReg));
232 unsigned DstBase = TRI.getEncodingValue(DstReg) & HW_REG_MASK;
233 DstReg = R600::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan);
234 }
235
236
237 NotLast = (Chan != 3 );
238
239
240 unsigned Opcode = MI.getOpcode();
241 switch (Opcode) {
242 case R600::CUBE_r600_pseudo:
243 Opcode = R600::CUBE_r600_real;
244 break;
245 case R600::CUBE_eg_pseudo:
246 Opcode = R600::CUBE_eg_real;
247 break;
248 default:
249 break;
250 }
251
252 MachineInstr *NewMI =
253 TII->buildDefaultInstruction(MBB, I, Opcode, DstReg, Src0, Src1);
254
255 if (Chan != 0)
257 if (Mask) {
259 }
260 if (NotLast) {
262 }
263 SetFlagInNewMI(NewMI, &MI, R600::OpName::clamp);
264 SetFlagInNewMI(NewMI, &MI, R600::OpName::literal);
265 SetFlagInNewMI(NewMI, &MI, R600::OpName::src0_abs);
266 SetFlagInNewMI(NewMI, &MI, R600::OpName::src1_abs);
267 SetFlagInNewMI(NewMI, &MI, R600::OpName::src0_neg);
268 SetFlagInNewMI(NewMI, &MI, R600::OpName::src1_neg);
269 }
270 MI.eraseFromParent();
271 }
272 }
274 return false;
275}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
#define HW_REG_MASK
Defines for extracting register information from register encoding.
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void bundleWithPred()
Bundle this instruction with its predecessor.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
StringRef - Represent a constant reference to a string, i.e.
const TargetRegisterInfo & getRegisterInfo() const
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createR600ExpandSpecialInstrsPass()
Definition R600ExpandSpecialInstrs.cpp:59
LLVM_ABI bool finalizeBundles(MachineFunction &MF)
finalizeBundles - Finalize instruction bundles in the specified MachineFunction.
DWARFExpression::Operation Op
char & R600ExpandSpecialInstrsPassID
Definition R600ExpandSpecialInstrs.cpp:57
static unsigned getSubRegFromChannel(unsigned Channel)