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