[llvm] RegAlloc: Fix failure on undef use when all registers are reserved (PR #119647)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 15 17:53:24 PST 2024


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/119647

>From f2375b7d16e00c80ad91f64e9e65680bcf5e55f1 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Thu, 12 Dec 2024 10:07:10 +0900
Subject: [PATCH 1/2] RegAlloc: Fix failure on undef use when all registers are
 reserved

Greedy and fast would hit different assertions on undef uses if all
registers in a class were reserved.
---
 llvm/lib/CodeGen/RegAllocFast.cpp                 | 15 +++++++++++----
 llvm/lib/CodeGen/RegAllocGreedy.cpp               |  2 +-
 ...an-out-of-registers-error-all-regs-reserved.ll | 10 +++++-----
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 8323a050bcbc4a..87c0636fc45188 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -982,16 +982,23 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) {
   if (!shouldAllocateRegister(VirtReg))
     return;
 
-  LiveRegMap::const_iterator LRI = findLiveVirtReg(VirtReg);
+  LiveRegMap::iterator LRI = findLiveVirtReg(VirtReg);
   MCPhysReg PhysReg;
   if (LRI != LiveVirtRegs.end() && LRI->PhysReg) {
     PhysReg = LRI->PhysReg;
   } else {
     const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
     ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
-    // FIXME: This can happen, and should fall back to a reserved entry in RC.
-    assert(!AllocationOrder.empty() && "Allocation order must not be empty");
-    PhysReg = AllocationOrder[0];
+    if (AllocationOrder.empty()) {
+      // All registers in the class were reserved.
+      //
+      // It might be OK to take any entry from the class as this is an undef
+      // use, but accepting this would give different behavior than greedy and
+      // basic.
+      PhysReg = getErrorAssignment(*LRI, *MO.getParent(), RC);
+      LRI->Error = true;
+    } else
+      PhysReg = AllocationOrder[0];
   }
 
   unsigned SubRegIdx = MO.getSubReg();
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index cb29218e966e06..af48e916feab45 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -2465,7 +2465,7 @@ MCRegister RAGreedy::selectOrSplitImpl(const LiveInterval &VirtReg,
     return 0;
   }
 
-  if (Stage < RS_Spill) {
+  if (Stage < RS_Spill && !VirtReg.empty()) {
     // Try splitting VirtReg or interferences.
     unsigned NewVRegSizeBefore = NewVRegs.size();
     Register PhysReg = trySplit(VirtReg, Order, NewVRegs, FixedRegisters);
diff --git a/llvm/test/CodeGen/AMDGPU/ran-out-of-registers-error-all-regs-reserved.ll b/llvm/test/CodeGen/AMDGPU/ran-out-of-registers-error-all-regs-reserved.ll
index 05975920ebeb8d..388a8e804a8896 100644
--- a/llvm/test/CodeGen/AMDGPU/ran-out-of-registers-error-all-regs-reserved.ll
+++ b/llvm/test/CodeGen/AMDGPU/ran-out-of-registers-error-all-regs-reserved.ll
@@ -24,10 +24,10 @@ define <32 x i32> @no_registers_from_class_available_to_allocate_asm_def() #0 {
   ret <32 x i32> %ret
 }
 
-; FIXME: Special case in fast RA, asserts. Also asserts in greedy
-; define void @no_registers_from_class_available_to_allocate_undef_asm() #0 {
-;   call void asm sideeffect "; use $0", "v"(<32 x i32> poison)
-;   ret void
-; }
+; CHECK: error: <unknown>:0:0: no registers from class available to allocate in function 'no_registers_from_class_available_to_allocate_undef_asm'
+define void @no_registers_from_class_available_to_allocate_undef_asm() #0 {
+  call void asm sideeffect "; use $0", "v"(<32 x i32> poison)
+  ret void
+}
 
 attributes #0 = { "amdgpu-waves-per-eu"="10,10" }

>From be078172c447170685296db2a4381e891221d73b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 13 Dec 2024 10:00:56 +0900
Subject: [PATCH 2/2] Use .front

---
 llvm/lib/CodeGen/RegAllocFast.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 87c0636fc45188..fd3914f864c00c 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -998,7 +998,7 @@ void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) {
       PhysReg = getErrorAssignment(*LRI, *MO.getParent(), RC);
       LRI->Error = true;
     } else
-      PhysReg = AllocationOrder[0];
+      PhysReg = AllocationOrder.front();
   }
 
   unsigned SubRegIdx = MO.getSubReg();



More information about the llvm-commits mailing list