[llvm] [AMDGPU] Let SIOptimizeVGPRLiveRange handle AV-class virtual registers (PR #226527)
Pablo Reble via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 14:47:34 PDT 2026
https://github.com/reble updated https://github.com/llvm/llvm-project/pull/226527
>From d7ee1a38ace51188faf200eff32ffa72ecb9e65b Mon Sep 17 00:00:00 2001
From: Pablo Reble <pablo.reble at amd.com>
Date: Fri, 25 Sep 2026 10:11:55 -0500
Subject: [PATCH 1/2] [AMDGPU] Let SIOptimizeVGPRLiveRange handle AV-class
virtual registers
---
.../Target/AMDGPU/SIOptimizeVGPRLiveRange.cpp | 20 +-
.../test/CodeGen/AMDGPU/a-v-flat-atomicrmw.ll | 2 +
.../si-opt-vgpr-liverange-av-classes.mir | 330 ++++++++++++++++++
3 files changed, 347 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
diff --git a/llvm/lib/Target/AMDGPU/SIOptimizeVGPRLiveRange.cpp b/llvm/lib/Target/AMDGPU/SIOptimizeVGPRLiveRange.cpp
index c72b40e14ee0e..e7755de608ade 100644
--- a/llvm/lib/Target/AMDGPU/SIOptimizeVGPRLiveRange.cpp
+++ b/llvm/lib/Target/AMDGPU/SIOptimizeVGPRLiveRange.cpp
@@ -108,6 +108,9 @@ class SIOptimizeVGPRLiveRange {
// in.
bool isLiveIntoMBB(Register Reg, const MachineBasicBlock *MBB) const;
+ // Is \p Reg a virtual register of a vector class without SGPRs?
+ bool isVectorVirtReg(Register Reg) const;
+
public:
SIOptimizeVGPRLiveRange(LiveIntervals *LIS, LiveVariables *LV,
MachineDominatorTree *MDT, MachineLoopInfo *Loops)
@@ -217,6 +220,13 @@ bool SIOptimizeVGPRLiveRange::isLiveIntoMBB(
return LIS->isLiveInToMBB(LI, MBB);
}
+bool SIOptimizeVGPRLiveRange::isVectorVirtReg(Register Reg) const {
+ if (!Reg.isVirtual())
+ return false;
+ const TargetRegisterClass *RC = MRI->getRegClass(Reg);
+ return TRI->hasVectorRegisters(RC) && !TRI->hasSGPRs(RC);
+}
+
void SIOptimizeVGPRLiveRange::collectElseRegionBlocks(
MachineBasicBlock *Flow, MachineBasicBlock *Endif,
SmallSetVector<MachineBasicBlock *, 16> &Blocks) const {
@@ -274,8 +284,8 @@ void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
continue;
Register MOReg = MO.getReg();
- // We can only optimize AGPR/VGPR virtual register
- if (MOReg.isPhysical() || !TRI->isVectorRegister(*MRI, MOReg))
+ // We can only optimize VGPR/AGPR/AV virtual registers.
+ if (!isVectorVirtReg(MOReg))
continue;
if (MO.readsReg()) {
@@ -313,7 +323,7 @@ void SIOptimizeVGPRLiveRange::collectCandidateRegisters(
continue;
Register Reg = MO.getReg();
- if (Reg.isPhysical() || !TRI->isVectorRegister(*MRI, Reg))
+ if (!isVectorVirtReg(Reg))
continue;
if (isLiveIntoMBB(Reg, Endif)) {
@@ -396,8 +406,8 @@ void SIOptimizeVGPRLiveRange::collectWaterfallCandidateRegisters(
continue;
Register MOReg = MO.getReg();
- // We can only optimize AGPR/VGPR virtual register
- if (MOReg.isPhysical() || !TRI->isVectorRegister(*MRI, MOReg))
+ // We can only optimize VGPR/AGPR/AV virtual registers.
+ if (!isVectorVirtReg(MOReg))
continue;
if (MO.readsReg()) {
diff --git a/llvm/test/CodeGen/AMDGPU/a-v-flat-atomicrmw.ll b/llvm/test/CodeGen/AMDGPU/a-v-flat-atomicrmw.ll
index cb59bb925aab0..cd8d0122263b5 100644
--- a/llvm/test/CodeGen/AMDGPU/a-v-flat-atomicrmw.ll
+++ b/llvm/test/CodeGen/AMDGPU/a-v-flat-atomicrmw.ll
@@ -1519,6 +1519,7 @@ define void @flat_atomic_xchg_i64_noret_av(ptr %ptr) #0 {
; GFX90A-NEXT: buffer_invl2
; GFX90A-NEXT: buffer_wbinvl1_vol
; GFX90A-NEXT: ; implicit-def: $vgpr0_vgpr1
+; GFX90A-NEXT: ; implicit-def: $vgpr2_vgpr3
; GFX90A-NEXT: s_andn2_saveexec_b64 s[4:5], s[4:5]
; GFX90A-NEXT: s_cbranch_execz .LBB20_2
; GFX90A-NEXT: .LBB20_4: ; %atomicrmw.private
@@ -1554,6 +1555,7 @@ define void @flat_atomic_xchg_i64_noret_av(ptr %ptr) #0 {
; GFX950-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0)
; GFX950-NEXT: buffer_inv sc0 sc1
; GFX950-NEXT: ; implicit-def: $vgpr0_vgpr1
+; GFX950-NEXT: ; implicit-def: $vgpr2_vgpr3
; GFX950-NEXT: s_andn2_saveexec_b64 s[0:1], s[0:1]
; GFX950-NEXT: s_cbranch_execz .LBB20_2
; GFX950-NEXT: .LBB20_4: ; %atomicrmw.private
diff --git a/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir b/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
new file mode 100644
index 0000000000000..d331d81d14e80
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
@@ -0,0 +1,330 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgpu9.0a -run-pass=si-opt-vgpr-liverange -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=amdgpu9.0a -passes=si-opt-vgpr-liverange %s -o - | FileCheck %s
+
+# SIOptimizeVGPRLiveRange should handle virtual registers with AV classes the
+# same way as VGPR classes. %0 is killed in the else block, so its live range
+# through the else block is shortened with an undef PHI input in the Flow block.
+
+---
+name: else_av_32
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: else_av_32
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $vgpr0, $vgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY killed $vgpr1
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY killed $vgpr0
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:av_32 = COPY killed [[COPY]]
+ ; CHECK-NEXT: [[V_CMP_GT_I32_e64_:%[0-9]+]]:sreg_64 = V_CMP_GT_I32_e64 6, killed [[COPY1]], implicit $exec
+ ; CHECK-NEXT: [[SI_IF:%[0-9]+]]:sreg_64 = SI_IF killed [[V_CMP_GT_I32_e64_]], %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: S_BRANCH %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.4(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PHI:%[0-9]+]]:av_32 = PHI undef %6:av_32, %bb.0, %7, %bb.3
+ ; CHECK-NEXT: [[PHI1:%[0-9]+]]:av_32 = PHI [[COPY2]], %bb.0, undef %16:av_32, %bb.3
+ ; CHECK-NEXT: [[SI_ELSE:%[0-9]+]]:sreg_64 = SI_ELSE killed [[SI_IF]], %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: S_BRANCH %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.4(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY killed [[PHI1]]
+ ; CHECK-NEXT: [[V_ADD_F32_e32_:%[0-9]+]]:vgpr_32 = nofpexcept V_ADD_F32_e32 killed [[COPY3]], [[COPY3]], implicit $mode, implicit $exec
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:av_32 = COPY killed [[V_ADD_F32_e32_]]
+ ; CHECK-NEXT: S_BRANCH %bb.4
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[COPY2]]
+ ; CHECK-NEXT: [[V_MUL_F32_e32_:%[0-9]+]]:vgpr_32 = nofpexcept V_MUL_F32_e32 1077936128, killed [[COPY5]], implicit $mode, implicit $exec
+ ; CHECK-NEXT: [[COPY6:%[0-9]+]]:av_32 = COPY killed [[V_MUL_F32_e32_]]
+ ; CHECK-NEXT: S_BRANCH %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4:
+ ; CHECK-NEXT: [[PHI2:%[0-9]+]]:av_32 = PHI [[PHI]], %bb.1, [[COPY4]], %bb.2
+ ; CHECK-NEXT: SI_END_CF killed [[SI_ELSE]], implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: $vgpr0 = COPY killed [[PHI2]]
+ ; CHECK-NEXT: SI_RETURN_TO_EPILOG killed $vgpr0
+ bb.0:
+ successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ liveins: $vgpr0, $vgpr1
+
+ %10:vgpr_32 = COPY killed $vgpr1
+ %7:vgpr_32 = COPY killed $vgpr0
+ %0:av_32 = COPY killed %10
+ %14:sreg_64 = V_CMP_GT_I32_e64 6, killed %7, implicit $exec
+ %1:sreg_64 = SI_IF killed %14, %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ S_BRANCH %bb.3
+
+ bb.1:
+ successors: %bb.2(0x40000000), %bb.4(0x40000000)
+
+ %2:av_32 = PHI undef %11:av_32, %bb.0, %5, %bb.3
+ %3:sreg_64 = SI_ELSE killed %1, %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ S_BRANCH %bb.2
+
+ bb.2:
+ successors: %bb.4(0x80000000)
+
+ %20:vgpr_32 = COPY %0
+ %17:vgpr_32 = nofpexcept V_ADD_F32_e32 %20, %20, implicit $mode, implicit $exec
+ %4:av_32 = COPY killed %17
+ S_BRANCH %bb.4
+
+ bb.3:
+ successors: %bb.1(0x80000000)
+
+ %21:vgpr_32 = COPY %0
+ %16:vgpr_32 = nofpexcept V_MUL_F32_e32 1077936128, %21, implicit $mode, implicit $exec
+ %5:av_32 = COPY killed %16
+ S_BRANCH %bb.1
+
+ bb.4:
+ %6:av_32 = PHI %2, %bb.1, %4, %bb.2
+ SI_END_CF killed %3, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ $vgpr0 = COPY killed %6
+ SI_RETURN_TO_EPILOG killed $vgpr0
+...
+
+---
+name: else_av_64
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: else_av_64
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $vgpr0, $vgpr2_vgpr3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vreg_64_align2 = COPY killed $vgpr2_vgpr3
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY killed $vgpr0
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:av_64_align2 = COPY killed [[COPY]]
+ ; CHECK-NEXT: [[V_CMP_GT_I32_e64_:%[0-9]+]]:sreg_64 = V_CMP_GT_I32_e64 6, killed [[COPY1]], implicit $exec
+ ; CHECK-NEXT: [[SI_IF:%[0-9]+]]:sreg_64 = SI_IF killed [[V_CMP_GT_I32_e64_]], %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: S_BRANCH %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.4(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PHI:%[0-9]+]]:av_64_align2 = PHI undef %6:av_64_align2, %bb.0, %7, %bb.3
+ ; CHECK-NEXT: [[PHI1:%[0-9]+]]:av_64_align2 = PHI [[COPY2]], %bb.0, undef %16:av_64_align2, %bb.3
+ ; CHECK-NEXT: [[SI_ELSE:%[0-9]+]]:sreg_64 = SI_ELSE killed [[SI_IF]], %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: S_BRANCH %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.4(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vreg_64_align2 = COPY killed [[PHI1]]
+ ; CHECK-NEXT: [[V_ADD_F64_e64_:%[0-9]+]]:vreg_64_align2 = nofpexcept V_ADD_F64_e64 0, killed [[COPY3]], 0, [[COPY3]], 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:av_64_align2 = COPY killed [[V_ADD_F64_e64_]]
+ ; CHECK-NEXT: S_BRANCH %bb.4
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY5:%[0-9]+]]:vreg_64_align2 = COPY killed [[COPY2]]
+ ; CHECK-NEXT: [[V_MUL_F64_e64_:%[0-9]+]]:vreg_64_align2 = nofpexcept V_MUL_F64_e64 0, killed [[COPY5]], 0, [[COPY5]], 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: [[COPY6:%[0-9]+]]:av_64_align2 = COPY killed [[V_MUL_F64_e64_]]
+ ; CHECK-NEXT: S_BRANCH %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4:
+ ; CHECK-NEXT: [[PHI2:%[0-9]+]]:av_64_align2 = PHI [[PHI]], %bb.1, [[COPY4]], %bb.2
+ ; CHECK-NEXT: SI_END_CF killed [[SI_ELSE]], implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: $vgpr0_vgpr1 = COPY killed [[PHI2]]
+ ; CHECK-NEXT: SI_RETURN_TO_EPILOG killed $vgpr0_vgpr1
+ bb.0:
+ successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ liveins: $vgpr0, $vgpr2_vgpr3
+
+ %10:vreg_64_align2 = COPY killed $vgpr2_vgpr3
+ %7:vgpr_32 = COPY killed $vgpr0
+ %0:av_64_align2 = COPY killed %10
+ %14:sreg_64 = V_CMP_GT_I32_e64 6, killed %7, implicit $exec
+ %1:sreg_64 = SI_IF killed %14, %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ S_BRANCH %bb.3
+
+ bb.1:
+ successors: %bb.2(0x40000000), %bb.4(0x40000000)
+
+ %2:av_64_align2 = PHI undef %11:av_64_align2, %bb.0, %5, %bb.3
+ %3:sreg_64 = SI_ELSE killed %1, %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ S_BRANCH %bb.2
+
+ bb.2:
+ successors: %bb.4(0x80000000)
+
+ %20:vreg_64_align2 = COPY %0
+ %17:vreg_64_align2 = nofpexcept V_ADD_F64_e64 0, %20, 0, %20, 0, 0, implicit $mode, implicit $exec
+ %4:av_64_align2 = COPY killed %17
+ S_BRANCH %bb.4
+
+ bb.3:
+ successors: %bb.1(0x80000000)
+
+ %21:vreg_64_align2 = COPY %0
+ %16:vreg_64_align2 = nofpexcept V_MUL_F64_e64 0, %21, 0, %21, 0, 0, implicit $mode, implicit $exec
+ %5:av_64_align2 = COPY killed %16
+ S_BRANCH %bb.1
+
+ bb.4:
+ %6:av_64_align2 = PHI %2, %bb.1, %4, %bb.2
+ SI_END_CF killed %3, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ $vgpr0_vgpr1 = COPY killed %6
+ SI_RETURN_TO_EPILOG killed $vgpr0_vgpr1
+...
+
+# %0 has no use in the else block other than the incoming value of the endif
+# PHI. It is found by the endif PHI scan and gets an undef PHI input in the
+# Flow block.
+---
+name: endif_phi_av_32
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: endif_phi_av_32
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: liveins: $vgpr0, $vgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY killed $vgpr1
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY killed $vgpr0
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:av_32 = COPY killed [[COPY]]
+ ; CHECK-NEXT: [[V_CMP_GT_I32_e64_:%[0-9]+]]:sreg_64 = V_CMP_GT_I32_e64 6, [[COPY1]], implicit $exec
+ ; CHECK-NEXT: [[SI_IF:%[0-9]+]]:sreg_64 = SI_IF killed [[V_CMP_GT_I32_e64_]], %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: S_BRANCH %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.4(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PHI:%[0-9]+]]:av_32 = PHI undef %6:av_32, %bb.0, %7, %bb.3
+ ; CHECK-NEXT: [[PHI1:%[0-9]+]]:av_32 = PHI [[COPY2]], %bb.0, undef %12:av_32, %bb.3
+ ; CHECK-NEXT: [[SI_ELSE:%[0-9]+]]:sreg_64 = SI_ELSE killed [[SI_IF]], %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: S_BRANCH %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.4(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: S_BRANCH %bb.4
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[V_MUL_F32_e32_:%[0-9]+]]:vgpr_32 = nofpexcept V_MUL_F32_e32 1077936128, killed [[COPY1]], implicit $mode, implicit $exec
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:av_32 = COPY killed [[V_MUL_F32_e32_]]
+ ; CHECK-NEXT: S_BRANCH %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4:
+ ; CHECK-NEXT: [[PHI2:%[0-9]+]]:av_32 = PHI [[PHI]], %bb.1, [[PHI1]], %bb.2
+ ; CHECK-NEXT: SI_END_CF killed [[SI_ELSE]], implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: $vgpr0 = COPY killed [[PHI2]]
+ ; CHECK-NEXT: SI_RETURN_TO_EPILOG killed $vgpr0
+ bb.0:
+ successors: %bb.3(0x40000000), %bb.1(0x40000000)
+ liveins: $vgpr0, $vgpr1
+
+ %10:vgpr_32 = COPY killed $vgpr1
+ %7:vgpr_32 = COPY killed $vgpr0
+ %0:av_32 = COPY killed %10
+ %14:sreg_64 = V_CMP_GT_I32_e64 6, %7, implicit $exec
+ %1:sreg_64 = SI_IF killed %14, %bb.1, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ S_BRANCH %bb.3
+
+ bb.1:
+ successors: %bb.2(0x40000000), %bb.4(0x40000000)
+
+ %2:av_32 = PHI undef %11:av_32, %bb.0, %5, %bb.3
+ %3:sreg_64 = SI_ELSE killed %1, %bb.4, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ S_BRANCH %bb.2
+
+ bb.2:
+ successors: %bb.4(0x80000000)
+
+ S_BRANCH %bb.4
+
+ bb.3:
+ successors: %bb.1(0x80000000)
+
+ %16:vgpr_32 = nofpexcept V_MUL_F32_e32 1077936128, killed %7, implicit $mode, implicit $exec
+ %5:av_32 = COPY killed %16
+ S_BRANCH %bb.1
+
+ bb.4:
+ %6:av_32 = PHI %2, %bb.1, %0, %bb.2
+ SI_END_CF killed %3, implicit-def dead $exec, implicit-def dead $scc, implicit $exec
+ $vgpr0 = COPY killed %6
+ SI_RETURN_TO_EPILOG killed $vgpr0
+...
+
+# %1 is defined before the waterfall loop and only used inside it. It gets a
+# PHI in the loop header with an undef input from the loop latch.
+---
+name: waterfall_av_32
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: waterfall_av_32
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: liveins: $vgpr0, $vgpr1, $vgpr2, $sgpr0_sgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY killed $vgpr0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:av_32 = COPY killed $vgpr1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY killed $vgpr2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sreg_64_xexec_xnull = COPY killed $sgpr0_sgpr1
+ ; CHECK-NEXT: [[S_MOV_B64_:%[0-9]+]]:sreg_64_xexec = S_MOV_B64 $exec
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.2(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[PHI:%[0-9]+]]:vgpr_32 = PHI [[COPY]], %bb.0, undef %11:vgpr_32, %bb.2
+ ; CHECK-NEXT: [[PHI1:%[0-9]+]]:av_32 = PHI [[COPY1]], %bb.0, undef %13:av_32, %bb.2
+ ; CHECK-NEXT: [[PHI2:%[0-9]+]]:vgpr_32 = PHI [[COPY2]], %bb.0, undef %15:vgpr_32, %bb.2
+ ; CHECK-NEXT: [[V_READFIRSTLANE_B32_:%[0-9]+]]:sreg_32_xm0 = V_READFIRSTLANE_B32 [[PHI]], implicit $exec
+ ; CHECK-NEXT: [[V_CMP_EQ_U32_e64_:%[0-9]+]]:sreg_64_xexec = V_CMP_EQ_U32_e64 [[V_READFIRSTLANE_B32_]], killed [[PHI]], implicit $exec
+ ; CHECK-NEXT: [[S_AND_SAVEEXEC_B64_:%[0-9]+]]:sreg_64_xexec = S_AND_SAVEEXEC_B64 killed [[V_CMP_EQ_U32_e64_]], implicit-def $exec, implicit-def dead $scc, implicit $exec
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.3(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY killed [[PHI1]]
+ ; CHECK-NEXT: [[V_ADD_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e32 killed [[V_READFIRSTLANE_B32_]], killed [[COPY4]], implicit $exec
+ ; CHECK-NEXT: GLOBAL_STORE_DWORD_SADDR killed [[PHI2]], killed [[V_ADD_U32_e32_]], [[COPY3]], 0, 0, implicit $exec
+ ; CHECK-NEXT: $exec = S_XOR_B64_term $exec, killed [[S_AND_SAVEEXEC_B64_]], implicit-def dead $scc
+ ; CHECK-NEXT: SI_WATERFALL_LOOP %bb.1, implicit $exec
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: $exec = S_MOV_B64 killed [[S_MOV_B64_]]
+ ; CHECK-NEXT: SI_RETURN
+ bb.0:
+ successors: %bb.1(0x80000000)
+ liveins: $vgpr0, $vgpr1, $vgpr2, $sgpr0_sgpr1
+
+ %0:vgpr_32 = COPY killed $vgpr0
+ %1:av_32 = COPY killed $vgpr1
+ %2:vgpr_32 = COPY killed $vgpr2
+ %3:sreg_64_xexec_xnull = COPY killed $sgpr0_sgpr1
+ %4:sreg_64_xexec = S_MOV_B64 $exec
+
+ bb.1:
+ successors: %bb.2(0x80000000)
+
+ %5:sreg_32_xm0 = V_READFIRSTLANE_B32 %0, implicit $exec
+ %6:sreg_64_xexec = V_CMP_EQ_U32_e64 %5, %0, implicit $exec
+ %7:sreg_64_xexec = S_AND_SAVEEXEC_B64 killed %6, implicit-def $exec, implicit-def dead $scc, implicit $exec
+
+ bb.2:
+ successors: %bb.1(0x40000000), %bb.3(0x40000000)
+
+ %8:vgpr_32 = COPY %1
+ %9:vgpr_32 = V_ADD_U32_e32 killed %5, killed %8, implicit $exec
+ GLOBAL_STORE_DWORD_SADDR %2, killed %9, %3, 0, 0, implicit $exec
+ $exec = S_XOR_B64_term $exec, killed %7, implicit-def dead $scc
+ SI_WATERFALL_LOOP %bb.1, implicit $exec
+
+ bb.3:
+ $exec = S_MOV_B64 killed %4
+ SI_RETURN
+...
>From f3395d655468140fbc4413733e0fed657cbcb643 Mon Sep 17 00:00:00 2001
From: Pablo Reble <pablo.reble at amd.com>
Date: Mon, 28 Sep 2026 16:47:19 -0500
Subject: [PATCH 2/2] Update
llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir b/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
index d331d81d14e80..4723835a006f5 100644
--- a/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-opt-vgpr-liverange-av-classes.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=amdgpu9.0a -run-pass=si-opt-vgpr-liverange -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=amdgpu9.0a -run-pass=si-opt-vgpr-liverange %s -o - | FileCheck %s
# RUN: llc -mtriple=amdgpu9.0a -passes=si-opt-vgpr-liverange %s -o - | FileCheck %s
# SIOptimizeVGPRLiveRange should handle virtual registers with AV classes the
More information about the llvm-commits
mailing list