1 //===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// R600 Implementation of TargetInstrInfo.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "R600InstrInfo.h"
15 #include "AMDGPU.h"
16 #include "MCTargetDesc/R600MCTargetDesc.h"
17 #include "R600.h"
18 #include "R600Defines.h"
19 #include "R600Subtarget.h"
20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
22
23 using namespace llvm;
24
25 #define GET_INSTRINFO_CTOR_DTOR
26 #include "R600GenDFAPacketizer.inc"
27
28 #define GET_INSTRINFO_CTOR_DTOR
29 #define GET_INSTRMAP_INFO
30 #define GET_INSTRINFO_NAMED_OPS
31 #include "R600GenInstrInfo.inc"
32
R600InstrInfo(const R600Subtarget & ST)33 R600InstrInfo::R600InstrInfo(const R600Subtarget &ST)
34 : R600GenInstrInfo(-1, -1), RI(), ST(ST) {}
35
isVector(const MachineInstr & MI) const36 bool R600InstrInfo::isVector(const MachineInstr &MI) const {
37 return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
38 }
39
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const40 void R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
41 MachineBasicBlock::iterator MI,
42 const DebugLoc &DL, MCRegister DestReg,
43 MCRegister SrcReg, bool KillSrc) const {
44 unsigned VectorComponents = 0;
45 if ((R600::R600_Reg128RegClass.contains(DestReg) ||
46 R600::R600_Reg128VerticalRegClass.contains(DestReg)) &&
47 (R600::R600_Reg128RegClass.contains(SrcReg) ||
48 R600::R600_Reg128VerticalRegClass.contains(SrcReg))) {
49 VectorComponents = 4;
50 } else if((R600::R600_Reg64RegClass.contains(DestReg) ||
51 R600::R600_Reg64VerticalRegClass.contains(DestReg)) &&
52 (R600::R600_Reg64RegClass.contains(SrcReg) ||
53 R600::R600_Reg64VerticalRegClass.contains(SrcReg))) {
54 VectorComponents = 2;
55 }
56
57 if (VectorComponents > 0) {
58 for (unsigned I = 0; I < VectorComponents; I++) {
59 unsigned SubRegIndex = R600RegisterInfo::getSubRegFromChannel(I);
60 buildDefaultInstruction(MBB, MI, R600::MOV,
61 RI.getSubReg(DestReg, SubRegIndex),
62 RI.getSubReg(SrcReg, SubRegIndex))
63 .addReg(DestReg,
64 RegState::Define | RegState::Implicit);
65 }
66 } else {
67 MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, R600::MOV,
68 DestReg, SrcReg);
69 NewMI->getOperand(getOperandIdx(*NewMI, R600::OpName::src0))
70 .setIsKill(KillSrc);
71 }
72 }
73
74 /// \returns true if \p MBBI can be moved into a new basic.
isLegalToSplitMBBAt(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI) const75 bool R600InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
76 MachineBasicBlock::iterator MBBI) const {
77 for (MachineInstr::const_mop_iterator I = MBBI->operands_begin(),
78 E = MBBI->operands_end(); I != E; ++I) {
79 if (I->isReg() && !I->getReg().isVirtual() && I->isUse() &&
80 RI.isPhysRegLiveAcrossClauses(I->getReg()))
81 return false;
82 }
83 return true;
84 }
85
isMov(unsigned Opcode) const86 bool R600InstrInfo::isMov(unsigned Opcode) const {
87 switch(Opcode) {
88 default:
89 return false;
90 case R600::MOV:
91 case R600::MOV_IMM_F32:
92 case R600::MOV_IMM_I32:
93 return true;
94 }
95 }
96
isReductionOp(unsigned Opcode) const97 bool R600InstrInfo::isReductionOp(unsigned Opcode) const {
98 return false;
99 }
100
isCubeOp(unsigned Opcode) const101 bool R600InstrInfo::isCubeOp(unsigned Opcode) const {
102 switch(Opcode) {
103 default: return false;
104 case R600::CUBE_r600_pseudo:
105 case R600::CUBE_r600_real:
106 case R600::CUBE_eg_pseudo:
107 case R600::CUBE_eg_real:
108 return true;
109 }
110 }
111
isALUInstr(unsigned Opcode) const112 bool R600InstrInfo::isALUInstr(unsigned Opcode) const {
113 unsigned TargetFlags = get(Opcode).TSFlags;
114
115 return (TargetFlags & R600_InstFlag::ALU_INST);
116 }
117
hasInstrModifiers(unsigned Opcode) const118 bool R600InstrInfo::hasInstrModifiers(unsigned Opcode) const {
119 unsigned TargetFlags = get(Opcode).TSFlags;
120
121 return ((TargetFlags & R600_InstFlag::OP1) |
122 (TargetFlags & R600_InstFlag::OP2) |
123 (TargetFlags & R600_InstFlag::OP3));
124 }
125
isLDSInstr(unsigned Opcode) const126 bool R600InstrInfo::isLDSInstr(unsigned Opcode) const {
127 unsigned TargetFlags = get(Opcode).TSFlags;
128
129 return ((TargetFlags & R600_InstFlag::LDS_1A) |
130 (TargetFlags & R600_InstFlag::LDS_1A1D) |
131 (TargetFlags & R600_InstFlag::LDS_1A2D));
132 }
133
isLDSRetInstr(unsigned Opcode) const134 bool R600InstrInfo::isLDSRetInstr(unsigned Opcode) const {
135 return isLDSInstr(Opcode) && getOperandIdx(Opcode, R600::OpName::dst) != -1;
136 }
137
canBeConsideredALU(const MachineInstr & MI) const138 bool R600InstrInfo::canBeConsideredALU(const MachineInstr &MI) const {
139 if (isALUInstr(MI.getOpcode()))
140 return true;
141 if (isVector(MI) || isCubeOp(MI.getOpcode()))
142 return true;
143 switch (MI.getOpcode()) {
144 case R600::PRED_X:
145 case R600::INTERP_PAIR_XY:
146 case R600::INTERP_PAIR_ZW:
147 case R600::INTERP_VEC_LOAD:
148 case R600::COPY:
149 case R600::DOT_4:
150 return true;
151 default:
152 return false;
153 }
154 }
155
isTransOnly(unsigned Opcode) const156 bool R600InstrInfo::isTransOnly(unsigned Opcode) const {
157 if (ST.hasCaymanISA())
158 return false;
159 return (get(Opcode).getSchedClass() == R600::Sched::TransALU);
160 }
161
isTransOnly(const MachineInstr & MI) const162 bool R600InstrInfo::isTransOnly(const MachineInstr &MI) const {
163 return isTransOnly(MI.getOpcode());
164 }
165
isVectorOnly(unsigned Opcode) const166 bool R600InstrInfo::isVectorOnly(unsigned Opcode) const {
167 return (get(Opcode).getSchedClass() == R600::Sched::VecALU);
168 }
169
isVectorOnly(const MachineInstr & MI) const170 bool R600InstrInfo::isVectorOnly(const MachineInstr &MI) const {
171 return isVectorOnly(MI.getOpcode());
172 }
173
isExport(unsigned Opcode) const174 bool R600InstrInfo::isExport(unsigned Opcode) const {
175 return (get(Opcode).TSFlags & R600_InstFlag::IS_EXPORT);
176 }
177
usesVertexCache(unsigned Opcode) const178 bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
179 return ST.hasVertexCache() && IS_VTX(get(Opcode));
180 }
181
usesVertexCache(const MachineInstr & MI) const182 bool R600InstrInfo::usesVertexCache(const MachineInstr &MI) const {
183 const MachineFunction *MF = MI.getParent()->getParent();
184 return !AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
185 usesVertexCache(MI.getOpcode());
186 }
187
usesTextureCache(unsigned Opcode) const188 bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
189 return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
190 }
191
usesTextureCache(const MachineInstr & MI) const192 bool R600InstrInfo::usesTextureCache(const MachineInstr &MI) const {
193 const MachineFunction *MF = MI.getParent()->getParent();
194 return (AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
195 usesVertexCache(MI.getOpcode())) ||
196 usesTextureCache(MI.getOpcode());
197 }
198
mustBeLastInClause(unsigned Opcode) const199 bool R600InstrInfo::mustBeLastInClause(unsigned Opcode) const {
200 switch (Opcode) {
201 case R600::KILLGT:
202 case R600::GROUP_BARRIER:
203 return true;
204 default:
205 return false;
206 }
207 }
208
usesAddressRegister(MachineInstr & MI) const209 bool R600InstrInfo::usesAddressRegister(MachineInstr &MI) const {
210 return MI.findRegisterUseOperandIdx(R600::AR_X, &RI, false) != -1;
211 }
212
definesAddressRegister(MachineInstr & MI) const213 bool R600InstrInfo::definesAddressRegister(MachineInstr &MI) const {
214 return MI.findRegisterDefOperandIdx(R600::AR_X, &RI, false, false) != -1;
215 }
216
readsLDSSrcReg(const MachineInstr & MI) const217 bool R600InstrInfo::readsLDSSrcReg(const MachineInstr &MI) const {
218 if (!isALUInstr(MI.getOpcode())) {
219 return false;
220 }
221 for (MachineInstr::const_mop_iterator I = MI.operands_begin(),
222 E = MI.operands_end();
223 I != E; ++I) {
224 if (!I->isReg() || !I->isUse() || I->getReg().isVirtual())
225 continue;
226
227 if (R600::R600_LDS_SRC_REGRegClass.contains(I->getReg()))
228 return true;
229 }
230 return false;
231 }
232
getSelIdx(unsigned Opcode,unsigned SrcIdx) const233 int R600InstrInfo::getSelIdx(unsigned Opcode, unsigned SrcIdx) const {
234 static const unsigned SrcSelTable[][2] = {
235 {R600::OpName::src0, R600::OpName::src0_sel},
236 {R600::OpName::src1, R600::OpName::src1_sel},
237 {R600::OpName::src2, R600::OpName::src2_sel},
238 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
239 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
240 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
241 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
242 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
243 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
244 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
245 {R600::OpName::src1_W, R600::OpName::src1_sel_W}
246 };
247
248 for (const auto &Row : SrcSelTable) {
249 if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {
250 return getOperandIdx(Opcode, Row[1]);
251 }
252 }
253 return -1;
254 }
255
256 SmallVector<std::pair<MachineOperand *, int64_t>, 3>
getSrcs(MachineInstr & MI) const257 R600InstrInfo::getSrcs(MachineInstr &MI) const {
258 SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;
259
260 if (MI.getOpcode() == R600::DOT_4) {
261 static const unsigned OpTable[8][2] = {
262 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
263 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
264 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
265 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
266 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
267 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
268 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
269 {R600::OpName::src1_W, R600::OpName::src1_sel_W},
270 };
271
272 for (const auto &Op : OpTable) {
273 MachineOperand &MO = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[0]));
274 Register Reg = MO.getReg();
275 if (Reg == R600::ALU_CONST) {
276 MachineOperand &Sel =
277 MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));
278 Result.push_back(std::pair(&MO, Sel.getImm()));
279 continue;
280 }
281 }
282 return Result;
283 }
284
285 static const unsigned OpTable[3][2] = {
286 {R600::OpName::src0, R600::OpName::src0_sel},
287 {R600::OpName::src1, R600::OpName::src1_sel},
288 {R600::OpName::src2, R600::OpName::src2_sel},
289 };
290
291 for (const auto &Op : OpTable) {
292 int SrcIdx = getOperandIdx(MI.getOpcode(), Op[0]);
293 if (SrcIdx < 0)
294 break;
295 MachineOperand &MO = MI.getOperand(SrcIdx);
296 Register Reg = MO.getReg();
297 if (Reg == R600::ALU_CONST) {
298 MachineOperand &Sel = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));
299 Result.push_back(std::pair(&MO, Sel.getImm()));
300 continue;
301 }
302 if (Reg == R600::ALU_LITERAL_X) {
303 MachineOperand &Operand =
304 MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
305 if (Operand.isImm()) {
306 Result.push_back(std::pair(&MO, Operand.getImm()));
307 continue;
308 }
309 assert(Operand.isGlobal());
310 }
311 Result.push_back(std::pair(&MO, 0));
312 }
313 return Result;
314 }
315
316 std::vector<std::pair<int, unsigned>>
ExtractSrcs(MachineInstr & MI,const DenseMap<unsigned,unsigned> & PV,unsigned & ConstCount) const317 R600InstrInfo::ExtractSrcs(MachineInstr &MI,
318 const DenseMap<unsigned, unsigned> &PV,
319 unsigned &ConstCount) const {
320 ConstCount = 0;
321 const std::pair<int, unsigned> DummyPair(-1, 0);
322 std::vector<std::pair<int, unsigned>> Result;
323 unsigned i = 0;
324 for (const auto &Src : getSrcs(MI)) {
325 ++i;
326 Register Reg = Src.first->getReg();
327 int Index = RI.getEncodingValue(Reg) & 0xff;
328 if (Reg == R600::OQAP) {
329 Result.emplace_back(Index, 0U);
330 }
331 if (PV.contains(Reg)) {
332 // 255 is used to tells its a PS/PV reg
333 Result.emplace_back(255, 0U);
334 continue;
335 }
336 if (Index > 127) {
337 ConstCount++;
338 Result.push_back(DummyPair);
339 continue;
340 }
341 unsigned Chan = RI.getHWRegChan(Reg);
342 Result.emplace_back(Index, Chan);
343 }
344 for (; i < 3; ++i)
345 Result.push_back(DummyPair);
346 return Result;
347 }
348
349 static std::vector<std::pair<int, unsigned>>
Swizzle(std::vector<std::pair<int,unsigned>> Src,R600InstrInfo::BankSwizzle Swz)350 Swizzle(std::vector<std::pair<int, unsigned>> Src,
351 R600InstrInfo::BankSwizzle Swz) {
352 if (Src[0] == Src[1])
353 Src[1].first = -1;
354 switch (Swz) {
355 case R600InstrInfo::ALU_VEC_012_SCL_210:
356 break;
357 case R600InstrInfo::ALU_VEC_021_SCL_122:
358 std::swap(Src[1], Src[2]);
359 break;
360 case R600InstrInfo::ALU_VEC_102_SCL_221:
361 std::swap(Src[0], Src[1]);
362 break;
363 case R600InstrInfo::ALU_VEC_120_SCL_212:
364 std::swap(Src[0], Src[1]);
365 std::swap(Src[0], Src[2]);
366 break;
367 case R600InstrInfo::ALU_VEC_201:
368 std::swap(Src[0], Src[2]);
369 std::swap(Src[0], Src[1]);
370 break;
371 case R600InstrInfo::ALU_VEC_210:
372 std::swap(Src[0], Src[2]);
373 break;
374 }
375 return Src;
376 }
377
getTransSwizzle(R600InstrInfo::BankSwizzle Swz,unsigned Op)378 static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
379 assert(Op < 3 && "Out of range swizzle index");
380 switch (Swz) {
381 case R600InstrInfo::ALU_VEC_012_SCL_210: {
382 unsigned Cycles[3] = { 2, 1, 0};
383 return Cycles[Op];
384 }
385 case R600InstrInfo::ALU_VEC_021_SCL_122: {
386 unsigned Cycles[3] = { 1, 2, 2};
387 return Cycles[Op];
388 }
389 case R600InstrInfo::ALU_VEC_120_SCL_212: {
390 unsigned Cycles[3] = { 2, 1, 2};
391 return Cycles[Op];
392 }
393 case R600InstrInfo::ALU_VEC_102_SCL_221: {
394 unsigned Cycles[3] = { 2, 2, 1};
395 return Cycles[Op];
396 }
397 default:
398 llvm_unreachable("Wrong Swizzle for Trans Slot");
399 }
400 }
401
402 /// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
403 /// in the same Instruction Group while meeting read port limitations given a
404 /// Swz swizzle sequence.
isLegalUpTo(const std::vector<std::vector<std::pair<int,unsigned>>> & IGSrcs,const std::vector<R600InstrInfo::BankSwizzle> & Swz,const std::vector<std::pair<int,unsigned>> & TransSrcs,R600InstrInfo::BankSwizzle TransSwz) const405 unsigned R600InstrInfo::isLegalUpTo(
406 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
407 const std::vector<R600InstrInfo::BankSwizzle> &Swz,
408 const std::vector<std::pair<int, unsigned>> &TransSrcs,
409 R600InstrInfo::BankSwizzle TransSwz) const {
410 int Vector[4][3];
411 memset(Vector, -1, sizeof(Vector));
412 for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
413 const std::vector<std::pair<int, unsigned>> &Srcs =
414 Swizzle(IGSrcs[i], Swz[i]);
415 for (unsigned j = 0; j < 3; j++) {
416 const std::pair<int, unsigned> &Src = Srcs[j];
417 if (Src.first < 0 || Src.first == 255)
418 continue;
419 if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {
420 if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&
421 Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {
422 // The value from output queue A (denoted by register OQAP) can
423 // only be fetched during the first cycle.
424 return false;
425 }
426 // OQAP does not count towards the normal read port restrictions
427 continue;
428 }
429 if (Vector[Src.second][j] < 0)
430 Vector[Src.second][j] = Src.first;
431 if (Vector[Src.second][j] != Src.first)
432 return i;
433 }
434 }
435 // Now check Trans Alu
436 for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
437 const std::pair<int, unsigned> &Src = TransSrcs[i];
438 unsigned Cycle = getTransSwizzle(TransSwz, i);
439 if (Src.first < 0)
440 continue;
441 if (Src.first == 255)
442 continue;
443 if (Vector[Src.second][Cycle] < 0)
444 Vector[Src.second][Cycle] = Src.first;
445 if (Vector[Src.second][Cycle] != Src.first)
446 return IGSrcs.size() - 1;
447 }
448 return IGSrcs.size();
449 }
450
451 /// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
452 /// (in lexicographic term) swizzle sequence assuming that all swizzles after
453 /// Idx can be skipped
454 static bool
NextPossibleSolution(std::vector<R600InstrInfo::BankSwizzle> & SwzCandidate,unsigned Idx)455 NextPossibleSolution(
456 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
457 unsigned Idx) {
458 assert(Idx < SwzCandidate.size());
459 int ResetIdx = Idx;
460 while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
461 ResetIdx --;
462 for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
463 SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
464 }
465 if (ResetIdx == -1)
466 return false;
467 int NextSwizzle = SwzCandidate[ResetIdx] + 1;
468 SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
469 return true;
470 }
471
472 /// Enumerate all possible Swizzle sequence to find one that can meet all
473 /// read port requirements.
FindSwizzleForVectorSlot(const std::vector<std::vector<std::pair<int,unsigned>>> & IGSrcs,std::vector<R600InstrInfo::BankSwizzle> & SwzCandidate,const std::vector<std::pair<int,unsigned>> & TransSrcs,R600InstrInfo::BankSwizzle TransSwz) const474 bool R600InstrInfo::FindSwizzleForVectorSlot(
475 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
476 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
477 const std::vector<std::pair<int, unsigned>> &TransSrcs,
478 R600InstrInfo::BankSwizzle TransSwz) const {
479 unsigned ValidUpTo = 0;
480 do {
481 ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
482 if (ValidUpTo == IGSrcs.size())
483 return true;
484 } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
485 return false;
486 }
487
488 /// Instructions in Trans slot can't read gpr at cycle 0 if they also read
489 /// a const, and can't read a gpr at cycle 1 if they read 2 const.
490 static bool
isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,const std::vector<std::pair<int,unsigned>> & TransOps,unsigned ConstCount)491 isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,
492 const std::vector<std::pair<int, unsigned>> &TransOps,
493 unsigned ConstCount) {
494 // TransALU can't read 3 constants
495 if (ConstCount > 2)
496 return false;
497 for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
498 const std::pair<int, unsigned> &Src = TransOps[i];
499 unsigned Cycle = getTransSwizzle(TransSwz, i);
500 if (Src.first < 0)
501 continue;
502 if (ConstCount > 0 && Cycle == 0)
503 return false;
504 if (ConstCount > 1 && Cycle == 1)
505 return false;
506 }
507 return true;
508 }
509
510 bool
fitsReadPortLimitations(const std::vector<MachineInstr * > & IG,const DenseMap<unsigned,unsigned> & PV,std::vector<BankSwizzle> & ValidSwizzle,bool isLastAluTrans) const511 R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
512 const DenseMap<unsigned, unsigned> &PV,
513 std::vector<BankSwizzle> &ValidSwizzle,
514 bool isLastAluTrans)
515 const {
516 //Todo : support shared src0 - src1 operand
517
518 std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
519 ValidSwizzle.clear();
520 unsigned ConstCount;
521 BankSwizzle TransBS = ALU_VEC_012_SCL_210;
522 for (MachineInstr *MI : IG) {
523 IGSrcs.push_back(ExtractSrcs(*MI, PV, ConstCount));
524 unsigned Op = getOperandIdx(MI->getOpcode(), R600::OpName::bank_swizzle);
525 ValidSwizzle.push_back(
526 (R600InstrInfo::BankSwizzle)MI->getOperand(Op).getImm());
527 }
528 std::vector<std::pair<int, unsigned>> TransOps;
529 if (!isLastAluTrans)
530 return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
531
532 TransOps = std::move(IGSrcs.back());
533 IGSrcs.pop_back();
534 ValidSwizzle.pop_back();
535
536 static const R600InstrInfo::BankSwizzle TransSwz[] = {
537 ALU_VEC_012_SCL_210,
538 ALU_VEC_021_SCL_122,
539 ALU_VEC_120_SCL_212,
540 ALU_VEC_102_SCL_221
541 };
542 for (R600InstrInfo::BankSwizzle TransBS : TransSwz) {
543 if (!isConstCompatible(TransBS, TransOps, ConstCount))
544 continue;
545 bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
546 TransBS);
547 if (Result) {
548 ValidSwizzle.push_back(TransBS);
549 return true;
550 }
551 }
552
553 return false;
554 }
555
556 bool
fitsConstReadLimitations(const std::vector<unsigned> & Consts) const557 R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
558 const {
559 assert (Consts.size() <= 12 && "Too many operands in instructions group");
560 unsigned Pair1 = 0, Pair2 = 0;
561 for (unsigned Const : Consts) {
562 unsigned ReadConstHalf = Const & 2;
563 unsigned ReadConstIndex = Const & (~3);
564 unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
565 if (!Pair1) {
566 Pair1 = ReadHalfConst;
567 continue;
568 }
569 if (Pair1 == ReadHalfConst)
570 continue;
571 if (!Pair2) {
572 Pair2 = ReadHalfConst;
573 continue;
574 }
575 if (Pair2 != ReadHalfConst)
576 return false;
577 }
578 return true;
579 }
580
581 bool
fitsConstReadLimitations(const std::vector<MachineInstr * > & MIs) const582 R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
583 const {
584 std::vector<unsigned> Consts;
585 SmallSet<int64_t, 4> Literals;
586 for (MachineInstr *MI : MIs) {
587 if (!isALUInstr(MI->getOpcode()))
588 continue;
589
590 for (const auto &Src : getSrcs(*MI)) {
591 if (Src.first->getReg() == R600::ALU_LITERAL_X)
592 Literals.insert(Src.second);
593 if (Literals.size() > 4)
594 return false;
595 if (Src.first->getReg() == R600::ALU_CONST)
596 Consts.push_back(Src.second);
597 if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
598 R600::R600_KC1RegClass.contains(Src.first->getReg())) {
599 unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
600 unsigned Chan = RI.getHWRegChan(Src.first->getReg());
601 Consts.push_back((Index << 2) | Chan);
602 }
603 }
604 }
605 return fitsConstReadLimitations(Consts);
606 }
607
608 DFAPacketizer *
CreateTargetScheduleState(const TargetSubtargetInfo & STI) const609 R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {
610 const InstrItineraryData *II = STI.getInstrItineraryData();
611 return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
612 }
613
614 static bool
isPredicateSetter(unsigned Opcode)615 isPredicateSetter(unsigned Opcode) {
616 switch (Opcode) {
617 case R600::PRED_X:
618 return true;
619 default:
620 return false;
621 }
622 }
623
624 static MachineInstr *
findFirstPredicateSetterFrom(MachineBasicBlock & MBB,MachineBasicBlock::iterator I)625 findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
626 MachineBasicBlock::iterator I) {
627 while (I != MBB.begin()) {
628 --I;
629 MachineInstr &MI = *I;
630 if (isPredicateSetter(MI.getOpcode()))
631 return &MI;
632 }
633
634 return nullptr;
635 }
636
637 static
isJump(unsigned Opcode)638 bool isJump(unsigned Opcode) {
639 return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
640 }
641
isBranch(unsigned Opcode)642 static bool isBranch(unsigned Opcode) {
643 return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
644 Opcode == R600::BRANCH_COND_f32;
645 }
646
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const647 bool R600InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
648 MachineBasicBlock *&TBB,
649 MachineBasicBlock *&FBB,
650 SmallVectorImpl<MachineOperand> &Cond,
651 bool AllowModify) const {
652 // Most of the following comes from the ARM implementation of analyzeBranch
653
654 // If the block has no terminators, it just falls into the block after it.
655 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
656 if (I == MBB.end())
657 return false;
658
659 // R600::BRANCH* instructions are only available after isel and are not
660 // handled
661 if (isBranch(I->getOpcode()))
662 return true;
663 if (!isJump(I->getOpcode())) {
664 return false;
665 }
666
667 // Remove successive JUMP
668 while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
669 MachineBasicBlock::iterator PriorI = std::prev(I);
670 if (AllowModify)
671 I->removeFromParent();
672 I = PriorI;
673 }
674 MachineInstr &LastInst = *I;
675
676 // If there is only one terminator instruction, process it.
677 unsigned LastOpc = LastInst.getOpcode();
678 if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
679 if (LastOpc == R600::JUMP) {
680 TBB = LastInst.getOperand(0).getMBB();
681 return false;
682 }
683 if (LastOpc == R600::JUMP_COND) {
684 auto predSet = I;
685 while (!isPredicateSetter(predSet->getOpcode())) {
686 predSet = --I;
687 }
688 TBB = LastInst.getOperand(0).getMBB();
689 Cond.push_back(predSet->getOperand(1));
690 Cond.push_back(predSet->getOperand(2));
691 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
692 return false;
693 }
694 return true; // Can't handle indirect branch.
695 }
696
697 // Get the instruction before it if it is a terminator.
698 MachineInstr &SecondLastInst = *I;
699 unsigned SecondLastOpc = SecondLastInst.getOpcode();
700
701 // If the block ends with a B and a Bcc, handle it.
702 if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
703 auto predSet = --I;
704 while (!isPredicateSetter(predSet->getOpcode())) {
705 predSet = --I;
706 }
707 TBB = SecondLastInst.getOperand(0).getMBB();
708 FBB = LastInst.getOperand(0).getMBB();
709 Cond.push_back(predSet->getOperand(1));
710 Cond.push_back(predSet->getOperand(2));
711 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
712 return false;
713 }
714
715 // Otherwise, can't handle this.
716 return true;
717 }
718
719 static
FindLastAluClause(MachineBasicBlock & MBB)720 MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {
721 for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
722 It != E; ++It) {
723 if (It->getOpcode() == R600::CF_ALU ||
724 It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
725 return It.getReverse();
726 }
727 return MBB.end();
728 }
729
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const730 unsigned R600InstrInfo::insertBranch(MachineBasicBlock &MBB,
731 MachineBasicBlock *TBB,
732 MachineBasicBlock *FBB,
733 ArrayRef<MachineOperand> Cond,
734 const DebugLoc &DL,
735 int *BytesAdded) const {
736 assert(TBB && "insertBranch must not be told to insert a fallthrough");
737 assert(!BytesAdded && "code size not handled");
738
739 if (!FBB) {
740 if (Cond.empty()) {
741 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
742 return 1;
743 }
744 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
745 assert(PredSet && "No previous predicate !");
746 addFlag(*PredSet, 0, MO_FLAG_PUSH);
747 PredSet->getOperand(2).setImm(Cond[1].getImm());
748
749 BuildMI(&MBB, DL, get(R600::JUMP_COND))
750 .addMBB(TBB)
751 .addReg(R600::PREDICATE_BIT, RegState::Kill);
752 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
753 if (CfAlu == MBB.end())
754 return 1;
755 assert (CfAlu->getOpcode() == R600::CF_ALU);
756 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
757 return 1;
758 }
759 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
760 assert(PredSet && "No previous predicate !");
761 addFlag(*PredSet, 0, MO_FLAG_PUSH);
762 PredSet->getOperand(2).setImm(Cond[1].getImm());
763 BuildMI(&MBB, DL, get(R600::JUMP_COND))
764 .addMBB(TBB)
765 .addReg(R600::PREDICATE_BIT, RegState::Kill);
766 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);
767 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
768 if (CfAlu == MBB.end())
769 return 2;
770 assert(CfAlu->getOpcode() == R600::CF_ALU);
771 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
772 return 2;
773 }
774
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const775 unsigned R600InstrInfo::removeBranch(MachineBasicBlock &MBB,
776 int *BytesRemoved) const {
777 assert(!BytesRemoved && "code size not handled");
778
779 // Note : we leave PRED* instructions there.
780 // They may be needed when predicating instructions.
781
782 MachineBasicBlock::iterator I = MBB.end();
783
784 if (I == MBB.begin()) {
785 return 0;
786 }
787 --I;
788 switch (I->getOpcode()) {
789 default:
790 return 0;
791 case R600::JUMP_COND: {
792 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
793 clearFlag(*predSet, 0, MO_FLAG_PUSH);
794 I->eraseFromParent();
795 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
796 if (CfAlu == MBB.end())
797 break;
798 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
799 CfAlu->setDesc(get(R600::CF_ALU));
800 break;
801 }
802 case R600::JUMP:
803 I->eraseFromParent();
804 break;
805 }
806 I = MBB.end();
807
808 if (I == MBB.begin()) {
809 return 1;
810 }
811 --I;
812 switch (I->getOpcode()) {
813 // FIXME: only one case??
814 default:
815 return 1;
816 case R600::JUMP_COND: {
817 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
818 clearFlag(*predSet, 0, MO_FLAG_PUSH);
819 I->eraseFromParent();
820 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
821 if (CfAlu == MBB.end())
822 break;
823 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
824 CfAlu->setDesc(get(R600::CF_ALU));
825 break;
826 }
827 case R600::JUMP:
828 I->eraseFromParent();
829 break;
830 }
831 return 2;
832 }
833
isPredicated(const MachineInstr & MI) const834 bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {
835 int idx = MI.findFirstPredOperandIdx();
836 if (idx < 0)
837 return false;
838
839 Register Reg = MI.getOperand(idx).getReg();
840 switch (Reg) {
841 default: return false;
842 case R600::PRED_SEL_ONE:
843 case R600::PRED_SEL_ZERO:
844 case R600::PREDICATE_BIT:
845 return true;
846 }
847 }
848
isPredicable(const MachineInstr & MI) const849 bool R600InstrInfo::isPredicable(const MachineInstr &MI) const {
850 // XXX: KILL* instructions can be predicated, but they must be the last
851 // instruction in a clause, so this means any instructions after them cannot
852 // be predicated. Until we have proper support for instruction clauses in the
853 // backend, we will mark KILL* instructions as unpredicable.
854
855 if (MI.getOpcode() == R600::KILLGT)
856 return false;
857 if (MI.getOpcode() == R600::CF_ALU) {
858 // If the clause start in the middle of MBB then the MBB has more
859 // than a single clause, unable to predicate several clauses.
860 if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
861 return false;
862 // TODO: We don't support KC merging atm
863 return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
864 }
865 if (isVector(MI))
866 return false;
867 return TargetInstrInfo::isPredicable(MI);
868 }
869
870 bool
isProfitableToIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,unsigned ExtraPredCycles,BranchProbability Probability) const871 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
872 unsigned NumCycles,
873 unsigned ExtraPredCycles,
874 BranchProbability Probability) const{
875 return true;
876 }
877
878 bool
isProfitableToIfCvt(MachineBasicBlock & TMBB,unsigned NumTCycles,unsigned ExtraTCycles,MachineBasicBlock & FMBB,unsigned NumFCycles,unsigned ExtraFCycles,BranchProbability Probability) const879 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
880 unsigned NumTCycles,
881 unsigned ExtraTCycles,
882 MachineBasicBlock &FMBB,
883 unsigned NumFCycles,
884 unsigned ExtraFCycles,
885 BranchProbability Probability) const {
886 return true;
887 }
888
889 bool
isProfitableToDupForIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,BranchProbability Probability) const890 R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
891 unsigned NumCycles,
892 BranchProbability Probability)
893 const {
894 return true;
895 }
896
897 bool
isProfitableToUnpredicate(MachineBasicBlock & TMBB,MachineBasicBlock & FMBB) const898 R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
899 MachineBasicBlock &FMBB) const {
900 return false;
901 }
902
903 bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const904 R600InstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
905 MachineOperand &MO = Cond[1];
906 switch (MO.getImm()) {
907 case R600::PRED_SETE_INT:
908 MO.setImm(R600::PRED_SETNE_INT);
909 break;
910 case R600::PRED_SETNE_INT:
911 MO.setImm(R600::PRED_SETE_INT);
912 break;
913 case R600::PRED_SETE:
914 MO.setImm(R600::PRED_SETNE);
915 break;
916 case R600::PRED_SETNE:
917 MO.setImm(R600::PRED_SETE);
918 break;
919 default:
920 return true;
921 }
922
923 MachineOperand &MO2 = Cond[2];
924 switch (MO2.getReg()) {
925 case R600::PRED_SEL_ZERO:
926 MO2.setReg(R600::PRED_SEL_ONE);
927 break;
928 case R600::PRED_SEL_ONE:
929 MO2.setReg(R600::PRED_SEL_ZERO);
930 break;
931 default:
932 return true;
933 }
934 return false;
935 }
936
ClobbersPredicate(MachineInstr & MI,std::vector<MachineOperand> & Pred,bool SkipDead) const937 bool R600InstrInfo::ClobbersPredicate(MachineInstr &MI,
938 std::vector<MachineOperand> &Pred,
939 bool SkipDead) const {
940 return isPredicateSetter(MI.getOpcode());
941 }
942
PredicateInstruction(MachineInstr & MI,ArrayRef<MachineOperand> Pred) const943 bool R600InstrInfo::PredicateInstruction(MachineInstr &MI,
944 ArrayRef<MachineOperand> Pred) const {
945 int PIdx = MI.findFirstPredOperandIdx();
946
947 if (MI.getOpcode() == R600::CF_ALU) {
948 MI.getOperand(8).setImm(0);
949 return true;
950 }
951
952 if (MI.getOpcode() == R600::DOT_4) {
953 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
954 .setReg(Pred[2].getReg());
955 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
956 .setReg(Pred[2].getReg());
957 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
958 .setReg(Pred[2].getReg());
959 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
960 .setReg(Pred[2].getReg());
961 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
962 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
963 return true;
964 }
965
966 if (PIdx != -1) {
967 MachineOperand &PMO = MI.getOperand(PIdx);
968 PMO.setReg(Pred[2].getReg());
969 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
970 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
971 return true;
972 }
973
974 return false;
975 }
976
getPredicationCost(const MachineInstr &) const977 unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {
978 return 2;
979 }
980
getInstrLatency(const InstrItineraryData * ItinData,const MachineInstr &,unsigned * PredCost) const981 unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
982 const MachineInstr &,
983 unsigned *PredCost) const {
984 if (PredCost)
985 *PredCost = 2;
986 return 2;
987 }
988
calculateIndirectAddress(unsigned RegIndex,unsigned Channel) const989 unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
990 unsigned Channel) const {
991 assert(Channel == 0);
992 return RegIndex;
993 }
994
expandPostRAPseudo(MachineInstr & MI) const995 bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
996 switch (MI.getOpcode()) {
997 default: {
998 MachineBasicBlock *MBB = MI.getParent();
999 int OffsetOpIdx =
1000 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
1001 // addr is a custom operand with multiple MI operands, and only the
1002 // first MI operand is given a name.
1003 int RegOpIdx = OffsetOpIdx + 1;
1004 int ChanOpIdx =
1005 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
1006 if (isRegisterLoad(MI)) {
1007 int DstOpIdx =
1008 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
1009 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1010 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1011 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1012 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1013 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1014 buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
1015 getIndirectAddrRegClass()->getRegister(Address));
1016 } else {
1017 buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
1018 OffsetReg);
1019 }
1020 } else if (isRegisterStore(MI)) {
1021 int ValOpIdx =
1022 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
1023 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1024 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1025 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1026 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1027 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1028 buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
1029 MI.getOperand(ValOpIdx).getReg());
1030 } else {
1031 buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
1032 calculateIndirectAddress(RegIndex, Channel),
1033 OffsetReg);
1034 }
1035 } else {
1036 return false;
1037 }
1038
1039 MBB->erase(MI);
1040 return true;
1041 }
1042 case R600::R600_EXTRACT_ELT_V2:
1043 case R600::R600_EXTRACT_ELT_V4:
1044 buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
1045 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1046 MI.getOperand(2).getReg(),
1047 RI.getHWRegChan(MI.getOperand(1).getReg()));
1048 break;
1049 case R600::R600_INSERT_ELT_V2:
1050 case R600::R600_INSERT_ELT_V4:
1051 buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
1052 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1053 MI.getOperand(3).getReg(), // Offset
1054 RI.getHWRegChan(MI.getOperand(1).getReg())); // Channel
1055 break;
1056 }
1057 MI.eraseFromParent();
1058 return true;
1059 }
1060
reserveIndirectRegisters(BitVector & Reserved,const MachineFunction & MF,const R600RegisterInfo & TRI) const1061 void R600InstrInfo::reserveIndirectRegisters(BitVector &Reserved,
1062 const MachineFunction &MF,
1063 const R600RegisterInfo &TRI) const {
1064 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1065 const R600FrameLowering *TFL = ST.getFrameLowering();
1066
1067 unsigned StackWidth = TFL->getStackWidth(MF);
1068 int End = getIndirectIndexEnd(MF);
1069
1070 if (End == -1)
1071 return;
1072
1073 for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
1074 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1075 unsigned Reg = R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
1076 TRI.reserveRegisterTuples(Reserved, Reg);
1077 }
1078 }
1079 }
1080
getIndirectAddrRegClass() const1081 const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {
1082 return &R600::R600_TReg32_XRegClass;
1083 }
1084
buildIndirectWrite(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned ValueReg,unsigned Address,unsigned OffsetReg) const1085 MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1086 MachineBasicBlock::iterator I,
1087 unsigned ValueReg, unsigned Address,
1088 unsigned OffsetReg) const {
1089 return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
1090 }
1091
buildIndirectWrite(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned ValueReg,unsigned Address,unsigned OffsetReg,unsigned AddrChan) const1092 MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1093 MachineBasicBlock::iterator I,
1094 unsigned ValueReg, unsigned Address,
1095 unsigned OffsetReg,
1096 unsigned AddrChan) const {
1097 unsigned AddrReg;
1098 switch (AddrChan) {
1099 default: llvm_unreachable("Invalid Channel");
1100 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1101 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1102 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1103 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1104 }
1105 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1106 R600::AR_X, OffsetReg);
1107 setImmOperand(*MOVA, R600::OpName::write, 0);
1108
1109 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
1110 AddrReg, ValueReg)
1111 .addReg(R600::AR_X,
1112 RegState::Implicit | RegState::Kill);
1113 setImmOperand(*Mov, R600::OpName::dst_rel, 1);
1114 return Mov;
1115 }
1116
buildIndirectRead(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned ValueReg,unsigned Address,unsigned OffsetReg) const1117 MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1118 MachineBasicBlock::iterator I,
1119 unsigned ValueReg, unsigned Address,
1120 unsigned OffsetReg) const {
1121 return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
1122 }
1123
buildIndirectRead(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned ValueReg,unsigned Address,unsigned OffsetReg,unsigned AddrChan) const1124 MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1125 MachineBasicBlock::iterator I,
1126 unsigned ValueReg, unsigned Address,
1127 unsigned OffsetReg,
1128 unsigned AddrChan) const {
1129 unsigned AddrReg;
1130 switch (AddrChan) {
1131 default: llvm_unreachable("Invalid Channel");
1132 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1133 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1134 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1135 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1136 }
1137 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1138 R600::AR_X,
1139 OffsetReg);
1140 setImmOperand(*MOVA, R600::OpName::write, 0);
1141 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
1142 ValueReg,
1143 AddrReg)
1144 .addReg(R600::AR_X,
1145 RegState::Implicit | RegState::Kill);
1146 setImmOperand(*Mov, R600::OpName::src0_rel, 1);
1147
1148 return Mov;
1149 }
1150
getIndirectIndexBegin(const MachineFunction & MF) const1151 int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
1152 const MachineRegisterInfo &MRI = MF.getRegInfo();
1153 const MachineFrameInfo &MFI = MF.getFrameInfo();
1154 int Offset = -1;
1155
1156 if (MFI.getNumObjects() == 0) {
1157 return -1;
1158 }
1159
1160 if (MRI.livein_empty()) {
1161 return 0;
1162 }
1163
1164 const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
1165 for (std::pair<unsigned, unsigned> LI : MRI.liveins()) {
1166 Register Reg = LI.first;
1167 if (Reg.isVirtual() || !IndirectRC->contains(Reg))
1168 continue;
1169
1170 unsigned RegIndex;
1171 unsigned RegEnd;
1172 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
1173 ++RegIndex) {
1174 if (IndirectRC->getRegister(RegIndex) == (unsigned)Reg)
1175 break;
1176 }
1177 Offset = std::max(Offset, (int)RegIndex);
1178 }
1179
1180 return Offset + 1;
1181 }
1182
getIndirectIndexEnd(const MachineFunction & MF) const1183 int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
1184 int Offset = 0;
1185 const MachineFrameInfo &MFI = MF.getFrameInfo();
1186
1187 // Variable sized objects are not supported
1188 if (MFI.hasVarSizedObjects()) {
1189 return -1;
1190 }
1191
1192 if (MFI.getNumObjects() == 0) {
1193 return -1;
1194 }
1195
1196 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1197 const R600FrameLowering *TFL = ST.getFrameLowering();
1198
1199 Register IgnoredFrameReg;
1200 Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg).getFixed();
1201
1202 return getIndirectIndexBegin(MF) + Offset;
1203 }
1204
getMaxAlusPerClause() const1205 unsigned R600InstrInfo::getMaxAlusPerClause() const {
1206 return 115;
1207 }
1208
buildDefaultInstruction(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned Opcode,unsigned DstReg,unsigned Src0Reg,unsigned Src1Reg) const1209 MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
1210 MachineBasicBlock::iterator I,
1211 unsigned Opcode,
1212 unsigned DstReg,
1213 unsigned Src0Reg,
1214 unsigned Src1Reg) const {
1215 MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
1216 DstReg); // $dst
1217
1218 if (Src1Reg) {
1219 MIB.addImm(0) // $update_exec_mask
1220 .addImm(0); // $update_predicate
1221 }
1222 MIB.addImm(1) // $write
1223 .addImm(0) // $omod
1224 .addImm(0) // $dst_rel
1225 .addImm(0) // $dst_clamp
1226 .addReg(Src0Reg) // $src0
1227 .addImm(0) // $src0_neg
1228 .addImm(0) // $src0_rel
1229 .addImm(0) // $src0_abs
1230 .addImm(-1); // $src0_sel
1231
1232 if (Src1Reg) {
1233 MIB.addReg(Src1Reg) // $src1
1234 .addImm(0) // $src1_neg
1235 .addImm(0) // $src1_rel
1236 .addImm(0) // $src1_abs
1237 .addImm(-1); // $src1_sel
1238 }
1239
1240 //XXX: The r600g finalizer expects this to be 1, once we've moved the
1241 //scheduling to the backend, we can change the default to 0.
1242 MIB.addImm(1) // $last
1243 .addReg(R600::PRED_SEL_OFF) // $pred_sel
1244 .addImm(0) // $literal
1245 .addImm(0); // $bank_swizzle
1246
1247 return MIB;
1248 }
1249
1250 #define OPERAND_CASE(Label) \
1251 case Label: { \
1252 static const unsigned Ops[] = \
1253 { \
1254 Label##_X, \
1255 Label##_Y, \
1256 Label##_Z, \
1257 Label##_W \
1258 }; \
1259 return Ops[Slot]; \
1260 }
1261
getSlotedOps(unsigned Op,unsigned Slot)1262 static unsigned getSlotedOps(unsigned Op, unsigned Slot) {
1263 switch (Op) {
1264 OPERAND_CASE(R600::OpName::update_exec_mask)
1265 OPERAND_CASE(R600::OpName::update_pred)
1266 OPERAND_CASE(R600::OpName::write)
1267 OPERAND_CASE(R600::OpName::omod)
1268 OPERAND_CASE(R600::OpName::dst_rel)
1269 OPERAND_CASE(R600::OpName::clamp)
1270 OPERAND_CASE(R600::OpName::src0)
1271 OPERAND_CASE(R600::OpName::src0_neg)
1272 OPERAND_CASE(R600::OpName::src0_rel)
1273 OPERAND_CASE(R600::OpName::src0_abs)
1274 OPERAND_CASE(R600::OpName::src0_sel)
1275 OPERAND_CASE(R600::OpName::src1)
1276 OPERAND_CASE(R600::OpName::src1_neg)
1277 OPERAND_CASE(R600::OpName::src1_rel)
1278 OPERAND_CASE(R600::OpName::src1_abs)
1279 OPERAND_CASE(R600::OpName::src1_sel)
1280 OPERAND_CASE(R600::OpName::pred_sel)
1281 default:
1282 llvm_unreachable("Wrong Operand");
1283 }
1284 }
1285
1286 #undef OPERAND_CASE
1287
buildSlotOfVectorInstruction(MachineBasicBlock & MBB,MachineInstr * MI,unsigned Slot,unsigned DstReg) const1288 MachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
1289 MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
1290 const {
1291 assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
1292 unsigned Opcode;
1293 if (ST.getGeneration() <= AMDGPUSubtarget::R700)
1294 Opcode = R600::DOT4_r600;
1295 else
1296 Opcode = R600::DOT4_eg;
1297 MachineBasicBlock::iterator I = MI;
1298 MachineOperand &Src0 = MI->getOperand(
1299 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
1300 MachineOperand &Src1 = MI->getOperand(
1301 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
1302 MachineInstr *MIB = buildDefaultInstruction(
1303 MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
1304 static const unsigned Operands[14] = {
1305 R600::OpName::update_exec_mask,
1306 R600::OpName::update_pred,
1307 R600::OpName::write,
1308 R600::OpName::omod,
1309 R600::OpName::dst_rel,
1310 R600::OpName::clamp,
1311 R600::OpName::src0_neg,
1312 R600::OpName::src0_rel,
1313 R600::OpName::src0_abs,
1314 R600::OpName::src0_sel,
1315 R600::OpName::src1_neg,
1316 R600::OpName::src1_rel,
1317 R600::OpName::src1_abs,
1318 R600::OpName::src1_sel,
1319 };
1320
1321 MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
1322 getSlotedOps(R600::OpName::pred_sel, Slot)));
1323 MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
1324 .setReg(MO.getReg());
1325
1326 for (unsigned Operand : Operands) {
1327 MachineOperand &MO = MI->getOperand(
1328 getOperandIdx(MI->getOpcode(), getSlotedOps(Operand, Slot)));
1329 assert (MO.isImm());
1330 setImmOperand(*MIB, Operand, MO.getImm());
1331 }
1332 MIB->getOperand(20).setImm(0);
1333 return MIB;
1334 }
1335
buildMovImm(MachineBasicBlock & BB,MachineBasicBlock::iterator I,unsigned DstReg,uint64_t Imm) const1336 MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
1337 MachineBasicBlock::iterator I,
1338 unsigned DstReg,
1339 uint64_t Imm) const {
1340 MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
1341 R600::ALU_LITERAL_X);
1342 setImmOperand(*MovImm, R600::OpName::literal, Imm);
1343 return MovImm;
1344 }
1345
buildMovInstr(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned DstReg,unsigned SrcReg) const1346 MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,
1347 MachineBasicBlock::iterator I,
1348 unsigned DstReg, unsigned SrcReg) const {
1349 return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
1350 }
1351
getOperandIdx(const MachineInstr & MI,unsigned Op) const1352 int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1353 return getOperandIdx(MI.getOpcode(), Op);
1354 }
1355
getOperandIdx(unsigned Opcode,unsigned Op) const1356 int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
1357 return R600::getNamedOperandIdx(Opcode, Op);
1358 }
1359
setImmOperand(MachineInstr & MI,unsigned Op,int64_t Imm) const1360 void R600InstrInfo::setImmOperand(MachineInstr &MI, unsigned Op,
1361 int64_t Imm) const {
1362 int Idx = getOperandIdx(MI, Op);
1363 assert(Idx != -1 && "Operand not supported for this instruction.");
1364 assert(MI.getOperand(Idx).isImm());
1365 MI.getOperand(Idx).setImm(Imm);
1366 }
1367
1368 //===----------------------------------------------------------------------===//
1369 // Instruction flag getters/setters
1370 //===----------------------------------------------------------------------===//
1371
getFlagOp(MachineInstr & MI,unsigned SrcIdx,unsigned Flag) const1372 MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,
1373 unsigned Flag) const {
1374 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1375 int FlagIndex = 0;
1376 if (Flag != 0) {
1377 // If we pass something other than the default value of Flag to this
1378 // function, it means we are want to set a flag on an instruction
1379 // that uses native encoding.
1380 assert(HAS_NATIVE_OPERANDS(TargetFlags));
1381 bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1382 switch (Flag) {
1383 case MO_FLAG_CLAMP:
1384 FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
1385 break;
1386 case MO_FLAG_MASK:
1387 FlagIndex = getOperandIdx(MI, R600::OpName::write);
1388 break;
1389 case MO_FLAG_NOT_LAST:
1390 case MO_FLAG_LAST:
1391 FlagIndex = getOperandIdx(MI, R600::OpName::last);
1392 break;
1393 case MO_FLAG_NEG:
1394 switch (SrcIdx) {
1395 case 0:
1396 FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
1397 break;
1398 case 1:
1399 FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
1400 break;
1401 case 2:
1402 FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
1403 break;
1404 }
1405 break;
1406
1407 case MO_FLAG_ABS:
1408 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1409 "instructions.");
1410 (void)IsOP3;
1411 switch (SrcIdx) {
1412 case 0:
1413 FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
1414 break;
1415 case 1:
1416 FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
1417 break;
1418 }
1419 break;
1420
1421 default:
1422 FlagIndex = -1;
1423 break;
1424 }
1425 assert(FlagIndex != -1 && "Flag not supported for this instruction");
1426 } else {
1427 FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
1428 assert(FlagIndex != 0 &&
1429 "Instruction flags not supported for this instruction");
1430 }
1431
1432 MachineOperand &FlagOp = MI.getOperand(FlagIndex);
1433 assert(FlagOp.isImm());
1434 return FlagOp;
1435 }
1436
addFlag(MachineInstr & MI,unsigned Operand,unsigned Flag) const1437 void R600InstrInfo::addFlag(MachineInstr &MI, unsigned Operand,
1438 unsigned Flag) const {
1439 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1440 if (Flag == 0) {
1441 return;
1442 }
1443 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1444 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1445 if (Flag == MO_FLAG_NOT_LAST) {
1446 clearFlag(MI, Operand, MO_FLAG_LAST);
1447 } else if (Flag == MO_FLAG_MASK) {
1448 clearFlag(MI, Operand, Flag);
1449 } else {
1450 FlagOp.setImm(1);
1451 }
1452 } else {
1453 MachineOperand &FlagOp = getFlagOp(MI, Operand);
1454 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1455 }
1456 }
1457
clearFlag(MachineInstr & MI,unsigned Operand,unsigned Flag) const1458 void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned Operand,
1459 unsigned Flag) const {
1460 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1461 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1462 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1463 FlagOp.setImm(0);
1464 } else {
1465 MachineOperand &FlagOp = getFlagOp(MI);
1466 unsigned InstFlags = FlagOp.getImm();
1467 InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
1468 FlagOp.setImm(InstFlags);
1469 }
1470 }
1471