LLVM 20.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, MCRegister DestReg,
41 MCRegister 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 unsigned 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
239 for (const auto &Row : SrcSelTable) {
240 if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {
241 return getOperandIdx(Opcode, Row[1]);
242 }
243 }
244 return -1;
245}
246
250
251 if (MI.getOpcode() == R600::DOT_4) {
252 static const unsigned OpTable[8][2] = {
253 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
254 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
255 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
256 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
257 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
258 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
259 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
260 {R600::OpName::src1_W, R600::OpName::src1_sel_W},
261 };
262
263 for (const auto &Op : OpTable) {
264 MachineOperand &MO = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[0]));
265 Register Reg = MO.getReg();
266 if (Reg == R600::ALU_CONST) {
267 MachineOperand &Sel =
268 MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));
269 Result.push_back(std::pair(&MO, Sel.getImm()));
270 continue;
271 }
272 }
273 return Result;
274 }
275
276 static const unsigned OpTable[3][2] = {
277 {R600::OpName::src0, R600::OpName::src0_sel},
278 {R600::OpName::src1, R600::OpName::src1_sel},
279 {R600::OpName::src2, R600::OpName::src2_sel},
280 };
281
282 for (const auto &Op : OpTable) {
283 int SrcIdx = getOperandIdx(MI.getOpcode(), Op[0]);
284 if (SrcIdx < 0)
285 break;
286 MachineOperand &MO = MI.getOperand(SrcIdx);
287 Register Reg = MO.getReg();
288 if (Reg == R600::ALU_CONST) {
289 MachineOperand &Sel = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));
290 Result.push_back(std::pair(&MO, Sel.getImm()));
291 continue;
292 }
293 if (Reg == R600::ALU_LITERAL_X) {
294 MachineOperand &Operand =
295 MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
296 if (Operand.isImm()) {
297 Result.push_back(std::pair(&MO, Operand.getImm()));
298 continue;
299 }
300 assert(Operand.isGlobal());
301 }
302 Result.push_back(std::pair(&MO, 0));
303 }
304 return Result;
305}
306
307std::vector<std::pair<int, unsigned>>
308R600InstrInfo::ExtractSrcs(MachineInstr &MI,
310 unsigned &ConstCount) const {
311 ConstCount = 0;
312 const std::pair<int, unsigned> DummyPair(-1, 0);
313 std::vector<std::pair<int, unsigned>> Result;
314 unsigned i = 0;
315 for (const auto &Src : getSrcs(MI)) {
316 ++i;
317 Register Reg = Src.first->getReg();
318 int Index = RI.getEncodingValue(Reg) & 0xff;
319 if (Reg == R600::OQAP) {
320 Result.emplace_back(Index, 0U);
321 }
322 if (PV.contains(Reg)) {
323 // 255 is used to tells its a PS/PV reg
324 Result.emplace_back(255, 0U);
325 continue;
326 }
327 if (Index > 127) {
328 ConstCount++;
329 Result.push_back(DummyPair);
330 continue;
331 }
332 unsigned Chan = RI.getHWRegChan(Reg);
333 Result.emplace_back(Index, Chan);
334 }
335 for (; i < 3; ++i)
336 Result.push_back(DummyPair);
337 return Result;
338}
339
340static std::vector<std::pair<int, unsigned>>
341Swizzle(std::vector<std::pair<int, unsigned>> Src,
343 if (Src[0] == Src[1])
344 Src[1].first = -1;
345 switch (Swz) {
347 break;
349 std::swap(Src[1], Src[2]);
350 break;
352 std::swap(Src[0], Src[1]);
353 break;
355 std::swap(Src[0], Src[1]);
356 std::swap(Src[0], Src[2]);
357 break;
359 std::swap(Src[0], Src[2]);
360 std::swap(Src[0], Src[1]);
361 break;
363 std::swap(Src[0], Src[2]);
364 break;
365 }
366 return Src;
367}
368
369static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
370 assert(Op < 3 && "Out of range swizzle index");
371 switch (Swz) {
373 unsigned Cycles[3] = { 2, 1, 0};
374 return Cycles[Op];
375 }
377 unsigned Cycles[3] = { 1, 2, 2};
378 return Cycles[Op];
379 }
381 unsigned Cycles[3] = { 2, 1, 2};
382 return Cycles[Op];
383 }
385 unsigned Cycles[3] = { 2, 2, 1};
386 return Cycles[Op];
387 }
388 default:
389 llvm_unreachable("Wrong Swizzle for Trans Slot");
390 }
391}
392
393/// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
394/// in the same Instruction Group while meeting read port limitations given a
395/// Swz swizzle sequence.
397 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
398 const std::vector<R600InstrInfo::BankSwizzle> &Swz,
399 const std::vector<std::pair<int, unsigned>> &TransSrcs,
400 R600InstrInfo::BankSwizzle TransSwz) const {
401 int Vector[4][3];
402 memset(Vector, -1, sizeof(Vector));
403 for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
404 const std::vector<std::pair<int, unsigned>> &Srcs =
405 Swizzle(IGSrcs[i], Swz[i]);
406 for (unsigned j = 0; j < 3; j++) {
407 const std::pair<int, unsigned> &Src = Srcs[j];
408 if (Src.first < 0 || Src.first == 255)
409 continue;
410 if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {
413 // The value from output queue A (denoted by register OQAP) can
414 // only be fetched during the first cycle.
415 return false;
416 }
417 // OQAP does not count towards the normal read port restrictions
418 continue;
419 }
420 if (Vector[Src.second][j] < 0)
421 Vector[Src.second][j] = Src.first;
422 if (Vector[Src.second][j] != Src.first)
423 return i;
424 }
425 }
426 // Now check Trans Alu
427 for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
428 const std::pair<int, unsigned> &Src = TransSrcs[i];
429 unsigned Cycle = getTransSwizzle(TransSwz, i);
430 if (Src.first < 0)
431 continue;
432 if (Src.first == 255)
433 continue;
434 if (Vector[Src.second][Cycle] < 0)
435 Vector[Src.second][Cycle] = Src.first;
436 if (Vector[Src.second][Cycle] != Src.first)
437 return IGSrcs.size() - 1;
438 }
439 return IGSrcs.size();
440}
441
442/// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
443/// (in lexicographic term) swizzle sequence assuming that all swizzles after
444/// Idx can be skipped
445static bool
447 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
448 unsigned Idx) {
449 assert(Idx < SwzCandidate.size());
450 int ResetIdx = Idx;
451 while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
452 ResetIdx --;
453 for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
454 SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
455 }
456 if (ResetIdx == -1)
457 return false;
458 int NextSwizzle = SwzCandidate[ResetIdx] + 1;
459 SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
460 return true;
461}
462
463/// Enumerate all possible Swizzle sequence to find one that can meet all
464/// read port requirements.
466 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
467 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
468 const std::vector<std::pair<int, unsigned>> &TransSrcs,
469 R600InstrInfo::BankSwizzle TransSwz) const {
470 unsigned ValidUpTo = 0;
471 do {
472 ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
473 if (ValidUpTo == IGSrcs.size())
474 return true;
475 } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
476 return false;
477}
478
479/// Instructions in Trans slot can't read gpr at cycle 0 if they also read
480/// a const, and can't read a gpr at cycle 1 if they read 2 const.
481static bool
483 const std::vector<std::pair<int, unsigned>> &TransOps,
484 unsigned ConstCount) {
485 // TransALU can't read 3 constants
486 if (ConstCount > 2)
487 return false;
488 for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
489 const std::pair<int, unsigned> &Src = TransOps[i];
490 unsigned Cycle = getTransSwizzle(TransSwz, i);
491 if (Src.first < 0)
492 continue;
493 if (ConstCount > 0 && Cycle == 0)
494 return false;
495 if (ConstCount > 1 && Cycle == 1)
496 return false;
497 }
498 return true;
499}
500
501bool
502R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
504 std::vector<BankSwizzle> &ValidSwizzle,
505 bool isLastAluTrans)
506 const {
507 //Todo : support shared src0 - src1 operand
508
509 std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
510 ValidSwizzle.clear();
511 unsigned ConstCount;
513 for (MachineInstr *MI : IG) {
514 IGSrcs.push_back(ExtractSrcs(*MI, PV, ConstCount));
515 unsigned Op = getOperandIdx(MI->getOpcode(), R600::OpName::bank_swizzle);
516 ValidSwizzle.push_back(
517 (R600InstrInfo::BankSwizzle)MI->getOperand(Op).getImm());
518 }
519 std::vector<std::pair<int, unsigned>> TransOps;
520 if (!isLastAluTrans)
521 return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
522
523 TransOps = std::move(IGSrcs.back());
524 IGSrcs.pop_back();
525 ValidSwizzle.pop_back();
526
527 static const R600InstrInfo::BankSwizzle TransSwz[] = {
532 };
533 for (R600InstrInfo::BankSwizzle TransBS : TransSwz) {
534 if (!isConstCompatible(TransBS, TransOps, ConstCount))
535 continue;
536 bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
537 TransBS);
538 if (Result) {
539 ValidSwizzle.push_back(TransBS);
540 return true;
541 }
542 }
543
544 return false;
545}
546
547bool
548R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
549 const {
550 assert (Consts.size() <= 12 && "Too many operands in instructions group");
551 unsigned Pair1 = 0, Pair2 = 0;
552 for (unsigned Const : Consts) {
553 unsigned ReadConstHalf = Const & 2;
554 unsigned ReadConstIndex = Const & (~3);
555 unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
556 if (!Pair1) {
557 Pair1 = ReadHalfConst;
558 continue;
559 }
560 if (Pair1 == ReadHalfConst)
561 continue;
562 if (!Pair2) {
563 Pair2 = ReadHalfConst;
564 continue;
565 }
566 if (Pair2 != ReadHalfConst)
567 return false;
568 }
569 return true;
570}
571
572bool
573R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
574 const {
575 std::vector<unsigned> Consts;
576 SmallSet<int64_t, 4> Literals;
577 for (MachineInstr *MI : MIs) {
578 if (!isALUInstr(MI->getOpcode()))
579 continue;
580
581 for (const auto &Src : getSrcs(*MI)) {
582 if (Src.first->getReg() == R600::ALU_LITERAL_X)
583 Literals.insert(Src.second);
584 if (Literals.size() > 4)
585 return false;
586 if (Src.first->getReg() == R600::ALU_CONST)
587 Consts.push_back(Src.second);
588 if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
589 R600::R600_KC1RegClass.contains(Src.first->getReg())) {
590 unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
591 unsigned Chan = RI.getHWRegChan(Src.first->getReg());
592 Consts.push_back((Index << 2) | Chan);
593 }
594 }
595 }
596 return fitsConstReadLimitations(Consts);
597}
598
602 return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
603}
604
605static bool
606isPredicateSetter(unsigned Opcode) {
607 switch (Opcode) {
608 case R600::PRED_X:
609 return true;
610 default:
611 return false;
612 }
613}
614
615static MachineInstr *
618 while (I != MBB.begin()) {
619 --I;
620 MachineInstr &MI = *I;
621 if (isPredicateSetter(MI.getOpcode()))
622 return &MI;
623 }
624
625 return nullptr;
626}
627
628static
629bool isJump(unsigned Opcode) {
630 return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
631}
632
633static bool isBranch(unsigned Opcode) {
634 return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
635 Opcode == R600::BRANCH_COND_f32;
636}
637
640 MachineBasicBlock *&FBB,
642 bool AllowModify) const {
643 // Most of the following comes from the ARM implementation of analyzeBranch
644
645 // If the block has no terminators, it just falls into the block after it.
647 if (I == MBB.end())
648 return false;
649
650 // R600::BRANCH* instructions are only available after isel and are not
651 // handled
652 if (isBranch(I->getOpcode()))
653 return true;
654 if (!isJump(I->getOpcode())) {
655 return false;
656 }
657
658 // Remove successive JUMP
659 while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
660 MachineBasicBlock::iterator PriorI = std::prev(I);
661 if (AllowModify)
662 I->removeFromParent();
663 I = PriorI;
664 }
665 MachineInstr &LastInst = *I;
666
667 // If there is only one terminator instruction, process it.
668 unsigned LastOpc = LastInst.getOpcode();
669 if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
670 if (LastOpc == R600::JUMP) {
671 TBB = LastInst.getOperand(0).getMBB();
672 return false;
673 }
674 if (LastOpc == R600::JUMP_COND) {
675 auto predSet = I;
676 while (!isPredicateSetter(predSet->getOpcode())) {
677 predSet = --I;
678 }
679 TBB = LastInst.getOperand(0).getMBB();
680 Cond.push_back(predSet->getOperand(1));
681 Cond.push_back(predSet->getOperand(2));
682 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
683 return false;
684 }
685 return true; // Can't handle indirect branch.
686 }
687
688 // Get the instruction before it if it is a terminator.
689 MachineInstr &SecondLastInst = *I;
690 unsigned SecondLastOpc = SecondLastInst.getOpcode();
691
692 // If the block ends with a B and a Bcc, handle it.
693 if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
694 auto predSet = --I;
695 while (!isPredicateSetter(predSet->getOpcode())) {
696 predSet = --I;
697 }
698 TBB = SecondLastInst.getOperand(0).getMBB();
699 FBB = LastInst.getOperand(0).getMBB();
700 Cond.push_back(predSet->getOperand(1));
701 Cond.push_back(predSet->getOperand(2));
702 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
703 return false;
704 }
705
706 // Otherwise, can't handle this.
707 return true;
708}
709
710static
713 It != E; ++It) {
714 if (It->getOpcode() == R600::CF_ALU ||
715 It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
716 return It.getReverse();
717 }
718 return MBB.end();
719}
720
725 const DebugLoc &DL,
726 int *BytesAdded) const {
727 assert(TBB && "insertBranch must not be told to insert a fallthrough");
728 assert(!BytesAdded && "code size not handled");
729
730 if (!FBB) {
731 if (Cond.empty()) {
732 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
733 return 1;
734 }
736 assert(PredSet && "No previous predicate !");
737 addFlag(*PredSet, 0, MO_FLAG_PUSH);
738 PredSet->getOperand(2).setImm(Cond[1].getImm());
739
740 BuildMI(&MBB, DL, get(R600::JUMP_COND))
741 .addMBB(TBB)
742 .addReg(R600::PREDICATE_BIT, RegState::Kill);
744 if (CfAlu == MBB.end())
745 return 1;
746 assert (CfAlu->getOpcode() == R600::CF_ALU);
747 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
748 return 1;
749 }
751 assert(PredSet && "No previous predicate !");
752 addFlag(*PredSet, 0, MO_FLAG_PUSH);
753 PredSet->getOperand(2).setImm(Cond[1].getImm());
754 BuildMI(&MBB, DL, get(R600::JUMP_COND))
755 .addMBB(TBB)
756 .addReg(R600::PREDICATE_BIT, RegState::Kill);
757 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);
759 if (CfAlu == MBB.end())
760 return 2;
761 assert(CfAlu->getOpcode() == R600::CF_ALU);
762 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
763 return 2;
764}
765
767 int *BytesRemoved) const {
768 assert(!BytesRemoved && "code size not handled");
769
770 // Note : we leave PRED* instructions there.
771 // They may be needed when predicating instructions.
772
774
775 if (I == MBB.begin()) {
776 return 0;
777 }
778 --I;
779 switch (I->getOpcode()) {
780 default:
781 return 0;
782 case R600::JUMP_COND: {
784 clearFlag(*predSet, 0, MO_FLAG_PUSH);
785 I->eraseFromParent();
787 if (CfAlu == MBB.end())
788 break;
789 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
790 CfAlu->setDesc(get(R600::CF_ALU));
791 break;
792 }
793 case R600::JUMP:
794 I->eraseFromParent();
795 break;
796 }
797 I = MBB.end();
798
799 if (I == MBB.begin()) {
800 return 1;
801 }
802 --I;
803 switch (I->getOpcode()) {
804 // FIXME: only one case??
805 default:
806 return 1;
807 case R600::JUMP_COND: {
809 clearFlag(*predSet, 0, MO_FLAG_PUSH);
810 I->eraseFromParent();
812 if (CfAlu == MBB.end())
813 break;
814 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
815 CfAlu->setDesc(get(R600::CF_ALU));
816 break;
817 }
818 case R600::JUMP:
819 I->eraseFromParent();
820 break;
821 }
822 return 2;
823}
824
826 int idx = MI.findFirstPredOperandIdx();
827 if (idx < 0)
828 return false;
829
830 Register Reg = MI.getOperand(idx).getReg();
831 switch (Reg) {
832 default: return false;
833 case R600::PRED_SEL_ONE:
834 case R600::PRED_SEL_ZERO:
835 case R600::PREDICATE_BIT:
836 return true;
837 }
838}
839
841 // XXX: KILL* instructions can be predicated, but they must be the last
842 // instruction in a clause, so this means any instructions after them cannot
843 // be predicated. Until we have proper support for instruction clauses in the
844 // backend, we will mark KILL* instructions as unpredicable.
845
846 if (MI.getOpcode() == R600::KILLGT)
847 return false;
848 if (MI.getOpcode() == R600::CF_ALU) {
849 // If the clause start in the middle of MBB then the MBB has more
850 // than a single clause, unable to predicate several clauses.
851 if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
852 return false;
853 // TODO: We don't support KC merging atm
854 return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
855 }
856 if (isVector(MI))
857 return false;
859}
860
861bool
863 unsigned NumCycles,
864 unsigned ExtraPredCycles,
865 BranchProbability Probability) const{
866 return true;
867}
868
869bool
871 unsigned NumTCycles,
872 unsigned ExtraTCycles,
873 MachineBasicBlock &FMBB,
874 unsigned NumFCycles,
875 unsigned ExtraFCycles,
876 BranchProbability Probability) const {
877 return true;
878}
879
880bool
882 unsigned NumCycles,
883 BranchProbability Probability)
884 const {
885 return true;
886}
887
888bool
890 MachineBasicBlock &FMBB) const {
891 return false;
892}
893
894bool
896 MachineOperand &MO = Cond[1];
897 switch (MO.getImm()) {
898 case R600::PRED_SETE_INT:
899 MO.setImm(R600::PRED_SETNE_INT);
900 break;
901 case R600::PRED_SETNE_INT:
902 MO.setImm(R600::PRED_SETE_INT);
903 break;
904 case R600::PRED_SETE:
905 MO.setImm(R600::PRED_SETNE);
906 break;
907 case R600::PRED_SETNE:
908 MO.setImm(R600::PRED_SETE);
909 break;
910 default:
911 return true;
912 }
913
914 MachineOperand &MO2 = Cond[2];
915 switch (MO2.getReg()) {
916 case R600::PRED_SEL_ZERO:
917 MO2.setReg(R600::PRED_SEL_ONE);
918 break;
919 case R600::PRED_SEL_ONE:
920 MO2.setReg(R600::PRED_SEL_ZERO);
921 break;
922 default:
923 return true;
924 }
925 return false;
926}
927
929 std::vector<MachineOperand> &Pred,
930 bool SkipDead) const {
931 return isPredicateSetter(MI.getOpcode());
932}
933
935 ArrayRef<MachineOperand> Pred) const {
936 int PIdx = MI.findFirstPredOperandIdx();
937
938 if (MI.getOpcode() == R600::CF_ALU) {
939 MI.getOperand(8).setImm(0);
940 return true;
941 }
942
943 if (MI.getOpcode() == R600::DOT_4) {
944 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
945 .setReg(Pred[2].getReg());
946 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
947 .setReg(Pred[2].getReg());
948 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
949 .setReg(Pred[2].getReg());
950 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
951 .setReg(Pred[2].getReg());
952 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
953 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
954 return true;
955 }
956
957 if (PIdx != -1) {
958 MachineOperand &PMO = MI.getOperand(PIdx);
959 PMO.setReg(Pred[2].getReg());
960 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
961 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
962 return true;
963 }
964
965 return false;
966}
967
969 return 2;
970}
971
973 const MachineInstr &,
974 unsigned *PredCost) const {
975 if (PredCost)
976 *PredCost = 2;
977 return 2;
978}
979
981 unsigned Channel) const {
982 assert(Channel == 0);
983 return RegIndex;
984}
985
987 switch (MI.getOpcode()) {
988 default: {
989 MachineBasicBlock *MBB = MI.getParent();
990 int OffsetOpIdx =
991 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
992 // addr is a custom operand with multiple MI operands, and only the
993 // first MI operand is given a name.
994 int RegOpIdx = OffsetOpIdx + 1;
995 int ChanOpIdx =
996 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
997 if (isRegisterLoad(MI)) {
998 int DstOpIdx =
999 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
1000 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1001 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1002 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1003 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1004 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1005 buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
1006 getIndirectAddrRegClass()->getRegister(Address));
1007 } else {
1008 buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
1009 OffsetReg);
1010 }
1011 } else if (isRegisterStore(MI)) {
1012 int ValOpIdx =
1013 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
1014 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1015 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1016 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1017 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1018 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1020 MI.getOperand(ValOpIdx).getReg());
1021 } else {
1022 buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
1023 calculateIndirectAddress(RegIndex, Channel),
1024 OffsetReg);
1025 }
1026 } else {
1027 return false;
1028 }
1029
1030 MBB->erase(MI);
1031 return true;
1032 }
1033 case R600::R600_EXTRACT_ELT_V2:
1034 case R600::R600_EXTRACT_ELT_V4:
1035 buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
1036 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1037 MI.getOperand(2).getReg(),
1038 RI.getHWRegChan(MI.getOperand(1).getReg()));
1039 break;
1040 case R600::R600_INSERT_ELT_V2:
1041 case R600::R600_INSERT_ELT_V4:
1042 buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
1043 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1044 MI.getOperand(3).getReg(), // Offset
1045 RI.getHWRegChan(MI.getOperand(1).getReg())); // Channel
1046 break;
1047 }
1048 MI.eraseFromParent();
1049 return true;
1050}
1051
1053 const MachineFunction &MF,
1054 const R600RegisterInfo &TRI) const {
1055 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1056 const R600FrameLowering *TFL = ST.getFrameLowering();
1057
1058 unsigned StackWidth = TFL->getStackWidth(MF);
1059 int End = getIndirectIndexEnd(MF);
1060
1061 if (End == -1)
1062 return;
1063
1064 for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
1065 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1066 unsigned Reg = 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 unsigned 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 unsigned 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 unsigned Ops[] = \
1244 { \
1245 Label##_X, \
1246 Label##_Y, \
1247 Label##_Z, \
1248 Label##_W \
1249 }; \
1250 return Ops[Slot]; \
1251 }
1252
1253static unsigned getSlotedOps(unsigned Op, unsigned Slot) {
1254 switch (Op) {
1255 OPERAND_CASE(R600::OpName::update_exec_mask)
1256 OPERAND_CASE(R600::OpName::update_pred)
1257 OPERAND_CASE(R600::OpName::write)
1258 OPERAND_CASE(R600::OpName::omod)
1259 OPERAND_CASE(R600::OpName::dst_rel)
1260 OPERAND_CASE(R600::OpName::clamp)
1261 OPERAND_CASE(R600::OpName::src0)
1262 OPERAND_CASE(R600::OpName::src0_neg)
1263 OPERAND_CASE(R600::OpName::src0_rel)
1264 OPERAND_CASE(R600::OpName::src0_abs)
1265 OPERAND_CASE(R600::OpName::src0_sel)
1266 OPERAND_CASE(R600::OpName::src1)
1267 OPERAND_CASE(R600::OpName::src1_neg)
1268 OPERAND_CASE(R600::OpName::src1_rel)
1269 OPERAND_CASE(R600::OpName::src1_abs)
1270 OPERAND_CASE(R600::OpName::src1_sel)
1271 OPERAND_CASE(R600::OpName::pred_sel)
1272 default:
1273 llvm_unreachable("Wrong Operand");
1274 }
1275}
1276
1277#undef OPERAND_CASE
1278
1280 MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
1281 const {
1282 assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
1283 unsigned Opcode;
1285 Opcode = R600::DOT4_r600;
1286 else
1287 Opcode = R600::DOT4_eg;
1289 MachineOperand &Src0 = MI->getOperand(
1290 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
1291 MachineOperand &Src1 = MI->getOperand(
1292 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
1294 MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
1295 static const unsigned Operands[14] = {
1296 R600::OpName::update_exec_mask,
1297 R600::OpName::update_pred,
1298 R600::OpName::write,
1299 R600::OpName::omod,
1300 R600::OpName::dst_rel,
1301 R600::OpName::clamp,
1302 R600::OpName::src0_neg,
1303 R600::OpName::src0_rel,
1304 R600::OpName::src0_abs,
1305 R600::OpName::src0_sel,
1306 R600::OpName::src1_neg,
1307 R600::OpName::src1_rel,
1308 R600::OpName::src1_abs,
1309 R600::OpName::src1_sel,
1310 };
1311
1312 MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
1313 getSlotedOps(R600::OpName::pred_sel, Slot)));
1314 MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
1315 .setReg(MO.getReg());
1316
1317 for (unsigned Operand : Operands) {
1318 MachineOperand &MO = MI->getOperand(
1319 getOperandIdx(MI->getOpcode(), getSlotedOps(Operand, Slot)));
1320 assert (MO.isImm());
1321 setImmOperand(*MIB, Operand, MO.getImm());
1322 }
1323 MIB->getOperand(20).setImm(0);
1324 return MIB;
1325}
1326
1329 unsigned DstReg,
1330 uint64_t Imm) const {
1331 MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
1332 R600::ALU_LITERAL_X);
1333 setImmOperand(*MovImm, R600::OpName::literal, Imm);
1334 return MovImm;
1335}
1336
1339 unsigned DstReg, unsigned SrcReg) const {
1340 return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
1341}
1342
1343int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1344 return getOperandIdx(MI.getOpcode(), Op);
1345}
1346
1347int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
1348 return R600::getNamedOperandIdx(Opcode, Op);
1349}
1350
1352 int64_t Imm) const {
1353 int Idx = getOperandIdx(MI, Op);
1354 assert(Idx != -1 && "Operand not supported for this instruction.");
1355 assert(MI.getOperand(Idx).isImm());
1356 MI.getOperand(Idx).setImm(Imm);
1357}
1358
1359//===----------------------------------------------------------------------===//
1360// Instruction flag getters/setters
1361//===----------------------------------------------------------------------===//
1362
1364 unsigned Flag) const {
1365 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1366 int FlagIndex = 0;
1367 if (Flag != 0) {
1368 // If we pass something other than the default value of Flag to this
1369 // function, it means we are want to set a flag on an instruction
1370 // that uses native encoding.
1371 assert(HAS_NATIVE_OPERANDS(TargetFlags));
1372 bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1373 switch (Flag) {
1374 case MO_FLAG_CLAMP:
1375 FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
1376 break;
1377 case MO_FLAG_MASK:
1378 FlagIndex = getOperandIdx(MI, R600::OpName::write);
1379 break;
1380 case MO_FLAG_NOT_LAST:
1381 case MO_FLAG_LAST:
1382 FlagIndex = getOperandIdx(MI, R600::OpName::last);
1383 break;
1384 case MO_FLAG_NEG:
1385 switch (SrcIdx) {
1386 case 0:
1387 FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
1388 break;
1389 case 1:
1390 FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
1391 break;
1392 case 2:
1393 FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
1394 break;
1395 }
1396 break;
1397
1398 case MO_FLAG_ABS:
1399 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1400 "instructions.");
1401 (void)IsOP3;
1402 switch (SrcIdx) {
1403 case 0:
1404 FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
1405 break;
1406 case 1:
1407 FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
1408 break;
1409 }
1410 break;
1411
1412 default:
1413 FlagIndex = -1;
1414 break;
1415 }
1416 assert(FlagIndex != -1 && "Flag not supported for this instruction");
1417 } else {
1418 FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
1419 assert(FlagIndex != 0 &&
1420 "Instruction flags not supported for this instruction");
1421 }
1422
1423 MachineOperand &FlagOp = MI.getOperand(FlagIndex);
1424 assert(FlagOp.isImm());
1425 return FlagOp;
1426}
1427
1429 unsigned Flag) const {
1430 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1431 if (Flag == 0) {
1432 return;
1433 }
1434 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1435 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1436 if (Flag == MO_FLAG_NOT_LAST) {
1437 clearFlag(MI, Operand, MO_FLAG_LAST);
1438 } else if (Flag == MO_FLAG_MASK) {
1439 clearFlag(MI, Operand, Flag);
1440 } else {
1441 FlagOp.setImm(1);
1442 }
1443 } else {
1444 MachineOperand &FlagOp = getFlagOp(MI, Operand);
1445 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1446 }
1447}
1448
1450 unsigned Flag) const {
1451 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1452 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1453 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1454 FlagOp.setImm(0);
1455 } else {
1456 MachineOperand &FlagOp = getFlagOp(MI);
1457 unsigned InstFlags = FlagOp.getImm();
1458 InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
1459 FlagOp.setImm(InstFlags);
1460 }
1461}
unsigned const MachineRegisterInfo * MRI
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
unsigned 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 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 unsigned getSlotedOps(unsigned Op, unsigned Slot)
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
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:191
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:33
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition: DenseMap.h:147
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:277
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()
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
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:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
int64_t getImm() const
MachineBasicBlock * getMBB() const
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
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
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
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+.
void addFlag(MachineInstr &MI, unsigned Operand, unsigned Flag) const
Add one of the MO_FLAG* flags to the specified Operand.
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.
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
bool isVectorOnly(unsigned Opcode) const
bool isExport(unsigned Opcode) const
int getOperandIdx(const MachineInstr &MI, unsigned Op) const
Get the index of Op in the MachineInstr.
SmallVector< std::pair< MachineOperand *, int64_t >, 3 > getSrcs(MachineInstr &MI) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void setImmOperand(MachineInstr &MI, unsigned Op, int64_t Imm) const
Helper function for setting instruction flag values.
MachineInstr * buildMovInstr(MachineBasicBlock *MBB, MachineBasicBlock::iterator I, unsigned DstReg, unsigned SrcReg) const
void clearFlag(MachineInstr &MI, unsigned Operand, unsigned Flag) const
Clear the specified flag on the instruction.
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:132
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:181
size_type size() const
Definition: SmallSet.h:170
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
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.
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:480
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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:860
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