[llvm] [AMDGPU] Handle register variant S_SETREG when fixing VGPR MSB clobbers (PR #218941)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 00:38:41 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/218941

>From 28978216727bce793531a1508cf5c25e01589653 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 26 Aug 2026 16:22:28 +0200
Subject: [PATCH 1/4] [AMDGPU] Handle register variant S_SETREG when fixing
 VGPR MSB clobbers

Its value is unknown at compile time, so the clobbered VGPR MSBs must always be restored
---
 .../Target/AMDGPU/AMDGPULowerVGPREncoding.cpp |  49 ++++---
 .../lib/Target/AMDGPU/GCNHazardRecognizer.cpp |  19 +--
 llvm/lib/Target/AMDGPU/SIInstrInfo.h          |  13 ++
 .../CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll   |  27 ++++
 .../CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir  | 122 ++++++++++++++++++
 5 files changed, 199 insertions(+), 31 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll

diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerVGPREncoding.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerVGPREncoding.cpp
index 75c3dd3b1de09..ccacca66f5fcf 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULowerVGPREncoding.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULowerVGPREncoding.cpp
@@ -197,20 +197,24 @@ class AMDGPULowerVGPREncoding {
   MachineBasicBlock::instr_iterator
   handleCoissue(MachineBasicBlock::instr_iterator I);
 
-  /// S_SET_VGPR_MSB immediately after S_SETREG_IMM32_B32 targeting MODE is
+  /// S_SET_VGPR_MSB immediately after an S_SETREG variant targeting MODE is
   /// silently dropped on GFX1250. When set, the next S_SET_VGPR_MSB insertion
   /// must be preceded by S_NOP to avoid the hazard.
   bool needNopBeforeSetVGPRMSB(MachineBasicBlock::instr_iterator I);
 
-  /// Handle S_SETREG_IMM32_B32 targeting MODE register. On certain hardware,
+  /// Handle an S_SETREG variant targeting MODE register. On certain hardware,
   /// this instruction clobbers VGPR MSB bits[12:19], so we need to restore
   /// the current mode. \returns true if the instruction was modified or a
   /// new one was inserted.
   bool handleSetregMode(MachineInstr &MI);
 
-  /// Update bits[12:19] of the imm operand in S_SETREG_IMM32_B32 to contain
-  /// the VGPR MSB mode value. \returns true if the immediate was changed.
+  /// Update bits[12:19] of the imm operand in an S_SETREG_IMM32_B32 variant to
+  /// contain the VGPR MSB mode value. \returns true if the immediate was
+  /// changed.
   bool updateSetregModeImm(MachineInstr &MI, int64_t ModeValue);
+
+  /// Insert S_NOP + S_SET_VGPR_MSB restoring \p ModeValue after setreg \p MI.
+  void restoreModeAfterSetreg(MachineInstr &MI, int64_t ModeValue);
 };
 
 bool AMDGPULowerVGPREncoding::setMode(ModeTy NewMode,
@@ -433,9 +437,9 @@ AMDGPULowerVGPREncoding::handleCoissue(MachineBasicBlock::instr_iterator I) {
   return I;
 }
 
-/// Returns whether \p MI is a S_SETREG_IMM32_B32(MODE).
+/// Returns whether \p MI is an S_SETREG variant targeting MODE.
 static bool isSetregMode(const MachineInstr &MI, const SIInstrInfo &TII) {
-  if (MI.getOpcode() != AMDGPU::S_SETREG_IMM32_B32)
+  if (!SIInstrInfo::isSSetReg(MI.getOpcode()))
     return false;
 
   const MachineOperand *SIMM16Op =
@@ -460,7 +464,7 @@ bool AMDGPULowerVGPREncoding::needNopBeforeSetVGPRMSB(
     }
 
     // Look for a potential fallthrough predecessor block. When it ends with a
-    // S_SETREG_IMM32_B32(MODE) we need to insert a S_NOP too. We assume that an
+    // setreg targeting MODE we need to insert a S_NOP too. We assume that an
     // explicit jump to the current block from the block that would otherwise
     // have naturally fallen through to it will remain in the final assembly.
     CurrentMBB = CurrentMBB->getPrevNode();
@@ -482,7 +486,8 @@ static int64_t convertModeToSetregFormat(int64_t Mode) {
 
 bool AMDGPULowerVGPREncoding::updateSetregModeImm(MachineInstr &MI,
                                                   int64_t ModeValue) {
-  assert(MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32);
+  assert(MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
+         MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32_mode);
 
   // Convert from S_SET_VGPR_MSB format to MODE register format
   int64_t SetregMode = convertModeToSetregFormat(ModeValue);
@@ -499,8 +504,8 @@ bool AMDGPULowerVGPREncoding::updateSetregModeImm(MachineInstr &MI,
 bool AMDGPULowerVGPREncoding::handleSetregMode(MachineInstr &MI) {
   using namespace AMDGPU::Hwreg;
 
-  assert(MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 &&
-         "only S_SETREG_IMM32_B32 needs to be handled");
+  assert(SIInstrInfo::isSSetReg(MI.getOpcode()) &&
+         "expected an S_SETREG variant");
 
   LLVM_DEBUG(dbgs() << "  handleSetregMode: " << MI);
 
@@ -526,6 +531,14 @@ bool AMDGPULowerVGPREncoding::handleSetregMode(MachineInstr &MI) {
            << " VGPRMSBShift=" << VGPRMSBShift << '\n';
   });
 
+  // Register variants write an SGPR to MODE, so the resulting VGPR MSBs are
+  // unknown at compile time.
+  if (MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
+      MI.getOpcode() == AMDGPU::S_SETREG_B32_mode) {
+    restoreModeAfterSetreg(MI, ModeValue);
+    return true;
+  }
+
   // Case 1: Size <= 12 - the original instruction uses imm32[0:Size-1], so
   // imm32[12:19] is unused, or Offset is zero and it is safe to set
   // imm32[12:19] to the correct VGPR MSBs.
@@ -555,10 +568,15 @@ bool AMDGPULowerVGPREncoding::handleSetregMode(MachineInstr &MI) {
     return false;
   }
 
-  // imm32[12:19] doesn't match VGPR MSBs - insert s_set_vgpr_msb after
-  // the original instruction to restore the correct value. Insert S_NOP
-  // to avoid the GFX1250 hazard where S_SET_VGPR_MSB immediately after
-  // S_SETREG_IMM32_B32(MODE) is silently dropped.
+  // imm32[12:19] doesn't match VGPR MSBs - restore the correct value after MI.
+  restoreModeAfterSetreg(MI, ModeValue);
+  return true;
+}
+
+void AMDGPULowerVGPREncoding::restoreModeAfterSetreg(MachineInstr &MI,
+                                                     int64_t ModeValue) {
+  // S_NOP avoids the GFX1250 hazard: S_SET_VGPR_MSB right after a MODE setreg
+  // is silently dropped.
   MachineBasicBlock::iterator InsertPt = std::next(MI.getIterator());
   BuildMI(*MBB, InsertPt, MI.getDebugLoc(), TII->get(AMDGPU::S_NOP)).addImm(0);
   MostRecentModeSet = BuildMI(*MBB, InsertPt, MI.getDebugLoc(),
@@ -566,7 +584,6 @@ bool AMDGPULowerVGPREncoding::handleSetregMode(MachineInstr &MI) {
                           .addImm(ModeValue | (ModeValue << ModeWidth));
   LLVM_DEBUG(dbgs() << "    -> inserted S_SET_VGPR_MSB after setreg: "
                     << *MostRecentModeSet);
-  return true;
 }
 
 bool AMDGPULowerVGPREncoding::run(MachineFunction &MF) {
@@ -623,7 +640,7 @@ bool AMDGPULowerVGPREncoding::run(MachineFunction &MF) {
         continue;
       }
 
-      if (MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 &&
+      if (SIInstrInfo::isSSetReg(MI.getOpcode()) &&
           ST.hasSetregVGPRMSBFixup()) {
         Changed |= handleSetregMode(MI);
         continue;
diff --git a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp
index 9d01a529eb012..3c0d9656dc4ab 100644
--- a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp
@@ -459,17 +459,6 @@ static bool isSGetReg(unsigned Opcode) {
   return Opcode == AMDGPU::S_GETREG_B32 || Opcode == AMDGPU::S_GETREG_B32_const;
 }
 
-static bool isSSetReg(unsigned Opcode) {
-  switch (Opcode) {
-  case AMDGPU::S_SETREG_B32:
-  case AMDGPU::S_SETREG_B32_mode:
-  case AMDGPU::S_SETREG_IMM32_B32:
-  case AMDGPU::S_SETREG_IMM32_B32_mode:
-    return true;
-  }
-  return false;
-}
-
 static bool isRWLane(unsigned Opcode) {
   return Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32;
 }
@@ -615,7 +604,7 @@ GCNHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
   if (isSGetReg(MI->getOpcode()) && checkGetRegHazards(MI) > 0)
     return HazardType;
 
-  if (isSSetReg(MI->getOpcode()) && checkSetRegHazards(MI) > 0)
+  if (SIInstrInfo::isSSetReg(MI->getOpcode()) && checkSetRegHazards(MI) > 0)
     return HazardType;
 
   if (isRFE(MI->getOpcode()) && checkRFEHazards(MI) > 0)
@@ -773,7 +762,7 @@ unsigned GCNHazardRecognizer::PreEmitNoopsCommon(MachineInstr *MI) const {
   if (isSGetReg(MI->getOpcode()))
     return std::max(WaitStates, checkGetRegHazards(MI));
 
-  if (isSSetReg(MI->getOpcode()))
+  if (SIInstrInfo::isSSetReg(MI->getOpcode()))
     return std::max(WaitStates, checkSetRegHazards(MI));
 
   if (isRFE(MI->getOpcode()))
@@ -1094,7 +1083,7 @@ int GCNHazardRecognizer::getWaitStatesSinceDef(unsigned Reg,
 int GCNHazardRecognizer::getWaitStatesSinceSetReg(IsHazardFn IsHazard,
                                                   int Limit) const {
   auto IsHazardFn = [IsHazard](const MachineInstr &MI) {
-    return isSSetReg(MI.getOpcode()) && IsHazard(MI);
+    return SIInstrInfo::isSSetReg(MI.getOpcode()) && IsHazard(MI);
   };
 
   return getWaitStatesSince(IsHazardFn, Limit);
@@ -4300,7 +4289,7 @@ bool GCNHazardRecognizer::fixScratchBaseForwardingHazard(MachineInstr *MI) {
 }
 
 bool GCNHazardRecognizer::fixSetRegMode(MachineInstr *MI) {
-  if (!isSSetReg(MI->getOpcode()) ||
+  if (!SIInstrInfo::isSSetReg(MI->getOpcode()) ||
       MI->getOperand(1).getImm() != AMDGPU::Hwreg::ID_MODE)
     return false;
 
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index a62a753b41b08..b49524be99c98 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -1252,6 +1252,19 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
     }
   }
 
+  /// \returns true if \p Opcode is any S_SETREG_B32/S_SETREG_IMM32_B32 variant.
+  static bool isSSetReg(unsigned Opcode) {
+    switch (Opcode) {
+    case AMDGPU::S_SETREG_B32:
+    case AMDGPU::S_SETREG_B32_mode:
+    case AMDGPU::S_SETREG_IMM32_B32:
+    case AMDGPU::S_SETREG_IMM32_B32_mode:
+      return true;
+    default:
+      return false;
+    }
+  }
+
   bool isVGPRCopy(const MachineInstr &MI) const {
     assert(isCopyInstr(MI));
     Register Dest = MI.getOperand(0).getReg();
diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
new file mode 100644
index 0000000000000..ab53e3fa6f19c
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
@@ -0,0 +1,27 @@
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 < %s | FileCheck %s
+
+; llvm.set.rounding lowers to s_setreg_b32(MODE), leaving garbage in
+; bits[19:12] of the SGPR operand, so the tracked mode must be re-established.
+
+declare void @llvm.set.rounding(i32)
+
+; CHECK-LABEL: {{^}}dynamic_rounding_mode_with_high_vgprs:
+; CHECK: s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
+; CHECK-NEXT: s_nop 0
+; CHECK-NEXT: s_set_vgpr_msb 0x4141
+define amdgpu_kernel void @dynamic_rounding_mode_with_high_vgprs(ptr addrspace(1) %p, ptr addrspace(1) %q, i32 %mode) #0 {
+  %a = load volatile <64 x float>, ptr addrspace(1) %p
+  %b = load volatile <64 x float>, ptr addrspace(1) %p
+  %c = load volatile <64 x float>, ptr addrspace(1) %p
+  %d = load volatile <64 x float>, ptr addrspace(1) %p
+  %e = load volatile <64 x float>, ptr addrspace(1) %p
+  store volatile <64 x float> %a, ptr addrspace(1) %q
+  call void @llvm.set.rounding(i32 %mode)
+  %sum = call <64 x float> @llvm.experimental.constrained.fadd.v64f32(<64 x float> %b, <64 x float> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+  store volatile <64 x float> %sum, ptr addrspace(1) %q
+  store volatile <64 x float> %d, ptr addrspace(1) %q
+  store volatile <64 x float> %e, ptr addrspace(1) %q
+  ret void
+}
+
+attributes #0 = { strictfp "amdgpu-flat-work-group-size"="1,32" "amdgpu-waves-per-eu"="1,1" }
diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir
index b9c3cdb3db45f..b0a0143325f07 100644
--- a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir
+++ b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.mir
@@ -517,3 +517,125 @@ body:             |
     S_SETREG_IMM32_B32 23228, 30785, implicit-def $mode, implicit $mode
     S_ENDPGM 0
 ...
+
+---
+# S_SETREG_IMM32_B32_mode clobbers VGPR MSBs the same way as S_SETREG_IMM32_B32.
+
+# ASM-LABEL: {{^}}setreg_imm32_mode_variant:
+# ASM: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), 0x5005
+
+# DIS-LABEL: <setreg_imm32_mode_variant>:
+# DIS: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), 0x5005
+# DIS-NEXT: v_mov_b32_e32 v2 /*v258*/, v3 /*v259*/
+
+name:            setreg_imm32_mode_variant
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    ; CHECK-LABEL: name: setreg_imm32_mode_variant
+    ; 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_mode 20485, 6145, implicit-def $mode, implicit $mode
+    ; CHECK-NEXT: $vgpr258 = V_MOV_B32_e32 $vgpr259, implicit $exec
+    ; CHECK-NEXT: S_ENDPGM 0
+    $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; size=4, offset=0, hwreg=MODE: simm16 = 0x1801 = 6145
+    S_SETREG_IMM32_B32_mode 5, 6145, implicit-def $mode, implicit $mode
+    $vgpr258 = V_MOV_B32_e32 $vgpr259, implicit $exec
+    S_ENDPGM 0
+...
+
+---
+# Register variants write an SGPR to MODE, so the VGPR MSBs are unknown at
+# compile time and must always be restored.
+
+# ASM-LABEL: {{^}}setreg_sgpr:
+# ASM: s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
+# ASM-NEXT: s_nop 0
+# ASM-NEXT: s_set_vgpr_msb 0x4141
+
+# DIS-LABEL: <setreg_sgpr>:
+# DIS: s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
+# DIS-NEXT: s_nop 0
+# DIS-NEXT: s_set_vgpr_msb 0x4141
+# DIS-NEXT: v_mov_b32_e32 v2 /*v258*/, v3 /*v259*/
+
+name:            setreg_sgpr
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $sgpr0
+    ; CHECK-LABEL: name: setreg_sgpr
+    ; CHECK: S_SET_VGPR_MSB 65, implicit-def $mode
+    ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; CHECK-NEXT: S_SETREG_B32 $sgpr0, 6145, implicit-def $mode, implicit $mode
+    ; CHECK-NEXT: S_NOP 0
+    ; CHECK-NEXT: S_SET_VGPR_MSB 16705, implicit-def $mode
+    ; CHECK-NEXT: $vgpr258 = V_MOV_B32_e32 $vgpr259, implicit $exec
+    ; CHECK-NEXT: S_ENDPGM 0
+    $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; size=4, offset=0, hwreg=MODE: simm16 = 0x1801 = 6145
+    S_SETREG_B32 $sgpr0, 6145, implicit-def $mode, implicit $mode
+    $vgpr258 = V_MOV_B32_e32 $vgpr259, implicit $exec
+    S_ENDPGM 0
+...
+
+---
+# ASM-LABEL: {{^}}setreg_sgpr_mode_variant:
+# ASM: s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
+# ASM-NEXT: s_nop 0
+# ASM-NEXT: s_set_vgpr_msb 0x4141
+
+# DIS-LABEL: <setreg_sgpr_mode_variant>:
+# DIS: s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
+# DIS-NEXT: s_nop 0
+# DIS-NEXT: s_set_vgpr_msb 0x4141
+# DIS-NEXT: v_mov_b32_e32 v2 /*v258*/, v3 /*v259*/
+
+name:            setreg_sgpr_mode_variant
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $sgpr0
+    ; CHECK-LABEL: name: setreg_sgpr_mode_variant
+    ; CHECK: S_SET_VGPR_MSB 65, implicit-def $mode
+    ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; CHECK-NEXT: S_SETREG_B32_mode $sgpr0, 6145, implicit-def $mode, implicit $mode
+    ; CHECK-NEXT: S_NOP 0
+    ; CHECK-NEXT: S_SET_VGPR_MSB 16705, implicit-def $mode
+    ; CHECK-NEXT: $vgpr258 = V_MOV_B32_e32 $vgpr259, implicit $exec
+    ; CHECK-NEXT: S_ENDPGM 0
+    $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; size=4, offset=0, hwreg=MODE: simm16 = 0x1801 = 6145
+    S_SETREG_B32_mode $sgpr0, 6145, implicit-def $mode, implicit $mode
+    $vgpr258 = V_MOV_B32_e32 $vgpr259, implicit $exec
+    S_ENDPGM 0
+...
+
+---
+# A non-MODE register setreg must be left alone.
+
+# ASM-LABEL: {{^}}setreg_sgpr_non_mode:
+# ASM: s_setreg_b32 hwreg(HW_REG_WAVE_STATUS, 0, 4), s0
+# ASM-NOT: s_set_vgpr_msb
+# ASM: s_endpgm
+
+# DIS-LABEL: <setreg_sgpr_non_mode>:
+# DIS: s_setreg_b32 hwreg(HW_REG_WAVE_STATUS, 0, 4), s0
+# DIS-NEXT: s_endpgm
+
+name:            setreg_sgpr_non_mode
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $sgpr0
+    ; CHECK-LABEL: name: setreg_sgpr_non_mode
+    ; CHECK: S_SET_VGPR_MSB 65, implicit-def $mode
+    ; CHECK-NEXT: $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; CHECK-NEXT: S_SETREG_B32 $sgpr0, 6146, implicit-def $mode, implicit $mode
+    ; CHECK-NEXT: S_ENDPGM 0
+    $vgpr256 = V_MOV_B32_e32 $vgpr257, implicit $exec
+    ; size=4, offset=0, hwreg=STATUS: simm16 = 0x1802 = 6146
+    S_SETREG_B32 $sgpr0, 6146, implicit-def $mode, implicit $mode
+    S_ENDPGM 0
+...

>From d66ae6c75b003b75b60e6578c3b80c8e6f587970 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 26 Aug 2026 21:41:59 +0200
Subject: [PATCH 2/4] comments part 1

---
 llvm/lib/Target/AMDGPU/SIInstrInfo.cpp    | 7 +++----
 llvm/lib/Target/AMDGPU/SIModeRegister.cpp | 5 +----
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index bc419d813f171..d26ed603efce6 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -3597,15 +3597,14 @@ bool SIInstrInfo::isXcntDrain(const MachineInstr &MI) {
   if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
     return true;
 
+  if (isSSetReg(MI.getOpcode()))
+    return true;
+
   switch (MI.getOpcode()) {
   case AMDGPU::S_ENDPGM:
   case AMDGPU::S_ENDPGM_SAVED:
   case AMDGPU::S_TRAP:
   case AMDGPU::S_GETREG_B32:
-  case AMDGPU::S_SETREG_B32:
-  case AMDGPU::S_SETREG_B32_mode:
-  case AMDGPU::S_SETREG_IMM32_B32:
-  case AMDGPU::S_SETREG_IMM32_B32_mode:
   case AMDGPU::S_SENDMSG:
   case AMDGPU::S_SENDMSGHALT:
   case AMDGPU::S_SENDMSG_RTN_B32:
diff --git a/llvm/lib/Target/AMDGPU/SIModeRegister.cpp b/llvm/lib/Target/AMDGPU/SIModeRegister.cpp
index f9b33b4175c2f..98d245c2390cd 100644
--- a/llvm/lib/Target/AMDGPU/SIModeRegister.cpp
+++ b/llvm/lib/Target/AMDGPU/SIModeRegister.cpp
@@ -273,10 +273,7 @@ void SIModeRegister::processBlockPhase1(MachineBasicBlock &MBB,
   Status IPChange;
   for (MachineInstr &MI : MBB) {
     Status InstrMode = getInstructionMode(MI, TII);
-    if (MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
-        MI.getOpcode() == AMDGPU::S_SETREG_B32_mode ||
-        MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
-        MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32_mode) {
+    if (SIInstrInfo::isSSetReg(MI.getOpcode())) {
       // We preserve any explicit mode register setreg instruction we encounter,
       // as we assume it has been inserted by a higher authority (this is
       // likely to be a very rare occurrence).

>From 8d8ced814ccdf0736efe5b6893b8ff8a170a15d2 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 27 Aug 2026 06:13:27 +0200
Subject: [PATCH 3/4] comments part 2

---
 .../CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll   | 408 +++++++++++++++++-
 1 file changed, 401 insertions(+), 7 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
index ab53e3fa6f19c..fbeba56244ac7 100644
--- a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
+++ b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
@@ -1,15 +1,409 @@
-; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=amdgpu12.50-amd-amdhsa < %s | FileCheck %s
 
 ; llvm.set.rounding lowers to s_setreg_b32(MODE), leaving garbage in
 ; bits[19:12] of the SGPR operand, so the tracked mode must be re-established.
 
-declare void @llvm.set.rounding(i32)
-
-; CHECK-LABEL: {{^}}dynamic_rounding_mode_with_high_vgprs:
-; CHECK: s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
-; CHECK-NEXT: s_nop 0
-; CHECK-NEXT: s_set_vgpr_msb 0x4141
 define amdgpu_kernel void @dynamic_rounding_mode_with_high_vgprs(ptr addrspace(1) %p, ptr addrspace(1) %q, i32 %mode) #0 {
+; CHECK-LABEL: dynamic_rounding_mode_with_high_vgprs:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_set_vgpr_msb 64 ; msbs: dst=1 src0=0 src1=0 src2=0
+; CHECK-NEXT:    v_mov_b32_e32 v64 /*v320*/, 0
+; CHECK-NEXT:    s_set_vgpr_msb 0x4001 ; msbs: dst=0 src0=1 src1=0 src2=0
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[0:3], v64 /*v320*/, s[0:1] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[4:7], v64 /*v320*/, s[0:1] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[8:11], v64 /*v320*/, s[0:1] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[12:15], v64 /*v320*/, s[0:1] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[16:19], v64 /*v320*/, s[0:1] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[20:23], v64 /*v320*/, s[0:1] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[24:27], v64 /*v320*/, s[0:1] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[28:31], v64 /*v320*/, s[0:1] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[32:35], v64 /*v320*/, s[0:1] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[36:39], v64 /*v320*/, s[0:1] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[40:43], v64 /*v320*/, s[0:1] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[44:47], v64 /*v320*/, s[0:1] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[48:51], v64 /*v320*/, s[0:1] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[52:55], v64 /*v320*/, s[0:1] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[56:59], v64 /*v320*/, s[0:1] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[60:63], v64 /*v320*/, s[0:1] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[64:67], v64 /*v320*/, s[0:1] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[68:71], v64 /*v320*/, s[0:1] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[72:75], v64 /*v320*/, s[0:1] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[76:79], v64 /*v320*/, s[0:1] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[80:83], v64 /*v320*/, s[0:1] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[84:87], v64 /*v320*/, s[0:1] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[88:91], v64 /*v320*/, s[0:1] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[92:95], v64 /*v320*/, s[0:1] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[96:99], v64 /*v320*/, s[0:1] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[100:103], v64 /*v320*/, s[0:1] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[104:107], v64 /*v320*/, s[0:1] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[108:111], v64 /*v320*/, s[0:1] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[112:115], v64 /*v320*/, s[0:1] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[116:119], v64 /*v320*/, s[0:1] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[120:123], v64 /*v320*/, s[0:1] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[124:127], v64 /*v320*/, s[0:1] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[128:131], v64 /*v320*/, s[0:1] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[132:135], v64 /*v320*/, s[0:1] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[136:139], v64 /*v320*/, s[0:1] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[140:143], v64 /*v320*/, s[0:1] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[144:147], v64 /*v320*/, s[0:1] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[148:151], v64 /*v320*/, s[0:1] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[152:155], v64 /*v320*/, s[0:1] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[156:159], v64 /*v320*/, s[0:1] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[160:163], v64 /*v320*/, s[0:1] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[164:167], v64 /*v320*/, s[0:1] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[168:171], v64 /*v320*/, s[0:1] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[172:175], v64 /*v320*/, s[0:1] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[176:179], v64 /*v320*/, s[0:1] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[180:183], v64 /*v320*/, s[0:1] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[184:187], v64 /*v320*/, s[0:1] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[188:191], v64 /*v320*/, s[0:1] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[192:195], v64 /*v320*/, s[0:1] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[196:199], v64 /*v320*/, s[0:1] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[200:203], v64 /*v320*/, s[0:1] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[204:207], v64 /*v320*/, s[0:1] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[208:211], v64 /*v320*/, s[0:1] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[212:215], v64 /*v320*/, s[0:1] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[216:219], v64 /*v320*/, s[0:1] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[220:223], v64 /*v320*/, s[0:1] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[224:227], v64 /*v320*/, s[0:1] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[228:231], v64 /*v320*/, s[0:1] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[232:235], v64 /*v320*/, s[0:1] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[236:239], v64 /*v320*/, s[0:1] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[240:243], v64 /*v320*/, s[0:1] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[244:247], v64 /*v320*/, s[0:1] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[248:251], v64 /*v320*/, s[0:1] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[252:255], v64 /*v320*/, s[0:1] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_set_vgpr_msb 0x141 ; msbs: dst=1 src0=1 src1=0 src2=0
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[0:3] /*v[256:259]*/, v64 /*v320*/, s[0:1] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[4:7] /*v[260:263]*/, v64 /*v320*/, s[0:1] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[8:11] /*v[264:267]*/, v64 /*v320*/, s[0:1] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[12:15] /*v[268:271]*/, v64 /*v320*/, s[0:1] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[16:19] /*v[272:275]*/, v64 /*v320*/, s[0:1] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[20:23] /*v[276:279]*/, v64 /*v320*/, s[0:1] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[24:27] /*v[280:283]*/, v64 /*v320*/, s[0:1] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[28:31] /*v[284:287]*/, v64 /*v320*/, s[0:1] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[32:35] /*v[288:291]*/, v64 /*v320*/, s[0:1] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[36:39] /*v[292:295]*/, v64 /*v320*/, s[0:1] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[40:43] /*v[296:299]*/, v64 /*v320*/, s[0:1] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[44:47] /*v[300:303]*/, v64 /*v320*/, s[0:1] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[48:51] /*v[304:307]*/, v64 /*v320*/, s[0:1] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[52:55] /*v[308:311]*/, v64 /*v320*/, s[0:1] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[56:59] /*v[312:315]*/, v64 /*v320*/, s[0:1] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_load_b128 v[60:63] /*v[316:319]*/, v64 /*v320*/, s[0:1] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[60:63], s[2:3] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[56:59], s[2:3] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[52:55], s[2:3] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[48:51], s[2:3] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[44:47], s[2:3] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[40:43], s[2:3] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[36:39], s[2:3] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[32:35], s[2:3] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[28:31], s[2:3] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[24:27], s[2:3] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[20:23], s[2:3] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[16:19], s[2:3] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[12:15], s[2:3] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[8:11], s[2:3] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[4:7], s[2:3] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[0:3], s[2:3] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_sleep_var 0x1801
+; CHECK-NEXT:    s_set_vgpr_msb 0x4100 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    v_dual_add_f32 v63, v67, v131 :: v_dual_add_f32 v62, v66, v130
+; CHECK-NEXT:    v_dual_add_f32 v61, v65, v129 :: v_dual_add_f32 v60, v64, v128
+; CHECK-NEXT:    v_dual_add_f32 v53, v73, v137 :: v_dual_add_f32 v59, v71, v135
+; CHECK-NEXT:    v_dual_add_f32 v58, v70, v134 :: v_dual_add_f32 v57, v69, v133
+; CHECK-NEXT:    v_dual_add_f32 v56, v68, v132 :: v_dual_add_f32 v55, v75, v139
+; CHECK-NEXT:    v_dual_add_f32 v54, v74, v138 :: v_dual_add_f32 v52, v72, v136
+; CHECK-NEXT:    v_dual_add_f32 v45, v81, v145 :: v_dual_add_f32 v51, v79, v143
+; CHECK-NEXT:    v_dual_add_f32 v50, v78, v142 :: v_dual_add_f32 v49, v77, v141
+; CHECK-NEXT:    v_dual_add_f32 v48, v76, v140 :: v_dual_add_f32 v47, v83, v147
+; CHECK-NEXT:    v_dual_add_f32 v46, v82, v146 :: v_dual_add_f32 v44, v80, v144
+; CHECK-NEXT:    v_dual_add_f32 v3, v127, v191 :: v_dual_add_f32 v2, v126, v190
+; CHECK-NEXT:    v_dual_add_f32 v1, v125, v189 :: v_dual_add_f32 v0, v124, v188
+; CHECK-NEXT:    v_dual_add_f32 v7, v123, v187 :: v_dual_add_f32 v6, v122, v186
+; CHECK-NEXT:    v_dual_add_f32 v5, v121, v185 :: v_dual_add_f32 v4, v120, v184
+; CHECK-NEXT:    v_dual_add_f32 v11, v119, v183 :: v_dual_add_f32 v10, v118, v182
+; CHECK-NEXT:    v_dual_add_f32 v9, v117, v181 :: v_dual_add_f32 v8, v116, v180
+; CHECK-NEXT:    v_dual_add_f32 v15, v115, v179 :: v_dual_add_f32 v14, v114, v178
+; CHECK-NEXT:    v_dual_add_f32 v13, v113, v177 :: v_dual_add_f32 v12, v112, v176
+; CHECK-NEXT:    v_dual_add_f32 v19, v111, v175 :: v_dual_add_f32 v18, v110, v174
+; CHECK-NEXT:    v_dual_add_f32 v17, v109, v173 :: v_dual_add_f32 v16, v108, v172
+; CHECK-NEXT:    v_dual_add_f32 v23, v107, v171 :: v_dual_add_f32 v22, v106, v170
+; CHECK-NEXT:    v_dual_add_f32 v21, v105, v169 :: v_dual_add_f32 v20, v104, v168
+; CHECK-NEXT:    v_dual_add_f32 v27, v103, v167 :: v_dual_add_f32 v26, v102, v166
+; CHECK-NEXT:    v_dual_add_f32 v25, v101, v165 :: v_dual_add_f32 v24, v100, v164
+; CHECK-NEXT:    v_dual_add_f32 v31, v99, v163 :: v_dual_add_f32 v30, v98, v162
+; CHECK-NEXT:    v_dual_add_f32 v29, v97, v161 :: v_dual_add_f32 v28, v96, v160
+; CHECK-NEXT:    v_dual_add_f32 v35, v95, v159 :: v_dual_add_f32 v34, v94, v158
+; CHECK-NEXT:    v_dual_add_f32 v33, v93, v157 :: v_dual_add_f32 v32, v92, v156
+; CHECK-NEXT:    v_dual_add_f32 v39, v91, v155 :: v_dual_add_f32 v38, v90, v154
+; CHECK-NEXT:    v_dual_add_f32 v37, v89, v153 :: v_dual_add_f32 v36, v88, v152
+; CHECK-NEXT:    v_dual_add_f32 v43, v87, v151 :: v_dual_add_f32 v42, v86, v150
+; CHECK-NEXT:    v_dual_add_f32 v41, v85, v149 :: v_dual_add_f32 v40, v84, v148
+; CHECK-NEXT:    s_set_vgpr_msb 1 ; msbs: dst=0 src0=1 src1=0 src2=0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[60:63], s[2:3] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[56:59], s[2:3] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[52:55], s[2:3] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[48:51], s[2:3] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[44:47], s[2:3] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[40:43], s[2:3] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[36:39], s[2:3] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[32:35], s[2:3] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[28:31], s[2:3] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[24:27], s[2:3] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[20:23], s[2:3] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[16:19], s[2:3] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[12:15], s[2:3] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[8:11], s[2:3] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[4:7], s[2:3] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[0:3], s[2:3] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[252:255], s[2:3] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[248:251], s[2:3] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[244:247], s[2:3] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[240:243], s[2:3] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[236:239], s[2:3] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[232:235], s[2:3] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[228:231], s[2:3] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[224:227], s[2:3] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[220:223], s[2:3] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[216:219], s[2:3] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[212:215], s[2:3] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[208:211], s[2:3] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[204:207], s[2:3] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[200:203], s[2:3] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[196:199], s[2:3] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[192:195], s[2:3] scope:SCOPE_SYS
+; CHECK-NEXT:    s_set_vgpr_msb 0x105 ; msbs: dst=0 src0=1 src1=1 src2=0
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[60:63] /*v[316:319]*/, s[2:3] offset:224 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[56:59] /*v[312:315]*/, s[2:3] offset:240 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[52:55] /*v[308:311]*/, s[2:3] offset:192 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[48:51] /*v[304:307]*/, s[2:3] offset:208 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[44:47] /*v[300:303]*/, s[2:3] offset:160 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[40:43] /*v[296:299]*/, s[2:3] offset:176 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[36:39] /*v[292:295]*/, s[2:3] offset:128 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[32:35] /*v[288:291]*/, s[2:3] offset:144 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[28:31] /*v[284:287]*/, s[2:3] offset:96 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[24:27] /*v[280:283]*/, s[2:3] offset:112 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[20:23] /*v[276:279]*/, s[2:3] offset:64 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[16:19] /*v[272:275]*/, s[2:3] offset:80 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[12:15] /*v[268:271]*/, s[2:3] offset:32 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[8:11] /*v[264:267]*/, s[2:3] offset:48 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[4:7] /*v[260:263]*/, s[2:3] scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_wait_xcnt 0x0
+; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[0:3] /*v[256:259]*/, s[2:3] offset:16 scope:SCOPE_SYS
+; CHECK-NEXT:    s_wait_storecnt 0x0
+; CHECK-NEXT:    s_sendmsg sendmsg(MSG_DEALLOC_VGPRS)
+; CHECK-NEXT:    s_endpgm
   %a = load volatile <64 x float>, ptr addrspace(1) %p
   %b = load volatile <64 x float>, ptr addrspace(1) %p
   %c = load volatile <64 x float>, ptr addrspace(1) %p

>From d206186001808b9c9bf0d1aa1d133b0e1fe41a90 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 27 Aug 2026 09:38:24 +0200
Subject: [PATCH 4/4] fix test

---
 llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
index fbeba56244ac7..0f7d43cccef21 100644
--- a/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
+++ b/llvm/test/CodeGen/AMDGPU/vgpr-setreg-mode-swar.ll
@@ -14,6 +14,7 @@ define amdgpu_kernel void @dynamic_rounding_mode_with_high_vgprs(ptr addrspace(1
 ; CHECK-NEXT:    s_load_b128 s[0:3], s[4:5], 0x0 nv
 ; CHECK-NEXT:    s_set_vgpr_msb 64 ; msbs: dst=1 src0=0 src1=0 src2=0
 ; CHECK-NEXT:    v_mov_b32_e32 v64 /*v320*/, 0
+; CHECK-NEXT:    s_load_b32 s4, s[4:5], 0x10 nv
 ; CHECK-NEXT:    s_set_vgpr_msb 0x4001 ; msbs: dst=0 src0=1 src1=0 src2=0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
 ; CHECK-NEXT:    global_load_b128 v[0:3], v64 /*v320*/, s[0:1] offset:16 scope:SCOPE_SYS
@@ -224,7 +225,13 @@ define amdgpu_kernel void @dynamic_rounding_mode_with_high_vgprs(ptr addrspace(1
 ; CHECK-NEXT:    s_wait_xcnt 0x0
 ; CHECK-NEXT:    global_store_b128 v64 /*v320*/, v[0:3], s[2:3] offset:16 scope:SCOPE_SYS
 ; CHECK-NEXT:    s_wait_storecnt 0x0
-; CHECK-NEXT:    s_sleep_var 0x1801
+; CHECK-NEXT:    s_add_co_i32 s0, s4, -4
+; CHECK-NEXT:    s_min_u32 s0, s4, s0
+; CHECK-NEXT:    s_lshl_b32 s0, s0, 2
+; CHECK-NEXT:    s_lshr_b64 s[0:1], 0xb73e62d91c84a50f, s0
+; CHECK-NEXT:    s_setreg_b32 hwreg(HW_REG_WAVE_MODE, 0, 4), s0
+; CHECK-NEXT:    s_nop 0
+; CHECK-NEXT:    s_set_vgpr_msb 0x4141 ; msbs: dst=1 src0=1 src1=0 src2=0
 ; CHECK-NEXT:    s_set_vgpr_msb 0x4100 ; msbs: dst=0 src0=0 src1=0 src2=0
 ; CHECK-NEXT:    v_dual_add_f32 v63, v67, v131 :: v_dual_add_f32 v62, v66, v130
 ; CHECK-NEXT:    v_dual_add_f32 v61, v65, v129 :: v_dual_add_f32 v60, v64, v128



More information about the llvm-commits mailing list