[llvm] [RegAlloc] Add register allocation anti-hints infrastructure (PR #218071)
Syadus Sefat via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 12:17:48 PDT 2026
https://github.com/mssefat updated https://github.com/llvm/llvm-project/pull/218071
>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 1/5] [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 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 2/5] 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 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 3/5] 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 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 4/5] 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 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 5/5] 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(
More information about the llvm-commits
mailing list