[llvm] [AMDGPU] Emit format opcodes for i8 buffer.{load, store}.format in SDAG (PR #209703)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 03:17:04 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/209703
>From 555706ff2e4d9b9af27c830faf0c45c6d3cf79e2 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 15 Jul 2026 12:16:09 +0200
Subject: [PATCH] [AMDGPU] Reject sub-dword format buffer loads and stores
An i8 buffer.{load,store}.format has no corresponding hardware instruction so diagnose it in SelectionDAG and fail legalization in GlobalISel instead of emitting invalid format opcodes
---
.../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 6 +++++
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 24 +++++++++++++++++++
...mdgcn.struct.ptr.buffer.format.i8.xfail.ll | 20 ++++++++++++++++
3 files changed, 50 insertions(+)
create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.format.i8.xfail.ll
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 2180ce67d576f..55b42fb268cf4 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -6701,6 +6701,9 @@ bool AMDGPULegalizerInfo::legalizeBufferStore(MachineInstr &MI,
const int MemSize = MMO->getSize().getValue();
LLT MemTy = MMO->getMemoryType();
+ if (IsFormat && !IsD16 && MemTy.getSizeInBits() < 32)
+ return false;
+
VData = fixStoreSourceType(B, VData, MemTy, IsFormat);
castBufferRsrcArgToV4I32(MI, B, 2);
@@ -6871,6 +6874,9 @@ bool AMDGPULegalizerInfo::legalizeBufferLoad(MachineInstr &MI,
const bool IsD16 = IsFormat && (EltTy.getSizeInBits() == 16);
const bool Unpacked = ST.hasUnpackedD16VMem();
+ if (IsFormat && !IsD16 && MemTy.getSizeInBits() < 32)
+ return false;
+
std::tie(VOffset, ImmOffset) = splitBufferOffsets(B, VOffset);
unsigned Opc;
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 9cf33b4ccbb87..79dd42e80a0c4 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -7813,6 +7813,13 @@ SDValue SITargetLowering::lowerIntrinsicLoad(MemSDNode *M, bool IsFormat,
bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
+ if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(),
+ "unsupported sub-dword format buffer load", DL.getDebugLoc()));
+ return DAG.getMergeValues({DAG.getPOISON(LoadVT), M->getOperand(0)}, DL);
+ }
+
assert(M->getNumValues() == 2 || M->getNumValues() == 3);
bool IsTFE = M->getNumValues() == 3;
@@ -12371,6 +12378,15 @@ SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
EVT VDataVT = VData.getValueType();
EVT EltType = VDataVT.getScalarType();
bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
+
+ // Sub-dword format stores (i8) do not correspond to any real instruction.
+ if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(),
+ "unsupported sub-dword format buffer store", DL.getDebugLoc()));
+ return Chain;
+ }
+
if (IsD16) {
VData = handleD16VData(VData, DAG);
VDataVT = VData.getValueType();
@@ -12422,6 +12438,14 @@ SDValue SITargetLowering::LowerINTRINSIC_VOID(SDValue Op,
EVT EltType = VDataVT.getScalarType();
bool IsD16 = IsFormat && (EltType.getSizeInBits() == 16);
+ // Sub-dword format stores (i8) do not correspond to any real instruction.
+ if (IsFormat && !IsD16 && EltType.getSizeInBits() < 32) {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(),
+ "unsupported sub-dword format buffer store", DL.getDebugLoc()));
+ return Chain;
+ }
+
if (IsD16) {
VData = handleD16VData(VData, DAG);
VDataVT = VData.getValueType();
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.format.i8.xfail.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.format.i8.xfail.ll
new file mode 100644
index 0000000000000..2dec0c5364449
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.format.i8.xfail.ll
@@ -0,0 +1,20 @@
+; RUN: not llc -mtriple=amdgcn -mcpu=gfx900 -filetype=null %s 2>&1 | FileCheck -check-prefix=SDAG %s
+; RUN: not llc -global-isel -mtriple=amdgcn -mcpu=gfx900 -filetype=null %s 2>&1 | FileCheck -check-prefix=GISEL %s
+
+; An i8 buffer.load.format / buffer.store.format has no corresponding real
+; instruction (no byte-granularity format access exists in hardware), so both
+; SelectionDAG and GlobalISel must refuse to lower it.
+
+; SDAG: error: {{.*}}unsupported sub-dword format buffer load
+define amdgpu_ps float @load_i8(ptr addrspace(8) inreg %rsrc) {
+ %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
+}
+
+; GISEL: LLVM ERROR: unable to legalize instruction
+define amdgpu_ps void @store_i8(ptr addrspace(8) inreg %rsrc, i8 %data, i32 %index) {
+ 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
+}
More information about the llvm-commits
mailing list