[llvm] cf8ce56 - RegAllocFast: Mark unspilled implicit_def physreg defs dead (#226295)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 01:21:07 PDT 2026


Author: Matt Arsenault
Date: 2026-09-25T10:21:00+02:00
New Revision: cf8ce56a1f39f9a771d03aeedd9d89475e72a659

URL: https://github.com/llvm/llvm-project/commit/cf8ce56a1f39f9a771d03aeedd9d89475e72a659
DIFF: https://github.com/llvm/llvm-project/commit/cf8ce56a1f39f9a771d03aeedd9d89475e72a659.diff

LOG: RegAllocFast: Mark unspilled implicit_def physreg defs dead (#226295)

When a virtual register defined by an IMPLICIT_DEF is live out of the
block, or reloaded below, defineVirtReg deliberately skips the spill.
If there is also no use of the value in the block, the resulting physreg
def has no reader at all, but was left without a dead flag.

This avoids some unnecessary churn between regalloc runs on AMDGPU.
Since RA runs multiple times, missed dead flags in the first RA run get
re-inferred by the later runs which this avoids.

Co-authored-by: Claude Opus 5 <noreply at anthropic.com>

Added: 
    llvm/test/CodeGen/X86/regallocfast-implicit-def-live-out.mir

Modified: 
    llvm/lib/CodeGen/RegAllocFast.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp
index 524ed5e069941..078b3f3056a7e 100644
--- a/llvm/lib/CodeGen/RegAllocFast.cpp
+++ b/llvm/lib/CodeGen/RegAllocFast.cpp
@@ -1180,6 +1180,9 @@ bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum,
       }
 
       LRI->LastUse = nullptr;
+    } else if (!LRI->LastUse) {
+      // No spill was inserted, so nothing below reads this def.
+      MO.setIsDead(true);
     }
     // A def above spills only if a displacement above reloads again.
     LRI->LiveOut = false;

diff  --git a/llvm/test/CodeGen/X86/regallocfast-implicit-def-live-out.mir b/llvm/test/CodeGen/X86/regallocfast-implicit-def-live-out.mir
new file mode 100644
index 0000000000000..9e6e03e15c04a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/regallocfast-implicit-def-live-out.mir
@@ -0,0 +1,53 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s
+
+# An implicit_def is never spilled, so a live out value with no use in
+# the defining block has no reader at all.
+
+---
+name:            implicit_def_live_out_no_use
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: implicit_def_live_out_no_use
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   dead renamable $eax = IMPLICIT_DEF
+  ; CHECK-NEXT:   JMP_1 %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $eax = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load (s32) from %stack.0)
+  ; CHECK-NEXT:   RET64 implicit killed $eax
+  bb.0:
+    %0:gr32 = IMPLICIT_DEF
+    JMP_1 %bb.1
+
+  bb.1:
+    $eax = COPY %0
+    RET64 implicit $eax
+...
+
+---
+name:            implicit_def_live_out_with_use
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: implicit_def_live_out_with_use
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   renamable $eax = IMPLICIT_DEF
+  ; CHECK-NEXT:   MOV32mr $rsp, 1, $noreg, 0, $noreg, renamable $eax
+  ; CHECK-NEXT:   JMP_1 %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   $ecx = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load (s32) from %stack.0)
+  ; CHECK-NEXT:   RET64 implicit killed $ecx
+  bb.0:
+    %0:gr32 = IMPLICIT_DEF
+    MOV32mr $rsp, 1, $noreg, 0, $noreg, %0
+    JMP_1 %bb.1
+
+  bb.1:
+    $ecx = COPY %0
+    RET64 implicit $ecx
+...


        


More information about the llvm-commits mailing list