[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