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());
948 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(0), Op3.getReg(0), Flags);
950 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(1), Op3.getReg(1), Flags);
952 B.buildMergeLikeInstr(Dst, {Lo, Hi});
953 MI.eraseFromParent();
957bool RegBankLegalizeHelper::lowerSplitTo32SExtInReg(MachineInstr &
MI) {
958 auto Op1 = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
959 int Amt =
MI.getOperand(2).getImm();
963 auto Freeze = B.buildFreeze(VgprRB_I32, Op1.getReg(0));
966 Lo = Freeze.getReg(0);
969 Lo = B.buildSExtInReg(VgprRB_I32, Freeze, Amt).getReg(0);
972 auto SignExtCst = B.buildConstant(SgprRB_I32, 31);
973 Hi = B.buildAShr(VgprRB_I32,
Lo, SignExtCst).getReg(0);
977 Hi = B.buildSExtInReg(VgprRB_I32, Op1.getReg(1), Amt - 32).getReg(0);
980 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(), {Lo, Hi});
981 MI.eraseFromParent();
985bool RegBankLegalizeHelper::lowerSplitBitCount64To32(MachineInstr &
MI) {
991 unsigned Opc =
MI.getOpcode();
1000 case AMDGPU::G_AMDGPU_FFBH_U32:
1002 AddOpc = AMDGPU::G_UADDSAT;
1003 SearchFromMSB =
true;
1005 case AMDGPU::G_AMDGPU_FFBL_B32:
1007 AddOpc = AMDGPU::G_UADDSAT;
1008 SearchFromMSB =
false;
1010 case AMDGPU::G_CTLZ_ZERO_POISON:
1011 FFBOpc = AMDGPU::G_AMDGPU_FFBH_U32;
1012 AddOpc = AMDGPU::G_ADD;
1013 SearchFromMSB =
true;
1015 case AMDGPU::G_CTTZ_ZERO_POISON:
1016 FFBOpc = AMDGPU::G_AMDGPU_FFBL_B32;
1017 AddOpc = AMDGPU::G_ADD;
1018 SearchFromMSB =
false;
1024 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1031 auto Primary = B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Hi :
Lo});
1033 B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Lo :
Hi});
1035 auto Adjusted = B.buildInstr(AddOpc, {VgprRB_I32},
1036 {Secondary, B.buildConstant(VgprRB_I32, 32)});
1037 B.buildUMin(
MI.getOperand(0).getReg(), Primary, Adjusted);
1039 MI.eraseFromParent();
1043bool RegBankLegalizeHelper::lowerExtrVecEltToSel(MachineInstr &
MI) {
1055 LLT VecTy = MRI.getType(Src);
1058 MachineRegisterInfo::VRegAttrs VgprRB_EltTy = {VgprRB, ScalarTy};
1060 auto Unmerge = B.buildUnmerge(VgprRB_EltTy, Src);
1063 Register PrevSelect = Unmerge.getReg(0);
1064 for (
unsigned I = 1;
I < NumElts; ++
I) {
1065 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1068 B.buildSelect(VgprRB_EltTy, Cmp, Unmerge.getReg(
I), PrevSelect)
1071 B.buildCopy(Dst, PrevSelect);
1073 auto InitUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(0));
1074 Register PrevLo = InitUnmerge.getReg(0);
1075 Register PrevHi = InitUnmerge.getReg(1);
1076 for (
unsigned I = 1;
I < NumElts; ++
I) {
1077 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1079 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(
I));
1080 PrevLo = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(0), PrevLo)
1082 PrevHi = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(1), PrevHi)
1085 B.buildMergeLikeInstr(Dst, {PrevLo, PrevHi});
1089 "AMDGPU RegBankLegalize: ExtrVecEltToSel unsupported element type",
MI);
1093 MI.eraseFromParent();
1097bool RegBankLegalizeHelper::lowerExtrVecEltTo32(MachineInstr &
MI) {
1110 LLT SrcTy = MRI.getType(Src);
1113 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1114 "expected VGPR src and SGPR idx");
1116 auto CastSrc = B.buildBitcast({VgprRB, Vec32Ty}, Src);
1119 auto One = B.buildConstant(SgprRB_I32, 1);
1120 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1121 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1123 auto ExtLo = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxLo);
1124 auto ExtHi = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxHi);
1126 B.buildMergeLikeInstr(Dst, {ExtLo.getReg(0), ExtHi.getReg(0)});
1128 MI.eraseFromParent();
1132bool RegBankLegalizeHelper::lowerInsVecEltToSel(MachineInstr &
MI) {
1145 LLT VecTy = MRI.getType(Src);
1148 const RegisterBank *SrcRB = MRI.getRegBank(Src);
1149 bool IsSGPR = (SrcRB == SgprRB);
1150 SmallVector<Register, 16> Selects;
1154 auto Unmerge = B.buildUnmerge(VgprRB_I32, Src);
1155 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1156 Register EltLo = EltUnmerge.getReg(0);
1157 Register EltHi = EltUnmerge.getReg(1);
1158 for (
unsigned I = 0;
I < NumElts; ++
I) {
1159 auto IdxConst = B.buildConstant(VgprRB_I32,
I);
1162 B.buildSelect(VgprRB_I32, Cmp, EltLo, Unmerge.getReg(2 *
I))
1165 B.buildSelect(VgprRB_I32, Cmp, EltHi, Unmerge.getReg(2 *
I + 1))
1169 auto Vec32 = B.buildBuildVector({VgprRB, Vec32Ty}, Selects);
1170 B.buildBitcast(Dst, Vec32);
1173 MachineRegisterInfo::VRegAttrs SrcRB_EltTy = {SrcRB, ScalarTy};
1174 MachineRegisterInfo::VRegAttrs CmpTy = IsSGPR ? SgprRB_I32 : VccRB_S1;
1175 auto Unmerge = B.buildUnmerge(SrcRB_EltTy, Src);
1176 for (
unsigned I = 0;
I < NumElts; ++
I) {
1177 auto IdxConst = B.buildConstant(SgprRB_I32,
I);
1180 B.buildSelect(SrcRB_EltTy, Cmp, Elt, Unmerge.getReg(
I)).getReg(0));
1182 B.buildMergeLikeInstr(Dst, Selects);
1186 "AMDGPU RegBankLegalize: InsVecEltToSel unsupported element type",
MI);
1190 MI.eraseFromParent();
1194bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &
MI) {
1209 LLT SrcTy = MRI.getType(Src);
1212 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1213 "expected VGPR src and SGPR idx");
1215 MachineRegisterInfo::VRegAttrs VgprRB_Vec32Ty = {VgprRB, Vec32Ty};
1217 auto CastSrc = B.buildBitcast(VgprRB_Vec32Ty, Src);
1218 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1221 auto One = B.buildConstant(SgprRB_I32, 1);
1222 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1223 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1225 auto InsLo = B.buildInsertVectorElement(VgprRB_Vec32Ty, CastSrc,
1226 EltUnmerge.getReg(0), IdxLo);
1227 auto InsHi = B.buildInsertVectorElement(VgprRB_Vec32Ty, InsLo,
1228 EltUnmerge.getReg(1), IdxHi);
1230 B.buildBitcast(Dst, InsHi);
1232 MI.eraseFromParent();
1236bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &
MI) {
1246 LLT Ty = MRI.getType(DstReg);
1252 Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).
getReg(0);
1254 assert((Ty == S32 || Ty == S16) &&
"unexpected type for AbsToNegMax");
1255 Zero = B.buildConstant({VgprRB, Ty}, 0).
getReg(0);
1258 auto Neg = B.buildSub({VgprRB, Ty},
Zero, SrcReg);
1259 B.buildSMax(DstReg, SrcReg, Neg);
1260 MI.eraseFromParent();
1264bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &
MI) {
1274 auto Bitcast = B.buildBitcast({SgprRB_I32},
MI.getOperand(1).
getReg());
1275 auto SextInReg = B.buildSExtInReg({SgprRB_I32},
Bitcast, 16);
1277 B.buildAShr({SgprRB_I32},
Bitcast, B.buildConstant({SgprRB_I32}, 16));
1279 auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {SextInReg});
1280 auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {ShiftHi});
1281 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
1282 {AbsLo.getReg(0), AbsHi.getReg(0)});
1284 MI.eraseFromParent();
1290bool RegBankLegalizeHelper::lowerSetRounding(MachineInstr &
MI) {
1291 Register NewMode =
MI.getOperand(0).getReg();
1296 uint32_t ClampedVal = std::min(
1297 static_cast<uint32_t
>(ConstMode->Value.getZExtValue()),
1300 NewMode = B.buildConstant(SgprRB_I32, DecodedVal).getReg(0);
1304 KnownBits
Known = VT->getKnownBits(NewMode);
1305 const bool UseReducedTable =
Known.countMinLeadingZeros() >= 30;
1309 if (UseReducedTable) {
1311 auto BitTable = B.buildConstant(
1314 auto Two = B.buildConstant(SgprRB_I32, 2);
1315 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, NewMode, Two);
1318 B.buildLShr(SgprRB_I32, BitTable, RoundModeTimesNumBits).getReg(0);
1325 auto NegFour = B.buildConstant(SgprRB_I32, -4);
1326 auto OffsetEnum = B.buildAdd(SgprRB_I32, NewMode, NegFour);
1327 auto IndexVal = B.buildUMin(SgprRB_I32, NewMode, OffsetEnum);
1329 auto Two = B.buildConstant(SgprRB_I32, 2);
1330 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, IndexVal, Two);
1335 B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1338 NewMode = B.buildTrunc(SgprRB_I32, TableValue).getReg(0);
1344 uint32_t BothRoundHwReg =
1348 .addImm(
static_cast<int16_t
>(BothRoundHwReg))
1351 MI.eraseFromParent();
1357bool RegBankLegalizeHelper::lowerGetRounding(MachineInstr &
MI) {
1360 uint32_t BothRoundHwReg =
1363 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {SgprRB_I32},
1365 .addImm(BothRoundHwReg);
1396 auto Two = B.buildConstant(SgprRB_I32, 2);
1397 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, GetReg, Two);
1401 auto TableValue = B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1402 auto TruncTable = B.buildTrunc(SgprRB_I32, TableValue);
1404 auto EntryMask = B.buildConstant(SgprRB_I32, 0xf);
1405 auto TableEntry = B.buildAnd(SgprRB_I32, TruncTable, EntryMask);
1409 auto Four = B.buildConstant(SgprRB_I32, 4);
1410 auto EnumOffset = B.buildAdd(SgprRB_I32, TableEntry, Four);
1411 auto IsStandardMode =
1413 B.buildSelect(Dst, IsStandardMode, TableEntry, EnumOffset);
1415 MI.eraseFromParent();
1419bool RegBankLegalizeHelper::lower(MachineInstr &
MI,
1427 return lowerVccExtToSel(
MI);
1429 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1430 auto True = B.buildConstant({SgprRB, Ty},
1431 MI.getOpcode() == AMDGPU::G_SEXT ? -1 : 1);
1432 auto False = B.buildConstant({SgprRB, Ty}, 0);
1436 B.buildSelect(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg(), True,
1438 MI.eraseFromParent();
1442 return lowerUnpackBitShift(
MI);
1444 return lowerUnpackMinMax(
MI);
1446 return lowerSplitTo16(
MI);
1448 const RegisterBank *RB = MRI.getRegBank(
MI.getOperand(0).getReg());
1449 MachineInstrBuilder
Hi;
1450 switch (
MI.getOpcode()) {
1451 case AMDGPU::G_ZEXT: {
1452 Hi = B.buildConstant({RB, I32}, 0);
1455 case AMDGPU::G_SEXT: {
1457 auto ShiftAmt = B.buildConstant({RB, I32}, 31);
1458 Hi = B.buildAShr({RB, MRI.getType(
MI.getOperand(1).getReg())},
1459 MI.getOperand(1).
getReg(), ShiftAmt);
1462 case AMDGPU::G_ANYEXT: {
1463 Hi = B.buildUndef({RB, I32});
1468 "AMDGPU RegBankLegalize: Ext32To64, unsuported opcode",
1473 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(),
1474 {MI.getOperand(1).getReg(), Hi});
1475 MI.eraseFromParent();
1479 uint64_t ConstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1480 B.buildConstant(
MI.getOperand(0).getReg(), ConstVal);
1482 MI.eraseFromParent();
1487 LLT Ty = MRI.getType(Src);
1491 Register BoolSrc = MRI.createVirtualRegister({VgprRB, Ty});
1493 auto Src64 = B.buildUnmerge(VgprRB_I32, Src);
1494 auto One = B.buildConstant(VgprRB_I32, 1);
1495 auto AndLo = B.buildAnd(VgprRB_I32, Src64.getReg(0), One);
1496 auto Zero = B.buildConstant(VgprRB_I32, 0);
1497 auto AndHi = B.buildAnd(VgprRB_I32, Src64.getReg(1), Zero);
1498 B.buildMergeLikeInstr(BoolSrc, {AndLo, AndHi});
1500 assert(Ty == S32 || Ty == S16);
1501 auto One = B.buildConstant({VgprRB, Ty}, 1);
1502 B.buildAnd(BoolSrc, Src, One);
1504 auto Zero = B.buildConstant({VgprRB, Ty}, 0);
1506 MI.eraseFromParent();
1510 return lowerV_BFE(
MI);
1512 return lowerS_BFE(
MI);
1514 return lowerUniMAD64(
MI);
1516 B.buildMul(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2));
1517 MI.eraseFromParent();
1521 auto Op1 = B.buildTrunc(VgprRB_I32,
MI.getOperand(1));
1522 auto Op2 = B.buildTrunc(VgprRB_I32,
MI.getOperand(2));
1523 auto Zero = B.buildConstant(VgprRB_I64, 0);
1525 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_AMDGPU_S_MUL_U64_U32
1526 ? AMDGPU::G_AMDGPU_MAD_U64_U32
1527 : AMDGPU::G_AMDGPU_MAD_I64_I32;
1529 B.buildInstr(NewOpc, {
MI.getOperand(0).getReg(), SgprRB_I32},
1531 MI.eraseFromParent();
1535 return lowerSplitTo32(
MI);
1537 return lowerSplitTo32Mul(
MI);
1539 return lowerSplitTo32Select(
MI);
1541 return lowerSplitTo32SExtInReg(
MI);
1543 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1544 auto LoPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(0));
1545 auto HiPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(1));
1547 B.buildAdd(
MI.getOperand(0).getReg(), LoPopCnt, HiPopCnt,
1550 MI.eraseFromParent();
1554 return lowerSBufToBuf(
MI, WFI);
1556 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1567 if (
Size / 128 == 2)
1569 else if (
Size / 128 == 4)
1573 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1579 else if (DstTy == S96)
1580 splitLoad(
MI, {S64, S32}, S32);
1581 else if (DstTy == V3S32)
1582 splitLoad(
MI, {V2S32, S32}, S32);
1583 else if (DstTy == V6S16)
1584 splitLoad(
MI, {V4S16, V2S16}, V2S16);
1587 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1594 const auto &TFI = *ST.getFrameLowering();
1598 "Stack grows upwards for AMDGPU");
1601 Register AllocSize =
MI.getOperand(1).getReg();
1606 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
1607 MI.eraseFromParent();
1609 if (MRI.getRegBank(AllocSize) != SgprRB) {
1610 auto WaveReduction =
1611 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {SgprRB_I32})
1614 AllocSize = WaveReduction.getReg(0);
1617 LLT PtrTy = MRI.getType(Dst);
1619 "Expected 32-bit pointer for stack allocation");
1620 const SIMachineFunctionInfo *
Info = MF.getInfo<SIMachineFunctionInfo>();
1624 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1625 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1628 if (!HasFlatScratch) {
1629 auto WaveSize = B.buildConstant(SgprRB_I32, WavefrontSizeLog2);
1630 AdjustedSize = B.buildShl(SgprRB_I32, AllocSize, WaveSize).getReg(0);
1632 if (Alignment > TFI.getStackAlign()) {
1633 const uint64_t EffectiveAlignment =
1634 Alignment.value() << (HasFlatScratch ? 0 : WavefrontSizeLog2);
1635 auto OldSP = B.buildCopy({SgprRB, PtrTy},
SPReg);
1637 B.buildPtrAdd({SgprRB, PtrTy}, OldSP,
1638 B.buildConstant(SgprRB_I32, EffectiveAlignment - 1));
1640 B.buildPtrMask(Dst, Tmp1, B.buildConstant(SgprRB_I32, Mask));
1642 B.buildCopy(Dst,
SPReg);
1644 auto PtrAdd = B.buildPtrAdd({SgprRB, PtrTy}, Dst, AdjustedSize);
1645 B.buildCopy(
SPReg, PtrAdd);
1649 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1651 widenLoad(
MI, S128);
1652 else if (DstTy == V3S32)
1653 widenLoad(
MI, V4S32, S32);
1654 else if (DstTy == V6S16)
1655 widenLoad(
MI, V8S16, V2S16);
1658 "AMDGPU RegBankLegalize: WidenLoad, unsuported type",
1665 return lowerUnpackAExt(
MI);
1670 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1676 return MRI.getRegBankOrNull(Op.getReg()) == VgprRB;
1678 B.setInstrAndDebugLoc(
MI);
1679 for (
unsigned i =
MI.getNumDefs(); i <
MI.getNumOperands(); ++i) {
1680 MachineOperand &
Op =
MI.getOperand(i);
1684 if (MRI.getRegBank(
Reg) != VgprRB) {
1685 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
1686 Op.setReg(
Copy.getReg(0));
1696 "AMDGPU RegBankLegalize: unmerge not multiple of 32",
1701 B.setInstrAndDebugLoc(
MI);
1704 B.buildUnmerge({SgprRB, V2S16}, Unmerge->
getSourceReg());
1705 for (
unsigned i = 0; i < UnmergeV2S16->getNumDefs(); ++i) {
1706 auto [Dst0I32, Dst1I32] =
1707 unpackAExt(UnmergeV2S16->getOperand(i).getReg());
1708 B.buildTrunc(
MI.getOperand(i * 2).getReg(), Dst0I32);
1709 B.buildTrunc(
MI.getOperand(i * 2 + 1).getReg(), Dst1I32);
1712 auto [Dst0I32, Dst1I32] = unpackAExt(
MI.getOperand(2).getReg());
1713 B.buildTrunc(
MI.getOperand(0).getReg(), Dst0I32);
1714 B.buildTrunc(
MI.getOperand(1).getReg(), Dst1I32);
1717 MI.eraseFromParent();
1722 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
1723 B.setInsertPt(*
MI.getParent(),
MI.getParent()->getFirstNonPHI());
1724 MI.getOperand(0).setReg(NewDst);
1725 B.buildTrunc(Dst, NewDst);
1727 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1735 auto NewUse = B.buildAnyExt(SgprRB_I32,
UseReg);
1736 MI.getOperand(i).setReg(NewUse.getReg(0));
1744 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1749 assert(MRI.getRegBankOrNull(
MI.getOperand(0).getReg()) == VgprRB);
1753 const RegisterBank *RB = MRI.getRegBankOrNull(Op.getReg());
1754 return RB == VgprRB || RB == SgprRB;
1759 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
1764 unsigned RsrcIdx = RSrcIntrin->
RsrcArg +
MI.getNumExplicitDefs() + 1;
1765 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1771 unsigned RsrcIdx =
MI.getNumOperands();
1772 while (RsrcIdx-- >
MI.getNumExplicitDefs()) {
1773 const MachineOperand &
Op =
MI.getOperand(RsrcIdx);
1774 if (
Op.isReg() &&
Op.getReg().isVirtual())
1777 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1780 return lowerSplitBitCount64To32(
MI);
1782 return lowerExtrVecEltToSel(
MI);
1784 return lowerExtrVecEltTo32(
MI);
1786 return lowerInsVecEltToSel(
MI);
1788 return lowerInsVecEltTo32(
MI);
1790 return lowerAbsToNegMax(
MI);
1792 return lowerAbsToS32(
MI);
1794 MI.eraseFromParent();
1797 return lowerSetRounding(
MI);
1799 return lowerGetRounding(
MI);
1922 return isAnyPtr(Ty, 32) ? Ty : LLT();
1925 return isAnyPtr(Ty, 64) ? Ty : LLT();
1928 return isAnyPtr(Ty, 128) ? Ty : LLT();
1968 const SIRegisterInfo *
TRI =
1969 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
1971 if (LLTSize >= 32 &&
TRI->getSGPRClassForBitWidth(LLTSize))
1976 const SIRegisterInfo *
TRI =
1977 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
2100bool RegBankLegalizeHelper::applyMappingDst(
2101 MachineInstr &
MI,
unsigned &OpIdx,
2102 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs) {
2104 for (; OpIdx < MethodIDs.
size(); ++OpIdx) {
2105 if (MethodIDs[OpIdx] ==
None)
2107 MachineOperand &
Op =
MI.getOperand(OpIdx);
2109 LLT Ty = MRI.getType(
Reg);
2110 [[maybe_unused]]
const RegisterBank *RB = MRI.getRegBank(
Reg);
2112 switch (MethodIDs[OpIdx]) {
2152 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2153 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2178 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2179 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2189 Register NewAgprDst = MRI.createVirtualRegister({AgprRB, Ty});
2190 Op.setReg(NewAgprDst);
2191 if (!MRI.use_nodbg_empty(
Reg))
2192 B.buildCopy(
Reg, NewAgprDst);
2197 const RegisterBank *DstRB =
2198 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2201 Register NewDst = MRI.createVirtualRegister({DstRB, Ty});
2203 if (!MRI.use_nodbg_empty(
Reg))
2204 B.buildCopy(
Reg, NewDst);
2211 Register NewDst = MRI.createVirtualRegister(VccRB_S1);
2213 if (!MRI.use_empty(
Reg)) {
2215 B.buildInstr(AMDGPU::G_AMDGPU_COPY_SCC_VCC, {SgprRB_I32}, {NewDst});
2216 B.buildTrunc(
Reg, CopyS32_Vcc);
2221 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2223 Register NewVgprDst16 = MRI.createVirtualRegister({VgprRB, Ty});
2224 Register NewVgprDstI32 = MRI.createVirtualRegister(VgprRB_I32);
2225 Register NewSgprDstI32 = MRI.createVirtualRegister(SgprRB_I32);
2226 Op.setReg(NewVgprDst16);
2227 B.buildAnyExt(NewVgprDstI32, NewVgprDst16);
2229 B.buildTrunc(
Reg, NewSgprDstI32);
2246 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2248 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2249 Op.setReg(NewVgprDst);
2260 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2262 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2263 Op.setReg(NewVgprDst);
2271 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
2273 if (!MRI.use_empty(
Reg))
2274 B.buildTrunc(
Reg, NewDst);
2279 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2281 Op.setReg(MRI.createVirtualRegister({SgprRB, Ty}));
2282 B.buildCopy(
Reg,
Op.getReg());
2288 "AMDGPU RegBankLegalize: missing fast rule ('Div' or 'Uni') for",
MI);
2294 "AMDGPU RegBankLegalize: applyMappingDst, ID not supported",
MI);
2302bool RegBankLegalizeHelper::applyMappingSrc(
2303 MachineInstr &
MI,
unsigned &OpIdx,
2304 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs,
2306 for (
unsigned i = 0; i < MethodIDs.
size(); ++OpIdx, ++i) {
2307 if (MethodIDs[i] ==
None || MethodIDs[i] ==
IntrId || MethodIDs[i] ==
Imm)
2310 MachineOperand &
Op =
MI.getOperand(OpIdx);
2312 LLT Ty = MRI.getType(
Reg);
2313 const RegisterBank *RB = MRI.getRegBank(
Reg);
2315 switch (MethodIDs[i]) {
2318 assert(RB == VccRB || RB == SgprRB);
2320 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2321 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2322 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2323 auto CopyVcc_Scc = B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC,
2324 {VccRB_S1}, {BoolInReg});
2325 Op.setReg(CopyVcc_Scc.getReg(0));
2344 assert(Ty == getTyFromID(MethodIDs[i]));
2345 assert(RB == getRegBankFromID(MethodIDs[i]));
2359 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2360 assert(RB == getRegBankFromID(MethodIDs[i]));
2387 assert(Ty == getTyFromID(MethodIDs[i]));
2389 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2390 Op.setReg(CopyToVgpr.getReg(0));
2406 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2408 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2409 Op.setReg(CopyToVgpr.getReg(0));
2415 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2416 Op.setReg(CopyToVgpr.getReg(0));
2422 auto CopyToAgpr = B.buildCopy({AgprRB, Ty},
Reg);
2423 Op.setReg(CopyToAgpr.getReg(0));
2429 const RegisterBank *SrcRB =
2430 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2432 Op.setReg(B.buildCopy({SrcRB, Ty},
Reg).getReg(0));
2438 assert(Ty == getTyFromID(MethodIDs[i]));
2443 WFI.
End = std::next(
MI.getIterator());
2450 assert(Ty == getTyFromID(MethodIDs[i]));
2456 while (
Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
2461 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
2473 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2477 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2484 assert(Ty == getTyFromID(MethodIDs[i]));
2488 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2498 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2499 Op.setReg(Aext.getReg(0));
2506 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2509 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2510 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2511 Op.setReg(BoolInReg.getReg(0));
2517 auto Sext = B.buildSExt(SgprRB_I32,
Reg);
2518 Op.setReg(Sext.getReg(0));
2524 auto Zext = B.buildZExt(SgprRB_I32,
Reg);
2525 Op.setReg(Zext.getReg(0));
2531 auto Aext = B.buildAnyExt(VgprRB_I32,
Reg);
2532 Op.setReg(Aext.getReg(0));
2539 auto Sext = B.buildSExt(VgprRB_I32,
Reg);
2540 Op.setReg(Sext.getReg(0));
2547 auto Zext = B.buildZExt(VgprRB_I32,
Reg);
2548 Op.setReg(Zext.getReg(0));
2554 "AMDGPU RegBankLegalize: applyMappingSrc, ID not supported",
MI);
2564 unsigned StartOpIdx,
2565 unsigned EndOpIdx) {
2566 for (
unsigned i = StartOpIdx; i <= EndOpIdx; ++i) {
2573bool RegBankLegalizeHelper::applyRegisterBanksVgprWithSgprRsrc(
2574 MachineInstr &
MI,
unsigned RsrcIdx) {
2575 const unsigned NumDefs =
MI.getNumExplicitDefs();
2581 for (
unsigned i = 0; i < NumDefs; ++i) {
2583 if (MRI.getRegBank(
Reg) == VgprRB)
2586 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, MRI.getType(
Reg)});
2587 MI.getOperand(i).setReg(NewVgprDst);
2591 B.setInstrAndDebugLoc(
MI);
2594 for (
unsigned i = NumDefs; i < RsrcIdx; ++i) {
2595 MachineOperand &
Op =
MI.getOperand(i);
2603 if (MRI.getRegBank(
Reg) == VgprRB)
2606 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
2607 Op.setReg(
Copy.getReg(0));
2610 SmallSet<Register, 4> OpsToWaterfall;
2613 for (
unsigned i = RsrcIdx; i <
MI.getNumOperands(); ++i) {
2614 MachineOperand &
Op =
MI.getOperand(i);
2619 if (MRI.getRegBank(
Reg) != SgprRB)
2623 if (!OpsToWaterfall.
empty()) {
2625 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