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.push_back(std::pair(Index, 0U));
330 }
331 if (PV.contains(Reg)) {
332 // 255 is used to tells its a PS/PV reg
333 Result.push_back(std::pair(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.push_back(std::pair(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 } else if (LastOpc == R600::JUMP_COND) {
683 auto predSet = I;
684 while (!isPredicateSetter(predSet->getOpcode())) {
685 predSet = --I;
686 }
687 TBB = LastInst.getOperand(0).getMBB();
688 Cond.push_back(predSet->getOperand(1));
689 Cond.push_back(predSet->getOperand(2));
690 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
691 return false;
692 }
693 return true; // Can't handle indirect branch.
694 }
695
696 // Get the instruction before it if it is a terminator.
697 MachineInstr &SecondLastInst = *I;
698 unsigned SecondLastOpc = SecondLastInst.getOpcode();
699
700 // If the block ends with a B and a Bcc, handle it.
701 if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
702 auto predSet = --I;
703 while (!isPredicateSetter(predSet->getOpcode())) {
704 predSet = --I;
705 }
706 TBB = SecondLastInst.getOperand(0).getMBB();
707 FBB = LastInst.getOperand(0).getMBB();
708 Cond.push_back(predSet->getOperand(1));
709 Cond.push_back(predSet->getOperand(2));
710 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
711 return false;
712 }
713
714 // Otherwise, can't handle this.
715 return true;
716}
717
718static
721 It != E; ++It) {
722 if (It->getOpcode() == R600::CF_ALU ||
723 It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
724 return It.getReverse();
725 }
726 return MBB.end();
727}
728
733 const DebugLoc &DL,
734 int *BytesAdded) const {
735 assert(TBB && "insertBranch must not be told to insert a fallthrough");
736 assert(!BytesAdded && "code size not handled");
737
738 if (!FBB) {
739 if (Cond.empty()) {
740 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
741 return 1;
742 } else {
744 assert(PredSet && "No previous predicate !");
745 addFlag(*PredSet, 0, MO_FLAG_PUSH);
746 PredSet->getOperand(2).setImm(Cond[1].getImm());
747
748 BuildMI(&MBB, DL, get(R600::JUMP_COND))
749 .addMBB(TBB)
750 .addReg(R600::PREDICATE_BIT, RegState::Kill);
752 if (CfAlu == MBB.end())
753 return 1;
754 assert (CfAlu->getOpcode() == R600::CF_ALU);
755 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
756 return 1;
757 }
758 } else {
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}
775
777 int *BytesRemoved) const {
778 assert(!BytesRemoved && "code size not handled");
779
780 // Note : we leave PRED* instructions there.
781 // They may be needed when predicating instructions.
782
784
785 if (I == MBB.begin()) {
786 return 0;
787 }
788 --I;
789 switch (I->getOpcode()) {
790 default:
791 return 0;
792 case R600::JUMP_COND: {
794 clearFlag(*predSet, 0, MO_FLAG_PUSH);
795 I->eraseFromParent();
797 if (CfAlu == MBB.end())
798 break;
799 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
800 CfAlu->setDesc(get(R600::CF_ALU));
801 break;
802 }
803 case R600::JUMP:
804 I->eraseFromParent();
805 break;
806 }
807 I = MBB.end();
808
809 if (I == MBB.begin()) {
810 return 1;
811 }
812 --I;
813 switch (I->getOpcode()) {
814 // FIXME: only one case??
815 default:
816 return 1;
817 case R600::JUMP_COND: {
819 clearFlag(*predSet, 0, MO_FLAG_PUSH);
820 I->eraseFromParent();
822 if (CfAlu == MBB.end())
823 break;
824 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
825 CfAlu->setDesc(get(R600::CF_ALU));
826 break;
827 }
828 case R600::JUMP:
829 I->eraseFromParent();
830 break;
831 }
832 return 2;
833}
834
836 int idx = MI.findFirstPredOperandIdx();
837 if (idx < 0)
838 return false;
839
840 Register Reg = MI.getOperand(idx).getReg();
841 switch (Reg) {
842 default: return false;
843 case R600::PRED_SEL_ONE:
844 case R600::PRED_SEL_ZERO:
845 case R600::PREDICATE_BIT:
846 return true;
847 }
848}
849
851 // XXX: KILL* instructions can be predicated, but they must be the last
852 // instruction in a clause, so this means any instructions after them cannot
853 // be predicated. Until we have proper support for instruction clauses in the
854 // backend, we will mark KILL* instructions as unpredicable.
855
856 if (MI.getOpcode() == R600::KILLGT) {
857 return false;
858 } else if (MI.getOpcode() == R600::CF_ALU) {
859 // If the clause start in the middle of MBB then the MBB has more
860 // than a single clause, unable to predicate several clauses.
861 if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
862 return false;
863 // TODO: We don't support KC merging atm
864 return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
865 } else if (isVector(MI)) {
866 return false;
867 } else {
869 }
870}
871
872bool
874 unsigned NumCycles,
875 unsigned ExtraPredCycles,
876 BranchProbability Probability) const{
877 return true;
878}
879
880bool
882 unsigned NumTCycles,
883 unsigned ExtraTCycles,
884 MachineBasicBlock &FMBB,
885 unsigned NumFCycles,
886 unsigned ExtraFCycles,
887 BranchProbability Probability) const {
888 return true;
889}
890
891bool
893 unsigned NumCycles,
894 BranchProbability Probability)
895 const {
896 return true;
897}
898
899bool
901 MachineBasicBlock &FMBB) const {
902 return false;
903}
904
905bool
907 MachineOperand &MO = Cond[1];
908 switch (MO.getImm()) {
909 case R600::PRED_SETE_INT:
910 MO.setImm(R600::PRED_SETNE_INT);
911 break;
912 case R600::PRED_SETNE_INT:
913 MO.setImm(R600::PRED_SETE_INT);
914 break;
915 case R600::PRED_SETE:
916 MO.setImm(R600::PRED_SETNE);
917 break;
918 case R600::PRED_SETNE:
919 MO.setImm(R600::PRED_SETE);
920 break;
921 default:
922 return true;
923 }
924
925 MachineOperand &MO2 = Cond[2];
926 switch (MO2.getReg()) {
927 case R600::PRED_SEL_ZERO:
928 MO2.setReg(R600::PRED_SEL_ONE);
929 break;
930 case R600::PRED_SEL_ONE:
931 MO2.setReg(R600::PRED_SEL_ZERO);
932 break;
933 default:
934 return true;
935 }
936 return false;
937}
938
940 std::vector<MachineOperand> &Pred,
941 bool SkipDead) const {
942 return isPredicateSetter(MI.getOpcode());
943}
944
946 ArrayRef<MachineOperand> Pred) const {
947 int PIdx = MI.findFirstPredOperandIdx();
948
949 if (MI.getOpcode() == R600::CF_ALU) {
950 MI.getOperand(8).setImm(0);
951 return true;
952 }
953
954 if (MI.getOpcode() == R600::DOT_4) {
955 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
956 .setReg(Pred[2].getReg());
957 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
958 .setReg(Pred[2].getReg());
959 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
960 .setReg(Pred[2].getReg());
961 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
962 .setReg(Pred[2].getReg());
963 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
964 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
965 return true;
966 }
967
968 if (PIdx != -1) {
969 MachineOperand &PMO = MI.getOperand(PIdx);
970 PMO.setReg(Pred[2].getReg());
971 MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
972 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
973 return true;
974 }
975
976 return false;
977}
978
980 return 2;
981}
982
984 const MachineInstr &,
985 unsigned *PredCost) const {
986 if (PredCost)
987 *PredCost = 2;
988 return 2;
989}
990
992 unsigned Channel) const {
993 assert(Channel == 0);
994 return RegIndex;
995}
996
998 switch (MI.getOpcode()) {
999 default: {
1000 MachineBasicBlock *MBB = MI.getParent();
1001 int OffsetOpIdx =
1002 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
1003 // addr is a custom operand with multiple MI operands, and only the
1004 // first MI operand is given a name.
1005 int RegOpIdx = OffsetOpIdx + 1;
1006 int ChanOpIdx =
1007 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
1008 if (isRegisterLoad(MI)) {
1009 int DstOpIdx =
1010 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
1011 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1012 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1013 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1014 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1015 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1016 buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
1017 getIndirectAddrRegClass()->getRegister(Address));
1018 } else {
1019 buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
1020 OffsetReg);
1021 }
1022 } else if (isRegisterStore(MI)) {
1023 int ValOpIdx =
1024 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
1025 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1026 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1027 unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1028 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1029 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1031 MI.getOperand(ValOpIdx).getReg());
1032 } else {
1033 buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
1034 calculateIndirectAddress(RegIndex, Channel),
1035 OffsetReg);
1036 }
1037 } else {
1038 return false;
1039 }
1040
1041 MBB->erase(MI);
1042 return true;
1043 }
1044 case R600::R600_EXTRACT_ELT_V2:
1045 case R600::R600_EXTRACT_ELT_V4:
1046 buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
1047 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1048 MI.getOperand(2).getReg(),
1049 RI.getHWRegChan(MI.getOperand(1).getReg()));
1050 break;
1051 case R600::R600_INSERT_ELT_V2:
1052 case R600::R600_INSERT_ELT_V4:
1053 buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
1054 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address
1055 MI.getOperand(3).getReg(), // Offset
1056 RI.getHWRegChan(MI.getOperand(1).getReg())); // Channel
1057 break;
1058 }
1059 MI.eraseFromParent();
1060 return true;
1061}
1062
1064 const MachineFunction &MF,
1065 const R600RegisterInfo &TRI) const {
1066 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1067 const R600FrameLowering *TFL = ST.getFrameLowering();
1068
1069 unsigned StackWidth = TFL->getStackWidth(MF);
1070 int End = getIndirectIndexEnd(MF);
1071
1072 if (End == -1)
1073 return;
1074
1075 for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
1076 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1077 unsigned Reg = R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
1078 TRI.reserveRegisterTuples(Reserved, Reg);
1079 }
1080 }
1081}
1082
1084 return &R600::R600_TReg32_XRegClass;
1085}
1086
1087MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1089 unsigned ValueReg, unsigned Address,
1090 unsigned OffsetReg) const {
1091 return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
1092}
1093
1094MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1096 unsigned ValueReg, unsigned Address,
1097 unsigned OffsetReg,
1098 unsigned AddrChan) const {
1099 unsigned AddrReg;
1100 switch (AddrChan) {
1101 default: llvm_unreachable("Invalid Channel");
1102 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1103 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1104 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1105 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1106 }
1107 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1108 R600::AR_X, OffsetReg);
1109 setImmOperand(*MOVA, R600::OpName::write, 0);
1110
1112 AddrReg, ValueReg)
1113 .addReg(R600::AR_X,
1115 setImmOperand(*Mov, R600::OpName::dst_rel, 1);
1116 return Mov;
1117}
1118
1119MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1121 unsigned ValueReg, unsigned Address,
1122 unsigned OffsetReg) const {
1123 return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
1124}
1125
1126MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1128 unsigned ValueReg, unsigned Address,
1129 unsigned OffsetReg,
1130 unsigned AddrChan) const {
1131 unsigned AddrReg;
1132 switch (AddrChan) {
1133 default: llvm_unreachable("Invalid Channel");
1134 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1135 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1136 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1137 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1138 }
1139 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1140 R600::AR_X,
1141 OffsetReg);
1142 setImmOperand(*MOVA, R600::OpName::write, 0);
1144 ValueReg,
1145 AddrReg)
1146 .addReg(R600::AR_X,
1148 setImmOperand(*Mov, R600::OpName::src0_rel, 1);
1149
1150 return Mov;
1151}
1152
1154 const MachineRegisterInfo &MRI = MF.getRegInfo();
1155 const MachineFrameInfo &MFI = MF.getFrameInfo();
1156 int Offset = -1;
1157
1158 if (MFI.getNumObjects() == 0) {
1159 return -1;
1160 }
1161
1162 if (MRI.livein_empty()) {
1163 return 0;
1164 }
1165
1166 const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
1167 for (std::pair<unsigned, unsigned> LI : MRI.liveins()) {
1168 Register Reg = LI.first;
1169 if (Reg.isVirtual() || !IndirectRC->contains(Reg))
1170 continue;
1171
1172 unsigned RegIndex;
1173 unsigned RegEnd;
1174 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
1175 ++RegIndex) {
1176 if (IndirectRC->getRegister(RegIndex) == (unsigned)Reg)
1177 break;
1178 }
1179 Offset = std::max(Offset, (int)RegIndex);
1180 }
1181
1182 return Offset + 1;
1183}
1184
1186 int Offset = 0;
1187 const MachineFrameInfo &MFI = MF.getFrameInfo();
1188
1189 // Variable sized objects are not supported
1190 if (MFI.hasVarSizedObjects()) {
1191 return -1;
1192 }
1193
1194 if (MFI.getNumObjects() == 0) {
1195 return -1;
1196 }
1197
1198 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1199 const R600FrameLowering *TFL = ST.getFrameLowering();
1200
1201 Register IgnoredFrameReg;
1202 Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg).getFixed();
1203
1204 return getIndirectIndexBegin(MF) + Offset;
1205}
1206
1208 return 115;
1209}
1210
1213 unsigned Opcode,
1214 unsigned DstReg,
1215 unsigned Src0Reg,
1216 unsigned Src1Reg) const {
1218 DstReg); // $dst
1219
1220 if (Src1Reg) {
1221 MIB.addImm(0) // $update_exec_mask
1222 .addImm(0); // $update_predicate
1223 }
1224 MIB.addImm(1) // $write
1225 .addImm(0) // $omod
1226 .addImm(0) // $dst_rel
1227 .addImm(0) // $dst_clamp
1228 .addReg(Src0Reg) // $src0
1229 .addImm(0) // $src0_neg
1230 .addImm(0) // $src0_rel
1231 .addImm(0) // $src0_abs
1232 .addImm(-1); // $src0_sel
1233
1234 if (Src1Reg) {
1235 MIB.addReg(Src1Reg) // $src1
1236 .addImm(0) // $src1_neg
1237 .addImm(0) // $src1_rel
1238 .addImm(0) // $src1_abs
1239 .addImm(-1); // $src1_sel
1240 }
1241
1242 //XXX: The r600g finalizer expects this to be 1, once we've moved the
1243 //scheduling to the backend, we can change the default to 0.
1244 MIB.addImm(1) // $last
1245 .addReg(R600::PRED_SEL_OFF) // $pred_sel
1246 .addImm(0) // $literal
1247 .addImm(0); // $bank_swizzle
1248
1249 return MIB;
1250}
1251
1252#define OPERAND_CASE(Label) \
1253 case Label: { \
1254 static const unsigned Ops[] = \
1255 { \
1256 Label##_X, \
1257 Label##_Y, \
1258 Label##_Z, \
1259 Label##_W \
1260 }; \
1261 return Ops[Slot]; \
1262 }
1263
1264static unsigned getSlotedOps(unsigned Op, unsigned Slot) {
1265 switch (Op) {
1266 OPERAND_CASE(R600::OpName::update_exec_mask)
1267 OPERAND_CASE(R600::OpName::update_pred)
1268 OPERAND_CASE(R600::OpName::write)
1269 OPERAND_CASE(R600::OpName::omod)
1270 OPERAND_CASE(R600::OpName::dst_rel)
1271 OPERAND_CASE(R600::OpName::clamp)
1272 OPERAND_CASE(R600::OpName::src0)
1273 OPERAND_CASE(R600::OpName::src0_neg)
1274 OPERAND_CASE(R600::OpName::src0_rel)
1275 OPERAND_CASE(R600::OpName::src0_abs)
1276 OPERAND_CASE(R600::OpName::src0_sel)
1277 OPERAND_CASE(R600::OpName::src1)
1278 OPERAND_CASE(R600::OpName::src1_neg)
1279 OPERAND_CASE(R600::OpName::src1_rel)
1280 OPERAND_CASE(R600::OpName::src1_abs)
1281 OPERAND_CASE(R600::OpName::src1_sel)
1282 OPERAND_CASE(R600::OpName::pred_sel)
1283 default:
1284 llvm_unreachable("Wrong Operand");
1285 }
1286}
1287
1288#undef OPERAND_CASE
1289
1291 MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
1292 const {
1293 assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
1294 unsigned Opcode;
1296 Opcode = R600::DOT4_r600;
1297 else
1298 Opcode = R600::DOT4_eg;
1300 MachineOperand &Src0 = MI->getOperand(
1301 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
1302 MachineOperand &Src1 = MI->getOperand(
1303 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
1305 MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
1306 static const unsigned Operands[14] = {
1307 R600::OpName::update_exec_mask,
1308 R600::OpName::update_pred,
1309 R600::OpName::write,
1310 R600::OpName::omod,
1311 R600::OpName::dst_rel,
1312 R600::OpName::clamp,
1313 R600::OpName::src0_neg,
1314 R600::OpName::src0_rel,
1315 R600::OpName::src0_abs,
1316 R600::OpName::src0_sel,
1317 R600::OpName::src1_neg,
1318 R600::OpName::src1_rel,
1319 R600::OpName::src1_abs,
1320 R600::OpName::src1_sel,
1321 };
1322
1323 MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
1324 getSlotedOps(R600::OpName::pred_sel, Slot)));
1325 MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
1326 .setReg(MO.getReg());
1327
1328 for (unsigned Operand : Operands) {
1329 MachineOperand &MO = MI->getOperand(
1330 getOperandIdx(MI->getOpcode(), getSlotedOps(Operand, Slot)));
1331 assert (MO.isImm());
1332 setImmOperand(*MIB, Operand, MO.getImm());
1333 }
1334 MIB->getOperand(20).setImm(0);
1335 return MIB;
1336}
1337
1340 unsigned DstReg,
1341 uint64_t Imm) const {
1342 MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
1343 R600::ALU_LITERAL_X);
1344 setImmOperand(*MovImm, R600::OpName::literal, Imm);
1345 return MovImm;
1346}
1347
1350 unsigned DstReg, unsigned SrcReg) const {
1351 return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
1352}
1353
1354int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1355 return getOperandIdx(MI.getOpcode(), Op);
1356}
1357
1358int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
1359 return R600::getNamedOperandIdx(Opcode, Op);
1360}
1361
1363 int64_t Imm) const {
1364 int Idx = getOperandIdx(MI, Op);
1365 assert(Idx != -1 && "Operand not supported for this instruction.");
1366 assert(MI.getOperand(Idx).isImm());
1367 MI.getOperand(Idx).setImm(Imm);
1368}
1369
1370//===----------------------------------------------------------------------===//
1371// Instruction flag getters/setters
1372//===----------------------------------------------------------------------===//
1373
1375 unsigned Flag) const {
1376 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1377 int FlagIndex = 0;
1378 if (Flag != 0) {
1379 // If we pass something other than the default value of Flag to this
1380 // function, it means we are want to set a flag on an instruction
1381 // that uses native encoding.
1382 assert(HAS_NATIVE_OPERANDS(TargetFlags));
1383 bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1384 switch (Flag) {
1385 case MO_FLAG_CLAMP:
1386 FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
1387 break;
1388 case MO_FLAG_MASK:
1389 FlagIndex = getOperandIdx(MI, R600::OpName::write);
1390 break;
1391 case MO_FLAG_NOT_LAST:
1392 case MO_FLAG_LAST:
1393 FlagIndex = getOperandIdx(MI, R600::OpName::last);
1394 break;
1395 case MO_FLAG_NEG:
1396 switch (SrcIdx) {
1397 case 0:
1398 FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
1399 break;
1400 case 1:
1401 FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
1402 break;
1403 case 2:
1404 FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
1405 break;
1406 }
1407 break;
1408
1409 case MO_FLAG_ABS:
1410 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1411 "instructions.");
1412 (void)IsOP3;
1413 switch (SrcIdx) {
1414 case 0:
1415 FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
1416 break;
1417 case 1:
1418 FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
1419 break;
1420 }
1421 break;
1422
1423 default:
1424 FlagIndex = -1;
1425 break;
1426 }
1427 assert(FlagIndex != -1 && "Flag not supported for this instruction");
1428 } else {
1429 FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
1430 assert(FlagIndex != 0 &&
1431 "Instruction flags not supported for this instruction");
1432 }
1433
1434 MachineOperand &FlagOp = MI.getOperand(FlagIndex);
1435 assert(FlagOp.isImm());
1436 return FlagOp;
1437}
1438
1440 unsigned Flag) const {
1441 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1442 if (Flag == 0) {
1443 return;
1444 }
1445 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1446 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1447 if (Flag == MO_FLAG_NOT_LAST) {
1448 clearFlag(MI, Operand, MO_FLAG_LAST);
1449 } else if (Flag == MO_FLAG_MASK) {
1450 clearFlag(MI, Operand, Flag);
1451 } else {
1452 FlagOp.setImm(1);
1453 }
1454 } else {
1455 MachineOperand &FlagOp = getFlagOp(MI, Operand);
1456 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1457 }
1458}
1459
1461 unsigned Flag) const {
1462 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1463 if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1464 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1465 FlagOp.setImm(0);
1466 } else {
1467 MachineOperand &FlagOp = getFlagOp(MI);
1468 unsigned InstFlags = FlagOp.getImm();
1469 InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
1470 FlagOp.setImm(InstFlags);
1471 }
1472}
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:264
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:566
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:576
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:456
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