[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