From 59bc629bf37abe57e1f7e6e61b378e134c3e42bb Mon Sep 17 00:00:00 2001 From: Stanislav Mekhanoshin Date: Thu, 19 Mar 2026 14:08:03 -0700 Subject: [PATCH] [AMDGPU] Fix decoding of SETREG MSBs (#187578) Decoding of the immediate was wrong with non-zero offset and did not factor MSB fixup offset handling. --- .../Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 7 +++- .../CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir | 40 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp index 10c9921f3431..ef7bf16196c2 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -3618,9 +3618,12 @@ convertSetRegImmToVgprMSBs(unsigned Imm, unsigned Simm16, auto [HwRegId, Offset, Size] = Hwreg::HwregEncoding::decode(Simm16); if (HwRegId != Hwreg::ID_MODE || - (!HasSetregVGPRMSBFixup && (Offset + Size) <= VGPRMSBShift)) + (!HasSetregVGPRMSBFixup && (Offset + Size) < VGPRMSBShift)) return {}; - Imm = ((Imm >> Offset) & Hwreg::VGPR_MSB_MASK) >> VGPRMSBShift; + // If there is SetregVGPRMSBFixup then Offset is ignored. + if (!HasSetregVGPRMSBFixup) + Imm <<= Offset; + Imm = (Imm & Hwreg::VGPR_MSB_MASK) >> VGPRMSBShift; if (!HasSetregVGPRMSBFixup) Imm &= llvm::maskTrailingOnes(Size); return llvm::rotr(static_cast(Imm), /*R=*/2); diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir index b1ee9d115048..6f08fa8df94f 100644 --- a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir +++ b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir @@ -315,3 +315,43 @@ body: | $vgpr512 = V_MOV_B32_e32 $vgpr513, implicit $exec S_ENDPGM 0 ... + +# ASM-LABEL: {{^}}multiple_setreg: +# ASM: s_set_vgpr_msb 0x41 ; msbs: dst=1 src0=1 src1=0 src2=0 +# ASM: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +# ASM: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), 0x5005 ; msbs: dst=1 src0=1 src1=0 src2=0 +# ASM: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +# ASM: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), 0x5005 ; msbs: dst=1 src0=1 src1=0 src2=0 +# ASM: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +# ASM: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 0x5001 ; msbs: dst=1 src0=1 src1=0 src2=0 +# ASM: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ + +# DIS-LABEL: : +# DIS: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +# DIS: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +# DIS: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +# DIS: v_mov_b32_e32 v0 /*v256*/, v1 /*v257*/ +--- +name: multiple_setreg +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: multiple_setreg + ; CHECK: S_SET_VGPR_MSB 65, implicit-def $mode + ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + ; CHECK-NEXT: S_SETREG_IMM32_B32 20485, 6145, implicit-def $mode, implicit $mode + ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + ; CHECK-NEXT: S_SETREG_IMM32_B32 20485, 6145, implicit-def $mode, implicit $mode + ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + ; CHECK-NEXT: S_SETREG_IMM32_B32 20481, 1601, implicit-def $mode, implicit $mode + ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + ; CHECK-NEXT: S_ENDPGM 0 + $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + S_SETREG_IMM32_B32 5, 6145, implicit-def $mode, implicit $mode + $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + S_SETREG_IMM32_B32 5, 6145, implicit-def $mode, implicit $mode + $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + S_SETREG_IMM32_B32 1, 1601, implicit-def $mode, implicit $mode + $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec + S_ENDPGM 0 +...