[llvm] 9bf40ce - [AMDGPU] Fix s_buffer_load crash for illegal result types (#215483)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 13 13:57:55 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-09-13T22:57:50+02:00
New Revision: 9bf40ce33523745e19328924593134e4510bfa5f
URL: https://github.com/llvm/llvm-project/commit/9bf40ce33523745e19328924593134e4510bfa5f
DIFF: https://github.com/llvm/llvm-project/commit/9bf40ce33523745e19328924593134e4510bfa5f.diff
LOG: [AMDGPU] Fix s_buffer_load crash for illegal result types (#215483)
i1, i4, v2i1, v3i16, v6i8, and i128 had no SBUFFER_LOAD selection
pattern and crashed
Load a legal i32/vNi32 carrier instead and narrow/bitcast down to the
requested type
Added:
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ptr.s.buffer.load.illegal-types.ll
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.buffer.load.illegal-types.ll
Modified:
llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
llvm/lib/Target/AMDGPU/SIISelLowering.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 397755a43854a..6ca65e6fa01af 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -7776,8 +7776,22 @@ bool AMDGPULegalizerInfo::legalizeSBufferLoad(LegalizerHelper &Helper,
unsigned Size = Ty.getSizeInBits();
MachineFunction &MF = B.getMF();
bool HasMMO = !MI.memoperands_empty();
+
+ // S_BUFFER_LOAD only produces values that fill whole SGPRs, apart from the
+ // subword loads below. Those truncate from an s32 result, so they need a
+ // scalar destination.
+ bool IsSubwordLoad = Ty.isScalar() && Size < 32 && ST.hasScalarSubwordLoads();
+ if (Size % 32 != 0 && !IsSubwordLoad) {
+ const Function &Fn = MF.getFunction();
+ Fn.getContext().diagnose(DiagnosticInfoUnsupported(
+ Fn, "unsupported s_buffer_load result type", MI.getDebugLoc()));
+ B.buildUndef(OrigDst);
+ MI.eraseFromParent();
+ return true;
+ }
+
unsigned Opc = 0;
- if (Size < 32 && ST.hasScalarSubwordLoads()) {
+ if (IsSubwordLoad) {
assert(Size == 8 || Size == 16);
Opc = Size == 8 ? AMDGPU::G_AMDGPU_S_BUFFER_LOAD_UBYTE
: AMDGPU::G_AMDGPU_S_BUFFER_LOAD_USHORT;
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 95c951c5cb2b1..3efb257091759 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -1070,6 +1070,22 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
MVT::i16, MVT::bf16, MVT::i8, MVT::i128},
Custom);
+ // The s_buffer_load intrinsics accept any result type in IR, but only a few
+ // of them can be selected. Mark the remaining illegal result types Custom so
+ // ReplaceNodeResults gets a chance to diagnose them instead of letting the
+ // type legalizer abort. Its INTRINSIC_WO_CHAIN case dispatches on the
+ // intrinsic ID, but INTRINSIC_W_CHAIN does not, so remember the types added
+ // here to keep other chained intrinsics on generic legalization.
+ for (MVT VT : MVT::all_valuetypes()) {
+ if (VT.isScalableVector() || isTypeLegal(VT))
+ continue;
+ setOperationAction(ISD::INTRINSIC_WO_CHAIN, VT, Custom);
+ if (getOperationAction(ISD::INTRINSIC_W_CHAIN, VT) != Custom) {
+ setOperationAction(ISD::INTRINSIC_W_CHAIN, VT, Custom);
+ SBufferLoadDiagnosticVTs.set(VT.SimpleTy);
+ }
+ }
+
setOperationAction(ISD::INTRINSIC_VOID,
{MVT::Other, MVT::v2i16, MVT::v2f16, MVT::v2bf16,
MVT::v3i16, MVT::v3f16, MVT::v4f16, MVT::v4i16,
@@ -8499,53 +8515,11 @@ void SITargetLowering::ReplaceNodeResults(SDNode *N,
return;
}
case Intrinsic::amdgcn_s_buffer_load: {
- // Lower llvm.amdgcn.s.buffer.load.(i8, u8) intrinsics. First, we generate
- // s_buffer_load_u8 for signed and unsigned load instructions. Next, DAG
- // combiner tries to merge the s_buffer_load_u8 with a sext instruction
- // (performSignExtendInRegCombine()) and it replaces s_buffer_load_u8 with
- // s_buffer_load_i8.
- if (!Subtarget->hasScalarSubwordLoads())
- return;
SDValue Op = SDValue(N, 0);
- SDValue Rsrc = Op.getOperand(1);
- SDValue Offset = Op.getOperand(2);
- SDValue CachePolicy = Op.getOperand(3);
EVT VT = Op.getValueType();
- assert(VT == MVT::i8 && "Expected 8-bit s_buffer_load intrinsics.\n");
- SDLoc DL(Op);
- MachineFunction &MF = DAG.getMachineFunction();
- const DataLayout &DataLayout = DAG.getDataLayout();
- Align Alignment =
- DataLayout.getABITypeAlign(VT.getTypeForEVT(*DAG.getContext()));
- MachineMemOperand *MMO = MF.getMachineMemOperand(
- MachinePointerInfo(),
- MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
- MachineMemOperand::MOInvariant,
- VT.getStoreSize(), Alignment);
- SDValue LoadVal;
- if (!Offset->isDivergent()) {
- SDValue Ops[] = {DAG.getEntryNode(), // Chain
- Rsrc, // source register
- Offset, CachePolicy};
- SDValue BufferLoad = DAG.getMemIntrinsicNode(
- AMDGPUISD::SBUFFER_LOAD_UBYTE, DL,
- DAG.getVTList(MVT::i32, MVT::Other), Ops, VT, MMO);
- LoadVal = DAG.getNode(ISD::TRUNCATE, DL, VT, BufferLoad);
- } else {
- SDValue Ops[] = {
- DAG.getEntryNode(), // Chain
- Rsrc, // rsrc
- DAG.getConstant(0, DL, MVT::i32), // vindex
- {}, // voffset
- {}, // soffset
- {}, // offset
- CachePolicy, // cachepolicy
- DAG.getTargetConstant(0, DL, MVT::i1), // idxen
- };
- setBufferOffsets(Offset, DAG, &Ops[3], Align(4));
- LoadVal = handleByteShortBufferLoads(DAG, VT, DL, Ops, MMO);
- }
- Results.push_back(LoadVal);
+ Results.push_back(lowerSBuffer(VT, VT, SDLoc(Op), DAG.getEntryNode(),
+ Op.getOperand(1), Op.getOperand(2),
+ Op.getOperand(3), DAG));
return;
}
case Intrinsic::amdgcn_dead: {
@@ -8557,6 +8531,10 @@ void SITargetLowering::ReplaceNodeResults(SDNode *N,
break;
}
case ISD::INTRINSIC_W_CHAIN: {
+ if (N->getConstantOperandVal(1) != Intrinsic::amdgcn_ptr_s_buffer_load &&
+ N->getValueType(0).isSimple() &&
+ SBufferLoadDiagnosticVTs[N->getSimpleValueType(0).SimpleTy])
+ break;
if (SDValue Res = LowerINTRINSIC_W_CHAIN(SDValue(N, 0), DAG)) {
if (Res.getOpcode() == ISD::MERGE_VALUES) {
// FIXME: Hacky
@@ -10896,6 +10874,19 @@ SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
MachineFunction &MF = DAG.getMachineFunction();
bool HasChainResult = MMO != nullptr;
+ // SBUFFER_LOAD only produces values that fill whole SGPRs, apart from the
+ // subword loads below.
+ bool IsSubwordLoad = (MemVT == MVT::i8 || MemVT == MVT::i16) &&
+ Subtarget->hasScalarSubwordLoads();
+ if ((!isTypeLegal(VT) || VT.getSizeInBits() % 32 != 0) && !IsSubwordLoad) {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ MF.getFunction(), "unsupported s_buffer_load result type",
+ DL.getDebugLoc()));
+ EVT ResultTypes[] = {VT, MVT::Other};
+ return DAG.getErrorMergeValues(
+ ArrayRef(ResultTypes, HasChainResult ? 2 : 1), Chain, DL);
+ }
+
if (!HasChainResult) {
const DataLayout &DataLayout = DAG.getDataLayout();
Align Alignment =
@@ -10931,8 +10922,9 @@ SDValue SITargetLowering::lowerSBuffer(EVT VT, EVT MemVT, SDLoc DL,
if (MemVT == MVT::i16 && Subtarget->hasScalarSubwordLoads())
return HandleScalarSubwordLoads(AMDGPUISD::SBUFFER_LOAD_USHORT);
- // Widen vec3 load to vec4.
+ // Widen vec3 load to vec4. Only 32-bit elements have a vec4 pattern.
if (VT.isVector() && VT.getVectorNumElements() == 3 &&
+ VT.getVectorElementType().getSizeInBits() == 32 &&
!Subtarget->hasScalarDwordx3Loads()) {
EVT WidenedVT =
EVT::getVectorVT(*DAG.getContext(), VT.getVectorElementType(), 4);
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h
index 421954ebf3363..fc52aa4eeb5a4 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.h
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h
@@ -19,6 +19,7 @@
#include "SIDefines.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include <bitset>
namespace llvm {
@@ -34,6 +35,11 @@ class SITargetLowering final : public AMDGPUTargetLowering {
private:
const GCNSubtarget *Subtarget;
+ /// Result types made Custom for ISD::INTRINSIC_W_CHAIN only so that
+ /// unsupported s_buffer_load result types can be diagnosed. Any other
+ /// intrinsic returning one of these must keep using generic legalization.
+ std::bitset<MVT::VALUETYPE_SIZE> SBufferLoadDiagnosticVTs;
+
public:
MVT getRegisterTypeForCallingConv(LLVMContext &Context,
CallingConv::ID CC,
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ptr.s.buffer.load.illegal-types.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ptr.s.buffer.load.illegal-types.ll
new file mode 100644
index 0000000000000..64430382ec1bf
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ptr.s.buffer.load.illegal-types.ll
@@ -0,0 +1,101 @@
+; RUN: not llc -mtriple=amdgpu9.00-amd-amdhsa -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,SDAG
+; RUN: not llc -global-isel=1 -mtriple=amdgpu9.00-amd-amdhsa -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GISEL
+; RUN: not llc -mtriple=amdgpu11.00-amd-amdhsa -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,SDAG
+; RUN: not llc -global-isel=1 -mtriple=amdgpu11.00-amd-amdhsa -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GISEL
+
+; There is no s_buffer_load for these result types.
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_i1 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i1(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call i1 @llvm.amdgcn.ptr.s.buffer.load.i1(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i1 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_i4 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i4(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call i4 @llvm.amdgcn.ptr.s.buffer.load.i4(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i4 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_i2 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i2(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call i2 @llvm.amdgcn.ptr.s.buffer.load.i2(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i2 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_v3i8 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_v3i8(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call <3 x i8> @llvm.amdgcn.ptr.s.buffer.load.v3i8(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store <3 x i8> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_v2i1 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_v2i1(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call <2 x i1> @llvm.amdgcn.ptr.s.buffer.load.v2i1(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store <2 x i1> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_v3i16 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_v3i16(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call <3 x i16> @llvm.amdgcn.ptr.s.buffer.load.v3i16(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store <3 x i16> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_v3f16 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_v3f16(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call <3 x half> @llvm.amdgcn.ptr.s.buffer.load.v3f16(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store <3 x half> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_v6i8 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_v6i8(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call <6 x i8> @llvm.amdgcn.ptr.s.buffer.load.v6i8(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store <6 x i8> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; i128 is illegal for SelectionDAG, but GlobalISel selects s_buffer_load_b128.
+; GISEL-NOT: in function {{.*}}_i128
+; SDAG: error: {{.*}} in function ptr_s_buffer_load_i128 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i128(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call i128 @llvm.amdgcn.ptr.s.buffer.load.i128(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i128 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_i8 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i8(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call i8 @llvm.amdgcn.ptr.s.buffer.load.i8(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i8 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_i16 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i16(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc, i32 inreg %offset) {
+ %load = call i16 @llvm.amdgcn.ptr.s.buffer.load.i16(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i16 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_i1_divergent {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_i1_divergent(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc) {
+ %offset = call i32 @llvm.amdgcn.workitem.id.x()
+ %load = call i1 @llvm.amdgcn.ptr.s.buffer.load.i1(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store i1 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function ptr_s_buffer_load_v6i8_divergent {{.*}}: unsupported s_buffer_load result type
+define amdgpu_kernel void @ptr_s_buffer_load_v6i8_divergent(ptr addrspace(1) %out, ptr addrspace(8) inreg %rsrc) {
+ %offset = call i32 @llvm.amdgcn.workitem.id.x()
+ %load = call <6 x i8> @llvm.amdgcn.ptr.s.buffer.load.v6i8(ptr addrspace(8) %rsrc, i32 %offset, i32 0)
+ store <6 x i8> %load, ptr addrspace(1) %out
+ ret void
+}
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.buffer.load.illegal-types.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.buffer.load.illegal-types.ll
new file mode 100644
index 0000000000000..0cc2a1f5fc5d9
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.s.buffer.load.illegal-types.ll
@@ -0,0 +1,101 @@
+; RUN: not llc -mtriple=amdgpu9.00 -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,SDAG
+; RUN: not llc -global-isel=1 -mtriple=amdgpu9.00 -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GISEL
+; RUN: not llc -mtriple=amdgpu11.00 -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,SDAG
+; RUN: not llc -global-isel=1 -mtriple=amdgpu11.00 -filetype=null %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GISEL
+
+; There is no s_buffer_load for these result types.
+
+; CHECK: error: {{.*}} in function s_buffer_load_i1 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i1(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call i1 @llvm.amdgcn.s.buffer.load.i1(<4 x i32> %desc, i32 0, i32 0)
+ store i1 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_i4 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i4(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call i4 @llvm.amdgcn.s.buffer.load.i4(<4 x i32> %desc, i32 0, i32 0)
+ store i4 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_i2 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i2(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call i2 @llvm.amdgcn.s.buffer.load.i2(<4 x i32> %desc, i32 0, i32 0)
+ store i2 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_v3i8 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_v3i8(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call <3 x i8> @llvm.amdgcn.s.buffer.load.v3i8(<4 x i32> %desc, i32 0, i32 0)
+ store <3 x i8> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_v2i1 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_v2i1(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call <2 x i1> @llvm.amdgcn.s.buffer.load.v2i1(<4 x i32> %desc, i32 0, i32 0)
+ store <2 x i1> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_v3i16 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_v3i16(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call <3 x i16> @llvm.amdgcn.s.buffer.load.v3i16(<4 x i32> %desc, i32 0, i32 0)
+ store <3 x i16> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_v3f16 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_v3f16(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call <3 x half> @llvm.amdgcn.s.buffer.load.v3f16(<4 x i32> %desc, i32 0, i32 0)
+ store <3 x half> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_v6i8 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_v6i8(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call <6 x i8> @llvm.amdgcn.s.buffer.load.v6i8(<4 x i32> %desc, i32 0, i32 0)
+ store <6 x i8> %load, ptr addrspace(1) %out
+ ret void
+}
+
+; i128 is illegal for SelectionDAG, but GlobalISel selects s_buffer_load_b128.
+; GISEL-NOT: in function {{.*}}_i128
+; SDAG: error: {{.*}} in function s_buffer_load_i128 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i128(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call i128 @llvm.amdgcn.s.buffer.load.i128(<4 x i32> %desc, i32 0, i32 0)
+ store i128 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_i8 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i8(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call i8 @llvm.amdgcn.s.buffer.load.i8(<4 x i32> %desc, i32 0, i32 0)
+ store i8 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_i16 {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i16(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %load = call i16 @llvm.amdgcn.s.buffer.load.i16(<4 x i32> %desc, i32 0, i32 0)
+ store i16 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_i1_divergent {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_i1_divergent(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %offset = call i32 @llvm.amdgcn.workitem.id.x()
+ %load = call i1 @llvm.amdgcn.s.buffer.load.i1(<4 x i32> %desc, i32 %offset, i32 0)
+ store i1 %load, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: {{.*}} in function s_buffer_load_v6i8_divergent {{.*}}: unsupported s_buffer_load result type
+define amdgpu_ps void @s_buffer_load_v6i8_divergent(<4 x i32> inreg %desc, ptr addrspace(1) %out) {
+ %offset = call i32 @llvm.amdgcn.workitem.id.x()
+ %load = call <6 x i8> @llvm.amdgcn.s.buffer.load.v6i8(<4 x i32> %desc, i32 %offset, i32 0)
+ store <6 x i8> %load, ptr addrspace(1) %out
+ ret void
+}
More information about the llvm-commits
mailing list