[llvm] [CodeGen] Remove unsatisfiable hints in RegAllocGreedy. (PR #190983)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 17 11:39:00 PDT 2026
https://github.com/mgudim updated https://github.com/llvm/llvm-project/pull/190983
>From 4b60d4c301b9f9fa92c579b79a263a9c42308387 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at qti.qualcomm.com>
Date: Mon, 6 Apr 2026 09:15:12 -0700
Subject: [PATCH 1/2] [CodeGen] Remove unsatisfiable hints in RegAllocGreedy.
If a virtual register's live range `LR` is hinted to `PhysReg` but at the same
time `PhysReg` and `LR` interfere, the hint can never be satisfied, so
it should be removed.
---
llvm/lib/CodeGen/RegAllocGreedy.cpp | 27 +++++++++++++++++++++++++++
llvm/lib/CodeGen/RegAllocGreedy.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index 8565a7233d32c..0cb33105e8058 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -81,6 +81,8 @@ using namespace llvm;
STATISTIC(NumGlobalSplits, "Number of split global live ranges");
STATISTIC(NumLocalSplits, "Number of split local live ranges");
STATISTIC(NumEvicted, "Number of interferences evicted");
+STATISTIC(NumUnsatisfiableHintsRemoved,
+ "Number of unsatisfiable hints removed");
static cl::opt<SplitEditor::ComplementSpillMode> SplitSpillMode(
"split-spill-mode", cl::Hidden,
@@ -2454,6 +2456,30 @@ void RAGreedy::initializeCSRCost() {
}
}
+/// For each virtual register whose simple hint is a physical register,
+/// check whether that physreg's live range overlaps the vreg's live range.
+/// If it does the hint can never be satisfied; clear it so the vreg does not
+/// receive a spurious priority boost and does not trigger futile evictions.
+void RAGreedy::removeUnsatisfiableHints() {
+ for (unsigned Idx = 0, End = MRI->getNumVirtRegs(); Idx < End; ++Idx) {
+ Register VReg = Register::index2VirtReg(Idx);
+ if (MRI->reg_nodbg_empty(VReg))
+ continue;
+ Register HintReg = MRI->getSimpleHint(VReg);
+ if (!HintReg.isPhysical())
+ continue;
+ const LiveInterval &LI = LIS->getInterval(VReg);
+ for (MCRegUnit Unit : TRI->regunits(HintReg.asMCReg())) {
+ const LiveRange &PhysLR = LIS->getRegUnit(Unit);
+ if (!PhysLR.empty() && PhysLR.overlaps(LI)) {
+ MRI->clearSimpleHint(VReg);
+ ++NumUnsatisfiableHintsRemoved;
+ break;
+ }
+ }
+ }
+}
+
/// Collect the hint info for \p Reg.
/// The results are stored into \p Out.
/// \p Out is not cleared before being populated.
@@ -2971,6 +2997,7 @@ bool RAGreedy::run(MachineFunction &mf) {
*VRM, *VRAI, Matrix));
VRAI->calculateSpillWeightsAndHints();
+ removeUnsatisfiableHints();
LLVM_DEBUG(LIS->dump());
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.h b/llvm/lib/CodeGen/RegAllocGreedy.h
index 465be0d76809e..c16bca452c01a 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.h
+++ b/llvm/lib/CodeGen/RegAllocGreedy.h
@@ -362,6 +362,7 @@ class LLVM_LIBRARY_VISIBILITY RAGreedy : public RegAllocBase,
SmallVectorImpl<Register> &NewVRegs);
BlockFrequency calcSpillCost(const LiveInterval &LI);
void initializeCSRCost();
+ void removeUnsatisfiableHints();
MCRegister tryBlockSplit(const LiveInterval &, AllocationOrder &,
SmallVectorImpl<Register> &);
MCRegister tryInstructionSplit(const LiveInterval &, AllocationOrder &,
>From b968ee7b7ef3ae2014012d96df0a9a9e171038c8 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at qti.qualcomm.com>
Date: Fri, 17 Apr 2026 11:29:01 -0700
Subject: [PATCH 2/2] addressed review comments
---
llvm/include/llvm/CodeGen/CalcSpillWeights.h | 7 +++++++
llvm/include/llvm/CodeGen/MachineRegisterInfo.h | 8 ++++++++
llvm/lib/CodeGen/CalcSpillWeights.cpp | 16 ++++++++++++++++
llvm/lib/CodeGen/MachineRegisterInfo.cpp | 17 +++++++++++++++++
llvm/lib/CodeGen/RegAllocGreedy.cpp | 12 ++++--------
5 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/llvm/include/llvm/CodeGen/CalcSpillWeights.h
index dc2725e970dbe..88a69aaa6c8f5 100644
--- a/llvm/include/llvm/CodeGen/CalcSpillWeights.h
+++ b/llvm/include/llvm/CodeGen/CalcSpillWeights.h
@@ -77,6 +77,13 @@ class VirtRegMap;
const TargetRegisterInfo &TRI,
const MachineRegisterInfo &MRI);
+ /// Returns true if the hint \p PhysHint for virtual register \p VReg is
+ /// unsatisfiable because the physreg live range already overlaps the
+ /// vreg live range, meaning the hint can never be fulfilled.
+ static bool isUnsatisfiableHint(Register VReg, MCRegister PhysHint,
+ const LiveIntervals &LIS,
+ const TargetRegisterInfo &TRI);
+
/// Determine if all values in LI are rematerializable.
static bool isRematerializable(const LiveInterval &LI,
const LiveIntervals &LIS,
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 737b74ef3f761..62a0cda64ee7e 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -42,6 +42,7 @@
namespace llvm {
class PSetIterator;
+class VirtRegMap;
/// Convenient type to represent either a register class or a register bank.
using RegClassOrRegBank =
@@ -831,6 +832,13 @@ class MachineRegisterInfo {
RegAllocHints[VReg].second.clear();
}
+ /// removeRegAllocationHint - Remove a physical register from the hint
+ /// vector of a virtual register. Any virtual register hints that resolve
+ /// to \p PhysReg via \p VRM are also removed. If \p VRM is null, only
+ /// direct physical register matches are removed.
+ LLVM_ABI void removeRegAllocationHint(Register VReg, MCRegister PhysReg,
+ const VirtRegMap &VRM);
+
/// getRegAllocationHint - Return the register allocation hint for the
/// specified virtual register. If there are many hints, this returns the
/// one with the greatest weight.
diff --git a/llvm/lib/CodeGen/CalcSpillWeights.cpp b/llvm/lib/CodeGen/CalcSpillWeights.cpp
index 51cce4eb78c94..7abce0fb6faa7 100644
--- a/llvm/lib/CodeGen/CalcSpillWeights.cpp
+++ b/llvm/lib/CodeGen/CalcSpillWeights.cpp
@@ -35,10 +35,15 @@ void VirtRegAuxInfo::calculateSpillWeightsAndHints() {
<< "********** Function: " << MF.getName() << '\n');
MachineRegisterInfo &MRI = MF.getRegInfo();
+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
Register Reg = Register::index2VirtReg(I);
if (MRI.reg_nodbg_empty(Reg))
continue;
+ Register HintReg = MRI.getSimpleHint(Reg);
+ if (HintReg.isPhysical() &&
+ isUnsatisfiableHint(Reg, HintReg.asMCReg(), LIS, TRI))
+ MRI.removeRegAllocationHint(Reg, HintReg.asMCReg(), VRM);
calculateSpillWeightAndHint(LIS.getInterval(Reg));
}
}
@@ -77,6 +82,17 @@ Register VirtRegAuxInfo::copyHint(const MachineInstr *MI, Register Reg,
return Register();
}
+// Return true if PhysHint's live range already overlaps VReg's live range,
+// meaning the hint can never be satisfied.
+bool VirtRegAuxInfo::isUnsatisfiableHint(Register VReg, MCRegister PhysHint,
+ const LiveIntervals &LIS,
+ const TargetRegisterInfo &TRI) {
+ const LiveInterval &VRegLI = LIS.getInterval(VReg);
+ return llvm::any_of(TRI.regunits(PhysHint), [&](const MCRegUnit Unit) {
+ return LIS.getRegUnit(Unit).overlaps(VRegLI);
+ });
+}
+
// Check if all values in LI are rematerializable
bool VirtRegAuxInfo::isRematerializable(const LiveInterval &LI,
const LiveIntervals &LIS,
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index 094315b3903ea..95b52845557c1 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -20,6 +20,7 @@
#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"
@@ -674,3 +675,19 @@ bool MachineRegisterInfo::isReservedRegUnit(MCRegUnit Unit) const {
}
return false;
}
+
+void MachineRegisterInfo::removeRegAllocationHint(Register VReg,
+ MCRegister PhysReg,
+ const VirtRegMap &VRM) {
+ assert(VReg.isVirtual());
+ if (!RegAllocHints.inBounds(VReg))
+ return;
+ auto Hints = RegAllocHints[VReg].second;
+ llvm::erase_if(Hints, [&](Register H) {
+ if (H.isPhysical())
+ return H == PhysReg;
+ if (VRM.hasPhys(H))
+ return VRM.getPhys(H) == PhysReg;
+ return false;
+ });
+}
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index 0cb33105e8058..cdc2a17f45dcc 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -2468,14 +2468,10 @@ void RAGreedy::removeUnsatisfiableHints() {
Register HintReg = MRI->getSimpleHint(VReg);
if (!HintReg.isPhysical())
continue;
- const LiveInterval &LI = LIS->getInterval(VReg);
- for (MCRegUnit Unit : TRI->regunits(HintReg.asMCReg())) {
- const LiveRange &PhysLR = LIS->getRegUnit(Unit);
- if (!PhysLR.empty() && PhysLR.overlaps(LI)) {
- MRI->clearSimpleHint(VReg);
- ++NumUnsatisfiableHintsRemoved;
- break;
- }
+ MCRegister PhysRegHint = HintReg.asMCReg();
+ if (VirtRegAuxInfo::isUnsatisfiableHint(VReg, PhysRegHint, *LIS, *TRI)) {
+ MRI->removeRegAllocationHint(VReg, PhysRegHint, *VRM);
+ ++NumUnsatisfiableHintsRemoved;
}
}
}
More information about the llvm-commits
mailing list