[llvm] [AMDGPU][GlobalIsel] Add RegBankLegalize rules and lowering for G_AMDGPU_S_BUFFER_LOAD (PR #192480)
Petar Avramovic via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 10:21:08 PDT 2026
================
@@ -1205,6 +1272,109 @@ bool RegBankLegalizeHelper::lower(MachineInstr &MI,
return lowerSplitTo32Select(MI);
case SplitTo32SExtInReg:
return lowerSplitTo32SExtInReg(MI);
+ case S_BUF_to_BUF: {
+ Register Dst = MI.getOperand(0).getReg();
+ LLT Ty = MRI.getType(Dst);
+ const RegisterBank *RSrcBank = MRI.getRegBank(MI.getOperand(1).getReg());
+ // FIXME: 96-bit case was widened during legalize. We need to narrow it
+ // back here but don't have an MMO.
+ unsigned LoadSize = Ty.getSizeInBits();
+ int NumLoads = 1;
+ if (LoadSize == 256 || LoadSize == 512) {
+ NumLoads = LoadSize / 128;
+ Ty = Ty.divide(NumLoads);
+ }
+ // Use the alignment to ensure that the required offsets will fit into the
+ // immediate offsets.
+ const Align Alignment = NumLoads > 1 ? Align(16 * NumLoads) : Align(1);
+ MachineFunction &MF = B.getMF();
+ Register SOffset;
+ Register VOffset;
+ int64_t ImmOffset = 0;
+ unsigned MMOOffset = setBufferOffsets(B, MI.getOperand(2).getReg(), VOffset,
+ SOffset, ImmOffset, Alignment);
+ // TODO: 96-bit loads were widened to 128-bit results. Shrink the
+ // result if we can, but we need to track an MMO for that.
+ // const unsigned MemSize = (Ty.getSizeInBits() + 7) / 8;
+ const unsigned MemSize = divideCeil(Ty.getSizeInBits(), 8);
+ const DataLayout DL = MF.getDataLayout();
+ Type *IRTy = getTypeForLLT(Ty, MF.getFunction().getContext());
+ const Align MemAlign(DL.getABITypeAlign(IRTy));
+ MachineMemOperand *BaseMMO = MF.getMachineMemOperand(
+ MachinePointerInfo(),
+ MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
+ MachineMemOperand::MOInvariant,
+ MemSize, MemAlign);
+ if (MMOOffset != 0)
+ BaseMMO = MF.getMachineMemOperand(BaseMMO, MMOOffset, MemSize);
+ // If only the offset is divergent, emit a MUBUF buffer load
+ // instead. We can assume that the buffer is unswizzled.
+ Register RSrc = MI.getOperand(1).getReg();
+ Register VIndex = B.buildConstant(S32, 0).getReg(0);
+ B.getMRI()->setRegBank(VIndex, *VgprRB);
+ SmallVector<Register, 4> LoadParts(NumLoads);
+ MachineBasicBlock::iterator MII = MI.getIterator();
+ MachineInstrSpan Span(MII, &B.getMBB());
+ unsigned Opc = AMDGPU::G_AMDGPU_BUFFER_LOAD;
+ switch (MI.getOpcode()) {
+ case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SBYTE:
+ Opc = G_AMDGPU_BUFFER_LOAD_SBYTE;
+ break;
+ case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE:
+ Opc = G_AMDGPU_BUFFER_LOAD_UBYTE;
+ break;
+ case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_SSHORT:
+ Opc = G_AMDGPU_BUFFER_LOAD_SSHORT;
+ break;
+ case AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT:
+ Opc = G_AMDGPU_BUFFER_LOAD_USHORT;
+ break;
+ default:
+ break;
+ }
+ for (int i = 0; i < NumLoads; ++i) {
+ if (NumLoads == 1) {
+ LoadParts[i] = Dst;
+ } else {
+ LoadParts[i] = MRI.createGenericVirtualRegister(Ty);
+ MRI.setRegBank(LoadParts[i], *VgprRB);
+ }
+ if (i != 0)
+ BaseMMO = MF.getMachineMemOperand(BaseMMO, 16, MemSize);
+ B.buildInstr(Opc)
+ .addDef(LoadParts[i]) // vdata
+ .addUse(RSrc) // rsrc
+ .addUse(VIndex) // vindex
+ .addUse(VOffset) // voffset
+ .addUse(SOffset) // soffset
+ .addImm(ImmOffset + 16 * i) // offset(imm)
+ .addImm(0) // cachepolicy, swizzled buffer(imm)
+ .addImm(0) // idxen(imm)
+ .addMemOperand(BaseMMO);
+ }
+ // TODO: If only the resource is a VGPR, it may be better to execute the
+ // scalar load in the waterfall loop if the resource is expected to
+ // frequently be dynamically uniform.
+ if (RSrcBank != SgprRB) {
+ // Remove the original instruction to avoid potentially confusing the
+ // waterfall loop logic.
+ B.setInstr(*Span.begin());
+ MI.eraseFromParent();
+ SmallSet<Register, 4> OpsToWaterfall;
+ OpsToWaterfall.insert(RSrc);
+ executeInWaterfallLoop(B, {OpsToWaterfall, Span.begin(), Span.end()});
+ }
+ if (NumLoads != 1) {
+ if (Ty.isVector())
+ B.buildConcatVectors(Dst, LoadParts);
+ else
----------------
petar-avramovic wrote:
buildMergeLikeInstr does this already
https://github.com/llvm/llvm-project/pull/192480
More information about the llvm-commits
mailing list