[llvm] [AMDGPU] Emit format opcodes for i8 buffer.{load, store}.format in SDAG (PR #209703)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 02:05:52 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Arseniy Obolenskiy (aobolensk)
<details>
<summary>Changes</summary>
Select the format opcodes, matching GlobalISel behavior
Currently they are missing in Selection DAG handling scenario
---
Full diff: https://github.com/llvm/llvm-project/pull/209703.diff
4 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/SIISelLowering.cpp (+14-9)
- (modified) llvm/lib/Target/AMDGPU/SIISelLowering.h (+4-4)
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll (+40)
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.store.format.ll (+11)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 9cf33b4ccbb87..38acddfd7141b 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -7828,7 +7828,7 @@ SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
// Handle BUFFER_LOAD_BYTE/UBYTE/SHORT/USHORT overloaded intrinsics
if (!IsD16 && !LoadVT.isVector() && EltType.getSizeInBits() < 32)
return handleByteShortBufferLoads(DAG, LoadVT, DL, Ops, M->getMemOperand(),
- IsTFE);
+ IsTFE, IsFormat);
if (isTypeLegal(LoadVT)) {
return getMemIntrinsicNode(Opc, DL, M->getVTList(), Ops, IntVT,
@@ -12403,7 +12403,7 @@ SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
// Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
- return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M);
+ return handleByteShortBufferStores(DAG, VDataVT, DL, Ops, M, IsFormat);
return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
M->getMemoryVT(), M->getMemOperand());
@@ -12455,7 +12455,7 @@ SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
// Handle BUFFER_STORE_BYTE/SHORT overloaded intrinsics
EVT VDataType = VData.getValueType().getScalarType();
if (!IsD16 && !VDataVT.isVector() && EltType.getSizeInBits() < 32)
- return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M);
+ return handleByteShortBufferStores(DAG, VDataType, DL, Ops, M, IsFormat);
return DAG.getMemIntrinsicNode(Opc, DL, Op->getVTList(), Ops,
M->getMemoryVT(), M->getMemOperand());
@@ -13022,11 +13022,13 @@ SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
EVT LoadVT, SDLoc DL,
ArrayRef<SDValue> Ops,
MachineMemOperand *MMO,
- bool IsTFE) const {
+ bool IsTFE,
+ bool IsFormat) const {
EVT IntVT = LoadVT.changeTypeToInteger();
if (IsTFE) {
- unsigned Opc = (LoadVT.getScalarType() == MVT::i8)
+ unsigned Opc = IsFormat ? AMDGPUISD::BUFFER_LOAD_FORMAT_TFE
+ : (LoadVT.getScalarType() == MVT::i8)
? AMDGPUISD::BUFFER_LOAD_UBYTE_TFE
: AMDGPUISD::BUFFER_LOAD_USHORT_TFE;
MachineFunction &MF = DAG.getMachineFunction();
@@ -13042,7 +13044,8 @@ SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
return DAG.getMergeValues({Value, Status, SDValue(Op.getNode(), 1)}, DL);
}
- unsigned Opc = LoadVT.getScalarType() == MVT::i8
+ unsigned Opc = IsFormat ? AMDGPUISD::BUFFER_LOAD_FORMAT
+ : LoadVT.getScalarType() == MVT::i8
? AMDGPUISD::BUFFER_LOAD_UBYTE
: AMDGPUISD::BUFFER_LOAD_USHORT;
@@ -13059,14 +13062,16 @@ SDValue SITargetLowering::handleByteShortBufferLoads(SelectionDAG &DAG,
SDValue SITargetLowering::handleByteShortBufferStores(SelectionDAG &DAG,
EVT VDataType, SDLoc DL,
SDValue Ops[],
- MemSDNode *M) const {
+ MemSDNode *M,
+ bool IsFormat) const {
if (VDataType == MVT::f16 || VDataType == MVT::bf16)
Ops[1] = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Ops[1]);
SDValue BufferStoreExt = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Ops[1]);
Ops[1] = BufferStoreExt;
- unsigned Opc = (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
- : AMDGPUISD::BUFFER_STORE_SHORT;
+ unsigned Opc = IsFormat ? AMDGPUISD::BUFFER_STORE_FORMAT
+ : (VDataType == MVT::i8) ? AMDGPUISD::BUFFER_STORE_BYTE
+ : AMDGPUISD::BUFFER_STORE_SHORT;
ArrayRef<SDValue> OpsRef = ArrayRef(&Ops[0], 9);
return DAG.getMemIntrinsicNode(Opc, DL, M->getVTList(), OpsRef, VDataType,
M->getMemOperand());
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index a181fa072d534..1005ad0999d4b 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -313,13 +313,13 @@ class SITargetLowering final : public AMDGPUTargetLowering {
// Handle 8 bit and 16 bit buffer loads
SDValue handleByteShortBufferLoads(SelectionDAG &DAG, EVT LoadVT, SDLoc DL,
ArrayRef<SDValue> Ops,
- MachineMemOperand *MMO,
- bool IsTFE = false) const;
+ MachineMemOperand *MMO, bool IsTFE = false,
+ bool IsFormat = false) const;
// Handle 8 bit and 16 bit buffer stores
SDValue handleByteShortBufferStores(SelectionDAG &DAG, EVT VDataType,
- SDLoc DL, SDValue Ops[],
- MemSDNode *M) const;
+ SDLoc DL, SDValue Ops[], MemSDNode *M,
+ bool IsFormat = false) const;
public:
SITargetLowering(const TargetMachine &tm, const GCNSubtarget &STI);
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll
index 2f319fd8d01f4..31e98ef05416f 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll
@@ -608,6 +608,45 @@ main_body:
ret float %fdata
}
+define amdgpu_ps float @buffer_load_x_i8(ptr addrspace(8) inreg %rsrc) {
+; GFX6-LABEL: buffer_load_x_i8:
+; GFX6: ; %bb.0: ; %main_body
+; GFX6-NEXT: v_mov_b32_e32 v0, 0
+; GFX6-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen
+; GFX6-NEXT: s_waitcnt vmcnt(0)
+; GFX6-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX6-NEXT: ; return to shader part epilog
+;
+; GFX8PLUS-LABEL: buffer_load_x_i8:
+; GFX8PLUS: ; %bb.0: ; %main_body
+; GFX8PLUS-NEXT: v_mov_b32_e32 v0, 0
+; GFX8PLUS-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen
+; GFX8PLUS-NEXT: s_waitcnt vmcnt(0)
+; GFX8PLUS-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX8PLUS-NEXT: ; return to shader part epilog
+;
+; GFX11-LABEL: buffer_load_x_i8:
+; GFX11: ; %bb.0: ; %main_body
+; GFX11-NEXT: v_mov_b32_e32 v0, 0
+; GFX11-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen
+; GFX11-NEXT: s_waitcnt vmcnt(0)
+; GFX11-NEXT: v_and_b32_e32 v0, 0xff, v0
+; GFX11-NEXT: ; return to shader part epilog
+;
+; NOPRT-LABEL: buffer_load_x_i8:
+; NOPRT: ; %bb.0: ; %main_body
+; NOPRT-NEXT: v_mov_b32_e32 v0, 0
+; NOPRT-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen
+; NOPRT-NEXT: s_waitcnt vmcnt(0)
+; NOPRT-NEXT: v_and_b32_e32 v0, 0xff, v0
+; NOPRT-NEXT: ; return to shader part epilog
+main_body:
+ %data = call i8 @llvm.amdgcn.struct.ptr.buffer.load.format.i8(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0)
+ %zext = zext i8 %data to i32
+ %fdata = bitcast i32 %zext to float
+ ret float %fdata
+}
+
define amdgpu_ps <2 x float> @buffer_load_xy(ptr addrspace(8) inreg %rsrc) {
; GFX6-LABEL: buffer_load_xy:
; GFX6: ; %bb.0: ; %main_body
@@ -1117,6 +1156,7 @@ declare float @llvm.amdgcn.struct.ptr.buffer.load.format.f32(ptr addrspace(8), i
declare <2 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v2f32(ptr addrspace(8), i32, i32, i32, i32) #0
declare <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8), i32, i32, i32, i32) #0
declare i32 @llvm.amdgcn.struct.ptr.buffer.load.format.i32(ptr addrspace(8), i32, i32, i32, i32) #0
+declare i8 @llvm.amdgcn.struct.ptr.buffer.load.format.i8(ptr addrspace(8), i32, i32, i32, i32) #0
declare { <4 x i32>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v4i32i32s(ptr addrspace(8), i32, i32, i32, i32 immarg) #0
declare { <4 x float>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v4f32i32s(ptr addrspace(8), i32, i32, i32, i32 immarg) #0
declare { <3 x i32>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v3i32i32s(ptr addrspace(8), i32, i32, i32, i32 immarg) #0
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.store.format.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.store.format.ll
index 51840ae5ba1f8..6ce7dff66a1a7 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.store.format.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.store.format.ll
@@ -118,6 +118,16 @@ main_body:
ret void
}
+define amdgpu_ps void @buffer_store_x1_i8(ptr addrspace(8) inreg %rsrc, i8 %data, i32 %index) {
+; CHECK-LABEL: buffer_store_x1_i8:
+; CHECK: ; %bb.0: ; %main_body
+; CHECK-NEXT: buffer_store_format_x v0, v1, s[0:3], 0 idxen
+; CHECK-NEXT: s_endpgm
+main_body:
+ call void @llvm.amdgcn.struct.ptr.buffer.store.format.i8(i8 %data, ptr addrspace(8) %rsrc, i32 %index, i32 0, i32 0, i32 0)
+ ret void
+}
+
define amdgpu_ps void @buffer_store_x2(ptr addrspace(8) inreg %rsrc, <2 x float> %data, i32 %index) {
; CHECK-LABEL: buffer_store_x2:
; CHECK: ; %bb.0: ; %main_body
@@ -132,6 +142,7 @@ declare void @llvm.amdgcn.struct.ptr.buffer.store.format.f32(float, ptr addrspac
declare void @llvm.amdgcn.struct.ptr.buffer.store.format.v2f32(<2 x float>, ptr addrspace(8), i32, i32, i32, i32) #0
declare void @llvm.amdgcn.struct.ptr.buffer.store.format.v4f32(<4 x float>, ptr addrspace(8), i32, i32, i32, i32) #0
declare void @llvm.amdgcn.struct.ptr.buffer.store.format.i32(i32, ptr addrspace(8), i32, i32, i32, i32) #0
+declare void @llvm.amdgcn.struct.ptr.buffer.store.format.i8(i8, ptr addrspace(8), i32, i32, i32, i32) #0
declare <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8), i32, i32, i32, i32) #1
attributes #0 = { nounwind }
``````````
</details>
https://github.com/llvm/llvm-project/pull/209703
More information about the llvm-commits
mailing list