Skip to content

[CalcSpillWeights] Simplify copy hint register collection. NFC. #114236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 7, 2024

Conversation

vpykhtin
Copy link
Contributor

CopyHints set has been collecting duplicates of a register with increasing weight and then deduplicated with HintedRegs set. Let's stop collecting duplicates at the first place.

@llvmbot
Copy link
Member

llvmbot commented Oct 30, 2024

@llvm/pr-subscribers-llvm-regalloc

Author: Valery Pykhtin (vpykhtin)

Changes

CopyHints set has been collecting duplicates of a register with increasing weight and then deduplicated with HintedRegs set. Let's stop collecting duplicates at the first place.


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

1 Files Affected:

  • (modified) llvm/lib/CodeGen/CalcSpillWeights.cpp (+24-43)
diff --git a/llvm/lib/CodeGen/CalcSpillWeights.cpp b/llvm/lib/CodeGen/CalcSpillWeights.cpp
index f361c956092e88..4cc7fa149e2efd 100644
--- a/llvm/lib/CodeGen/CalcSpillWeights.cpp
+++ b/llvm/lib/CodeGen/CalcSpillWeights.cpp
@@ -207,24 +207,8 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
     NumInstr += 2;
   }
 
-  // CopyHint is a sortable hint derived from a COPY instruction.
-  struct CopyHint {
-    const Register Reg;
-    const float Weight;
-    CopyHint(Register R, float W) : Reg(R), Weight(W) {}
-    bool operator<(const CopyHint &Rhs) const {
-      // Always prefer any physreg hint.
-      if (Reg.isPhysical() != Rhs.Reg.isPhysical())
-        return Reg.isPhysical();
-      if (Weight != Rhs.Weight)
-        return (Weight > Rhs.Weight);
-      return Reg.id() < Rhs.Reg.id(); // Tie-breaker.
-    }
-  };
-
   bool IsExiting = false;
-  std::set<CopyHint> CopyHints;
-  SmallDenseMap<unsigned, float, 8> Hint;
+  SmallDenseMap<Register, float, 8> Hint;
   for (MachineRegisterInfo::reg_instr_nodbg_iterator
            I = MRI.reg_instr_nodbg_begin(LI.reg()),
            E = MRI.reg_instr_nodbg_end();
@@ -238,16 +222,8 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
       continue;
 
     NumInstr++;
-    bool identityCopy = false;
-    auto DestSrc = TII.isCopyInstr(*MI);
-    if (DestSrc) {
-      const MachineOperand *DestRegOp = DestSrc->Destination;
-      const MachineOperand *SrcRegOp = DestSrc->Source;
-      identityCopy = DestRegOp->getReg() == SrcRegOp->getReg() &&
-                     DestRegOp->getSubReg() == SrcRegOp->getSubReg();
-    }
 
-    if (identityCopy || MI->isImplicitDef())
+    if (MI->isIdentityCopy() || MI->isImplicitDef())
       continue;
     if (!Visited.insert(MI).second)
       continue;
@@ -260,8 +236,7 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
       return -1.0f;
     }
 
-    // Force Weight onto the stack so that x86 doesn't add hidden precision,
-    // similar to HWeight below.
+    // Force Weight onto the stack so that x86 doesn't add hidden precision.
     stack_float_t Weight = 1.0f;
     if (IsSpillable) {
       // Get loop info for mi.
@@ -287,29 +262,35 @@ float VirtRegAuxInfo::weightCalcHelper(LiveInterval &LI, SlotIndex *Start,
     if (!TII.isCopyInstr(*MI))
       continue;
     Register HintReg = copyHint(MI, LI.reg(), TRI, MRI);
-    if (!HintReg)
-      continue;
-    // Force HWeight onto the stack so that x86 doesn't add hidden precision,
-    // making the comparison incorrectly pass (i.e., 1 > 1 == true??).
-    stack_float_t HWeight = Hint[HintReg] += Weight;
-    if (HintReg.isVirtual() || MRI.isAllocatable(HintReg))
-      CopyHints.insert(CopyHint(HintReg, HWeight));
+    if (HintReg && (HintReg.isVirtual() || MRI.isAllocatable(HintReg)))
+      Hint[HintReg] += Weight;
   }
 
   // Pass all the sorted copy hints to mri.
-  if (ShouldUpdateLI && CopyHints.size()) {
+  if (ShouldUpdateLI && Hint.size()) {
     // Remove a generic hint if previously added by target.
     if (TargetHint.first == 0 && TargetHint.second)
       MRI.clearSimpleHint(LI.reg());
 
-    SmallSet<Register, 4> HintedRegs;
-    for (const auto &Hint : CopyHints) {
-      if (!HintedRegs.insert(Hint.Reg).second ||
-          (TargetHint.first != 0 && Hint.Reg == TargetHint.second))
-        // Don't add the same reg twice or the target-type hint again.
-        continue;
-      MRI.addRegAllocationHint(LI.reg(), Hint.Reg);
+    // Don't add the same reg twice or the target-type hint again.
+    Register SkipReg = TargetHint.first != 0 ? TargetHint.second : Register();
+    SmallVector<std::pair<float, Register>, 4> FRegHints, VRegHints;
+    for (const auto &[Reg, Weight] : Hint) {
+      if (Reg != SkipReg)
+        (Reg.isPhysical() ? &FRegHints : &VRegHints)
+            ->emplace_back(Weight, Reg);
     }
+    auto HeavyFirst = [](const auto &LHS, const auto &RHS) {
+      if (LHS.first != RHS.first)
+        return LHS.first > RHS.first;
+      return LHS.second.id() < RHS.second.id();
+    };
+    sort(FRegHints, HeavyFirst);
+    sort(VRegHints, HeavyFirst);
+    for (const auto &[Weight, Reg] : FRegHints) // Prefer physregs hints first.
+      MRI.addRegAllocationHint(LI.reg(), Reg);
+    for (const auto &[Weight, Reg] : VRegHints)
+      MRI.addRegAllocationHint(LI.reg(), Reg);
 
     // Weakly boost the spill weight of hinted registers.
     TotalWeight *= 1.01F;

Copy link

github-actions bot commented Oct 30, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@vpykhtin vpykhtin self-assigned this Oct 30, 2024
@vpykhtin vpykhtin force-pushed the refactor_calc_spill_weights branch from 9d575a5 to 06e5544 Compare October 31, 2024 07:41
MRI.addRegAllocationHint(LI.reg(), Hint.Reg);
// Don't add the target-type hint again.
Register SkipReg = TargetHint.first != 0 ? TargetHint.second : Register();
SmallVector<std::pair<float, Register>, 4> FRegHints, VRegHints;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having two different lists, could we change HeavyFirst to put the PhysReg first like it was in the CopyHint::operator<?

I feel that maintaining two lists is overkill.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I have no strong preference here, so I've returned the original CopyHint structure (except for const members) and made one sorted list.

@vpykhtin vpykhtin force-pushed the refactor_calc_spill_weights branch from 70b4a88 to d321b12 Compare November 1, 2024 09:40
Copy link
Collaborator

@qcolombet qcolombet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@vpykhtin vpykhtin force-pushed the refactor_calc_spill_weights branch from d321b12 to 157897f Compare November 6, 2024 11:20
@vpykhtin vpykhtin merged commit 9470945 into llvm:main Nov 7, 2024
8 checks passed
@vpykhtin vpykhtin deleted the refactor_calc_spill_weights branch November 7, 2024 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants