[llvm-branch-commits] [llvm] [AMDGPU] Pre-commit unit test for RP tracking `reset`/`advance` inconsistencies fix (PR #196098)
Lucas Ramirez via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri May 8 08:09:21 PDT 2026
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 <lucas.rami at proton.me>
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);
+}
More information about the llvm-branch-commits
mailing list