28#include "llvm/IR/IntrinsicsAMDGPU.h"
30#define DEBUG_TYPE "amdgpu-reg-bank-legalize"
40 ST(MF.getSubtarget<
GCNSubtarget>()), TII(*ST.getInstrInfo()), B(B),
41 MRI(*B.getMRI()), MUI(MUI), VT(VT), RBI(RBI), MORE(MF, nullptr),
42 RBLRules(RBLRules), IsWave32(ST.isWave32()),
43 SgprRB(&RBI.getRegBank(
AMDGPU::SGPRRegBankID)),
44 VgprRB(&RBI.getRegBank(
AMDGPU::VGPRRegBankID)),
45 AgprRB(&RBI.getRegBank(
AMDGPU::AGPRRegBankID)),
46 VccRB(&RBI.getRegBank(
AMDGPU::VCCRegBankID)) {}
52 "No AMDGPU RegBankLegalize rules defined for opcode",
60 "AMDGPU RegBankLegalize: none of the rules defined with "
61 "'Any' for MI's opcode matched MI",
69 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
79 if (!lower(
MI, *Mapping, WFI))
83 if (!executeInWaterfallLoop(B, WFI))
93 "Waterfall range not initialized");
110 const int OrigRangeSize = std::distance(BeginIt, EndIt);
119 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(InitSaveExecReg);
145 MBB.addSuccessor(LoopBB);
148 B.setInsertPt(*LoopBB, LoopBB->
end());
199 auto NewEnd = BodyBB->
end();
200 assert(std::distance(NewBegin, NewEnd) == OrigRangeSize);
213 auto OldVal = WaterfalledRegMap.
find(OldReg);
214 if (OldVal != WaterfalledRegMap.
end()) {
215 Op.setReg(OldVal->second);
228 unsigned OpSize =
OpTy.getSizeInBits();
229 unsigned PartSize = (OpSize % 64 == 0) ? 64 : 32;
231 unsigned NumParts = OpSize / PartSize;
237 CurrentLaneParts.
push_back(CurrentLaneReg);
239 auto UnmergeOp = B.buildUnmerge({VgprRB, PartTy}, OpReg);
240 auto UnmergeCurrLane = B.buildUnmerge({SgprRB, PartTy}, CurrentLaneReg);
241 for (
unsigned i = 0; i < NumParts; ++i) {
243 CurrentLaneParts.
push_back(UnmergeCurrLane.getReg(i));
247 for (
unsigned i = 0; i < NumParts; ++i) {
248 Register CmpReg = MRI.createVirtualRegister(VccRB_S1);
254 CondReg = B.buildAnd(VccRB_S1, CondReg, CmpReg).getReg(0);
257 Op.setReg(CurrentLaneReg);
260 WaterfalledRegMap.
insert(std::pair(OldReg,
Op.getReg()));
266 MRI.createVirtualRegister({WaveRC,
LLT::integer(IsWave32 ? 32 : 64)});
267 B.buildIntrinsic(Intrinsic::amdgcn_ballot, CondRegLM).addReg(CondReg);
274 MRI.setSimpleHint(SavedExec, CondRegLM);
276 B.setInsertPt(*BodyBB, BodyBB->
end());
289 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
293 B.buildInstr(LMC.
MovOpc).addDef(SaveExecReg).addReg(LMC.
ExecReg);
296 B.setInsertPt(*RestoreExecBB, RestoreExecBB->
begin());
301 B.setInsertPt(*RemainderBB, RemainderBB->
begin());
308unsigned RegBankLegalizeHelper::setBufferOffsets(
310 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) {
311 if (std::optional<int64_t>
Imm =
313 uint32_t SOffset, ImmOffset;
314 if (TII.splitMUBUFOffset(*
Imm, SOffset, ImmOffset, Alignment)) {
315 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
316 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
317 InstOffsetVal = ImmOffset;
318 return SOffset + ImmOffset;
321 const bool CheckNUW = ST.hasGFX1250Insts();
323 MRI, CombinedOffset,
nullptr,
325 uint32_t SOffset, ImmOffset;
326 if (
static_cast<int32_t
>(
Offset) > 0 &&
327 TII.splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
328 if (
Base.isValid() && MRI.getRegBank(
Base) == VgprRB) {
330 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
331 InstOffsetVal = ImmOffset;
336 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
338 InstOffsetVal = ImmOffset;
344 if (
Add &&
static_cast<int32_t
>(
Offset) >= 0 &&
348 const RegisterBank *Src0Bank = MRI.getRegBank(Src0);
349 const RegisterBank *Src1Bank = MRI.getRegBank(Src1);
350 if (Src0Bank == VgprRB && Src1Bank == SgprRB) {
355 if (Src0Bank == SgprRB && Src1Bank == VgprRB) {
363 if (MRI.getRegBank(CombinedOffset) == VgprRB) {
364 VOffsetReg = CombinedOffset;
366 VOffsetReg = B.buildCopy(VgprRB_I32, CombinedOffset).getReg(0);
368 SOffsetReg = B.buildConstant(SgprRB_I32, 0).getReg(0);
372bool RegBankLegalizeHelper::splitLoad(MachineInstr &
MI,
375 assert(
MI.getNumMemOperands() == 1);
376 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
378 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
380 LLT PtrTy = MRI.getType(
Base);
381 const RegisterBank *PtrRB = MRI.getRegBankOrNull(
Base);
385 unsigned ByteOffset = 0;
386 for (LLT PartTy : LLTBreakdown) {
388 if (ByteOffset == 0) {
389 BasePlusOffset =
Base;
391 auto Offset = B.buildConstant({PtrRB, OffsetTy}, ByteOffset);
395 auto *OffsetMMO = MF.getMachineMemOperand(&BaseMMO, ByteOffset, PartTy);
396 auto LoadPart = B.buildLoad({DstRB, PartTy}, BasePlusOffset, *OffsetMMO);
397 LoadPartRegs.
push_back(LoadPart.getReg(0));
403 B.buildMergeLikeInstr(Dst, LoadPartRegs);
409 if (MRI.getType(
Reg) == MergeTy) {
412 auto Unmerge = B.buildUnmerge({DstRB, MergeTy},
Reg);
413 for (
unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i)
414 MergeTyParts.
push_back(Unmerge.getReg(i));
417 B.buildMergeLikeInstr(Dst, MergeTyParts);
419 MI.eraseFromParent();
423bool RegBankLegalizeHelper::widenLoad(MachineInstr &
MI, LLT WideTy,
426 assert(
MI.getNumMemOperands() == 1);
427 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
429 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
432 MachineMemOperand *WideMMO = MF.getMachineMemOperand(&BaseMMO, 0, WideTy);
433 auto WideLoad = B.buildLoad({DstRB, WideTy},
Base, *WideMMO);
436 B.buildTrunc(Dst, WideLoad);
439 auto Unmerge = B.buildUnmerge({DstRB, MergeTy}, WideLoad);
441 LLT DstTy = MRI.getType(Dst);
443 for (
unsigned i = 0; i < NumElts; ++i) {
444 MergeTyParts.
push_back(Unmerge.getReg(i));
446 B.buildMergeLikeInstr(Dst, MergeTyParts);
448 MI.eraseFromParent();
452bool RegBankLegalizeHelper::widenMMOToS32(GAnyLoad &
MI)
const {
455 MachineMemOperand &MMO =
MI.getMMO();
458 MachineMemOperand *WideMMO = B.getMF().getMachineMemOperand(&MMO, 0, S32);
460 if (
MI.getOpcode() == G_LOAD) {
461 B.buildLoad(Dst, Ptr, *WideMMO);
463 auto Load = B.buildLoad(SgprRB_I32, Ptr, *WideMMO);
465 if (
MI.getOpcode() == G_ZEXTLOAD) {
467 auto MaskCst = B.buildConstant(SgprRB_I32, Mask);
468 B.buildAnd(Dst,
Load, MaskCst);
470 assert(
MI.getOpcode() == G_SEXTLOAD);
471 B.buildSExtInReg(Dst,
Load, MemSize);
475 MI.eraseFromParent();
479bool RegBankLegalizeHelper::lowerVccExtToSel(MachineInstr &
MI) {
481 LLT Ty = MRI.getType(Dst);
483 unsigned Opc =
MI.getOpcode();
484 int TrueExtCst =
Opc == G_SEXT ? -1 : 1;
485 if (Ty == S32 || Ty == S16) {
486 auto True = B.buildConstant({VgprRB, Ty}, TrueExtCst);
487 auto False = B.buildConstant({VgprRB, Ty}, 0);
489 }
else if (Ty == S64) {
490 auto True = B.buildConstant({VgprRB_I32}, TrueExtCst);
491 auto False = B.buildConstant({VgprRB_I32}, 0);
492 auto Lo = B.buildSelect({VgprRB_I32}, Src,
True,
False);
493 MachineInstrBuilder
Hi;
502 Hi = B.buildUndef({VgprRB_I32});
507 "AMDGPU RegBankLegalize: lowerVccExtToSel, Opcode not supported",
MI);
511 B.buildMergeValues(Dst, {
Lo.getReg(0),
Hi.getReg(0)});
515 "AMDGPU RegBankLegalize: lowerVccExtToSel, Type not supported",
MI);
519 MI.eraseFromParent();
523std::pair<Register, Register> RegBankLegalizeHelper::unpackZExt(
Register Reg) {
524 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
525 auto Mask = B.buildConstant(SgprRB_I32, 0x0000ffff);
526 auto Lo = B.buildAnd(SgprRB_I32, PackedI32, Mask);
527 auto Hi = B.buildLShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
528 return {
Lo.getReg(0),
Hi.getReg(0)};
531std::pair<Register, Register> RegBankLegalizeHelper::unpackSExt(
Register Reg) {
532 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
533 auto Lo = B.buildSExtInReg(SgprRB_I32, PackedI32, 16);
534 auto Hi = B.buildAShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
535 return {
Lo.getReg(0),
Hi.getReg(0)};
538std::pair<Register, Register> RegBankLegalizeHelper::unpackAExt(
Register Reg) {
540 if (MRI.getType(
Reg) != I32)
541 RegI32 = B.buildBitcast(SgprRB_I32,
Reg).getReg(0);
543 auto Hi = B.buildLShr(SgprRB_I32, RegI32, B.buildConstant(SgprRB_I32, 16));
544 return {RegI32,
Hi.getReg(0)};
547std::pair<Register, Register>
548RegBankLegalizeHelper::unpackAExtTruncS16(
Register Reg) {
549 auto [Lo32, Hi32] = unpackAExt(
Reg);
550 LLT EltTy = MRI.getType(
Reg).getElementType();
551 return {B.buildTrunc({SgprRB, EltTy}, Lo32).
getReg(0),
552 B.buildTrunc({SgprRB, EltTy}, Hi32).
getReg(0)};
555bool RegBankLegalizeHelper::lowerUnpackBitShift(MachineInstr &
MI) {
557 switch (
MI.getOpcode()) {
558 case AMDGPU::G_SHL: {
559 auto [Val0, Val1] = unpackAExt(
MI.getOperand(1).getReg());
560 auto [Amt0, Amt1] = unpackAExt(
MI.getOperand(2).getReg());
561 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
562 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
565 case AMDGPU::G_LSHR: {
566 auto [Val0, Val1] = unpackZExt(
MI.getOperand(1).getReg());
567 auto [Amt0, Amt1] = unpackZExt(
MI.getOperand(2).getReg());
568 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
569 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
572 case AMDGPU::G_ASHR: {
573 auto [Val0, Val1] = unpackSExt(
MI.getOperand(1).getReg());
574 auto [Amt0, Amt1] = unpackSExt(
MI.getOperand(2).getReg());
575 Lo = B.buildAShr(SgprRB_I32, Val0, Amt0).getReg(0);
576 Hi = B.buildAShr(SgprRB_I32, Val1, Amt1).getReg(0);
582 "AMDGPU RegBankLegalize: lowerUnpackBitShift, case not implemented",
586 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
587 MI.eraseFromParent();
591bool RegBankLegalizeHelper::lowerUnpackMinMax(MachineInstr &
MI) {
593 switch (
MI.getOpcode()) {
595 case AMDGPU::G_SMAX: {
597 auto [Val0_Lo, Val0_Hi] = unpackSExt(
MI.getOperand(1).getReg());
598 auto [Val1_Lo, Val1_Hi] = unpackSExt(
MI.getOperand(2).getReg());
599 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
601 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
606 case AMDGPU::G_UMAX: {
608 auto [Val0_Lo, Val0_Hi] = unpackZExt(
MI.getOperand(1).getReg());
609 auto [Val1_Lo, Val1_Hi] = unpackZExt(
MI.getOperand(2).getReg());
610 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
612 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
619 "AMDGPU RegBankLegalize: lowerUnpackMinMax, case not implemented",
MI);
622 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
623 MI.eraseFromParent();
627bool RegBankLegalizeHelper::lowerUnpackAExt(MachineInstr &
MI) {
628 auto [Op1Lo, Op1Hi] = unpackAExt(
MI.getOperand(1).getReg());
629 auto [Op2Lo, Op2Hi] = unpackAExt(
MI.getOperand(2).getReg());
630 auto ResLo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Lo, Op2Lo});
631 auto ResHi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Hi, Op2Hi});
632 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
633 {ResLo.getReg(0), ResHi.getReg(0)});
634 MI.eraseFromParent();
638bool RegBankLegalizeHelper::lowerSBufToBuf(MachineInstr &
MI,
641 LLT Ty = MRI.getType(Dst);
642 const RegisterBank *RSrcBank = MRI.getRegBank(
MI.getOperand(1).getReg());
646 if (LoadSize == 256 || LoadSize == 512) {
647 NumLoads = LoadSize / 128;
650 for (
int I = 0;
I < NumLoads; ++
I)
651 LoadParts.
emplace_back(MRI.createVirtualRegister({VgprRB, Ty}));
652 MachineMemOperand *OrigMMO = *
MI.memoperands_begin();
657 int64_t ImmOffset = 0;
658 unsigned MMOOffset = setBufferOffsets(B,
MI.getOperand(2).getReg(), VOffset,
659 SOffset, ImmOffset, Alignment);
661 MachineMemOperand *BaseMMO = MF.getMachineMemOperand(OrigMMO, 0, MemSize);
663 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
667 Register VIndex = B.buildConstant(VgprRB_I32, 0).getReg(0);
668 unsigned CachePolicy =
MI.getOperand(3).getImm();
669 unsigned Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
670 switch (
MI.getOpcode()) {
671 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
672 Opc = G_AMDGPU_BUFFER_LOAD_SBYTE;
674 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
675 Opc = G_AMDGPU_BUFFER_LOAD_UBYTE;
677 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
678 Opc = G_AMDGPU_BUFFER_LOAD_SSHORT;
680 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
681 Opc = G_AMDGPU_BUFFER_LOAD_USHORT;
686 for (
int I = 0;
I < NumLoads; ++
I) {
688 .addDef(LoadParts[
I])
693 .addImm(ImmOffset + 16 *
I)
696 .addMemOperand(MF.getMachineMemOperand(BaseMMO, 16 *
I, MemSize));
699 B.buildCopy(Dst, LoadParts[0]);
701 B.buildMergeLikeInstr(Dst, LoadParts);
702 B.setInstr(*MRI.getVRegDef(LoadParts[0]));
703 if (RSrcBank != SgprRB) {
705 WFI.
Start = MRI.getVRegDef(LoadParts.
front());
706 WFI.
End = std::next(MRI.getVRegDef(LoadParts.
back())->getIterator());
708 MI.eraseFromParent();
714 return (GI->is(Intrinsic::amdgcn_sbfe));
716 return MI.getOpcode() == AMDGPU::G_SBFX;
719bool RegBankLegalizeHelper::lowerV_BFE(MachineInstr &
MI) {
726 Register Src =
MI.getOperand(FirstOpnd).getReg();
727 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
728 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
733 unsigned SHROpc =
Signed ? AMDGPU::G_ASHR : AMDGPU::G_LSHR;
734 auto SHRSrc = B.buildInstr(SHROpc, {VgprRB_I64}, {Src, LSBit});
742 auto Amt = B.buildSub(VgprRB_I32, B.buildConstant(SgprRB_I32, 64), Width);
743 auto SignBit = B.buildShl(VgprRB_I64, SHRSrc, Amt);
744 B.buildInstr(SHROpc, {Dst}, {SignBit, Amt});
745 MI.eraseFromParent();
749 uint64_t WidthImm = ConstWidth->Value.getZExtValue();
750 auto UnmergeSHRSrc = B.buildUnmerge(VgprRB_I32, SHRSrc);
751 Register SHRSrcLo = UnmergeSHRSrc.getReg(0);
752 Register SHRSrcHi = UnmergeSHRSrc.getReg(1);
753 auto Zero = B.buildConstant(VgprRB_I32, 0);
754 unsigned BFXOpc =
Signed ? AMDGPU::G_SBFX : AMDGPU::G_UBFX;
756 if (WidthImm <= 32) {
762 B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcLo,
Zero, Width}).
getReg(0);
764 MachineInstrBuilder
Hi;
767 Hi = B.buildAShr(VgprRB_I32,
Lo, B.buildConstant(VgprRB_I32, 31));
772 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
778 auto Amt = B.buildConstant(VgprRB_I32, WidthImm - 32);
779 Hi = B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcHi,
Zero, Amt}).
getReg(0);
781 B.buildMergeLikeInstr(Dst, {SHRSrcLo,
Hi});
784 MI.eraseFromParent();
788bool RegBankLegalizeHelper::lowerS_BFE(MachineInstr &
MI) {
790 LLT Ty = MRI.getType(DstReg);
793 Register Src =
MI.getOperand(FirstOpnd).getReg();
794 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
795 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
802 auto FieldOffset = B.buildAnd(SgprRB_I32, LSBit, Mask);
803 auto Size = B.buildShl(SgprRB_I32, Width, B.buildConstant(SgprRB_I32, 16));
804 auto Src1 = B.buildOr(SgprRB_I32, FieldOffset,
Size);
805 unsigned Opc32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
806 unsigned Opc64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
807 unsigned Opc = Ty == S32 ? Opc32 : Opc64;
811 auto S_BFE = B.buildInstr(
Opc, {{SgprRB, Ty}},
812 {B.buildCopy(Ty, Src), B.buildCopy(I32, Src1)});
814 *ST.getRegisterInfo(), RBI);
816 B.buildCopy(DstReg,
S_BFE->getOperand(0).getReg());
817 MI.eraseFromParent();
821bool RegBankLegalizeHelper::lowerSplitTo32(MachineInstr &
MI) {
823 LLT DstTy = MRI.getType(Dst);
824 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64);
826 auto Op1 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(1).
getReg());
827 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
828 unsigned Opc =
MI.getOpcode();
831 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(0), Op2.getReg(0)},
Flags);
833 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(1), Op2.getReg(1)},
Flags);
834 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
835 MI.eraseFromParent();
839bool RegBankLegalizeHelper::lowerSplitTo32Mul(MachineInstr &
MI) {
841 assert(MRI.getType(Dst) == S64);
842 auto Op1 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(1).
getReg());
843 auto Op2 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(2).
getReg());
847 auto Lo = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
848 auto Carry = B.buildUMulH(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
849 auto MulLo0Hi1 = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(1));
850 auto MulHi0Lo1 = B.buildMul(VgprRB_I32, Op1.getReg(1), Op2.getReg(0));
851 auto Sum = B.buildAdd(VgprRB_I32, MulLo0Hi1, MulHi0Lo1);
852 auto Hi = B.buildAdd(VgprRB_I32, Sum, Carry);
854 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
855 MI.eraseFromParent();
859bool RegBankLegalizeHelper::lowerSplitTo16(MachineInstr &
MI) {
861 assert(MRI.getType(Dst) == V2S16);
862 unsigned Opc =
MI.getOpcode();
863 unsigned NumOps =
MI.getNumOperands();
866 auto [Op1Lo, Op1Hi] = unpackAExtTruncS16(
MI.getOperand(1).getReg());
870 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo},
Flags);
871 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi},
Flags);
872 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
873 MI.eraseFromParent();
877 auto [Op2Lo, Op2Hi] = unpackAExtTruncS16(
MI.getOperand(2).getReg());
880 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo},
Flags);
881 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi},
Flags);
882 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
883 MI.eraseFromParent();
888 auto [Op3Lo, Op3Hi] = unpackAExtTruncS16(
MI.getOperand(3).getReg());
889 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo, Op3Lo},
Flags);
890 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi, Op3Hi},
Flags);
891 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
892 MI.eraseFromParent();
896bool RegBankLegalizeHelper::lowerUniMAD64(MachineInstr &
MI) {
903 const GCNSubtarget &ST = B.getMF().getSubtarget<GCNSubtarget>();
906 Register DstLo = B.buildMul(SgprRB_I32, Src0, Src1).getReg(0);
907 Register DstHi = MRI.createVirtualRegister(SgprRB_I32);
908 if (ST.hasScalarMulHiInsts()) {
909 B.buildInstr(AMDGPU::G_UMULH, {{DstHi}}, {Src0, Src1});
911 auto VSrc0 = B.buildCopy(VgprRB_I32, Src0);
912 auto VSrc1 = B.buildCopy(VgprRB_I32, Src1);
913 auto MulHi = B.buildInstr(AMDGPU::G_UMULH, {VgprRB_I32}, {VSrc0, VSrc1});
924 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
925 B.buildConstant(Dst1, 0);
928 Register Src2Lo = MRI.createVirtualRegister(SgprRB_I32);
929 Register Src2Hi = MRI.createVirtualRegister(SgprRB_I32);
930 B.buildUnmerge({Src2Lo, Src2Hi}, Src2);
932 auto AddLo = B.buildUAddo(SgprRB_I32, SgprRB_I32, DstLo, Src2Lo);
934 B.buildUAdde(SgprRB_I32, SgprRB_I32, DstHi, Src2Hi, AddLo.getReg(1));
935 B.buildMergeLikeInstr(Dst0, {AddLo.getReg(0), AddHi.getReg(0)});
936 B.buildCopy(Dst1, AddHi.getReg(1));
939 MI.eraseFromParent();
943bool RegBankLegalizeHelper::lowerSplitTo32Select(MachineInstr &
MI) {
945 LLT DstTy = MRI.getType(Dst);
946 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64 ||
949 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
950 auto Op3 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(3).
getReg());
955 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(0), Op3.getReg(0), Flags);
957 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(1), Op3.getReg(1), Flags);
959 B.buildMergeLikeInstr(Dst, {Lo, Hi});
960 MI.eraseFromParent();
964bool RegBankLegalizeHelper::lowerSplitTo32SExtInReg(MachineInstr &
MI) {
965 auto Op1 = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
966 int Amt =
MI.getOperand(2).getImm();
970 auto Freeze = B.buildFreeze(VgprRB_I32, Op1.getReg(0));
973 Lo = Freeze.getReg(0);
976 Lo = B.buildSExtInReg(VgprRB_I32, Freeze, Amt).getReg(0);
979 auto SignExtCst = B.buildConstant(SgprRB_I32, 31);
980 Hi = B.buildAShr(VgprRB_I32,
Lo, SignExtCst).getReg(0);
984 Hi = B.buildSExtInReg(VgprRB_I32, Op1.getReg(1), Amt - 32).getReg(0);
987 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(), {Lo, Hi});
988 MI.eraseFromParent();
992bool RegBankLegalizeHelper::lowerSplitBitCount64To32(MachineInstr &
MI) {
998 unsigned Opc =
MI.getOpcode();
1007 case AMDGPU::G_AMDGPU_FFBH_U32:
1009 AddOpc = AMDGPU::G_UADDSAT;
1010 SearchFromMSB =
true;
1012 case AMDGPU::G_AMDGPU_FFBL_B32:
1014 AddOpc = AMDGPU::G_UADDSAT;
1015 SearchFromMSB =
false;
1017 case AMDGPU::G_CTLZ_ZERO_POISON:
1018 FFBOpc = AMDGPU::G_AMDGPU_FFBH_U32;
1019 AddOpc = AMDGPU::G_ADD;
1020 SearchFromMSB =
true;
1022 case AMDGPU::G_CTTZ_ZERO_POISON:
1023 FFBOpc = AMDGPU::G_AMDGPU_FFBL_B32;
1024 AddOpc = AMDGPU::G_ADD;
1025 SearchFromMSB =
false;
1031 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1038 auto Primary = B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Hi :
Lo});
1040 B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Lo :
Hi});
1042 auto Adjusted = B.buildInstr(AddOpc, {VgprRB_I32},
1043 {Secondary, B.buildConstant(VgprRB_I32, 32)});
1044 B.buildUMin(
MI.getOperand(0).getReg(), Primary, Adjusted);
1046 MI.eraseFromParent();
1050bool RegBankLegalizeHelper::lowerExtrVecEltToSel(MachineInstr &
MI) {
1062 LLT VecTy = MRI.getType(Src);
1065 MachineRegisterInfo::VRegAttrs VgprRB_EltTy = {VgprRB, ScalarTy};
1067 auto Unmerge = B.buildUnmerge(VgprRB_EltTy, Src);
1070 Register PrevSelect = Unmerge.getReg(0);
1071 for (
unsigned I = 1;
I < NumElts; ++
I) {
1072 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1075 B.buildSelect(VgprRB_EltTy, Cmp, Unmerge.getReg(
I), PrevSelect)
1078 B.buildCopy(Dst, PrevSelect);
1080 auto InitUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(0));
1081 Register PrevLo = InitUnmerge.getReg(0);
1082 Register PrevHi = InitUnmerge.getReg(1);
1083 for (
unsigned I = 1;
I < NumElts; ++
I) {
1084 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1086 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(
I));
1087 PrevLo = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(0), PrevLo)
1089 PrevHi = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(1), PrevHi)
1092 B.buildMergeLikeInstr(Dst, {PrevLo, PrevHi});
1096 "AMDGPU RegBankLegalize: ExtrVecEltToSel unsupported element type",
MI);
1100 MI.eraseFromParent();
1104bool RegBankLegalizeHelper::lowerExtrVecEltTo32(MachineInstr &
MI) {
1117 LLT SrcTy = MRI.getType(Src);
1120 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1121 "expected VGPR src and SGPR idx");
1123 auto CastSrc = B.buildBitcast({VgprRB, Vec32Ty}, Src);
1126 auto One = B.buildConstant(SgprRB_I32, 1);
1127 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1128 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1130 auto ExtLo = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxLo);
1131 auto ExtHi = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxHi);
1133 B.buildMergeLikeInstr(Dst, {ExtLo.getReg(0), ExtHi.getReg(0)});
1135 MI.eraseFromParent();
1139bool RegBankLegalizeHelper::lowerInsVecEltToSel(MachineInstr &
MI) {
1152 LLT VecTy = MRI.getType(Src);
1155 const RegisterBank *SrcRB = MRI.getRegBank(Src);
1156 bool IsSGPR = (SrcRB == SgprRB);
1157 SmallVector<Register, 16> Selects;
1161 auto Unmerge = B.buildUnmerge(VgprRB_I32, Src);
1162 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1163 Register EltLo = EltUnmerge.getReg(0);
1164 Register EltHi = EltUnmerge.getReg(1);
1165 for (
unsigned I = 0;
I < NumElts; ++
I) {
1166 auto IdxConst = B.buildConstant(VgprRB_I32,
I);
1169 B.buildSelect(VgprRB_I32, Cmp, EltLo, Unmerge.getReg(2 *
I))
1172 B.buildSelect(VgprRB_I32, Cmp, EltHi, Unmerge.getReg(2 *
I + 1))
1176 auto Vec32 = B.buildBuildVector({VgprRB, Vec32Ty}, Selects);
1177 B.buildBitcast(Dst, Vec32);
1180 MachineRegisterInfo::VRegAttrs SrcRB_EltTy = {SrcRB, ScalarTy};
1181 MachineRegisterInfo::VRegAttrs CmpTy = IsSGPR ? SgprRB_I32 : VccRB_S1;
1182 auto Unmerge = B.buildUnmerge(SrcRB_EltTy, Src);
1183 for (
unsigned I = 0;
I < NumElts; ++
I) {
1184 auto IdxConst = B.buildConstant(SgprRB_I32,
I);
1187 B.buildSelect(SrcRB_EltTy, Cmp, Elt, Unmerge.getReg(
I)).getReg(0));
1189 B.buildMergeLikeInstr(Dst, Selects);
1193 "AMDGPU RegBankLegalize: InsVecEltToSel unsupported element type",
MI);
1197 MI.eraseFromParent();
1201bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &
MI) {
1216 LLT SrcTy = MRI.getType(Src);
1219 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1220 "expected VGPR src and SGPR idx");
1222 MachineRegisterInfo::VRegAttrs VgprRB_Vec32Ty = {VgprRB, Vec32Ty};
1224 auto CastSrc = B.buildBitcast(VgprRB_Vec32Ty, Src);
1225 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1228 auto One = B.buildConstant(SgprRB_I32, 1);
1229 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1230 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1232 auto InsLo = B.buildInsertVectorElement(VgprRB_Vec32Ty, CastSrc,
1233 EltUnmerge.getReg(0), IdxLo);
1234 auto InsHi = B.buildInsertVectorElement(VgprRB_Vec32Ty, InsLo,
1235 EltUnmerge.getReg(1), IdxHi);
1237 B.buildBitcast(Dst, InsHi);
1239 MI.eraseFromParent();
1243bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &
MI) {
1253 LLT Ty = MRI.getType(DstReg);
1259 Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).
getReg(0);
1261 assert((Ty == S32 || Ty == S16) &&
"unexpected type for AbsToNegMax");
1262 Zero = B.buildConstant({VgprRB, Ty}, 0).
getReg(0);
1265 auto Neg = B.buildSub({VgprRB, Ty},
Zero, SrcReg);
1266 B.buildSMax(DstReg, SrcReg, Neg);
1267 MI.eraseFromParent();
1271bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &
MI) {
1281 auto Bitcast = B.buildBitcast({SgprRB_I32},
MI.getOperand(1).
getReg());
1282 auto SextInReg = B.buildSExtInReg({SgprRB_I32},
Bitcast, 16);
1284 B.buildAShr({SgprRB_I32},
Bitcast, B.buildConstant({SgprRB_I32}, 16));
1286 auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {SextInReg});
1287 auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {ShiftHi});
1288 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
1289 {AbsLo.getReg(0), AbsHi.getReg(0)});
1291 MI.eraseFromParent();
1297bool RegBankLegalizeHelper::lowerSetRounding(MachineInstr &
MI) {
1298 Register NewMode =
MI.getOperand(0).getReg();
1303 uint32_t ClampedVal = std::min(
1304 static_cast<uint32_t
>(ConstMode->Value.getZExtValue()),
1307 NewMode = B.buildConstant(SgprRB_I32, DecodedVal).getReg(0);
1311 KnownBits
Known = VT->getKnownBits(NewMode);
1312 const bool UseReducedTable =
Known.countMinLeadingZeros() >= 30;
1316 if (UseReducedTable) {
1318 auto BitTable = B.buildConstant(
1321 auto Two = B.buildConstant(SgprRB_I32, 2);
1322 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, NewMode, Two);
1325 B.buildLShr(SgprRB_I32, BitTable, RoundModeTimesNumBits).getReg(0);
1332 auto NegFour = B.buildConstant(SgprRB_I32, -4);
1333 auto OffsetEnum = B.buildAdd(SgprRB_I32, NewMode, NegFour);
1334 auto IndexVal = B.buildUMin(SgprRB_I32, NewMode, OffsetEnum);
1336 auto Two = B.buildConstant(SgprRB_I32, 2);
1337 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, IndexVal, Two);
1342 B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1345 NewMode = B.buildTrunc(SgprRB_I32, TableValue).getReg(0);
1351 uint32_t BothRoundHwReg =
1355 .addImm(
static_cast<int16_t
>(BothRoundHwReg))
1358 MI.eraseFromParent();
1364bool RegBankLegalizeHelper::lowerGetRounding(MachineInstr &
MI) {
1367 uint32_t BothRoundHwReg =
1370 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {SgprRB_I32},
1372 .addImm(BothRoundHwReg);
1403 auto Two = B.buildConstant(SgprRB_I32, 2);
1404 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, GetReg, Two);
1408 auto TableValue = B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1409 auto TruncTable = B.buildTrunc(SgprRB_I32, TableValue);
1411 auto EntryMask = B.buildConstant(SgprRB_I32, 0xf);
1412 auto TableEntry = B.buildAnd(SgprRB_I32, TruncTable, EntryMask);
1416 auto Four = B.buildConstant(SgprRB_I32, 4);
1417 auto EnumOffset = B.buildAdd(SgprRB_I32, TableEntry, Four);
1418 auto IsStandardMode =
1420 B.buildSelect(Dst, IsStandardMode, TableEntry, EnumOffset);
1422 MI.eraseFromParent();
1426bool RegBankLegalizeHelper::lower(MachineInstr &
MI,
1434 return lowerVccExtToSel(
MI);
1436 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1437 auto True = B.buildConstant({SgprRB, Ty},
1438 MI.getOpcode() == AMDGPU::G_SEXT ? -1 : 1);
1439 auto False = B.buildConstant({SgprRB, Ty}, 0);
1443 B.buildSelect(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg(),
True,
1445 MI.eraseFromParent();
1449 return lowerUnpackBitShift(
MI);
1451 return lowerUnpackMinMax(
MI);
1453 return lowerSplitTo16(
MI);
1455 const RegisterBank *RB = MRI.getRegBank(
MI.getOperand(0).getReg());
1456 MachineInstrBuilder
Hi;
1457 switch (
MI.getOpcode()) {
1458 case AMDGPU::G_ZEXT: {
1459 Hi = B.buildConstant({RB, I32}, 0);
1462 case AMDGPU::G_SEXT: {
1464 auto ShiftAmt = B.buildConstant({RB, I32}, 31);
1465 Hi = B.buildAShr({RB, MRI.getType(
MI.getOperand(1).getReg())},
1466 MI.getOperand(1).
getReg(), ShiftAmt);
1469 case AMDGPU::G_ANYEXT: {
1470 Hi = B.buildUndef({RB, I32});
1475 "AMDGPU RegBankLegalize: Ext32To64, unsuported opcode",
1480 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(),
1481 {MI.getOperand(1).getReg(), Hi});
1482 MI.eraseFromParent();
1486 uint64_t ConstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1487 B.buildConstant(
MI.getOperand(0).getReg(), ConstVal);
1489 MI.eraseFromParent();
1494 LLT Ty = MRI.getType(Src);
1498 Register BoolSrc = MRI.createVirtualRegister({VgprRB, Ty});
1500 auto Src64 = B.buildUnmerge(VgprRB_I32, Src);
1501 auto One = B.buildConstant(VgprRB_I32, 1);
1502 auto AndLo = B.buildAnd(VgprRB_I32, Src64.getReg(0), One);
1503 auto Zero = B.buildConstant(VgprRB_I32, 0);
1504 auto AndHi = B.buildAnd(VgprRB_I32, Src64.getReg(1), Zero);
1505 B.buildMergeLikeInstr(BoolSrc, {AndLo, AndHi});
1507 assert(Ty == S32 || Ty == S16);
1508 auto One = B.buildConstant({VgprRB, Ty}, 1);
1509 B.buildAnd(BoolSrc, Src, One);
1511 auto Zero = B.buildConstant({VgprRB, Ty}, 0);
1513 MI.eraseFromParent();
1517 return lowerV_BFE(
MI);
1519 return lowerS_BFE(
MI);
1521 return lowerUniMAD64(
MI);
1523 B.buildMul(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2));
1524 MI.eraseFromParent();
1528 auto Op1 = B.buildTrunc(VgprRB_I32,
MI.getOperand(1));
1529 auto Op2 = B.buildTrunc(VgprRB_I32,
MI.getOperand(2));
1530 auto Zero = B.buildConstant(VgprRB_I64, 0);
1532 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_AMDGPU_S_MUL_U64_U32
1533 ? AMDGPU::G_AMDGPU_MAD_U64_U32
1534 : AMDGPU::G_AMDGPU_MAD_I64_I32;
1536 B.buildInstr(NewOpc, {
MI.getOperand(0).getReg(), SgprRB_I32},
1538 MI.eraseFromParent();
1542 return lowerSplitTo32(
MI);
1544 return lowerSplitTo32Mul(
MI);
1546 return lowerSplitTo32Select(
MI);
1548 return lowerSplitTo32SExtInReg(
MI);
1550 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1551 auto LoPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(0));
1552 auto HiPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(1));
1554 B.buildAdd(
MI.getOperand(0).getReg(), LoPopCnt, HiPopCnt,
1557 MI.eraseFromParent();
1561 return lowerSBufToBuf(
MI, WFI);
1563 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1574 if (
Size / 128 == 2)
1576 else if (
Size / 128 == 4)
1580 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1586 else if (DstTy == S96)
1587 splitLoad(
MI, {S64, S32}, S32);
1588 else if (DstTy == V3S32)
1589 splitLoad(
MI, {V2S32, S32}, S32);
1590 else if (DstTy == V6S16)
1591 splitLoad(
MI, {V4S16, V2S16}, V2S16);
1594 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1601 const auto &TFI = *ST.getFrameLowering();
1605 "Stack grows upwards for AMDGPU");
1608 Register AllocSize =
MI.getOperand(1).getReg();
1613 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
1614 MI.eraseFromParent();
1616 if (MRI.getRegBank(AllocSize) != SgprRB) {
1617 auto WaveReduction =
1618 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {SgprRB_I32})
1621 AllocSize = WaveReduction.getReg(0);
1624 LLT PtrTy = MRI.getType(Dst);
1626 "Expected 32-bit pointer for stack allocation");
1627 const SIMachineFunctionInfo *
Info = MF.getInfo<SIMachineFunctionInfo>();
1631 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1632 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1635 if (!HasFlatScratch) {
1636 auto WaveSize = B.buildConstant(SgprRB_I32, WavefrontSizeLog2);
1637 AdjustedSize = B.buildShl(SgprRB_I32, AllocSize, WaveSize).getReg(0);
1639 if (Alignment > TFI.getStackAlign()) {
1640 const uint64_t EffectiveAlignment =
1641 Alignment.value() << (HasFlatScratch ? 0 : WavefrontSizeLog2);
1642 auto OldSP = B.buildCopy({SgprRB, PtrTy},
SPReg);
1644 B.buildPtrAdd({SgprRB, PtrTy}, OldSP,
1645 B.buildConstant(SgprRB_I32, EffectiveAlignment - 1));
1647 B.buildPtrMask(Dst, Tmp1, B.buildConstant(SgprRB_I32, Mask));
1649 B.buildCopy(Dst,
SPReg);
1651 auto PtrAdd = B.buildPtrAdd({SgprRB, PtrTy}, Dst, AdjustedSize);
1652 B.buildCopy(
SPReg, PtrAdd);
1656 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1658 widenLoad(
MI, S128);
1659 else if (DstTy == V3S32)
1660 widenLoad(
MI, V4S32, S32);
1661 else if (DstTy == V6S16)
1662 widenLoad(
MI, V8S16, V2S16);
1665 "AMDGPU RegBankLegalize: WidenLoad, unsuported type",
1672 return lowerUnpackAExt(
MI);
1677 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1683 return MRI.getRegBankOrNull(Op.getReg()) == VgprRB;
1685 B.setInstrAndDebugLoc(
MI);
1686 for (
unsigned i =
MI.getNumDefs(); i <
MI.getNumOperands(); ++i) {
1687 MachineOperand &
Op =
MI.getOperand(i);
1691 if (MRI.getRegBank(
Reg) != VgprRB) {
1692 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
1693 Op.setReg(
Copy.getReg(0));
1703 "AMDGPU RegBankLegalize: unmerge not multiple of 32",
1708 B.setInstrAndDebugLoc(
MI);
1711 B.buildUnmerge({SgprRB, V2S16}, Unmerge->
getSourceReg());
1712 for (
unsigned i = 0; i < UnmergeV2S16->getNumDefs(); ++i) {
1713 auto [Dst0I32, Dst1I32] =
1714 unpackAExt(UnmergeV2S16->getOperand(i).getReg());
1715 B.buildTrunc(
MI.getOperand(i * 2).getReg(), Dst0I32);
1716 B.buildTrunc(
MI.getOperand(i * 2 + 1).getReg(), Dst1I32);
1719 auto [Dst0I32, Dst1I32] = unpackAExt(
MI.getOperand(2).getReg());
1720 B.buildTrunc(
MI.getOperand(0).getReg(), Dst0I32);
1721 B.buildTrunc(
MI.getOperand(1).getReg(), Dst1I32);
1724 MI.eraseFromParent();
1729 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
1730 B.setInsertPt(*
MI.getParent(),
MI.getParent()->getFirstNonPHI());
1731 MI.getOperand(0).setReg(NewDst);
1732 B.buildTrunc(Dst, NewDst);
1734 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1742 auto NewUse = B.buildAnyExt(SgprRB_I32,
UseReg);
1743 MI.getOperand(i).setReg(NewUse.getReg(0));
1751 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1756 assert(MRI.getRegBankOrNull(
MI.getOperand(0).getReg()) == VgprRB);
1760 const RegisterBank *RB = MRI.getRegBankOrNull(Op.getReg());
1761 return RB == VgprRB || RB == SgprRB;
1766 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
1771 unsigned RsrcIdx = RSrcIntrin->
RsrcArg +
MI.getNumExplicitDefs() + 1;
1772 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1778 unsigned RsrcIdx =
MI.getNumOperands();
1779 while (RsrcIdx-- >
MI.getNumExplicitDefs()) {
1780 const MachineOperand &
Op =
MI.getOperand(RsrcIdx);
1781 if (
Op.isReg() &&
Op.getReg().isVirtual())
1784 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1787 return lowerSplitBitCount64To32(
MI);
1789 return lowerExtrVecEltToSel(
MI);
1791 return lowerExtrVecEltTo32(
MI);
1793 return lowerInsVecEltToSel(
MI);
1795 return lowerInsVecEltTo32(
MI);
1797 return lowerAbsToNegMax(
MI);
1799 return lowerAbsToS32(
MI);
1801 MI.eraseFromParent();
1804 return lowerSetRounding(
MI);
1806 return lowerGetRounding(
MI);
1929 return isAnyPtr(Ty, 32) ? Ty : LLT();
1932 return isAnyPtr(Ty, 64) ? Ty : LLT();
1935 return isAnyPtr(Ty, 128) ? Ty : LLT();
1975 const SIRegisterInfo *
TRI =
1976 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
1978 if (LLTSize >= 32 &&
TRI->getSGPRClassForBitWidth(LLTSize))
1983 const SIRegisterInfo *
TRI =
1984 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
2107bool RegBankLegalizeHelper::applyMappingDst(
2108 MachineInstr &
MI,
unsigned &OpIdx,
2109 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs) {
2111 for (; OpIdx < MethodIDs.
size(); ++OpIdx) {
2112 if (MethodIDs[OpIdx] ==
None)
2114 MachineOperand &
Op =
MI.getOperand(OpIdx);
2116 LLT Ty = MRI.getType(
Reg);
2117 [[maybe_unused]]
const RegisterBank *RB = MRI.getRegBank(
Reg);
2119 switch (MethodIDs[OpIdx]) {
2159 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2160 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2185 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2186 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2196 Register NewAgprDst = MRI.createVirtualRegister({AgprRB, Ty});
2197 Op.setReg(NewAgprDst);
2198 if (!MRI.use_nodbg_empty(
Reg))
2199 B.buildCopy(
Reg, NewAgprDst);
2204 const RegisterBank *DstRB =
2205 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2208 Register NewDst = MRI.createVirtualRegister({DstRB, Ty});
2210 if (!MRI.use_nodbg_empty(
Reg))
2211 B.buildCopy(
Reg, NewDst);
2218 Register NewDst = MRI.createVirtualRegister(VccRB_S1);
2220 if (!MRI.use_empty(
Reg)) {
2222 B.buildInstr(AMDGPU::G_AMDGPU_COPY_SCC_VCC, {SgprRB_I32}, {NewDst});
2223 B.buildTrunc(
Reg, CopyS32_Vcc);
2228 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2230 Register NewVgprDst16 = MRI.createVirtualRegister({VgprRB, Ty});
2231 Register NewVgprDstI32 = MRI.createVirtualRegister(VgprRB_I32);
2232 Register NewSgprDstI32 = MRI.createVirtualRegister(SgprRB_I32);
2233 Op.setReg(NewVgprDst16);
2234 B.buildAnyExt(NewVgprDstI32, NewVgprDst16);
2236 B.buildTrunc(
Reg, NewSgprDstI32);
2253 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2255 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2256 Op.setReg(NewVgprDst);
2267 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2269 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2270 Op.setReg(NewVgprDst);
2278 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
2280 if (!MRI.use_empty(
Reg))
2281 B.buildTrunc(
Reg, NewDst);
2286 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2288 Op.setReg(MRI.createVirtualRegister({SgprRB, Ty}));
2289 B.buildCopy(
Reg,
Op.getReg());
2295 "AMDGPU RegBankLegalize: missing fast rule ('Div' or 'Uni') for",
MI);
2301 "AMDGPU RegBankLegalize: applyMappingDst, ID not supported",
MI);
2309bool RegBankLegalizeHelper::applyMappingSrc(
2310 MachineInstr &
MI,
unsigned &OpIdx,
2311 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs,
2313 for (
unsigned i = 0; i < MethodIDs.
size(); ++OpIdx, ++i) {
2314 if (MethodIDs[i] ==
None || MethodIDs[i] ==
IntrId || MethodIDs[i] ==
Imm)
2317 MachineOperand &
Op =
MI.getOperand(OpIdx);
2319 LLT Ty = MRI.getType(
Reg);
2320 const RegisterBank *RB = MRI.getRegBank(
Reg);
2322 switch (MethodIDs[i]) {
2325 assert(RB == VccRB || RB == SgprRB);
2327 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2328 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2329 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2330 auto CopyVcc_Scc = B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC,
2331 {VccRB_S1}, {BoolInReg});
2332 Op.setReg(CopyVcc_Scc.getReg(0));
2351 assert(Ty == getTyFromID(MethodIDs[i]));
2352 assert(RB == getRegBankFromID(MethodIDs[i]));
2366 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2367 assert(RB == getRegBankFromID(MethodIDs[i]));
2394 assert(Ty == getTyFromID(MethodIDs[i]));
2396 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2397 Op.setReg(CopyToVgpr.getReg(0));
2413 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2415 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2416 Op.setReg(CopyToVgpr.getReg(0));
2422 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2423 Op.setReg(CopyToVgpr.getReg(0));
2429 auto CopyToAgpr = B.buildCopy({AgprRB, Ty},
Reg);
2430 Op.setReg(CopyToAgpr.getReg(0));
2436 const RegisterBank *SrcRB =
2437 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2439 Op.setReg(B.buildCopy({SrcRB, Ty},
Reg).getReg(0));
2445 assert(Ty == getTyFromID(MethodIDs[i]));
2450 WFI.
End = std::next(
MI.getIterator());
2457 assert(Ty == getTyFromID(MethodIDs[i]));
2463 while (
Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
2468 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
2480 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2484 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2491 assert(Ty == getTyFromID(MethodIDs[i]));
2495 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2505 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2506 Op.setReg(Aext.getReg(0));
2513 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2516 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2517 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2518 Op.setReg(BoolInReg.getReg(0));
2524 auto Sext = B.buildSExt(SgprRB_I32,
Reg);
2525 Op.setReg(Sext.getReg(0));
2531 auto Zext = B.buildZExt(SgprRB_I32,
Reg);
2532 Op.setReg(Zext.getReg(0));
2538 auto Aext = B.buildAnyExt(VgprRB_I32,
Reg);
2539 Op.setReg(Aext.getReg(0));
2546 auto Sext = B.buildSExt(VgprRB_I32,
Reg);
2547 Op.setReg(Sext.getReg(0));
2554 auto Zext = B.buildZExt(VgprRB_I32,
Reg);
2555 Op.setReg(Zext.getReg(0));
2561 "AMDGPU RegBankLegalize: applyMappingSrc, ID not supported",
MI);
2571 unsigned StartOpIdx,
2572 unsigned EndOpIdx) {
2573 for (
unsigned i = StartOpIdx; i <= EndOpIdx; ++i) {
2580bool RegBankLegalizeHelper::applyRegisterBanksVgprWithSgprRsrc(
2581 MachineInstr &
MI,
unsigned RsrcIdx) {
2582 const unsigned NumDefs =
MI.getNumExplicitDefs();
2588 for (
unsigned i = 0; i < NumDefs; ++i) {
2590 if (MRI.getRegBank(
Reg) == VgprRB)
2593 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, MRI.getType(
Reg)});
2594 MI.getOperand(i).setReg(NewVgprDst);
2598 B.setInstrAndDebugLoc(
MI);
2601 for (
unsigned i = NumDefs; i < RsrcIdx; ++i) {
2602 MachineOperand &
Op =
MI.getOperand(i);
2610 if (MRI.getRegBank(
Reg) == VgprRB)
2613 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
2614 Op.setReg(
Copy.getReg(0));
2617 SmallSet<Register, 4> OpsToWaterfall;
2620 for (
unsigned i = RsrcIdx; i <
MI.getNumOperands(); ++i) {
2621 MachineOperand &
Op =
MI.getOperand(i);
2626 if (MRI.getRegBank(
Reg) != SgprRB)
2630 if (!OpsToWaterfall.
empty()) {
2632 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