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