[llvm] [AMDGPU] Fix i64 amdgcn.ubfe/sbfe lowering crash (PR #217461)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 19 23:51:17 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/217461
>From 3ca4c787addc4fe7fcd76af85c1a4b55ce52c141 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 19 Aug 2026 22:39:07 +0200
Subject: [PATCH 1/2] [AMDGPU] Fix i64 amdgcn.ubfe/sbfe lowering crash
- BFE_I32/BFE_U32 are 32-bit only
- wider widths now expand to shifts
---
llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 4 +-
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 56 ++-
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll | 137 ++++++++
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll | 327 ++++++++++++++++++
4 files changed, 518 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 3f93ca66dca17..3d4b3dac7520f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -5676,8 +5676,8 @@ SDValue AMDGPUTargetLowering::PerformDAGCombine(SDNode *N,
return performFAbsCombine(N, DCI);
case AMDGPUISD::BFE_I32:
case AMDGPUISD::BFE_U32: {
- assert(!N->getValueType(0).isVector() &&
- "Vector handling of BFE not implemented");
+ assert(N->getValueType(0) == MVT::i32 &&
+ "BFE_I32/BFE_U32 is a 32-bit operation");
ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
if (!Width)
break;
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index f9943c6208656..c0b3e3d3cfe2e 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8059,6 +8059,57 @@ static SDValue lowerBALLOTIntrinsic(const SITargetLowering &TLI, SDNode *N,
DAG.getConstant(0, SL, MVT::i32), DAG.getCondCode(ISD::SETNE));
}
+static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, bool Signed) {
+ SDLoc DL(Op);
+ EVT VT = Op.getValueType();
+ SDValue Src = Op.getOperand(1);
+ SDValue Offset = Op.getOperand(2);
+ SDValue Width = Op.getOperand(3);
+
+ if (VT == MVT::i32)
+ return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
+ Src, Offset, Width);
+
+ assert(!VT.isVector() && "Vector handling of BFE not implemented");
+
+ auto *CWidth = dyn_cast<ConstantSDNode>(Width);
+ if (CWidth && CWidth->getZExtValue() == 0)
+ return DAG.getConstant(0, DL, VT);
+
+ // BFE_I32/BFE_U32 are 32-bit only; expand wider extracts into shifts. Mask
+ // a constant offset explicitly so the shift below doesn't fold to poison.
+ unsigned Size = VT.getSizeInBits();
+ unsigned ShrOpc = Signed ? ISD::SRA : ISD::SRL;
+ if (auto *COffset = dyn_cast<ConstantSDNode>(Offset))
+ Offset =
+ DAG.getConstant(COffset->getZExtValue() & (Size - 1), DL, MVT::i32);
+
+ SDValue Shift = DAG.getNode(ShrOpc, DL, VT, Src, Offset);
+
+ if (CWidth) {
+ uint64_t WidthVal = CWidth->getZExtValue();
+
+ // S_BFE_{I,U}64's width field is 7 bits; a full-width value needs no mask.
+ if (WidthVal >= Size)
+ return Shift;
+
+ EVT WidthVT = EVT::getIntegerVT(*DAG.getContext(), WidthVal);
+ if (Signed)
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Shift,
+ DAG.getValueType(WidthVT));
+ return DAG.getZeroExtendInReg(Shift, DL, WidthVT);
+ }
+
+ // Select handles Width == 0: a shift amount of Size wraps to a shift by 0
+ // on hardware, so the shifts alone would wrongly return Src >> Offset.
+ SDValue ExtShift = DAG.getNode(ISD::SUB, DL, MVT::i32,
+ DAG.getConstant(Size, DL, MVT::i32), Width);
+ SDValue Shl = DAG.getNode(ISD::SHL, DL, VT, Shift, ExtShift);
+ SDValue Ext = DAG.getNode(ShrOpc, DL, VT, Shl, ExtShift);
+ return DAG.getSelectCC(DL, Width, DAG.getConstant(0, DL, MVT::i32),
+ DAG.getConstant(0, DL, VT), Ext, ISD::SETEQ);
+}
+
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL,
EVT VT);
@@ -11459,11 +11510,8 @@ SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
return DAG.getNode(AMDGPUISD::FMUL_LEGACY, DL, VT, Op.getOperand(1),
Op.getOperand(2));
case Intrinsic::amdgcn_sbfe:
- return DAG.getNode(AMDGPUISD::BFE_I32, DL, VT, Op.getOperand(1),
- Op.getOperand(2), Op.getOperand(3));
case Intrinsic::amdgcn_ubfe:
- return DAG.getNode(AMDGPUISD::BFE_U32, DL, VT, Op.getOperand(1),
- Op.getOperand(2), Op.getOperand(3));
+ return lowerBFEIntrinsic(Op, DAG, IntrinsicID == Intrinsic::amdgcn_sbfe);
case Intrinsic::amdgcn_cvt_pkrtz:
case Intrinsic::amdgcn_cvt_pknorm_i16:
case Intrinsic::amdgcn_cvt_pknorm_u16:
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll
index f2274e3eef31e..412e8209e2d06 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll
@@ -590,6 +590,143 @@ define amdgpu_kernel void @bfe_i32_width_32(ptr addrspace(1) %out) #0 {
ret void
}
+; GCN-LABEL: {{^}}v_sbfe_i64_width_0:
+; GCN-DAG: v_mov_b32_e32 v0, 0
+; GCN-DAG: v_mov_b32_e32 v1, 0
+define i64 @v_sbfe_i64_width_0(i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 0)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_width_31:
+; GCN: v_lshl{{(rev)?}}_b64 v[0:1], {{.*}}25
+; GCN-NEXT: v_ashrrev_i32_e32 v0, 1, v1
+; GCN-NEXT: v_ashrrev_i32_e32 v1, 31, v1
+define i64 @v_sbfe_i64_width_31(i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 31)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_width_32:
+; GCN: v_lshr{{(rev)?}}_b64 v[2:3], {{.*}}8
+; GCN-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; GCN-NEXT: v_ashrrev_i32_e32 v2, 31, v2
+; GCN-NEXT: v_mov_b32_e32 v1, v2
+define i64 @v_sbfe_i64_width_32(i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 32)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_width_33:
+; GCN: v_lshl{{(rev)?}}_b64 v[0:1], {{.*}}23
+; GCN-NEXT: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}31
+define i64 @v_sbfe_i64_width_33(i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 33)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_width_63:
+; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}8
+define i64 @v_sbfe_i64_width_63(i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 63)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_width_64:
+; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}8
+define i64 @v_sbfe_i64_width_64(i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 64)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_width_0:
+; GCN-DAG: v_mov_b32_e32 v0, 0
+; GCN-DAG: v_mov_b32_e32 v1, 0
+define i64 @s_sbfe_i64_width_0(i64 inreg %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 0)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_width_31:
+; GCN: s_lshl_b64 s[4:5], s[16:17], 25
+; GCN-NEXT: s_ashr_i32 s4, s5, 1
+; GCN-NEXT: s_ashr_i32 s5, s5, 31
+define i64 @s_sbfe_i64_width_31(i64 inreg %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 31)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_width_32:
+; GCN: s_lshr_b64 s[4:5], s[16:17], 8
+; GCN-NEXT: s_bfe_i64 s[6:7], s[4:5], 0x200000
+; GCN-NEXT: v_mov_b32_e32 v0, s4
+; GCN-NEXT: v_mov_b32_e32 v1, s7
+define i64 @s_sbfe_i64_width_32(i64 inreg %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 32)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_width_33:
+; GCN: s_lshl_b64 s[4:5], s[16:17], 23
+; GCN-NEXT: s_ashr_i64 s[4:5], s[4:5], 31
+define i64 @s_sbfe_i64_width_33(i64 inreg %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 33)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_width_63:
+; GCN: s_ashr_i64 s[4:5], s[16:17], 8
+define i64 @s_sbfe_i64_width_63(i64 inreg %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 63)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_width_64:
+; GCN: s_ashr_i64 s[4:5], s[16:17], 8
+define i64 @s_sbfe_i64_width_64(i64 inreg %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 64)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_arg_width:
+; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}8
+; GCN: v_sub_{{[iu]}}32_e32 v3, vcc, 64, v2
+; GCN: v_lshl{{(rev)?}}_b64 v[0:1],
+; GCN: v_cmp_eq_u32_e32 vcc, 0, v2
+; GCN: v_ashr{{(rev)?}}_i64 v[0:1],
+; GCN: v_cndmask_b32_e64 v0, v0, 0, vcc
+; GCN-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+define i64 @v_sbfe_i64_arg_width(i64 %src, i32 %width) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 %width)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}v_sbfe_i64_arg_offset_arg_width:
+; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}v2
+; GCN: v_sub_{{[iu]}}32_e32 v2, vcc, 64, v3
+; GCN: v_lshl{{(rev)?}}_b64 v[0:1],
+; GCN: v_cmp_eq_u32_e32 vcc, 0, v3
+; GCN: v_ashr{{(rev)?}}_i64 v[0:1],
+; GCN: v_cndmask_b32_e64 v0, v0, 0, vcc
+; GCN-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+define i64 @v_sbfe_i64_arg_offset_arg_width(i64 %src, i32 %offset, i32 %width) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 %offset, i32 %width)
+ ret i64 %bfe
+}
+
+; GCN-LABEL: {{^}}s_sbfe_i64_arg_width:
+; GCN-DAG: s_sub_i32 s6, 64, s18
+; GCN-DAG: s_ashr_i64 s[4:5], s[16:17], 8
+; GCN: s_lshl_b64 s[4:5], s[4:5], s6
+; GCN-NEXT: s_ashr_i64 s[4:5], s[4:5], s6
+; GCN-NEXT: s_cmp_eq_u32 s18, 0
+; GCN-NEXT: s_cselect_b32 s4, 0, s4
+; GCN-NEXT: s_cselect_b32 s5, 0, s5
+define i64 @s_sbfe_i64_arg_width(i64 inreg %src, i32 inreg %width) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 %width)
+ ret i64 %bfe
+}
+
declare i32 @llvm.amdgcn.sbfe.i32(i32, i32, i32) #1
attributes #0 = { nounwind }
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll
index 44acba7be3d14..7bf7006944ce4 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll
@@ -1810,3 +1810,330 @@ define amdgpu_kernel void @bfe_u32_offset_0_width_24_ashr(ptr addrspace(1) %out,
store i32 %bfe, ptr addrspace(1) %out, align 4
ret void
}
+
+define i64 @v_ubfe_i64_width_0(i64 %src) {
+; SI-LABEL: v_ubfe_i64_width_0:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_mov_b32_e32 v0, 0
+; SI-NEXT: v_mov_b32_e32 v1, 0
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_width_0:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_mov_b32_e32 v0, 0
+; VI-NEXT: v_mov_b32_e32 v1, 0
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 0)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_width_31(i64 %src) {
+; SI-LABEL: v_ubfe_i64_width_31:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; SI-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0
+; SI-NEXT: v_mov_b32_e32 v1, 0
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_width_31:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; VI-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0
+; VI-NEXT: v_mov_b32_e32 v1, 0
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 31)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_width_32(i64 %src) {
+; SI-LABEL: v_ubfe_i64_width_32:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; SI-NEXT: v_mov_b32_e32 v1, 0
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_width_32:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; VI-NEXT: v_mov_b32_e32 v1, 0
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 32)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_width_33(i64 %src) {
+;
+; SI-LABEL: v_ubfe_i64_width_33:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], 8
+; SI-NEXT: v_and_b32_e32 v1, 1, v1
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_width_33:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_lshrrev_b64 v[0:1], 8, v[0:1]
+; VI-NEXT: v_and_b32_e32 v1, 1, v1
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 33)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_width_63(i64 %src) {
+; SI-LABEL: v_ubfe_i64_width_63:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; SI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_width_63:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; VI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 63)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_width_64(i64 %src) {
+; SI-LABEL: v_ubfe_i64_width_64:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; SI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_width_64:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
+; VI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 64)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_width_0(i64 inreg %src) {
+; SI-LABEL: s_ubfe_i64_width_0:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_mov_b32_e32 v0, 0
+; SI-NEXT: v_mov_b32_e32 v1, 0
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_width_0:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_mov_b32_e32 v0, 0
+; VI-NEXT: v_mov_b32_e32 v1, 0
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 0)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_width_31(i64 inreg %src) {
+; SI-LABEL: s_ubfe_i64_width_31:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; SI-NEXT: s_bitset0_b32 s4, 31
+; SI-NEXT: v_mov_b32_e32 v0, s4
+; SI-NEXT: v_mov_b32_e32 v1, 0
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_width_31:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; VI-NEXT: s_bitset0_b32 s4, 31
+; VI-NEXT: v_mov_b32_e32 v0, s4
+; VI-NEXT: v_mov_b32_e32 v1, 0
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 31)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_width_32(i64 inreg %src) {
+; SI-LABEL: s_ubfe_i64_width_32:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; SI-NEXT: v_mov_b32_e32 v0, s4
+; SI-NEXT: v_mov_b32_e32 v1, 0
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_width_32:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; VI-NEXT: v_mov_b32_e32 v0, s4
+; VI-NEXT: v_mov_b32_e32 v1, 0
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 32)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_width_33(i64 inreg %src) {
+; SI-LABEL: s_ubfe_i64_width_33:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; SI-NEXT: s_and_b32 s5, s5, 1
+; SI-NEXT: v_mov_b32_e32 v0, s4
+; SI-NEXT: v_mov_b32_e32 v1, s5
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_width_33:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; VI-NEXT: s_and_b32 s5, s5, 1
+; VI-NEXT: v_mov_b32_e32 v0, s4
+; VI-NEXT: v_mov_b32_e32 v1, s5
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 33)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_width_63(i64 inreg %src) {
+; SI-LABEL: s_ubfe_i64_width_63:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; SI-NEXT: s_lshr_b32 s5, s17, 8
+; SI-NEXT: v_mov_b32_e32 v0, s4
+; SI-NEXT: v_mov_b32_e32 v1, s5
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_width_63:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; VI-NEXT: s_lshr_b32 s5, s17, 8
+; VI-NEXT: v_mov_b32_e32 v0, s4
+; VI-NEXT: v_mov_b32_e32 v1, s5
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 63)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_width_64(i64 inreg %src) {
+; SI-LABEL: s_ubfe_i64_width_64:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; SI-NEXT: s_lshr_b32 s5, s17, 8
+; SI-NEXT: v_mov_b32_e32 v0, s4
+; SI-NEXT: v_mov_b32_e32 v1, s5
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_width_64:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; VI-NEXT: s_lshr_b32 s5, s17, 8
+; VI-NEXT: v_mov_b32_e32 v0, s4
+; VI-NEXT: v_mov_b32_e32 v1, s5
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 64)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_arg_width(i64 %src, i32 %width) {
+;
+; SI-LABEL: v_ubfe_i64_arg_width:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], 8
+; SI-NEXT: v_sub_i32_e32 v3, vcc, 64, v2
+; SI-NEXT: v_lshl_b64 v[0:1], v[0:1], v3
+; SI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2
+; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], v3
+; SI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
+; SI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_arg_width:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_lshrrev_b64 v[0:1], 8, v[0:1]
+; VI-NEXT: v_sub_u32_e32 v3, vcc, 64, v2
+; VI-NEXT: v_lshlrev_b64 v[0:1], v3, v[0:1]
+; VI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2
+; VI-NEXT: v_lshrrev_b64 v[0:1], v3, v[0:1]
+; VI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
+; VI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 %width)
+ ret i64 %bfe
+}
+
+define i64 @v_ubfe_i64_arg_offset_arg_width(i64 %src, i32 %offset, i32 %width) {
+;
+; SI-LABEL: v_ubfe_i64_arg_offset_arg_width:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], v2
+; SI-NEXT: v_sub_i32_e32 v2, vcc, 64, v3
+; SI-NEXT: v_lshl_b64 v[0:1], v[0:1], v2
+; SI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3
+; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], v2
+; SI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
+; SI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: v_ubfe_i64_arg_offset_arg_width:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: v_lshrrev_b64 v[0:1], v2, v[0:1]
+; VI-NEXT: v_sub_u32_e32 v2, vcc, 64, v3
+; VI-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1]
+; VI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3
+; VI-NEXT: v_lshrrev_b64 v[0:1], v2, v[0:1]
+; VI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
+; VI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 %offset, i32 %width)
+ ret i64 %bfe
+}
+
+define i64 @s_ubfe_i64_arg_width(i64 inreg %src, i32 inreg %width) {
+; SI-LABEL: s_ubfe_i64_arg_width:
+; SI: ; %bb.0:
+; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SI-NEXT: s_sub_i32 s6, 64, s18
+; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; SI-NEXT: s_lshl_b64 s[4:5], s[4:5], s6
+; SI-NEXT: s_lshr_b64 s[4:5], s[4:5], s6
+; SI-NEXT: s_cmp_eq_u32 s18, 0
+; SI-NEXT: s_cselect_b32 s4, 0, s4
+; SI-NEXT: s_cselect_b32 s5, 0, s5
+; SI-NEXT: v_mov_b32_e32 v0, s4
+; SI-NEXT: v_mov_b32_e32 v1, s5
+; SI-NEXT: s_setpc_b64 s[30:31]
+;
+; VI-LABEL: s_ubfe_i64_arg_width:
+; VI: ; %bb.0:
+; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; VI-NEXT: s_sub_i32 s6, 64, s18
+; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
+; VI-NEXT: s_lshl_b64 s[4:5], s[4:5], s6
+; VI-NEXT: s_lshr_b64 s[4:5], s[4:5], s6
+; VI-NEXT: s_cmp_eq_u32 s18, 0
+; VI-NEXT: s_cselect_b32 s4, 0, s4
+; VI-NEXT: s_cselect_b32 s5, 0, s5
+; VI-NEXT: v_mov_b32_e32 v0, s4
+; VI-NEXT: v_mov_b32_e32 v1, s5
+; VI-NEXT: s_setpc_b64 s[30:31]
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 %width)
+ ret i64 %bfe
+}
>From d17113998b2923394e671bdb8430fbbc3fb097be Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 20 Aug 2026 08:50:59 +0200
Subject: [PATCH 2/2] report an error
---
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 51 +--
.../AMDGPU/llvm.amdgcn.sbfe.i64.err.ll | 11 +
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll | 137 --------
.../AMDGPU/llvm.amdgcn.ubfe.i64.err.ll | 11 +
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll | 327 ------------------
5 files changed, 32 insertions(+), 505 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.i64.err.ll
create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.i64.err.ll
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index c0b3e3d3cfe2e..66cf57e866227 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8066,48 +8066,17 @@ static SDValue lowerBFEIntrinsic(SDValue Op, SelectionDAG &DAG, bool Signed) {
SDValue Offset = Op.getOperand(2);
SDValue Width = Op.getOperand(3);
- if (VT == MVT::i32)
- return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
- Src, Offset, Width);
-
- assert(!VT.isVector() && "Vector handling of BFE not implemented");
-
- auto *CWidth = dyn_cast<ConstantSDNode>(Width);
- if (CWidth && CWidth->getZExtValue() == 0)
- return DAG.getConstant(0, DL, VT);
+ if (VT != MVT::i32) {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ DAG.getMachineFunction().getFunction(),
+ Twine("llvm.amdgcn.") + (Signed ? "sbfe" : "ubfe") +
+ " only supports i32",
+ DL.getDebugLoc()));
+ return DAG.getPOISON(VT);
+ }
- // BFE_I32/BFE_U32 are 32-bit only; expand wider extracts into shifts. Mask
- // a constant offset explicitly so the shift below doesn't fold to poison.
- unsigned Size = VT.getSizeInBits();
- unsigned ShrOpc = Signed ? ISD::SRA : ISD::SRL;
- if (auto *COffset = dyn_cast<ConstantSDNode>(Offset))
- Offset =
- DAG.getConstant(COffset->getZExtValue() & (Size - 1), DL, MVT::i32);
-
- SDValue Shift = DAG.getNode(ShrOpc, DL, VT, Src, Offset);
-
- if (CWidth) {
- uint64_t WidthVal = CWidth->getZExtValue();
-
- // S_BFE_{I,U}64's width field is 7 bits; a full-width value needs no mask.
- if (WidthVal >= Size)
- return Shift;
-
- EVT WidthVT = EVT::getIntegerVT(*DAG.getContext(), WidthVal);
- if (Signed)
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Shift,
- DAG.getValueType(WidthVT));
- return DAG.getZeroExtendInReg(Shift, DL, WidthVT);
- }
-
- // Select handles Width == 0: a shift amount of Size wraps to a shift by 0
- // on hardware, so the shifts alone would wrongly return Src >> Offset.
- SDValue ExtShift = DAG.getNode(ISD::SUB, DL, MVT::i32,
- DAG.getConstant(Size, DL, MVT::i32), Width);
- SDValue Shl = DAG.getNode(ISD::SHL, DL, VT, Shift, ExtShift);
- SDValue Ext = DAG.getNode(ShrOpc, DL, VT, Shl, ExtShift);
- return DAG.getSelectCC(DL, Width, DAG.getConstant(0, DL, MVT::i32),
- DAG.getConstant(0, DL, VT), Ext, ISD::SETEQ);
+ return DAG.getNode(Signed ? AMDGPUISD::BFE_I32 : AMDGPUISD::BFE_U32, DL, VT,
+ Src, Offset, Width);
}
static SDValue emitRemovedIntrinsicError(SelectionDAG &DAG, const SDLoc &DL,
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.i64.err.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.i64.err.ll
new file mode 100644
index 0000000000000..8e00d14c36f57
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.i64.err.ll
@@ -0,0 +1,11 @@
+; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s 2>&1 | FileCheck %s
+
+; CHECK: error: <unknown>:0:0: in function sbfe_i64 void (ptr addrspace(1), i64): llvm.amdgcn.sbfe only supports i32
+
+define amdgpu_kernel void @sbfe_i64(ptr addrspace(1) %out, i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 16)
+ store i64 %bfe, ptr addrspace(1) %out
+ ret void
+}
+
+declare i64 @llvm.amdgcn.sbfe.i64(i64, i32, i32)
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll
index 412e8209e2d06..f2274e3eef31e 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sbfe.ll
@@ -590,143 +590,6 @@ define amdgpu_kernel void @bfe_i32_width_32(ptr addrspace(1) %out) #0 {
ret void
}
-; GCN-LABEL: {{^}}v_sbfe_i64_width_0:
-; GCN-DAG: v_mov_b32_e32 v0, 0
-; GCN-DAG: v_mov_b32_e32 v1, 0
-define i64 @v_sbfe_i64_width_0(i64 %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 0)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_width_31:
-; GCN: v_lshl{{(rev)?}}_b64 v[0:1], {{.*}}25
-; GCN-NEXT: v_ashrrev_i32_e32 v0, 1, v1
-; GCN-NEXT: v_ashrrev_i32_e32 v1, 31, v1
-define i64 @v_sbfe_i64_width_31(i64 %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 31)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_width_32:
-; GCN: v_lshr{{(rev)?}}_b64 v[2:3], {{.*}}8
-; GCN-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; GCN-NEXT: v_ashrrev_i32_e32 v2, 31, v2
-; GCN-NEXT: v_mov_b32_e32 v1, v2
-define i64 @v_sbfe_i64_width_32(i64 %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 32)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_width_33:
-; GCN: v_lshl{{(rev)?}}_b64 v[0:1], {{.*}}23
-; GCN-NEXT: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}31
-define i64 @v_sbfe_i64_width_33(i64 %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 33)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_width_63:
-; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}8
-define i64 @v_sbfe_i64_width_63(i64 %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 63)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_width_64:
-; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}8
-define i64 @v_sbfe_i64_width_64(i64 %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 64)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_width_0:
-; GCN-DAG: v_mov_b32_e32 v0, 0
-; GCN-DAG: v_mov_b32_e32 v1, 0
-define i64 @s_sbfe_i64_width_0(i64 inreg %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 0)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_width_31:
-; GCN: s_lshl_b64 s[4:5], s[16:17], 25
-; GCN-NEXT: s_ashr_i32 s4, s5, 1
-; GCN-NEXT: s_ashr_i32 s5, s5, 31
-define i64 @s_sbfe_i64_width_31(i64 inreg %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 31)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_width_32:
-; GCN: s_lshr_b64 s[4:5], s[16:17], 8
-; GCN-NEXT: s_bfe_i64 s[6:7], s[4:5], 0x200000
-; GCN-NEXT: v_mov_b32_e32 v0, s4
-; GCN-NEXT: v_mov_b32_e32 v1, s7
-define i64 @s_sbfe_i64_width_32(i64 inreg %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 32)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_width_33:
-; GCN: s_lshl_b64 s[4:5], s[16:17], 23
-; GCN-NEXT: s_ashr_i64 s[4:5], s[4:5], 31
-define i64 @s_sbfe_i64_width_33(i64 inreg %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 33)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_width_63:
-; GCN: s_ashr_i64 s[4:5], s[16:17], 8
-define i64 @s_sbfe_i64_width_63(i64 inreg %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 63)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_width_64:
-; GCN: s_ashr_i64 s[4:5], s[16:17], 8
-define i64 @s_sbfe_i64_width_64(i64 inreg %src) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 64)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_arg_width:
-; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}8
-; GCN: v_sub_{{[iu]}}32_e32 v3, vcc, 64, v2
-; GCN: v_lshl{{(rev)?}}_b64 v[0:1],
-; GCN: v_cmp_eq_u32_e32 vcc, 0, v2
-; GCN: v_ashr{{(rev)?}}_i64 v[0:1],
-; GCN: v_cndmask_b32_e64 v0, v0, 0, vcc
-; GCN-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
-define i64 @v_sbfe_i64_arg_width(i64 %src, i32 %width) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 %width)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}v_sbfe_i64_arg_offset_arg_width:
-; GCN: v_ashr{{(rev)?}}_i64 v[0:1], {{.*}}v2
-; GCN: v_sub_{{[iu]}}32_e32 v2, vcc, 64, v3
-; GCN: v_lshl{{(rev)?}}_b64 v[0:1],
-; GCN: v_cmp_eq_u32_e32 vcc, 0, v3
-; GCN: v_ashr{{(rev)?}}_i64 v[0:1],
-; GCN: v_cndmask_b32_e64 v0, v0, 0, vcc
-; GCN-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
-define i64 @v_sbfe_i64_arg_offset_arg_width(i64 %src, i32 %offset, i32 %width) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 %offset, i32 %width)
- ret i64 %bfe
-}
-
-; GCN-LABEL: {{^}}s_sbfe_i64_arg_width:
-; GCN-DAG: s_sub_i32 s6, 64, s18
-; GCN-DAG: s_ashr_i64 s[4:5], s[16:17], 8
-; GCN: s_lshl_b64 s[4:5], s[4:5], s6
-; GCN-NEXT: s_ashr_i64 s[4:5], s[4:5], s6
-; GCN-NEXT: s_cmp_eq_u32 s18, 0
-; GCN-NEXT: s_cselect_b32 s4, 0, s4
-; GCN-NEXT: s_cselect_b32 s5, 0, s5
-define i64 @s_sbfe_i64_arg_width(i64 inreg %src, i32 inreg %width) {
- %bfe = call i64 @llvm.amdgcn.sbfe.i64(i64 %src, i32 8, i32 %width)
- ret i64 %bfe
-}
-
declare i32 @llvm.amdgcn.sbfe.i32(i32, i32, i32) #1
attributes #0 = { nounwind }
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.i64.err.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.i64.err.ll
new file mode 100644
index 0000000000000..2551dd61c591a
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.i64.err.ll
@@ -0,0 +1,11 @@
+; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s 2>&1 | FileCheck %s
+
+; CHECK: error: <unknown>:0:0: in function ubfe_i64 void (ptr addrspace(1), i64): llvm.amdgcn.ubfe only supports i32
+
+define amdgpu_kernel void @ubfe_i64(ptr addrspace(1) %out, i64 %src) {
+ %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 16)
+ store i64 %bfe, ptr addrspace(1) %out
+ ret void
+}
+
+declare i64 @llvm.amdgcn.ubfe.i64(i64, i32, i32)
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll
index 7bf7006944ce4..44acba7be3d14 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ubfe.ll
@@ -1810,330 +1810,3 @@ define amdgpu_kernel void @bfe_u32_offset_0_width_24_ashr(ptr addrspace(1) %out,
store i32 %bfe, ptr addrspace(1) %out, align 4
ret void
}
-
-define i64 @v_ubfe_i64_width_0(i64 %src) {
-; SI-LABEL: v_ubfe_i64_width_0:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_mov_b32_e32 v0, 0
-; SI-NEXT: v_mov_b32_e32 v1, 0
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_width_0:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_mov_b32_e32 v0, 0
-; VI-NEXT: v_mov_b32_e32 v1, 0
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 0)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_width_31(i64 %src) {
-; SI-LABEL: v_ubfe_i64_width_31:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; SI-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0
-; SI-NEXT: v_mov_b32_e32 v1, 0
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_width_31:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; VI-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0
-; VI-NEXT: v_mov_b32_e32 v1, 0
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 31)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_width_32(i64 %src) {
-; SI-LABEL: v_ubfe_i64_width_32:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; SI-NEXT: v_mov_b32_e32 v1, 0
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_width_32:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; VI-NEXT: v_mov_b32_e32 v1, 0
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 32)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_width_33(i64 %src) {
-;
-; SI-LABEL: v_ubfe_i64_width_33:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], 8
-; SI-NEXT: v_and_b32_e32 v1, 1, v1
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_width_33:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_lshrrev_b64 v[0:1], 8, v[0:1]
-; VI-NEXT: v_and_b32_e32 v1, 1, v1
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 33)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_width_63(i64 %src) {
-; SI-LABEL: v_ubfe_i64_width_63:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; SI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_width_63:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; VI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 63)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_width_64(i64 %src) {
-; SI-LABEL: v_ubfe_i64_width_64:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; SI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_width_64:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_alignbit_b32 v0, v1, v0, 8
-; VI-NEXT: v_lshrrev_b32_e32 v1, 8, v1
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 64)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_width_0(i64 inreg %src) {
-; SI-LABEL: s_ubfe_i64_width_0:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_mov_b32_e32 v0, 0
-; SI-NEXT: v_mov_b32_e32 v1, 0
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_width_0:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_mov_b32_e32 v0, 0
-; VI-NEXT: v_mov_b32_e32 v1, 0
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 0)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_width_31(i64 inreg %src) {
-; SI-LABEL: s_ubfe_i64_width_31:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; SI-NEXT: s_bitset0_b32 s4, 31
-; SI-NEXT: v_mov_b32_e32 v0, s4
-; SI-NEXT: v_mov_b32_e32 v1, 0
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_width_31:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; VI-NEXT: s_bitset0_b32 s4, 31
-; VI-NEXT: v_mov_b32_e32 v0, s4
-; VI-NEXT: v_mov_b32_e32 v1, 0
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 31)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_width_32(i64 inreg %src) {
-; SI-LABEL: s_ubfe_i64_width_32:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; SI-NEXT: v_mov_b32_e32 v0, s4
-; SI-NEXT: v_mov_b32_e32 v1, 0
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_width_32:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; VI-NEXT: v_mov_b32_e32 v0, s4
-; VI-NEXT: v_mov_b32_e32 v1, 0
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 32)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_width_33(i64 inreg %src) {
-; SI-LABEL: s_ubfe_i64_width_33:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; SI-NEXT: s_and_b32 s5, s5, 1
-; SI-NEXT: v_mov_b32_e32 v0, s4
-; SI-NEXT: v_mov_b32_e32 v1, s5
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_width_33:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; VI-NEXT: s_and_b32 s5, s5, 1
-; VI-NEXT: v_mov_b32_e32 v0, s4
-; VI-NEXT: v_mov_b32_e32 v1, s5
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 33)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_width_63(i64 inreg %src) {
-; SI-LABEL: s_ubfe_i64_width_63:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; SI-NEXT: s_lshr_b32 s5, s17, 8
-; SI-NEXT: v_mov_b32_e32 v0, s4
-; SI-NEXT: v_mov_b32_e32 v1, s5
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_width_63:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; VI-NEXT: s_lshr_b32 s5, s17, 8
-; VI-NEXT: v_mov_b32_e32 v0, s4
-; VI-NEXT: v_mov_b32_e32 v1, s5
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 63)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_width_64(i64 inreg %src) {
-; SI-LABEL: s_ubfe_i64_width_64:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; SI-NEXT: s_lshr_b32 s5, s17, 8
-; SI-NEXT: v_mov_b32_e32 v0, s4
-; SI-NEXT: v_mov_b32_e32 v1, s5
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_width_64:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; VI-NEXT: s_lshr_b32 s5, s17, 8
-; VI-NEXT: v_mov_b32_e32 v0, s4
-; VI-NEXT: v_mov_b32_e32 v1, s5
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 64)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_arg_width(i64 %src, i32 %width) {
-;
-; SI-LABEL: v_ubfe_i64_arg_width:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], 8
-; SI-NEXT: v_sub_i32_e32 v3, vcc, 64, v2
-; SI-NEXT: v_lshl_b64 v[0:1], v[0:1], v3
-; SI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2
-; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], v3
-; SI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
-; SI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_arg_width:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_lshrrev_b64 v[0:1], 8, v[0:1]
-; VI-NEXT: v_sub_u32_e32 v3, vcc, 64, v2
-; VI-NEXT: v_lshlrev_b64 v[0:1], v3, v[0:1]
-; VI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2
-; VI-NEXT: v_lshrrev_b64 v[0:1], v3, v[0:1]
-; VI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
-; VI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 %width)
- ret i64 %bfe
-}
-
-define i64 @v_ubfe_i64_arg_offset_arg_width(i64 %src, i32 %offset, i32 %width) {
-;
-; SI-LABEL: v_ubfe_i64_arg_offset_arg_width:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], v2
-; SI-NEXT: v_sub_i32_e32 v2, vcc, 64, v3
-; SI-NEXT: v_lshl_b64 v[0:1], v[0:1], v2
-; SI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3
-; SI-NEXT: v_lshr_b64 v[0:1], v[0:1], v2
-; SI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
-; SI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: v_ubfe_i64_arg_offset_arg_width:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: v_lshrrev_b64 v[0:1], v2, v[0:1]
-; VI-NEXT: v_sub_u32_e32 v2, vcc, 64, v3
-; VI-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1]
-; VI-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3
-; VI-NEXT: v_lshrrev_b64 v[0:1], v2, v[0:1]
-; VI-NEXT: v_cndmask_b32_e64 v0, v0, 0, vcc
-; VI-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 %offset, i32 %width)
- ret i64 %bfe
-}
-
-define i64 @s_ubfe_i64_arg_width(i64 inreg %src, i32 inreg %width) {
-; SI-LABEL: s_ubfe_i64_arg_width:
-; SI: ; %bb.0:
-; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; SI-NEXT: s_sub_i32 s6, 64, s18
-; SI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; SI-NEXT: s_lshl_b64 s[4:5], s[4:5], s6
-; SI-NEXT: s_lshr_b64 s[4:5], s[4:5], s6
-; SI-NEXT: s_cmp_eq_u32 s18, 0
-; SI-NEXT: s_cselect_b32 s4, 0, s4
-; SI-NEXT: s_cselect_b32 s5, 0, s5
-; SI-NEXT: v_mov_b32_e32 v0, s4
-; SI-NEXT: v_mov_b32_e32 v1, s5
-; SI-NEXT: s_setpc_b64 s[30:31]
-;
-; VI-LABEL: s_ubfe_i64_arg_width:
-; VI: ; %bb.0:
-; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; VI-NEXT: s_sub_i32 s6, 64, s18
-; VI-NEXT: s_lshr_b64 s[4:5], s[16:17], 8
-; VI-NEXT: s_lshl_b64 s[4:5], s[4:5], s6
-; VI-NEXT: s_lshr_b64 s[4:5], s[4:5], s6
-; VI-NEXT: s_cmp_eq_u32 s18, 0
-; VI-NEXT: s_cselect_b32 s4, 0, s4
-; VI-NEXT: s_cselect_b32 s5, 0, s5
-; VI-NEXT: v_mov_b32_e32 v0, s4
-; VI-NEXT: v_mov_b32_e32 v1, s5
-; VI-NEXT: s_setpc_b64 s[30:31]
- %bfe = call i64 @llvm.amdgcn.ubfe.i64(i64 %src, i32 8, i32 %width)
- ret i64 %bfe
-}
More information about the llvm-commits
mailing list