https://github.com/lucas-rami updated 
https://github.com/llvm/llvm-project/pull/196098

>From c35c4499a80bc97cd36e8fb1ecca282dc5bdfa9f Mon Sep 17 00:00:00 2001
From: Lucas Ramirez <[email protected]>
Date: Wed, 6 May 2026 15:15:30 +0000
Subject: [PATCH] [AMDGPU] Pre-commit unit test for RP tracking reset/advance
 behavior

This adds a new AMDGPU unit test file for testing the behavior of
`GCNRPTracker` and its related classes. The two test showcase confusing
return value and behavioral semantics for variants of the advance and
reset functions, which will be clarified in a follow up commit.

This also moves some common test helpers from other AMDGPU unit tests to
the `AMDGPUUnitTests` TU to avoid repetition between unit tests.
---
 llvm/unittests/Target/AMDGPU/CMakeLists.txt   |   1 +
 .../Target/AMDGPU/GCNRegPressureTest.cpp      | 156 ++++++++++++++++++
 2 files changed, 157 insertions(+)
 create mode 100644 llvm/unittests/Target/AMDGPU/GCNRegPressureTest.cpp

diff --git a/llvm/unittests/Target/AMDGPU/CMakeLists.txt 
b/llvm/unittests/Target/AMDGPU/CMakeLists.txt
index 2425556ebe33f..6dfd635065dfe 100644
--- a/llvm/unittests/Target/AMDGPU/CMakeLists.txt
+++ b/llvm/unittests/Target/AMDGPU/CMakeLists.txt
@@ -26,6 +26,7 @@ add_llvm_target_unittest(AMDGPUTests
   CSETest.cpp
   DwarfRegMappings.cpp
   ExecMayBeModifiedBeforeAnyUse.cpp
+  GCNRegPressureTest.cpp
   LiveRegUnits.cpp
   PALMetadata.cpp
   UniformityAnalysisTest.cpp
diff --git a/llvm/unittests/Target/AMDGPU/GCNRegPressureTest.cpp 
b/llvm/unittests/Target/AMDGPU/GCNRegPressureTest.cpp
new file mode 100644
index 0000000000000..ad84f4df65288
--- /dev/null
+++ b/llvm/unittests/Target/AMDGPU/GCNRegPressureTest.cpp
@@ -0,0 +1,156 @@
+//===- GCNRegPressureTest.cpp -----------------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "GCNRegPressure.h"
+#include "AMDGPUUnitTests.h"
+#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/MIRParser/MIRParser.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineScheduler.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+class GCNRegPressureTest : public llvm::CodeGenTestBase {
+public:
+  void SetUp() override { setUpImpl("amdgcn--", "gfx908", ""); }
+};
+
+TEST_F(GCNRegPressureTest, DownwardTrackerEndOnDbgVal) {
+  StringRef MIR = R"(
+name:            DownwardTrackerEndOnDbgVal
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  bb.0:
+    %0:vgpr_32 = IMPLICIT_DEF
+    %1:vgpr_32 = IMPLICIT_DEF
+  
+  bb.1:
+    DBG_VALUE %0
+    DBG_VALUE %1
+    %2:vgpr_32 = IMPLICIT_DEF
+  
+  bb.3:
+    S_NOP 0, implicit %0, implicit %1, implicit %2
+    S_ENDPGM 0
+...
+)";
+  EXPECT_TRUE(parseMIR(MIR));
+  MachineFunction &MF = getMF("DownwardTrackerEndOnDbgVal");
+  const LiveIntervals &LIS = MFAM.getResult<LiveIntervalsAnalysis>(MF);
+
+  // MBB1 live-in pressure is equivalent to MBB0 live-out pressure.
+  MachineBasicBlock &MBB0 = *MF.getBlockNumbered(0);
+  MachineBasicBlock &MBB1 = *MF.getBlockNumbered(1);
+  GCNRPTracker::LiveRegSet MBB1LiveIns =
+      getLiveRegs(LIS.getInstructionIndex(*MBB0.rbegin()).getDeadSlot(), LIS,
+                  MF.getRegInfo());
+
+  // Track pressure across MBB1.
+  {
+    GCNDownwardRPTracker RPTracker(LIS), RPTrackerNoLiveIns(LIS);
+
+    // There is a non-debug instruction in bb.1 (%2's def), so advance should
+    // return true.
+    EXPECT_TRUE(RPTracker.advance(MBB1.begin(), MBB1.end(), &MBB1LiveIns));
+    EXPECT_TRUE(RPTrackerNoLiveIns.advance(MBB1.begin(), MBB1.end(), nullptr));
+
+    // When advance returns true, maximum pressure should be the pressured
+    // induced by the block's live-ins plus %2's def i.e., 3 VGPRs.
+    EXPECT_EQ(RPTracker.moveMaxPressure().getVGPRNum(false), 3U);
+    EXPECT_EQ(RPTrackerNoLiveIns.moveMaxPressure().getVGPRNum(false), 3U);
+  }
+
+  // Track pressure just across the first debug value of bb.1.
+  {
+    MachineBasicBlock::iterator Dbg1 = std::next(MBB1.begin());
+    GCNDownwardRPTracker RPTracker(LIS), RPTrackerNoLiveIns(LIS);
+
+    // The following unpacks a call to
+    // advance(*MBB1.begin(), Dbg1, [MBB1LiveIns|nullptr])
+    // which would return false in this case.
+    //
+    // There aren't any non-debug instruction between the beginning of bb1 and
+    // Dbg1 (exclusive). However, the call to reset takes the end of the MBB as
+    // the limit, so it pushes the beginning of the block up to %2's def and
+    // considers the reset successful.
+    EXPECT_TRUE(RPTracker.reset(*MBB1.begin(), &MBB1LiveIns));
+    EXPECT_TRUE(RPTrackerNoLiveIns.reset(*MBB1.begin(), nullptr));
+    // advance then unnecessarily processes instructions in order until the end
+    // of the block, even though it is already past Dbg1. It still returns 
false
+    // because it is stopped by the end of block delimiter, not the end
+    // iterator.
+    EXPECT_FALSE(RPTracker.advance(Dbg1));
+    EXPECT_FALSE(RPTrackerNoLiveIns.advance(Dbg1));
+
+    // In that case, the maximum pressure is also the pressure induced by the
+    // block's live-ins plus %2's def i.e., 3 VGPRs. This is confusing because
+    // %2's def is outside the [Begin,End) range we passed to advance, and 
there
+    // is no indication that a false return value should make the tracked
+    // pressure invalid.
+    EXPECT_EQ(RPTracker.moveMaxPressure().getVGPRNum(false), 3U);
+    EXPECT_EQ(RPTrackerNoLiveIns.moveMaxPressure().getVGPRNum(false), 3U);
+  }
+}
+
+TEST_F(GCNRegPressureTest, DownwardTrackerAllDbgVal) {
+  StringRef MIR = R"(
+name:            DownwardTrackerAllDbgVal
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  bb.0:
+    %0:vgpr_32 = IMPLICIT_DEF
+
+  bb.1:
+    DBG_VALUE %0
+  
+  bb.2:
+    S_NOP 0, implicit %0
+    S_ENDPGM 0
+...
+)";
+  EXPECT_TRUE(parseMIR(MIR));
+  MachineFunction &MF = getMF("DownwardTrackerAllDbgVal");
+  const LiveIntervals &LIS = MFAM.getResult<LiveIntervalsAnalysis>(MF);
+
+  // MBB1 live-in pressure is equivalent to MBB0 live-out pressure.
+  MachineBasicBlock &MBB0 = *MF.getBlockNumbered(0);
+  GCNRPTracker::LiveRegSet MBB1LiveIns =
+      getLiveRegs(LIS.getInstructionIndex(*MBB0.rbegin()).getDeadSlot(), LIS,
+                  MF.getRegInfo());
+
+  MachineBasicBlock &MBB1 = *MF.getBlockNumbered(1);
+  GCNDownwardRPTracker RPTracker(LIS), RPTrackerNoLiveIns(LIS);
+
+  // The following unpacks a call to
+  // advance(MBB1.begin(), MBB1.end(), [MBB1LiveIns|nullptr])
+  // which would return true in this case.
+  //
+  // There aren't any non-debug instruction in bb.2, the reset is therefore
+  // unsuccessful. However the advance caller discards that return value and
+  // proceeds to calling its override.
+  EXPECT_FALSE(RPTracker.reset(*MBB1.begin(), &MBB1LiveIns));
+  EXPECT_FALSE(RPTrackerNoLiveIns.reset(*MBB1.begin(), nullptr));
+  // advance then produces true even though no advancement actually happened.
+  EXPECT_TRUE(RPTracker.advance(MBB1.end()));
+  EXPECT_TRUE(RPTrackerNoLiveIns.advance(MBB1.end()));
+
+  // In that case, the maximum pressure is unchanged from the beginning since
+  // reset was unsuccessful. This is confusing because the top-level advance
+  // call produced true, yet the block's live-in pressure was not considered.
+  EXPECT_EQ(RPTracker.moveMaxPressure().getVGPRNum(false), 0U);
+  EXPECT_EQ(RPTrackerNoLiveIns.moveMaxPressure().getVGPRNum(false), 0U);
+}

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to