[llvm] [RegisterCoalescer] Fix compile-time blowup with partially-reserved physregs (PR #181728)

via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 16 11:25:43 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-hexagon

Author: Brian Cain (androm3da)

<details>
<summary>Changes</summary>

canJoinPhys checks isReserved on the super-register but joinReservedPhysReg additionally requires every register-unit root to be reserved.  When a target reserves only part of a super-register (e.g. Hexagon -ffixed-r19 reserves R19 and D9, but not R18), the mismatch causes joinReservedPhysReg to fail, reMaterializeDef to fail, and the copy to be unconditionally retried (Again = true) every worklist round.  In large functions this O(N^2) retry behaviour leads to multi-hour compile times.

Add the same regunit-root-reserved check to canJoinPhys so that it returns false early, routing through the !canJoinPhys path where Again is only set when IsDefCopy is true.

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


2 Files Affected:

- (modified) llvm/lib/CodeGen/RegisterCoalescer.cpp (+14) 
- (added) llvm/test/CodeGen/Hexagon/coalescer-partial-reserved-physreg.mir (+20) 


``````````diff
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 586c27b7e3baf..6db602ee5fb2a 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -1982,6 +1982,20 @@ bool RegisterCoalescer::canJoinPhys(const CoalescerPair &CP) {
     return false;
   }
 
+  // Verify all register unit roots are reserved. joinReservedPhysReg requires
+  // this, so reject early to route the copy through the !canJoinPhys path
+  // where Again is only set when IsDefCopy is true.
+  if (!MRI->isConstantPhysReg(CP.getDstReg())) {
+    for (MCRegUnit Unit : TRI->regunits(CP.getDstReg())) {
+      for (MCRegUnitRootIterator RI(Unit, TRI); RI.isValid(); ++RI) {
+        if (!MRI->isReserved(*RI)) {
+          LLVM_DEBUG(dbgs() << "\tNot all register unit roots reserved.\n");
+          return false;
+        }
+      }
+    }
+  }
+
   LiveInterval &JoinVInt = LIS->getInterval(CP.getSrcReg());
   if (JoinVInt.containsOneValue())
     return true;
diff --git a/llvm/test/CodeGen/Hexagon/coalescer-partial-reserved-physreg.mir b/llvm/test/CodeGen/Hexagon/coalescer-partial-reserved-physreg.mir
new file mode 100644
index 0000000000000..1b3c2f306edec
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/coalescer-partial-reserved-physreg.mir
@@ -0,0 +1,20 @@
+# RUN: llc -mtriple=hexagon -mattr=+reserved-r19 \
+# RUN:   -run-pass=register-coalescer -o - %s | FileCheck %s
+#
+# Regression test for a compile-time blowup in the register coalescer with
+# partially-reserved physical registers.
+#
+# CHECK-LABEL: name: test
+# CHECK: bb.0:
+---
+name: test
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $r31
+
+    %0:doubleregs = A2_tfrpi 1
+    $r18 = COPY %0.isub_lo:doubleregs
+    J2_jumpr $r31, implicit-def dead $pc, implicit $r18
+
+...

``````````

</details>


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


More information about the llvm-commits mailing list