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