[llvm] [CodeGen] Remove unsatisfiable hints in RegAllocGreedy. (PR #190983)

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 11:39:34 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-regalloc

Author: Mikhail Gudim (mgudim)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/190983.diff


6 Files Affected:

- (modified) llvm/include/llvm/CodeGen/CalcSpillWeights.h (+7) 
- (modified) llvm/include/llvm/CodeGen/MachineRegisterInfo.h (+8) 
- (modified) llvm/lib/CodeGen/CalcSpillWeights.cpp (+16) 
- (modified) llvm/lib/CodeGen/MachineRegisterInfo.cpp (+17) 
- (modified) llvm/lib/CodeGen/RegAllocGreedy.cpp (+23) 
- (modified) llvm/lib/CodeGen/RegAllocGreedy.h (+1) 


``````````diff
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 8565a7233d32c..cdc2a17f45dcc 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,26 @@ 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;
+    MCRegister PhysRegHint = HintReg.asMCReg();
+    if (VirtRegAuxInfo::isUnsatisfiableHint(VReg, PhysRegHint, *LIS, *TRI)) {
+      MRI->removeRegAllocationHint(VReg, PhysRegHint, *VRM);
+      ++NumUnsatisfiableHintsRemoved;
+    }
+  }
+}
+
 /// Collect the hint info for \p Reg.
 /// The results are stored into \p Out.
 /// \p Out is not cleared before being populated.
@@ -2971,6 +2993,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 &,

``````````

</details>


https://github.com/llvm/llvm-project/pull/190983


More information about the llvm-commits mailing list