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
23using 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
33R600InstrInfo::R600InstrInfo(const R600Subtarget &ST)
34 : R600GenInstrInfo(-1, -1), RI(), ST(ST) {}
35
36bool R600InstrInfo::isVector(const MachineInstr &MI) const {
37 return get(Opcode: MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
38}
39
40void 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(Reg: DestReg) ||
46 R600::R600_Reg128VerticalRegClass.contains(Reg: DestReg)) &&
47 (R600::R600_Reg128RegClass.contains(Reg: SrcReg) ||
48 R600::R600_Reg128VerticalRegClass.contains(Reg: SrcReg))) {
49 VectorComponents = 4;
50 } else if((R600::R600_Reg64RegClass.contains(Reg: DestReg) ||
51 R600::R600_Reg64VerticalRegClass.contains(Reg: DestReg)) &&
52 (R600::R600_Reg64RegClass.contains(Reg: SrcReg) ||
53 R600::R600_Reg64VerticalRegClass.contains(Reg: SrcReg))) {
54 VectorComponents = 2;
55 }
56
57 if (VectorComponents > 0) {
58 for (unsigned I = 0; I < VectorComponents; I++) {
59 unsigned SubRegIndex = R600RegisterInfo::getSubRegFromChannel(Channel: I);
60 buildDefaultInstruction(MBB, I: MI, Opcode: R600::MOV,
61 DstReg: RI.getSubReg(Reg: DestReg, Idx: SubRegIndex),
62 Src0Reg: RI.getSubReg(Reg: SrcReg, Idx: SubRegIndex))
63 .addReg(RegNo: DestReg,
64 flags: RegState::Define | RegState::Implicit);
65 }
66 } else {
67 MachineInstr *NewMI = buildDefaultInstruction(MBB, I: MI, Opcode: R600::MOV,
68 DstReg: DestReg, Src0Reg: SrcReg);
69 NewMI->getOperand(i: getOperandIdx(MI: *NewMI, Op: R600::OpName::src0))
70 .setIsKill(KillSrc);
71 }
72}
73
74/// \returns true if \p MBBI can be moved into a new basic.
75bool 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(Reg: I->getReg()))
81 return false;
82 }
83 return true;
84}
85
86bool 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
97bool R600InstrInfo::isReductionOp(unsigned Opcode) const {
98 return false;
99}
100
101bool 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
112bool R600InstrInfo::isALUInstr(unsigned Opcode) const {
113 unsigned TargetFlags = get(Opcode).TSFlags;
114
115 return (TargetFlags & R600_InstFlag::ALU_INST);
116}
117
118bool 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
126bool 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
134bool R600InstrInfo::isLDSRetInstr(unsigned Opcode) const {
135 return isLDSInstr(Opcode) && getOperandIdx(Opcode, Op: R600::OpName::dst) != -1;
136}
137
138bool R600InstrInfo::canBeConsideredALU(const MachineInstr &MI) const {
139 if (isALUInstr(Opcode: MI.getOpcode()))
140 return true;
141 if (isVector(MI) || isCubeOp(Opcode: 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
156bool R600InstrInfo::isTransOnly(unsigned Opcode) const {
157 if (ST.hasCaymanISA())
158 return false;
159 return (get(Opcode).getSchedClass() == R600::Sched::TransALU);
160}
161
162bool R600InstrInfo::isTransOnly(const MachineInstr &MI) const {
163 return isTransOnly(Opcode: MI.getOpcode());
164}
165
166bool R600InstrInfo::isVectorOnly(unsigned Opcode) const {
167 return (get(Opcode).getSchedClass() == R600::Sched::VecALU);
168}
169
170bool R600InstrInfo::isVectorOnly(const MachineInstr &MI) const {
171 return isVectorOnly(Opcode: MI.getOpcode());
172}
173
174bool R600InstrInfo::isExport(unsigned Opcode) const {
175 return (get(Opcode).TSFlags & R600_InstFlag::IS_EXPORT);
176}
177
178bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
179 return ST.hasVertexCache() && IS_VTX(get(Opcode));
180}
181
182bool R600InstrInfo::usesVertexCache(const MachineInstr &MI) const {
183 const MachineFunction *MF = MI.getParent()->getParent();
184 return !AMDGPU::isCompute(CC: MF->getFunction().getCallingConv()) &&
185 usesVertexCache(Opcode: MI.getOpcode());
186}
187
188bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
189 return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
190}
191
192bool R600InstrInfo::usesTextureCache(const MachineInstr &MI) const {
193 const MachineFunction *MF = MI.getParent()->getParent();
194 return (AMDGPU::isCompute(CC: MF->getFunction().getCallingConv()) &&
195 usesVertexCache(Opcode: MI.getOpcode())) ||
196 usesTextureCache(Opcode: MI.getOpcode());
197}
198
199bool 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
209bool R600InstrInfo::usesAddressRegister(MachineInstr &MI) const {
210 return MI.findRegisterUseOperandIdx(Reg: R600::AR_X, TRI: &RI, isKill: false) != -1;
211}
212
213bool R600InstrInfo::definesAddressRegister(MachineInstr &MI) const {
214 return MI.findRegisterDefOperandIdx(Reg: R600::AR_X, TRI: &RI, isDead: false, Overlap: false) != -1;
215}
216
217bool R600InstrInfo::readsLDSSrcReg(const MachineInstr &MI) const {
218 if (!isALUInstr(Opcode: 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(Reg: I->getReg()))
228 return true;
229 }
230 return false;
231}
232
233int 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, Op: Row[0]) == (int)SrcIdx) {
250 return getOperandIdx(Opcode, Op: Row[1]);
251 }
252 }
253 return -1;
254}
255
256SmallVector<std::pair<MachineOperand *, int64_t>, 3>
257R600InstrInfo::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(i: getOperandIdx(Opcode: MI.getOpcode(), Op: Op[0]));
274 Register Reg = MO.getReg();
275 if (Reg == R600::ALU_CONST) {
276 MachineOperand &Sel =
277 MI.getOperand(i: getOperandIdx(Opcode: MI.getOpcode(), Op: Op[1]));
278 Result.push_back(Elt: 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(Opcode: MI.getOpcode(), Op: Op[0]);
293 if (SrcIdx < 0)
294 break;
295 MachineOperand &MO = MI.getOperand(i: SrcIdx);
296 Register Reg = MO.getReg();
297 if (Reg == R600::ALU_CONST) {
298 MachineOperand &Sel = MI.getOperand(i: getOperandIdx(Opcode: MI.getOpcode(), Op: Op[1]));
299 Result.push_back(Elt: std::pair(&MO, Sel.getImm()));
300 continue;
301 }
302 if (Reg == R600::ALU_LITERAL_X) {
303 MachineOperand &Operand =
304 MI.getOperand(i: getOperandIdx(Opcode: MI.getOpcode(), Op: R600::OpName::literal));
305 if (Operand.isImm()) {
306 Result.push_back(Elt: std::pair(&MO, Operand.getImm()));
307 continue;
308 }
309 assert(Operand.isGlobal());
310 }
311 Result.push_back(Elt: std::pair(&MO, 0));
312 }
313 return Result;
314}
315
316std::vector<std::pair<int, unsigned>>
317R600InstrInfo::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(RegNo: Reg) & 0xff;
328 if (Reg == R600::OQAP) {
329 Result.emplace_back(args&: Index, args: 0U);
330 }
331 if (PV.contains(Val: Reg)) {
332 // 255 is used to tells its a PS/PV reg
333 Result.emplace_back(args: 255, args: 0U);
334 continue;
335 }
336 if (Index > 127) {
337 ConstCount++;
338 Result.push_back(x: DummyPair);
339 continue;
340 }
341 unsigned Chan = RI.getHWRegChan(reg: Reg);
342 Result.emplace_back(args&: Index, args&: Chan);
343 }
344 for (; i < 3; ++i)
345 Result.push_back(x: DummyPair);
346 return Result;
347}
348
349static std::vector<std::pair<int, unsigned>>
350Swizzle(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(x&: Src[1], y&: Src[2]);
359 break;
360 case R600InstrInfo::ALU_VEC_102_SCL_221:
361 std::swap(x&: Src[0], y&: Src[1]);
362 break;
363 case R600InstrInfo::ALU_VEC_120_SCL_212:
364 std::swap(x&: Src[0], y&: Src[1]);
365 std::swap(x&: Src[0], y&: Src[2]);
366 break;
367 case R600InstrInfo::ALU_VEC_201:
368 std::swap(x&: Src[0], y&: Src[2]);
369 std::swap(x&: Src[0], y&: Src[1]);
370 break;
371 case R600InstrInfo::ALU_VEC_210:
372 std::swap(x&: Src[0], y&: Src[2]);
373 break;
374 }
375 return Src;
376}
377
378static 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.
405unsigned 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(s: Vector, c: -1, n: sizeof(Vector));
412 for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
413 const std::vector<std::pair<int, unsigned>> &Srcs =
414 Swizzle(Src: IGSrcs[i], Swz: 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(Swz: TransSwz, Op: 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
454static bool
455NextPossibleSolution(
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.
474bool 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, Swz: SwzCandidate, TransSrcs, TransSwz);
482 if (ValidUpTo == IGSrcs.size())
483 return true;
484 } while (NextPossibleSolution(SwzCandidate, Idx: 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.
490static bool
491isConstCompatible(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(Swz: TransSwz, Op: 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
510bool
511R600InstrInfo::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(x: ExtractSrcs(MI&: *MI, PV, ConstCount));
524 unsigned Op = getOperandIdx(Opcode: MI->getOpcode(), Op: R600::OpName::bank_swizzle);
525 ValidSwizzle.push_back(
526 x: (R600InstrInfo::BankSwizzle)MI->getOperand(i: Op).getImm());
527 }
528 std::vector<std::pair<int, unsigned>> TransOps;
529 if (!isLastAluTrans)
530 return FindSwizzleForVectorSlot(IGSrcs, SwzCandidate&: ValidSwizzle, TransSrcs: TransOps, TransSwz: 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(TransSwz: TransBS, TransOps, ConstCount))
544 continue;
545 bool Result = FindSwizzleForVectorSlot(IGSrcs, SwzCandidate&: ValidSwizzle, TransSrcs: TransOps,
546 TransSwz: TransBS);
547 if (Result) {
548 ValidSwizzle.push_back(x: TransBS);
549 return true;
550 }
551 }
552
553 return false;
554}
555
556bool
557R600InstrInfo::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
581bool
582R600InstrInfo::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(Opcode: MI->getOpcode()))
588 continue;
589
590 for (const auto &Src : getSrcs(MI&: *MI)) {
591 if (Src.first->getReg() == R600::ALU_LITERAL_X)
592 Literals.insert(V: Src.second);
593 if (Literals.size() > 4)
594 return false;
595 if (Src.first->getReg() == R600::ALU_CONST)
596 Consts.push_back(x: Src.second);
597 if (R600::R600_KC0RegClass.contains(Reg: Src.first->getReg()) ||
598 R600::R600_KC1RegClass.contains(Reg: Src.first->getReg())) {
599 unsigned Index = RI.getEncodingValue(RegNo: Src.first->getReg()) & 0xff;
600 unsigned Chan = RI.getHWRegChan(reg: Src.first->getReg());
601 Consts.push_back(x: (Index << 2) | Chan);
602 }
603 }
604 }
605 return fitsConstReadLimitations(Consts);
606}
607
608DFAPacketizer *
609R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {
610 const InstrItineraryData *II = STI.getInstrItineraryData();
611 return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(IID: II);
612}
613
614static bool
615isPredicateSetter(unsigned Opcode) {
616 switch (Opcode) {
617 case R600::PRED_X:
618 return true;
619 default:
620 return false;
621 }
622}
623
624static MachineInstr *
625findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
626 MachineBasicBlock::iterator I) {
627 while (I != MBB.begin()) {
628 --I;
629 MachineInstr &MI = *I;
630 if (isPredicateSetter(Opcode: MI.getOpcode()))
631 return &MI;
632 }
633
634 return nullptr;
635}
636
637static
638bool isJump(unsigned Opcode) {
639 return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
640}
641
642static bool isBranch(unsigned Opcode) {
643 return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
644 Opcode == R600::BRANCH_COND_f32;
645}
646
647bool 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(Opcode: I->getOpcode()))
662 return true;
663 if (!isJump(Opcode: I->getOpcode())) {
664 return false;
665 }
666
667 // Remove successive JUMP
668 while (I != MBB.begin() && std::prev(x: I)->getOpcode() == R600::JUMP) {
669 MachineBasicBlock::iterator PriorI = std::prev(x: 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(Opcode: (--I)->getOpcode())) {
679 if (LastOpc == R600::JUMP) {
680 TBB = LastInst.getOperand(i: 0).getMBB();
681 return false;
682 }
683 if (LastOpc == R600::JUMP_COND) {
684 auto predSet = I;
685 while (!isPredicateSetter(Opcode: predSet->getOpcode())) {
686 predSet = --I;
687 }
688 TBB = LastInst.getOperand(i: 0).getMBB();
689 Cond.push_back(Elt: predSet->getOperand(i: 1));
690 Cond.push_back(Elt: predSet->getOperand(i: 2));
691 Cond.push_back(Elt: MachineOperand::CreateReg(Reg: R600::PRED_SEL_ONE, isDef: 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(Opcode: predSet->getOpcode())) {
705 predSet = --I;
706 }
707 TBB = SecondLastInst.getOperand(i: 0).getMBB();
708 FBB = LastInst.getOperand(i: 0).getMBB();
709 Cond.push_back(Elt: predSet->getOperand(i: 1));
710 Cond.push_back(Elt: predSet->getOperand(i: 2));
711 Cond.push_back(Elt: MachineOperand::CreateReg(Reg: R600::PRED_SEL_ONE, isDef: false));
712 return false;
713 }
714
715 // Otherwise, can't handle this.
716 return true;
717}
718
719static
720MachineBasicBlock::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
730unsigned 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(BB: &MBB, MIMD: DL, MCID: get(Opcode: R600::JUMP)).addMBB(MBB: TBB);
742 return 1;
743 }
744 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, I: MBB.end());
745 assert(PredSet && "No previous predicate !");
746 addFlag(MI&: *PredSet, Operand: 0, MO_FLAG_PUSH);
747 PredSet->getOperand(i: 2).setImm(Cond[1].getImm());
748
749 BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: R600::JUMP_COND))
750 .addMBB(MBB: TBB)
751 .addReg(RegNo: R600::PREDICATE_BIT, flags: 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(Opcode: R600::CF_ALU_PUSH_BEFORE));
757 return 1;
758 }
759 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, I: MBB.end());
760 assert(PredSet && "No previous predicate !");
761 addFlag(MI&: *PredSet, Operand: 0, MO_FLAG_PUSH);
762 PredSet->getOperand(i: 2).setImm(Cond[1].getImm());
763 BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: R600::JUMP_COND))
764 .addMBB(MBB: TBB)
765 .addReg(RegNo: R600::PREDICATE_BIT, flags: RegState::Kill);
766 BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: R600::JUMP)).addMBB(MBB: 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(Opcode: R600::CF_ALU_PUSH_BEFORE));
772 return 2;
773}
774
775unsigned 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(MI&: *predSet, Operand: 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(Opcode: 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(MI&: *predSet, Operand: 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(Opcode: R600::CF_ALU));
825 break;
826 }
827 case R600::JUMP:
828 I->eraseFromParent();
829 break;
830 }
831 return 2;
832}
833
834bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {
835 int idx = MI.findFirstPredOperandIdx();
836 if (idx < 0)
837 return false;
838
839 Register Reg = MI.getOperand(i: 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
849bool 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(i: 3).getImm() == 0 && MI.getOperand(i: 4).getImm() == 0;
864 }
865 if (isVector(MI))
866 return false;
867 return TargetInstrInfo::isPredicable(MI);
868}
869
870bool
871R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
872 unsigned NumCycles,
873 unsigned ExtraPredCycles,
874 BranchProbability Probability) const{
875 return true;
876}
877
878bool
879R600InstrInfo::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
889bool
890R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
891 unsigned NumCycles,
892 BranchProbability Probability)
893 const {
894 return true;
895}
896
897bool
898R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
899 MachineBasicBlock &FMBB) const {
900 return false;
901}
902
903bool
904R600InstrInfo::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
937bool R600InstrInfo::ClobbersPredicate(MachineInstr &MI,
938 std::vector<MachineOperand> &Pred,
939 bool SkipDead) const {
940 return isPredicateSetter(Opcode: MI.getOpcode());
941}
942
943bool 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(i: 8).setImm(0);
949 return true;
950 }
951
952 if (MI.getOpcode() == R600::DOT_4) {
953 MI.getOperand(i: getOperandIdx(MI, Op: R600::OpName::pred_sel_X))
954 .setReg(Pred[2].getReg());
955 MI.getOperand(i: getOperandIdx(MI, Op: R600::OpName::pred_sel_Y))
956 .setReg(Pred[2].getReg());
957 MI.getOperand(i: getOperandIdx(MI, Op: R600::OpName::pred_sel_Z))
958 .setReg(Pred[2].getReg());
959 MI.getOperand(i: getOperandIdx(MI, Op: R600::OpName::pred_sel_W))
960 .setReg(Pred[2].getReg());
961 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
962 MIB.addReg(RegNo: R600::PREDICATE_BIT, flags: RegState::Implicit);
963 return true;
964 }
965
966 if (PIdx != -1) {
967 MachineOperand &PMO = MI.getOperand(i: PIdx);
968 PMO.setReg(Pred[2].getReg());
969 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
970 MIB.addReg(RegNo: R600::PREDICATE_BIT, flags: RegState::Implicit);
971 return true;
972 }
973
974 return false;
975}
976
977unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {
978 return 2;
979}
980
981unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
982 const MachineInstr &,
983 unsigned *PredCost) const {
984 if (PredCost)
985 *PredCost = 2;
986 return 2;
987}
988
989unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
990 unsigned Channel) const {
991 assert(Channel == 0);
992 return RegIndex;
993}
994
995bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
996 switch (MI.getOpcode()) {
997 default: {
998 MachineBasicBlock *MBB = MI.getParent();
999 int OffsetOpIdx =
1000 R600::getNamedOperandIdx(Opcode: MI.getOpcode(), NamedIdx: 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(Opcode: MI.getOpcode(), NamedIdx: R600::OpName::chan);
1006 if (isRegisterLoad(MI)) {
1007 int DstOpIdx =
1008 R600::getNamedOperandIdx(Opcode: MI.getOpcode(), NamedIdx: R600::OpName::dst);
1009 unsigned RegIndex = MI.getOperand(i: RegOpIdx).getImm();
1010 unsigned Channel = MI.getOperand(i: ChanOpIdx).getImm();
1011 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1012 Register OffsetReg = MI.getOperand(i: OffsetOpIdx).getReg();
1013 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1014 buildMovInstr(MBB, I: MI, DstReg: MI.getOperand(i: DstOpIdx).getReg(),
1015 SrcReg: getIndirectAddrRegClass()->getRegister(i: Address));
1016 } else {
1017 buildIndirectRead(MBB, I: MI, ValueReg: MI.getOperand(i: DstOpIdx).getReg(), Address,
1018 OffsetReg);
1019 }
1020 } else if (isRegisterStore(MI)) {
1021 int ValOpIdx =
1022 R600::getNamedOperandIdx(Opcode: MI.getOpcode(), NamedIdx: R600::OpName::val);
1023 unsigned RegIndex = MI.getOperand(i: RegOpIdx).getImm();
1024 unsigned Channel = MI.getOperand(i: ChanOpIdx).getImm();
1025 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1026 Register OffsetReg = MI.getOperand(i: OffsetOpIdx).getReg();
1027 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1028 buildMovInstr(MBB, I: MI, DstReg: getIndirectAddrRegClass()->getRegister(i: Address),
1029 SrcReg: MI.getOperand(i: ValOpIdx).getReg());
1030 } else {
1031 buildIndirectWrite(MBB, I: MI, ValueReg: MI.getOperand(i: ValOpIdx).getReg(),
1032 Address: calculateIndirectAddress(RegIndex, Channel),
1033 OffsetReg);
1034 }
1035 } else {
1036 return false;
1037 }
1038
1039 MBB->erase(I: MI);
1040 return true;
1041 }
1042 case R600::R600_EXTRACT_ELT_V2:
1043 case R600::R600_EXTRACT_ELT_V4:
1044 buildIndirectRead(MBB: MI.getParent(), I: MI, ValueReg: MI.getOperand(i: 0).getReg(),
1045 Address: RI.getHWRegIndex(Reg: MI.getOperand(i: 1).getReg()), // Address
1046 OffsetReg: MI.getOperand(i: 2).getReg(),
1047 AddrChan: RI.getHWRegChan(reg: MI.getOperand(i: 1).getReg()));
1048 break;
1049 case R600::R600_INSERT_ELT_V2:
1050 case R600::R600_INSERT_ELT_V4:
1051 buildIndirectWrite(MBB: MI.getParent(), I: MI, ValueReg: MI.getOperand(i: 2).getReg(), // Value
1052 Address: RI.getHWRegIndex(Reg: MI.getOperand(i: 1).getReg()), // Address
1053 OffsetReg: MI.getOperand(i: 3).getReg(), // Offset
1054 AddrChan: RI.getHWRegChan(reg: MI.getOperand(i: 1).getReg())); // Channel
1055 break;
1056 }
1057 MI.eraseFromParent();
1058 return true;
1059}
1060
1061void 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(i: (4 * Index) + Chan);
1076 TRI.reserveRegisterTuples(Reserved, Reg);
1077 }
1078 }
1079}
1080
1081const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {
1082 return &R600::R600_TReg32_XRegClass;
1083}
1084
1085MachineInstrBuilder 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, AddrChan: 0);
1090}
1091
1092MachineInstrBuilder 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(i: Address); break;
1101 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(i: Address); break;
1102 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(i: Address); break;
1103 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(i: Address); break;
1104 }
1105 MachineInstr *MOVA = buildDefaultInstruction(MBB&: *MBB, I, Opcode: R600::MOVA_INT_eg,
1106 DstReg: R600::AR_X, Src0Reg: OffsetReg);
1107 setImmOperand(MI&: *MOVA, Op: R600::OpName::write, Imm: 0);
1108
1109 MachineInstrBuilder Mov = buildDefaultInstruction(MBB&: *MBB, I, Opcode: R600::MOV,
1110 DstReg: AddrReg, Src0Reg: ValueReg)
1111 .addReg(RegNo: R600::AR_X,
1112 flags: RegState::Implicit | RegState::Kill);
1113 setImmOperand(MI&: *Mov, Op: R600::OpName::dst_rel, Imm: 1);
1114 return Mov;
1115}
1116
1117MachineInstrBuilder 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, AddrChan: 0);
1122}
1123
1124MachineInstrBuilder 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(i: Address); break;
1133 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(i: Address); break;
1134 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(i: Address); break;
1135 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(i: Address); break;
1136 }
1137 MachineInstr *MOVA = buildDefaultInstruction(MBB&: *MBB, I, Opcode: R600::MOVA_INT_eg,
1138 DstReg: R600::AR_X,
1139 Src0Reg: OffsetReg);
1140 setImmOperand(MI&: *MOVA, Op: R600::OpName::write, Imm: 0);
1141 MachineInstrBuilder Mov = buildDefaultInstruction(MBB&: *MBB, I, Opcode: R600::MOV,
1142 DstReg: ValueReg,
1143 Src0Reg: AddrReg)
1144 .addReg(RegNo: R600::AR_X,
1145 flags: RegState::Implicit | RegState::Kill);
1146 setImmOperand(MI&: *Mov, Op: R600::OpName::src0_rel, Imm: 1);
1147
1148 return Mov;
1149}
1150
1151int 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(i: RegIndex) == (unsigned)Reg)
1175 break;
1176 }
1177 Offset = std::max(a: Offset, b: (int)RegIndex);
1178 }
1179
1180 return Offset + 1;
1181}
1182
1183int 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, FI: -1, FrameReg&: IgnoredFrameReg).getFixed();
1201
1202 return getIndirectIndexBegin(MF) + Offset;
1203}
1204
1205unsigned R600InstrInfo::getMaxAlusPerClause() const {
1206 return 115;
1207}
1208
1209MachineInstrBuilder 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(BB&: MBB, I, MIMD: MBB.findDebugLoc(MBBI: I), MCID: get(Opcode),
1216 DestReg: DstReg); // $dst
1217
1218 if (Src1Reg) {
1219 MIB.addImm(Val: 0) // $update_exec_mask
1220 .addImm(Val: 0); // $update_predicate
1221 }
1222 MIB.addImm(Val: 1) // $write
1223 .addImm(Val: 0) // $omod
1224 .addImm(Val: 0) // $dst_rel
1225 .addImm(Val: 0) // $dst_clamp
1226 .addReg(RegNo: Src0Reg) // $src0
1227 .addImm(Val: 0) // $src0_neg
1228 .addImm(Val: 0) // $src0_rel
1229 .addImm(Val: 0) // $src0_abs
1230 .addImm(Val: -1); // $src0_sel
1231
1232 if (Src1Reg) {
1233 MIB.addReg(RegNo: Src1Reg) // $src1
1234 .addImm(Val: 0) // $src1_neg
1235 .addImm(Val: 0) // $src1_rel
1236 .addImm(Val: 0) // $src1_abs
1237 .addImm(Val: -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(Val: 1) // $last
1243 .addReg(RegNo: R600::PRED_SEL_OFF) // $pred_sel
1244 .addImm(Val: 0) // $literal
1245 .addImm(Val: 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
1262static 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
1288MachineInstr *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 i: getOperandIdx(Opcode: MI->getOpcode(), Op: getSlotedOps(Op: R600::OpName::src0, Slot)));
1300 MachineOperand &Src1 = MI->getOperand(
1301 i: getOperandIdx(Opcode: MI->getOpcode(), Op: getSlotedOps(Op: R600::OpName::src1, Slot)));
1302 MachineInstr *MIB = buildDefaultInstruction(
1303 MBB, I, Opcode, DstReg, Src0Reg: Src0.getReg(), Src1Reg: 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(i: getOperandIdx(Opcode: MI->getOpcode(),
1322 Op: getSlotedOps(Op: R600::OpName::pred_sel, Slot)));
1323 MIB->getOperand(i: getOperandIdx(Opcode, Op: R600::OpName::pred_sel))
1324 .setReg(MO.getReg());
1325
1326 for (unsigned Operand : Operands) {
1327 MachineOperand &MO = MI->getOperand(
1328 i: getOperandIdx(Opcode: MI->getOpcode(), Op: getSlotedOps(Op: Operand, Slot)));
1329 assert (MO.isImm());
1330 setImmOperand(MI&: *MIB, Op: Operand, Imm: MO.getImm());
1331 }
1332 MIB->getOperand(i: 20).setImm(0);
1333 return MIB;
1334}
1335
1336MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
1337 MachineBasicBlock::iterator I,
1338 unsigned DstReg,
1339 uint64_t Imm) const {
1340 MachineInstr *MovImm = buildDefaultInstruction(MBB&: BB, I, Opcode: R600::MOV, DstReg,
1341 Src0Reg: R600::ALU_LITERAL_X);
1342 setImmOperand(MI&: *MovImm, Op: R600::OpName::literal, Imm);
1343 return MovImm;
1344}
1345
1346MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,
1347 MachineBasicBlock::iterator I,
1348 unsigned DstReg, unsigned SrcReg) const {
1349 return buildDefaultInstruction(MBB&: *MBB, I, Opcode: R600::MOV, DstReg, Src0Reg: SrcReg);
1350}
1351
1352int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1353 return getOperandIdx(Opcode: MI.getOpcode(), Op);
1354}
1355
1356int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
1357 return R600::getNamedOperandIdx(Opcode, NamedIdx: Op);
1358}
1359
1360void 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(i: Idx).setImm(Imm);
1366}
1367
1368//===----------------------------------------------------------------------===//
1369// Instruction flag getters/setters
1370//===----------------------------------------------------------------------===//
1371
1372MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,
1373 unsigned Flag) const {
1374 unsigned TargetFlags = get(Opcode: 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, Op: R600::OpName::clamp);
1385 break;
1386 case MO_FLAG_MASK:
1387 FlagIndex = getOperandIdx(MI, Op: R600::OpName::write);
1388 break;
1389 case MO_FLAG_NOT_LAST:
1390 case MO_FLAG_LAST:
1391 FlagIndex = getOperandIdx(MI, Op: R600::OpName::last);
1392 break;
1393 case MO_FLAG_NEG:
1394 switch (SrcIdx) {
1395 case 0:
1396 FlagIndex = getOperandIdx(MI, Op: R600::OpName::src0_neg);
1397 break;
1398 case 1:
1399 FlagIndex = getOperandIdx(MI, Op: R600::OpName::src1_neg);
1400 break;
1401 case 2:
1402 FlagIndex = getOperandIdx(MI, Op: 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, Op: R600::OpName::src0_abs);
1414 break;
1415 case 1:
1416 FlagIndex = getOperandIdx(MI, Op: 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(i: FlagIndex);
1433 assert(FlagOp.isImm());
1434 return FlagOp;
1435}
1436
1437void R600InstrInfo::addFlag(MachineInstr &MI, unsigned Operand,
1438 unsigned Flag) const {
1439 unsigned TargetFlags = get(Opcode: MI.getOpcode()).TSFlags;
1440 if (Flag == 0) {
1441 return;
1442 }
1443 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1444 MachineOperand &FlagOp = getFlagOp(MI, SrcIdx: 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, SrcIdx: Operand);
1454 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1455 }
1456}
1457
1458void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned Operand,
1459 unsigned Flag) const {
1460 unsigned TargetFlags = get(Opcode: MI.getOpcode()).TSFlags;
1461 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1462 MachineOperand &FlagOp = getFlagOp(MI, SrcIdx: 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