[llvm] [AMDGPU] Do not erase KILLs that redefine a register in SIPostRABundler (PR #218349)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 01:31:19 PDT 2026


https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/218349

None

>From 77c32c204e4081a6b80cd558956deae9a6e42fbe Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 24 Aug 2026 10:30:01 +0200
Subject: [PATCH] [AMDGPU] Do not erase KILLs that redefine a register in
 SIPostRABundler

---
 llvm/lib/Target/AMDGPU/SIPostRABundler.cpp    | 14 +++--
 .../CodeGen/AMDGPU/postra-bundle-memops.mir   | 52 +++++++++++++++++++
 .../splitkit-getsubrangeformask-phi-extend.ll | 23 ++++++++
 3 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIPostRABundler.cpp b/llvm/lib/Target/AMDGPU/SIPostRABundler.cpp
index 66dc17aa46e96..16d02b5fc7421 100644
--- a/llvm/lib/Target/AMDGPU/SIPostRABundler.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPostRABundler.cpp
@@ -222,6 +222,12 @@ bool SIPostRABundler::run(MachineFunction &MF) {
 
           while (Next != E && Next->isKill()) {
             MachineInstr &Kill = *Next;
+
+            // KILL from an undef-source COPY keeps its def; must not erase it.
+            if (!Kill.all_defs().empty())
+              break;
+
+            KillUsedRegUnits.reset();
             collectUsedRegUnits(Kill, KillUsedRegUnits);
 
             KillUsedRegUnits &= BundleUsedRegUnits;
@@ -230,13 +236,11 @@ bool SIPostRABundler::run(MachineFunction &MF) {
             //
             // TODO: Should we just remove all kills? Is there any real reason to
             // keep them after RA?
-            if (KillUsedRegUnits.none()) {
-              ++Next;
-              Kill.eraseFromParent();
-            } else
+            if (!KillUsedRegUnits.none())
               break;
 
-            KillUsedRegUnits.reset();
+            ++Next;
+            Kill.eraseFromParent();
           }
 
           BundleUsedRegUnits.reset();
diff --git a/llvm/test/CodeGen/AMDGPU/postra-bundle-memops.mir b/llvm/test/CodeGen/AMDGPU/postra-bundle-memops.mir
index 03f6d2607c842..c71bec6f7b2d2 100644
--- a/llvm/test/CodeGen/AMDGPU/postra-bundle-memops.mir
+++ b/llvm/test/CodeGen/AMDGPU/postra-bundle-memops.mir
@@ -352,6 +352,58 @@ body:             |
     KILL killed $vgpr3_vgpr4, killed $vgpr5_vgpr6
 ...
 
+# The trailing KILL defines $vgpr0 (lowerCopy'd from an undef COPY) and must not be erased.
+---
+name: post_bundle_kill_with_def
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr1, $vgpr2, $vgpr3_vgpr4, $vgpr5_vgpr6
+    ; GCN-LABEL: name: post_bundle_kill_with_def
+    ; GCN: liveins: $vgpr1, $vgpr2, $vgpr3_vgpr4, $vgpr5_vgpr6
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: BUNDLE implicit $vgpr3_vgpr4, implicit killed $vgpr1, implicit $exec, implicit $vgpr5_vgpr6, implicit killed $vgpr2 {
+    ; GCN-NEXT:   GLOBAL_STORE_DWORD $vgpr3_vgpr4, killed $vgpr1, 0, 0, implicit $exec
+    ; GCN-NEXT:   GLOBAL_STORE_DWORD $vgpr5_vgpr6, killed $vgpr2, 0, 0, implicit $exec
+    ; GCN-NEXT: }
+    ; GCN-NEXT: $vgpr0 = KILL undef $sgpr4, implicit $exec
+    ; GCN-NEXT: S_NOP 0, implicit killed $vgpr0
+    GLOBAL_STORE_DWORD $vgpr3_vgpr4, killed $vgpr1, 0, 0, implicit $exec
+    GLOBAL_STORE_DWORD $vgpr5_vgpr6, killed $vgpr2, 0, 0, implicit $exec
+    $vgpr0 = KILL undef $sgpr4, implicit $exec
+    S_NOP 0, implicit killed $vgpr0
+...
+
+# A non-erasable KILL must not leak state that blocks erasing the next bundle's KILL.
+---
+name: post_bundle_kill_after_nonerasable_kill
+body:             |
+  bb.0:
+    liveins: $vgpr1, $vgpr2, $vgpr3_vgpr4, $vgpr5_vgpr6, $vgpr7, $vgpr8, $vgpr9
+    ; GCN-LABEL: name: post_bundle_kill_after_nonerasable_kill
+    ; GCN: liveins: $vgpr1, $vgpr2, $vgpr3_vgpr4, $vgpr5_vgpr6, $vgpr7, $vgpr8, $vgpr9
+    ; GCN-NEXT: {{  $}}
+    ; GCN-NEXT: BUNDLE implicit $vgpr3_vgpr4, implicit killed $vgpr1, implicit $exec, implicit $vgpr5_vgpr6, implicit killed $vgpr2 {
+    ; GCN-NEXT:   GLOBAL_STORE_DWORD $vgpr3_vgpr4, killed $vgpr1, 0, 0, implicit $exec
+    ; GCN-NEXT:   GLOBAL_STORE_DWORD $vgpr5_vgpr6, killed $vgpr2, 0, 0, implicit $exec
+    ; GCN-NEXT: }
+    ; GCN-NEXT: KILL killed $vgpr7
+    ; GCN-NEXT: S_NOP 0
+    ; GCN-NEXT: BUNDLE implicit $vgpr3_vgpr4, implicit killed $vgpr8, implicit $exec, implicit $vgpr5_vgpr6, implicit killed $vgpr9 {
+    ; GCN-NEXT:   GLOBAL_STORE_DWORD $vgpr3_vgpr4, killed $vgpr8, 0, 0, implicit $exec
+    ; GCN-NEXT:   GLOBAL_STORE_DWORD $vgpr5_vgpr6, killed $vgpr9, 0, 0, implicit $exec
+    ; GCN-NEXT: }
+    ; GCN-NEXT: S_NOP 1
+    GLOBAL_STORE_DWORD $vgpr3_vgpr4, killed $vgpr1, 0, 0, implicit $exec
+    GLOBAL_STORE_DWORD $vgpr5_vgpr6, killed $vgpr2, 0, 0, implicit $exec
+    KILL killed $vgpr7
+    S_NOP 0
+    GLOBAL_STORE_DWORD $vgpr3_vgpr4, killed $vgpr8, 0, 0, implicit $exec
+    GLOBAL_STORE_DWORD $vgpr5_vgpr6, killed $vgpr9, 0, 0, implicit $exec
+    KILL killed $vgpr8
+    S_NOP 1
+...
+
 # Avoid bundling if a MBB has SCHED_BARRIER
 ---
 name: no_sched_barrier_within_bundle
diff --git a/llvm/test/CodeGen/AMDGPU/splitkit-getsubrangeformask-phi-extend.ll b/llvm/test/CodeGen/AMDGPU/splitkit-getsubrangeformask-phi-extend.ll
index c40e35bbe1754..35882965e2be0 100644
--- a/llvm/test/CodeGen/AMDGPU/splitkit-getsubrangeformask-phi-extend.ll
+++ b/llvm/test/CodeGen/AMDGPU/splitkit-getsubrangeformask-phi-extend.ll
@@ -271,6 +271,7 @@ define void @f(ptr %p, <16 x i1> %m, <16 x i63> %pt, <16 x i1> %sc,
 ; CHECK-NEXT:    buffer_load_dword v32, off, s[0:3], s32 offset:148
 ; CHECK-NEXT:    buffer_load_dword v31, off, s[0:3], s32 offset:144
 ; CHECK-NEXT:    buffer_load_dword v30, off, s[0:3], s32 offset:140
+; CHECK-NEXT:    ; kill: def $vgpr3 killed $sgpr4 killed $exec
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[42:43], 1, v18
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[28:29], 1, v20
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[26:27], 1, v17
@@ -278,6 +279,17 @@ define void @f(ptr %p, <16 x i1> %m, <16 x i63> %pt, <16 x i1> %sc,
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[18:19], 1, v21
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[24:25], 1, v23
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[20:21], 1, v25
+; CHECK-NEXT:    ; kill: def $vgpr5 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr7 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr9 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr11 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr13 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr15 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr17 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr19 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr21 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr23 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr25 killed $sgpr4 killed $exec
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[16:17], 1, v27
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[12:13], 1, v26
 ; CHECK-NEXT:    v_cmp_eq_u32_e64 s[8:9], 1, v29
@@ -384,6 +396,16 @@ define void @f(ptr %p, <16 x i1> %m, <16 x i63> %pt, <16 x i1> %sc,
 ; CHECK-NEXT:    buffer_store_dword v61, off, s[0:3], s32 offset:1396 ; 4-byte Folded Spill
 ; CHECK-NEXT:    v_and_b32_e32 v1, 1, v1
 ; CHECK-NEXT:    v_cmp_ne_u32_e64 s[46:47], 1, v1
+; CHECK-NEXT:    ; kill: def $vgpr1 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr57 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr49 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr43 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr51 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $agpr33 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $agpr35 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $vgpr59 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $agpr39 killed $sgpr4 killed $exec
+; CHECK-NEXT:    ; kill: def $agpr37 killed $sgpr4 killed $exec
 ; CHECK-NEXT:    s_waitcnt vmcnt(32)
 ; CHECK-NEXT:    buffer_store_dword a0, off, s[0:3], s32 offset:1000 ; 4-byte Folded Spill
 ; CHECK-NEXT:    s_nop 0
@@ -481,6 +503,7 @@ define void @f(ptr %p, <16 x i1> %m, <16 x i63> %pt, <16 x i1> %sc,
 ; CHECK-NEXT:    buffer_load_dword v18, off, s[0:3], s32 offset:528
 ; CHECK-NEXT:    s_nop 0
 ; CHECK-NEXT:    buffer_load_dword v2, off, s[0:3], s32 offset:524
+; CHECK-NEXT:    ; kill: def $vgpr3 killed $sgpr4 killed $exec
 ; CHECK-NEXT:    s_nop 0
 ; CHECK-NEXT:    buffer_store_dword v0, off, s[0:3], s32 offset:1504 ; 4-byte Folded Spill
 ; CHECK-NEXT:    s_nop 0



More information about the llvm-commits mailing list