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);
273 MRI.setSimpleHint(SavedExec, CondRegLM);
275 B.setInsertPt(*BodyBB, BodyBB->
end());
287 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
291 B.buildInstr(LMC.
MovOpc).addDef(SaveExecReg).addReg(LMC.
ExecReg);
294 B.setInsertPt(*RestoreExecBB, RestoreExecBB->
begin());
299 B.setInsertPt(*RemainderBB, RemainderBB->
begin());
306unsigned RegBankLegalizeHelper::setBufferOffsets(
308 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) {
309 if (std::optional<int64_t>
Imm =
311 uint32_t SOffset, ImmOffset;
312 if (TII.splitMUBUFOffset(*
Imm, SOffset, ImmOffset, Alignment)) {
313 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
314 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
315 InstOffsetVal = ImmOffset;
316 return SOffset + ImmOffset;
319 const bool CheckNUW = ST.hasGFX1250Insts();
321 MRI, CombinedOffset,
nullptr,
323 uint32_t SOffset, ImmOffset;
324 if (
static_cast<int32_t
>(
Offset) > 0 &&
325 TII.splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
326 if (
Base.isValid() && MRI.getRegBank(
Base) == VgprRB) {
328 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
329 InstOffsetVal = ImmOffset;
334 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
336 InstOffsetVal = ImmOffset;
342 if (
Add &&
static_cast<int32_t
>(
Offset) >= 0 &&
346 const RegisterBank *Src0Bank = MRI.getRegBank(Src0);
347 const RegisterBank *Src1Bank = MRI.getRegBank(Src1);
348 if (Src0Bank == VgprRB && Src1Bank == SgprRB) {
353 if (Src0Bank == SgprRB && Src1Bank == VgprRB) {
361 if (MRI.getRegBank(CombinedOffset) == VgprRB) {
362 VOffsetReg = CombinedOffset;
364 VOffsetReg = B.buildCopy(VgprRB_I32, CombinedOffset).getReg(0);
366 SOffsetReg = B.buildConstant(SgprRB_I32, 0).getReg(0);
370bool RegBankLegalizeHelper::splitLoad(MachineInstr &
MI,
373 assert(
MI.getNumMemOperands() == 1);
374 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
376 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
378 LLT PtrTy = MRI.getType(
Base);
379 const RegisterBank *PtrRB = MRI.getRegBankOrNull(
Base);
383 unsigned ByteOffset = 0;
384 for (LLT PartTy : LLTBreakdown) {
386 if (ByteOffset == 0) {
387 BasePlusOffset =
Base;
389 auto Offset = B.buildConstant({PtrRB, OffsetTy}, ByteOffset);
393 auto *OffsetMMO = MF.getMachineMemOperand(&BaseMMO, ByteOffset, PartTy);
394 auto LoadPart = B.buildLoad({DstRB, PartTy}, BasePlusOffset, *OffsetMMO);
395 LoadPartRegs.
push_back(LoadPart.getReg(0));
401 B.buildMergeLikeInstr(Dst, LoadPartRegs);
407 if (MRI.getType(
Reg) == MergeTy) {
410 auto Unmerge = B.buildUnmerge({DstRB, MergeTy},
Reg);
411 for (
unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i)
412 MergeTyParts.
push_back(Unmerge.getReg(i));
415 B.buildMergeLikeInstr(Dst, MergeTyParts);
417 MI.eraseFromParent();
421bool RegBankLegalizeHelper::widenLoad(MachineInstr &
MI, LLT WideTy,
424 assert(
MI.getNumMemOperands() == 1);
425 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
427 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
430 MachineMemOperand *WideMMO = MF.getMachineMemOperand(&BaseMMO, 0, WideTy);
431 auto WideLoad = B.buildLoad({DstRB, WideTy},
Base, *WideMMO);
434 B.buildTrunc(Dst, WideLoad);
437 auto Unmerge = B.buildUnmerge({DstRB, MergeTy}, WideLoad);
439 LLT DstTy = MRI.getType(Dst);
441 for (
unsigned i = 0; i < NumElts; ++i) {
442 MergeTyParts.
push_back(Unmerge.getReg(i));
444 B.buildMergeLikeInstr(Dst, MergeTyParts);
446 MI.eraseFromParent();
450bool RegBankLegalizeHelper::widenMMOToS32(GAnyLoad &
MI)
const {
453 MachineMemOperand &MMO =
MI.getMMO();
456 MachineMemOperand *WideMMO = B.getMF().getMachineMemOperand(&MMO, 0, S32);
458 if (
MI.getOpcode() == G_LOAD) {
459 B.buildLoad(Dst, Ptr, *WideMMO);
461 auto Load = B.buildLoad(SgprRB_I32, Ptr, *WideMMO);
463 if (
MI.getOpcode() == G_ZEXTLOAD) {
465 auto MaskCst = B.buildConstant(SgprRB_I32, Mask);
466 B.buildAnd(Dst,
Load, MaskCst);
468 assert(
MI.getOpcode() == G_SEXTLOAD);
469 B.buildSExtInReg(Dst,
Load, MemSize);
473 MI.eraseFromParent();
477bool RegBankLegalizeHelper::lowerVccExtToSel(MachineInstr &
MI) {
479 LLT Ty = MRI.getType(Dst);
481 unsigned Opc =
MI.getOpcode();
482 int TrueExtCst =
Opc == G_SEXT ? -1 : 1;
483 if (Ty == S32 || Ty == S16) {
484 auto True = B.buildConstant({VgprRB, Ty}, TrueExtCst);
485 auto False = B.buildConstant({VgprRB, Ty}, 0);
486 B.buildSelect(Dst, Src, True, False);
487 }
else if (Ty == S64) {
488 auto True = B.buildConstant({VgprRB_I32}, TrueExtCst);
489 auto False = B.buildConstant({VgprRB_I32}, 0);
490 auto Lo = B.buildSelect({VgprRB_I32}, Src, True, False);
491 MachineInstrBuilder
Hi;
500 Hi = B.buildUndef({VgprRB_I32});
505 "AMDGPU RegBankLegalize: lowerVccExtToSel, Opcode not supported",
MI);
509 B.buildMergeValues(Dst, {
Lo.getReg(0),
Hi.getReg(0)});
513 "AMDGPU RegBankLegalize: lowerVccExtToSel, Type not supported",
MI);
517 MI.eraseFromParent();
521std::pair<Register, Register> RegBankLegalizeHelper::unpackZExt(
Register Reg) {
522 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
523 auto Mask = B.buildConstant(SgprRB_I32, 0x0000ffff);
524 auto Lo = B.buildAnd(SgprRB_I32, PackedI32, Mask);
525 auto Hi = B.buildLShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
526 return {
Lo.getReg(0),
Hi.getReg(0)};
529std::pair<Register, Register> RegBankLegalizeHelper::unpackSExt(
Register Reg) {
530 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
531 auto Lo = B.buildSExtInReg(SgprRB_I32, PackedI32, 16);
532 auto Hi = B.buildAShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
533 return {
Lo.getReg(0),
Hi.getReg(0)};
536std::pair<Register, Register> RegBankLegalizeHelper::unpackAExt(
Register Reg) {
538 if (MRI.getType(
Reg) != I32)
539 RegI32 = B.buildBitcast(SgprRB_I32,
Reg).getReg(0);
541 auto Hi = B.buildLShr(SgprRB_I32, RegI32, B.buildConstant(SgprRB_I32, 16));
542 return {RegI32,
Hi.getReg(0)};
545std::pair<Register, Register>
546RegBankLegalizeHelper::unpackAExtTruncS16(
Register Reg) {
547 auto [Lo32, Hi32] = unpackAExt(
Reg);
548 LLT EltTy = MRI.getType(
Reg).getElementType();
549 return {B.buildTrunc({SgprRB, EltTy}, Lo32).
getReg(0),
550 B.buildTrunc({SgprRB, EltTy}, Hi32).
getReg(0)};
553bool RegBankLegalizeHelper::lowerUnpackBitShift(MachineInstr &
MI) {
555 switch (
MI.getOpcode()) {
556 case AMDGPU::G_SHL: {
557 auto [Val0, Val1] = unpackAExt(
MI.getOperand(1).getReg());
558 auto [Amt0, Amt1] = unpackAExt(
MI.getOperand(2).getReg());
559 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
560 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
563 case AMDGPU::G_LSHR: {
564 auto [Val0, Val1] = unpackZExt(
MI.getOperand(1).getReg());
565 auto [Amt0, Amt1] = unpackZExt(
MI.getOperand(2).getReg());
566 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
567 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
570 case AMDGPU::G_ASHR: {
571 auto [Val0, Val1] = unpackSExt(
MI.getOperand(1).getReg());
572 auto [Amt0, Amt1] = unpackSExt(
MI.getOperand(2).getReg());
573 Lo = B.buildAShr(SgprRB_I32, Val0, Amt0).getReg(0);
574 Hi = B.buildAShr(SgprRB_I32, Val1, Amt1).getReg(0);
580 "AMDGPU RegBankLegalize: lowerUnpackBitShift, case not implemented",
584 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
585 MI.eraseFromParent();
589bool RegBankLegalizeHelper::lowerUnpackMinMax(MachineInstr &
MI) {
591 switch (
MI.getOpcode()) {
593 case AMDGPU::G_SMAX: {
595 auto [Val0_Lo, Val0_Hi] = unpackSExt(
MI.getOperand(1).getReg());
596 auto [Val1_Lo, Val1_Hi] = unpackSExt(
MI.getOperand(2).getReg());
597 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
599 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
604 case AMDGPU::G_UMAX: {
606 auto [Val0_Lo, Val0_Hi] = unpackZExt(
MI.getOperand(1).getReg());
607 auto [Val1_Lo, Val1_Hi] = unpackZExt(
MI.getOperand(2).getReg());
608 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
610 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
617 "AMDGPU RegBankLegalize: lowerUnpackMinMax, case not implemented",
MI);
620 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
621 MI.eraseFromParent();
625bool RegBankLegalizeHelper::lowerUnpackAExt(MachineInstr &
MI) {
626 auto [Op1Lo, Op1Hi] = unpackAExt(
MI.getOperand(1).getReg());
627 auto [Op2Lo, Op2Hi] = unpackAExt(
MI.getOperand(2).getReg());
628 auto ResLo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Lo, Op2Lo});
629 auto ResHi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Hi, Op2Hi});
630 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
631 {ResLo.getReg(0), ResHi.getReg(0)});
632 MI.eraseFromParent();
636bool RegBankLegalizeHelper::lowerSBufToBuf(MachineInstr &
MI,
639 LLT Ty = MRI.getType(Dst);
640 const RegisterBank *RSrcBank = MRI.getRegBank(
MI.getOperand(1).getReg());
644 if (LoadSize == 256 || LoadSize == 512) {
645 NumLoads = LoadSize / 128;
648 for (
int I = 0;
I < NumLoads; ++
I)
649 LoadParts.
emplace_back(MRI.createVirtualRegister({VgprRB, Ty}));
650 MachineMemOperand *OrigMMO = *
MI.memoperands_begin();
655 int64_t ImmOffset = 0;
656 unsigned MMOOffset = setBufferOffsets(B,
MI.getOperand(2).getReg(), VOffset,
657 SOffset, ImmOffset, Alignment);
659 MachineMemOperand *BaseMMO = MF.getMachineMemOperand(OrigMMO, 0, MemSize);
661 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
665 Register VIndex = B.buildConstant(VgprRB_I32, 0).getReg(0);
666 unsigned CachePolicy =
MI.getOperand(3).getImm();
667 unsigned Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
668 switch (
MI.getOpcode()) {
669 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
670 Opc = G_AMDGPU_BUFFER_LOAD_SBYTE;
672 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
673 Opc = G_AMDGPU_BUFFER_LOAD_UBYTE;
675 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
676 Opc = G_AMDGPU_BUFFER_LOAD_SSHORT;
678 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
679 Opc = G_AMDGPU_BUFFER_LOAD_USHORT;
684 for (
int I = 0;
I < NumLoads; ++
I) {
686 .addDef(LoadParts[
I])
691 .addImm(ImmOffset + 16 *
I)
694 .addMemOperand(MF.getMachineMemOperand(BaseMMO, 16 *
I, MemSize));
697 B.buildCopy(Dst, LoadParts[0]);
699 B.buildMergeLikeInstr(Dst, LoadParts);
700 B.setInstr(*MRI.getVRegDef(LoadParts[0]));
701 if (RSrcBank != SgprRB) {
703 WFI.
Start = MRI.getVRegDef(LoadParts.
front());
704 WFI.
End = std::next(MRI.getVRegDef(LoadParts.
back())->getIterator());
706 MI.eraseFromParent();
712 return (GI->is(Intrinsic::amdgcn_sbfe));
714 return MI.getOpcode() == AMDGPU::G_SBFX;
717bool RegBankLegalizeHelper::lowerV_BFE(MachineInstr &
MI) {
724 Register Src =
MI.getOperand(FirstOpnd).getReg();
725 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
726 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
731 unsigned SHROpc =
Signed ? AMDGPU::G_ASHR : AMDGPU::G_LSHR;
732 auto SHRSrc = B.buildInstr(SHROpc, {VgprRB_I64}, {Src, LSBit});
740 auto Amt = B.buildSub(VgprRB_I32, B.buildConstant(SgprRB_I32, 64), Width);
741 auto SignBit = B.buildShl(VgprRB_I64, SHRSrc, Amt);
742 B.buildInstr(SHROpc, {Dst}, {SignBit, Amt});
743 MI.eraseFromParent();
747 uint64_t WidthImm = ConstWidth->Value.getZExtValue();
748 auto UnmergeSHRSrc = B.buildUnmerge(VgprRB_I32, SHRSrc);
749 Register SHRSrcLo = UnmergeSHRSrc.getReg(0);
750 Register SHRSrcHi = UnmergeSHRSrc.getReg(1);
751 auto Zero = B.buildConstant(VgprRB_I32, 0);
752 unsigned BFXOpc =
Signed ? AMDGPU::G_SBFX : AMDGPU::G_UBFX;
754 if (WidthImm <= 32) {
760 B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcLo,
Zero, Width}).
getReg(0);
762 MachineInstrBuilder
Hi;
765 Hi = B.buildAShr(VgprRB_I32,
Lo, B.buildConstant(VgprRB_I32, 31));
770 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
772 auto Amt = B.buildConstant(VgprRB_I32, WidthImm - 32);
774 auto Hi = B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcHi,
Zero, Amt});
775 B.buildMergeLikeInstr(Dst, {SHRSrcLo,
Hi});
778 MI.eraseFromParent();
782bool RegBankLegalizeHelper::lowerS_BFE(MachineInstr &
MI) {
784 LLT Ty = MRI.getType(DstReg);
787 Register Src =
MI.getOperand(FirstOpnd).getReg();
788 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
789 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
796 auto FieldOffset = B.buildAnd(SgprRB_I32, LSBit, Mask);
797 auto Size = B.buildShl(SgprRB_I32, Width, B.buildConstant(SgprRB_I32, 16));
798 auto Src1 = B.buildOr(SgprRB_I32, FieldOffset,
Size);
799 unsigned Opc32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
800 unsigned Opc64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
801 unsigned Opc = Ty == S32 ? Opc32 : Opc64;
805 auto S_BFE = B.buildInstr(
Opc, {{SgprRB, Ty}},
806 {B.buildCopy(Ty, Src), B.buildCopy(I32, Src1)});
808 *ST.getRegisterInfo(), RBI);
810 B.buildCopy(DstReg,
S_BFE->getOperand(0).getReg());
811 MI.eraseFromParent();
815bool RegBankLegalizeHelper::lowerSplitTo32(MachineInstr &
MI) {
817 LLT DstTy = MRI.getType(Dst);
818 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64);
820 auto Op1 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(1).
getReg());
821 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
822 unsigned Opc =
MI.getOpcode();
825 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(0), Op2.getReg(0)},
Flags);
827 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(1), Op2.getReg(1)},
Flags);
828 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
829 MI.eraseFromParent();
833bool RegBankLegalizeHelper::lowerSplitTo32Mul(MachineInstr &
MI) {
835 assert(MRI.getType(Dst) == S64);
836 auto Op1 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(1).
getReg());
837 auto Op2 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(2).
getReg());
841 auto Lo = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
842 auto Carry = B.buildUMulH(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
843 auto MulLo0Hi1 = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(1));
844 auto MulHi0Lo1 = B.buildMul(VgprRB_I32, Op1.getReg(1), Op2.getReg(0));
845 auto Sum = B.buildAdd(VgprRB_I32, MulLo0Hi1, MulHi0Lo1);
846 auto Hi = B.buildAdd(VgprRB_I32, Sum, Carry);
848 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
849 MI.eraseFromParent();
853bool RegBankLegalizeHelper::lowerSplitTo16(MachineInstr &
MI) {
855 assert(MRI.getType(Dst) == V2S16);
856 unsigned Opc =
MI.getOpcode();
857 unsigned NumOps =
MI.getNumOperands();
860 auto [Op1Lo, Op1Hi] = unpackAExtTruncS16(
MI.getOperand(1).getReg());
864 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo},
Flags);
865 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi},
Flags);
866 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
867 MI.eraseFromParent();
871 auto [Op2Lo, Op2Hi] = unpackAExtTruncS16(
MI.getOperand(2).getReg());
874 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo},
Flags);
875 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi},
Flags);
876 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
877 MI.eraseFromParent();
882 auto [Op3Lo, Op3Hi] = unpackAExtTruncS16(
MI.getOperand(3).getReg());
883 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo, Op3Lo},
Flags);
884 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi, Op3Hi},
Flags);
885 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
886 MI.eraseFromParent();
890bool RegBankLegalizeHelper::lowerUniMAD64(MachineInstr &
MI) {
897 const GCNSubtarget &ST = B.getMF().getSubtarget<GCNSubtarget>();
900 Register DstLo = B.buildMul(SgprRB_I32, Src0, Src1).getReg(0);
901 Register DstHi = MRI.createVirtualRegister(SgprRB_I32);
902 if (ST.hasScalarMulHiInsts()) {
903 B.buildInstr(AMDGPU::G_UMULH, {{DstHi}}, {Src0, Src1});
905 auto VSrc0 = B.buildCopy(VgprRB_I32, Src0);
906 auto VSrc1 = B.buildCopy(VgprRB_I32, Src1);
907 auto MulHi = B.buildInstr(AMDGPU::G_UMULH, {VgprRB_I32}, {VSrc0, VSrc1});
918 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
919 B.buildConstant(Dst1, 0);
922 Register Src2Lo = MRI.createVirtualRegister(SgprRB_I32);
923 Register Src2Hi = MRI.createVirtualRegister(SgprRB_I32);
924 B.buildUnmerge({Src2Lo, Src2Hi}, Src2);
926 auto AddLo = B.buildUAddo(SgprRB_I32, SgprRB_I32, DstLo, Src2Lo);
928 B.buildUAdde(SgprRB_I32, SgprRB_I32, DstHi, Src2Hi, AddLo.getReg(1));
929 B.buildMergeLikeInstr(Dst0, {AddLo.getReg(0), AddHi.getReg(0)});
930 B.buildCopy(Dst1, AddHi.getReg(1));
933 MI.eraseFromParent();
937bool RegBankLegalizeHelper::lowerSplitTo32Select(MachineInstr &
MI) {
939 LLT DstTy = MRI.getType(Dst);
940 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64 ||
943 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
944 auto Op3 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(3).
getReg());
949 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(0), Op3.getReg(0), Flags);
951 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(1), Op3.getReg(1), Flags);
953 B.buildMergeLikeInstr(Dst, {Lo, Hi});
954 MI.eraseFromParent();
958bool RegBankLegalizeHelper::lowerSplitTo32SExtInReg(MachineInstr &
MI) {
959 auto Op1 = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
960 int Amt =
MI.getOperand(2).getImm();
964 auto Freeze = B.buildFreeze(VgprRB_I32, Op1.getReg(0));
967 Lo = Freeze.getReg(0);
970 Lo = B.buildSExtInReg(VgprRB_I32, Freeze, Amt).getReg(0);
973 auto SignExtCst = B.buildConstant(SgprRB_I32, 31);
974 Hi = B.buildAShr(VgprRB_I32,
Lo, SignExtCst).getReg(0);
978 Hi = B.buildSExtInReg(VgprRB_I32, Op1.getReg(1), Amt - 32).getReg(0);
981 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(), {Lo, Hi});
982 MI.eraseFromParent();
986bool RegBankLegalizeHelper::lowerSplitBitCount64To32(MachineInstr &
MI) {
992 unsigned Opc =
MI.getOpcode();
1001 case AMDGPU::G_AMDGPU_FFBH_U32:
1003 AddOpc = AMDGPU::G_UADDSAT;
1004 SearchFromMSB =
true;
1006 case AMDGPU::G_AMDGPU_FFBL_B32:
1008 AddOpc = AMDGPU::G_UADDSAT;
1009 SearchFromMSB =
false;
1011 case AMDGPU::G_CTLZ_ZERO_POISON:
1012 FFBOpc = AMDGPU::G_AMDGPU_FFBH_U32;
1013 AddOpc = AMDGPU::G_ADD;
1014 SearchFromMSB =
true;
1016 case AMDGPU::G_CTTZ_ZERO_POISON:
1017 FFBOpc = AMDGPU::G_AMDGPU_FFBL_B32;
1018 AddOpc = AMDGPU::G_ADD;
1019 SearchFromMSB =
false;
1025 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1032 auto Primary = B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Hi :
Lo});
1034 B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Lo :
Hi});
1036 auto Adjusted = B.buildInstr(AddOpc, {VgprRB_I32},
1037 {Secondary, B.buildConstant(VgprRB_I32, 32)});
1038 B.buildUMin(
MI.getOperand(0).getReg(), Primary, Adjusted);
1040 MI.eraseFromParent();
1044bool RegBankLegalizeHelper::lowerExtrVecEltToSel(MachineInstr &
MI) {
1056 LLT VecTy = MRI.getType(Src);
1059 MachineRegisterInfo::VRegAttrs VgprRB_EltTy = {VgprRB, ScalarTy};
1061 auto Unmerge = B.buildUnmerge(VgprRB_EltTy, Src);
1064 Register PrevSelect = Unmerge.getReg(0);
1065 for (
unsigned I = 1;
I < NumElts; ++
I) {
1066 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1069 B.buildSelect(VgprRB_EltTy, Cmp, Unmerge.getReg(
I), PrevSelect)
1072 B.buildCopy(Dst, PrevSelect);
1074 auto InitUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(0));
1075 Register PrevLo = InitUnmerge.getReg(0);
1076 Register PrevHi = InitUnmerge.getReg(1);
1077 for (
unsigned I = 1;
I < NumElts; ++
I) {
1078 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1080 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(
I));
1081 PrevLo = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(0), PrevLo)
1083 PrevHi = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(1), PrevHi)
1086 B.buildMergeLikeInstr(Dst, {PrevLo, PrevHi});
1090 "AMDGPU RegBankLegalize: ExtrVecEltToSel unsupported element type",
MI);
1094 MI.eraseFromParent();
1098bool RegBankLegalizeHelper::lowerExtrVecEltTo32(MachineInstr &
MI) {
1111 LLT SrcTy = MRI.getType(Src);
1114 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1115 "expected VGPR src and SGPR idx");
1117 auto CastSrc = B.buildBitcast({VgprRB, Vec32Ty}, Src);
1120 auto One = B.buildConstant(SgprRB_I32, 1);
1121 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1122 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1124 auto ExtLo = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxLo);
1125 auto ExtHi = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxHi);
1127 B.buildMergeLikeInstr(Dst, {ExtLo.getReg(0), ExtHi.getReg(0)});
1129 MI.eraseFromParent();
1133bool RegBankLegalizeHelper::lowerInsVecEltToSel(MachineInstr &
MI) {
1146 LLT VecTy = MRI.getType(Src);
1149 const RegisterBank *SrcRB = MRI.getRegBank(Src);
1150 bool IsSGPR = (SrcRB == SgprRB);
1151 SmallVector<Register, 16> Selects;
1155 auto Unmerge = B.buildUnmerge(VgprRB_I32, Src);
1156 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1157 Register EltLo = EltUnmerge.getReg(0);
1158 Register EltHi = EltUnmerge.getReg(1);
1159 for (
unsigned I = 0;
I < NumElts; ++
I) {
1160 auto IdxConst = B.buildConstant(VgprRB_I32,
I);
1163 B.buildSelect(VgprRB_I32, Cmp, EltLo, Unmerge.getReg(2 *
I))
1166 B.buildSelect(VgprRB_I32, Cmp, EltHi, Unmerge.getReg(2 *
I + 1))
1170 auto Vec32 = B.buildBuildVector({VgprRB, Vec32Ty}, Selects);
1171 B.buildBitcast(Dst, Vec32);
1174 MachineRegisterInfo::VRegAttrs SrcRB_EltTy = {SrcRB, ScalarTy};
1175 MachineRegisterInfo::VRegAttrs CmpTy = IsSGPR ? SgprRB_I32 : VccRB_S1;
1176 auto Unmerge = B.buildUnmerge(SrcRB_EltTy, Src);
1177 for (
unsigned I = 0;
I < NumElts; ++
I) {
1178 auto IdxConst = B.buildConstant(SgprRB_I32,
I);
1181 B.buildSelect(SrcRB_EltTy, Cmp, Elt, Unmerge.getReg(
I)).getReg(0));
1183 B.buildMergeLikeInstr(Dst, Selects);
1187 "AMDGPU RegBankLegalize: InsVecEltToSel unsupported element type",
MI);
1191 MI.eraseFromParent();
1195bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &
MI) {
1210 LLT SrcTy = MRI.getType(Src);
1213 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1214 "expected VGPR src and SGPR idx");
1216 MachineRegisterInfo::VRegAttrs VgprRB_Vec32Ty = {VgprRB, Vec32Ty};
1218 auto CastSrc = B.buildBitcast(VgprRB_Vec32Ty, Src);
1219 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1222 auto One = B.buildConstant(SgprRB_I32, 1);
1223 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1224 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1226 auto InsLo = B.buildInsertVectorElement(VgprRB_Vec32Ty, CastSrc,
1227 EltUnmerge.getReg(0), IdxLo);
1228 auto InsHi = B.buildInsertVectorElement(VgprRB_Vec32Ty, InsLo,
1229 EltUnmerge.getReg(1), IdxHi);
1231 B.buildBitcast(Dst, InsHi);
1233 MI.eraseFromParent();
1237bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &
MI) {
1247 LLT Ty = MRI.getType(DstReg);
1253 Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).
getReg(0);
1255 assert((Ty == S32 || Ty == S16) &&
"unexpected type for AbsToNegMax");
1256 Zero = B.buildConstant({VgprRB, Ty}, 0).
getReg(0);
1259 auto Neg = B.buildSub({VgprRB, Ty},
Zero, SrcReg);
1260 B.buildSMax(DstReg, SrcReg, Neg);
1261 MI.eraseFromParent();
1265bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &
MI) {
1275 auto Bitcast = B.buildBitcast({SgprRB_I32},
MI.getOperand(1).
getReg());
1276 auto SextInReg = B.buildSExtInReg({SgprRB_I32},
Bitcast, 16);
1278 B.buildAShr({SgprRB_I32},
Bitcast, B.buildConstant({SgprRB_I32}, 16));
1280 auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {SextInReg});
1281 auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {ShiftHi});
1282 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
1283 {AbsLo.getReg(0), AbsHi.getReg(0)});
1285 MI.eraseFromParent();
1291bool RegBankLegalizeHelper::lowerSetRounding(MachineInstr &
MI) {
1292 Register NewMode =
MI.getOperand(0).getReg();
1297 uint32_t ClampedVal = std::min(
1298 static_cast<uint32_t
>(ConstMode->Value.getZExtValue()),
1301 NewMode = B.buildConstant(SgprRB_I32, DecodedVal).getReg(0);
1305 KnownBits
Known = VT->getKnownBits(NewMode);
1306 const bool UseReducedTable =
Known.countMinLeadingZeros() >= 30;
1310 if (UseReducedTable) {
1312 auto BitTable = B.buildConstant(
1315 auto Two = B.buildConstant(SgprRB_I32, 2);
1316 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, NewMode, Two);
1319 B.buildLShr(SgprRB_I32, BitTable, RoundModeTimesNumBits).getReg(0);
1326 auto NegFour = B.buildConstant(SgprRB_I32, -4);
1327 auto OffsetEnum = B.buildAdd(SgprRB_I32, NewMode, NegFour);
1328 auto IndexVal = B.buildUMin(SgprRB_I32, NewMode, OffsetEnum);
1330 auto Two = B.buildConstant(SgprRB_I32, 2);
1331 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, IndexVal, Two);
1336 B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1339 NewMode = B.buildTrunc(SgprRB_I32, TableValue).getReg(0);
1345 uint32_t BothRoundHwReg =
1349 .addImm(
static_cast<int16_t
>(BothRoundHwReg))
1352 MI.eraseFromParent();
1358bool RegBankLegalizeHelper::lowerGetRounding(MachineInstr &
MI) {
1361 uint32_t BothRoundHwReg =
1364 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {SgprRB_I32},
1366 .addImm(BothRoundHwReg);
1397 auto Two = B.buildConstant(SgprRB_I32, 2);
1398 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, GetReg, Two);
1402 auto TableValue = B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1403 auto TruncTable = B.buildTrunc(SgprRB_I32, TableValue);
1405 auto EntryMask = B.buildConstant(SgprRB_I32, 0xf);
1406 auto TableEntry = B.buildAnd(SgprRB_I32, TruncTable, EntryMask);
1410 auto Four = B.buildConstant(SgprRB_I32, 4);
1411 auto EnumOffset = B.buildAdd(SgprRB_I32, TableEntry, Four);
1412 auto IsStandardMode =
1414 B.buildSelect(Dst, IsStandardMode, TableEntry, EnumOffset);
1416 MI.eraseFromParent();
1420bool RegBankLegalizeHelper::lower(MachineInstr &
MI,
1428 return lowerVccExtToSel(
MI);
1430 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1431 auto True = B.buildConstant({SgprRB, Ty},
1432 MI.getOpcode() == AMDGPU::G_SEXT ? -1 : 1);
1433 auto False = B.buildConstant({SgprRB, Ty}, 0);
1437 B.buildSelect(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg(), True,
1439 MI.eraseFromParent();
1443 return lowerUnpackBitShift(
MI);
1445 return lowerUnpackMinMax(
MI);
1447 return lowerSplitTo16(
MI);
1449 const RegisterBank *RB = MRI.getRegBank(
MI.getOperand(0).getReg());
1450 MachineInstrBuilder
Hi;
1451 switch (
MI.getOpcode()) {
1452 case AMDGPU::G_ZEXT: {
1453 Hi = B.buildConstant({RB, I32}, 0);
1456 case AMDGPU::G_SEXT: {
1458 auto ShiftAmt = B.buildConstant({RB, I32}, 31);
1459 Hi = B.buildAShr({RB, MRI.getType(
MI.getOperand(1).getReg())},
1460 MI.getOperand(1).
getReg(), ShiftAmt);
1463 case AMDGPU::G_ANYEXT: {
1464 Hi = B.buildUndef({RB, I32});
1469 "AMDGPU RegBankLegalize: Ext32To64, unsuported opcode",
1474 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(),
1475 {MI.getOperand(1).getReg(), Hi});
1476 MI.eraseFromParent();
1480 uint64_t ConstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1481 B.buildConstant(
MI.getOperand(0).getReg(), ConstVal);
1483 MI.eraseFromParent();
1488 LLT Ty = MRI.getType(Src);
1492 Register BoolSrc = MRI.createVirtualRegister({VgprRB, Ty});
1494 auto Src64 = B.buildUnmerge(VgprRB_I32, Src);
1495 auto One = B.buildConstant(VgprRB_I32, 1);
1496 auto AndLo = B.buildAnd(VgprRB_I32, Src64.getReg(0), One);
1497 auto Zero = B.buildConstant(VgprRB_I32, 0);
1498 auto AndHi = B.buildAnd(VgprRB_I32, Src64.getReg(1), Zero);
1499 B.buildMergeLikeInstr(BoolSrc, {AndLo, AndHi});
1501 assert(Ty == S32 || Ty == S16);
1502 auto One = B.buildConstant({VgprRB, Ty}, 1);
1503 B.buildAnd(BoolSrc, Src, One);
1505 auto Zero = B.buildConstant({VgprRB, Ty}, 0);
1507 MI.eraseFromParent();
1511 return lowerV_BFE(
MI);
1513 return lowerS_BFE(
MI);
1515 return lowerUniMAD64(
MI);
1517 B.buildMul(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2));
1518 MI.eraseFromParent();
1522 auto Op1 = B.buildTrunc(VgprRB_I32,
MI.getOperand(1));
1523 auto Op2 = B.buildTrunc(VgprRB_I32,
MI.getOperand(2));
1524 auto Zero = B.buildConstant(VgprRB_I64, 0);
1526 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_AMDGPU_S_MUL_U64_U32
1527 ? AMDGPU::G_AMDGPU_MAD_U64_U32
1528 : AMDGPU::G_AMDGPU_MAD_I64_I32;
1530 B.buildInstr(NewOpc, {
MI.getOperand(0).getReg(), SgprRB_I32},
1532 MI.eraseFromParent();
1536 return lowerSplitTo32(
MI);
1538 return lowerSplitTo32Mul(
MI);
1540 return lowerSplitTo32Select(
MI);
1542 return lowerSplitTo32SExtInReg(
MI);
1544 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1545 auto LoPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(0));
1546 auto HiPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(1));
1548 B.buildAdd(
MI.getOperand(0).getReg(), LoPopCnt, HiPopCnt,
1551 MI.eraseFromParent();
1555 return lowerSBufToBuf(
MI, WFI);
1557 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1568 if (
Size / 128 == 2)
1570 else if (
Size / 128 == 4)
1574 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1580 else if (DstTy == S96)
1581 splitLoad(
MI, {S64, S32}, S32);
1582 else if (DstTy == V3S32)
1583 splitLoad(
MI, {V2S32, S32}, S32);
1584 else if (DstTy == V6S16)
1585 splitLoad(
MI, {V4S16, V2S16}, V2S16);
1588 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1595 const auto &TFI = *ST.getFrameLowering();
1599 "Stack grows upwards for AMDGPU");
1602 Register AllocSize =
MI.getOperand(1).getReg();
1607 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
1608 MI.eraseFromParent();
1610 if (MRI.getRegBank(AllocSize) != SgprRB) {
1611 auto WaveReduction =
1612 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {SgprRB_I32})
1615 AllocSize = WaveReduction.getReg(0);
1618 LLT PtrTy = MRI.getType(Dst);
1620 "Expected 32-bit pointer for stack allocation");
1621 const SIMachineFunctionInfo *
Info = MF.getInfo<SIMachineFunctionInfo>();
1625 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1626 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1629 if (!HasFlatScratch) {
1630 auto WaveSize = B.buildConstant(SgprRB_I32, WavefrontSizeLog2);
1631 AdjustedSize = B.buildShl(SgprRB_I32, AllocSize, WaveSize).getReg(0);
1633 if (Alignment > TFI.getStackAlign()) {
1634 const uint64_t EffectiveAlignment =
1635 Alignment.value() << (HasFlatScratch ? 0 : WavefrontSizeLog2);
1636 auto OldSP = B.buildCopy({SgprRB, PtrTy},
SPReg);
1638 B.buildPtrAdd({SgprRB, PtrTy}, OldSP,
1639 B.buildConstant(SgprRB_I32, EffectiveAlignment - 1));
1641 B.buildPtrMask(Dst, Tmp1, B.buildConstant(SgprRB_I32, Mask));
1643 B.buildCopy(Dst,
SPReg);
1645 auto PtrAdd = B.buildPtrAdd({SgprRB, PtrTy}, Dst, AdjustedSize);
1646 B.buildCopy(
SPReg, PtrAdd);
1650 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1652 widenLoad(
MI, S128);
1653 else if (DstTy == V3S32)
1654 widenLoad(
MI, V4S32, S32);
1655 else if (DstTy == V6S16)
1656 widenLoad(
MI, V8S16, V2S16);
1659 "AMDGPU RegBankLegalize: WidenLoad, unsuported type",
1666 return lowerUnpackAExt(
MI);
1671 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1677 return MRI.getRegBankOrNull(Op.getReg()) == VgprRB;
1679 B.setInstrAndDebugLoc(
MI);
1680 for (
unsigned i =
MI.getNumDefs(); i <
MI.getNumOperands(); ++i) {
1681 MachineOperand &
Op =
MI.getOperand(i);
1685 if (MRI.getRegBank(
Reg) != VgprRB) {
1686 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
1687 Op.setReg(
Copy.getReg(0));
1697 "AMDGPU RegBankLegalize: unmerge not multiple of 32",
1702 B.setInstrAndDebugLoc(
MI);
1705 B.buildUnmerge({SgprRB, V2S16}, Unmerge->
getSourceReg());
1706 for (
unsigned i = 0; i < UnmergeV2S16->getNumDefs(); ++i) {
1707 auto [Dst0I32, Dst1I32] =
1708 unpackAExt(UnmergeV2S16->getOperand(i).getReg());
1709 B.buildTrunc(
MI.getOperand(i * 2).getReg(), Dst0I32);
1710 B.buildTrunc(
MI.getOperand(i * 2 + 1).getReg(), Dst1I32);
1713 auto [Dst0I32, Dst1I32] = unpackAExt(
MI.getOperand(2).getReg());
1714 B.buildTrunc(
MI.getOperand(0).getReg(), Dst0I32);
1715 B.buildTrunc(
MI.getOperand(1).getReg(), Dst1I32);
1718 MI.eraseFromParent();
1723 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
1724 B.setInsertPt(*
MI.getParent(),
MI.getParent()->getFirstNonPHI());
1725 MI.getOperand(0).setReg(NewDst);
1726 B.buildTrunc(Dst, NewDst);
1728 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1736 auto NewUse = B.buildAnyExt(SgprRB_I32,
UseReg);
1737 MI.getOperand(i).setReg(NewUse.getReg(0));
1745 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1750 assert(MRI.getRegBankOrNull(
MI.getOperand(0).getReg()) == VgprRB);
1754 const RegisterBank *RB = MRI.getRegBankOrNull(Op.getReg());
1755 return RB == VgprRB || RB == SgprRB;
1760 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
1765 unsigned RsrcIdx = RSrcIntrin->
RsrcArg +
MI.getNumExplicitDefs() + 1;
1766 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1772 unsigned RsrcIdx =
MI.getNumOperands();
1773 while (RsrcIdx-- >
MI.getNumExplicitDefs()) {
1774 const MachineOperand &
Op =
MI.getOperand(RsrcIdx);
1775 if (
Op.isReg() &&
Op.getReg().isVirtual())
1778 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1781 return lowerSplitBitCount64To32(
MI);
1783 return lowerExtrVecEltToSel(
MI);
1785 return lowerExtrVecEltTo32(
MI);
1787 return lowerInsVecEltToSel(
MI);
1789 return lowerInsVecEltTo32(
MI);
1791 return lowerAbsToNegMax(
MI);
1793 return lowerAbsToS32(
MI);
1795 MI.eraseFromParent();
1798 return lowerSetRounding(
MI);
1800 return lowerGetRounding(
MI);
1923 return isAnyPtr(Ty, 32) ? Ty : LLT();
1926 return isAnyPtr(Ty, 64) ? Ty : LLT();
1929 return isAnyPtr(Ty, 128) ? Ty : LLT();
1969 const SIRegisterInfo *
TRI =
1970 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
1972 if (LLTSize >= 32 &&
TRI->getSGPRClassForBitWidth(LLTSize))
1977 const SIRegisterInfo *
TRI =
1978 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
2101bool RegBankLegalizeHelper::applyMappingDst(
2102 MachineInstr &
MI,
unsigned &OpIdx,
2103 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs) {
2105 for (; OpIdx < MethodIDs.
size(); ++OpIdx) {
2106 if (MethodIDs[OpIdx] ==
None)
2108 MachineOperand &
Op =
MI.getOperand(OpIdx);
2110 LLT Ty = MRI.getType(
Reg);
2111 [[maybe_unused]]
const RegisterBank *RB = MRI.getRegBank(
Reg);
2113 switch (MethodIDs[OpIdx]) {
2153 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2154 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2179 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2180 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2190 Register NewAgprDst = MRI.createVirtualRegister({AgprRB, Ty});
2191 Op.setReg(NewAgprDst);
2192 if (!MRI.use_nodbg_empty(
Reg))
2193 B.buildCopy(
Reg, NewAgprDst);
2198 const RegisterBank *DstRB =
2199 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2202 Register NewDst = MRI.createVirtualRegister({DstRB, Ty});
2204 if (!MRI.use_nodbg_empty(
Reg))
2205 B.buildCopy(
Reg, NewDst);
2212 Register NewDst = MRI.createVirtualRegister(VccRB_S1);
2214 if (!MRI.use_empty(
Reg)) {
2216 B.buildInstr(AMDGPU::G_AMDGPU_COPY_SCC_VCC, {SgprRB_I32}, {NewDst});
2217 B.buildTrunc(
Reg, CopyS32_Vcc);
2222 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2224 Register NewVgprDst16 = MRI.createVirtualRegister({VgprRB, Ty});
2225 Register NewVgprDstI32 = MRI.createVirtualRegister(VgprRB_I32);
2226 Register NewSgprDstI32 = MRI.createVirtualRegister(SgprRB_I32);
2227 Op.setReg(NewVgprDst16);
2228 B.buildAnyExt(NewVgprDstI32, NewVgprDst16);
2230 B.buildTrunc(
Reg, NewSgprDstI32);
2247 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2249 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2250 Op.setReg(NewVgprDst);
2261 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2263 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2264 Op.setReg(NewVgprDst);
2272 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
2274 if (!MRI.use_empty(
Reg))
2275 B.buildTrunc(
Reg, NewDst);
2280 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2282 Op.setReg(MRI.createVirtualRegister({SgprRB, Ty}));
2283 B.buildCopy(
Reg,
Op.getReg());
2289 "AMDGPU RegBankLegalize: missing fast rule ('Div' or 'Uni') for",
MI);
2295 "AMDGPU RegBankLegalize: applyMappingDst, ID not supported",
MI);
2303bool RegBankLegalizeHelper::applyMappingSrc(
2304 MachineInstr &
MI,
unsigned &OpIdx,
2305 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs,
2307 for (
unsigned i = 0; i < MethodIDs.
size(); ++OpIdx, ++i) {
2308 if (MethodIDs[i] ==
None || MethodIDs[i] ==
IntrId || MethodIDs[i] ==
Imm)
2311 MachineOperand &
Op =
MI.getOperand(OpIdx);
2313 LLT Ty = MRI.getType(
Reg);
2314 const RegisterBank *RB = MRI.getRegBank(
Reg);
2316 switch (MethodIDs[i]) {
2319 assert(RB == VccRB || RB == SgprRB);
2321 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2322 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2323 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2324 auto CopyVcc_Scc = B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC,
2325 {VccRB_S1}, {BoolInReg});
2326 Op.setReg(CopyVcc_Scc.getReg(0));
2345 assert(Ty == getTyFromID(MethodIDs[i]));
2346 assert(RB == getRegBankFromID(MethodIDs[i]));
2360 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2361 assert(RB == getRegBankFromID(MethodIDs[i]));
2388 assert(Ty == getTyFromID(MethodIDs[i]));
2390 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2391 Op.setReg(CopyToVgpr.getReg(0));
2407 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2409 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2410 Op.setReg(CopyToVgpr.getReg(0));
2416 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2417 Op.setReg(CopyToVgpr.getReg(0));
2423 auto CopyToAgpr = B.buildCopy({AgprRB, Ty},
Reg);
2424 Op.setReg(CopyToAgpr.getReg(0));
2430 const RegisterBank *SrcRB =
2431 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2433 Op.setReg(B.buildCopy({SrcRB, Ty},
Reg).getReg(0));
2439 assert(Ty == getTyFromID(MethodIDs[i]));
2444 WFI.
End = std::next(
MI.getIterator());
2451 assert(Ty == getTyFromID(MethodIDs[i]));
2457 while (
Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
2462 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
2474 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2478 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2485 assert(Ty == getTyFromID(MethodIDs[i]));
2489 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2499 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2500 Op.setReg(Aext.getReg(0));
2507 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2510 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2511 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2512 Op.setReg(BoolInReg.getReg(0));
2518 auto Sext = B.buildSExt(SgprRB_I32,
Reg);
2519 Op.setReg(Sext.getReg(0));
2525 auto Zext = B.buildZExt(SgprRB_I32,
Reg);
2526 Op.setReg(Zext.getReg(0));
2532 auto Aext = B.buildAnyExt(VgprRB_I32,
Reg);
2533 Op.setReg(Aext.getReg(0));
2540 auto Sext = B.buildSExt(VgprRB_I32,
Reg);
2541 Op.setReg(Sext.getReg(0));
2548 auto Zext = B.buildZExt(VgprRB_I32,
Reg);
2549 Op.setReg(Zext.getReg(0));
2555 "AMDGPU RegBankLegalize: applyMappingSrc, ID not supported",
MI);
2565 unsigned StartOpIdx,
2566 unsigned EndOpIdx) {
2567 for (
unsigned i = StartOpIdx; i <= EndOpIdx; ++i) {
2574bool RegBankLegalizeHelper::applyRegisterBanksVgprWithSgprRsrc(
2575 MachineInstr &
MI,
unsigned RsrcIdx) {
2576 const unsigned NumDefs =
MI.getNumExplicitDefs();
2582 for (
unsigned i = 0; i < NumDefs; ++i) {
2584 if (MRI.getRegBank(
Reg) == VgprRB)
2587 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, MRI.getType(
Reg)});
2588 MI.getOperand(i).setReg(NewVgprDst);
2592 B.setInstrAndDebugLoc(
MI);
2595 for (
unsigned i = NumDefs; i < RsrcIdx; ++i) {
2596 MachineOperand &
Op =
MI.getOperand(i);
2604 if (MRI.getRegBank(
Reg) == VgprRB)
2607 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
2608 Op.setReg(
Copy.getReg(0));
2611 SmallSet<Register, 4> OpsToWaterfall;
2614 for (
unsigned i = RsrcIdx; i <
MI.getNumOperands(); ++i) {
2615 MachineOperand &
Op =
MI.getOperand(i);
2620 if (MRI.getRegBank(
Reg) != SgprRB)
2624 if (!OpsToWaterfall.
empty()) {
2626 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