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