[llvm-branch-commits] [llvm] release/23.x: [RegisterCoalescer] Avoid retrying high-cost joins for live intervals (#207976) (PR #221331)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Sep 4 12:59:14 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-regalloc
Author: llvmbot
<details>
<summary>Changes</summary>
Backport fd9e690cdbeb02832cc36d455bffda9e7e813785
Requested by: @<!-- -->brad0
---
Full diff: https://github.com/llvm/llvm-project/pull/221331.diff
1 Files Affected:
- (modified) llvm/lib/CodeGen/RegisterCoalescer.cpp (+69-50)
``````````diff
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index fa1616e57bb19..8bb4ad76a0059 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -232,21 +232,26 @@ class RegisterCoalescer : private LiveRangeEdit::Delegate {
void setUndefOnPrunedSubRegUses(LiveInterval &LI, Register Reg,
LaneBitmask PrunedLanes);
+ /// Result of attempting to coalesce a copy.
+ /// - Joined: the copy was removed or otherwise fully handled.
+ /// - Deferred: retry after other coalescing may make progress.
+ /// - Rejected: do not retry, either because the copy is not a coalescing
+ /// candidate or because the join was intentionally rejected.
+ enum class JoinResult { Joined, Deferred, Rejected };
+
/// Attempt to join intervals corresponding to SrcReg/DstReg, which are the
- /// src/dst of the copy instruction CopyMI. This returns true if the copy
- /// was successfully coalesced away. If it is not currently possible to
- /// coalesce this interval, but it may be possible if other things get
- /// coalesced, then it returns true by reference in 'Again'.
- bool joinCopy(MachineInstr *CopyMI, bool &Again,
- SmallPtrSetImpl<MachineInstr *> &CurrentErasedInstrs);
+ /// src/dst of the copy instruction CopyMI.
+ JoinResult joinCopy(MachineInstr *CopyMI,
+ SmallPtrSetImpl<MachineInstr *> &CurrentErasedInstrs);
- /// Attempt to join these two intervals. On failure, this
- /// returns false. The output "SrcInt" will not have been modified, so we
- /// can use this information below to update aliases.
- bool joinIntervals(CoalescerPair &CP);
+ /// Attempt to join these two intervals. On failure, the output "SrcInt"
+ /// will not have been modified, so we can use this information below to
+ /// update aliases. Returns Deferred when it may be possible to join later,
+ /// or Rejected when retrying should be avoided.
+ JoinResult joinIntervals(CoalescerPair &CP);
- /// Attempt joining two virtual registers. Return true on success.
- bool joinVirtRegs(CoalescerPair &CP);
+ /// Attempt joining two virtual registers.
+ JoinResult joinVirtRegs(CoalescerPair &CP);
/// If a live interval has many valnos and is coalesced with other
/// live intervals many times, we regard such live interval as having
@@ -2044,23 +2049,22 @@ void RegisterCoalescer::setUndefOnPrunedSubRegUses(LiveInterval &LI,
LIS->shrinkToUses(&LI);
}
-bool RegisterCoalescer::joinCopy(
- MachineInstr *CopyMI, bool &Again,
+RegisterCoalescer::JoinResult RegisterCoalescer::joinCopy(
+ MachineInstr *CopyMI,
SmallPtrSetImpl<MachineInstr *> &CurrentErasedInstrs) {
- Again = false;
LLVM_DEBUG(dbgs() << LIS->getInstructionIndex(*CopyMI) << '\t' << *CopyMI);
CoalescerPair CP(*TRI);
if (!CP.setRegisters(CopyMI)) {
LLVM_DEBUG(dbgs() << "\tNot coalescable.\n");
- return false;
+ return JoinResult::Rejected;
}
if (CP.getNewRC()) {
if (RegClassInfo.getNumAllocatableRegs(CP.getNewRC()) == 0) {
LLVM_DEBUG(dbgs() << "\tNo " << TRI->getRegClassName(CP.getNewRC())
<< "are available for allocation\n");
- return false;
+ return JoinResult::Rejected;
}
auto SrcRC = MRI->getRegClass(CP.getSrcReg());
@@ -2074,7 +2078,7 @@ bool RegisterCoalescer::joinCopy(
if (!TRI->shouldCoalesce(CopyMI, SrcRC, SrcIdx, DstRC, DstIdx,
CP.getNewRC(), *LIS)) {
LLVM_DEBUG(dbgs() << "\tSubtarget bailed on coalescing.\n");
- return false;
+ return JoinResult::Rejected;
}
}
@@ -2085,7 +2089,7 @@ bool RegisterCoalescer::joinCopy(
LLVM_DEBUG(dbgs() << "\tCopy is dead.\n");
DeadDefs.push_back(CopyMI);
eliminateDeadDefs();
- return true;
+ return JoinResult::Joined;
}
// Eliminate undefs.
@@ -2093,9 +2097,9 @@ bool RegisterCoalescer::joinCopy(
// If this is an IMPLICIT_DEF, leave it alone, but don't try to coalesce.
if (MachineInstr *UndefMI = eliminateUndefCopy(CopyMI)) {
if (UndefMI->isImplicitDef())
- return false;
+ return JoinResult::Rejected;
deleteInstr(CopyMI);
- return false; // Not coalescable.
+ return JoinResult::Rejected; // Not coalescable.
}
}
@@ -2143,7 +2147,7 @@ bool RegisterCoalescer::joinCopy(
LLVM_DEBUG(dbgs() << "\tMerged values: " << LI << '\n');
}
deleteInstr(CopyMI);
- return true;
+ return JoinResult::Joined;
}
// Enforce policies.
@@ -2156,10 +2160,10 @@ bool RegisterCoalescer::joinCopy(
// the copy instead if it is cheap.
bool IsDefCopy = false;
if (reMaterializeDef(CP, CopyMI, IsDefCopy))
- return true;
+ return JoinResult::Joined;
if (IsDefCopy)
- Again = true; // May be possible to coalesce later.
- return false;
+ return JoinResult::Deferred; // May be possible to coalesce later.
+ return JoinResult::Rejected;
}
} else {
// When possible, let DstReg be the larger interval.
@@ -2184,17 +2188,18 @@ bool RegisterCoalescer::joinCopy(
ShrinkMask = LaneBitmask::getNone();
ShrinkMainRange = false;
- // Okay, attempt to join these two intervals. On failure, this returns false.
- // Otherwise, if one of the intervals being joined is a physreg, this method
- // always canonicalizes DstInt to be it. The output "SrcInt" will not have
- // been modified, so we can use this information below to update aliases.
- if (!joinIntervals(CP)) {
+ // Okay, attempt to join these two intervals. If one of the intervals being
+ // joined is a physreg and the join succeeds, this method always canonicalizes
+ // DstInt to be it. The output "SrcInt" will not have been modified, so we
+ // can use this information below to update aliases.
+ JoinResult Result = joinIntervals(CP);
+ if (Result != JoinResult::Joined) {
// Coalescing failed.
// Try rematerializing the definition of the source if it is cheap.
bool IsDefCopy = false;
if (reMaterializeDef(CP, CopyMI, IsDefCopy))
- return true;
+ return JoinResult::Joined;
// If we can eliminate the copy without merging the live segments, do so
// now.
@@ -2212,7 +2217,7 @@ bool RegisterCoalescer::joinCopy(
LLVM_DEBUG(dbgs() << "\t\tshrunk: " << DstLI << '\n');
}
LLVM_DEBUG(dbgs() << "\tTrivial!\n");
- return true;
+ return JoinResult::Joined;
}
}
@@ -2220,12 +2225,16 @@ bool RegisterCoalescer::joinCopy(
// its predecessor.
if (!CP.isPartial() && !CP.isPhys())
if (removePartialRedundancy(CP, *CopyMI))
- return true;
+ return JoinResult::Joined;
// Otherwise, we are unable to join the intervals.
LLVM_DEBUG(dbgs() << "\tInterference!\n");
- Again = true; // May be possible to coalesce later.
- return false;
+ // A high-cost interval is already too expensive to retry. Keeping the copy
+ // in WorkList would make every subsequent successful join rescan it again,
+ // which can dominate compile time.
+ if (Result == JoinResult::Deferred)
+ LLVM_DEBUG(dbgs() << "\tWill retry later.\n");
+ return Result;
}
// Coalescing to a virtual register that is of a sub-register class of the
@@ -2297,7 +2306,7 @@ bool RegisterCoalescer::joinCopy(
});
++numJoins;
- return true;
+ return JoinResult::Joined;
}
bool RegisterCoalescer::joinReservedPhysReg(CoalescerPair &CP) {
@@ -3694,7 +3703,8 @@ bool RegisterCoalescer::isHighCostLiveInterval(LiveInterval &LI) {
return true;
}
-bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
+RegisterCoalescer::JoinResult
+RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
SmallVector<VNInfo *, 16> NewVNInfo;
LiveInterval &RHS = LIS->getInterval(CP.getSrcReg());
LiveInterval &LHS = LIS->getInterval(CP.getDstReg());
@@ -3706,17 +3716,24 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
LLVM_DEBUG(dbgs() << "\t\tRHS = " << RHS << "\n\t\tLHS = " << LHS << '\n');
- if (isHighCostLiveInterval(LHS) || isHighCostLiveInterval(RHS))
- return false;
+ if (isHighCostLiveInterval(LHS) || isHighCostLiveInterval(RHS)) {
+ LLVM_DEBUG(dbgs() << "\t\tHigh-cost live interval: RHS valnos="
+ << RHS.valnos.size() << ", segments=" << RHS.size()
+ << "; LHS valnos=" << LHS.valnos.size()
+ << ", segments=" << LHS.size() << '\n');
+ return JoinResult::Rejected;
+ }
- // First compute NewVNInfo and the simple value mappings.
- // Detect impossible conflicts early.
+ // First compute NewVNInfo and the simple value mappings. Conflicts found
+ // here only reject this attempt; subsequent coalescing may still make the
+ // same copy joinable, so keep it deferred.
if (!LHSVals.mapValues(RHSVals) || !RHSVals.mapValues(LHSVals))
- return false;
+ return JoinResult::Deferred;
// Some conflicts can only be resolved after all values have been mapped.
+ // As above, unresolved conflicts are retryable interference.
if (!LHSVals.resolveConflicts(RHSVals) || !RHSVals.resolveConflicts(LHSVals))
- return false;
+ return JoinResult::Deferred;
// All clear, the live ranges can be merged.
if (RHS.hasSubRanges() || LHS.hasSubRanges()) {
@@ -3871,11 +3888,14 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
LIS->extendToIndices((LiveRange &)LHS, EndPoints);
}
- return true;
+ return JoinResult::Joined;
}
-bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) {
- return CP.isPhys() ? joinReservedPhysReg(CP) : joinVirtRegs(CP);
+RegisterCoalescer::JoinResult
+RegisterCoalescer::joinIntervals(CoalescerPair &CP) {
+ if (CP.isPhys())
+ return joinReservedPhysReg(CP) ? JoinResult::Joined : JoinResult::Deferred;
+ return joinVirtRegs(CP);
}
void RegisterCoalescer::buildVRegToDbgValueMap(MachineFunction &MF) {
@@ -4091,10 +4111,9 @@ bool RegisterCoalescer::copyCoalesceWorkList(
MI = nullptr;
continue;
}
- bool Again = false;
- bool Success = joinCopy(MI, Again, CurrentErasedInstrs);
- Progress |= Success;
- if (Success || !Again)
+ JoinResult Result = joinCopy(MI, CurrentErasedInstrs);
+ Progress |= Result == JoinResult::Joined;
+ if (Result != JoinResult::Deferred)
MI = nullptr;
}
// Clear instructions not recorded in `ErasedInstrs` but erased.
``````````
</details>
https://github.com/llvm/llvm-project/pull/221331
More information about the llvm-branch-commits
mailing list