28#include "llvm/IR/IntrinsicsAMDGPU.h"
30#define DEBUG_TYPE "amdgpu-reg-bank-legalize"
40 ST(MF.getSubtarget<
GCNSubtarget>()), TII(*ST.getInstrInfo()), B(B),
41 MRI(*B.getMRI()), MUI(MUI), VT(VT), RBI(RBI), MORE(MF, nullptr),
42 RBLRules(RBLRules), IsWave32(ST.isWave32()),
43 SgprRB(&RBI.getRegBank(
AMDGPU::SGPRRegBankID)),
44 VgprRB(&RBI.getRegBank(
AMDGPU::VGPRRegBankID)),
45 AgprRB(&RBI.getRegBank(
AMDGPU::AGPRRegBankID)),
46 VccRB(&RBI.getRegBank(
AMDGPU::VCCRegBankID)) {}
52 "No AMDGPU RegBankLegalize rules defined for opcode",
60 "AMDGPU RegBankLegalize: none of the rules defined with "
61 "'Any' for MI's opcode matched MI",
69 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
79 if (!lower(
MI, *Mapping, WFI))
83 if (!executeInWaterfallLoop(B, WFI))
93 "Waterfall range not initialized");
110 const int OrigRangeSize = std::distance(BeginIt, EndIt);
119 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(InitSaveExecReg);
145 MBB.addSuccessor(LoopBB);
148 B.setInsertPt(*LoopBB, LoopBB->
end());
199 auto NewEnd = BodyBB->
end();
200 assert(std::distance(NewBegin, NewEnd) == OrigRangeSize);
213 auto OldVal = WaterfalledRegMap.
find(OldReg);
214 if (OldVal != WaterfalledRegMap.
end()) {
215 Op.setReg(OldVal->second);
228 unsigned OpSize =
OpTy.getSizeInBits();
229 unsigned PartSize = (OpSize % 64 == 0) ? 64 : 32;
231 unsigned NumParts = OpSize / PartSize;
237 CurrentLaneParts.
push_back(CurrentLaneReg);
239 auto UnmergeOp = B.buildUnmerge({VgprRB, PartTy}, OpReg);
240 auto UnmergeCurrLane = B.buildUnmerge({SgprRB, PartTy}, CurrentLaneReg);
241 for (
unsigned i = 0; i < NumParts; ++i) {
243 CurrentLaneParts.
push_back(UnmergeCurrLane.getReg(i));
247 for (
unsigned i = 0; i < NumParts; ++i) {
248 Register CmpReg = MRI.createVirtualRegister(VccRB_S1);
254 CondReg = B.buildAnd(VccRB_S1, CondReg, CmpReg).getReg(0);
257 Op.setReg(CurrentLaneReg);
260 WaterfalledRegMap.
insert(std::pair(OldReg,
Op.getReg()));
266 MRI.createVirtualRegister({WaveRC,
LLT::integer(IsWave32 ? 32 : 64)});
267 B.buildIntrinsic(Intrinsic::amdgcn_ballot, CondRegLM).addReg(CondReg);
274 MRI.setSimpleHint(SavedExec, CondRegLM);
276 B.setInsertPt(*BodyBB, BodyBB->
end());
289 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
293 B.buildInstr(LMC.
MovOpc).addDef(SaveExecReg).addReg(LMC.
ExecReg);
296 B.setInsertPt(*RestoreExecBB, RestoreExecBB->
begin());
301 B.setInsertPt(*RemainderBB, RemainderBB->
begin());
308unsigned RegBankLegalizeHelper::setBufferOffsets(
310 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) {
311 if (std::optional<int64_t>
Imm =
313 uint32_t SOffset, ImmOffset;
314 if (TII.splitMUBUFOffset(*
Imm, SOffset, ImmOffset, Alignment)) {
315 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
316 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
317 InstOffsetVal = ImmOffset;
318 return SOffset + ImmOffset;
321 const bool CheckNUW = ST.hasGFX1250Insts();
323 MRI, CombinedOffset,
nullptr,
325 uint32_t SOffset, ImmOffset;
326 if (
static_cast<int32_t
>(
Offset) > 0 &&
327 TII.splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
328 if (
Base.isValid() && MRI.getRegBank(
Base) == VgprRB) {
330 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
331 InstOffsetVal = ImmOffset;
336 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
338 InstOffsetVal = ImmOffset;
344 if (
Add &&
static_cast<int32_t
>(
Offset) >= 0 &&
348 const RegisterBank *Src0Bank = MRI.getRegBank(Src0);
349 const RegisterBank *Src1Bank = MRI.getRegBank(Src1);
350 if (Src0Bank == VgprRB && Src1Bank == SgprRB) {
355 if (Src0Bank == SgprRB && Src1Bank == VgprRB) {
363 if (MRI.getRegBank(CombinedOffset) == VgprRB) {
364 VOffsetReg = CombinedOffset;
366 VOffsetReg = B.buildCopy(VgprRB_I32, CombinedOffset).getReg(0);
368 SOffsetReg = B.buildConstant(SgprRB_I32, 0).getReg(0);
372bool RegBankLegalizeHelper::splitLoad(MachineInstr &
MI,
375 assert(
MI.getNumMemOperands() == 1);
376 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
378 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
380 LLT PtrTy = MRI.getType(
Base);
381 const RegisterBank *PtrRB = MRI.getRegBankOrNull(
Base);
385 unsigned ByteOffset = 0;
386 for (LLT PartTy : LLTBreakdown) {
388 if (ByteOffset == 0) {
389 BasePlusOffset =
Base;
391 auto Offset = B.buildConstant({PtrRB, OffsetTy}, ByteOffset);
395 auto *OffsetMMO = MF.getMachineMemOperand(&BaseMMO, ByteOffset, PartTy);
396 auto LoadPart = B.buildLoad({DstRB, PartTy}, BasePlusOffset, *OffsetMMO);
397 LoadPartRegs.
push_back(LoadPart.getReg(0));
403 B.buildMergeLikeInstr(Dst, LoadPartRegs);
409 if (MRI.getType(
Reg) == MergeTy) {
412 auto Unmerge = B.buildUnmerge({DstRB, MergeTy},
Reg);
413 for (
unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i)
414 MergeTyParts.
push_back(Unmerge.getReg(i));
417 B.buildMergeLikeInstr(Dst, MergeTyParts);
419 MI.eraseFromParent();
423bool RegBankLegalizeHelper::widenLoad(MachineInstr &
MI, LLT WideTy,
426 assert(
MI.getNumMemOperands() == 1);
427 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
429 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
432 MachineMemOperand *WideMMO = MF.getMachineMemOperand(&BaseMMO, 0, WideTy);
433 auto WideLoad = B.buildLoad({DstRB, WideTy},
Base, *WideMMO);
436 B.buildTrunc(Dst, WideLoad);
439 auto Unmerge = B.buildUnmerge({DstRB, MergeTy}, WideLoad);
441 LLT DstTy = MRI.getType(Dst);
443 for (
unsigned i = 0; i < NumElts; ++i) {
444 MergeTyParts.
push_back(Unmerge.getReg(i));
446 B.buildMergeLikeInstr(Dst, MergeTyParts);
448 MI.eraseFromParent();
452bool RegBankLegalizeHelper::widenMMOToS32(GAnyLoad &
MI)
const {
455 MachineMemOperand &MMO =
MI.getMMO();
458 MachineMemOperand *WideMMO = B.getMF().getMachineMemOperand(&MMO, 0, S32);
460 if (
MI.getOpcode() == G_LOAD) {
461 B.buildLoad(Dst, Ptr, *WideMMO);
463 auto Load = B.buildLoad(SgprRB_I32, Ptr, *WideMMO);
465 if (
MI.getOpcode() == G_ZEXTLOAD) {
467 auto MaskCst = B.buildConstant(SgprRB_I32, Mask);
468 B.buildAnd(Dst,
Load, MaskCst);
470 assert(
MI.getOpcode() == G_SEXTLOAD);
471 B.buildSExtInReg(Dst,
Load, MemSize);
475 MI.eraseFromParent();
479bool RegBankLegalizeHelper::lowerVccExtToSel(MachineInstr &
MI) {
481 LLT Ty = MRI.getType(Dst);
483 unsigned Opc =
MI.getOpcode();
484 int TrueExtCst =
Opc == G_SEXT ? -1 : 1;
485 if (Ty == S32 || Ty == S16) {
486 auto True = B.buildConstant({VgprRB, Ty}, TrueExtCst);
487 auto False = B.buildConstant({VgprRB, Ty}, 0);
488 B.buildSelect(Dst, Src, True, False);
489 }
else if (Ty == S64) {
490 auto True = B.buildConstant({VgprRB_I32}, TrueExtCst);
491 auto False = B.buildConstant({VgprRB_I32}, 0);
492 auto Lo = B.buildSelect({VgprRB_I32}, Src, True, False);
493 MachineInstrBuilder
Hi;
502 Hi = B.buildUndef({VgprRB_I32});
507 "AMDGPU RegBankLegalize: lowerVccExtToSel, Opcode not supported",
MI);
511 B.buildMergeValues(Dst, {
Lo.getReg(0),
Hi.getReg(0)});
515 "AMDGPU RegBankLegalize: lowerVccExtToSel, Type not supported",
MI);
519 MI.eraseFromParent();
523std::pair<Register, Register> RegBankLegalizeHelper::unpackZExt(
Register Reg) {
524 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
525 auto Mask = B.buildConstant(SgprRB_I32, 0x0000ffff);
526 auto Lo = B.buildAnd(SgprRB_I32, PackedI32, Mask);
527 auto Hi = B.buildLShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
528 return {
Lo.getReg(0),
Hi.getReg(0)};
531std::pair<Register, Register> RegBankLegalizeHelper::unpackSExt(
Register Reg) {
532 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
533 auto Lo = B.buildSExtInReg(SgprRB_I32, PackedI32, 16);
534 auto Hi = B.buildAShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
535 return {
Lo.getReg(0),
Hi.getReg(0)};
538std::pair<Register, Register> RegBankLegalizeHelper::unpackAExt(
Register Reg) {
540 if (MRI.getType(
Reg) != I32)
541 RegI32 = B.buildBitcast(SgprRB_I32,
Reg).getReg(0);
543 auto Hi = B.buildLShr(SgprRB_I32, RegI32, B.buildConstant(SgprRB_I32, 16));
544 return {RegI32,
Hi.getReg(0)};
547std::pair<Register, Register>
548RegBankLegalizeHelper::unpackAExtTruncS16(
Register Reg) {
549 auto [Lo32, Hi32] = unpackAExt(
Reg);
550 LLT EltTy = MRI.getType(
Reg).getElementType();
551 return {B.buildTrunc({SgprRB, EltTy}, Lo32).
getReg(0),
552 B.buildTrunc({SgprRB, EltTy}, Hi32).
getReg(0)};
555bool RegBankLegalizeHelper::lowerUnpackBitShift(MachineInstr &
MI) {
557 switch (
MI.getOpcode()) {
558 case AMDGPU::G_SHL: {
559 auto [Val0, Val1] = unpackAExt(
MI.getOperand(1).getReg());
560 auto [Amt0, Amt1] = unpackAExt(
MI.getOperand(2).getReg());
561 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
562 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
565 case AMDGPU::G_LSHR: {
566 auto [Val0, Val1] = unpackZExt(
MI.getOperand(1).getReg());
567 auto [Amt0, Amt1] = unpackZExt(
MI.getOperand(2).getReg());
568 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
569 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
572 case AMDGPU::G_ASHR: {
573 auto [Val0, Val1] = unpackSExt(
MI.getOperand(1).getReg());
574 auto [Amt0, Amt1] = unpackSExt(
MI.getOperand(2).getReg());
575 Lo = B.buildAShr(SgprRB_I32, Val0, Amt0).getReg(0);
576 Hi = B.buildAShr(SgprRB_I32, Val1, Amt1).getReg(0);
582 "AMDGPU RegBankLegalize: lowerUnpackBitShift, case not implemented",
586 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
587 MI.eraseFromParent();
591bool RegBankLegalizeHelper::lowerUnpackMinMax(MachineInstr &
MI) {
593 switch (
MI.getOpcode()) {
595 case AMDGPU::G_SMAX: {
597 auto [Val0_Lo, Val0_Hi] = unpackSExt(
MI.getOperand(1).getReg());
598 auto [Val1_Lo, Val1_Hi] = unpackSExt(
MI.getOperand(2).getReg());
599 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
601 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
606 case AMDGPU::G_UMAX: {
608 auto [Val0_Lo, Val0_Hi] = unpackZExt(
MI.getOperand(1).getReg());
609 auto [Val1_Lo, Val1_Hi] = unpackZExt(
MI.getOperand(2).getReg());
610 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
612 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
619 "AMDGPU RegBankLegalize: lowerUnpackMinMax, case not implemented",
MI);
622 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
623 MI.eraseFromParent();
627bool RegBankLegalizeHelper::lowerUnpackAExt(MachineInstr &
MI) {
628 auto [Op1Lo, Op1Hi] = unpackAExt(
MI.getOperand(1).getReg());
629 auto [Op2Lo, Op2Hi] = unpackAExt(
MI.getOperand(2).getReg());
630 auto ResLo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Lo, Op2Lo});
631 auto ResHi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Hi, Op2Hi});
632 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
633 {ResLo.getReg(0), ResHi.getReg(0)});
634 MI.eraseFromParent();
638bool RegBankLegalizeHelper::lowerSBufToBuf(MachineInstr &
MI,
641 LLT Ty = MRI.getType(Dst);
642 const RegisterBank *RSrcBank = MRI.getRegBank(
MI.getOperand(1).getReg());
646 if (LoadSize == 256 || LoadSize == 512) {
647 NumLoads = LoadSize / 128;
650 for (
int I = 0;
I < NumLoads; ++
I)
651 LoadParts.
emplace_back(MRI.createVirtualRegister({VgprRB, Ty}));
652 MachineMemOperand *OrigMMO = *
MI.memoperands_begin();
657 int64_t ImmOffset = 0;
658 unsigned MMOOffset = setBufferOffsets(B,
MI.getOperand(2).getReg(), VOffset,
659 SOffset, ImmOffset, Alignment);
661 MachineMemOperand *BaseMMO = MF.getMachineMemOperand(OrigMMO, 0, MemSize);
663 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
667 Register VIndex = B.buildConstant(VgprRB_I32, 0).getReg(0);
668 unsigned CachePolicy =
MI.getOperand(3).getImm();
669 unsigned Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
670 switch (
MI.getOpcode()) {
671 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
672 Opc = G_AMDGPU_BUFFER_LOAD_SBYTE;
674 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
675 Opc = G_AMDGPU_BUFFER_LOAD_UBYTE;
677 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
678 Opc = G_AMDGPU_BUFFER_LOAD_SSHORT;
680 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
681 Opc = G_AMDGPU_BUFFER_LOAD_USHORT;
686 for (
int I = 0;
I < NumLoads; ++
I) {
688 .addDef(LoadParts[
I])
693 .addImm(ImmOffset + 16 *
I)
696 .addMemOperand(MF.getMachineMemOperand(BaseMMO, 16 *
I, MemSize));
699 B.buildCopy(Dst, LoadParts[0]);
701 B.buildMergeLikeInstr(Dst, LoadParts);
702 B.setInstr(*MRI.getVRegDef(LoadParts[0]));
703 if (RSrcBank != SgprRB) {
705 WFI.
Start = MRI.getVRegDef(LoadParts.
front());
706 WFI.
End = std::next(MRI.getVRegDef(LoadParts.
back())->getIterator());
708 MI.eraseFromParent();
714 return (GI->is(Intrinsic::amdgcn_sbfe));
716 return MI.getOpcode() == AMDGPU::G_SBFX;
719bool RegBankLegalizeHelper::lowerV_BFE(MachineInstr &
MI) {
726 Register Src =
MI.getOperand(FirstOpnd).getReg();
727 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
728 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
733 unsigned SHROpc =
Signed ? AMDGPU::G_ASHR : AMDGPU::G_LSHR;
734 auto SHRSrc = B.buildInstr(SHROpc, {VgprRB_I64}, {Src, LSBit});
742 auto Amt = B.buildSub(VgprRB_I32, B.buildConstant(SgprRB_I32, 64), Width);
743 auto SignBit = B.buildShl(VgprRB_I64, SHRSrc, Amt);
744 B.buildInstr(SHROpc, {Dst}, {SignBit, Amt});
745 MI.eraseFromParent();
749 uint64_t WidthImm = ConstWidth->Value.getZExtValue();
750 auto UnmergeSHRSrc = B.buildUnmerge(VgprRB_I32, SHRSrc);
751 Register SHRSrcLo = UnmergeSHRSrc.getReg(0);
752 Register SHRSrcHi = UnmergeSHRSrc.getReg(1);
753 auto Zero = B.buildConstant(VgprRB_I32, 0);
754 unsigned BFXOpc =
Signed ? AMDGPU::G_SBFX : AMDGPU::G_UBFX;
756 if (WidthImm <= 32) {
762 B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcLo,
Zero, Width}).
getReg(0);
764 MachineInstrBuilder
Hi;
767 Hi = B.buildAShr(VgprRB_I32,
Lo, B.buildConstant(VgprRB_I32, 31));
772 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
774 auto Amt = B.buildConstant(VgprRB_I32, WidthImm - 32);
776 auto Hi = B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcHi,
Zero, Amt});
777 B.buildMergeLikeInstr(Dst, {SHRSrcLo,
Hi});
780 MI.eraseFromParent();
784bool RegBankLegalizeHelper::lowerS_BFE(MachineInstr &
MI) {
786 LLT Ty = MRI.getType(DstReg);
789 Register Src =
MI.getOperand(FirstOpnd).getReg();
790 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
791 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
798 auto FieldOffset = B.buildAnd(SgprRB_I32, LSBit, Mask);
799 auto Size = B.buildShl(SgprRB_I32, Width, B.buildConstant(SgprRB_I32, 16));
800 auto Src1 = B.buildOr(SgprRB_I32, FieldOffset,
Size);
801 unsigned Opc32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
802 unsigned Opc64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
803 unsigned Opc = Ty == S32 ? Opc32 : Opc64;
807 auto S_BFE = B.buildInstr(
Opc, {{SgprRB, Ty}},
808 {B.buildCopy(Ty, Src), B.buildCopy(I32, Src1)});
810 *ST.getRegisterInfo(), RBI);
812 B.buildCopy(DstReg,
S_BFE->getOperand(0).getReg());
813 MI.eraseFromParent();
817bool RegBankLegalizeHelper::lowerSplitTo32(MachineInstr &
MI) {
819 LLT DstTy = MRI.getType(Dst);
820 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64);
822 auto Op1 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(1).
getReg());
823 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
824 unsigned Opc =
MI.getOpcode();
827 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(0), Op2.getReg(0)},
Flags);
829 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(1), Op2.getReg(1)},
Flags);
830 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
831 MI.eraseFromParent();
835bool RegBankLegalizeHelper::lowerSplitTo32Mul(MachineInstr &
MI) {
837 assert(MRI.getType(Dst) == S64);
838 auto Op1 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(1).
getReg());
839 auto Op2 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(2).
getReg());
843 auto Lo = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
844 auto Carry = B.buildUMulH(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
845 auto MulLo0Hi1 = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(1));
846 auto MulHi0Lo1 = B.buildMul(VgprRB_I32, Op1.getReg(1), Op2.getReg(0));
847 auto Sum = B.buildAdd(VgprRB_I32, MulLo0Hi1, MulHi0Lo1);
848 auto Hi = B.buildAdd(VgprRB_I32, Sum, Carry);
850 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
851 MI.eraseFromParent();
855bool RegBankLegalizeHelper::lowerSplitTo16(MachineInstr &
MI) {
857 assert(MRI.getType(Dst) == V2S16);
858 unsigned Opc =
MI.getOpcode();
859 unsigned NumOps =
MI.getNumOperands();
862 auto [Op1Lo, Op1Hi] = unpackAExtTruncS16(
MI.getOperand(1).getReg());
866 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo},
Flags);
867 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi},
Flags);
868 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
869 MI.eraseFromParent();
873 auto [Op2Lo, Op2Hi] = unpackAExtTruncS16(
MI.getOperand(2).getReg());
876 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo},
Flags);
877 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi},
Flags);
878 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
879 MI.eraseFromParent();
884 auto [Op3Lo, Op3Hi] = unpackAExtTruncS16(
MI.getOperand(3).getReg());
885 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo, Op3Lo},
Flags);
886 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi, Op3Hi},
Flags);
887 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
888 MI.eraseFromParent();
892bool RegBankLegalizeHelper::lowerUniMAD64(MachineInstr &
MI) {
899 const GCNSubtarget &ST = B.getMF().getSubtarget<GCNSubtarget>();
902 Register DstLo = B.buildMul(SgprRB_I32, Src0, Src1).getReg(0);
903 Register DstHi = MRI.createVirtualRegister(SgprRB_I32);
904 if (ST.hasScalarMulHiInsts()) {
905 B.buildInstr(AMDGPU::G_UMULH, {{DstHi}}, {Src0, Src1});
907 auto VSrc0 = B.buildCopy(VgprRB_I32, Src0);
908 auto VSrc1 = B.buildCopy(VgprRB_I32, Src1);
909 auto MulHi = B.buildInstr(AMDGPU::G_UMULH, {VgprRB_I32}, {VSrc0, VSrc1});
920 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
921 B.buildConstant(Dst1, 0);
924 Register Src2Lo = MRI.createVirtualRegister(SgprRB_I32);
925 Register Src2Hi = MRI.createVirtualRegister(SgprRB_I32);
926 B.buildUnmerge({Src2Lo, Src2Hi}, Src2);
928 auto AddLo = B.buildUAddo(SgprRB_I32, SgprRB_I32, DstLo, Src2Lo);
930 B.buildUAdde(SgprRB_I32, SgprRB_I32, DstHi, Src2Hi, AddLo.getReg(1));
931 B.buildMergeLikeInstr(Dst0, {AddLo.getReg(0), AddHi.getReg(0)});
932 B.buildCopy(Dst1, AddHi.getReg(1));
935 MI.eraseFromParent();
939bool RegBankLegalizeHelper::lowerSplitTo32Select(MachineInstr &
MI) {
941 LLT DstTy = MRI.getType(Dst);
942 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64 ||
945 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
946 auto Op3 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(3).
getReg());
951 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(0), Op3.getReg(0), Flags);
953 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(1), Op3.getReg(1), Flags);
955 B.buildMergeLikeInstr(Dst, {Lo, Hi});
956 MI.eraseFromParent();
960bool RegBankLegalizeHelper::lowerSplitTo32SExtInReg(MachineInstr &
MI) {
961 auto Op1 = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
962 int Amt =
MI.getOperand(2).getImm();
966 auto Freeze = B.buildFreeze(VgprRB_I32, Op1.getReg(0));
969 Lo = Freeze.getReg(0);
972 Lo = B.buildSExtInReg(VgprRB_I32, Freeze, Amt).getReg(0);
975 auto SignExtCst = B.buildConstant(SgprRB_I32, 31);
976 Hi = B.buildAShr(VgprRB_I32,
Lo, SignExtCst).getReg(0);
980 Hi = B.buildSExtInReg(VgprRB_I32, Op1.getReg(1), Amt - 32).getReg(0);
983 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(), {Lo, Hi});
984 MI.eraseFromParent();
988bool RegBankLegalizeHelper::lowerSplitBitCount64To32(MachineInstr &
MI) {
994 unsigned Opc =
MI.getOpcode();
1003 case AMDGPU::G_AMDGPU_FFBH_U32:
1005 AddOpc = AMDGPU::G_UADDSAT;
1006 SearchFromMSB =
true;
1008 case AMDGPU::G_AMDGPU_FFBL_B32:
1010 AddOpc = AMDGPU::G_UADDSAT;
1011 SearchFromMSB =
false;
1013 case AMDGPU::G_CTLZ_ZERO_POISON:
1014 FFBOpc = AMDGPU::G_AMDGPU_FFBH_U32;
1015 AddOpc = AMDGPU::G_ADD;
1016 SearchFromMSB =
true;
1018 case AMDGPU::G_CTTZ_ZERO_POISON:
1019 FFBOpc = AMDGPU::G_AMDGPU_FFBL_B32;
1020 AddOpc = AMDGPU::G_ADD;
1021 SearchFromMSB =
false;
1027 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1034 auto Primary = B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Hi :
Lo});
1036 B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Lo :
Hi});
1038 auto Adjusted = B.buildInstr(AddOpc, {VgprRB_I32},
1039 {Secondary, B.buildConstant(VgprRB_I32, 32)});
1040 B.buildUMin(
MI.getOperand(0).getReg(), Primary, Adjusted);
1042 MI.eraseFromParent();
1046bool RegBankLegalizeHelper::lowerExtrVecEltToSel(MachineInstr &
MI) {
1058 LLT VecTy = MRI.getType(Src);
1061 MachineRegisterInfo::VRegAttrs VgprRB_EltTy = {VgprRB, ScalarTy};
1063 auto Unmerge = B.buildUnmerge(VgprRB_EltTy, Src);
1066 Register PrevSelect = Unmerge.getReg(0);
1067 for (
unsigned I = 1;
I < NumElts; ++
I) {
1068 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1071 B.buildSelect(VgprRB_EltTy, Cmp, Unmerge.getReg(
I), PrevSelect)
1074 B.buildCopy(Dst, PrevSelect);
1076 auto InitUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(0));
1077 Register PrevLo = InitUnmerge.getReg(0);
1078 Register PrevHi = InitUnmerge.getReg(1);
1079 for (
unsigned I = 1;
I < NumElts; ++
I) {
1080 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1082 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(
I));
1083 PrevLo = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(0), PrevLo)
1085 PrevHi = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(1), PrevHi)
1088 B.buildMergeLikeInstr(Dst, {PrevLo, PrevHi});
1092 "AMDGPU RegBankLegalize: ExtrVecEltToSel unsupported element type",
MI);
1096 MI.eraseFromParent();
1100bool RegBankLegalizeHelper::lowerExtrVecEltTo32(MachineInstr &
MI) {
1113 LLT SrcTy = MRI.getType(Src);
1116 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1117 "expected VGPR src and SGPR idx");
1119 auto CastSrc = B.buildBitcast({VgprRB, Vec32Ty}, Src);
1122 auto One = B.buildConstant(SgprRB_I32, 1);
1123 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1124 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1126 auto ExtLo = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxLo);
1127 auto ExtHi = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxHi);
1129 B.buildMergeLikeInstr(Dst, {ExtLo.getReg(0), ExtHi.getReg(0)});
1131 MI.eraseFromParent();
1135bool RegBankLegalizeHelper::lowerInsVecEltToSel(MachineInstr &
MI) {
1148 LLT VecTy = MRI.getType(Src);
1151 const RegisterBank *SrcRB = MRI.getRegBank(Src);
1152 bool IsSGPR = (SrcRB == SgprRB);
1153 SmallVector<Register, 16> Selects;
1157 auto Unmerge = B.buildUnmerge(VgprRB_I32, Src);
1158 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1159 Register EltLo = EltUnmerge.getReg(0);
1160 Register EltHi = EltUnmerge.getReg(1);
1161 for (
unsigned I = 0;
I < NumElts; ++
I) {
1162 auto IdxConst = B.buildConstant(VgprRB_I32,
I);
1165 B.buildSelect(VgprRB_I32, Cmp, EltLo, Unmerge.getReg(2 *
I))
1168 B.buildSelect(VgprRB_I32, Cmp, EltHi, Unmerge.getReg(2 *
I + 1))
1172 auto Vec32 = B.buildBuildVector({VgprRB, Vec32Ty}, Selects);
1173 B.buildBitcast(Dst, Vec32);
1176 MachineRegisterInfo::VRegAttrs SrcRB_EltTy = {SrcRB, ScalarTy};
1177 MachineRegisterInfo::VRegAttrs CmpTy = IsSGPR ? SgprRB_I32 : VccRB_S1;
1178 auto Unmerge = B.buildUnmerge(SrcRB_EltTy, Src);
1179 for (
unsigned I = 0;
I < NumElts; ++
I) {
1180 auto IdxConst = B.buildConstant(SgprRB_I32,
I);
1183 B.buildSelect(SrcRB_EltTy, Cmp, Elt, Unmerge.getReg(
I)).getReg(0));
1185 B.buildMergeLikeInstr(Dst, Selects);
1189 "AMDGPU RegBankLegalize: InsVecEltToSel unsupported element type",
MI);
1193 MI.eraseFromParent();
1197bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &
MI) {
1212 LLT SrcTy = MRI.getType(Src);
1215 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1216 "expected VGPR src and SGPR idx");
1218 MachineRegisterInfo::VRegAttrs VgprRB_Vec32Ty = {VgprRB, Vec32Ty};
1220 auto CastSrc = B.buildBitcast(VgprRB_Vec32Ty, Src);
1221 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1224 auto One = B.buildConstant(SgprRB_I32, 1);
1225 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1226 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1228 auto InsLo = B.buildInsertVectorElement(VgprRB_Vec32Ty, CastSrc,
1229 EltUnmerge.getReg(0), IdxLo);
1230 auto InsHi = B.buildInsertVectorElement(VgprRB_Vec32Ty, InsLo,
1231 EltUnmerge.getReg(1), IdxHi);
1233 B.buildBitcast(Dst, InsHi);
1235 MI.eraseFromParent();
1239bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &
MI) {
1249 LLT Ty = MRI.getType(DstReg);
1255 Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).
getReg(0);
1257 assert((Ty == S32 || Ty == S16) &&
"unexpected type for AbsToNegMax");
1258 Zero = B.buildConstant({VgprRB, Ty}, 0).
getReg(0);
1261 auto Neg = B.buildSub({VgprRB, Ty},
Zero, SrcReg);
1262 B.buildSMax(DstReg, SrcReg, Neg);
1263 MI.eraseFromParent();
1267bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &
MI) {
1277 auto Bitcast = B.buildBitcast({SgprRB_I32},
MI.getOperand(1).
getReg());
1278 auto SextInReg = B.buildSExtInReg({SgprRB_I32},
Bitcast, 16);
1280 B.buildAShr({SgprRB_I32},
Bitcast, B.buildConstant({SgprRB_I32}, 16));
1282 auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {SextInReg});
1283 auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {ShiftHi});
1284 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
1285 {AbsLo.getReg(0), AbsHi.getReg(0)});
1287 MI.eraseFromParent();
1293bool RegBankLegalizeHelper::lowerSetRounding(MachineInstr &
MI) {
1294 Register NewMode =
MI.getOperand(0).getReg();
1299 uint32_t ClampedVal = std::min(
1300 static_cast<uint32_t
>(ConstMode->Value.getZExtValue()),
1303 NewMode = B.buildConstant(SgprRB_I32, DecodedVal).getReg(0);
1307 KnownBits
Known = VT->getKnownBits(NewMode);
1308 const bool UseReducedTable =
Known.countMinLeadingZeros() >= 30;
1312 if (UseReducedTable) {
1314 auto BitTable = B.buildConstant(
1317 auto Two = B.buildConstant(SgprRB_I32, 2);
1318 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, NewMode, Two);
1321 B.buildLShr(SgprRB_I32, BitTable, RoundModeTimesNumBits).getReg(0);
1328 auto NegFour = B.buildConstant(SgprRB_I32, -4);
1329 auto OffsetEnum = B.buildAdd(SgprRB_I32, NewMode, NegFour);
1330 auto IndexVal = B.buildUMin(SgprRB_I32, NewMode, OffsetEnum);
1332 auto Two = B.buildConstant(SgprRB_I32, 2);
1333 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, IndexVal, Two);
1338 B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1341 NewMode = B.buildTrunc(SgprRB_I32, TableValue).getReg(0);
1347 uint32_t BothRoundHwReg =
1351 .addImm(
static_cast<int16_t
>(BothRoundHwReg))
1354 MI.eraseFromParent();
1360bool RegBankLegalizeHelper::lowerGetRounding(MachineInstr &
MI) {
1363 uint32_t BothRoundHwReg =
1366 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {SgprRB_I32},
1368 .addImm(BothRoundHwReg);
1399 auto Two = B.buildConstant(SgprRB_I32, 2);
1400 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, GetReg, Two);
1404 auto TableValue = B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1405 auto TruncTable = B.buildTrunc(SgprRB_I32, TableValue);
1407 auto EntryMask = B.buildConstant(SgprRB_I32, 0xf);
1408 auto TableEntry = B.buildAnd(SgprRB_I32, TruncTable, EntryMask);
1412 auto Four = B.buildConstant(SgprRB_I32, 4);
1413 auto EnumOffset = B.buildAdd(SgprRB_I32, TableEntry, Four);
1414 auto IsStandardMode =
1416 B.buildSelect(Dst, IsStandardMode, TableEntry, EnumOffset);
1418 MI.eraseFromParent();
1422bool RegBankLegalizeHelper::lower(MachineInstr &
MI,
1430 return lowerVccExtToSel(
MI);
1432 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1433 auto True = B.buildConstant({SgprRB, Ty},
1434 MI.getOpcode() == AMDGPU::G_SEXT ? -1 : 1);
1435 auto False = B.buildConstant({SgprRB, Ty}, 0);
1439 B.buildSelect(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg(), True,
1441 MI.eraseFromParent();
1445 return lowerUnpackBitShift(
MI);
1447 return lowerUnpackMinMax(
MI);
1449 return lowerSplitTo16(
MI);
1451 const RegisterBank *RB = MRI.getRegBank(
MI.getOperand(0).getReg());
1452 MachineInstrBuilder
Hi;
1453 switch (
MI.getOpcode()) {
1454 case AMDGPU::G_ZEXT: {
1455 Hi = B.buildConstant({RB, I32}, 0);
1458 case AMDGPU::G_SEXT: {
1460 auto ShiftAmt = B.buildConstant({RB, I32}, 31);
1461 Hi = B.buildAShr({RB, MRI.getType(
MI.getOperand(1).getReg())},
1462 MI.getOperand(1).
getReg(), ShiftAmt);
1465 case AMDGPU::G_ANYEXT: {
1466 Hi = B.buildUndef({RB, I32});
1471 "AMDGPU RegBankLegalize: Ext32To64, unsuported opcode",
1476 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(),
1477 {MI.getOperand(1).getReg(), Hi});
1478 MI.eraseFromParent();
1482 uint64_t ConstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1483 B.buildConstant(
MI.getOperand(0).getReg(), ConstVal);
1485 MI.eraseFromParent();
1490 LLT Ty = MRI.getType(Src);
1494 Register BoolSrc = MRI.createVirtualRegister({VgprRB, Ty});
1496 auto Src64 = B.buildUnmerge(VgprRB_I32, Src);
1497 auto One = B.buildConstant(VgprRB_I32, 1);
1498 auto AndLo = B.buildAnd(VgprRB_I32, Src64.getReg(0), One);
1499 auto Zero = B.buildConstant(VgprRB_I32, 0);
1500 auto AndHi = B.buildAnd(VgprRB_I32, Src64.getReg(1), Zero);
1501 B.buildMergeLikeInstr(BoolSrc, {AndLo, AndHi});
1503 assert(Ty == S32 || Ty == S16);
1504 auto One = B.buildConstant({VgprRB, Ty}, 1);
1505 B.buildAnd(BoolSrc, Src, One);
1507 auto Zero = B.buildConstant({VgprRB, Ty}, 0);
1509 MI.eraseFromParent();
1513 return lowerV_BFE(
MI);
1515 return lowerS_BFE(
MI);
1517 return lowerUniMAD64(
MI);
1519 B.buildMul(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2));
1520 MI.eraseFromParent();
1524 auto Op1 = B.buildTrunc(VgprRB_I32,
MI.getOperand(1));
1525 auto Op2 = B.buildTrunc(VgprRB_I32,
MI.getOperand(2));
1526 auto Zero = B.buildConstant(VgprRB_I64, 0);
1528 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_AMDGPU_S_MUL_U64_U32
1529 ? AMDGPU::G_AMDGPU_MAD_U64_U32
1530 : AMDGPU::G_AMDGPU_MAD_I64_I32;
1532 B.buildInstr(NewOpc, {
MI.getOperand(0).getReg(), SgprRB_I32},
1534 MI.eraseFromParent();
1538 return lowerSplitTo32(
MI);
1540 return lowerSplitTo32Mul(
MI);
1542 return lowerSplitTo32Select(
MI);
1544 return lowerSplitTo32SExtInReg(
MI);
1546 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1547 auto LoPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(0));
1548 auto HiPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(1));
1550 B.buildAdd(
MI.getOperand(0).getReg(), LoPopCnt, HiPopCnt,
1553 MI.eraseFromParent();
1557 return lowerSBufToBuf(
MI, WFI);
1559 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1570 if (
Size / 128 == 2)
1572 else if (
Size / 128 == 4)
1576 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1582 else if (DstTy == S96)
1583 splitLoad(
MI, {S64, S32}, S32);
1584 else if (DstTy == V3S32)
1585 splitLoad(
MI, {V2S32, S32}, S32);
1586 else if (DstTy == V6S16)
1587 splitLoad(
MI, {V4S16, V2S16}, V2S16);
1590 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1597 const auto &TFI = *ST.getFrameLowering();
1601 "Stack grows upwards for AMDGPU");
1604 Register AllocSize =
MI.getOperand(1).getReg();
1609 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
1610 MI.eraseFromParent();
1612 if (MRI.getRegBank(AllocSize) != SgprRB) {
1613 auto WaveReduction =
1614 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {SgprRB_I32})
1617 AllocSize = WaveReduction.getReg(0);
1620 LLT PtrTy = MRI.getType(Dst);
1622 "Expected 32-bit pointer for stack allocation");
1623 const SIMachineFunctionInfo *
Info = MF.getInfo<SIMachineFunctionInfo>();
1627 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1628 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1631 if (!HasFlatScratch) {
1632 auto WaveSize = B.buildConstant(SgprRB_I32, WavefrontSizeLog2);
1633 AdjustedSize = B.buildShl(SgprRB_I32, AllocSize, WaveSize).getReg(0);
1635 if (Alignment > TFI.getStackAlign()) {
1636 const uint64_t EffectiveAlignment =
1637 Alignment.value() << (HasFlatScratch ? 0 : WavefrontSizeLog2);
1638 auto OldSP = B.buildCopy({SgprRB, PtrTy},
SPReg);
1640 B.buildPtrAdd({SgprRB, PtrTy}, OldSP,
1641 B.buildConstant(SgprRB_I32, EffectiveAlignment - 1));
1643 B.buildPtrMask(Dst, Tmp1, B.buildConstant(SgprRB_I32, Mask));
1645 B.buildCopy(Dst,
SPReg);
1647 auto PtrAdd = B.buildPtrAdd({SgprRB, PtrTy}, Dst, AdjustedSize);
1648 B.buildCopy(
SPReg, PtrAdd);
1652 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1654 widenLoad(
MI, S128);
1655 else if (DstTy == V3S32)
1656 widenLoad(
MI, V4S32, S32);
1657 else if (DstTy == V6S16)
1658 widenLoad(
MI, V8S16, V2S16);
1661 "AMDGPU RegBankLegalize: WidenLoad, unsuported type",
1668 return lowerUnpackAExt(
MI);
1673 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1679 return MRI.getRegBankOrNull(Op.getReg()) == VgprRB;
1681 B.setInstrAndDebugLoc(
MI);
1682 for (
unsigned i =
MI.getNumDefs(); i <
MI.getNumOperands(); ++i) {
1683 MachineOperand &
Op =
MI.getOperand(i);
1687 if (MRI.getRegBank(
Reg) != VgprRB) {
1688 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
1689 Op.setReg(
Copy.getReg(0));
1699 "AMDGPU RegBankLegalize: unmerge not multiple of 32",
1704 B.setInstrAndDebugLoc(
MI);
1707 B.buildUnmerge({SgprRB, V2S16}, Unmerge->
getSourceReg());
1708 for (
unsigned i = 0; i < UnmergeV2S16->getNumDefs(); ++i) {
1709 auto [Dst0I32, Dst1I32] =
1710 unpackAExt(UnmergeV2S16->getOperand(i).getReg());
1711 B.buildTrunc(
MI.getOperand(i * 2).getReg(), Dst0I32);
1712 B.buildTrunc(
MI.getOperand(i * 2 + 1).getReg(), Dst1I32);
1715 auto [Dst0I32, Dst1I32] = unpackAExt(
MI.getOperand(2).getReg());
1716 B.buildTrunc(
MI.getOperand(0).getReg(), Dst0I32);
1717 B.buildTrunc(
MI.getOperand(1).getReg(), Dst1I32);
1720 MI.eraseFromParent();
1725 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
1726 B.setInsertPt(*
MI.getParent(),
MI.getParent()->getFirstNonPHI());
1727 MI.getOperand(0).setReg(NewDst);
1728 B.buildTrunc(Dst, NewDst);
1730 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1738 auto NewUse = B.buildAnyExt(SgprRB_I32,
UseReg);
1739 MI.getOperand(i).setReg(NewUse.getReg(0));
1747 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1752 assert(MRI.getRegBankOrNull(
MI.getOperand(0).getReg()) == VgprRB);
1756 const RegisterBank *RB = MRI.getRegBankOrNull(Op.getReg());
1757 return RB == VgprRB || RB == SgprRB;
1762 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
1767 unsigned RsrcIdx = RSrcIntrin->
RsrcArg +
MI.getNumExplicitDefs() + 1;
1768 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1774 unsigned RsrcIdx =
MI.getNumOperands();
1775 while (RsrcIdx-- >
MI.getNumExplicitDefs()) {
1776 const MachineOperand &
Op =
MI.getOperand(RsrcIdx);
1777 if (
Op.isReg() &&
Op.getReg().isVirtual())
1780 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1783 return lowerSplitBitCount64To32(
MI);
1785 return lowerExtrVecEltToSel(
MI);
1787 return lowerExtrVecEltTo32(
MI);
1789 return lowerInsVecEltToSel(
MI);
1791 return lowerInsVecEltTo32(
MI);
1793 return lowerAbsToNegMax(
MI);
1795 return lowerAbsToS32(
MI);
1797 MI.eraseFromParent();
1800 return lowerSetRounding(
MI);
1802 return lowerGetRounding(
MI);
1925 return isAnyPtr(Ty, 32) ? Ty : LLT();
1928 return isAnyPtr(Ty, 64) ? Ty : LLT();
1931 return isAnyPtr(Ty, 128) ? Ty : LLT();
1971 const SIRegisterInfo *
TRI =
1972 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
1974 if (LLTSize >= 32 &&
TRI->getSGPRClassForBitWidth(LLTSize))
1979 const SIRegisterInfo *
TRI =
1980 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
2103bool RegBankLegalizeHelper::applyMappingDst(
2104 MachineInstr &
MI,
unsigned &OpIdx,
2105 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs) {
2107 for (; OpIdx < MethodIDs.
size(); ++OpIdx) {
2108 if (MethodIDs[OpIdx] ==
None)
2110 MachineOperand &
Op =
MI.getOperand(OpIdx);
2112 LLT Ty = MRI.getType(
Reg);
2113 [[maybe_unused]]
const RegisterBank *RB = MRI.getRegBank(
Reg);
2115 switch (MethodIDs[OpIdx]) {
2155 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2156 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2181 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2182 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2192 Register NewAgprDst = MRI.createVirtualRegister({AgprRB, Ty});
2193 Op.setReg(NewAgprDst);
2194 if (!MRI.use_nodbg_empty(
Reg))
2195 B.buildCopy(
Reg, NewAgprDst);
2200 const RegisterBank *DstRB =
2201 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2204 Register NewDst = MRI.createVirtualRegister({DstRB, Ty});
2206 if (!MRI.use_nodbg_empty(
Reg))
2207 B.buildCopy(
Reg, NewDst);
2214 Register NewDst = MRI.createVirtualRegister(VccRB_S1);
2216 if (!MRI.use_empty(
Reg)) {
2218 B.buildInstr(AMDGPU::G_AMDGPU_COPY_SCC_VCC, {SgprRB_I32}, {NewDst});
2219 B.buildTrunc(
Reg, CopyS32_Vcc);
2224 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2226 Register NewVgprDst16 = MRI.createVirtualRegister({VgprRB, Ty});
2227 Register NewVgprDstI32 = MRI.createVirtualRegister(VgprRB_I32);
2228 Register NewSgprDstI32 = MRI.createVirtualRegister(SgprRB_I32);
2229 Op.setReg(NewVgprDst16);
2230 B.buildAnyExt(NewVgprDstI32, NewVgprDst16);
2232 B.buildTrunc(
Reg, NewSgprDstI32);
2249 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2251 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2252 Op.setReg(NewVgprDst);
2263 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2265 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2266 Op.setReg(NewVgprDst);
2274 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
2276 if (!MRI.use_empty(
Reg))
2277 B.buildTrunc(
Reg, NewDst);
2282 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2284 Op.setReg(MRI.createVirtualRegister({SgprRB, Ty}));
2285 B.buildCopy(
Reg,
Op.getReg());
2291 "AMDGPU RegBankLegalize: missing fast rule ('Div' or 'Uni') for",
MI);
2297 "AMDGPU RegBankLegalize: applyMappingDst, ID not supported",
MI);
2305bool RegBankLegalizeHelper::applyMappingSrc(
2306 MachineInstr &
MI,
unsigned &OpIdx,
2307 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs,
2309 for (
unsigned i = 0; i < MethodIDs.
size(); ++OpIdx, ++i) {
2310 if (MethodIDs[i] ==
None || MethodIDs[i] ==
IntrId || MethodIDs[i] ==
Imm)
2313 MachineOperand &
Op =
MI.getOperand(OpIdx);
2315 LLT Ty = MRI.getType(
Reg);
2316 const RegisterBank *RB = MRI.getRegBank(
Reg);
2318 switch (MethodIDs[i]) {
2321 assert(RB == VccRB || RB == SgprRB);
2323 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2324 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2325 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2326 auto CopyVcc_Scc = B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC,
2327 {VccRB_S1}, {BoolInReg});
2328 Op.setReg(CopyVcc_Scc.getReg(0));
2347 assert(Ty == getTyFromID(MethodIDs[i]));
2348 assert(RB == getRegBankFromID(MethodIDs[i]));
2362 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2363 assert(RB == getRegBankFromID(MethodIDs[i]));
2390 assert(Ty == getTyFromID(MethodIDs[i]));
2392 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2393 Op.setReg(CopyToVgpr.getReg(0));
2409 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2411 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2412 Op.setReg(CopyToVgpr.getReg(0));
2418 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2419 Op.setReg(CopyToVgpr.getReg(0));
2425 auto CopyToAgpr = B.buildCopy({AgprRB, Ty},
Reg);
2426 Op.setReg(CopyToAgpr.getReg(0));
2432 const RegisterBank *SrcRB =
2433 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2435 Op.setReg(B.buildCopy({SrcRB, Ty},
Reg).getReg(0));
2441 assert(Ty == getTyFromID(MethodIDs[i]));
2446 WFI.
End = std::next(
MI.getIterator());
2453 assert(Ty == getTyFromID(MethodIDs[i]));
2459 while (
Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
2464 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
2476 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2480 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2487 assert(Ty == getTyFromID(MethodIDs[i]));
2491 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2501 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2502 Op.setReg(Aext.getReg(0));
2509 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2512 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2513 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2514 Op.setReg(BoolInReg.getReg(0));
2520 auto Sext = B.buildSExt(SgprRB_I32,
Reg);
2521 Op.setReg(Sext.getReg(0));
2527 auto Zext = B.buildZExt(SgprRB_I32,
Reg);
2528 Op.setReg(Zext.getReg(0));
2534 auto Aext = B.buildAnyExt(VgprRB_I32,
Reg);
2535 Op.setReg(Aext.getReg(0));
2542 auto Sext = B.buildSExt(VgprRB_I32,
Reg);
2543 Op.setReg(Sext.getReg(0));
2550 auto Zext = B.buildZExt(VgprRB_I32,
Reg);
2551 Op.setReg(Zext.getReg(0));
2557 "AMDGPU RegBankLegalize: applyMappingSrc, ID not supported",
MI);
2567 unsigned StartOpIdx,
2568 unsigned EndOpIdx) {
2569 for (
unsigned i = StartOpIdx; i <= EndOpIdx; ++i) {
2576bool RegBankLegalizeHelper::applyRegisterBanksVgprWithSgprRsrc(
2577 MachineInstr &
MI,
unsigned RsrcIdx) {
2578 const unsigned NumDefs =
MI.getNumExplicitDefs();
2584 for (
unsigned i = 0; i < NumDefs; ++i) {
2586 if (MRI.getRegBank(
Reg) == VgprRB)
2589 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, MRI.getType(
Reg)});
2590 MI.getOperand(i).setReg(NewVgprDst);
2594 B.setInstrAndDebugLoc(
MI);
2597 for (
unsigned i = NumDefs; i < RsrcIdx; ++i) {
2598 MachineOperand &
Op =
MI.getOperand(i);
2606 if (MRI.getRegBank(
Reg) == VgprRB)
2609 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
2610 Op.setReg(
Copy.getReg(0));
2613 SmallSet<Register, 4> OpsToWaterfall;
2616 for (
unsigned i = RsrcIdx; i <
MI.getNumOperands(); ++i) {
2617 MachineOperand &
Op =
MI.getOperand(i);
2622 if (MRI.getRegBank(
Reg) != SgprRB)
2626 if (!OpsToWaterfall.
empty()) {
2628 executeInWaterfallLoop(B, {OpsToWaterfall, MII, std::next(MII)});
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
static bool isSignedBFE(MachineInstr &MI)
static bool verifyRegBankOnOperands(MachineInstr &MI, const RegisterBank *RB, MachineRegisterInfo &MRI, unsigned StartOpIdx, unsigned EndOpIdx)
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
static Register UseReg(const MachineOperand &MO)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
static const LaneMaskConstants & get(const GCNSubtarget &ST)
const unsigned XorTermOpc
const unsigned MovTermOpc
const unsigned AndSaveExecOpc
bool findRuleAndApplyMapping(MachineInstr &MI)
RegBankLegalizeHelper(MachineIRBuilder &B, const MachineUniformityInfo &MUI, GISelValueTracking *VT, const RegisterBankInfo &RBI, const RegBankLegalizeRules &RBLRules)
const RegBankLLTMapping * findMappingForMI(const MachineInstr &MI, const MachineRegisterInfo &MRI, const MachineUniformityInfo &MUI) const
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
@ ICMP_ULT
unsigned less than
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
const SIRegisterInfo * getRegisterInfo() const override
Represents a call to an intrinsic.
Register getSourceReg() const
Get the unmerge source register.
constexpr bool isScalar() const
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isFloat() const
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
LLT divide(int Factor) const
Return a type that is Factor times smaller.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
static constexpr LLT float32()
Get a 32-bit IEEE float value.
TypeSize getValue() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI iterator SkipPHIsAndLabels(iterator I)
Return the first instruction in MBB after I that is not a PHI or a label.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
BasicBlockListType::iterator iterator
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
Helper class to build MachineInstr.
bool isValid() const
Check for null.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
LocationSize getSize() const
Return the size in bytes of the memory reference.
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const RegisterBank * getRegBank(Register Reg) const
Return the register bank of Reg.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
const RegisterBank * getRegBankOrNull(Register Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
Holds all the information related to register banks.
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
const uint64_t FltRoundToHWConversionTable
@ SgprV4S32_ReadFirstLane
@ SgprV8S32_ReadFirstLane
bool isAnyPtr(LLT Ty, unsigned Width)
@ TowardZeroF32_TowardNegativeF64
uint32_t decodeFltRoundToHWConversionTable(uint32_t FltRounds)
Read the hardware rounding mode equivalent of a AMDGPUFltRounds value.
Intrinsic::ID getIntrinsicID(const MachineInstr &I)
Return the intrinsic ID for opcodes with the G_AMDGPU_INTRIN_ prefix.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
@ VerifyAllSgprOrVgprGPHI
@ AextToS32InIncomingBlockGPHI
void buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, Register VgprSrc, const RegisterBankInfo &RBI)
const RsrcIntrinsic * lookupRsrcIntrinsic(unsigned Intr)
void buildReadFirstLane(MachineIRBuilder &B, Register SgprDst, Register VgprSrc, const RegisterBankInfo &RBI)
const uint64_t FltRoundConversionTable
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
This is an optimization pass for GlobalISel generic memory operations.
GenericUniformityInfo< MachineSSAContext > MachineUniformityInfo
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
@ Known
Known to have no common set bits.
@ Kill
The last use of a register.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
@ Load
The value being inserted comes from a load (InsertElement only).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
LLVM_ABI std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
LLVM_ABI void reportGISelFailure(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R)
Report an ISel error as a missed optimization remark to the LLVMContext's diagnostic stream.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
MCRegisterClass TargetRegisterClass
static constexpr uint64_t encode(Fields... Values)
LoweringMethodID LoweringMethod
SmallVector< RegBankLLTMappingApplyID, 2 > DstOpMapping
SmallVector< RegBankLLTMappingApplyID, 4 > SrcOpMapping
Holds waterfall loop information: the set of SGPR operand registers that need waterfalling,...
MachineBasicBlock::iterator Start
SmallSet< Register, 4 > SgprWaterfallOperandRegs
MachineBasicBlock::iterator End