[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