[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