LLVM: lib/Target/AMDGPU/R600InstrInfo.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
20
21using namespace llvm;
22
23#define GET_INSTRINFO_CTOR_DTOR
24#include "R600GenDFAPacketizer.inc"
25
26#define GET_INSTRINFO_CTOR_DTOR
27#define GET_INSTRMAP_INFO
28#define GET_INSTRINFO_NAMED_OPS
29#include "R600GenInstrInfo.inc"
30
33
37
41 Register SrcReg, bool KillSrc,
42 bool RenamableDest, bool RenamableSrc) const {
43 unsigned VectorComponents = 0;
44 if ((R600::R600_Reg128RegClass.contains(DestReg) ||
45 R600::R600_Reg128VerticalRegClass.contains(DestReg)) &&
46 (R600::R600_Reg128RegClass.contains(SrcReg) ||
47 R600::R600_Reg128VerticalRegClass.contains(SrcReg))) {
48 VectorComponents = 4;
49 } else if((R600::R600_Reg64RegClass.contains(DestReg) ||
50 R600::R600_Reg64VerticalRegClass.contains(DestReg)) &&
51 (R600::R600_Reg64RegClass.contains(SrcReg) ||
52 R600::R600_Reg64VerticalRegClass.contains(SrcReg))) {
53 VectorComponents = 2;
54 }
55
56 if (VectorComponents > 0) {
57 for (unsigned I = 0; I < VectorComponents; I++) {
60 RI.getSubReg(DestReg, SubRegIndex),
61 RI.getSubReg(SrcReg, SubRegIndex))
64 }
65 } else {
67 DestReg, SrcReg);
70 }
71}
72
73
77 if (!MO.getReg().isVirtual() && RI.isPhysRegLiveAcrossClauses(MO.getReg()))
78 return false;
79 return true;
80}
81
83 switch(Opcode) {
84 default:
85 return false;
86 case R600::MOV:
87 case R600::MOV_IMM_F32:
88 case R600::MOV_IMM_I32:
89 return true;
90 }
91}
92
96
98 switch(Opcode) {
99 default: return false;
100 case R600::CUBE_r600_pseudo:
101 case R600::CUBE_r600_real:
102 case R600::CUBE_eg_pseudo:
103 case R600::CUBE_eg_real:
104 return true;
105 }
106}
107
109 unsigned TargetFlags = get(Opcode).TSFlags;
110
112}
113
115 unsigned TargetFlags = get(Opcode).TSFlags;
116
120}
121
123 unsigned TargetFlags = get(Opcode).TSFlags;
124
128}
129
133
136 return true;
138 return true;
139 switch (MI.getOpcode()) {
140 case R600::PRED_X:
141 case R600::INTERP_PAIR_XY:
142 case R600::INTERP_PAIR_ZW:
143 case R600::INTERP_VEC_LOAD:
144 case R600::COPY:
145 case R600::DOT_4:
146 return true;
147 default:
148 return false;
149 }
150}
151
153 if (ST.hasCaymanISA())
154 return false;
155 return (get(Opcode).getSchedClass() == R600::Sched::TransALU);
156}
157
161
163 return (get(Opcode).getSchedClass() == R600::Sched::VecALU);
164}
165
169
173
175 return ST.hasVertexCache() && IS_VTX(get(Opcode));
176}
177
183
187
194
196 switch (Opcode) {
197 case R600::KILLGT:
198 case R600::GROUP_BARRIER:
199 return true;
200 default:
201 return false;
202 }
203}
204
206 return MI.findRegisterUseOperandIdx(R600::AR_X, &RI, false) != -1;
207}
208
210 return MI.findRegisterDefOperandIdx(R600::AR_X, &RI, false, false) != -1;
211}
212
215 return false;
216 }
218 if (MO.getReg().isPhysical() &&
219 R600::R600_LDS_SRC_REGRegClass.contains(MO.getReg()))
220 return true;
221 return false;
222}
223
225 static const R600::OpName SrcSelTable[][2] = {
226 {R600::OpName::src0, R600::OpName::src0_sel},
227 {R600::OpName::src1, R600::OpName::src1_sel},
228 {R600::OpName::src2, R600::OpName::src2_sel},
229 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
230 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
231 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
232 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
233 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
234 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
235 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
236 {R600::OpName::src1_W, R600::OpName::src1_sel_W}};
237
238 for (const auto &Row : SrcSelTable) {
239 if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {
241 }
242 }
243 return -1;
244}
245
249
250 if (MI.getOpcode() == R600::DOT_4) {
251 static const R600::OpName OpTable[8][2] = {
252 {R600::OpName::src0_X, R600::OpName::src0_sel_X},
253 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
254 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
255 {R600::OpName::src0_W, R600::OpName::src0_sel_W},
256 {R600::OpName::src1_X, R600::OpName::src1_sel_X},
257 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
258 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
259 {R600::OpName::src1_W, R600::OpName::src1_sel_W},
260 };
261
262 for (const auto &Op : OpTable) {
265 if (Reg == R600::ALU_CONST) {
268 Result.push_back(std::pair(&MO, Sel.getImm()));
269 continue;
270 }
271 }
272 return Result;
273 }
274
275 static const R600::OpName OpTable[3][2] = {
276 {R600::OpName::src0, R600::OpName::src0_sel},
277 {R600::OpName::src1, R600::OpName::src1_sel},
278 {R600::OpName::src2, R600::OpName::src2_sel},
279 };
280
281 for (const auto &Op : OpTable) {
283 if (SrcIdx < 0)
284 break;
287 if (Reg == R600::ALU_CONST) {
289 Result.push_back(std::pair(&MO, Sel.getImm()));
290 continue;
291 }
292 if (Reg == R600::ALU_LITERAL_X) {
294 MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
295 if (Operand.isImm()) {
296 Result.push_back(std::pair(&MO, Operand.getImm()));
297 continue;
298 }
300 }
301 Result.push_back(std::pair(&MO, 0));
302 }
303 return Result;
304}
305
306std::vector<std::pair<int, unsigned>>
309 unsigned &ConstCount) const {
310 ConstCount = 0;
311 const std::pair<int, unsigned> DummyPair(-1, 0);
312 std::vector<std::pair<int, unsigned>> Result;
313 unsigned i = 0;
314 for (const auto &Src : getSrcs(MI)) {
315 ++i;
316 Register Reg = Src.first->getReg();
317 int Index = RI.getEncodingValue(Reg) & 0xff;
318 if (Reg == R600::OQAP) {
319 Result.emplace_back(Index, 0U);
320 }
322
323 Result.emplace_back(255, 0U);
324 continue;
325 }
326 if (Index > 127) {
327 ConstCount++;
328 Result.push_back(DummyPair);
329 continue;
330 }
332 Result.emplace_back(Index, Chan);
333 }
334 for (; i < 3; ++i)
335 Result.push_back(DummyPair);
337}
338
339static std::vector<std::pair<int, unsigned>>
340Swizzle(std::vector<std::pair<int, unsigned>> Src,
342 if (Src[0] == Src[1])
343 Src[1].first = -1;
344 switch (Swz) {
346 break;
349 break;
352 break;
356 break;
360 break;
363 break;
364 }
365 return Src;
366}
367
369 assert(Op < 3 && "Out of range swizzle index");
370 switch (Swz) {
372 unsigned Cycles[3] = { 2, 1, 0};
373 return Cycles[Op];
374 }
376 unsigned Cycles[3] = { 1, 2, 2};
377 return Cycles[Op];
378 }
380 unsigned Cycles[3] = { 2, 1, 2};
381 return Cycles[Op];
382 }
384 unsigned Cycles[3] = { 2, 2, 1};
385 return Cycles[Op];
386 }
387 default:
389 }
390}
391
392
393
394
396 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
397 const std::vectorR600InstrInfo::BankSwizzle &Swz,
398 const std::vector<std::pair<int, unsigned>> &TransSrcs,
402 for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
403 const std::vector<std::pair<int, unsigned>> &Srcs =
404 Swizzle(IGSrcs[i], Swz[i]);
405 for (unsigned j = 0; j < 3; j++) {
406 const std::pair<int, unsigned> &Src = Srcs[j];
407 if (Src.first < 0 || Src.first == 255)
408 continue;
409 if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {
412
413
414 return false;
415 }
416
417 continue;
418 }
419 if (Vector[Src.second][j] < 0)
420 Vector[Src.second][j] = Src.first;
421 if (Vector[Src.second][j] != Src.first)
422 return i;
423 }
424 }
425
426 for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
427 const std::pair<int, unsigned> &Src = TransSrcs[i];
429 if (Src.first < 0)
430 continue;
431 if (Src.first == 255)
432 continue;
435 if (Vector[Src.second][Cycle] != Src.first)
436 return IGSrcs.size() - 1;
437 }
438 return IGSrcs.size();
439}
440
441
442
443
444static bool
446 std::vectorR600InstrInfo::BankSwizzle &SwzCandidate,
447 unsigned Idx) {
448 assert(Idx < SwzCandidate.size());
449 int ResetIdx = Idx;
451 ResetIdx --;
452 for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
454 }
455 if (ResetIdx == -1)
456 return false;
457 int NextSwizzle = SwzCandidate[ResetIdx] + 1;
459 return true;
460}
461
462
463
465 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
466 std::vectorR600InstrInfo::BankSwizzle &SwzCandidate,
467 const std::vector<std::pair<int, unsigned>> &TransSrcs,
469 unsigned ValidUpTo = 0;
470 do {
471 ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
472 if (ValidUpTo == IGSrcs.size())
473 return true;
475 return false;
476}
477
478
479
480static bool
482 const std::vector<std::pair<int, unsigned>> &TransOps,
483 unsigned ConstCount) {
484
485 if (ConstCount > 2)
486 return false;
487 for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
488 const std::pair<int, unsigned> &Src = TransOps[i];
490 if (Src.first < 0)
491 continue;
492 if (ConstCount > 0 && Cycle == 0)
493 return false;
494 if (ConstCount > 1 && Cycle == 1)
495 return false;
496 }
497 return true;
498}
499
500bool
503 std::vector &ValidSwizzle,
504 bool isLastAluTrans)
505 const {
506
507
508 std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
509 ValidSwizzle.clear();
510 unsigned ConstCount;
513 IGSrcs.push_back(ExtractSrcs(*MI, PV, ConstCount));
514 unsigned Op = getOperandIdx(MI->getOpcode(), R600::OpName::bank_swizzle);
515 ValidSwizzle.push_back(
517 }
518 std::vector<std::pair<int, unsigned>> TransOps;
519 if (!isLastAluTrans)
521
522 TransOps = std::move(IGSrcs.back());
523 IGSrcs.pop_back();
524 ValidSwizzle.pop_back();
525
531 };
534 continue;
536 TransBS);
537 if (Result) {
538 ValidSwizzle.push_back(TransBS);
539 return true;
540 }
541 }
542
543 return false;
544}
545
546bool
548 const {
549 assert (Consts.size() <= 12 && "Too many operands in instructions group");
550 unsigned Pair1 = 0, Pair2 = 0;
551 for (unsigned Const : Consts) {
552 unsigned ReadConstHalf = Const & 2;
553 unsigned ReadConstIndex = Const & (~3);
554 unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
555 if (!Pair1) {
556 Pair1 = ReadHalfConst;
557 continue;
558 }
559 if (Pair1 == ReadHalfConst)
560 continue;
561 if (!Pair2) {
562 Pair2 = ReadHalfConst;
563 continue;
564 }
565 if (Pair2 != ReadHalfConst)
566 return false;
567 }
568 return true;
569}
570
571bool
573 const {
574 std::vector Consts;
578 continue;
579
580 for (const auto &Src : getSrcs(*MI)) {
581 if (Src.first->getReg() == R600::ALU_LITERAL_X)
582 Literals.insert(Src.second);
583 if (Literals.size() > 4)
584 return false;
585 if (Src.first->getReg() == R600::ALU_CONST)
586 Consts.push_back(Src.second);
587 if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
588 R600::R600_KC1RegClass.contains(Src.first->getReg())) {
589 unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
590 unsigned Chan = RI.getHWRegChan(Src.first->getReg());
591 Consts.push_back((Index << 2) | Chan);
592 }
593 }
594 }
596}
597
601 return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
602}
603
604static bool
606 switch (Opcode) {
607 case R600::PRED_X:
608 return true;
609 default:
610 return false;
611 }
612}
613
617 while (I != MBB.begin()) {
618 --I;
621 return &MI;
622 }
623
624 return nullptr;
625}
626
627static
629 return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
630}
631
633 return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
634 Opcode == R600::BRANCH_COND_f32;
635}
636
641 bool AllowModify) const {
642
643
644
647 return false;
648
649
650
652 return true;
653 if ((I->getOpcode())) {
654 return false;
655 }
656
657
658 while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
660 if (AllowModify)
661 I->removeFromParent();
662 I = PriorI;
663 }
665
666
667 unsigned LastOpc = LastInst.getOpcode();
669 if (LastOpc == R600::JUMP) {
671 return false;
672 }
673 if (LastOpc == R600::JUMP_COND) {
674 auto predSet = I;
676 predSet = --I;
677 }
679 Cond.push_back(predSet->getOperand(1));
680 Cond.push_back(predSet->getOperand(2));
682 return false;
683 }
684 return true;
685 }
686
687
689 unsigned SecondLastOpc = SecondLastInst.getOpcode();
690
691
692 if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
693 auto predSet = --I;
695 predSet = --I;
696 }
699 Cond.push_back(predSet->getOperand(1));
700 Cond.push_back(predSet->getOperand(2));
702 return false;
703 }
704
705
706 return true;
707}
708
709static
712 It != E; ++It) {
713 if (It->getOpcode() == R600::CF_ALU ||
714 It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
715 return It.getReverse();
716 }
717 return MBB.end();
718}
719
725 int *BytesAdded) const {
726 assert(TBB && "insertBranch must not be told to insert a fallthrough");
727 assert(!BytesAdded && "code size not handled");
728
729 if (!FBB) {
730 if (Cond.empty()) {
732 return 1;
733 }
735 assert(PredSet && "No previous predicate !");
738
743 if (CfAlu == MBB.end())
744 return 1;
745 assert (CfAlu->getOpcode() == R600::CF_ALU);
746 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
747 return 1;
748 }
750 assert(PredSet && "No previous predicate !");
758 if (CfAlu == MBB.end())
759 return 2;
760 assert(CfAlu->getOpcode() == R600::CF_ALU);
761 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
762 return 2;
763}
764
766 int *BytesRemoved) const {
767 assert(!BytesRemoved && "code size not handled");
768
769
770
771
773
775 return 0;
776 }
777 --I;
778 switch (I->getOpcode()) {
779 default:
780 return 0;
781 case R600::JUMP_COND: {
784 I->eraseFromParent();
786 if (CfAlu == MBB.end())
787 break;
788 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
789 CfAlu->setDesc(get(R600::CF_ALU));
790 break;
791 }
792 case R600::JUMP:
793 I->eraseFromParent();
794 break;
795 }
797
799 return 1;
800 }
801 --I;
802 switch (I->getOpcode()) {
803
804 default:
805 return 1;
806 case R600::JUMP_COND: {
809 I->eraseFromParent();
811 if (CfAlu == MBB.end())
812 break;
813 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
814 CfAlu->setDesc(get(R600::CF_ALU));
815 break;
816 }
817 case R600::JUMP:
818 I->eraseFromParent();
819 break;
820 }
821 return 2;
822}
823
825 int idx = MI.findFirstPredOperandIdx();
826 if (idx < 0)
827 return false;
828
829 Register Reg = MI.getOperand(idx).getReg();
830 switch (Reg) {
831 default: return false;
832 case R600::PRED_SEL_ONE:
833 case R600::PRED_SEL_ZERO:
834 case R600::PREDICATE_BIT:
835 return true;
836 }
837}
838
840
841
842
843
844
845 if (MI.getOpcode() == R600::KILLGT)
846 return false;
847 if (MI.getOpcode() == R600::CF_ALU) {
848
849
851 return false;
852
853 return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
854 }
856 return false;
858}
859
860bool
862 unsigned NumCycles,
863 unsigned ExtraPredCycles,
865 return true;
866}
867
868bool
870 unsigned NumTCycles,
871 unsigned ExtraTCycles,
873 unsigned NumFCycles,
874 unsigned ExtraFCycles,
876 return true;
877}
878
879bool
881 unsigned NumCycles,
883 const {
884 return true;
885}
886
887bool
892
893bool
896 switch (MO.getImm()) {
897 case R600::PRED_SETE_INT:
898 MO.setImm(R600::PRED_SETNE_INT);
899 break;
900 case R600::PRED_SETNE_INT:
901 MO.setImm(R600::PRED_SETE_INT);
902 break;
903 case R600::PRED_SETE:
904 MO.setImm(R600::PRED_SETNE);
905 break;
906 case R600::PRED_SETNE:
907 MO.setImm(R600::PRED_SETE);
908 break;
909 default:
910 return true;
911 }
912
914 switch (MO2.getReg()) {
915 case R600::PRED_SEL_ZERO:
916 MO2.setReg(R600::PRED_SEL_ONE);
917 break;
918 case R600::PRED_SEL_ONE:
919 MO2.setReg(R600::PRED_SEL_ZERO);
920 break;
921 default:
922 return true;
923 }
924 return false;
925}
926
928 std::vector &Pred,
929 bool SkipDead) const {
931}
932
935 int PIdx = MI.findFirstPredOperandIdx();
936
937 if (MI.getOpcode() == R600::CF_ALU) {
938 MI.getOperand(8).setImm(0);
939 return true;
940 }
941
942 if (MI.getOpcode() == R600::DOT_4) {
944 .setReg(Pred[2].getReg());
946 .setReg(Pred[2].getReg());
948 .setReg(Pred[2].getReg());
950 .setReg(Pred[2].getReg());
953 return true;
954 }
955
956 if (PIdx != -1) {
961 return true;
962 }
963
964 return false;
965}
966
970
973 unsigned *PredCost) const {
974 if (PredCost)
975 *PredCost = 2;
976 return 2;
977}
978
980 unsigned Channel) const {
981 assert(Channel == 0);
982 return RegIndex;
983}
984
986 switch (MI.getOpcode()) {
987 default: {
989 int OffsetOpIdx =
990 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
991
992
993 int RegOpIdx = OffsetOpIdx + 1;
994 int ChanOpIdx =
995 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
997 int DstOpIdx =
998 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
999 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1000 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1002 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1003 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1006 } else {
1007 buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
1008 OffsetReg);
1009 }
1011 int ValOpIdx =
1012 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
1013 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1014 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1016 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1017 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1019 MI.getOperand(ValOpIdx).getReg());
1020 } else {
1021 buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
1023 OffsetReg);
1024 }
1025 } else {
1026 return false;
1027 }
1028
1030 return true;
1031 }
1032 case R600::R600_EXTRACT_ELT_V2:
1033 case R600::R600_EXTRACT_ELT_V4:
1034 buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
1035 RI.getHWRegIndex(MI.getOperand(1).getReg()),
1036 MI.getOperand(2).getReg(),
1037 RI.getHWRegChan(MI.getOperand(1).getReg()));
1038 break;
1039 case R600::R600_INSERT_ELT_V2:
1040 case R600::R600_INSERT_ELT_V4:
1041 buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(),
1042 RI.getHWRegIndex(MI.getOperand(1).getReg()),
1043 MI.getOperand(3).getReg(),
1044 RI.getHWRegChan(MI.getOperand(1).getReg()));
1045 break;
1046 }
1047 MI.eraseFromParent();
1048 return true;
1049}
1050
1056
1059
1060 if (End == -1)
1061 return;
1062
1064 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1066 R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
1067 TRI.reserveRegisterTuples(Reserved, Reg);
1068 }
1069 }
1070}
1071
1073 return &R600::R600_TReg32_XRegClass;
1074}
1075
1078 unsigned ValueReg, unsigned Address,
1079 unsigned OffsetReg) const {
1080 return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
1081}
1082
1085 unsigned ValueReg, unsigned Address,
1086 unsigned OffsetReg,
1087 unsigned AddrChan) const {
1089 switch (AddrChan) {
1091 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1092 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1093 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1094 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1095 }
1097 R600::AR_X, OffsetReg);
1099
1101 AddrReg, ValueReg)
1105 return Mov;
1106}
1107
1110 unsigned ValueReg, unsigned Address,
1111 unsigned OffsetReg) const {
1112 return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
1113}
1114
1117 unsigned ValueReg, unsigned Address,
1118 unsigned OffsetReg,
1119 unsigned AddrChan) const {
1121 switch (AddrChan) {
1123 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1124 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1125 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1126 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1127 }
1129 R600::AR_X,
1130 OffsetReg);
1133 ValueReg,
1134 AddrReg)
1138
1139 return Mov;
1140}
1141
1146
1148 return -1;
1149 }
1150
1151 if (MRI.livein_empty()) {
1152 return 0;
1153 }
1154
1156 for (std::pair<MCRegister, Register> LI : MRI.liveins()) {
1158 if (Reg.isVirtual() || !IndirectRC->contains(Reg))
1159 continue;
1160
1161 unsigned RegIndex;
1162 unsigned RegEnd;
1163 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
1164 ++RegIndex) {
1165 if (IndirectRC->getRegister(RegIndex) == (unsigned)Reg)
1166 break;
1167 }
1169 }
1170
1172}
1173
1177
1178
1180 return -1;
1181 }
1182
1184 return -1;
1185 }
1186
1189
1191 Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg).getFixed();
1192
1194}
1195
1199
1240
1241#define OPERAND_CASE(Label) \
1242 case Label: { \
1243 static const R600::OpName Ops[] = {Label##_X, Label##_Y, Label##_Z, \
1244 Label##_W}; \
1245 return Ops[Slot]; \
1246 }
1247
1249 switch (Op) {
1250 OPERAND_CASE(R600::OpName::update_exec_mask)
1267 default:
1269 }
1270}
1271
1272#undef OPERAND_CASE
1273
1276 const {
1277 assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
1278 unsigned Opcode;
1280 Opcode = R600::DOT4_r600;
1281 else
1282 Opcode = R600::DOT4_eg;
1290 static const R600::OpName Operands[14] = {
1291 R600::OpName::update_exec_mask,
1292 R600::OpName::update_pred,
1293 R600::OpName::write,
1294 R600::OpName::omod,
1295 R600::OpName::dst_rel,
1296 R600::OpName::clamp,
1297 R600::OpName::src0_neg,
1298 R600::OpName::src0_rel,
1299 R600::OpName::src0_abs,
1300 R600::OpName::src0_sel,
1301 R600::OpName::src1_neg,
1302 R600::OpName::src1_rel,
1303 R600::OpName::src1_abs,
1304 R600::OpName::src1_sel,
1305 };
1306
1308 getSlotedOps(R600::OpName::pred_sel, Slot)));
1311
1312 for (R600::OpName Operand : Operands) {
1317 }
1319 return MIB;
1320}
1321
1324 unsigned DstReg,
1327 R600::ALU_LITERAL_X);
1328 setImmOperand(*MovImm, R600::OpName::literal, Imm);
1329 return MovImm;
1330}
1331
1334 unsigned DstReg, unsigned SrcReg) const {
1336}
1337
1339 R600::OpName Op) const {
1341}
1342
1344 return R600::getNamedOperandIdx(Opcode, Op);
1345}
1346
1348 int64_t Imm) const {
1350 assert(Idx != -1 && "Operand not supported for this instruction.");
1351 assert(MI.getOperand(Idx).isImm());
1352 MI.getOperand(Idx).setImm(Imm);
1353}
1354
1355
1356
1357
1358
1360 unsigned Flag) const {
1361 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1362 int FlagIndex = 0;
1363 if (Flag != 0) {
1364
1365
1366
1369 switch (Flag) {
1372 break;
1375 break;
1379 break;
1381 switch (SrcIdx) {
1382 case 0:
1384 break;
1385 case 1:
1387 break;
1388 case 2:
1390 break;
1391 }
1392 break;
1393
1395 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1396 "instructions.");
1397 (void)IsOP3;
1398 switch (SrcIdx) {
1399 case 0:
1401 break;
1402 case 1:
1404 break;
1405 }
1406 break;
1407
1408 default:
1409 FlagIndex = -1;
1410 break;
1411 }
1412 assert(FlagIndex != -1 && "Flag not supported for this instruction");
1413 } else {
1415 assert(FlagIndex != 0 &&
1416 "Instruction flags not supported for this instruction");
1417 }
1418
1421 return FlagOp;
1422}
1423
1425 unsigned Flag) const {
1426 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1427 if (Flag == 0) {
1428 return;
1429 }
1436 } else {
1438 }
1439 } else {
1442 }
1443}
1444
1446 unsigned Flag) const {
1447 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1451 } else {
1453 unsigned InstFlags = FlagOp.getImm();
1454 InstFlags &= ~(Flag << (NUM_MO_FLAGS * SrcIdx));
1455 FlagOp.setImm(InstFlags);
1456 }
1457}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Register const TargetRegisterInfo * TRI
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
uint64_t IntrinsicInst * II
#define GET_REG_INDEX(reg)
#define HAS_NATIVE_OPERANDS(Flags)
#define GET_FLAG_OPERAND_IDX(Flags)
Helper for getting the operand index for the instruction flags operand.
static MachineInstr * findFirstPredicateSetterFrom(MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Definition R600InstrInfo.cpp:615
static R600::OpName getSlotedOps(R600::OpName Op, unsigned Slot)
Definition R600InstrInfo.cpp:1248
static bool isBranch(unsigned Opcode)
Definition R600InstrInfo.cpp:632
static MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB)
Definition R600InstrInfo.cpp:710
#define OPERAND_CASE(Label)
Definition R600InstrInfo.cpp:1241
static std::vector< std::pair< int, unsigned > > Swizzle(std::vector< std::pair< int, unsigned > > Src, R600InstrInfo::BankSwizzle Swz)
Definition R600InstrInfo.cpp:340
static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op)
Definition R600InstrInfo.cpp:368
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 ...
Definition R600InstrInfo.cpp:481
static bool isPredicateSetter(unsigned Opcode)
Definition R600InstrInfo.cpp:605
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...
Definition R600InstrInfo.cpp:445
static bool isJump(unsigned Opcode)
Definition R600InstrInfo.cpp:628
Interface definition for R600InstrInfo.
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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.
unsigned getStackWidth(const MachineFunction &MF) const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Itinerary data supplied by a subtarget to be used by a target.
Wrapper class representing physical registers. Should be passed by value.
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 & 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
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)
MachineBasicBlock * getMBB() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool usesVertexCache(unsigned Opcode) const
Definition R600InstrInfo.cpp:174
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...
Definition R600InstrInfo.cpp:1200
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Definition R600InstrInfo.cpp:894
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Definition R600InstrInfo.cpp:637
void addFlag(MachineInstr &MI, unsigned SrcIdx, unsigned Flag) const
Add one of the MO_FLAG* flags to the operand at SrcIdx.
Definition R600InstrInfo.cpp:1424
bool usesAddressRegister(MachineInstr &MI) const
Definition R600InstrInfo.cpp:205
unsigned calculateIndirectAddress(unsigned RegIndex, unsigned Channel) const
Calculate the "Indirect Address" for the given RegIndex and Channel.
Definition R600InstrInfo.cpp:979
bool hasInstrModifiers(unsigned Opcode) const
Definition R600InstrInfo.cpp:114
R600InstrInfo(const R600Subtarget &)
Definition R600InstrInfo.cpp:31
bool isMov(unsigned Opcode) const
Definition R600InstrInfo.cpp:82
bool isRegisterLoad(const MachineInstr &MI) const
int getIndirectIndexBegin(const MachineFunction &MF) const
Definition R600InstrInfo.cpp:1142
bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, BranchProbability Probability) const override
Definition R600InstrInfo.cpp:880
bool usesTextureCache(unsigned Opcode) const
Definition R600InstrInfo.cpp:184
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...
Definition R600InstrInfo.cpp:395
unsigned int getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr &MI, unsigned *PredCost=nullptr) const override
Definition R600InstrInfo.cpp:971
const TargetRegisterClass * getIndirectAddrRegClass() const
Definition R600InstrInfo.cpp:1072
void clearFlag(MachineInstr &MI, unsigned SrcIdx, unsigned Flag) const
Clear the specified flag on the instruction.
Definition R600InstrInfo.cpp:1445
MachineInstr * buildMovImm(MachineBasicBlock &BB, MachineBasicBlock::iterator I, unsigned DstReg, uint64_t Imm) const
Definition R600InstrInfo.cpp:1322
bool definesAddressRegister(MachineInstr &MI) const
Definition R600InstrInfo.cpp:209
unsigned getMaxAlusPerClause() const
Definition R600InstrInfo.cpp:1196
bool PredicateInstruction(MachineInstr &MI, ArrayRef< MachineOperand > Pred) const override
Definition R600InstrInfo.cpp:933
int getOperandIdx(const MachineInstr &MI, R600::OpName Op) const
Get the index of Op in the MachineInstr.
Definition R600InstrInfo.cpp:1338
bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const override
Definition R600InstrInfo.cpp:74
bool canBeConsideredALU(const MachineInstr &MI) const
Definition R600InstrInfo.cpp:134
bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, MachineBasicBlock &FMBB) const override
Definition R600InstrInfo.cpp:888
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+.
Definition R600InstrInfo.cpp:572
bool isVector(const MachineInstr &MI) const
Vector instructions are instructions that must fill all instruction slots within an instruction group...
Definition R600InstrInfo.cpp:34
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
Definition R600InstrInfo.cpp:765
bool mustBeLastInClause(unsigned Opcode) const
Definition R600InstrInfo.cpp:195
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
Definition R600InstrInfo.cpp:720
int getIndirectIndexEnd(const MachineFunction &MF) const
Definition R600InstrInfo.cpp:1174
bool isTransOnly(unsigned Opcode) const
Definition R600InstrInfo.cpp:152
DFAPacketizer * CreateTargetScheduleState(const TargetSubtargetInfo &) const override
Definition R600InstrInfo.cpp:599
bool isReductionOp(unsigned opcode) const
Definition R600InstrInfo.cpp:93
bool isRegisterStore(const MachineInstr &MI) const
bool isCubeOp(unsigned opcode) const
Definition R600InstrInfo.cpp:97
bool isLDSInstr(unsigned Opcode) const
Definition R600InstrInfo.cpp:122
void reserveIndirectRegisters(BitVector &Reserved, const MachineFunction &MF, const R600RegisterInfo &TRI) const
Reserve the registers that may be accessed using indirect addressing.
Definition R600InstrInfo.cpp:1051
void setImmOperand(MachineInstr &MI, R600::OpName Op, int64_t Imm) const
Helper function for setting instruction flag values.
Definition R600InstrInfo.cpp:1347
bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override
Definition R600InstrInfo.cpp:861
bool isPredicable(const MachineInstr &MI) const override
Definition R600InstrInfo.cpp:839
bool isPredicated(const MachineInstr &MI) const override
Definition R600InstrInfo.cpp:824
bool expandPostRAPseudo(MachineInstr &MI) const override
Definition R600InstrInfo.cpp:985
bool isLDSRetInstr(unsigned Opcode) const
Definition R600InstrInfo.cpp:130
int getSelIdx(unsigned Opcode, unsigned SrcIdx) const
Definition R600InstrInfo.cpp:224
MachineOperand & getFlagOp(MachineInstr &MI, unsigned SrcIdx=0, unsigned Flag=0) const
Definition R600InstrInfo.cpp:1359
unsigned int getPredicationCost(const MachineInstr &) const override
Definition R600InstrInfo.cpp:967
MachineInstr * buildSlotOfVectorInstruction(MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg) const
Definition R600InstrInfo.cpp:1274
bool readsLDSSrcReg(const MachineInstr &MI) const
Definition R600InstrInfo.cpp:213
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.
Definition R600InstrInfo.cpp:464
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 ...
Definition R600InstrInfo.cpp:501
bool ClobbersPredicate(MachineInstr &MI, std::vector< MachineOperand > &Pred, bool SkipDead) const override
Definition R600InstrInfo.cpp:927
bool isALUInstr(unsigned Opcode) const
Definition R600InstrInfo.cpp:108
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
Definition R600InstrInfo.cpp:38
bool isVectorOnly(unsigned Opcode) const
Definition R600InstrInfo.cpp:162
bool isExport(unsigned Opcode) const
Definition R600InstrInfo.cpp:170
SmallVector< std::pair< MachineOperand *, int64_t >, 3 > getSrcs(MachineInstr &MI) const
Definition R600InstrInfo.cpp:247
MachineInstr * buildMovInstr(MachineBasicBlock *MBB, MachineBasicBlock::iterator I, unsigned DstReg, unsigned SrcReg) const
Definition R600InstrInfo.cpp:1332
Wrapper class representing virtual and physical registers.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
unsigned getNumRegs() const
Return the number of registers in this class.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
MCRegister getRegister(unsigned i) const
Return the specified register in the class.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const InstrItineraryData * getInstrItineraryData() const
getInstrItineraryData - Returns instruction itinerary data for the target or specific subtarget.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
DWARFExpression::Operation Op
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
unsigned getHWRegChan(unsigned reg) const
get the HW encoding for a register's channel.
static unsigned getSubRegFromChannel(unsigned Channel)