[llvm] [AMDGPU] Apply occupancy-aware register allocation anti-hints (PR #218074)
Syadus Sefat via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 19:27:31 PDT 2026
https://github.com/mssefat updated https://github.com/llvm/llvm-project/pull/218074
>From c07ea5062c496e42eb8d70103dfdae199a31a7a3 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 19 Aug 2026 13:08:34 -0500
Subject: [PATCH 01/19] [RegAlloc] Add register allocation anti-hints
infrastructure
---
.../llvm/CodeGen/MachineRegisterInfo.h | 59 +++++++++++++++++++
.../include/llvm/CodeGen/TargetRegisterInfo.h | 9 +++
llvm/lib/CodeGen/AllocationOrder.cpp | 36 ++++++++++-
llvm/lib/CodeGen/AllocationOrder.h | 11 ++++
llvm/lib/CodeGen/MachineRegisterInfo.cpp | 22 +++++++
llvm/lib/CodeGen/TargetRegisterInfo.cpp | 40 +++++++++++++
.../unittests/CodeGen/AllocationOrderTest.cpp | 24 ++++++++
7 files changed, 198 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index a26462641de52..890355febbb28 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSet.h"
@@ -42,6 +43,7 @@
namespace llvm {
class PSetIterator;
+class VirtRegMap;
/// Convenient type to represent either a register class or a register bank.
using RegClassOrRegBank =
@@ -119,6 +121,12 @@ class MachineRegisterInfo {
/// pass when deserializing from .mir files.
SmallVector<PendingVirtRegMapEntry, 0> PendingVirtRegMapEntries;
+ /// AntiHintRegs - This vector records register anti-hints for
+ /// virtual registers. For each virtual register, it keeps a vector of virtual
+ /// registers that should NOT be allocated to the same or overlapping physical
+ /// registers.
+ IndexedMap<SmallVector<Register, 4>, VirtReg2IndexFunctor> AntiHintRegs;
+
/// PhysRegUseDefLists - This is an array of the head of the use/def list for
/// physical registers.
std::unique_ptr<MachineOperand *[]> PhysRegUseDefLists;
@@ -906,6 +914,57 @@ class MachineRegisterInfo {
return RegAllocHints.inBounds(VReg) ? &RegAllocHints[VReg] : nullptr;
}
+ /// Add a register allocation anti-hint for the specified virtual register.
+ /// This tells the allocator to avoid allocating VReg to the same physical
+ /// register as AntiHintVReg (or overlapping ones).
+ void addRegAllocAntiHint(Register VReg, Register AntiHintVReg) {
+ assert(VReg.isVirtual() && AntiHintVReg.isVirtual() &&
+ "Anti-hints and anti-hint targets are only for virtual registers");
+ AntiHintRegs.grow(VReg);
+ SmallVector<Register, 4> &AntiHints = AntiHintRegs[VReg];
+ // Avoid duplicates
+ if (!is_contained(AntiHints, AntiHintVReg))
+ AntiHints.push_back(AntiHintVReg);
+ }
+
+ /// Add multiple anti-hints at once.
+ void addRegAllocationAntiHints(Register VReg,
+ ArrayRef<Register> AntiHintVRegs) {
+ for (Register AntiHint : AntiHintVRegs)
+ addRegAllocAntiHint(VReg, AntiHint);
+ }
+
+ /// Clear all anti-hints for a register.
+ void clearRegAllocationAntiHints(Register VReg) {
+ assert(VReg.isVirtual() && "Anti-hints are only for virtual registers");
+ if (AntiHintRegs.inBounds(VReg))
+ AntiHintRegs[VReg].clear();
+ }
+
+ /// Return the vector of anti-hints for VReg.
+ ArrayRef<Register> getRegAllocationAntiHints(Register VReg) const {
+ assert(VReg.isVirtual() && "Anti-hints are only for virtual registers");
+ if (!AntiHintRegs.inBounds(VReg))
+ return ArrayRef<Register>();
+ return AntiHintRegs[VReg];
+ }
+
+ /// Check if VReg has AntiHintVReg as an anti-hint.
+ bool hasRegAllocationAntiHint(Register VReg, Register AntiHintVReg) const {
+ assert(VReg.isVirtual() && AntiHintVReg.isVirtual() &&
+ "Anti-hints and anti-hint targets are only for virtual registers");
+ if (!AntiHintRegs.inBounds(VReg))
+ return false;
+ const SmallVector<Register, 4> &AntiHints = AntiHintRegs[VReg];
+ return is_contained(AntiHints, AntiHintVReg);
+ }
+
+ /// Get the set of physical registers to avoid.
+ /// VRM is the current virtual register map showing allocations made so far.
+ void getPhysRegAntiHints(Register VReg,
+ SmallVectorImpl<MCPhysReg> &PhysAntiHints,
+ const VirtRegMap &VRM) const;
+
/// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the
/// specified register as undefined which causes the DBG_VALUE to be
/// deleted during LiveDebugVariables analysis.
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 484234fa055fe..e0c358d25a087 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -852,6 +852,15 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
// Do nothing.
}
+ /// Apply anti-hints to the allocation order.
+ virtual void
+ applyRegAllocationAntiHints(Register VirtReg, ArrayRef<MCPhysReg> &Order,
+ SmallVectorImpl<MCPhysReg> &OrderStorage,
+ SmallVectorImpl<MCPhysReg> &AntiHints,
+ const MachineFunction &MF,
+ const VirtRegMap *VRM = nullptr,
+ const LiveRegMatrix *Matrix = nullptr) const;
+
/// Allow the target to reverse allocation order of local live ranges. This
/// will generally allocate shorter local live ranges first. For targets with
/// many registers, this could reduce regalloc compile time by a large
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index 183dc8af1b91b..1b3d3639fbc2a 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -31,6 +31,7 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
const LiveRegMatrix *Matrix) {
const MachineFunction &MF = VRM.getMachineFunction();
const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo();
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
auto Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
SmallVector<MCPhysReg, 16> Hints;
bool HardHints =
@@ -44,8 +45,37 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
dbgs() << '\n';
}
});
- assert(all_of(Hints,
- [&](MCPhysReg Hint) { return is_contained(Order, Hint); }) &&
+
+ // Get anti-hints
+ SmallVector<MCPhysReg, 16> AntiHintedPhysRegs;
+ MRI.getPhysRegAntiHints(VirtReg, AntiHintedPhysRegs, VRM);
+
+ LLVM_DEBUG({
+ if (!AntiHintedPhysRegs.empty()) {
+ dbgs() << "anti-hints:";
+ for (MCPhysReg AntiHint : AntiHintedPhysRegs)
+ dbgs() << ' ' << printReg(AntiHint, TRI);
+ dbgs() << '\n';
+ }
+ });
+
+ // Storage for filtered order (used if anti-hints cause reordering)
+ SmallVector<MCPhysReg, 16> ShuffledOrder;
+
+ if (!AntiHintedPhysRegs.empty()) {
+ TRI->applyRegAllocationAntiHints(VirtReg, Order, ShuffledOrder,
+ AntiHintedPhysRegs, MF, &VRM, Matrix);
+ }
+ // Use ShuffledOrder as the order if it was populated by anti-hints
+ // processing
+ ArrayRef<MCPhysReg> FinalOrder =
+ ShuffledOrder.empty() ? Order : ShuffledOrder;
+ // Create allocation order object
+ AllocationOrder AO(std::move(Hints), FinalOrder, HardHints,
+ std::move(ShuffledOrder));
+
+ assert(all_of(AO.Hints,
+ [&](MCPhysReg Hint) { return is_contained(AO.Order, Hint); }) &&
"Target hint is outside allocation order.");
- return AllocationOrder(std::move(Hints), Order, HardHints);
+ return AO;
}
diff --git a/llvm/lib/CodeGen/AllocationOrder.h b/llvm/lib/CodeGen/AllocationOrder.h
index 3dd02c3b14d3a..3b7c7cd4cac10 100644
--- a/llvm/lib/CodeGen/AllocationOrder.h
+++ b/llvm/lib/CodeGen/AllocationOrder.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
namespace llvm {
@@ -29,6 +30,9 @@ class LiveRegMatrix;
class LLVM_LIBRARY_VISIBILITY AllocationOrder {
const SmallVector<MCPhysReg, 16> Hints;
+ // Used as storage if the Order received in the constructor needs to be
+ // altered.
+ SmallVector<MCPhysReg, 16> FilteredOrderStorage;
ArrayRef<MCPhysReg> Order;
// How far into the Order we can iterate. This is 0 if the AllocationOrder is
// constructed with HardHints = true, Order.size() otherwise. While
@@ -92,6 +96,13 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
: Hints(std::move(Hints)), Order(Order),
IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {}
+ /// Create an AllocationOrder with pre-computed FilteredOrderStorage.
+ AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order,
+ bool HardHints, SmallVector<MCPhysReg, 16> &&Storage)
+ : Hints(std::move(Hints)), FilteredOrderStorage(std::move(Storage)),
+ Order(FilteredOrderStorage.empty() ? Order : FilteredOrderStorage),
+ IterationLimit(HardHints ? 0 : static_cast<int>(this->Order.size())) {}
+
Iterator begin() const {
return Iterator(*this, -(static_cast<int>(Hints.size())));
}
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index dbba413548018..3918c169b978c 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -11,15 +11,18 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/DebugLoc.h"
@@ -714,3 +717,22 @@ void MachineRegisterInfo::updateDbgUsersToReg(
}
}
}
+
+void MachineRegisterInfo::getPhysRegAntiHints(
+ Register VReg, SmallVectorImpl<MCPhysReg> &PhysAntiHints,
+ const VirtRegMap &VRM) const {
+ assert(VReg.isVirtual() && "Anti-hints are only for virtual registers");
+ if (!AntiHintRegs.inBounds(VReg))
+ return;
+
+ const SmallVector<Register, 4> &AntiHints = AntiHintRegs[VReg];
+
+ for (Register AntiHintVReg : AntiHints) {
+ // Check if the anti-hinted register has been allocated
+ if (VRM.hasPhys(AntiHintVReg)) {
+ MCPhysReg PhysReg = VRM.getPhys(AntiHintVReg);
+ if (!is_contained(PhysAntiHints, PhysReg))
+ PhysAntiHints.push_back(PhysReg);
+ }
+ }
+}
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 3b29b0863dd6c..fd696297e35d9 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -443,6 +443,46 @@ bool TargetRegisterInfo::getRegAllocationHints(
return false;
}
+void TargetRegisterInfo::applyRegAllocationAntiHints(
+ Register VirtReg, ArrayRef<MCPhysReg> &Order,
+ SmallVectorImpl<MCPhysReg> &OrderStorage,
+ SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
+ const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
+
+ if (AntiHints.empty() || !VRM)
+ return;
+
+ auto isAntiHinted = [&](MCPhysReg Reg) {
+ return llvm::any_of(AntiHints, [&](MCPhysReg AntiHint) {
+ return regsOverlap(Reg, AntiHint);
+ });
+ };
+
+ // Copy order into storage
+ OrderStorage.clear();
+ OrderStorage.assign(Order.begin(), Order.end());
+
+ // Partition non-anti-hinted register go first
+ auto PartionPoint =
+ std::stable_partition(OrderStorage.begin(), OrderStorage.end(),
+ [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
+
+ Order = OrderStorage;
+
+ // print the details
+ LLVM_DEBUG({
+ size_t NonAntiHintedCount =
+ std::distance(OrderStorage.begin(), PartionPoint);
+ size_t AntiHintedCount = std::distance(PartionPoint, OrderStorage.end());
+ dbgs() << "Added " << NonAntiHintedCount
+ << " non-anti-hinted registers first\n"
+ << "Added " << AntiHintedCount
+ << " anti-hinted registers at the end\n";
+ });
+
+ return;
+}
+
bool TargetRegisterInfo::isCalleeSavedPhysReg(
MCRegister PhysReg, const MachineFunction &MF) const {
if (!PhysReg)
diff --git a/llvm/unittests/CodeGen/AllocationOrderTest.cpp b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
index d4da8e28ae7f7..ec02579f55c58 100644
--- a/llvm/unittests/CodeGen/AllocationOrderTest.cpp
+++ b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
@@ -116,3 +116,27 @@ TEST(AllocationOrderTest, IsHintTest) {
EXPECT_FALSE(I.isHint());
EXPECT_EQ(V, 5U);
}
+
+TEST(AllocationOrderTest, StorageOverridesOrder) {
+ SmallVector<MCPhysReg, 16> Hints = {1, 2};
+ SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
+ SmallVector<MCPhysReg, 16> Storage = {5, 3, 4};
+ AllocationOrder O(std::move(Hints), Order, false, std::move(Storage));
+ EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 5, 3, 4}), loadOrder(O));
+}
+
+TEST(AllocationOrderTest, EmptyStorageFallsBackToOrder) {
+ SmallVector<MCPhysReg, 16> Hints = {1, 2};
+ SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
+ SmallVector<MCPhysReg, 16> Storage;
+ AllocationOrder O(std::move(Hints), Order, false, std::move(Storage));
+ EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5}), loadOrder(O));
+}
+
+TEST(AllocationOrderTest, StorageHardHints) {
+ SmallVector<MCPhysReg, 16> Hints = {1, 2};
+ SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
+ SmallVector<MCPhysReg, 16> Storage = {5, 3, 4};
+ AllocationOrder O(std::move(Hints), Order, true, std::move(Storage));
+ EXPECT_EQ((std::vector<MCPhysReg>{1, 2}), loadOrder(O));
+}
>From 244fb01f8407f2138d07509ee26c2d3097bce79d Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 19 Aug 2026 14:18:37 -0500
Subject: [PATCH 02/19] [MIR] Serialize register allocation anti-hints
---
.../include/llvm/CodeGen/MIRParser/MIParser.h | 1 +
llvm/include/llvm/CodeGen/MIRYamlMapping.h | 4 +
llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 18 +++
llvm/lib/CodeGen/MIRPrinter.cpp | 12 ++
...r-allocation-antihints-mir-print-parse.mir | 121 ++++++++++++++++++
5 files changed, 156 insertions(+)
create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir
diff --git a/llvm/include/llvm/CodeGen/MIRParser/MIParser.h b/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
index 622862279cfdd..d163451a8a588 100644
--- a/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
+++ b/llvm/include/llvm/CodeGen/MIRParser/MIParser.h
@@ -47,6 +47,7 @@ struct VRegInfo {
} D;
Register VReg;
Register PreferredReg;
+ SmallVector<Register, 4> AntiHints;
uint8_t Flags = 0;
};
diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index 76f5e38a045ff..05f6be547f367 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -203,6 +203,7 @@ struct VirtualRegisterDefinition {
StringValue Class;
StringValue PreferredRegister;
std::vector<FlowStringValue> RegisterFlags;
+ std::vector<FlowStringValue> AntiHints;
// VirtRegMap state.
// SplitFrom: id-form virtual register only (e.g. '%0'); physregs and named
// vregs are rejected by the parser.
@@ -227,6 +228,9 @@ template <> struct MappingTraits<VirtualRegisterDefinition> {
StringValue()); // Don't print out when it's empty.
YamlIO.mapOptional("flags", Reg.RegisterFlags,
std::vector<FlowStringValue>());
+ if (!YamlIO.outputting() || !Reg.AntiHints.empty())
+ YamlIO.mapOptional("anti-hints", Reg.AntiHints,
+ std::vector<FlowStringValue>());
// MIRPrinter sets WriteDefaultValues=true unless -simplify-mir is passed,
// so a plain mapOptional with an empty default would still emit the keys
// and change every existing test's output.
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 6f1e7594f34da..8783078485877 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -772,6 +772,22 @@ bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
FlagStringValue.Value + "'");
Info.Flags |= FlagValue;
}
+ if (!VReg.AntiHints.empty() && Info.Kind != VRegInfo::NORMAL)
+ return error(VReg.AntiHints.front().SourceRange.Start,
+ Twine("anti-hints can only be set for normal vregs"));
+
+ for (const auto &AntiHintValue : VReg.AntiHints) {
+ Register AntiHintReg;
+ if (parseRegisterReference(PFS, AntiHintReg, AntiHintValue.Value, Error))
+ return error(Error, AntiHintValue.SourceRange);
+
+ if (!AntiHintReg.isVirtual())
+ return error(AntiHintValue.SourceRange.Start,
+ Twine("anti-hint '") + AntiHintValue.Value +
+ "' must be a virtual register");
+
+ Info.AntiHints.push_back(AntiHintReg);
+ }
RegInfo.noteNewVirtualRegister(Info.VReg);
}
@@ -878,6 +894,8 @@ bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS,
MRI.setRegClass(Reg, Info.D.RC);
if (Info.PreferredReg != 0)
MRI.setSimpleHint(Reg, Info.PreferredReg);
+ if (!Info.AntiHints.empty())
+ MRI.addRegAllocationAntiHints(Reg, Info.AntiHints);
break;
case VRegInfo::GENERIC:
break;
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 8acd6f14ebc2e..d4dff3be9041a 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -323,6 +323,18 @@ static void convertMRI(yaml::MachineFunction &YamlMF, const MachineFunction &MF,
if (PreferredReg)
printRegMIR(PreferredReg, VReg.PreferredRegister, TRI);
printRegFlags(Reg, VReg.RegisterFlags, MF, TRI);
+
+ // Print the anti-hints.
+ const auto &AntiHints = RegInfo.getRegAllocationAntiHints(Reg);
+ if (!AntiHints.empty()) {
+ std::vector<yaml::FlowStringValue> AntiHintStrings;
+ for (Register AntiHint : AntiHints) {
+ yaml::FlowStringValue AntiHintStr;
+ printRegMIR(AntiHint, AntiHintStr, TRI);
+ AntiHintStrings.push_back(std::move(AntiHintStr));
+ }
+ VReg.AntiHints = std::move(AntiHintStrings);
+ }
if (VRM) {
Register Orig = VRM->getPreSplitReg(Reg);
if (Orig && Orig != Reg) {
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir b/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir
new file mode 100644
index 0000000000000..574fe61c416de
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir
@@ -0,0 +1,121 @@
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -run-pass=none -o - %s | FileCheck %s
+
+---
+name: single_anti_hint
+tracksRegLiveness: true
+# CHECK-LABEL: name: single_anti_hint
+# CHECK: registers:
+# CHECK: - { id: 3, class: vreg_128_align2, preferred-register: '', flags: [ ],
+# CHECK-NEXT: anti-hints: [ '%1' ] }
+registers:
+ - { id: 0, class: vgpr_32 }
+ - { id: 1, class: vreg_512_align2 }
+ - { id: 2, class: vreg_512_align2 }
+ - { id: 3, class: vreg_128_align2, anti-hints: [ '%1' ] }
+body: |
+ bb.0:
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vreg_512_align2 = IMPLICIT_DEF
+ %2:vreg_512_align2 = contract V_MFMA_F32_32X32X16_FP8_FP8_vgprcd_e64 %1.sub0_sub1, %1.sub2_sub3, %1, 0, 0, 0, implicit $mode, implicit $exec
+ %3:vreg_128_align2 = DS_READ_B128_gfx9 %0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ S_ENDPGM 0, implicit %2, implicit %3
+...
+
+---
+name: multiple_anti_hints
+tracksRegLiveness: true
+# CHECK-LABEL: name: multiple_anti_hints
+# CHECK: registers:
+# CHECK: - { id: 3, class: vgpr_32, preferred-register: '', flags: [ ], anti-hints: [
+# CHECK-NEXT: '%1',
+# CHECK-NEXT: '%2' ] }
+# CHECK-NEXT: - { id: 4, class: vreg_128_align2, preferred-register: '', flags: [ ],
+# CHECK-NEXT: anti-hints: [ '%2' ] }
+registers:
+ - { id: 0, class: vgpr_32 }
+ - { id: 1, class: vreg_512_align2 }
+ - { id: 2, class: vreg_512_align2 }
+ - { id: 3, class: vgpr_32, anti-hints: [ '%1', '%2' ] }
+ - { id: 4, class: vreg_128_align2, anti-hints: [ '%2' ] }
+body: |
+ bb.0:
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vreg_512_align2 = IMPLICIT_DEF
+ %2:vreg_512_align2 = contract V_MFMA_F32_32X32X16_FP8_FP8_vgprcd_e64 %1.sub0_sub1, %1.sub2_sub3, %1, 0, 0, 0, implicit $mode, implicit $exec
+ %3:vgpr_32 = V_ADD_U32_e32 4096, %0, implicit $exec
+ %4:vreg_128_align2 = DS_READ_B128_gfx9 %3, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ S_ENDPGM 0, implicit %2, implicit %4
+...
+
+---
+name: duplicate_anti_hints
+tracksRegLiveness: true
+# CHECK-LABEL: name: duplicate_anti_hints
+# CHECK: registers:
+# CHECK: - { id: 2, class: vgpr_32, preferred-register: '', flags: [ ], anti-hints: [
+# CHECK-NEXT: '%1' ] }
+registers:
+ - { id: 0, class: vgpr_32 }
+ - { id: 1, class: vreg_512_align2 }
+ - { id: 2, class: vgpr_32, anti-hints: [ '%1', '%1' ] }
+body: |
+ bb.0:
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vreg_512_align2 = IMPLICIT_DEF
+ %2:vgpr_32 = V_ADD_U32_e32 4096, %0, implicit $exec
+ S_ENDPGM 0, implicit %1, implicit %2
+...
+
+---
+name: anti_hint_with_preferred_register
+tracksRegLiveness: true
+# CHECK-LABEL: name: anti_hint_with_preferred_register
+# CHECK: registers:
+# CHECK: - { id: 2, class: vgpr_32, preferred-register: '$vgpr8', flags: [ ],
+# CHECK-NEXT: anti-hints: [ '%1' ] }
+registers:
+ - { id: 0, class: vgpr_32 }
+ - { id: 1, class: vreg_512_align2 }
+ - { id: 2, class: vgpr_32, preferred-register: '$vgpr8', anti-hints: [ '%1' ] }
+body: |
+ bb.0:
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vreg_512_align2 = IMPLICIT_DEF
+ %2:vgpr_32 = V_ADD_U32_e32 4096, %0, implicit $exec
+ S_ENDPGM 0, implicit %1, implicit %2
+...
+
+---
+name: empty_anti_hints
+tracksRegLiveness: true
+# CHECK-LABEL: name: empty_anti_hints
+# CHECK: registers:
+# CHECK: - { id: 1, class: vgpr_32, preferred-register: '', flags: [ ] }
+# CHECK-NEXT: liveins:
+registers:
+ - { id: 0, class: vgpr_32 }
+ - { id: 1, class: vgpr_32, anti-hints: [ ] }
+body: |
+ bb.0:
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vgpr_32 = V_ADD_U32_e32 4096, %0, implicit $exec
+ S_ENDPGM 0, implicit %1
+...
+
+---
+name: no_anti_hints
+tracksRegLiveness: true
+# CHECK-LABEL: name: no_anti_hints
+# CHECK: registers:
+# CHECK-NEXT: - { id: 0, class: vgpr_32, preferred-register: '', flags: [ ] }
+# CHECK-NEXT: - { id: 1, class: vgpr_32, preferred-register: '', flags: [ ] }
+# CHECK-NEXT: liveins:
+registers:
+ - { id: 0, class: vgpr_32 }
+ - { id: 1, class: vgpr_32 }
+body: |
+ bb.0:
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vgpr_32 = V_ADD_U32_e32 4096, %0, implicit $exec
+ S_ENDPGM 0, implicit %1
+...
>From 04a57042c2034b195a86614b938bd3126c13f578 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 19 Aug 2026 20:02:07 -0500
Subject: [PATCH 03/19] [AMDGPU] Apply occupancy-aware register allocation
anti-hints
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 131 +++++-
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 16 +
.../AMDGPU/llvm.amdgcn.mfma.anti-hints.mir | 373 ++++++++++++++++++
3 files changed, 519 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 971dedd0878f1..97fca7ca20a26 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -11,18 +11,23 @@
//
//===----------------------------------------------------------------------===//
+#include "SIRegisterInfo.h"
#include "AMDGPU.h"
#include "AMDGPURegisterBankInfo.h"
#include "GCNSubtarget.h"
#include "MCTargetDesc/AMDGPUInstPrinter.h"
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "SIMachineFunctionInfo.h"
-#include "SIRegisterInfo.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCRegister.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUG_TYPE "amdgpu-si-register-info"
using namespace llvm;
@@ -4173,6 +4178,130 @@ bool SIRegisterInfo::getRegAllocationHints(Register VirtReg,
}
}
+bool SIRegisterInfo::shouldApplyAntiHints(
+ const MachineFunction &MF, unsigned NumAllocatedVGPRs,
+ unsigned &MaxVGPRsForCurrentOccupancy) const {
+
+ const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
+ unsigned DynamicVGPRBlockSize = MFI->getDynamicVGPRBlockSize();
+ unsigned TargetOccupancy = MFI->getOccupancy();
+ unsigned CurrentOccupancy =
+ ST.getOccupancyWithNumVGPRs(NumAllocatedVGPRs, DynamicVGPRBlockSize);
+ MaxVGPRsForCurrentOccupancy =
+ ST.getMaxNumVGPRs(CurrentOccupancy, DynamicVGPRBlockSize);
+
+ LLVM_DEBUG(dbgs() << "anti-hints: " << NumAllocatedVGPRs
+ << " VGPRs allocated, target occupancy " << TargetOccupancy
+ << ", current occupancy " << CurrentOccupancy << '\n');
+
+ // If we are already at lowest occupancy, then there is no need to protect
+ // against occupancy regression.
+ if (CurrentOccupancy == 1)
+ return true;
+
+ // Set max VGPRs for target and current occupancy to early bail out if we are
+ // close to the limit.
+ unsigned MaxVGPRsCutOffForTargetOccupancy =
+ (ST.getMaxNumVGPRs(TargetOccupancy, DynamicVGPRBlockSize) * 80) / 100;
+ unsigned MaxVGPRsCutOffForCurrentOccupancy =
+ (MaxVGPRsForCurrentOccupancy * 95) / 100;
+
+ if (NumAllocatedVGPRs >= MaxVGPRsCutOffForTargetOccupancy) {
+ LLVM_DEBUG(dbgs() << "anti-hints: not applied, at or above the "
+ << MaxVGPRsCutOffForTargetOccupancy
+ << " VGPR cutoff for target occupancy\n");
+ return false;
+ }
+
+ if (NumAllocatedVGPRs >= MaxVGPRsCutOffForCurrentOccupancy) {
+ LLVM_DEBUG(dbgs() << "anti-hints: not applied, at or above the "
+ << MaxVGPRsCutOffForCurrentOccupancy
+ << " VGPR cutoff for current occupancy\n");
+ return false;
+ }
+
+ return true;
+}
+
+void SIRegisterInfo::applyRegAllocationAntiHints(
+ Register VirtReg, ArrayRef<MCPhysReg> &Order,
+ SmallVectorImpl<MCPhysReg> &OrderStorage,
+ SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
+ const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
+
+ // Early exit to default order if we have no anti-hints or no VRM.
+ if (AntiHints.empty() || !VRM)
+ return;
+
+ // Get total number of allocated VGPRs to determine the current occupancy.
+ unsigned NumVGPRs = 0;
+ unsigned NumAGPRs = 0;
+ if (Matrix) {
+ for (MCPhysReg Reg : AMDGPU::VGPR_32RegClass)
+ if (Matrix->isPhysRegUsed(Reg))
+ NumVGPRs = std::max(NumVGPRs, getHWRegIndex(Reg) + 1);
+ for (MCPhysReg Reg : AMDGPU::AGPR_32RegClass)
+ if (Matrix->isPhysRegUsed(Reg))
+ NumAGPRs = std::max(NumAGPRs, getHWRegIndex(Reg) + 1);
+ }
+ unsigned NumAllocatedVGPRs =
+ AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(), NumAGPRs, NumVGPRs);
+
+ // Early exit if we should not apply anti-hints.
+ unsigned MaxVGPRsForCurrentOccupancy = 0;
+ if (!shouldApplyAntiHints(MF, NumAllocatedVGPRs, MaxVGPRsForCurrentOccupancy))
+ return;
+
+ // Returns true if Reg fits within the current occupancy VGPR budget.
+ auto IsWithinBudget = [&](MCPhysReg Reg) -> bool {
+ const TargetRegisterClass *RC = getPhysRegBaseClass(Reg);
+
+ // No VGPR or AGPR usage.
+ if (!RC ||
+ (!isVGPRClass(RC) && !isAGPRClass(RC) && !isVectorSuperClass(RC)))
+ return true;
+
+ unsigned NumRegs = divideCeil(getRegSizeInBits(*RC), 32);
+ unsigned Highest = getHWRegIndex(Reg) + NumRegs - 1;
+ return Highest < MaxVGPRsForCurrentOccupancy;
+ };
+
+ // Copy order.
+ OrderStorage.clear();
+ OrderStorage.assign(Order.begin(), Order.end());
+
+ // Helper to check if a register overlaps with any anti-hint.
+ auto isAntiHinted = [&](MCPhysReg Reg) {
+ return llvm::any_of(AntiHints, [&](MCPhysReg AntiHint) {
+ return regsOverlap(Reg, AntiHint);
+ });
+ };
+
+ // Find the cutoff point for the current occupancy VGPR budget.
+ auto *BeyondBudgetStart = llvm::find_if(
+ OrderStorage, [&](MCPhysReg Reg) { return !IsWithinBudget(Reg); });
+
+ // Only shuffle within the current occupancy VGPR budget.
+ auto *PartitionPoint =
+ std::stable_partition(OrderStorage.begin(), BeyondBudgetStart,
+ [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
+
+ Order = OrderStorage;
+ LLVM_DEBUG({
+ size_t NonAntiHintedCount =
+ std::distance(OrderStorage.begin(), PartitionPoint);
+ size_t AntiHintedCount = std::distance(PartitionPoint, BeyondBudgetStart);
+ size_t BeyondBudgetCount =
+ std::distance(BeyondBudgetStart, OrderStorage.end());
+ dbgs() << "Added " << NonAntiHintedCount
+ << " non-anti-hinted registers first\n"
+ << "Added " << AntiHintedCount
+ << " anti-hinted registers at the end\n"
+ << "Beyond current occupancy budget, left: " << BeyondBudgetCount
+ << '\n';
+ });
+}
+
MCRegister SIRegisterInfo::getReturnAddressReg(const MachineFunction &MF) const {
// Not a callee saved register.
return AMDGPU::SGPR30_SGPR31;
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index e464c9334ffea..61fbf90d84488 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -15,6 +15,11 @@
#define LLVM_LIB_TARGET_AMDGPU_SIREGISTERINFO_H
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/LiveRegMatrix.h"
+#include "llvm/CodeGen/Register.h"
+#include "llvm/CodeGen/VirtRegMap.h"
+#include "llvm/MC/MCRegister.h"
#define GET_REGINFO_HEADER
#include "AMDGPUGenRegisterInfo.inc"
@@ -364,6 +369,17 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
const MachineFunction &MF, const VirtRegMap *VRM,
const LiveRegMatrix *Matrix) const override;
+ bool shouldApplyAntiHints(const MachineFunction &MF,
+ unsigned NumAllocatedVGPRs,
+ unsigned &MaxVGPRsForCurrentOccupancy) const;
+
+ void applyRegAllocationAntiHints(
+ Register VirtReg, ArrayRef<MCPhysReg> &Order,
+ SmallVectorImpl<MCPhysReg> &OrderStorage,
+ SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
+ const VirtRegMap *VRM = nullptr,
+ const LiveRegMatrix *Matrix = nullptr) const override;
+
const int *getRegUnitPressureSets(MCRegUnit RegUnit) const override;
MCRegister getReturnAddressReg(const MachineFunction &MF) const;
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
new file mode 100644
index 0000000000000..5d698f533acf2
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
@@ -0,0 +1,373 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -run-pass=greedy,machineverifier,virtregrewriter,post-RA-hazard-rec %s -o - | FileCheck %s
+
+--- |
+ define amdgpu_kernel void @anti_hints_present() #0 { ret void }
+ define amdgpu_kernel void @anti_hints_absent() #0 { ret void }
+ define amdgpu_kernel void @anti_hints_suppressed_by_target_budget() #0 { ret void }
+ define amdgpu_kernel void @anti_hints_suppressed_by_current_budget() #0 { ret void }
+ attributes #0 = { nounwind "amdgpu-agpr-alloc"="0" "frame-pointer"="none"}
+...
+
+---
+name: anti_hints_present
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 8
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: sgpr_128 }
+ - { id: 4, class: vgpr_32 }
+ - { id: 5, class: vgpr_32 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: vreg_512_align2 }
+ - { id: 8, class: vreg_512_align2 }
+ - { id: 9, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 10, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 11, class: vreg_128_align2, anti-hints: [ '%7' ] }
+ - { id: 12, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 13, class: vreg_512_align2 }
+ - { id: 14, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 15, class: vreg_128_align2, anti-hints: [ '%8' ] }
+ - { id: 16, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 17, class: vreg_512_align2 }
+ - { id: 18, class: vreg_128_align2, anti-hints: [ '%8', '%13' ] }
+ - { id: 19, class: vreg_128_align2, anti-hints: [ '%13' ] }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4' }
+ - { reg: '$vgpr5' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5
+ ; CHECK-LABEL: name: anti_hints_present
+ ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr46 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr47 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr48 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr42_vgpr43_vgpr44_vgpr45 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr42_vgpr43_vgpr44_vgpr45, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr46, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr38_vgpr39_vgpr40_vgpr41, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr38_vgpr39_vgpr40_vgpr41, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr42, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr46, implicit killed renamable $vgpr47, implicit killed renamable $vgpr48, implicit killed renamable $vgpr43, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr38_vgpr39_vgpr40_vgpr41
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vgpr_32 = COPY $vgpr4
+ %2:vgpr_32 = COPY $vgpr5
+ %3:sgpr_128 = IMPLICIT_DEF
+ %4:vgpr_32 = V_ADD_U32_e32 4096, %2, implicit $exec
+ %5:vgpr_32 = V_LSHLREV_B32_e32 2, %2, implicit $exec
+ %6:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %4, %3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ %7:vreg_512_align2 = IMPLICIT_DEF
+ %8:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %6.sub0_sub1, %7, 0, 0, 0, implicit $mode, implicit $exec
+ %9:vgpr_32 = V_LSHLREV_B32_e32 2, %4, implicit $exec
+ %10:vgpr_32 = V_LSHLREV_B32_e32 4, %2, implicit $exec
+ %11:vreg_128_align2 = DS_READ_B128_gfx9 %1, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %11, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ %12:vgpr_32 = V_ADD_U32_e32 %2, %5, implicit $exec
+ %13:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub2_sub3, %6.sub2_sub3, %8, 0, 0, 0, implicit $mode, implicit $exec
+ %14:vgpr_32 = V_LSHLREV_B32_e32 2, %12, implicit $exec
+ %15:vreg_128_align2 = DS_READ_B128_gfx9 %1, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %15, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ %16:vgpr_32 = V_ADD_U32_e32 8192, %12, implicit $exec
+ %17:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %0.sub2_sub3, %13, 0, 0, 0, implicit $mode, implicit $exec
+ %18:vreg_128_align2 = DS_READ_B128_gfx9 %1, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %18, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ %19:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %16, %3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %5, implicit %9, implicit %10, implicit %14, implicit %17, implicit %19
+...
+
+---
+name: anti_hints_absent
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 8
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: sgpr_128 }
+ - { id: 4, class: vgpr_32 }
+ - { id: 5, class: vgpr_32 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: vreg_512_align2 }
+ - { id: 8, class: vreg_512_align2 }
+ - { id: 9, class: vgpr_32 }
+ - { id: 10, class: vgpr_32 }
+ - { id: 11, class: vreg_128_align2 }
+ - { id: 12, class: vgpr_32 }
+ - { id: 13, class: vreg_512_align2 }
+ - { id: 14, class: vgpr_32 }
+ - { id: 15, class: vreg_128_align2 }
+ - { id: 16, class: vgpr_32 }
+ - { id: 17, class: vreg_512_align2 }
+ - { id: 18, class: vreg_128_align2 }
+ - { id: 19, class: vreg_128_align2 }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4' }
+ - { reg: '$vgpr5' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5
+ ; CHECK-LABEL: name: anti_hints_absent
+ ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; CHECK-NEXT: S_NOP 4
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; CHECK-NEXT: S_NOP 5
+ ; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_NOP 6
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vgpr_32 = COPY $vgpr4
+ %2:vgpr_32 = COPY $vgpr5
+ %3:sgpr_128 = IMPLICIT_DEF
+ %4:vgpr_32 = V_ADD_U32_e32 4096, %2, implicit $exec
+ %5:vgpr_32 = V_LSHLREV_B32_e32 2, %2, implicit $exec
+ %6:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %4, %3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ %7:vreg_512_align2 = IMPLICIT_DEF
+ %8:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %6.sub0_sub1, %7, 0, 0, 0, implicit $mode, implicit $exec
+ %9:vgpr_32 = V_LSHLREV_B32_e32 2, %4, implicit $exec
+ %10:vgpr_32 = V_LSHLREV_B32_e32 4, %2, implicit $exec
+ %11:vreg_128_align2 = DS_READ_B128_gfx9 %1, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %11, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ %12:vgpr_32 = V_ADD_U32_e32 %2, %5, implicit $exec
+ %13:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub2_sub3, %6.sub2_sub3, %8, 0, 0, 0, implicit $mode, implicit $exec
+ %14:vgpr_32 = V_LSHLREV_B32_e32 2, %12, implicit $exec
+ %15:vreg_128_align2 = DS_READ_B128_gfx9 %1, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %15, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ %16:vgpr_32 = V_ADD_U32_e32 8192, %12, implicit $exec
+ %17:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %0.sub2_sub3, %13, 0, 0, 0, implicit $mode, implicit $exec
+ %18:vreg_128_align2 = DS_READ_B128_gfx9 %1, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %18, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ %19:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %16, %3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %5, implicit %9, implicit %10, implicit %14, implicit %17, implicit %19
+...
+
+---
+name: anti_hints_suppressed_by_target_budget
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 8
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: sgpr_128 }
+ - { id: 4, class: vgpr_32 }
+ - { id: 5, class: vgpr_32 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: vreg_512_align2 }
+ - { id: 8, class: vreg_512_align2 }
+ - { id: 9, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 10, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 11, class: vreg_128_align2, anti-hints: [ '%7' ] }
+ - { id: 12, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 13, class: vreg_512_align2 }
+ - { id: 14, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 15, class: vreg_128_align2, anti-hints: [ '%8' ] }
+ - { id: 16, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 17, class: vreg_512_align2 }
+ - { id: 18, class: vreg_128_align2, anti-hints: [ '%8', '%13' ] }
+ - { id: 19, class: vreg_128_align2, anti-hints: [ '%13' ] }
+ - { id: 20, class: vreg_128_align2 }
+ - { id: 21, class: vreg_128_align2 }
+ - { id: 22, class: vreg_128_align2 }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4' }
+ - { reg: '$vgpr5' }
+ - { reg: '$vgpr52_vgpr53_vgpr54_vgpr55' }
+ - { reg: '$vgpr56_vgpr57_vgpr58_vgpr59' }
+ - { reg: '$vgpr60_vgpr61_vgpr62_vgpr63' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; CHECK-LABEL: name: anti_hints_suppressed_by_target_budget
+ ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; CHECK-NEXT: S_NOP 4
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; CHECK-NEXT: S_NOP 5
+ ; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_NOP 6
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
+ %20:vreg_128_align2 = COPY $vgpr52_vgpr53_vgpr54_vgpr55
+ %21:vreg_128_align2 = COPY $vgpr56_vgpr57_vgpr58_vgpr59
+ %22:vreg_128_align2 = COPY $vgpr60_vgpr61_vgpr62_vgpr63
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vgpr_32 = COPY $vgpr4
+ %2:vgpr_32 = COPY $vgpr5
+ %3:sgpr_128 = IMPLICIT_DEF
+ %4:vgpr_32 = V_ADD_U32_e32 4096, %2, implicit $exec
+ %5:vgpr_32 = V_LSHLREV_B32_e32 2, %2, implicit $exec
+ %6:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %4, %3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ %7:vreg_512_align2 = IMPLICIT_DEF
+ %8:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %6.sub0_sub1, %7, 0, 0, 0, implicit $mode, implicit $exec
+ %9:vgpr_32 = V_LSHLREV_B32_e32 2, %4, implicit $exec
+ %10:vgpr_32 = V_LSHLREV_B32_e32 4, %2, implicit $exec
+ %11:vreg_128_align2 = DS_READ_B128_gfx9 %1, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %11, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ %12:vgpr_32 = V_ADD_U32_e32 %2, %5, implicit $exec
+ %13:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub2_sub3, %6.sub2_sub3, %8, 0, 0, 0, implicit $mode, implicit $exec
+ %14:vgpr_32 = V_LSHLREV_B32_e32 2, %12, implicit $exec
+ %15:vreg_128_align2 = DS_READ_B128_gfx9 %1, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %15, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ %16:vgpr_32 = V_ADD_U32_e32 8192, %12, implicit $exec
+ %17:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %0.sub2_sub3, %13, 0, 0, 0, implicit $mode, implicit $exec
+ %18:vreg_128_align2 = DS_READ_B128_gfx9 %1, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %18, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ %19:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %16, %3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %5, implicit %9, implicit %10, implicit %14, implicit %17, implicit %19, implicit %20, implicit %21, implicit %22
+...
+
+---
+name: anti_hints_suppressed_by_current_budget
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 4
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: sgpr_128 }
+ - { id: 4, class: vgpr_32 }
+ - { id: 5, class: vgpr_32 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: vreg_512_align2 }
+ - { id: 8, class: vreg_512_align2 }
+ - { id: 9, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 10, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 11, class: vreg_128_align2, anti-hints: [ '%7' ] }
+ - { id: 12, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 13, class: vreg_512_align2 }
+ - { id: 14, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 15, class: vreg_128_align2, anti-hints: [ '%8' ] }
+ - { id: 16, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 17, class: vreg_512_align2 }
+ - { id: 18, class: vreg_128_align2, anti-hints: [ '%8', '%13' ] }
+ - { id: 19, class: vreg_128_align2, anti-hints: [ '%13' ] }
+ - { id: 20, class: vreg_128_align2 }
+ - { id: 21, class: vreg_128_align2 }
+ - { id: 22, class: vreg_128_align2 }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4' }
+ - { reg: '$vgpr5' }
+ - { reg: '$vgpr52_vgpr53_vgpr54_vgpr55' }
+ - { reg: '$vgpr56_vgpr57_vgpr58_vgpr59' }
+ - { reg: '$vgpr60_vgpr61_vgpr62_vgpr63' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; CHECK-LABEL: name: anti_hints_suppressed_by_current_budget
+ ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; CHECK-NEXT: S_NOP 4
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; CHECK-NEXT: S_NOP 5
+ ; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_NOP 6
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
+ %20:vreg_128_align2 = COPY $vgpr52_vgpr53_vgpr54_vgpr55
+ %21:vreg_128_align2 = COPY $vgpr56_vgpr57_vgpr58_vgpr59
+ %22:vreg_128_align2 = COPY $vgpr60_vgpr61_vgpr62_vgpr63
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vgpr_32 = COPY $vgpr4
+ %2:vgpr_32 = COPY $vgpr5
+ %3:sgpr_128 = IMPLICIT_DEF
+ %4:vgpr_32 = V_ADD_U32_e32 4096, %2, implicit $exec
+ %5:vgpr_32 = V_LSHLREV_B32_e32 2, %2, implicit $exec
+ %6:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %4, %3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ %7:vreg_512_align2 = IMPLICIT_DEF
+ %8:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %6.sub0_sub1, %7, 0, 0, 0, implicit $mode, implicit $exec
+ %9:vgpr_32 = V_LSHLREV_B32_e32 2, %4, implicit $exec
+ %10:vgpr_32 = V_LSHLREV_B32_e32 4, %2, implicit $exec
+ %11:vreg_128_align2 = DS_READ_B128_gfx9 %1, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %11, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ %12:vgpr_32 = V_ADD_U32_e32 %2, %5, implicit $exec
+ %13:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub2_sub3, %6.sub2_sub3, %8, 0, 0, 0, implicit $mode, implicit $exec
+ %14:vgpr_32 = V_LSHLREV_B32_e32 2, %12, implicit $exec
+ %15:vreg_128_align2 = DS_READ_B128_gfx9 %1, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %15, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ %16:vgpr_32 = V_ADD_U32_e32 8192, %12, implicit $exec
+ %17:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %0.sub2_sub3, %13, 0, 0, 0, implicit $mode, implicit $exec
+ %18:vreg_128_align2 = DS_READ_B128_gfx9 %1, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %18, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ %19:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %16, %3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %5, implicit %9, implicit %10, implicit %14, implicit %17, implicit %19, implicit %20, implicit %21, implicit %22
+...
>From 463d506d42371d2cfcdbcffc49a713d249c753ce Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 26 Aug 2026 10:18:38 -0500
Subject: [PATCH 04/19] Addressed review
---
llvm/lib/CodeGen/AllocationOrder.cpp | 12 +++++-------
llvm/lib/CodeGen/AllocationOrder.h | 8 ++++----
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index 1b3d3639fbc2a..ca34a00ea5d08 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -9,7 +9,8 @@
// This file implements an allocation order for virtual registers.
//
// The preferred allocation order for a virtual register depends on allocation
-// hints and target hooks. The AllocationOrder class encapsulates all of that.
+// hints, anti-hints, and target hooks. The AllocationOrder class encapsulates
+// all of that.
//
//===----------------------------------------------------------------------===//
@@ -59,19 +60,16 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
}
});
- // Storage for filtered order (used if anti-hints cause reordering)
+ // Storage for shuffled order (used if anti-hints cause reordering)
SmallVector<MCPhysReg, 16> ShuffledOrder;
if (!AntiHintedPhysRegs.empty()) {
TRI->applyRegAllocationAntiHints(VirtReg, Order, ShuffledOrder,
AntiHintedPhysRegs, MF, &VRM, Matrix);
}
- // Use ShuffledOrder as the order if it was populated by anti-hints
- // processing
- ArrayRef<MCPhysReg> FinalOrder =
- ShuffledOrder.empty() ? Order : ShuffledOrder;
+
// Create allocation order object
- AllocationOrder AO(std::move(Hints), FinalOrder, HardHints,
+ AllocationOrder AO(std::move(Hints), Order, HardHints,
std::move(ShuffledOrder));
assert(all_of(AO.Hints,
diff --git a/llvm/lib/CodeGen/AllocationOrder.h b/llvm/lib/CodeGen/AllocationOrder.h
index 3b7c7cd4cac10..84e459c5b8e67 100644
--- a/llvm/lib/CodeGen/AllocationOrder.h
+++ b/llvm/lib/CodeGen/AllocationOrder.h
@@ -32,7 +32,7 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
const SmallVector<MCPhysReg, 16> Hints;
// Used as storage if the Order received in the constructor needs to be
// altered.
- SmallVector<MCPhysReg, 16> FilteredOrderStorage;
+ SmallVector<MCPhysReg, 16> ShuffledOrderStorage;
ArrayRef<MCPhysReg> Order;
// How far into the Order we can iterate. This is 0 if the AllocationOrder is
// constructed with HardHints = true, Order.size() otherwise. While
@@ -96,11 +96,11 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
: Hints(std::move(Hints)), Order(Order),
IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {}
- /// Create an AllocationOrder with pre-computed FilteredOrderStorage.
+ /// Create an AllocationOrder with pre-computed ShuffledOrderStorage.
AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order,
bool HardHints, SmallVector<MCPhysReg, 16> &&Storage)
- : Hints(std::move(Hints)), FilteredOrderStorage(std::move(Storage)),
- Order(FilteredOrderStorage.empty() ? Order : FilteredOrderStorage),
+ : Hints(std::move(Hints)), ShuffledOrderStorage(std::move(Storage)),
+ Order(ShuffledOrderStorage.empty() ? Order : ShuffledOrderStorage),
IterationLimit(HardHints ? 0 : static_cast<int>(this->Order.size())) {}
Iterator begin() const {
>From 4b809a2ba5791f96d69b6801b94e1c1e7586bed7 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 26 Aug 2026 13:50:20 -0500
Subject: [PATCH 05/19] Addressed review
---
llvm/include/llvm/CodeGen/MIRYamlMapping.h | 6 +++---
llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 5 +++--
.../register-allocation-antihints-mir-print-parse.mir | 2 +-
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index 05f6be547f367..142ace2cf765f 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -228,13 +228,13 @@ template <> struct MappingTraits<VirtualRegisterDefinition> {
StringValue()); // Don't print out when it's empty.
YamlIO.mapOptional("flags", Reg.RegisterFlags,
std::vector<FlowStringValue>());
- if (!YamlIO.outputting() || !Reg.AntiHints.empty())
- YamlIO.mapOptional("anti-hints", Reg.AntiHints,
- std::vector<FlowStringValue>());
// MIRPrinter sets WriteDefaultValues=true unless -simplify-mir is passed,
// so a plain mapOptional with an empty default would still emit the keys
// and change every existing test's output.
// Skip the call on output when empty to keep them off entirely.
+ if (!YamlIO.outputting() || !Reg.AntiHints.empty())
+ YamlIO.mapOptional("anti-hints", Reg.AntiHints,
+ std::vector<FlowStringValue>());
if (!YamlIO.outputting() || !Reg.SplitFrom.Value.empty())
YamlIO.mapOptional("split-from", Reg.SplitFrom, StringValue());
if (!YamlIO.outputting() || !Reg.AssignedPhys.Value.empty())
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 8783078485877..febb010bb4d09 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -781,10 +781,11 @@ bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
if (parseRegisterReference(PFS, AntiHintReg, AntiHintValue.Value, Error))
return error(Error, AntiHintValue.SourceRange);
- if (!AntiHintReg.isVirtual())
+ if (!AntiHintReg.isVirtual()) {
return error(AntiHintValue.SourceRange.Start,
- Twine("anti-hint '") + AntiHintValue.Value +
+ "anti-hint '" + Twine(AntiHintValue.Value) +
"' must be a virtual register");
+ }
Info.AntiHints.push_back(AntiHintReg);
}
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir b/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir
index 574fe61c416de..12e15c3ef55b8 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/register-allocation-antihints-mir-print-parse.mir
@@ -1,4 +1,4 @@
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -run-pass=none -o - %s | FileCheck %s
+# RUN: llc -mtriple=amdgpu9.42-amd-amdhsa -run-pass=none -o - %s | FileCheck %s
---
name: single_anti_hint
>From a018b6c8a3ee5a4afeb50680faa2d0db5525cea7 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Sun, 30 Aug 2026 15:00:47 -0500
Subject: [PATCH 06/19] Addressed review: Removed ShuffledOrderStorage
---
.../include/llvm/CodeGen/TargetRegisterInfo.h | 13 +++---
llvm/lib/CodeGen/AllocationOrder.cpp | 31 +++++++------
llvm/lib/CodeGen/AllocationOrder.h | 44 +++++++++++--------
llvm/lib/CodeGen/TargetRegisterInfo.cpp | 25 +++++------
.../unittests/CodeGen/AllocationOrderTest.cpp | 21 ++++-----
5 files changed, 69 insertions(+), 65 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index e0c358d25a087..bdb2a4d0363b5 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -853,13 +853,12 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
}
/// Apply anti-hints to the allocation order.
- virtual void
- applyRegAllocationAntiHints(Register VirtReg, ArrayRef<MCPhysReg> &Order,
- SmallVectorImpl<MCPhysReg> &OrderStorage,
- SmallVectorImpl<MCPhysReg> &AntiHints,
- const MachineFunction &MF,
- const VirtRegMap *VRM = nullptr,
- const LiveRegMatrix *Matrix = nullptr) const;
+ virtual void applyRegAllocationAntiHints(
+ Register VirtReg, ArrayRef<MCPhysReg> Order,
+ SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
+ SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
+ const VirtRegMap *VRM = nullptr,
+ const LiveRegMatrix *Matrix = nullptr) const;
/// Allow the target to reverse allocation order of local live ranges. This
/// will generally allocate shorter local live ranges first. For targets with
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index ca34a00ea5d08..2367095ce23df 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -34,14 +34,20 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo();
const MachineRegisterInfo &MRI = MF.getRegInfo();
auto Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
- SmallVector<MCPhysReg, 16> Hints;
- bool HardHints =
- TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix);
+
+ // HintsAndCustomOrder holds Hints first followed by the shuffled order if the
+ // anti-hints shuffle it.
+ SmallVector<MCPhysReg, 16> HintsAndCustomOrder;
+
+ // Get hints
+ bool HardHints = TRI->getRegAllocationHints(
+ VirtReg, Order, HintsAndCustomOrder, MF, &VRM, Matrix);
+ const int NumHints = static_cast<int>(HintsAndCustomOrder.size());
LLVM_DEBUG({
- if (!Hints.empty()) {
+ if (NumHints) {
dbgs() << "hints:";
- for (MCPhysReg Hint : Hints)
+ for (MCPhysReg Hint : HintsAndCustomOrder)
dbgs() << ' ' << printReg(Hint, TRI);
dbgs() << '\n';
}
@@ -60,19 +66,18 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
}
});
- // Storage for shuffled order (used if anti-hints cause reordering)
- SmallVector<MCPhysReg, 16> ShuffledOrder;
-
if (!AntiHintedPhysRegs.empty()) {
- TRI->applyRegAllocationAntiHints(VirtReg, Order, ShuffledOrder,
- AntiHintedPhysRegs, MF, &VRM, Matrix);
+ HintsAndCustomOrder.reserve(NumHints + Order.size());
+ TRI->applyRegAllocationAntiHints(VirtReg, Order, HintsAndCustomOrder,
+ NumHints, AntiHintedPhysRegs, MF, &VRM,
+ Matrix);
}
// Create allocation order object
- AllocationOrder AO(std::move(Hints), Order, HardHints,
- std::move(ShuffledOrder));
+ AllocationOrder AO(std::move(HintsAndCustomOrder), NumHints, Order,
+ HardHints);
- assert(all_of(AO.Hints,
+ assert(all_of(AO.hints(),
[&](MCPhysReg Hint) { return is_contained(AO.Order, Hint); }) &&
"Target hint is outside allocation order.");
return AO;
diff --git a/llvm/lib/CodeGen/AllocationOrder.h b/llvm/lib/CodeGen/AllocationOrder.h
index 84e459c5b8e67..643c927103802 100644
--- a/llvm/lib/CodeGen/AllocationOrder.h
+++ b/llvm/lib/CodeGen/AllocationOrder.h
@@ -29,10 +29,11 @@ class VirtRegMap;
class LiveRegMatrix;
class LLVM_LIBRARY_VISIBILITY AllocationOrder {
- const SmallVector<MCPhysReg, 16> Hints;
- // Used as storage if the Order received in the constructor needs to be
- // altered.
- SmallVector<MCPhysReg, 16> ShuffledOrderStorage;
+ // The Hints occupy [0, NumHints). If the Order received in the constructor
+ // needed to be shuffled, the shuffled copy is stored right after them, at
+ // [NumHints, end).
+ const SmallVector<MCPhysReg, 16> HintsAndCustomOrder;
+ const int NumHints;
ArrayRef<MCPhysReg> Order;
// How far into the Order we can iterate. This is 0 if the AllocationOrder is
// constructed with HardHints = true, Order.size() otherwise. While
@@ -43,6 +44,10 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
// IterationLimit defines an invalid iterator position.
const int IterationLimit;
+ ArrayRef<MCPhysReg> hints() const {
+ return ArrayRef<MCPhysReg>(HintsAndCustomOrder).take_front(NumHints);
+ }
+
public:
/// Forward iterator for an AllocationOrder.
class Iterator final {
@@ -58,7 +63,7 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
/// Return the next physical register in the allocation order.
MCRegister operator*() const {
if (Pos < 0)
- return AO.Hints.end()[Pos];
+ return AO.HintsAndCustomOrder[AO.NumHints + Pos];
assert(Pos < AO.IterationLimit);
return AO.Order[Pos];
}
@@ -89,23 +94,26 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix);
+ /// Create an AllocationOrder from HintsAndCustomOrder that contains NumHints
+ /// Hints optionally followed by a reordered Order. If no reordered copy is
+ /// present use Order as-is.
+ AllocationOrder(SmallVector<MCPhysReg, 16> &&HintsAndCustomOrder,
+ int NumHints, ArrayRef<MCPhysReg> Order, bool HardHints)
+ : HintsAndCustomOrder(std::move(HintsAndCustomOrder)), NumHints(NumHints),
+ Order(static_cast<int>(this->HintsAndCustomOrder.size()) > NumHints
+ ? ArrayRef<MCPhysReg>(this->HintsAndCustomOrder)
+ .drop_front(NumHints)
+ : Order),
+ IterationLimit(HardHints ? 0 : static_cast<int>(this->Order.size())) {}
+
/// Create an AllocationOrder given the Hints, Order, and HardHints values.
/// Use the create method above - the ctor is for unittests.
AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order,
bool HardHints)
- : Hints(std::move(Hints)), Order(Order),
- IterationLimit(HardHints ? 0 : static_cast<int>(Order.size())) {}
+ : AllocationOrder(std::move(Hints), static_cast<int>(Hints.size()), Order,
+ HardHints) {}
- /// Create an AllocationOrder with pre-computed ShuffledOrderStorage.
- AllocationOrder(SmallVector<MCPhysReg, 16> &&Hints, ArrayRef<MCPhysReg> Order,
- bool HardHints, SmallVector<MCPhysReg, 16> &&Storage)
- : Hints(std::move(Hints)), ShuffledOrderStorage(std::move(Storage)),
- Order(ShuffledOrderStorage.empty() ? Order : ShuffledOrderStorage),
- IterationLimit(HardHints ? 0 : static_cast<int>(this->Order.size())) {}
-
- Iterator begin() const {
- return Iterator(*this, -(static_cast<int>(Hints.size())));
- }
+ Iterator begin() const { return Iterator(*this, -NumHints); }
Iterator end() const { return Iterator(*this, IterationLimit); }
@@ -126,7 +134,7 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
assert(!Reg.isPhysical() ||
Reg.id() <
static_cast<uint32_t>(std::numeric_limits<MCPhysReg>::max()));
- return Reg.isPhysical() && is_contained(Hints, Reg.id());
+ return Reg.isPhysical() && is_contained(hints(), Reg.id());
}
};
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index fd696297e35d9..44defb5e455a8 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -444,8 +444,8 @@ bool TargetRegisterInfo::getRegAllocationHints(
}
void TargetRegisterInfo::applyRegAllocationAntiHints(
- Register VirtReg, ArrayRef<MCPhysReg> &Order,
- SmallVectorImpl<MCPhysReg> &OrderStorage,
+ Register VirtReg, ArrayRef<MCPhysReg> Order,
+ SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
@@ -458,29 +458,24 @@ void TargetRegisterInfo::applyRegAllocationAntiHints(
});
};
- // Copy order into storage
- OrderStorage.clear();
- OrderStorage.assign(Order.begin(), Order.end());
+ HintsAndCustomOrder.truncate(NumHints);
+ HintsAndCustomOrder.append(Order.begin(), Order.end());
// Partition non-anti-hinted register go first
- auto PartionPoint =
- std::stable_partition(OrderStorage.begin(), OrderStorage.end(),
- [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
-
- Order = OrderStorage;
+ auto *PartitionPoint = std::stable_partition(
+ HintsAndCustomOrder.begin() + NumHints, HintsAndCustomOrder.end(),
+ [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
- // print the details
LLVM_DEBUG({
size_t NonAntiHintedCount =
- std::distance(OrderStorage.begin(), PartionPoint);
- size_t AntiHintedCount = std::distance(PartionPoint, OrderStorage.end());
+ std::distance(HintsAndCustomOrder.begin() + NumHints, PartitionPoint);
+ size_t AntiHintedCount =
+ std::distance(PartitionPoint, HintsAndCustomOrder.end());
dbgs() << "Added " << NonAntiHintedCount
<< " non-anti-hinted registers first\n"
<< "Added " << AntiHintedCount
<< " anti-hinted registers at the end\n";
});
-
- return;
}
bool TargetRegisterInfo::isCalleeSavedPhysReg(
diff --git a/llvm/unittests/CodeGen/AllocationOrderTest.cpp b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
index ec02579f55c58..aa636b6673b1e 100644
--- a/llvm/unittests/CodeGen/AllocationOrderTest.cpp
+++ b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
@@ -117,26 +117,23 @@ TEST(AllocationOrderTest, IsHintTest) {
EXPECT_EQ(V, 5U);
}
-TEST(AllocationOrderTest, StorageOverridesOrder) {
- SmallVector<MCPhysReg, 16> Hints = {1, 2};
+TEST(AllocationOrderTest, AntiHintShuffleOrderOverridesOrder) {
+ SmallVector<MCPhysReg, 16> HintsAndCustomOrder = {1, 2, 5, 3, 4};
SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
- SmallVector<MCPhysReg, 16> Storage = {5, 3, 4};
- AllocationOrder O(std::move(Hints), Order, false, std::move(Storage));
+ AllocationOrder O(std::move(HintsAndCustomOrder), 2, Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 5, 3, 4}), loadOrder(O));
}
-TEST(AllocationOrderTest, EmptyStorageFallsBackToOrder) {
- SmallVector<MCPhysReg, 16> Hints = {1, 2};
+TEST(AllocationOrderTest, EmptyAntiHintedCustomOrderFallsBackToOrder) {
+ SmallVector<MCPhysReg, 16> HintsAndCustomOrder = {1, 2};
SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
- SmallVector<MCPhysReg, 16> Storage;
- AllocationOrder O(std::move(Hints), Order, false, std::move(Storage));
+ AllocationOrder O(std::move(HintsAndCustomOrder), 2, Order, false);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5}), loadOrder(O));
}
-TEST(AllocationOrderTest, StorageHardHints) {
- SmallVector<MCPhysReg, 16> Hints = {1, 2};
+TEST(AllocationOrderTest, HardHintsIgnoreAntiHintShuffleOrder) {
+ SmallVector<MCPhysReg, 16> HintsAndCustomOrder = {1, 2, 5, 3, 4};
SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
- SmallVector<MCPhysReg, 16> Storage = {5, 3, 4};
- AllocationOrder O(std::move(Hints), Order, true, std::move(Storage));
+ AllocationOrder O(std::move(HintsAndCustomOrder), 2, Order, true);
EXPECT_EQ((std::vector<MCPhysReg>{1, 2}), loadOrder(O));
}
>From 5a1ffce4766e26eb752daaf0e1edade9fdeddf85 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Sun, 30 Aug 2026 21:27:17 -0500
Subject: [PATCH 07/19] Addressed review: Removed OrderStorage
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 25 +++++++++++------------
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 4 ++--
2 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 97fca7ca20a26..b83922edabdd0 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -4224,8 +4224,8 @@ bool SIRegisterInfo::shouldApplyAntiHints(
}
void SIRegisterInfo::applyRegAllocationAntiHints(
- Register VirtReg, ArrayRef<MCPhysReg> &Order,
- SmallVectorImpl<MCPhysReg> &OrderStorage,
+ Register VirtReg, ArrayRef<MCPhysReg> Order,
+ SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
@@ -4266,9 +4266,8 @@ void SIRegisterInfo::applyRegAllocationAntiHints(
return Highest < MaxVGPRsForCurrentOccupancy;
};
- // Copy order.
- OrderStorage.clear();
- OrderStorage.assign(Order.begin(), Order.end());
+ HintsAndCustomOrder.truncate(NumHints);
+ HintsAndCustomOrder.append(Order.begin(), Order.end());
// Helper to check if a register overlaps with any anti-hint.
auto isAntiHinted = [&](MCPhysReg Reg) {
@@ -4278,21 +4277,21 @@ void SIRegisterInfo::applyRegAllocationAntiHints(
};
// Find the cutoff point for the current occupancy VGPR budget.
- auto *BeyondBudgetStart = llvm::find_if(
- OrderStorage, [&](MCPhysReg Reg) { return !IsWithinBudget(Reg); });
+ auto *BeyondBudgetStart =
+ llvm::find_if(llvm::drop_begin(HintsAndCustomOrder, NumHints),
+ [&](MCPhysReg Reg) { return !IsWithinBudget(Reg); });
// Only shuffle within the current occupancy VGPR budget.
- auto *PartitionPoint =
- std::stable_partition(OrderStorage.begin(), BeyondBudgetStart,
- [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
+ auto *PartitionPoint = std::stable_partition(
+ HintsAndCustomOrder.begin() + NumHints, BeyondBudgetStart,
+ [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
- Order = OrderStorage;
LLVM_DEBUG({
size_t NonAntiHintedCount =
- std::distance(OrderStorage.begin(), PartitionPoint);
+ std::distance(HintsAndCustomOrder.begin() + NumHints, PartitionPoint);
size_t AntiHintedCount = std::distance(PartitionPoint, BeyondBudgetStart);
size_t BeyondBudgetCount =
- std::distance(BeyondBudgetStart, OrderStorage.end());
+ std::distance(BeyondBudgetStart, HintsAndCustomOrder.end());
dbgs() << "Added " << NonAntiHintedCount
<< " non-anti-hinted registers first\n"
<< "Added " << AntiHintedCount
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 61fbf90d84488..7765849ab804b 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -374,8 +374,8 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
unsigned &MaxVGPRsForCurrentOccupancy) const;
void applyRegAllocationAntiHints(
- Register VirtReg, ArrayRef<MCPhysReg> &Order,
- SmallVectorImpl<MCPhysReg> &OrderStorage,
+ Register VirtReg, ArrayRef<MCPhysReg> Order,
+ SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
const VirtRegMap *VRM = nullptr,
const LiveRegMatrix *Matrix = nullptr) const override;
>From 17742ac7d881877907d769a0ca04bb9d0007517a Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Tue, 1 Sep 2026 14:02:53 -0500
Subject: [PATCH 08/19] Addressed review: Added test
---
.../AMDGPU/llvm.amdgcn.mfma.anti-hints.mir | 406 +++++++++++++-----
1 file changed, 300 insertions(+), 106 deletions(-)
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
index 5d698f533acf2..6145c11dbc54b 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
@@ -1,12 +1,16 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -run-pass=greedy,machineverifier,virtregrewriter,post-RA-hazard-rec %s -o - | FileCheck %s
+# RUN: llc -mtriple=amdgpu9.42-amd-amdhsa -run-pass=greedy,machineverifier,virtregrewriter,post-RA-hazard-rec %s -o - | FileCheck %s --check-prefixes=AH,GFX942
+# RUN: llc -mtriple=amdgpu9.0a-amd-amdhsa -run-pass=greedy,machineverifier,virtregrewriter,post-RA-hazard-rec %s -o - | FileCheck %s --check-prefixes=AH,GFX90A
--- |
define amdgpu_kernel void @anti_hints_present() #0 { ret void }
define amdgpu_kernel void @anti_hints_absent() #0 { ret void }
define amdgpu_kernel void @anti_hints_suppressed_by_target_budget() #0 { ret void }
define amdgpu_kernel void @anti_hints_suppressed_by_current_budget() #0 { ret void }
+ define amdgpu_kernel void @anti_hints_unified_agpr_headroom () #1 { ret void }
+ define amdgpu_kernel void @anti_hints_unified_agpr_budget () #1 { ret void }
attributes #0 = { nounwind "amdgpu-agpr-alloc"="0" "frame-pointer"="none"}
+ attributes #1 = { nounwind "frame-pointer"="none"}
...
---
@@ -43,30 +47,30 @@ liveins:
body: |
bb.0:
liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5
- ; CHECK-LABEL: name: anti_hints_present
- ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
- ; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr46 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr47 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: renamable $vgpr48 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr42_vgpr43_vgpr44_vgpr45 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr42_vgpr43_vgpr44_vgpr45, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr46, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr38_vgpr39_vgpr40_vgpr41, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr38_vgpr39_vgpr40_vgpr41, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr42, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr46, implicit killed renamable $vgpr47, implicit killed renamable $vgpr48, implicit killed renamable $vgpr43, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr38_vgpr39_vgpr40_vgpr41
+ ; AH-LABEL: name: anti_hints_present
+ ; AH: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
+ ; AH-NEXT: {{ $}}
+ ; AH-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; AH-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; AH-NEXT: renamable $vgpr46 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; AH-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; AH-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; AH-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; AH-NEXT: renamable $vgpr47 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; AH-NEXT: renamable $vgpr48 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; AH-NEXT: renamable $vgpr42_vgpr43_vgpr44_vgpr45 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr42_vgpr43_vgpr44_vgpr45, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr46, implicit $exec
+ ; AH-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; AH-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; AH-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr38_vgpr39_vgpr40_vgpr41, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr42 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; AH-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; AH-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr38_vgpr39_vgpr40_vgpr41, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr42, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; AH-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr46, implicit killed renamable $vgpr47, implicit killed renamable $vgpr48, implicit killed renamable $vgpr43, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr38_vgpr39_vgpr40_vgpr41
%0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
%1:vgpr_32 = COPY $vgpr4
%2:vgpr_32 = COPY $vgpr5
@@ -127,33 +131,61 @@ liveins:
body: |
bb.0:
liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5
- ; CHECK-LABEL: name: anti_hints_absent
- ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
- ; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
- ; CHECK-NEXT: S_NOP 4
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
- ; CHECK-NEXT: S_NOP 5
- ; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: S_NOP 6
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25
+ ; GFX942-LABEL: name: anti_hints_absent
+ ; GFX942: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
+ ; GFX942-NEXT: {{ $}}
+ ; GFX942-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX942-NEXT: S_NOP 4
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX942-NEXT: S_NOP 5
+ ; GFX942-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: S_NOP 6
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25
+ ;
+ ; GFX90A-LABEL: name: anti_hints_absent
+ ; GFX90A: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3
+ ; GFX90A-NEXT: {{ $}}
+ ; GFX90A-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: S_NOP 12
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX90A-NEXT: S_NOP 13
+ ; GFX90A-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: S_NOP 14
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25
%0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
%1:vgpr_32 = COPY $vgpr4
%2:vgpr_32 = COPY $vgpr5
@@ -220,33 +252,61 @@ liveins:
body: |
bb.0:
liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
- ; CHECK-LABEL: name: anti_hints_suppressed_by_target_budget
- ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
- ; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
- ; CHECK-NEXT: S_NOP 4
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
- ; CHECK-NEXT: S_NOP 5
- ; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: S_NOP 6
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX942-LABEL: name: anti_hints_suppressed_by_target_budget
+ ; GFX942: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX942-NEXT: {{ $}}
+ ; GFX942-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX942-NEXT: S_NOP 4
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX942-NEXT: S_NOP 5
+ ; GFX942-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: S_NOP 6
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
+ ;
+ ; GFX90A-LABEL: name: anti_hints_suppressed_by_target_budget
+ ; GFX90A: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX90A-NEXT: {{ $}}
+ ; GFX90A-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: S_NOP 12
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX90A-NEXT: S_NOP 13
+ ; GFX90A-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: S_NOP 14
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
%20:vreg_128_align2 = COPY $vgpr52_vgpr53_vgpr54_vgpr55
%21:vreg_128_align2 = COPY $vgpr56_vgpr57_vgpr58_vgpr59
%22:vreg_128_align2 = COPY $vgpr60_vgpr61_vgpr62_vgpr63
@@ -316,33 +376,61 @@ liveins:
body: |
bb.0:
liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
- ; CHECK-LABEL: name: anti_hints_suppressed_by_current_budget
- ; CHECK: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
- ; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
- ; CHECK-NEXT: S_NOP 4
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
- ; CHECK-NEXT: S_NOP 5
- ; CHECK-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
- ; CHECK-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
- ; CHECK-NEXT: S_NOP 6
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
- ; CHECK-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
- ; CHECK-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
- ; CHECK-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX942-LABEL: name: anti_hints_suppressed_by_current_budget
+ ; GFX942: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX942-NEXT: {{ $}}
+ ; GFX942-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX942-NEXT: S_NOP 4
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX942-NEXT: S_NOP 5
+ ; GFX942-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: S_NOP 6
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
+ ;
+ ; GFX90A-LABEL: name: anti_hints_suppressed_by_current_budget
+ ; GFX90A: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX90A-NEXT: {{ $}}
+ ; GFX90A-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: S_NOP 12
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX90A-NEXT: S_NOP 13
+ ; GFX90A-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: S_NOP 14
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit killed renamable $vgpr52_vgpr53_vgpr54_vgpr55, implicit killed renamable $vgpr56_vgpr57_vgpr58_vgpr59, implicit killed renamable $vgpr60_vgpr61_vgpr62_vgpr63
%20:vreg_128_align2 = COPY $vgpr52_vgpr53_vgpr54_vgpr55
%21:vreg_128_align2 = COPY $vgpr56_vgpr57_vgpr58_vgpr59
%22:vreg_128_align2 = COPY $vgpr60_vgpr61_vgpr62_vgpr63
@@ -371,3 +459,109 @@ body: |
%19:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %16, %3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %5, implicit %9, implicit %10, implicit %14, implicit %17, implicit %19, implicit %20, implicit %21, implicit %22
...
+
+---
+name: anti_hints_unified_agpr_headroom
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 6
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vreg_128_align2 }
+ - { id: 2, class: vreg_128_align2 }
+ - { id: 3, class: vreg_128_align2 }
+ - { id: 4, class: vreg_512_align2, anti-hints: [ '%8' ] }
+ - { id: 5, class: vreg_128_align2 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: areg_256_align2 }
+ - { id: 8, class: vreg_512_align2, anti-hints: [ '%4' ] }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4_vgpr5_vgpr6_vgpr7' }
+ - { reg: '$vgpr8_vgpr9_vgpr10_vgpr11' }
+ - { reg: '$vgpr12_vgpr13_vgpr14_vgpr15' }
+ - { reg: '$vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31' }
+ - { reg: '$vgpr32_vgpr33_vgpr34_vgpr35' }
+ - { reg: '$vgpr36_vgpr37_vgpr38_vgpr39' }
+ - { reg: '$agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7
+ ; AH-LABEL: name: anti_hints_unified_agpr_headroom
+ ; AH: liveins: $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ ; AH-NEXT: {{ $}}
+ ; AH-NEXT: dead renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 $vgpr0_vgpr1, $vgpr4_vgpr5, killed $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec
+ ; AH-NEXT: renamable $vgpr40_vgpr41_vgpr42_vgpr43 = DS_READ_B128_gfx9 renamable $vgpr0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr44_vgpr45_vgpr46_vgpr47 = DS_READ_B128_gfx9 renamable $vgpr0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr48_vgpr49_vgpr50_vgpr51 = DS_READ_B128_gfx9 renamable $vgpr0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr52_vgpr53_vgpr54_vgpr55 = DS_READ_B128_gfx9 renamable $vgpr0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4_vgpr5_vgpr6_vgpr7, implicit killed renamable $vgpr8_vgpr9_vgpr10_vgpr11, implicit killed renamable $vgpr12_vgpr13_vgpr14_vgpr15, implicit killed renamable $vgpr32_vgpr33_vgpr34_vgpr35, implicit killed renamable $vgpr36_vgpr37_vgpr38_vgpr39, implicit killed renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7, implicit killed renamable $vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vreg_128_align2 = COPY $vgpr4_vgpr5_vgpr6_vgpr7
+ %2:vreg_128_align2 = COPY $vgpr8_vgpr9_vgpr10_vgpr11
+ %3:vreg_128_align2 = COPY $vgpr12_vgpr13_vgpr14_vgpr15
+ %4:vreg_512_align2 = COPY $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ %5:vreg_128_align2 = COPY $vgpr32_vgpr33_vgpr34_vgpr35
+ %6:vreg_128_align2 = COPY $vgpr36_vgpr37_vgpr38_vgpr39
+ %7:areg_256_align2 = COPY $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7
+ %4:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 %0.sub0_sub1, %1.sub0_sub1, %4, 0, 0, 0, implicit $mode, implicit $exec
+ undef %8.sub0_sub1_sub2_sub3:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ %8.sub4_sub5_sub6_sub7:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ %8.sub8_sub9_sub10_sub11:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ %8.sub12_sub13_sub14_sub15:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %3, implicit %5, implicit %6, implicit %7, implicit %8
+...
+
+---
+name: anti_hints_unified_agpr_budget
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 6
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vreg_128_align2 }
+ - { id: 2, class: vreg_128_align2 }
+ - { id: 3, class: vreg_128_align2 }
+ - { id: 4, class: vreg_512_align2, anti-hints: [ '%8' ] }
+ - { id: 5, class: vreg_128_align2 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: areg_512_align2 }
+ - { id: 8, class: vreg_512_align2, anti-hints: [ '%4' ] }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4_vgpr5_vgpr6_vgpr7' }
+ - { reg: '$vgpr8_vgpr9_vgpr10_vgpr11' }
+ - { reg: '$vgpr12_vgpr13_vgpr14_vgpr15' }
+ - { reg: '$vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31' }
+ - { reg: '$vgpr32_vgpr33_vgpr34_vgpr35' }
+ - { reg: '$vgpr36_vgpr37_vgpr38_vgpr39' }
+ - { reg: '$agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15
+ ; AH-LABEL: name: anti_hints_unified_agpr_budget
+ ; AH: liveins: $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ ; AH-NEXT: {{ $}}
+ ; AH-NEXT: dead renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 $vgpr0_vgpr1, $vgpr4_vgpr5, killed $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec
+ ; AH-NEXT: renamable $vgpr40_vgpr41_vgpr42_vgpr43 = DS_READ_B128_gfx9 renamable $vgpr0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr44_vgpr45_vgpr46_vgpr47 = DS_READ_B128_gfx9 renamable $vgpr0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr48_vgpr49_vgpr50_vgpr51 = DS_READ_B128_gfx9 renamable $vgpr0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: renamable $vgpr52_vgpr53_vgpr54_vgpr55 = DS_READ_B128_gfx9 renamable $vgpr0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4_vgpr5_vgpr6_vgpr7, implicit killed renamable $vgpr8_vgpr9_vgpr10_vgpr11, implicit killed renamable $vgpr12_vgpr13_vgpr14_vgpr15, implicit killed renamable $vgpr32_vgpr33_vgpr34_vgpr35, implicit killed renamable $vgpr36_vgpr37_vgpr38_vgpr39, implicit killed renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, implicit killed renamable $vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vreg_128_align2 = COPY $vgpr4_vgpr5_vgpr6_vgpr7
+ %2:vreg_128_align2 = COPY $vgpr8_vgpr9_vgpr10_vgpr11
+ %3:vreg_128_align2 = COPY $vgpr12_vgpr13_vgpr14_vgpr15
+ %4:vreg_512_align2 = COPY $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ %5:vreg_128_align2 = COPY $vgpr32_vgpr33_vgpr34_vgpr35
+ %6:vreg_128_align2 = COPY $vgpr36_vgpr37_vgpr38_vgpr39
+ %7:areg_512_align2 = COPY $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15
+ %4:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 %0.sub0_sub1, %1.sub0_sub1, %4, 0, 0, 0, implicit $mode, implicit $exec
+ undef %8.sub0_sub1_sub2_sub3:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ %8.sub4_sub5_sub6_sub7:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ %8.sub8_sub9_sub10_sub11:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ %8.sub12_sub13_sub14_sub15:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %3, implicit %5, implicit %6, implicit %7, implicit %8
+...
\ No newline at end of file
>From 47d8d5da1bf5ba803e7d87b24b64d249d509f30b Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Tue, 1 Sep 2026 14:23:36 -0500
Subject: [PATCH 09/19] Addressed reveiw
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 24 ++++++++++----
.../AMDGPU/llvm.amdgcn.mfma.anti-hints.mir | 33 +++++++++++++------
2 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index b83922edabdd0..93c9b1f8e948c 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -23,7 +23,6 @@
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
-#include "llvm/MC/MCRegister.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -4199,8 +4198,11 @@ bool SIRegisterInfo::shouldApplyAntiHints(
if (CurrentOccupancy == 1)
return true;
- // Set max VGPRs for target and current occupancy to early bail out if we are
- // close to the limit.
+ // Do not apply anti-hints if we are reaching close to the VGPR budget. For
+ // target occupancy, the 80% cutoff is a conservative: anti-hints are disabled
+ // early enough that later registers still have headroom to stay at target
+ // occupancy. For current occupancy, the 95% cutoff margin is used to apply
+ // anti-hints close to the limit of the current occupancy budget.
unsigned MaxVGPRsCutOffForTargetOccupancy =
(ST.getMaxNumVGPRs(TargetOccupancy, DynamicVGPRBlockSize) * 80) / 100;
unsigned MaxVGPRsCutOffForCurrentOccupancy =
@@ -4261,9 +4263,19 @@ void SIRegisterInfo::applyRegAllocationAntiHints(
(!isVGPRClass(RC) && !isAGPRClass(RC) && !isVectorSuperClass(RC)))
return true;
- unsigned NumRegs = divideCeil(getRegSizeInBits(*RC), 32);
- unsigned Highest = getHWRegIndex(Reg) + NumRegs - 1;
- return Highest < MaxVGPRsForCurrentOccupancy;
+ unsigned RegEndIndex =
+ getHWRegIndex(Reg) + divideCeil(getRegSizeInBits(*RC), 32);
+
+ unsigned MaxVGPR = NumVGPRs;
+ unsigned MaxAGPR = NumAGPRs;
+ if (isAGPRClass(RC))
+ MaxAGPR = std::max(MaxAGPR, RegEndIndex);
+ else
+ MaxVGPR = std::max(MaxVGPR, RegEndIndex);
+
+ return static_cast<unsigned>(AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(),
+ MaxAGPR, MaxVGPR)) <=
+ MaxVGPRsForCurrentOccupancy;
};
HintsAndCustomOrder.truncate(NumHints);
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
index 6145c11dbc54b..2eec9fe8c8eb2 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
@@ -541,15 +541,28 @@ liveins:
body: |
bb.0:
liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15
- ; AH-LABEL: name: anti_hints_unified_agpr_budget
- ; AH: liveins: $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
- ; AH-NEXT: {{ $}}
- ; AH-NEXT: dead renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 $vgpr0_vgpr1, $vgpr4_vgpr5, killed $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec
- ; AH-NEXT: renamable $vgpr40_vgpr41_vgpr42_vgpr43 = DS_READ_B128_gfx9 renamable $vgpr0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
- ; AH-NEXT: renamable $vgpr44_vgpr45_vgpr46_vgpr47 = DS_READ_B128_gfx9 renamable $vgpr0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
- ; AH-NEXT: renamable $vgpr48_vgpr49_vgpr50_vgpr51 = DS_READ_B128_gfx9 renamable $vgpr0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
- ; AH-NEXT: renamable $vgpr52_vgpr53_vgpr54_vgpr55 = DS_READ_B128_gfx9 renamable $vgpr0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
- ; AH-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4_vgpr5_vgpr6_vgpr7, implicit killed renamable $vgpr8_vgpr9_vgpr10_vgpr11, implicit killed renamable $vgpr12_vgpr13_vgpr14_vgpr15, implicit killed renamable $vgpr32_vgpr33_vgpr34_vgpr35, implicit killed renamable $vgpr36_vgpr37_vgpr38_vgpr39, implicit killed renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, implicit killed renamable $vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55
+ ; GFX942-LABEL: name: anti_hints_unified_agpr_budget
+ ; GFX942: liveins: $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ ; GFX942-NEXT: {{ $}}
+ ; GFX942-NEXT: dead renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 $vgpr0_vgpr1, $vgpr4_vgpr5, killed $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: S_NOP 10
+ ; GFX942-NEXT: renamable $vgpr16_vgpr17_vgpr18_vgpr19 = DS_READ_B128_gfx9 renamable $vgpr0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr20_vgpr21_vgpr22_vgpr23 = DS_READ_B128_gfx9 renamable $vgpr0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr24_vgpr25_vgpr26_vgpr27 = DS_READ_B128_gfx9 renamable $vgpr0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr28_vgpr29_vgpr30_vgpr31 = DS_READ_B128_gfx9 renamable $vgpr0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4_vgpr5_vgpr6_vgpr7, implicit killed renamable $vgpr8_vgpr9_vgpr10_vgpr11, implicit killed renamable $vgpr12_vgpr13_vgpr14_vgpr15, implicit killed renamable $vgpr32_vgpr33_vgpr34_vgpr35, implicit killed renamable $vgpr36_vgpr37_vgpr38_vgpr39, implicit killed renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, implicit killed renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ ;
+ ; GFX90A-LABEL: name: anti_hints_unified_agpr_budget
+ ; GFX90A: liveins: $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, $vgpr12_vgpr13_vgpr14_vgpr15, $vgpr32_vgpr33_vgpr34_vgpr35, $vgpr36_vgpr37_vgpr38_vgpr39, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
+ ; GFX90A-NEXT: {{ $}}
+ ; GFX90A-NEXT: dead renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = contract V_MFMA_F32_32X32X8F16_mac_vgprcd_e64 $vgpr0_vgpr1, $vgpr4_vgpr5, killed $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: S_NOP 15
+ ; GFX90A-NEXT: S_NOP 2
+ ; GFX90A-NEXT: renamable $vgpr16_vgpr17_vgpr18_vgpr19 = DS_READ_B128_gfx9 renamable $vgpr0, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr20_vgpr21_vgpr22_vgpr23 = DS_READ_B128_gfx9 renamable $vgpr0, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr24_vgpr25_vgpr26_vgpr27 = DS_READ_B128_gfx9 renamable $vgpr0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr28_vgpr29_vgpr30_vgpr31 = DS_READ_B128_gfx9 renamable $vgpr0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4_vgpr5_vgpr6_vgpr7, implicit killed renamable $vgpr8_vgpr9_vgpr10_vgpr11, implicit killed renamable $vgpr12_vgpr13_vgpr14_vgpr15, implicit killed renamable $vgpr32_vgpr33_vgpr34_vgpr35, implicit killed renamable $vgpr36_vgpr37_vgpr38_vgpr39, implicit killed renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, implicit killed renamable $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31
%0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
%1:vreg_128_align2 = COPY $vgpr4_vgpr5_vgpr6_vgpr7
%2:vreg_128_align2 = COPY $vgpr8_vgpr9_vgpr10_vgpr11
@@ -564,4 +577,4 @@ body: |
%8.sub8_sub9_sub10_sub11:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
%8.sub12_sub13_sub14_sub15:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %3, implicit %5, implicit %6, implicit %7, implicit %8
-...
\ No newline at end of file
+...
>From 82e68bdd3c0dd3f2e24ad168103edb2f4ffbdbc0 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Fri, 4 Sep 2026 22:29:10 -0500
Subject: [PATCH 10/19] Addressed review and added target overrideable
filterAndSort
---
.../llvm/CodeGen/MachineRegisterInfo.h | 9 ++--
.../include/llvm/CodeGen/TargetRegisterInfo.h | 15 +++++--
llvm/lib/CodeGen/AllocationOrder.cpp | 30 +++++++------
llvm/lib/CodeGen/AllocationOrder.h | 10 ++---
llvm/lib/CodeGen/MachineRegisterInfo.cpp | 26 ++++++------
llvm/lib/CodeGen/TargetRegisterInfo.cpp | 42 ++++++++++++-------
.../unittests/CodeGen/AllocationOrderTest.cpp | 4 +-
7 files changed, 81 insertions(+), 55 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 890355febbb28..69d14fd11507f 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -922,7 +922,7 @@ class MachineRegisterInfo {
"Anti-hints and anti-hint targets are only for virtual registers");
AntiHintRegs.grow(VReg);
SmallVector<Register, 4> &AntiHints = AntiHintRegs[VReg];
- // Avoid duplicates
+ // Avoid duplicates.
if (!is_contained(AntiHints, AntiHintVReg))
AntiHints.push_back(AntiHintVReg);
}
@@ -959,11 +959,10 @@ class MachineRegisterInfo {
return is_contained(AntiHints, AntiHintVReg);
}
- /// Get the set of physical registers to avoid.
+ /// Get the BitVector of register units to avoid in anti-hints.
/// VRM is the current virtual register map showing allocations made so far.
- void getPhysRegAntiHints(Register VReg,
- SmallVectorImpl<MCPhysReg> &PhysAntiHints,
- const VirtRegMap &VRM) const;
+ void getBitVecRegAntiHints(Register VReg, BitVector &AntiHintedRegUnits,
+ const VirtRegMap &VRM) const;
/// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the
/// specified register as undefined which causes the DBG_VALUE to be
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index bdb2a4d0363b5..9de9e644effda 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -852,12 +852,21 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
// Do nothing.
}
+ /// Return true if Reg overlaps one of the anti-hinted register units.
+ bool isAntiHintedReg(MCPhysReg Reg,
+ const BitVector &AntiHintedRegUnits) const;
+
/// Apply anti-hints to the allocation order.
- virtual void applyRegAllocationAntiHints(
+ void applyRegAllocationAntiHints(
Register VirtReg, ArrayRef<MCPhysReg> Order,
SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
- SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
- const VirtRegMap *VRM = nullptr,
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
+ const LiveRegMatrix *Matrix = nullptr) const;
+
+ /// Custom reordering of the allocation order.
+ virtual void filterAndSortForAntiHintedRegs(
+ Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
const LiveRegMatrix *Matrix = nullptr) const;
/// Allow the target to reverse allocation order of local live ranges. This
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index 2367095ce23df..ac4485c849a00 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "AllocationOrder.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
@@ -35,15 +36,16 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
const MachineRegisterInfo &MRI = MF.getRegInfo();
auto Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
- // HintsAndCustomOrder holds Hints first followed by the shuffled order if the
- // anti-hints shuffle it.
+ // HintsAndCustomOrder holds Hints first followed by the custom order if the
+ // anti-hints reorders it.
SmallVector<MCPhysReg, 16> HintsAndCustomOrder;
- // Get hints
+ // Get Hints.
bool HardHints = TRI->getRegAllocationHints(
VirtReg, Order, HintsAndCustomOrder, MF, &VRM, Matrix);
const int NumHints = static_cast<int>(HintsAndCustomOrder.size());
+ // HintsAndCustomOrder only holds Hints (custom order is not added yet).
LLVM_DEBUG({
if (NumHints) {
dbgs() << "hints:";
@@ -53,27 +55,29 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
}
});
- // Get anti-hints
- SmallVector<MCPhysReg, 16> AntiHintedPhysRegs;
- MRI.getPhysRegAntiHints(VirtReg, AntiHintedPhysRegs, VRM);
+ // Get anti-hints.
+ BitVector AntiHintedRegUnits;
+ MRI.getBitVecRegAntiHints(VirtReg, AntiHintedRegUnits, VRM);
LLVM_DEBUG({
- if (!AntiHintedPhysRegs.empty()) {
+ if (AntiHintedRegUnits.any()) {
dbgs() << "anti-hints:";
- for (MCPhysReg AntiHint : AntiHintedPhysRegs)
- dbgs() << ' ' << printReg(AntiHint, TRI);
+ for (Register AntiHintVReg : MRI.getRegAllocationAntiHints(VirtReg)) {
+ if (!VRM.hasPhys(AntiHintVReg))
+ continue;
+ dbgs() << ' ' << printReg(VRM.getPhys(AntiHintVReg), TRI);
+ }
dbgs() << '\n';
}
});
- if (!AntiHintedPhysRegs.empty()) {
+ if (AntiHintedRegUnits.any()) {
HintsAndCustomOrder.reserve(NumHints + Order.size());
TRI->applyRegAllocationAntiHints(VirtReg, Order, HintsAndCustomOrder,
- NumHints, AntiHintedPhysRegs, MF, &VRM,
- Matrix);
+ NumHints, AntiHintedRegUnits, MF, Matrix);
}
- // Create allocation order object
+ // Create allocation order object.
AllocationOrder AO(std::move(HintsAndCustomOrder), NumHints, Order,
HardHints);
diff --git a/llvm/lib/CodeGen/AllocationOrder.h b/llvm/lib/CodeGen/AllocationOrder.h
index 643c927103802..09d8fd68de17b 100644
--- a/llvm/lib/CodeGen/AllocationOrder.h
+++ b/llvm/lib/CodeGen/AllocationOrder.h
@@ -29,9 +29,9 @@ class VirtRegMap;
class LiveRegMatrix;
class LLVM_LIBRARY_VISIBILITY AllocationOrder {
- // The Hints occupy [0, NumHints). If the Order received in the constructor
- // needed to be shuffled, the shuffled copy is stored right after them, at
- // [NumHints, end).
+ // Used as storage for both Hints and CustomOrder if the Order received in the
+ // constructor needs to be altered. [0, NumHints) contains regular hints. If a
+ // custom order is present, [NumHints, end) contains the custom order.
const SmallVector<MCPhysReg, 16> HintsAndCustomOrder;
const int NumHints;
ArrayRef<MCPhysReg> Order;
@@ -95,8 +95,8 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
const LiveRegMatrix *Matrix);
/// Create an AllocationOrder from HintsAndCustomOrder that contains NumHints
- /// Hints optionally followed by a reordered Order. If no reordered copy is
- /// present use Order as-is.
+ /// Hints optionally followed by a custom order. When that custom order is
+ /// present it becomes the allocation order otherwise Order is used as-is.
AllocationOrder(SmallVector<MCPhysReg, 16> &&HintsAndCustomOrder,
int NumHints, ArrayRef<MCPhysReg> Order, bool HardHints)
: HintsAndCustomOrder(std::move(HintsAndCustomOrder)), NumHints(NumHints),
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index 3918c169b978c..61fae6d3fa281 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -718,21 +718,23 @@ void MachineRegisterInfo::updateDbgUsersToReg(
}
}
-void MachineRegisterInfo::getPhysRegAntiHints(
- Register VReg, SmallVectorImpl<MCPhysReg> &PhysAntiHints,
- const VirtRegMap &VRM) const {
+void MachineRegisterInfo::getBitVecRegAntiHints(Register VReg,
+ BitVector &AntiHintedRegUnits,
+ const VirtRegMap &VRM) const {
assert(VReg.isVirtual() && "Anti-hints are only for virtual registers");
if (!AntiHintRegs.inBounds(VReg))
return;
- const SmallVector<Register, 4> &AntiHints = AntiHintRegs[VReg];
-
- for (Register AntiHintVReg : AntiHints) {
- // Check if the anti-hinted register has been allocated
- if (VRM.hasPhys(AntiHintVReg)) {
- MCPhysReg PhysReg = VRM.getPhys(AntiHintVReg);
- if (!is_contained(PhysAntiHints, PhysReg))
- PhysAntiHints.push_back(PhysReg);
- }
+ auto *TRI = getTargetRegisterInfo();
+ for (Register AntiHintVReg : AntiHintRegs[VReg]) {
+ // Check if the anti-hinted register has been allocated.
+ if (!VRM.hasPhys(AntiHintVReg))
+ continue;
+ // Delay until first allocated anti-hinted register so unused cases keep
+ // default empty BitVector.
+ if (AntiHintedRegUnits.empty())
+ AntiHintedRegUnits.resize(TRI->getNumRegUnits());
+ for (MCRegUnit Unit : TRI->regunits(VRM.getPhys(AntiHintVReg)))
+ AntiHintedRegUnits.set(static_cast<unsigned>(Unit));
}
}
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 44defb5e455a8..f6ec5c9ac46e0 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -443,34 +443,46 @@ bool TargetRegisterInfo::getRegAllocationHints(
return false;
}
+bool TargetRegisterInfo::isAntiHintedReg(
+ MCPhysReg Reg, const BitVector &AntiHintedRegUnits) const {
+ return llvm::any_of(regunits(Reg), [&](MCRegUnit Unit) {
+ return AntiHintedRegUnits.test(static_cast<unsigned>(Unit));
+ });
+}
+
void TargetRegisterInfo::applyRegAllocationAntiHints(
Register VirtReg, ArrayRef<MCPhysReg> Order,
SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
- SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
- const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
+ const LiveRegMatrix *Matrix) const {
- if (AntiHints.empty() || !VRM)
+ if (AntiHintedRegUnits.none())
return;
- auto isAntiHinted = [&](MCPhysReg Reg) {
- return llvm::any_of(AntiHints, [&](MCPhysReg AntiHint) {
- return regsOverlap(Reg, AntiHint);
- });
- };
-
HintsAndCustomOrder.truncate(NumHints);
HintsAndCustomOrder.append(Order.begin(), Order.end());
- // Partition non-anti-hinted register go first
+ // Custom reordering of the allocation order.
+ filterAndSortForAntiHintedRegs(
+ VirtReg,
+ MutableArrayRef<MCPhysReg>(HintsAndCustomOrder).drop_front(NumHints),
+ AntiHintedRegUnits, MF, Matrix);
+}
+
+void TargetRegisterInfo::filterAndSortForAntiHintedRegs(
+ Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
+ const LiveRegMatrix *Matrix) const {
+
+ // Partition non-anti-hinted register go first.
auto *PartitionPoint = std::stable_partition(
- HintsAndCustomOrder.begin() + NumHints, HintsAndCustomOrder.end(),
- [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
+ CustomOrder.begin(), CustomOrder.end(),
+ [&](MCPhysReg Reg) { return !isAntiHintedReg(Reg, AntiHintedRegUnits); });
LLVM_DEBUG({
size_t NonAntiHintedCount =
- std::distance(HintsAndCustomOrder.begin() + NumHints, PartitionPoint);
- size_t AntiHintedCount =
- std::distance(PartitionPoint, HintsAndCustomOrder.end());
+ std::distance(CustomOrder.begin(), PartitionPoint);
+ size_t AntiHintedCount = std::distance(PartitionPoint, CustomOrder.end());
dbgs() << "Added " << NonAntiHintedCount
<< " non-anti-hinted registers first\n"
<< "Added " << AntiHintedCount
diff --git a/llvm/unittests/CodeGen/AllocationOrderTest.cpp b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
index aa636b6673b1e..5346d1b1863aa 100644
--- a/llvm/unittests/CodeGen/AllocationOrderTest.cpp
+++ b/llvm/unittests/CodeGen/AllocationOrderTest.cpp
@@ -117,7 +117,7 @@ TEST(AllocationOrderTest, IsHintTest) {
EXPECT_EQ(V, 5U);
}
-TEST(AllocationOrderTest, AntiHintShuffleOrderOverridesOrder) {
+TEST(AllocationOrderTest, AntiHintCustomOrderOverridesOrder) {
SmallVector<MCPhysReg, 16> HintsAndCustomOrder = {1, 2, 5, 3, 4};
SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
AllocationOrder O(std::move(HintsAndCustomOrder), 2, Order, false);
@@ -131,7 +131,7 @@ TEST(AllocationOrderTest, EmptyAntiHintedCustomOrderFallsBackToOrder) {
EXPECT_EQ((std::vector<MCPhysReg>{1, 2, 3, 4, 5}), loadOrder(O));
}
-TEST(AllocationOrderTest, HardHintsIgnoreAntiHintShuffleOrder) {
+TEST(AllocationOrderTest, HardHintsIgnoreAntiHintCustomOrder) {
SmallVector<MCPhysReg, 16> HintsAndCustomOrder = {1, 2, 5, 3, 4};
SmallVector<MCPhysReg, 16> Order = {3, 4, 5};
AllocationOrder O(std::move(HintsAndCustomOrder), 2, Order, true);
>From f81b77befe88133209d38a941182a0ec58678b01 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Fri, 4 Sep 2026 22:52:30 -0500
Subject: [PATCH 11/19] Addressed review and added target overrideable
filterAndSort
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 36 +++++++----------------
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 8 ++---
2 files changed, 13 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 93c9b1f8e948c..a6124cf8fc89c 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -4225,15 +4225,10 @@ bool SIRegisterInfo::shouldApplyAntiHints(
return true;
}
-void SIRegisterInfo::applyRegAllocationAntiHints(
- Register VirtReg, ArrayRef<MCPhysReg> Order,
- SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
- SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
- const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {
-
- // Early exit to default order if we have no anti-hints or no VRM.
- if (AntiHints.empty() || !VRM)
- return;
+void SIRegisterInfo::filterAndSortForAntiHintedRegs(
+ Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
+ const LiveRegMatrix *Matrix) const {
// Get total number of allocated VGPRs to determine the current occupancy.
unsigned NumVGPRs = 0;
@@ -4278,32 +4273,21 @@ void SIRegisterInfo::applyRegAllocationAntiHints(
MaxVGPRsForCurrentOccupancy;
};
- HintsAndCustomOrder.truncate(NumHints);
- HintsAndCustomOrder.append(Order.begin(), Order.end());
-
- // Helper to check if a register overlaps with any anti-hint.
- auto isAntiHinted = [&](MCPhysReg Reg) {
- return llvm::any_of(AntiHints, [&](MCPhysReg AntiHint) {
- return regsOverlap(Reg, AntiHint);
- });
- };
-
// Find the cutoff point for the current occupancy VGPR budget.
- auto *BeyondBudgetStart =
- llvm::find_if(llvm::drop_begin(HintsAndCustomOrder, NumHints),
- [&](MCPhysReg Reg) { return !IsWithinBudget(Reg); });
+ auto *BeyondBudgetStart = llvm::find_if(
+ CustomOrder, [&](MCPhysReg Reg) { return !IsWithinBudget(Reg); });
// Only shuffle within the current occupancy VGPR budget.
auto *PartitionPoint = std::stable_partition(
- HintsAndCustomOrder.begin() + NumHints, BeyondBudgetStart,
- [&](MCPhysReg Reg) { return !isAntiHinted(Reg); });
+ CustomOrder.begin(), BeyondBudgetStart,
+ [&](MCPhysReg Reg) { return !isAntiHintedReg(Reg, AntiHintedRegUnits); });
LLVM_DEBUG({
size_t NonAntiHintedCount =
- std::distance(HintsAndCustomOrder.begin() + NumHints, PartitionPoint);
+ std::distance(CustomOrder.begin(), PartitionPoint);
size_t AntiHintedCount = std::distance(PartitionPoint, BeyondBudgetStart);
size_t BeyondBudgetCount =
- std::distance(BeyondBudgetStart, HintsAndCustomOrder.end());
+ std::distance(BeyondBudgetStart, CustomOrder.end());
dbgs() << "Added " << NonAntiHintedCount
<< " non-anti-hinted registers first\n"
<< "Added " << AntiHintedCount
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index 7765849ab804b..a704767e3b749 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -373,11 +373,9 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
unsigned NumAllocatedVGPRs,
unsigned &MaxVGPRsForCurrentOccupancy) const;
- void applyRegAllocationAntiHints(
- Register VirtReg, ArrayRef<MCPhysReg> Order,
- SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
- SmallVectorImpl<MCPhysReg> &AntiHints, const MachineFunction &MF,
- const VirtRegMap *VRM = nullptr,
+ void filterAndSortForAntiHintedRegs(
+ Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
const LiveRegMatrix *Matrix = nullptr) const override;
const int *getRegUnitPressureSets(MCRegUnit RegUnit) const override;
>From 99f6c74ba2d0ad33772bd95d98393670f46f5a42 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Sat, 5 Sep 2026 10:52:01 -0500
Subject: [PATCH 12/19] Addressed review
---
llvm/include/llvm/CodeGen/MIRYamlMapping.h | 3 ++-
llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index 142ace2cf765f..27c9cc8301cba 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -232,9 +232,10 @@ template <> struct MappingTraits<VirtualRegisterDefinition> {
// so a plain mapOptional with an empty default would still emit the keys
// and change every existing test's output.
// Skip the call on output when empty to keep them off entirely.
- if (!YamlIO.outputting() || !Reg.AntiHints.empty())
+ if (!YamlIO.outputting() || !Reg.AntiHints.empty()) {
YamlIO.mapOptional("anti-hints", Reg.AntiHints,
std::vector<FlowStringValue>());
+ }
if (!YamlIO.outputting() || !Reg.SplitFrom.Value.empty())
YamlIO.mapOptional("split-from", Reg.SplitFrom, StringValue());
if (!YamlIO.outputting() || !Reg.AssignedPhys.Value.empty())
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index febb010bb4d09..965e7286d8cef 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -774,7 +774,7 @@ bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS,
}
if (!VReg.AntiHints.empty() && Info.Kind != VRegInfo::NORMAL)
return error(VReg.AntiHints.front().SourceRange.Start,
- Twine("anti-hints can only be set for normal vregs"));
+ "anti-hints can only be set for normal vregs");
for (const auto &AntiHintValue : VReg.AntiHints) {
Register AntiHintReg;
>From 22cdb36c98424b4bde30e6ff70ab9907ea0f035a Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Sat, 12 Sep 2026 13:34:40 -0500
Subject: [PATCH 13/19] Addressed review
---
llvm/include/llvm/CodeGen/TargetRegisterInfo.h | 7 +++++--
llvm/lib/CodeGen/AllocationOrder.cpp | 3 ++-
llvm/lib/CodeGen/AllocationOrder.h | 5 +++++
llvm/lib/CodeGen/RegAllocGreedy.cpp | 5 ++++-
llvm/lib/CodeGen/TargetRegisterInfo.cpp | 6 +++---
5 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 9de9e644effda..182a8984bae4d 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -39,6 +39,7 @@ class DIExpression;
class LiveRegMatrix;
class MachineFunction;
class MachineInstr;
+class RegisterClassInfo;
class RegScavenger;
class VirtRegMap;
class LiveIntervals;
@@ -861,13 +862,15 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
Register VirtReg, ArrayRef<MCPhysReg> Order,
SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix = nullptr) const;
+ const LiveRegMatrix *Matrix = nullptr,
+ const RegisterClassInfo *RegClassInfo = nullptr) const;
/// Custom reordering of the allocation order.
virtual void filterAndSortForAntiHintedRegs(
Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix = nullptr) const;
+ const LiveRegMatrix *Matrix = nullptr,
+ const RegisterClassInfo *RegClassInfo = nullptr) const;
/// Allow the target to reverse allocation order of local live ranges. This
/// will generally allocate shorter local live ranges first. For targets with
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index ac4485c849a00..705fcef23030b 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -74,7 +74,8 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
if (AntiHintedRegUnits.any()) {
HintsAndCustomOrder.reserve(NumHints + Order.size());
TRI->applyRegAllocationAntiHints(VirtReg, Order, HintsAndCustomOrder,
- NumHints, AntiHintedRegUnits, MF, Matrix);
+ NumHints, AntiHintedRegUnits, MF, Matrix,
+ &RegClassInfo);
}
// Create allocation order object.
diff --git a/llvm/lib/CodeGen/AllocationOrder.h b/llvm/lib/CodeGen/AllocationOrder.h
index 09d8fd68de17b..7c61c01d9ea59 100644
--- a/llvm/lib/CodeGen/AllocationOrder.h
+++ b/llvm/lib/CodeGen/AllocationOrder.h
@@ -129,6 +129,11 @@ class LLVM_LIBRARY_VISIBILITY AllocationOrder {
/// Get the allocation order without reordered hints.
ArrayRef<MCPhysReg> getOrder() const { return Order; }
+ /// Return true if a custom order replaced the RegisterClassInfo order.
+ bool hasCustomOrder() const {
+ return static_cast<int>(HintsAndCustomOrder.size()) > NumHints;
+ }
+
/// Return true if Reg is a preferred physical register.
bool isHint(Register Reg) const {
assert(!Reg.isPhysical() ||
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index fc28b229dcddc..42de9fc7f6f75 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -683,7 +683,10 @@ RegAllocEvictionAdvisor::getOrderLimit(const LiveInterval &VirtReg,
// It is normal for register classes to have a long tail of registers with
// the same cost. We don't need to look at them if they're too expensive.
- if (RegCosts[Order.getOrder().back()] >= CostPerUseLimit) {
+ // LastCostChange is an index into the original RegisterClassInfo order, so
+ // it cannot be used to shorten a custom order.
+ if (!Order.hasCustomOrder() &&
+ RegCosts[Order.getOrder().back()] >= CostPerUseLimit) {
OrderLimit = RegClassInfo.getLastCostChange(RC);
LLVM_DEBUG(dbgs() << "Only trying the first " << OrderLimit
<< " regs.\n");
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index f6ec5c9ac46e0..7db9732213ed5 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -454,7 +454,7 @@ void TargetRegisterInfo::applyRegAllocationAntiHints(
Register VirtReg, ArrayRef<MCPhysReg> Order,
SmallVectorImpl<MCPhysReg> &HintsAndCustomOrder, unsigned NumHints,
const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix) const {
+ const LiveRegMatrix *Matrix, const RegisterClassInfo *RegClassInfo) const {
if (AntiHintedRegUnits.none())
return;
@@ -466,13 +466,13 @@ void TargetRegisterInfo::applyRegAllocationAntiHints(
filterAndSortForAntiHintedRegs(
VirtReg,
MutableArrayRef<MCPhysReg>(HintsAndCustomOrder).drop_front(NumHints),
- AntiHintedRegUnits, MF, Matrix);
+ AntiHintedRegUnits, MF, Matrix, RegClassInfo);
}
void TargetRegisterInfo::filterAndSortForAntiHintedRegs(
Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix) const {
+ const LiveRegMatrix *Matrix, const RegisterClassInfo *RegClassInfo) const {
// Partition non-anti-hinted register go first.
auto *PartitionPoint = std::stable_partition(
>From 6ecc29f704356eec9bcc954f0b401983aa802f70 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Sat, 12 Sep 2026 13:41:13 -0500
Subject: [PATCH 14/19] Addressed review
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 85 ++++++----
llvm/lib/Target/AMDGPU/SIRegisterInfo.h | 8 +-
.../AMDGPU/llvm.amdgcn.mfma.anti-hints.mir | 156 ++++++++++++++++++
3 files changed, 212 insertions(+), 37 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index a6124cf8fc89c..598e836280963 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -4201,8 +4201,8 @@ bool SIRegisterInfo::shouldApplyAntiHints(
// Do not apply anti-hints if we are reaching close to the VGPR budget. For
// target occupancy, the 80% cutoff is a conservative: anti-hints are disabled
// early enough that later registers still have headroom to stay at target
- // occupancy. For current occupancy, the 95% cutoff margin is used to apply
- // anti-hints close to the limit of the current occupancy budget.
+ // occupancy. For current occupancy, the 95% cutoff margin is used to not
+ // apply anti-hints close to the limit of the current occupancy budget.
unsigned MaxVGPRsCutOffForTargetOccupancy =
(ST.getMaxNumVGPRs(TargetOccupancy, DynamicVGPRBlockSize) * 80) / 100;
unsigned MaxVGPRsCutOffForCurrentOccupancy =
@@ -4225,22 +4225,56 @@ bool SIRegisterInfo::shouldApplyAntiHints(
return true;
}
+// Returns true if Reg fits within the current occupancy VGPR budget.
+bool SIRegisterInfo::isRegWithinOccupancyBudget(
+ MCPhysReg Reg, unsigned NumVGPRs, unsigned NumAGPRs,
+ unsigned MaxVGPRsForCurrentOccupancy) const {
+ const TargetRegisterClass *RC = getPhysRegBaseClass(Reg);
+
+ // No VGPR or AGPR usage.
+ if (!RC || (!isVGPRClass(RC) && !isAGPRClass(RC)))
+ return true;
+
+ unsigned RegEndIndex =
+ getHWRegIndex(Reg) + divideCeil(getRegSizeInBits(*RC), 32);
+
+ unsigned MaxVGPR = NumVGPRs;
+ unsigned MaxAGPR = NumAGPRs;
+
+ if (isAGPRClass(RC))
+ MaxAGPR = std::max(MaxAGPR, RegEndIndex);
+ else
+ MaxVGPR = std::max(MaxVGPR, RegEndIndex);
+
+ return static_cast<unsigned>(
+ AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(), MaxAGPR, MaxVGPR)) <=
+ MaxVGPRsForCurrentOccupancy;
+}
+
void SIRegisterInfo::filterAndSortForAntiHintedRegs(
Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix) const {
+ const LiveRegMatrix *Matrix, const RegisterClassInfo *RegClassInfo) const {
+
+ if (none_of(CustomOrder, [&](MCPhysReg Reg) {
+ return isAntiHintedReg(Reg, AntiHintedRegUnits);
+ }))
+ return;
- // Get total number of allocated VGPRs to determine the current occupancy.
- unsigned NumVGPRs = 0;
- unsigned NumAGPRs = 0;
+ const MachineRegisterInfo &MRI = MF.getRegInfo();
+ unsigned NumVGPRs = getNumUsedPhysRegs(MRI, AMDGPU::VGPR_32RegClass,
+ /*IncludeCalls=*/false);
+ unsigned NumAGPRs = getNumUsedPhysRegs(MRI, AMDGPU::AGPR_32RegClass,
+ /*IncludeCalls=*/false);
if (Matrix) {
- for (MCPhysReg Reg : AMDGPU::VGPR_32RegClass)
+ for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::VGPR_32RegClass))
if (Matrix->isPhysRegUsed(Reg))
NumVGPRs = std::max(NumVGPRs, getHWRegIndex(Reg) + 1);
- for (MCPhysReg Reg : AMDGPU::AGPR_32RegClass)
+ for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::AGPR_32RegClass))
if (Matrix->isPhysRegUsed(Reg))
NumAGPRs = std::max(NumAGPRs, getHWRegIndex(Reg) + 1);
}
+
unsigned NumAllocatedVGPRs =
AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(), NumAGPRs, NumVGPRs);
@@ -4249,35 +4283,14 @@ void SIRegisterInfo::filterAndSortForAntiHintedRegs(
if (!shouldApplyAntiHints(MF, NumAllocatedVGPRs, MaxVGPRsForCurrentOccupancy))
return;
- // Returns true if Reg fits within the current occupancy VGPR budget.
- auto IsWithinBudget = [&](MCPhysReg Reg) -> bool {
- const TargetRegisterClass *RC = getPhysRegBaseClass(Reg);
-
- // No VGPR or AGPR usage.
- if (!RC ||
- (!isVGPRClass(RC) && !isAGPRClass(RC) && !isVectorSuperClass(RC)))
- return true;
-
- unsigned RegEndIndex =
- getHWRegIndex(Reg) + divideCeil(getRegSizeInBits(*RC), 32);
-
- unsigned MaxVGPR = NumVGPRs;
- unsigned MaxAGPR = NumAGPRs;
- if (isAGPRClass(RC))
- MaxAGPR = std::max(MaxAGPR, RegEndIndex);
- else
- MaxVGPR = std::max(MaxVGPR, RegEndIndex);
-
- return static_cast<unsigned>(AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(),
- MaxAGPR, MaxVGPR)) <=
- MaxVGPRsForCurrentOccupancy;
- };
-
- // Find the cutoff point for the current occupancy VGPR budget.
- auto *BeyondBudgetStart = llvm::find_if(
- CustomOrder, [&](MCPhysReg Reg) { return !IsWithinBudget(Reg); });
+ // Reorder all in-budget first so the anti-hinted partition covers
+ // both VGPRs and AGPRs.
+ auto *BeyondBudgetStart = std::stable_partition(
+ CustomOrder.begin(), CustomOrder.end(), [&](MCPhysReg Reg) {
+ return isRegWithinOccupancyBudget(Reg, NumVGPRs, NumAGPRs,
+ MaxVGPRsForCurrentOccupancy);
+ });
- // Only shuffle within the current occupancy VGPR budget.
auto *PartitionPoint = std::stable_partition(
CustomOrder.begin(), BeyondBudgetStart,
[&](MCPhysReg Reg) { return !isAntiHintedReg(Reg, AntiHintedRegUnits); });
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
index a704767e3b749..331dc858c1518 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.h
@@ -63,6 +63,11 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
void reserveRegisterTuples(BitVector &, MCRegister Reg) const;
+ /// True if assigning Reg would fit in the current occupancy VGPR budget.
+ bool isRegWithinOccupancyBudget(MCPhysReg Reg, unsigned NumVGPRs,
+ unsigned NumAGPRs,
+ unsigned MaxVGPRsForCurrentOccupancy) const;
+
public:
SIRegisterInfo(const GCNSubtarget &ST);
@@ -376,7 +381,8 @@ class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
void filterAndSortForAntiHintedRegs(
Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix = nullptr) const override;
+ const LiveRegMatrix *Matrix = nullptr,
+ const RegisterClassInfo *RegClassInfo = nullptr) const override;
const int *getRegUnitPressureSets(MCRegUnit RegUnit) const override;
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
index 2eec9fe8c8eb2..8224ed73fcf1d 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
@@ -9,8 +9,11 @@
define amdgpu_kernel void @anti_hints_suppressed_by_current_budget() #0 { ret void }
define amdgpu_kernel void @anti_hints_unified_agpr_headroom () #1 { ret void }
define amdgpu_kernel void @anti_hints_unified_agpr_budget () #1 { ret void }
+ define amdgpu_kernel void @anti_hints_high_vgpr_counts_for_budget() #0 { ret void }
+ define amdgpu_kernel void @anti_hints_av_class_applied_to_agpr() #2 { ret void }
attributes #0 = { nounwind "amdgpu-agpr-alloc"="0" "frame-pointer"="none"}
attributes #1 = { nounwind "frame-pointer"="none"}
+ attributes #2 = { nounwind "frame-pointer"="none" "amdgpu-num-vgpr"="20" "amdgpu-agpr-alloc"="36"}
...
---
@@ -578,3 +581,156 @@ body: |
%8.sub12_sub13_sub14_sub15:vreg_512_align2 = DS_READ_B128_gfx9 %0.sub0, 6144, 0, implicit $exec :: (load (s128), addrspace 3)
S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %3, implicit %5, implicit %6, implicit %7, implicit %8
...
+
+---
+name: anti_hints_high_vgpr_counts_for_budget
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 8
+registers:
+ - { id: 0, class: vreg_128_align2 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: vgpr_32 }
+ - { id: 3, class: sgpr_128 }
+ - { id: 4, class: vgpr_32 }
+ - { id: 5, class: vgpr_32 }
+ - { id: 6, class: vreg_128_align2 }
+ - { id: 7, class: vreg_512_align2 }
+ - { id: 8, class: vreg_512_align2 }
+ - { id: 9, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 10, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 11, class: vreg_128_align2, anti-hints: [ '%7' ] }
+ - { id: 12, class: vgpr_32, anti-hints: [ '%7' ] }
+ - { id: 13, class: vreg_512_align2 }
+ - { id: 14, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 15, class: vreg_128_align2, anti-hints: [ '%8' ] }
+ - { id: 16, class: vgpr_32, anti-hints: [ '%8' ] }
+ - { id: 17, class: vreg_512_align2 }
+ - { id: 18, class: vreg_128_align2, anti-hints: [ '%8', '%13' ] }
+ - { id: 19, class: vreg_128_align2, anti-hints: [ '%13' ] }
+liveins:
+ - { reg: '$vgpr0_vgpr1_vgpr2_vgpr3' }
+ - { reg: '$vgpr4' }
+ - { reg: '$vgpr5' }
+ - { reg: '$vgpr52_vgpr53_vgpr54_vgpr55' }
+ - { reg: '$vgpr56_vgpr57_vgpr58_vgpr59' }
+ - { reg: '$vgpr60_vgpr61_vgpr62_vgpr63' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4, $vgpr5, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX942-LABEL: name: anti_hints_high_vgpr_counts_for_budget
+ ; GFX942: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX942-NEXT: {{ $}}
+ ; GFX942-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX942-NEXT: S_NOP 4
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX942-NEXT: S_NOP 5
+ ; GFX942-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX942-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX942-NEXT: S_NOP 6
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX942-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX942-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX942-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit $vgpr52_vgpr53_vgpr54_vgpr55, implicit $vgpr56_vgpr57_vgpr58_vgpr59, implicit $vgpr60_vgpr61_vgpr62_vgpr63
+ ;
+ ; GFX90A-LABEL: name: anti_hints_high_vgpr_counts_for_budget
+ ; GFX90A: liveins: $vgpr4, $vgpr5, $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr52_vgpr53_vgpr54_vgpr55, $vgpr56_vgpr57_vgpr58_vgpr59, $vgpr60_vgpr61_vgpr62_vgpr63
+ ; GFX90A-NEXT: {{ $}}
+ ; GFX90A-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = IMPLICIT_DEF
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 4096, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr43 = V_LSHLREV_B32_e32 2, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38_vgpr39_vgpr40_vgpr41 = BUFFER_LOAD_DWORDX4_OFFEN renamable $vgpr42, renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = IMPLICIT_DEF
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr38_vgpr39, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr38 = V_LSHLREV_B32_e32 2, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr39 = V_LSHLREV_B32_e32 4, $vgpr5, implicit $exec
+ ; GFX90A-NEXT: S_NOP 12
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr42 = V_ADD_U32_e32 $vgpr5, $vgpr43, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr2_vgpr3, killed $vgpr40_vgpr41, killed $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: renamable $vgpr40 = V_LSHLREV_B32_e32 2, $vgpr42, implicit $exec
+ ; GFX90A-NEXT: S_NOP 13
+ ; GFX90A-NEXT: renamable $vgpr6_vgpr7_vgpr8_vgpr9 = DS_READ_B128_gfx9 renamable $vgpr4, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr6_vgpr7_vgpr8_vgpr9, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr41 = V_ADD_U32_e32 8192, killed $vgpr42, implicit $exec
+ ; GFX90A-NEXT: early-clobber renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, killed $vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37, 0, 0, 0, implicit $mode, implicit $exec
+ ; GFX90A-NEXT: S_NOP 14
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = DS_READ_B128_gfx9 renamable $vgpr4, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; GFX90A-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr4, killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; GFX90A-NEXT: renamable $vgpr22_vgpr23_vgpr24_vgpr25 = BUFFER_LOAD_DWORDX4_OFFEN killed renamable $vgpr41, killed renamable $sgpr0_sgpr1_sgpr2_sgpr3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ ; GFX90A-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1_vgpr2_vgpr3, implicit killed renamable $vgpr4, implicit killed renamable $vgpr5, implicit killed renamable $vgpr43, implicit killed renamable $vgpr38, implicit killed renamable $vgpr39, implicit killed renamable $vgpr40, implicit killed renamable $vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21, implicit killed renamable $vgpr22_vgpr23_vgpr24_vgpr25, implicit $vgpr52_vgpr53_vgpr54_vgpr55, implicit $vgpr56_vgpr57_vgpr58_vgpr59, implicit $vgpr60_vgpr61_vgpr62_vgpr63
+ %0:vreg_128_align2 = COPY $vgpr0_vgpr1_vgpr2_vgpr3
+ %1:vgpr_32 = COPY $vgpr4
+ %2:vgpr_32 = COPY $vgpr5
+ %3:sgpr_128 = IMPLICIT_DEF
+ %4:vgpr_32 = V_ADD_U32_e32 4096, %2, implicit $exec
+ %5:vgpr_32 = V_LSHLREV_B32_e32 2, %2, implicit $exec
+ %6:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %4, %3, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ %7:vreg_512_align2 = IMPLICIT_DEF
+ %8:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %6.sub0_sub1, %7, 0, 0, 0, implicit $mode, implicit $exec
+ %9:vgpr_32 = V_LSHLREV_B32_e32 2, %4, implicit $exec
+ %10:vgpr_32 = V_LSHLREV_B32_e32 4, %2, implicit $exec
+ %11:vreg_128_align2 = DS_READ_B128_gfx9 %1, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %11, 4096, 0, implicit $exec :: (store (s128), addrspace 3)
+ %12:vgpr_32 = V_ADD_U32_e32 %2, %5, implicit $exec
+ %13:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub2_sub3, %6.sub2_sub3, %8, 0, 0, 0, implicit $mode, implicit $exec
+ %14:vgpr_32 = V_LSHLREV_B32_e32 2, %12, implicit $exec
+ %15:vreg_128_align2 = DS_READ_B128_gfx9 %1, 2048, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %15, 6144, 0, implicit $exec :: (store (s128), addrspace 3)
+ %16:vgpr_32 = V_ADD_U32_e32 8192, %12, implicit $exec
+ %17:vreg_512_align2 = contract V_MFMA_F32_32X32X8F16_vgprcd_e64 %0.sub0_sub1, %0.sub2_sub3, %13, 0, 0, 0, implicit $mode, implicit $exec
+ %18:vreg_128_align2 = DS_READ_B128_gfx9 %1, 4096, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %18, 8192, 0, implicit $exec :: (store (s128), addrspace 3)
+ %19:vreg_128_align2 = BUFFER_LOAD_DWORDX4_OFFEN %16, %3, 0, 2048, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 8)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %2, implicit %5, implicit %9, implicit %10, implicit %14, implicit %17, implicit %19, implicit $vgpr52_vgpr53_vgpr54_vgpr55, implicit $vgpr56_vgpr57_vgpr58_vgpr59, implicit $vgpr60_vgpr61_vgpr62_vgpr63
+...
+
+---
+name: anti_hints_av_class_applied_to_agpr
+tracksRegLiveness: true
+machineFunctionInfo:
+ isEntryFunction: true
+ occupancy: 6
+registers:
+ - { id: 0, class: vreg_64_align2 }
+ - { id: 1, class: vgpr_32 }
+ - { id: 2, class: areg_512_align2 }
+ - { id: 3, class: areg_512_align2 }
+ - { id: 4, class: av_128_align2, anti-hints: [ '%2' ] }
+liveins:
+ - { reg: '$vgpr0_vgpr1' }
+ - { reg: '$vgpr2' }
+body: |
+ bb.0:
+ liveins: $vgpr0_vgpr1, $vgpr2
+ ; AH-LABEL: name: anti_hints_av_class_applied_to_agpr
+ ; AH: liveins: $vgpr2, $vgpr0_vgpr1
+ ; AH-NEXT: {{ $}}
+ ; AH-NEXT: renamable $agpr16_agpr17_agpr18_agpr19_agpr20_agpr21_agpr22_agpr23_agpr24_agpr25_agpr26_agpr27_agpr28_agpr29_agpr30_agpr31 = IMPLICIT_DEF
+ ; AH-NEXT: early-clobber renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = contract V_MFMA_F32_32X32X8F16_e64 $vgpr0_vgpr1, $vgpr0_vgpr1, killed $agpr16_agpr17_agpr18_agpr19_agpr20_agpr21_agpr22_agpr23_agpr24_agpr25_agpr26_agpr27_agpr28_agpr29_agpr30_agpr31, 0, 0, 0, implicit $mode, implicit $exec
+ ; AH-NEXT: renamable $agpr32_agpr33_agpr34_agpr35 = DS_READ_B128_gfx9 renamable $vgpr2, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ ; AH-NEXT: DS_WRITE_B128_gfx9 renamable $vgpr2, killed renamable $agpr32_agpr33_agpr34_agpr35, 2048, 0, implicit $exec :: (store (s128), addrspace 3)
+ ; AH-NEXT: S_ENDPGM 0, implicit killed renamable $vgpr0_vgpr1, implicit killed renamable $vgpr2, implicit killed renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15
+ %0:vreg_64_align2 = COPY $vgpr0_vgpr1
+ %1:vgpr_32 = COPY $vgpr2
+ %2:areg_512_align2 = IMPLICIT_DEF
+ early-clobber %3:areg_512_align2 = contract V_MFMA_F32_32X32X8F16_e64 %0, %0, killed %2, 0, 0, 0, implicit $mode, implicit $exec
+ %4:av_128_align2 = DS_READ_B128_gfx9 %1, 0, 0, implicit $exec :: (load (s128), addrspace 3)
+ DS_WRITE_B128_gfx9 %1, %4, 2048, 0, implicit $exec :: (store (s128), addrspace 3)
+ S_ENDPGM 0, implicit %0, implicit %1, implicit %3
+...
>From 6dc04cf3a99d4adbf2745a40c4d9f30a59907a81 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Tue, 15 Sep 2026 19:30:16 -0500
Subject: [PATCH 15/19] addressed review
---
llvm/include/llvm/CodeGen/MachineRegisterInfo.h | 4 ++--
llvm/include/llvm/CodeGen/TargetRegisterInfo.h | 14 +++++++-------
llvm/lib/CodeGen/AllocationOrder.cpp | 4 +---
llvm/lib/CodeGen/TargetRegisterInfo.cpp | 5 +++--
4 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 69d14fd11507f..8a50624d4fb27 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -917,7 +917,7 @@ class MachineRegisterInfo {
/// Add a register allocation anti-hint for the specified virtual register.
/// This tells the allocator to avoid allocating VReg to the same physical
/// register as AntiHintVReg (or overlapping ones).
- void addRegAllocAntiHint(Register VReg, Register AntiHintVReg) {
+ void addRegAllocationAntiHint(Register VReg, Register AntiHintVReg) {
assert(VReg.isVirtual() && AntiHintVReg.isVirtual() &&
"Anti-hints and anti-hint targets are only for virtual registers");
AntiHintRegs.grow(VReg);
@@ -931,7 +931,7 @@ class MachineRegisterInfo {
void addRegAllocationAntiHints(Register VReg,
ArrayRef<Register> AntiHintVRegs) {
for (Register AntiHint : AntiHintVRegs)
- addRegAllocAntiHint(VReg, AntiHint);
+ addRegAllocationAntiHint(VReg, AntiHint);
}
/// Clear all anti-hints for a register.
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 182a8984bae4d..449013cab7970 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -703,6 +703,13 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
return RCInfos[getNumRegClasses() * HwMode + RC.getID()];
}
+ /// Custom reordering of the allocation order.
+ virtual void filterAndSortForAntiHintedRegs(
+ Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
+ const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
+ const LiveRegMatrix *Matrix = nullptr,
+ const RegisterClassInfo *RegClassInfo = nullptr) const;
+
public:
/// Returns the register class associated with the enumeration value.
/// See class MCOperandInfo.
@@ -865,13 +872,6 @@ class LLVM_ABI TargetRegisterInfo : public MCRegisterInfo {
const LiveRegMatrix *Matrix = nullptr,
const RegisterClassInfo *RegClassInfo = nullptr) const;
- /// Custom reordering of the allocation order.
- virtual void filterAndSortForAntiHintedRegs(
- Register VirtReg, MutableArrayRef<MCPhysReg> CustomOrder,
- const BitVector &AntiHintedRegUnits, const MachineFunction &MF,
- const LiveRegMatrix *Matrix = nullptr,
- const RegisterClassInfo *RegClassInfo = nullptr) const;
-
/// Allow the target to reverse allocation order of local live ranges. This
/// will generally allocate shorter local live ranges first. For targets with
/// many registers, this could reduce regalloc compile time by a large
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index 705fcef23030b..55be86dab2b22 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -71,12 +71,10 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
}
});
- if (AntiHintedRegUnits.any()) {
- HintsAndCustomOrder.reserve(NumHints + Order.size());
+ if (AntiHintedRegUnits.any())
TRI->applyRegAllocationAntiHints(VirtReg, Order, HintsAndCustomOrder,
NumHints, AntiHintedRegUnits, MF, Matrix,
&RegClassInfo);
- }
// Create allocation order object.
AllocationOrder AO(std::move(HintsAndCustomOrder), NumHints, Order,
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 7db9732213ed5..79b01d27d91a5 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -459,7 +459,8 @@ void TargetRegisterInfo::applyRegAllocationAntiHints(
if (AntiHintedRegUnits.none())
return;
- HintsAndCustomOrder.truncate(NumHints);
+ assert(HintsAndCustomOrder.size() == NumHints &&
+ "HintsAndCustomOrder should only contain the hints here.");
HintsAndCustomOrder.append(Order.begin(), Order.end());
// Custom reordering of the allocation order.
@@ -475,7 +476,7 @@ void TargetRegisterInfo::filterAndSortForAntiHintedRegs(
const LiveRegMatrix *Matrix, const RegisterClassInfo *RegClassInfo) const {
// Partition non-anti-hinted register go first.
- auto *PartitionPoint = std::stable_partition(
+ [[maybe_unused]] auto *PartitionPoint = std::stable_partition(
CustomOrder.begin(), CustomOrder.end(),
[&](MCPhysReg Reg) { return !isAntiHintedReg(Reg, AntiHintedRegUnits); });
>From e339233fb03da60fb0df93a2045b0c92ca5ecff6 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Tue, 15 Sep 2026 19:33:57 -0500
Subject: [PATCH 16/19] addressed review
---
llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
index 8224ed73fcf1d..55c856f7a33d6 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.anti-hints.mir
@@ -13,7 +13,7 @@
define amdgpu_kernel void @anti_hints_av_class_applied_to_agpr() #2 { ret void }
attributes #0 = { nounwind "amdgpu-agpr-alloc"="0" "frame-pointer"="none"}
attributes #1 = { nounwind "frame-pointer"="none"}
- attributes #2 = { nounwind "frame-pointer"="none" "amdgpu-num-vgpr"="20" "amdgpu-agpr-alloc"="36"}
+ attributes #2 = { nounwind "frame-pointer"="none" "amdgpu-waves-per-eu"="8,8" "amdgpu-agpr-alloc"="60"}
...
---
>From 099e49a72ce331b98d3ade91fb7d0bacd43db5b3 Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 16 Sep 2026 11:52:53 -0500
Subject: [PATCH 17/19] Addressed reviews
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 57 ++++++++++++-----------
1 file changed, 31 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 598e836280963..44e893f5ed7e0 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -4183,15 +4183,16 @@ bool SIRegisterInfo::shouldApplyAntiHints(
const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
unsigned DynamicVGPRBlockSize = MFI->getDynamicVGPRBlockSize();
- unsigned TargetOccupancy = MFI->getOccupancy();
+ unsigned RecordedMaxOccupancy = MFI->getOccupancy();
unsigned CurrentOccupancy =
ST.getOccupancyWithNumVGPRs(NumAllocatedVGPRs, DynamicVGPRBlockSize);
MaxVGPRsForCurrentOccupancy =
ST.getMaxNumVGPRs(CurrentOccupancy, DynamicVGPRBlockSize);
LLVM_DEBUG(dbgs() << "anti-hints: " << NumAllocatedVGPRs
- << " VGPRs allocated, target occupancy " << TargetOccupancy
- << ", current occupancy " << CurrentOccupancy << '\n');
+ << " VGPRs allocated, RecordedMaxOccupancy "
+ << RecordedMaxOccupancy << ", current occupancy "
+ << CurrentOccupancy << '\n');
// If we are already at lowest occupancy, then there is no need to protect
// against occupancy regression.
@@ -4199,19 +4200,21 @@ bool SIRegisterInfo::shouldApplyAntiHints(
return true;
// Do not apply anti-hints if we are reaching close to the VGPR budget. For
- // target occupancy, the 80% cutoff is a conservative: anti-hints are disabled
- // early enough that later registers still have headroom to stay at target
- // occupancy. For current occupancy, the 95% cutoff margin is used to not
- // apply anti-hints close to the limit of the current occupancy budget.
- unsigned MaxVGPRsCutOffForTargetOccupancy =
- (ST.getMaxNumVGPRs(TargetOccupancy, DynamicVGPRBlockSize) * 80) / 100;
+ // recorded max occupancy, the 80% cutoff is a conservative: anti-hints are
+ // disabled early enough that later registers still have headroom to stay at
+ // recorded max occupancy. For current occupancy, the 95% cutoff margin is
+ // used to not apply anti-hints close to the limit of the current occupancy
+ // budget.
+ unsigned MaxVGPRsCutOffForRecordedMaxOccupancy =
+ (ST.getMaxNumVGPRs(RecordedMaxOccupancy, DynamicVGPRBlockSize) * 80) /
+ 100;
unsigned MaxVGPRsCutOffForCurrentOccupancy =
(MaxVGPRsForCurrentOccupancy * 95) / 100;
- if (NumAllocatedVGPRs >= MaxVGPRsCutOffForTargetOccupancy) {
+ if (NumAllocatedVGPRs >= MaxVGPRsCutOffForRecordedMaxOccupancy) {
LLVM_DEBUG(dbgs() << "anti-hints: not applied, at or above the "
- << MaxVGPRsCutOffForTargetOccupancy
- << " VGPR cutoff for target occupancy\n");
+ << MaxVGPRsCutOffForRecordedMaxOccupancy
+ << " VGPR cutoff for RecordedMaxOccupancy\n");
return false;
}
@@ -4232,7 +4235,7 @@ bool SIRegisterInfo::isRegWithinOccupancyBudget(
const TargetRegisterClass *RC = getPhysRegBaseClass(Reg);
// No VGPR or AGPR usage.
- if (!RC || (!isVGPRClass(RC) && !isAGPRClass(RC)))
+ if (!RC || !hasVectorRegisters(RC))
return true;
unsigned RegEndIndex =
@@ -4262,18 +4265,20 @@ void SIRegisterInfo::filterAndSortForAntiHintedRegs(
return;
const MachineRegisterInfo &MRI = MF.getRegInfo();
- unsigned NumVGPRs = getNumUsedPhysRegs(MRI, AMDGPU::VGPR_32RegClass,
- /*IncludeCalls=*/false);
- unsigned NumAGPRs = getNumUsedPhysRegs(MRI, AMDGPU::AGPR_32RegClass,
- /*IncludeCalls=*/false);
- if (Matrix) {
- for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::VGPR_32RegClass))
- if (Matrix->isPhysRegUsed(Reg))
- NumVGPRs = std::max(NumVGPRs, getHWRegIndex(Reg) + 1);
- for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::AGPR_32RegClass))
- if (Matrix->isPhysRegUsed(Reg))
- NumAGPRs = std::max(NumAGPRs, getHWRegIndex(Reg) + 1);
- }
+ assert(hasVectorRegisters(MRI.getRegClass(VirtReg)) &&
+ "SGPR anti-hints are not handled");
+ unsigned NumVGPRs = 0;
+ unsigned NumAGPRs = 0;
+
+ assert(RegClassInfo && "RegClassInfo required to compute occupancy");
+ for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::VGPR_32RegClass))
+ if ((Matrix && Matrix->isPhysRegUsed(Reg)) ||
+ MRI.isPhysRegUsed(Reg, /*SkipRegMaskTest=*/true))
+ NumVGPRs = std::max(NumVGPRs, getHWRegIndex(Reg) + 1);
+ for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::AGPR_32RegClass))
+ if ((Matrix && Matrix->isPhysRegUsed(Reg)) ||
+ MRI.isPhysRegUsed(Reg, /*SkipRegMaskTest=*/true))
+ NumAGPRs = std::max(NumAGPRs, getHWRegIndex(Reg) + 1);
unsigned NumAllocatedVGPRs =
AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(), NumAGPRs, NumVGPRs);
@@ -4291,7 +4296,7 @@ void SIRegisterInfo::filterAndSortForAntiHintedRegs(
MaxVGPRsForCurrentOccupancy);
});
- auto *PartitionPoint = std::stable_partition(
+ [[maybe_unused]] auto *PartitionPoint = std::stable_partition(
CustomOrder.begin(), BeyondBudgetStart,
[&](MCPhysReg Reg) { return !isAntiHintedReg(Reg, AntiHintedRegUnits); });
>From c409adea52ad8ee5b121860df91c6e4c24b4648a Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Wed, 16 Sep 2026 22:15:27 -0500
Subject: [PATCH 18/19] Addressed reveiw
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index 44e893f5ed7e0..5cccfd0e3d9be 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -4189,10 +4189,9 @@ bool SIRegisterInfo::shouldApplyAntiHints(
MaxVGPRsForCurrentOccupancy =
ST.getMaxNumVGPRs(CurrentOccupancy, DynamicVGPRBlockSize);
- LLVM_DEBUG(dbgs() << "anti-hints: " << NumAllocatedVGPRs
- << " VGPRs allocated, RecordedMaxOccupancy "
- << RecordedMaxOccupancy << ", current occupancy "
- << CurrentOccupancy << '\n');
+ LLVM_DEBUG(dbgs() << "anti-hints: VGPRs allocated = " << NumAllocatedVGPRs
+ << ", RecordedMaxOccupancy = " << RecordedMaxOccupancy
+ << ", current occupancy = " << CurrentOccupancy << '\n');
// If we are already at lowest occupancy, then there is no need to protect
// against occupancy regression.
@@ -4270,15 +4269,19 @@ void SIRegisterInfo::filterAndSortForAntiHintedRegs(
unsigned NumVGPRs = 0;
unsigned NumAGPRs = 0;
+ assert(Matrix && "LiveRegMatrix required to compute occupancy");
assert(RegClassInfo && "RegClassInfo required to compute occupancy");
- for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::VGPR_32RegClass))
- if ((Matrix && Matrix->isPhysRegUsed(Reg)) ||
+ for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::VGPR_32RegClass)) {
+ if (Matrix->isPhysRegUsed(Reg) ||
MRI.isPhysRegUsed(Reg, /*SkipRegMaskTest=*/true))
NumVGPRs = std::max(NumVGPRs, getHWRegIndex(Reg) + 1);
- for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::AGPR_32RegClass))
- if ((Matrix && Matrix->isPhysRegUsed(Reg)) ||
+ }
+
+ for (MCPhysReg Reg : RegClassInfo->getOrder(&AMDGPU::AGPR_32RegClass)) {
+ if (Matrix->isPhysRegUsed(Reg) ||
MRI.isPhysRegUsed(Reg, /*SkipRegMaskTest=*/true))
NumAGPRs = std::max(NumAGPRs, getHWRegIndex(Reg) + 1);
+ }
unsigned NumAllocatedVGPRs =
AMDGPU::getTotalNumVGPRs(ST.hasGFX90AInsts(), NumAGPRs, NumVGPRs);
>From a6fda0ada4c8b7d8a23c70d810696a3bf2655a2b Mon Sep 17 00:00:00 2001
From: mssefat <syadus.sefat at gmail.com>
Date: Thu, 24 Sep 2026 17:13:28 -0500
Subject: [PATCH 19/19] [NFC] Moved getBitVecRegAntiHints from
MachineRegisterInfo to AllocationOrder
---
.../llvm/CodeGen/MachineRegisterInfo.h | 5 -----
llvm/lib/CodeGen/AllocationOrder.cpp | 20 ++++++++++++++++-
llvm/lib/CodeGen/MachineRegisterInfo.cpp | 22 -------------------
3 files changed, 19 insertions(+), 28 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 77f75a48b5876..a5cd22f2c5d9a 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -965,11 +965,6 @@ class MachineRegisterInfo {
return is_contained(AntiHints, AntiHintVReg);
}
- /// Get the BitVector of register units to avoid in anti-hints.
- /// VRM is the current virtual register map showing allocations made so far.
- void getBitVecRegAntiHints(Register VReg, BitVector &AntiHintedRegUnits,
- const VirtRegMap &VRM) const;
-
/// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the
/// specified register as undefined which causes the DBG_VALUE to be
/// deleted during LiveDebugVariables analysis.
diff --git a/llvm/lib/CodeGen/AllocationOrder.cpp b/llvm/lib/CodeGen/AllocationOrder.cpp
index 55be86dab2b22..6294b86b27c44 100644
--- a/llvm/lib/CodeGen/AllocationOrder.cpp
+++ b/llvm/lib/CodeGen/AllocationOrder.cpp
@@ -27,6 +27,24 @@ using namespace llvm;
#define DEBUG_TYPE "regalloc"
+static void getBitVecRegAntiHints(Register VReg, BitVector &AntiHintedRegUnits,
+ const VirtRegMap &VRM,
+ const MachineRegisterInfo &MRI,
+ const TargetRegisterInfo &TRI) {
+ assert(VReg.isVirtual() && "Anti-hints are only for virtual registers");
+ for (Register AntiHintVReg : MRI.getRegAllocationAntiHints(VReg)) {
+ // Check if the anti-hinted register has been allocated.
+ if (!VRM.hasPhys(AntiHintVReg))
+ continue;
+ // Delay until first allocated anti-hinted register so unused cases keep
+ // default empty BitVector.
+ if (AntiHintedRegUnits.empty())
+ AntiHintedRegUnits.resize(TRI.getNumRegUnits());
+ for (MCRegUnit Unit : TRI.regunits(VRM.getPhys(AntiHintVReg)))
+ AntiHintedRegUnits.set(static_cast<unsigned>(Unit));
+ }
+}
+
// Compare VirtRegMap::getRegAllocPref().
AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
@@ -57,7 +75,7 @@ AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM,
// Get anti-hints.
BitVector AntiHintedRegUnits;
- MRI.getBitVecRegAntiHints(VirtReg, AntiHintedRegUnits, VRM);
+ getBitVecRegAntiHints(VirtReg, AntiHintedRegUnits, VRM, MRI, *TRI);
LLVM_DEBUG({
if (AntiHintedRegUnits.any()) {
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index 61fae6d3fa281..035ccaac06a5a 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -22,7 +22,6 @@
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/DebugLoc.h"
@@ -717,24 +716,3 @@ void MachineRegisterInfo::updateDbgUsersToReg(
}
}
}
-
-void MachineRegisterInfo::getBitVecRegAntiHints(Register VReg,
- BitVector &AntiHintedRegUnits,
- const VirtRegMap &VRM) const {
- assert(VReg.isVirtual() && "Anti-hints are only for virtual registers");
- if (!AntiHintRegs.inBounds(VReg))
- return;
-
- auto *TRI = getTargetRegisterInfo();
- for (Register AntiHintVReg : AntiHintRegs[VReg]) {
- // Check if the anti-hinted register has been allocated.
- if (!VRM.hasPhys(AntiHintVReg))
- continue;
- // Delay until first allocated anti-hinted register so unused cases keep
- // default empty BitVector.
- if (AntiHintedRegUnits.empty())
- AntiHintedRegUnits.resize(TRI->getNumRegUnits());
- for (MCRegUnit Unit : TRI->regunits(VRM.getPhys(AntiHintVReg)))
- AntiHintedRegUnits.set(static_cast<unsigned>(Unit));
- }
-}
More information about the llvm-commits
mailing list