29#include "llvm/IR/IntrinsicsAMDGPU.h"
31#define DEBUG_TYPE "amdgpu-regbanklegalize"
41 ST(MF.getSubtarget<
GCNSubtarget>()), TII(*ST.getInstrInfo()), B(B),
42 MRI(*B.getMRI()), MUI(MUI), VT(VT), RBI(RBI), MORE(MF, nullptr),
43 RBLRules(RBLRules), IsWave32(ST.isWave32()),
44 SgprRB(&RBI.getRegBank(
AMDGPU::SGPRRegBankID)),
45 VgprRB(&RBI.getRegBank(
AMDGPU::VGPRRegBankID)),
46 AgprRB(&RBI.getRegBank(
AMDGPU::AGPRRegBankID)),
47 VccRB(&RBI.getRegBank(
AMDGPU::VCCRegBankID)) {}
53 "No AMDGPU RegBankLegalize rules defined for opcode",
61 "AMDGPU RegBankLegalize: none of the rules defined with "
62 "'Any' for MI's opcode matched MI",
70 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
80 if (!lower(
MI, *Mapping, WFI))
84 if (!executeInWaterfallLoop(B, WFI))
94 "Waterfall range not initialized");
111 const int OrigRangeSize = std::distance(BeginIt, EndIt);
120 B.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(InitSaveExecReg);
146 MBB.addSuccessor(LoopBB);
149 B.setInsertPt(*LoopBB, LoopBB->
end());
200 auto NewEnd = BodyBB->
end();
201 assert(std::distance(NewBegin, NewEnd) == OrigRangeSize);
214 auto OldVal = WaterfalledRegMap.
find(OldReg);
215 if (OldVal != WaterfalledRegMap.
end()) {
216 Op.setReg(OldVal->second);
229 unsigned OpSize =
OpTy.getSizeInBits();
230 unsigned PartSize = (OpSize % 64 == 0) ? 64 : 32;
232 unsigned NumParts = OpSize / PartSize;
238 CurrentLaneParts.
push_back(CurrentLaneReg);
240 auto UnmergeOp = B.buildUnmerge({VgprRB, PartTy}, OpReg);
241 auto UnmergeCurrLane = B.buildUnmerge({SgprRB, PartTy}, CurrentLaneReg);
242 for (
unsigned i = 0; i < NumParts; ++i) {
244 CurrentLaneParts.
push_back(UnmergeCurrLane.getReg(i));
248 for (
unsigned i = 0; i < NumParts; ++i) {
249 Register CmpReg = MRI.createVirtualRegister(VccRB_S1);
255 CondReg = B.buildAnd(VccRB_S1, CondReg, CmpReg).getReg(0);
258 Op.setReg(CurrentLaneReg);
261 WaterfalledRegMap.
insert(std::pair(OldReg,
Op.getReg()));
267 MRI.createVirtualRegister({WaveRC,
LLT::integer(IsWave32 ? 32 : 64)});
268 B.buildIntrinsic(Intrinsic::amdgcn_ballot, CondRegLM).addReg(CondReg);
274 MRI.setSimpleHint(SavedExec, CondRegLM);
276 B.setInsertPt(*BodyBB, BodyBB->
end());
288 B.buildInstr(AMDGPU::SI_WATERFALL_LOOP).addMBB(LoopBB);
292 B.buildInstr(LMC.
MovOpc).addDef(SaveExecReg).addReg(LMC.
ExecReg);
295 B.setInsertPt(*RestoreExecBB, RestoreExecBB->
begin());
300 B.setInsertPt(*RemainderBB, RemainderBB->
begin());
307unsigned RegBankLegalizeHelper::setBufferOffsets(
309 Register &SOffsetReg, int64_t &InstOffsetVal, Align Alignment) {
310 if (std::optional<int64_t>
Imm =
312 uint32_t SOffset, ImmOffset;
313 if (TII.splitMUBUFOffset(*
Imm, SOffset, ImmOffset, Alignment)) {
314 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
315 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
316 InstOffsetVal = ImmOffset;
317 return SOffset + ImmOffset;
320 const bool CheckNUW = ST.hasGFX1250Insts();
322 MRI, CombinedOffset,
nullptr,
324 uint32_t SOffset, ImmOffset;
325 if (
static_cast<int32_t
>(
Offset) > 0 &&
326 TII.splitMUBUFOffset(
Offset, SOffset, ImmOffset, Alignment)) {
327 if (
Base.isValid() && MRI.getRegBank(
Base) == VgprRB) {
329 SOffsetReg = B.buildConstant(SgprRB_I32, SOffset).getReg(0);
330 InstOffsetVal = ImmOffset;
335 VOffsetReg = B.buildConstant(VgprRB_I32, 0).getReg(0);
337 InstOffsetVal = ImmOffset;
343 if (
Add &&
static_cast<int32_t
>(
Offset) >= 0 &&
347 const RegisterBank *Src0Bank = MRI.getRegBank(Src0);
348 const RegisterBank *Src1Bank = MRI.getRegBank(Src1);
349 if (Src0Bank == VgprRB && Src1Bank == SgprRB) {
354 if (Src0Bank == SgprRB && Src1Bank == VgprRB) {
362 if (MRI.getRegBank(CombinedOffset) == VgprRB) {
363 VOffsetReg = CombinedOffset;
365 VOffsetReg = B.buildCopy(VgprRB_I32, CombinedOffset).getReg(0);
367 SOffsetReg = B.buildConstant(SgprRB_I32, 0).getReg(0);
371bool RegBankLegalizeHelper::splitLoad(MachineInstr &
MI,
374 assert(
MI.getNumMemOperands() == 1);
375 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
377 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
379 LLT PtrTy = MRI.getType(
Base);
380 const RegisterBank *PtrRB = MRI.getRegBankOrNull(
Base);
384 unsigned ByteOffset = 0;
385 for (LLT PartTy : LLTBreakdown) {
387 if (ByteOffset == 0) {
388 BasePlusOffset =
Base;
390 auto Offset = B.buildConstant({PtrRB, OffsetTy}, ByteOffset);
394 auto *OffsetMMO = MF.getMachineMemOperand(&BaseMMO, ByteOffset, PartTy);
395 auto LoadPart = B.buildLoad({DstRB, PartTy}, BasePlusOffset, *OffsetMMO);
396 LoadPartRegs.
push_back(LoadPart.getReg(0));
402 B.buildMergeLikeInstr(Dst, LoadPartRegs);
408 if (MRI.getType(
Reg) == MergeTy) {
411 auto Unmerge = B.buildUnmerge({DstRB, MergeTy},
Reg);
412 for (
unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i)
413 MergeTyParts.
push_back(Unmerge.getReg(i));
416 B.buildMergeLikeInstr(Dst, MergeTyParts);
418 MI.eraseFromParent();
422bool RegBankLegalizeHelper::widenLoad(MachineInstr &
MI, LLT WideTy,
425 assert(
MI.getNumMemOperands() == 1);
426 MachineMemOperand &BaseMMO = **
MI.memoperands_begin();
428 const RegisterBank *DstRB = MRI.getRegBankOrNull(Dst);
431 MachineMemOperand *WideMMO = MF.getMachineMemOperand(&BaseMMO, 0, WideTy);
432 auto WideLoad = B.buildLoad({DstRB, WideTy},
Base, *WideMMO);
435 B.buildTrunc(Dst, WideLoad);
438 auto Unmerge = B.buildUnmerge({DstRB, MergeTy}, WideLoad);
440 LLT DstTy = MRI.getType(Dst);
442 for (
unsigned i = 0; i < NumElts; ++i) {
443 MergeTyParts.
push_back(Unmerge.getReg(i));
445 B.buildMergeLikeInstr(Dst, MergeTyParts);
447 MI.eraseFromParent();
451bool RegBankLegalizeHelper::widenMMOToS32(GAnyLoad &
MI)
const {
454 MachineMemOperand &MMO =
MI.getMMO();
457 MachineMemOperand *WideMMO = B.getMF().getMachineMemOperand(&MMO, 0, S32);
459 if (
MI.getOpcode() == G_LOAD) {
460 B.buildLoad(Dst, Ptr, *WideMMO);
462 auto Load = B.buildLoad(SgprRB_I32, Ptr, *WideMMO);
464 if (
MI.getOpcode() == G_ZEXTLOAD) {
466 auto MaskCst = B.buildConstant(SgprRB_I32, Mask);
467 B.buildAnd(Dst,
Load, MaskCst);
469 assert(
MI.getOpcode() == G_SEXTLOAD);
470 B.buildSExtInReg(Dst,
Load, MemSize);
474 MI.eraseFromParent();
478bool RegBankLegalizeHelper::lowerVccExtToSel(MachineInstr &
MI) {
480 LLT Ty = MRI.getType(Dst);
482 unsigned Opc =
MI.getOpcode();
483 int TrueExtCst =
Opc == G_SEXT ? -1 : 1;
484 if (Ty == S32 || Ty == S16) {
485 auto True = B.buildConstant({VgprRB, Ty}, TrueExtCst);
486 auto False = B.buildConstant({VgprRB, Ty}, 0);
487 B.buildSelect(Dst, Src, True, False);
488 }
else if (Ty == S64) {
489 auto True = B.buildConstant({VgprRB_I32}, TrueExtCst);
490 auto False = B.buildConstant({VgprRB_I32}, 0);
491 auto Lo = B.buildSelect({VgprRB_I32}, Src, True, False);
492 MachineInstrBuilder
Hi;
501 Hi = B.buildUndef({VgprRB_I32});
505 MF, MORE,
"amdgpu-regbanklegalize",
506 "AMDGPU RegBankLegalize: lowerVccExtToSel, Opcode not supported",
MI);
510 B.buildMergeValues(Dst, {
Lo.getReg(0),
Hi.getReg(0)});
513 MF, MORE,
"amdgpu-regbanklegalize",
514 "AMDGPU RegBankLegalize: lowerVccExtToSel, Type not supported",
MI);
518 MI.eraseFromParent();
522std::pair<Register, Register> RegBankLegalizeHelper::unpackZExt(
Register Reg) {
523 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
524 auto Mask = B.buildConstant(SgprRB_I32, 0x0000ffff);
525 auto Lo = B.buildAnd(SgprRB_I32, PackedI32, Mask);
526 auto Hi = B.buildLShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
527 return {
Lo.getReg(0),
Hi.getReg(0)};
530std::pair<Register, Register> RegBankLegalizeHelper::unpackSExt(
Register Reg) {
531 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
532 auto Lo = B.buildSExtInReg(SgprRB_I32, PackedI32, 16);
533 auto Hi = B.buildAShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
534 return {
Lo.getReg(0),
Hi.getReg(0)};
537std::pair<Register, Register> RegBankLegalizeHelper::unpackAExt(
Register Reg) {
538 auto PackedI32 = B.buildBitcast(SgprRB_I32,
Reg);
540 auto Hi = B.buildLShr(SgprRB_I32, PackedI32, B.buildConstant(SgprRB_I32, 16));
541 return {
Lo.getReg(0),
Hi.getReg(0)};
544std::pair<Register, Register>
545RegBankLegalizeHelper::unpackAExtTruncS16(
Register Reg) {
546 auto [Lo32, Hi32] = unpackAExt(
Reg);
547 LLT EltTy = MRI.getType(
Reg).getElementType();
548 return {B.buildTrunc({SgprRB, EltTy}, Lo32).
getReg(0),
549 B.buildTrunc({SgprRB, EltTy}, Hi32).
getReg(0)};
552bool RegBankLegalizeHelper::lowerUnpackBitShift(MachineInstr &
MI) {
554 switch (
MI.getOpcode()) {
555 case AMDGPU::G_SHL: {
556 auto [Val0, Val1] = unpackAExt(
MI.getOperand(1).getReg());
557 auto [Amt0, Amt1] = unpackAExt(
MI.getOperand(2).getReg());
558 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
559 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
562 case AMDGPU::G_LSHR: {
563 auto [Val0, Val1] = unpackZExt(
MI.getOperand(1).getReg());
564 auto [Amt0, Amt1] = unpackZExt(
MI.getOperand(2).getReg());
565 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0, Amt0}).getReg(0);
566 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val1, Amt1}).getReg(0);
569 case AMDGPU::G_ASHR: {
570 auto [Val0, Val1] = unpackSExt(
MI.getOperand(1).getReg());
571 auto [Amt0, Amt1] = unpackSExt(
MI.getOperand(2).getReg());
572 Lo = B.buildAShr(SgprRB_I32, Val0, Amt0).getReg(0);
573 Hi = B.buildAShr(SgprRB_I32, Val1, Amt1).getReg(0);
578 MF, MORE,
"amdgpu-regbanklegalize",
579 "AMDGPU RegBankLegalize: lowerUnpackBitShift, case not implemented",
583 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
584 MI.eraseFromParent();
588bool RegBankLegalizeHelper::lowerUnpackMinMax(MachineInstr &
MI) {
590 switch (
MI.getOpcode()) {
592 case AMDGPU::G_SMAX: {
594 auto [Val0_Lo, Val0_Hi] = unpackSExt(
MI.getOperand(1).getReg());
595 auto [Val1_Lo, Val1_Hi] = unpackSExt(
MI.getOperand(2).getReg());
596 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
598 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
603 case AMDGPU::G_UMAX: {
605 auto [Val0_Lo, Val0_Hi] = unpackZExt(
MI.getOperand(1).getReg());
606 auto [Val1_Lo, Val1_Hi] = unpackZExt(
MI.getOperand(2).getReg());
607 Lo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Lo, Val1_Lo})
609 Hi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Val0_Hi, Val1_Hi})
615 MF, MORE,
"amdgpu-regbanklegalize",
616 "AMDGPU RegBankLegalize: lowerUnpackMinMax, case not implemented",
MI);
619 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(), {Lo, Hi});
620 MI.eraseFromParent();
624bool RegBankLegalizeHelper::lowerUnpackAExt(MachineInstr &
MI) {
625 auto [Op1Lo, Op1Hi] = unpackAExt(
MI.getOperand(1).getReg());
626 auto [Op2Lo, Op2Hi] = unpackAExt(
MI.getOperand(2).getReg());
627 auto ResLo = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Lo, Op2Lo});
628 auto ResHi = B.buildInstr(
MI.getOpcode(), {SgprRB_I32}, {Op1Hi, Op2Hi});
629 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
630 {ResLo.getReg(0), ResHi.getReg(0)});
631 MI.eraseFromParent();
635bool RegBankLegalizeHelper::lowerSBufToBuf(MachineInstr &
MI,
638 LLT Ty = MRI.getType(Dst);
639 const RegisterBank *RSrcBank = MRI.getRegBank(
MI.getOperand(1).getReg());
643 if (LoadSize == 256 || LoadSize == 512) {
644 NumLoads = LoadSize / 128;
647 for (
int I = 0;
I < NumLoads; ++
I)
648 LoadParts.
emplace_back(MRI.createVirtualRegister({VgprRB, Ty}));
649 MachineMemOperand *OrigMMO = *
MI.memoperands_begin();
654 int64_t ImmOffset = 0;
655 unsigned MMOOffset = setBufferOffsets(B,
MI.getOperand(2).getReg(), VOffset,
656 SOffset, ImmOffset, Alignment);
658 MachineMemOperand *BaseMMO = MF.getMachineMemOperand(OrigMMO, 0, MemSize);
660 BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
664 Register VIndex = B.buildConstant(VgprRB_I32, 0).getReg(0);
665 unsigned CachePolicy =
MI.getOperand(3).getImm();
666 unsigned Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
667 switch (
MI.getOpcode()) {
668 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
669 Opc = G_AMDGPU_BUFFER_LOAD_SBYTE;
671 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
672 Opc = G_AMDGPU_BUFFER_LOAD_UBYTE;
674 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
675 Opc = G_AMDGPU_BUFFER_LOAD_SSHORT;
677 case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
678 Opc = G_AMDGPU_BUFFER_LOAD_USHORT;
683 for (
int I = 0;
I < NumLoads; ++
I) {
685 .addDef(LoadParts[
I])
690 .addImm(ImmOffset + 16 *
I)
693 .addMemOperand(MF.getMachineMemOperand(BaseMMO, 16 *
I, MemSize));
696 B.buildCopy(Dst, LoadParts[0]);
698 B.buildMergeLikeInstr(Dst, LoadParts);
699 B.setInstr(*MRI.getVRegDef(LoadParts[0]));
700 if (RSrcBank != SgprRB) {
702 WFI.
Start = MRI.getVRegDef(LoadParts.
front());
703 WFI.
End = std::next(MRI.getVRegDef(LoadParts.
back())->getIterator());
705 MI.eraseFromParent();
711 return (GI->is(Intrinsic::amdgcn_sbfe));
713 return MI.getOpcode() == AMDGPU::G_SBFX;
716bool RegBankLegalizeHelper::lowerV_BFE(MachineInstr &
MI) {
723 Register Src =
MI.getOperand(FirstOpnd).getReg();
724 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
725 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
730 unsigned SHROpc =
Signed ? AMDGPU::G_ASHR : AMDGPU::G_LSHR;
731 auto SHRSrc = B.buildInstr(SHROpc, {VgprRB_I64}, {Src, LSBit});
739 auto Amt = B.buildSub(VgprRB_I32, B.buildConstant(SgprRB_I32, 64), Width);
740 auto SignBit = B.buildShl(VgprRB_I64, SHRSrc, Amt);
741 B.buildInstr(SHROpc, {Dst}, {SignBit, Amt});
742 MI.eraseFromParent();
746 uint64_t WidthImm = ConstWidth->Value.getZExtValue();
747 auto UnmergeSHRSrc = B.buildUnmerge(VgprRB_I32, SHRSrc);
748 Register SHRSrcLo = UnmergeSHRSrc.getReg(0);
749 Register SHRSrcHi = UnmergeSHRSrc.getReg(1);
750 auto Zero = B.buildConstant(VgprRB_I32, 0);
751 unsigned BFXOpc =
Signed ? AMDGPU::G_SBFX : AMDGPU::G_UBFX;
753 if (WidthImm <= 32) {
759 B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcLo,
Zero, Width}).
getReg(0);
761 MachineInstrBuilder
Hi;
764 Hi = B.buildAShr(VgprRB_I32,
Lo, B.buildConstant(VgprRB_I32, 31));
769 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
771 auto Amt = B.buildConstant(VgprRB_I32, WidthImm - 32);
773 auto Hi = B.buildInstr(BFXOpc, {VgprRB_I32}, {SHRSrcHi,
Zero, Amt});
774 B.buildMergeLikeInstr(Dst, {SHRSrcLo,
Hi});
777 MI.eraseFromParent();
781bool RegBankLegalizeHelper::lowerS_BFE(MachineInstr &
MI) {
783 LLT Ty = MRI.getType(DstReg);
786 Register Src =
MI.getOperand(FirstOpnd).getReg();
787 Register LSBit =
MI.getOperand(FirstOpnd + 1).getReg();
788 Register Width =
MI.getOperand(FirstOpnd + 2).getReg();
795 auto FieldOffset = B.buildAnd(SgprRB_I32, LSBit, Mask);
796 auto Size = B.buildShl(SgprRB_I32, Width, B.buildConstant(SgprRB_I32, 16));
797 auto Src1 = B.buildOr(SgprRB_I32, FieldOffset,
Size);
798 unsigned Opc32 =
Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
799 unsigned Opc64 =
Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
800 unsigned Opc = Ty == S32 ? Opc32 : Opc64;
804 auto S_BFE = B.buildInstr(
Opc, {{SgprRB, Ty}},
805 {B.buildCopy(Ty, Src), B.buildCopy(I32, Src1)});
807 *ST.getRegisterInfo(), RBI);
809 B.buildCopy(DstReg,
S_BFE->getOperand(0).getReg());
810 MI.eraseFromParent();
814bool RegBankLegalizeHelper::lowerSplitTo32(MachineInstr &
MI) {
816 LLT DstTy = MRI.getType(Dst);
817 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64);
819 auto Op1 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(1).
getReg());
820 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
821 unsigned Opc =
MI.getOpcode();
824 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(0), Op2.getReg(0)},
Flags);
826 B.buildInstr(
Opc, {{VgprRB, Ty}}, {Op1.getReg(1), Op2.getReg(1)},
Flags);
827 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
828 MI.eraseFromParent();
832bool RegBankLegalizeHelper::lowerSplitTo32Mul(MachineInstr &
MI) {
834 assert(MRI.getType(Dst) == S64);
835 auto Op1 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(1).
getReg());
836 auto Op2 = B.buildUnmerge({VgprRB_I32},
MI.getOperand(2).
getReg());
840 auto Lo = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
841 auto Carry = B.buildUMulH(VgprRB_I32, Op1.getReg(0), Op2.getReg(0));
842 auto MulLo0Hi1 = B.buildMul(VgprRB_I32, Op1.getReg(0), Op2.getReg(1));
843 auto MulHi0Lo1 = B.buildMul(VgprRB_I32, Op1.getReg(1), Op2.getReg(0));
844 auto Sum = B.buildAdd(VgprRB_I32, MulLo0Hi1, MulHi0Lo1);
845 auto Hi = B.buildAdd(VgprRB_I32, Sum, Carry);
847 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
848 MI.eraseFromParent();
852bool RegBankLegalizeHelper::lowerSplitTo16(MachineInstr &
MI) {
854 assert(MRI.getType(Dst) == V2S16);
855 unsigned Opc =
MI.getOpcode();
856 unsigned NumOps =
MI.getNumOperands();
859 auto [Op1Lo, Op1Hi] = unpackAExtTruncS16(
MI.getOperand(1).getReg());
863 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo},
Flags);
864 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi},
Flags);
865 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
866 MI.eraseFromParent();
870 auto [Op2Lo, Op2Hi] = unpackAExtTruncS16(
MI.getOperand(2).getReg());
873 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo},
Flags);
874 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi},
Flags);
875 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
876 MI.eraseFromParent();
881 auto [Op3Lo, Op3Hi] = unpackAExtTruncS16(
MI.getOperand(3).getReg());
882 auto Lo = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Lo, Op2Lo, Op3Lo},
Flags);
883 auto Hi = B.buildInstr(
Opc, {{SgprRB, EltTy}}, {Op1Hi, Op2Hi, Op3Hi},
Flags);
884 B.buildMergeLikeInstr(Dst, {
Lo,
Hi});
885 MI.eraseFromParent();
889bool RegBankLegalizeHelper::lowerUniMAD64(MachineInstr &
MI) {
896 const GCNSubtarget &ST = B.getMF().getSubtarget<GCNSubtarget>();
899 Register DstLo = B.buildMul(SgprRB_I32, Src0, Src1).getReg(0);
900 Register DstHi = MRI.createVirtualRegister(SgprRB_I32);
901 if (ST.hasScalarMulHiInsts()) {
902 B.buildInstr(AMDGPU::G_UMULH, {{DstHi}}, {Src0, Src1});
904 auto VSrc0 = B.buildCopy(VgprRB_I32, Src0);
905 auto VSrc1 = B.buildCopy(VgprRB_I32, Src1);
906 auto MulHi = B.buildInstr(AMDGPU::G_UMULH, {VgprRB_I32}, {VSrc0, VSrc1});
917 B.buildMergeLikeInstr(Dst0, {DstLo, DstHi});
918 B.buildConstant(Dst1, 0);
921 Register Src2Lo = MRI.createVirtualRegister(SgprRB_I32);
922 Register Src2Hi = MRI.createVirtualRegister(SgprRB_I32);
923 B.buildUnmerge({Src2Lo, Src2Hi}, Src2);
925 auto AddLo = B.buildUAddo(SgprRB_I32, SgprRB_I32, DstLo, Src2Lo);
927 B.buildUAdde(SgprRB_I32, SgprRB_I32, DstHi, Src2Hi, AddLo.getReg(1));
928 B.buildMergeLikeInstr(Dst0, {AddLo.getReg(0), AddHi.getReg(0)});
929 B.buildCopy(Dst1, AddHi.getReg(1));
932 MI.eraseFromParent();
936bool RegBankLegalizeHelper::lowerSplitTo32Select(MachineInstr &
MI) {
938 LLT DstTy = MRI.getType(Dst);
939 assert(DstTy == V4S16 || DstTy == V2S32 || DstTy == S64 ||
942 auto Op2 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(2).
getReg());
943 auto Op3 = B.buildUnmerge({VgprRB, Ty},
MI.getOperand(3).
getReg());
947 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(0), Op3.getReg(0), Flags);
949 B.buildSelect({VgprRB, Ty},
Cond, Op2.getReg(1), Op3.getReg(1), Flags);
951 B.buildMergeLikeInstr(Dst, {Lo, Hi});
952 MI.eraseFromParent();
956bool RegBankLegalizeHelper::lowerSplitTo32SExtInReg(MachineInstr &
MI) {
957 auto Op1 = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
958 int Amt =
MI.getOperand(2).getImm();
962 auto Freeze = B.buildFreeze(VgprRB_I32, Op1.getReg(0));
965 Lo = Freeze.getReg(0);
968 Lo = B.buildSExtInReg(VgprRB_I32, Freeze, Amt).getReg(0);
971 auto SignExtCst = B.buildConstant(SgprRB_I32, 31);
972 Hi = B.buildAShr(VgprRB_I32,
Lo, SignExtCst).getReg(0);
976 Hi = B.buildSExtInReg(VgprRB_I32, Op1.getReg(1), Amt - 32).getReg(0);
979 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(), {Lo, Hi});
980 MI.eraseFromParent();
984bool RegBankLegalizeHelper::lowerSplitBitCount64To32(MachineInstr &
MI) {
990 unsigned Opc =
MI.getOpcode();
999 case AMDGPU::G_AMDGPU_FFBH_U32:
1001 AddOpc = AMDGPU::G_UADDSAT;
1002 SearchFromMSB =
true;
1004 case AMDGPU::G_AMDGPU_FFBL_B32:
1006 AddOpc = AMDGPU::G_UADDSAT;
1007 SearchFromMSB =
false;
1009 case AMDGPU::G_CTLZ_ZERO_POISON:
1010 FFBOpc = AMDGPU::G_AMDGPU_FFBH_U32;
1011 AddOpc = AMDGPU::G_ADD;
1012 SearchFromMSB =
true;
1014 case AMDGPU::G_CTTZ_ZERO_POISON:
1015 FFBOpc = AMDGPU::G_AMDGPU_FFBL_B32;
1016 AddOpc = AMDGPU::G_ADD;
1017 SearchFromMSB =
false;
1023 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1030 auto Primary = B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Hi :
Lo});
1032 B.buildInstr(FFBOpc, {VgprRB_I32}, {SearchFromMSB ?
Lo :
Hi});
1034 auto Adjusted = B.buildInstr(AddOpc, {VgprRB_I32},
1035 {Secondary, B.buildConstant(VgprRB_I32, 32)});
1036 B.buildUMin(
MI.getOperand(0).getReg(), Primary, Adjusted);
1038 MI.eraseFromParent();
1042bool RegBankLegalizeHelper::lowerExtrVecEltToSel(MachineInstr &
MI) {
1054 LLT VecTy = MRI.getType(Src);
1057 MachineRegisterInfo::VRegAttrs VgprRB_EltTy = {VgprRB, ScalarTy};
1059 auto Unmerge = B.buildUnmerge(VgprRB_EltTy, Src);
1062 Register PrevSelect = Unmerge.getReg(0);
1063 for (
unsigned I = 1;
I < NumElts; ++
I) {
1064 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1067 B.buildSelect(VgprRB_EltTy, Cmp, Unmerge.getReg(
I), PrevSelect)
1070 B.buildCopy(Dst, PrevSelect);
1072 auto InitUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(0));
1073 Register PrevLo = InitUnmerge.getReg(0);
1074 Register PrevHi = InitUnmerge.getReg(1);
1075 for (
unsigned I = 1;
I < NumElts; ++
I) {
1076 auto IdxConst = B.buildConstant({SgprRB, MRI.getType(Idx)},
I);
1078 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Unmerge.getReg(
I));
1079 PrevLo = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(0), PrevLo)
1081 PrevHi = B.buildSelect(VgprRB_I32, Cmp, EltUnmerge.getReg(1), PrevHi)
1084 B.buildMergeLikeInstr(Dst, {PrevLo, PrevHi});
1087 MF, MORE,
"amdgpu-regbanklegalize",
1088 "AMDGPU RegBankLegalize: ExtrVecEltToSel unsupported element type",
MI);
1092 MI.eraseFromParent();
1096bool RegBankLegalizeHelper::lowerExtrVecEltTo32(MachineInstr &
MI) {
1109 LLT SrcTy = MRI.getType(Src);
1112 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1113 "expected VGPR src and SGPR idx");
1115 auto CastSrc = B.buildBitcast({VgprRB, Vec32Ty}, Src);
1118 auto One = B.buildConstant(SgprRB_I32, 1);
1119 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1120 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1122 auto ExtLo = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxLo);
1123 auto ExtHi = B.buildExtractVectorElement(VgprRB_I32, CastSrc, IdxHi);
1125 B.buildMergeLikeInstr(Dst, {ExtLo.getReg(0), ExtHi.getReg(0)});
1127 MI.eraseFromParent();
1131bool RegBankLegalizeHelper::lowerInsVecEltToSel(MachineInstr &
MI) {
1144 LLT VecTy = MRI.getType(Src);
1147 const RegisterBank *SrcRB = MRI.getRegBank(Src);
1148 bool IsSGPR = (SrcRB == SgprRB);
1149 SmallVector<Register, 16> Selects;
1153 auto Unmerge = B.buildUnmerge(VgprRB_I32, Src);
1154 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1155 Register EltLo = EltUnmerge.getReg(0);
1156 Register EltHi = EltUnmerge.getReg(1);
1157 for (
unsigned I = 0;
I < NumElts; ++
I) {
1158 auto IdxConst = B.buildConstant(VgprRB_I32,
I);
1161 B.buildSelect(VgprRB_I32, Cmp, EltLo, Unmerge.getReg(2 *
I))
1164 B.buildSelect(VgprRB_I32, Cmp, EltHi, Unmerge.getReg(2 *
I + 1))
1168 auto Vec32 = B.buildBuildVector({VgprRB, Vec32Ty}, Selects);
1169 B.buildBitcast(Dst, Vec32);
1172 MachineRegisterInfo::VRegAttrs SrcRB_EltTy = {SrcRB, ScalarTy};
1173 MachineRegisterInfo::VRegAttrs CmpTy = IsSGPR ? SgprRB_I32 : VccRB_S1;
1174 auto Unmerge = B.buildUnmerge(SrcRB_EltTy, Src);
1175 for (
unsigned I = 0;
I < NumElts; ++
I) {
1176 auto IdxConst = B.buildConstant(SgprRB_I32,
I);
1179 B.buildSelect(SrcRB_EltTy, Cmp, Elt, Unmerge.getReg(
I)).getReg(0));
1181 B.buildMergeLikeInstr(Dst, Selects);
1184 MF, MORE,
"amdgpu-regbanklegalize",
1185 "AMDGPU RegBankLegalize: InsVecEltToSel unsupported element type",
MI);
1189 MI.eraseFromParent();
1193bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &
MI) {
1208 LLT SrcTy = MRI.getType(Src);
1211 assert(MRI.getRegBank(Src) == VgprRB && MRI.getRegBank(Idx) == SgprRB &&
1212 "expected VGPR src and SGPR idx");
1214 MachineRegisterInfo::VRegAttrs VgprRB_Vec32Ty = {VgprRB, Vec32Ty};
1216 auto CastSrc = B.buildBitcast(VgprRB_Vec32Ty, Src);
1217 auto EltUnmerge = B.buildUnmerge(VgprRB_I32, Elt);
1220 auto One = B.buildConstant(SgprRB_I32, 1);
1221 auto IdxLo = B.buildShl(SgprRB_I32, Idx, One);
1222 auto IdxHi = B.buildAdd(SgprRB_I32, IdxLo, One);
1224 auto InsLo = B.buildInsertVectorElement(VgprRB_Vec32Ty, CastSrc,
1225 EltUnmerge.getReg(0), IdxLo);
1226 auto InsHi = B.buildInsertVectorElement(VgprRB_Vec32Ty, InsLo,
1227 EltUnmerge.getReg(1), IdxHi);
1229 B.buildBitcast(Dst, InsHi);
1231 MI.eraseFromParent();
1235bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &
MI) {
1245 LLT Ty = MRI.getType(DstReg);
1251 Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).
getReg(0);
1253 assert((Ty == S32 || Ty == S16) &&
"unexpected type for AbsToNegMax");
1254 Zero = B.buildConstant({VgprRB, Ty}, 0).
getReg(0);
1257 auto Neg = B.buildSub({VgprRB, Ty},
Zero, SrcReg);
1258 B.buildSMax(DstReg, SrcReg, Neg);
1259 MI.eraseFromParent();
1263bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &
MI) {
1273 auto Bitcast = B.buildBitcast({SgprRB_I32},
MI.getOperand(1).
getReg());
1274 auto SextInReg = B.buildSExtInReg({SgprRB_I32},
Bitcast, 16);
1276 B.buildAShr({SgprRB_I32},
Bitcast, B.buildConstant({SgprRB_I32}, 16));
1278 auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {SextInReg});
1279 auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB_I32}}, {ShiftHi});
1280 B.buildBuildVectorTrunc(
MI.getOperand(0).getReg(),
1281 {AbsLo.getReg(0), AbsHi.getReg(0)});
1283 MI.eraseFromParent();
1289bool RegBankLegalizeHelper::lowerSetRounding(MachineInstr &
MI) {
1290 Register NewMode =
MI.getOperand(0).getReg();
1295 uint32_t ClampedVal = std::min(
1296 static_cast<uint32_t
>(ConstMode->Value.getZExtValue()),
1299 NewMode = B.buildConstant(SgprRB_I32, DecodedVal).getReg(0);
1303 KnownBits
Known = VT->getKnownBits(NewMode);
1304 const bool UseReducedTable =
Known.countMinLeadingZeros() >= 30;
1308 if (UseReducedTable) {
1310 auto BitTable = B.buildConstant(
1313 auto Two = B.buildConstant(SgprRB_I32, 2);
1314 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, NewMode, Two);
1317 B.buildLShr(SgprRB_I32, BitTable, RoundModeTimesNumBits).getReg(0);
1324 auto NegFour = B.buildConstant(SgprRB_I32, -4);
1325 auto OffsetEnum = B.buildAdd(SgprRB_I32, NewMode, NegFour);
1326 auto IndexVal = B.buildUMin(SgprRB_I32, NewMode, OffsetEnum);
1328 auto Two = B.buildConstant(SgprRB_I32, 2);
1329 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, IndexVal, Two);
1334 B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1337 NewMode = B.buildTrunc(SgprRB_I32, TableValue).getReg(0);
1343 uint32_t BothRoundHwReg =
1347 .addImm(
static_cast<int16_t
>(BothRoundHwReg))
1350 MI.eraseFromParent();
1356bool RegBankLegalizeHelper::lowerGetRounding(MachineInstr &
MI) {
1359 uint32_t BothRoundHwReg =
1362 B.buildIntrinsic(Intrinsic::amdgcn_s_getreg, {SgprRB_I32},
1364 .addImm(BothRoundHwReg);
1395 auto Two = B.buildConstant(SgprRB_I32, 2);
1396 auto RoundModeTimesNumBits = B.buildShl(SgprRB_I32, GetReg, Two);
1400 auto TableValue = B.buildLShr(SgprRB_I64, BitTable, RoundModeTimesNumBits);
1401 auto TruncTable = B.buildTrunc(SgprRB_I32, TableValue);
1403 auto EntryMask = B.buildConstant(SgprRB_I32, 0xf);
1404 auto TableEntry = B.buildAnd(SgprRB_I32, TruncTable, EntryMask);
1408 auto Four = B.buildConstant(SgprRB_I32, 4);
1409 auto EnumOffset = B.buildAdd(SgprRB_I32, TableEntry, Four);
1410 auto IsStandardMode =
1412 B.buildSelect(Dst, IsStandardMode, TableEntry, EnumOffset);
1414 MI.eraseFromParent();
1418bool RegBankLegalizeHelper::lower(MachineInstr &
MI,
1426 return lowerVccExtToSel(
MI);
1428 LLT Ty = MRI.getType(
MI.getOperand(0).getReg());
1429 auto True = B.buildConstant({SgprRB, Ty},
1430 MI.getOpcode() == AMDGPU::G_SEXT ? -1 : 1);
1431 auto False = B.buildConstant({SgprRB, Ty}, 0);
1435 B.buildSelect(
MI.getOperand(0).getReg(),
MI.getOperand(1).getReg(), True,
1437 MI.eraseFromParent();
1441 return lowerUnpackBitShift(
MI);
1443 return lowerUnpackMinMax(
MI);
1445 return lowerSplitTo16(
MI);
1447 const RegisterBank *RB = MRI.getRegBank(
MI.getOperand(0).getReg());
1448 MachineInstrBuilder
Hi;
1449 switch (
MI.getOpcode()) {
1450 case AMDGPU::G_ZEXT: {
1451 Hi = B.buildConstant({RB, I32}, 0);
1454 case AMDGPU::G_SEXT: {
1456 auto ShiftAmt = B.buildConstant({RB, I32}, 31);
1457 Hi = B.buildAShr({RB, MRI.getType(
MI.getOperand(1).getReg())},
1458 MI.getOperand(1).
getReg(), ShiftAmt);
1461 case AMDGPU::G_ANYEXT: {
1462 Hi = B.buildUndef({RB, I32});
1467 "AMDGPU RegBankLegalize: Ext32To64, unsuported opcode",
1472 B.buildMergeLikeInstr(
MI.getOperand(0).getReg(),
1473 {MI.getOperand(1).getReg(), Hi});
1474 MI.eraseFromParent();
1478 uint64_t ConstVal =
MI.getOperand(1).getCImm()->getZExtValue();
1479 B.buildConstant(
MI.getOperand(0).getReg(), ConstVal);
1481 MI.eraseFromParent();
1486 LLT Ty = MRI.getType(Src);
1490 Register BoolSrc = MRI.createVirtualRegister({VgprRB, Ty});
1492 auto Src64 = B.buildUnmerge(VgprRB_I32, Src);
1493 auto One = B.buildConstant(VgprRB_I32, 1);
1494 auto AndLo = B.buildAnd(VgprRB_I32, Src64.getReg(0), One);
1495 auto Zero = B.buildConstant(VgprRB_I32, 0);
1496 auto AndHi = B.buildAnd(VgprRB_I32, Src64.getReg(1), Zero);
1497 B.buildMergeLikeInstr(BoolSrc, {AndLo, AndHi});
1499 assert(Ty == S32 || Ty == S16);
1500 auto One = B.buildConstant({VgprRB, Ty}, 1);
1501 B.buildAnd(BoolSrc, Src, One);
1503 auto Zero = B.buildConstant({VgprRB, Ty}, 0);
1505 MI.eraseFromParent();
1509 return lowerV_BFE(
MI);
1511 return lowerS_BFE(
MI);
1513 return lowerUniMAD64(
MI);
1515 B.buildMul(
MI.getOperand(0),
MI.getOperand(1),
MI.getOperand(2));
1516 MI.eraseFromParent();
1520 auto Op1 = B.buildTrunc(VgprRB_I32,
MI.getOperand(1));
1521 auto Op2 = B.buildTrunc(VgprRB_I32,
MI.getOperand(2));
1522 auto Zero = B.buildConstant(VgprRB_I64, 0);
1524 unsigned NewOpc =
MI.getOpcode() == AMDGPU::G_AMDGPU_S_MUL_U64_U32
1525 ? AMDGPU::G_AMDGPU_MAD_U64_U32
1526 : AMDGPU::G_AMDGPU_MAD_I64_I32;
1528 B.buildInstr(NewOpc, {
MI.getOperand(0).getReg(), SgprRB_I32},
1530 MI.eraseFromParent();
1534 return lowerSplitTo32(
MI);
1536 return lowerSplitTo32Mul(
MI);
1538 return lowerSplitTo32Select(
MI);
1540 return lowerSplitTo32SExtInReg(
MI);
1542 auto Unmerge = B.buildUnmerge(VgprRB_I32,
MI.getOperand(1).getReg());
1543 auto LoPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(0));
1544 auto HiPopCnt = B.buildCTPOP(VgprRB_I32, Unmerge.getReg(1));
1546 B.buildAdd(
MI.getOperand(0).getReg(), LoPopCnt, HiPopCnt,
1549 MI.eraseFromParent();
1553 return lowerSBufToBuf(
MI, WFI);
1555 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1566 if (
Size / 128 == 2)
1568 else if (
Size / 128 == 4)
1572 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1578 else if (DstTy == S96)
1579 splitLoad(
MI, {S64, S32}, S32);
1580 else if (DstTy == V3S32)
1581 splitLoad(
MI, {V2S32, S32}, S32);
1582 else if (DstTy == V6S16)
1583 splitLoad(
MI, {V4S16, V2S16}, V2S16);
1586 "AMDGPU RegBankLegalize: SplitLoad, unsuported type",
1593 const auto &TFI = *ST.getFrameLowering();
1597 "Stack grows upwards for AMDGPU");
1600 Register AllocSize =
MI.getOperand(1).getReg();
1605 B.setInsertPt(*
MI.getParent(), std::next(
MI.getIterator()));
1606 MI.eraseFromParent();
1608 if (MRI.getRegBank(AllocSize) != SgprRB) {
1609 auto WaveReduction =
1610 B.buildIntrinsic(Intrinsic::amdgcn_wave_reduce_umax, {SgprRB_I32})
1613 AllocSize = WaveReduction.getReg(0);
1616 LLT PtrTy = MRI.getType(Dst);
1618 "Expected 32-bit pointer for stack allocation");
1619 const SIMachineFunctionInfo *
Info = MF.getInfo<SIMachineFunctionInfo>();
1623 const bool HasFlatScratch = ST.hasFlatScratchEnabled();
1624 const unsigned WavefrontSizeLog2 = ST.getWavefrontSizeLog2();
1627 if (!HasFlatScratch) {
1628 auto WaveSize = B.buildConstant(SgprRB_I32, WavefrontSizeLog2);
1629 AdjustedSize = B.buildShl(SgprRB_I32, AllocSize, WaveSize).getReg(0);
1631 if (Alignment > TFI.getStackAlign()) {
1632 const uint64_t EffectiveAlignment =
1633 Alignment.
value() << (HasFlatScratch ? 0 : WavefrontSizeLog2);
1634 auto OldSP = B.buildCopy({SgprRB, PtrTy},
SPReg);
1636 B.buildPtrAdd({SgprRB, PtrTy}, OldSP,
1637 B.buildConstant(SgprRB_I32, EffectiveAlignment - 1));
1639 B.buildPtrMask(Dst, Tmp1, B.buildConstant(SgprRB_I32, Mask));
1641 B.buildCopy(Dst,
SPReg);
1643 auto PtrAdd = B.buildPtrAdd({SgprRB, PtrTy}, Dst, AdjustedSize);
1644 B.buildCopy(
SPReg, PtrAdd);
1648 LLT DstTy = MRI.getType(
MI.getOperand(0).getReg());
1650 widenLoad(
MI, S128);
1651 else if (DstTy == V3S32)
1652 widenLoad(
MI, V4S32, S32);
1653 else if (DstTy == V6S16)
1654 widenLoad(
MI, V8S16, V2S16);
1657 "AMDGPU RegBankLegalize: WidenLoad, unsuported type",
1664 return lowerUnpackAExt(
MI);
1669 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1675 return MRI.getRegBankOrNull(Op.getReg()) == VgprRB;
1677 B.setInstrAndDebugLoc(
MI);
1678 for (
unsigned i =
MI.getNumDefs(); i <
MI.getNumOperands(); ++i) {
1679 MachineOperand &
Op =
MI.getOperand(i);
1683 if (MRI.getRegBank(
Reg) != VgprRB) {
1684 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
1685 Op.setReg(
Copy.getReg(0));
1695 "AMDGPU RegBankLegalize: unmerge not multiple of 32",
1700 B.setInstrAndDebugLoc(
MI);
1703 B.buildUnmerge({SgprRB, V2S16}, Unmerge->
getSourceReg());
1704 for (
unsigned i = 0; i < UnmergeV2S16->getNumDefs(); ++i) {
1705 auto [Dst0I32, Dst1I32] =
1706 unpackAExt(UnmergeV2S16->getOperand(i).getReg());
1707 B.buildTrunc(
MI.getOperand(i * 2).getReg(), Dst0I32);
1708 B.buildTrunc(
MI.getOperand(i * 2 + 1).getReg(), Dst1I32);
1711 auto [Dst0I32, Dst1I32] = unpackAExt(
MI.getOperand(2).getReg());
1712 B.buildTrunc(
MI.getOperand(0).getReg(), Dst0I32);
1713 B.buildTrunc(
MI.getOperand(1).getReg(), Dst1I32);
1716 MI.eraseFromParent();
1721 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
1722 B.setInsertPt(*
MI.getParent(),
MI.getParent()->getFirstNonPHI());
1723 MI.getOperand(0).setReg(NewDst);
1724 B.buildTrunc(Dst, NewDst);
1726 for (
unsigned i = 1; i <
MI.getNumOperands(); i += 2) {
1734 auto NewUse = B.buildAnyExt(SgprRB_I32,
UseReg);
1735 MI.getOperand(i).setReg(NewUse.getReg(0));
1743 return MRI.getRegBankOrNull(Op.getReg()) == SgprRB;
1748 assert(MRI.getRegBankOrNull(
MI.getOperand(0).getReg()) == VgprRB);
1752 const RegisterBank *RB = MRI.getRegBankOrNull(Op.getReg());
1753 return RB == VgprRB || RB == SgprRB;
1758 const AMDGPU::RsrcIntrinsic *RSrcIntrin =
1763 unsigned RsrcIdx = RSrcIntrin->
RsrcArg +
MI.getNumExplicitDefs() + 1;
1764 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1770 unsigned RsrcIdx =
MI.getNumOperands();
1771 while (RsrcIdx-- >
MI.getNumExplicitDefs()) {
1772 const MachineOperand &
Op =
MI.getOperand(RsrcIdx);
1773 if (
Op.isReg() &&
Op.getReg().isVirtual())
1776 return applyRegisterBanksVgprWithSgprRsrc(
MI, RsrcIdx);
1779 return lowerSplitBitCount64To32(
MI);
1781 return lowerExtrVecEltToSel(
MI);
1783 return lowerExtrVecEltTo32(
MI);
1785 return lowerInsVecEltToSel(
MI);
1787 return lowerInsVecEltTo32(
MI);
1789 return lowerAbsToNegMax(
MI);
1791 return lowerAbsToS32(
MI);
1793 MI.eraseFromParent();
1796 return lowerSetRounding(
MI);
1798 return lowerGetRounding(
MI);
1921 return isAnyPtr(Ty, 32) ? Ty : LLT();
1924 return isAnyPtr(Ty, 64) ? Ty : LLT();
1927 return isAnyPtr(Ty, 128) ? Ty : LLT();
1967 const SIRegisterInfo *
TRI =
1968 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
1970 if (LLTSize >= 32 &&
TRI->getSGPRClassForBitWidth(LLTSize))
1975 const SIRegisterInfo *
TRI =
1976 static_cast<const SIRegisterInfo *
>(MRI.getTargetRegisterInfo());
2099bool RegBankLegalizeHelper::applyMappingDst(
2100 MachineInstr &
MI,
unsigned &OpIdx,
2101 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs) {
2103 for (; OpIdx < MethodIDs.
size(); ++OpIdx) {
2104 if (MethodIDs[OpIdx] ==
None)
2106 MachineOperand &
Op =
MI.getOperand(OpIdx);
2108 LLT Ty = MRI.getType(
Reg);
2109 [[maybe_unused]]
const RegisterBank *RB = MRI.getRegBank(
Reg);
2111 switch (MethodIDs[OpIdx]) {
2151 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2152 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2177 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2178 assert(RB == getRegBankFromID(MethodIDs[OpIdx]));
2188 Register NewAgprDst = MRI.createVirtualRegister({AgprRB, Ty});
2189 Op.setReg(NewAgprDst);
2190 if (!MRI.use_nodbg_empty(
Reg))
2191 B.buildCopy(
Reg, NewAgprDst);
2196 const RegisterBank *DstRB =
2197 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2200 Register NewDst = MRI.createVirtualRegister({DstRB, Ty});
2202 if (!MRI.use_nodbg_empty(
Reg))
2203 B.buildCopy(
Reg, NewDst);
2210 Register NewDst = MRI.createVirtualRegister(VccRB_S1);
2212 if (!MRI.use_empty(
Reg)) {
2214 B.buildInstr(AMDGPU::G_AMDGPU_COPY_SCC_VCC, {SgprRB_I32}, {NewDst});
2215 B.buildTrunc(
Reg, CopyS32_Vcc);
2220 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2222 Register NewVgprDst16 = MRI.createVirtualRegister({VgprRB, Ty});
2223 Register NewVgprDstI32 = MRI.createVirtualRegister(VgprRB_I32);
2224 Register NewSgprDstI32 = MRI.createVirtualRegister(SgprRB_I32);
2225 Op.setReg(NewVgprDst16);
2226 B.buildAnyExt(NewVgprDstI32, NewVgprDst16);
2228 B.buildTrunc(
Reg, NewSgprDstI32);
2245 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2247 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2248 Op.setReg(NewVgprDst);
2259 assert(Ty == getBTyFromID(MethodIDs[OpIdx], Ty));
2261 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, Ty});
2262 Op.setReg(NewVgprDst);
2270 Register NewDst = MRI.createVirtualRegister(SgprRB_I32);
2272 if (!MRI.use_empty(
Reg))
2273 B.buildTrunc(
Reg, NewDst);
2278 assert(Ty == getTyFromID(MethodIDs[OpIdx]));
2280 Op.setReg(MRI.createVirtualRegister({SgprRB, Ty}));
2281 B.buildCopy(
Reg,
Op.getReg());
2286 MF, MORE,
"amdgpu-regbanklegalize",
2287 "AMDGPU RegBankLegalize: missing fast rule ('Div' or 'Uni') for",
MI);
2292 MF, MORE,
"amdgpu-regbanklegalize",
2293 "AMDGPU RegBankLegalize: applyMappingDst, ID not supported",
MI);
2301bool RegBankLegalizeHelper::applyMappingSrc(
2302 MachineInstr &
MI,
unsigned &OpIdx,
2303 const SmallVectorImpl<RegBankLLTMappingApplyID> &MethodIDs,
2305 for (
unsigned i = 0; i < MethodIDs.
size(); ++OpIdx, ++i) {
2306 if (MethodIDs[i] ==
None || MethodIDs[i] ==
IntrId || MethodIDs[i] ==
Imm)
2309 MachineOperand &
Op =
MI.getOperand(OpIdx);
2311 LLT Ty = MRI.getType(
Reg);
2312 const RegisterBank *RB = MRI.getRegBank(
Reg);
2314 switch (MethodIDs[i]) {
2317 assert(RB == VccRB || RB == SgprRB);
2319 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2320 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2321 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2322 auto CopyVcc_Scc = B.buildInstr(AMDGPU::G_AMDGPU_COPY_VCC_SCC,
2323 {VccRB_S1}, {BoolInReg});
2324 Op.setReg(CopyVcc_Scc.getReg(0));
2343 assert(Ty == getTyFromID(MethodIDs[i]));
2344 assert(RB == getRegBankFromID(MethodIDs[i]));
2358 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2359 assert(RB == getRegBankFromID(MethodIDs[i]));
2386 assert(Ty == getTyFromID(MethodIDs[i]));
2388 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2389 Op.setReg(CopyToVgpr.getReg(0));
2405 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2407 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2408 Op.setReg(CopyToVgpr.getReg(0));
2414 auto CopyToVgpr = B.buildCopy({VgprRB, Ty},
Reg);
2415 Op.setReg(CopyToVgpr.getReg(0));
2421 auto CopyToAgpr = B.buildCopy({AgprRB, Ty},
Reg);
2422 Op.setReg(CopyToAgpr.getReg(0));
2428 const RegisterBank *SrcRB =
2429 MFI->selectAGPRFormMFMA(NumRegs) ? AgprRB : VgprRB;
2431 Op.setReg(B.buildCopy({SrcRB, Ty},
Reg).getReg(0));
2437 assert(Ty == getTyFromID(MethodIDs[i]));
2442 WFI.
End = std::next(
MI.getIterator());
2449 assert(Ty == getTyFromID(MethodIDs[i]));
2455 while (
Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
2460 while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
2472 assert(Ty == getBTyFromID(MethodIDs[i], Ty));
2476 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2483 assert(Ty == getTyFromID(MethodIDs[i]));
2487 Register NewSGPR = MRI.createVirtualRegister({SgprRB, Ty});
2497 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2498 Op.setReg(Aext.getReg(0));
2505 auto Aext = B.buildAnyExt(SgprRB_I32,
Reg);
2508 auto Cst1 = B.buildConstant(SgprRB_I32, 1);
2509 auto BoolInReg = B.buildAnd(SgprRB_I32, Aext, Cst1);
2510 Op.setReg(BoolInReg.getReg(0));
2516 auto Sext = B.buildSExt(SgprRB_I32,
Reg);
2517 Op.setReg(Sext.getReg(0));
2523 auto Zext = B.buildZExt(SgprRB_I32,
Reg);
2524 Op.setReg(Zext.getReg(0));
2530 auto Aext = B.buildAnyExt(VgprRB_I32,
Reg);
2531 Op.setReg(Aext.getReg(0));
2538 auto Sext = B.buildSExt(VgprRB_I32,
Reg);
2539 Op.setReg(Sext.getReg(0));
2546 auto Zext = B.buildZExt(VgprRB_I32,
Reg);
2547 Op.setReg(Zext.getReg(0));
2552 MF, MORE,
"amdgpu-regbanklegalize",
2553 "AMDGPU RegBankLegalize: applyMappingSrc, ID not supported",
MI);
2563 unsigned StartOpIdx,
2564 unsigned EndOpIdx) {
2565 for (
unsigned i = StartOpIdx; i <= EndOpIdx; ++i) {
2572bool RegBankLegalizeHelper::applyRegisterBanksVgprWithSgprRsrc(
2573 MachineInstr &
MI,
unsigned RsrcIdx) {
2574 const unsigned NumDefs =
MI.getNumExplicitDefs();
2576 MachineBasicBlock *
MBB =
MI.getParent();
2580 for (
unsigned i = 0; i < NumDefs; ++i) {
2582 if (MRI.getRegBank(
Reg) == VgprRB)
2585 Register NewVgprDst = MRI.createVirtualRegister({VgprRB, MRI.getType(
Reg)});
2586 MI.getOperand(i).setReg(NewVgprDst);
2590 B.setInstrAndDebugLoc(
MI);
2593 for (
unsigned i = NumDefs; i < RsrcIdx; ++i) {
2594 MachineOperand &
Op =
MI.getOperand(i);
2602 if (MRI.getRegBank(
Reg) == VgprRB)
2605 auto Copy = B.buildCopy({VgprRB, MRI.getType(
Reg)},
Reg);
2606 Op.setReg(
Copy.getReg(0));
2609 SmallSet<Register, 4> OpsToWaterfall;
2612 for (
unsigned i = RsrcIdx; i <
MI.getNumOperands(); ++i) {
2613 MachineOperand &
Op =
MI.getOperand(i);
2618 if (MRI.getRegBank(
Reg) != SgprRB)
2622 if (!OpsToWaterfall.
empty()) {
2624 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.
Provides AMDGPU specific target descriptions.
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.
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
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.