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
