[llvm] [AMDGPU] Use correct SlotIndex to calculate live-out register set. (PR #161720)
Valery Pykhtin via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 3 06:00:14 PDT 2025
https://github.com/vpykhtin updated https://github.com/llvm/llvm-project/pull/161720
>From d27a6de2757d159d13609b3ef864eb48ae546aa9 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Thu, 2 Oct 2025 18:33:54 +0000
Subject: [PATCH 1/3] [AMDGPU] Use correct SlotIndex to calculate live-out
register set.
Using SlotIndexes::getMBBEndIdx() isn't the correct choice here
because it returns the starting index of the next basic block,
causing live-ins of the next block to be calculated instead of
the intended live-outs of the current block.
Add SlotIndexes::getMBBLastIdx() method to return the last valid
SlotIndex within a basic block, enabling correct live-out calculations.
---
llvm/include/llvm/CodeGen/SlotIndexes.h | 17 +++++++-
llvm/lib/Target/AMDGPU/GCNRegPressure.cpp | 39 ++++++++++---------
llvm/lib/Target/AMDGPU/GCNRegPressure.h | 4 +-
.../CodeGen/AMDGPU/regpressure_printer.mir | 18 ++++-----
4 files changed, 45 insertions(+), 33 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SlotIndexes.h b/llvm/include/llvm/CodeGen/SlotIndexes.h
index 1e270b4d9d302..c81c843522b34 100644
--- a/llvm/include/llvm/CodeGen/SlotIndexes.h
+++ b/llvm/include/llvm/CodeGen/SlotIndexes.h
@@ -467,16 +467,29 @@ class raw_ostream;
return getMBBRange(mbb).first;
}
- /// Returns the last index in the given basic block number.
+ /// Returns the index past the last valid index in the given basic block.
SlotIndex getMBBEndIdx(unsigned Num) const {
return getMBBRange(Num).second;
}
- /// Returns the last index in the given basic block.
+ /// Returns the index past the last valid index in the given basic block.
SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const {
return getMBBRange(mbb).second;
}
+ /// Returns the last valid index in the given basic block.
+ /// This index corresponds to the dead slot of the last non-debug
+ /// instruction and can be used to find live-out ranges of the block. Note
+ /// that getMBBEndIdx returns the start index of the next block, which is
+ /// also used as the start index for segments with phi-def values. Returns
+ /// an invalid SlotIndex if the block has no non-debug instructions.
+ SlotIndex getMBBLastIdx(const MachineBasicBlock *MBB) const {
+ auto LastInstrI = MBB->getLastNonDebugInstr();
+ return LastInstrI == MBB->end()
+ ? SlotIndex()
+ : getInstructionIndex(*LastInstrI).getDeadSlot();
+ }
+
/// Iterator over the idx2MBBMap (sorted pairs of slot index of basic block
/// begin and basic block)
using MBBIndexIterator = SmallVectorImpl<IdxMBBPair>::const_iterator;
diff --git a/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp b/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
index ef63acc6355d2..d95fdec1fbef9 100644
--- a/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
@@ -461,6 +461,8 @@ GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
const LiveIntervals &LIS,
const MachineRegisterInfo &MRI) {
GCNRPTracker::LiveRegSet LiveRegs;
+ if (!SI.isValid())
+ return LiveRegs;
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
auto Reg = Register::index2VirtReg(I);
if (!LIS.hasInterval(Reg))
@@ -906,32 +908,31 @@ bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
+ SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(&MBB);
GCNRPTracker::LiveRegSet LiveIn, LiveOut;
GCNRegPressure RPAtMBBEnd;
- if (UseDownwardTracker) {
- if (MBB.empty()) {
- LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
- RPAtMBBEnd = getRegPressure(MRI, LiveIn);
- } else {
- GCNDownwardRPTracker RPT(LIS);
- RPT.reset(MBB.front());
+ if (!MBBLastSlot.isValid()) { // MBB doesn't have any non-debug instrs.
+ LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
+ RPAtMBBEnd = getRegPressure(MRI, LiveIn);
+ } else if (UseDownwardTracker) {
+ GCNDownwardRPTracker RPT(LIS);
+ RPT.reset(MBB.front());
- LiveIn = RPT.getLiveRegs();
-
- while (!RPT.advanceBeforeNext()) {
- GCNRegPressure RPBeforeMI = RPT.getPressure();
- RPT.advanceToNext();
- RP.emplace_back(RPBeforeMI, RPT.getPressure());
- }
+ LiveIn = RPT.getLiveRegs();
- LiveOut = RPT.getLiveRegs();
- RPAtMBBEnd = RPT.getPressure();
+ while (!RPT.advanceBeforeNext()) {
+ GCNRegPressure RPBeforeMI = RPT.getPressure();
+ RPT.advanceToNext();
+ RP.emplace_back(RPBeforeMI, RPT.getPressure());
}
+
+ LiveOut = RPT.getLiveRegs();
+ RPAtMBBEnd = RPT.getPressure();
} else {
GCNUpwardRPTracker RPT(LIS);
- RPT.reset(MRI, MBBEndSlot);
+ RPT.reset(MRI, MBBLastSlot);
LiveOut = RPT.getLiveRegs();
RPAtMBBEnd = RPT.getPressure();
@@ -965,8 +966,8 @@ bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
OS << printRP(RPAtMBBEnd) << '\n';
OS << PFX " Live-out:" << llvm::print(LiveOut, MRI);
- if (UseDownwardTracker)
- ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBEndSlot, LIS, MRI));
+ if (UseDownwardTracker && MBBLastSlot.isValid())
+ ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBLastSlot, LIS, MRI));
GCNRPTracker::LiveRegSet LiveThrough;
for (auto [Reg, Mask] : LiveIn) {
diff --git a/llvm/lib/Target/AMDGPU/GCNRegPressure.h b/llvm/lib/Target/AMDGPU/GCNRegPressure.h
index a9c58bb90ef03..898d1ffc10b79 100644
--- a/llvm/lib/Target/AMDGPU/GCNRegPressure.h
+++ b/llvm/lib/Target/AMDGPU/GCNRegPressure.h
@@ -313,8 +313,8 @@ class GCNUpwardRPTracker : public GCNRPTracker {
/// reset tracker to the end of the \p MBB.
void reset(const MachineBasicBlock &MBB) {
- reset(MBB.getParent()->getRegInfo(),
- LIS.getSlotIndexes()->getMBBEndIdx(&MBB));
+ SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(&MBB);
+ reset(MBB.getParent()->getRegInfo(), MBBLastSlot);
}
/// reset tracker to the point just after \p MI (in program order).
diff --git a/llvm/test/CodeGen/AMDGPU/regpressure_printer.mir b/llvm/test/CodeGen/AMDGPU/regpressure_printer.mir
index 8d5b5e4e8cae1..b41aa088bfdde 100644
--- a/llvm/test/CodeGen/AMDGPU/regpressure_printer.mir
+++ b/llvm/test/CodeGen/AMDGPU/regpressure_printer.mir
@@ -510,14 +510,14 @@ body: |
; RPU-NEXT: 0 0 $sgpr0 = S_BUFFER_LOAD_DWORD_IMM $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0
; RPU-NEXT: 0 0
; RPU-NEXT: 0 1 undef %0.sub5:vreg_512 = V_MOV_B32_e32 5, implicit $exec
- ; RPU-NEXT: 0 0
- ; RPU-NEXT: 0 0 S_CMP_GT_U32 $sgpr0, 15, implicit-def $scc
- ; RPU-NEXT: 0 0
- ; RPU-NEXT: 0 0 S_CBRANCH_SCC1 %bb.2, implicit $scc
- ; RPU-NEXT: 0 0
- ; RPU-NEXT: 0 0 S_BRANCH %bb.1
- ; RPU-NEXT: 0 0
- ; RPU-NEXT: Live-out:
+ ; RPU-NEXT: 0 1
+ ; RPU-NEXT: 0 1 S_CMP_GT_U32 $sgpr0, 15, implicit-def $scc
+ ; RPU-NEXT: 0 1
+ ; RPU-NEXT: 0 1 S_CBRANCH_SCC1 %bb.2, implicit $scc
+ ; RPU-NEXT: 0 1
+ ; RPU-NEXT: 0 1 S_BRANCH %bb.1
+ ; RPU-NEXT: 0 1
+ ; RPU-NEXT: Live-out: %0:0000000000000C00
; RPU-NEXT: Live-thr:
; RPU-NEXT: 0 0
; RPU-NEXT: bb.1:
@@ -571,8 +571,6 @@ body: |
; RPD-NEXT: 0 1 S_BRANCH %bb.1
; RPD-NEXT: 0 1
; RPD-NEXT: Live-out: %0:0000000000000C00
- ; RPD-NEXT: mis LIS:
- ; RPD-NEXT: %0:L0000000000000C00 isn't found in LIS reported set
; RPD-NEXT: Live-thr:
; RPD-NEXT: 0 0
; RPD-NEXT: bb.1:
>From 4874306982a9b0e9ed0fa727d1c8523c67a33904 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Fri, 3 Oct 2025 10:36:32 +0000
Subject: [PATCH 2/3] Use getMBBEndIdx(MBB).getPrevSlot() as getMBBLastIdx
result.
---
llvm/include/llvm/CodeGen/SlotIndexes.h | 10 ++++------
llvm/lib/Target/AMDGPU/GCNRegPressure.cpp | 7 ++++---
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SlotIndexes.h b/llvm/include/llvm/CodeGen/SlotIndexes.h
index c81c843522b34..780bd82a4c624 100644
--- a/llvm/include/llvm/CodeGen/SlotIndexes.h
+++ b/llvm/include/llvm/CodeGen/SlotIndexes.h
@@ -481,13 +481,11 @@ class raw_ostream;
/// This index corresponds to the dead slot of the last non-debug
/// instruction and can be used to find live-out ranges of the block. Note
/// that getMBBEndIdx returns the start index of the next block, which is
- /// also used as the start index for segments with phi-def values. Returns
- /// an invalid SlotIndex if the block has no non-debug instructions.
+ /// also used as the start index for segments with phi-def values. If the
+ /// basic block doesn't contain any non-debug instructions, this returns
+ /// the same as getMBBStartIdx.getDeadSlot().
SlotIndex getMBBLastIdx(const MachineBasicBlock *MBB) const {
- auto LastInstrI = MBB->getLastNonDebugInstr();
- return LastInstrI == MBB->end()
- ? SlotIndex()
- : getInstructionIndex(*LastInstrI).getDeadSlot();
+ return getMBBEndIdx(MBB).getPrevSlot();
}
/// Iterator over the idx2MBBMap (sorted pairs of slot index of basic block
diff --git a/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp b/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
index d95fdec1fbef9..0ee9a8f063b47 100644
--- a/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
@@ -907,13 +907,13 @@ bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
OS << ":\n";
SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
- SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(&MBB);
+ bool MBBHasNonDebugInstrs = MBBStartSlot != MBBLastSlot.getBaseIndex();
GCNRPTracker::LiveRegSet LiveIn, LiveOut;
GCNRegPressure RPAtMBBEnd;
- if (!MBBLastSlot.isValid()) { // MBB doesn't have any non-debug instrs.
+ if (!MBBHasNonDebugInstrs) {
LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
RPAtMBBEnd = getRegPressure(MRI, LiveIn);
} else if (UseDownwardTracker) {
@@ -966,13 +966,14 @@ bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
OS << printRP(RPAtMBBEnd) << '\n';
OS << PFX " Live-out:" << llvm::print(LiveOut, MRI);
- if (UseDownwardTracker && MBBLastSlot.isValid())
+ if (UseDownwardTracker)
ReportLISMismatchIfAny(LiveOut, getLiveRegs(MBBLastSlot, LIS, MRI));
GCNRPTracker::LiveRegSet LiveThrough;
for (auto [Reg, Mask] : LiveIn) {
LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
if (MaskIntersection.any()) {
+ SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
LaneBitmask LTMask = getRegLiveThroughMask(
MRI, LIS, Reg, MBBStartSlot, MBBEndSlot, MaskIntersection);
if (LTMask.any())
>From 9bf26398fae78b116d977923c451d1c6907e69e6 Mon Sep 17 00:00:00 2001
From: Valery Pykhtin <valery.pykhtin at amd.com>
Date: Fri, 3 Oct 2025 12:59:38 +0000
Subject: [PATCH 3/3] Remove unrelated changes, use MBBLastSlot for
live-throughs as well.
---
llvm/lib/Target/AMDGPU/GCNRegPressure.cpp | 36 +++++++++++------------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp b/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
index 0ee9a8f063b47..71494be74ec52 100644
--- a/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNRegPressure.cpp
@@ -461,8 +461,6 @@ GCNRPTracker::LiveRegSet llvm::getLiveRegs(SlotIndex SI,
const LiveIntervals &LIS,
const MachineRegisterInfo &MRI) {
GCNRPTracker::LiveRegSet LiveRegs;
- if (!SI.isValid())
- return LiveRegs;
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
auto Reg = Register::index2VirtReg(I);
if (!LIS.hasInterval(Reg))
@@ -908,28 +906,29 @@ bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
SlotIndex MBBStartSlot = LIS.getSlotIndexes()->getMBBStartIdx(&MBB);
SlotIndex MBBLastSlot = LIS.getSlotIndexes()->getMBBLastIdx(&MBB);
- bool MBBHasNonDebugInstrs = MBBStartSlot != MBBLastSlot.getBaseIndex();
GCNRPTracker::LiveRegSet LiveIn, LiveOut;
GCNRegPressure RPAtMBBEnd;
- if (!MBBHasNonDebugInstrs) {
- LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
- RPAtMBBEnd = getRegPressure(MRI, LiveIn);
- } else if (UseDownwardTracker) {
- GCNDownwardRPTracker RPT(LIS);
- RPT.reset(MBB.front());
+ if (UseDownwardTracker) {
+ if (MBB.empty()) {
+ LiveIn = LiveOut = getLiveRegs(MBBStartSlot, LIS, MRI);
+ RPAtMBBEnd = getRegPressure(MRI, LiveIn);
+ } else {
+ GCNDownwardRPTracker RPT(LIS);
+ RPT.reset(MBB.front());
- LiveIn = RPT.getLiveRegs();
+ LiveIn = RPT.getLiveRegs();
- while (!RPT.advanceBeforeNext()) {
- GCNRegPressure RPBeforeMI = RPT.getPressure();
- RPT.advanceToNext();
- RP.emplace_back(RPBeforeMI, RPT.getPressure());
- }
+ while (!RPT.advanceBeforeNext()) {
+ GCNRegPressure RPBeforeMI = RPT.getPressure();
+ RPT.advanceToNext();
+ RP.emplace_back(RPBeforeMI, RPT.getPressure());
+ }
- LiveOut = RPT.getLiveRegs();
- RPAtMBBEnd = RPT.getPressure();
+ LiveOut = RPT.getLiveRegs();
+ RPAtMBBEnd = RPT.getPressure();
+ }
} else {
GCNUpwardRPTracker RPT(LIS);
RPT.reset(MRI, MBBLastSlot);
@@ -973,9 +972,8 @@ bool GCNRegPressurePrinter::runOnMachineFunction(MachineFunction &MF) {
for (auto [Reg, Mask] : LiveIn) {
LaneBitmask MaskIntersection = Mask & LiveOut.lookup(Reg);
if (MaskIntersection.any()) {
- SlotIndex MBBEndSlot = LIS.getSlotIndexes()->getMBBEndIdx(&MBB);
LaneBitmask LTMask = getRegLiveThroughMask(
- MRI, LIS, Reg, MBBStartSlot, MBBEndSlot, MaskIntersection);
+ MRI, LIS, Reg, MBBStartSlot, MBBLastSlot, MaskIntersection);
if (LTMask.any())
LiveThrough[Reg] = LTMask;
}
More information about the llvm-commits
mailing list