[llvm] PeepholeOpt: Clear kill flags in foldImmediate (PR #195680)
Frederik Harwath via llvm-commits
llvm-commits at lists.llvm.org
Mon May 4 08:58:05 PDT 2026
https://github.com/frederik-h created https://github.com/llvm/llvm-project/pull/195680
When foldImmediate replaces a COPY destination with its source,
it extends the live range of the source, but it does not
update the kill flags.
Clear kill flags on the source register after replacement.
>From b8498092a977da9bb746688801407cf4915be225 Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharwath at amd.com>
Date: Mon, 4 May 2026 06:44:35 -0400
Subject: [PATCH 1/2] [AMDGPU] Add test for peephole kill flag bug
Add test case that shows that peephole-opt incorrectly
preserves kill flags.
---
.../AMDGPU/peephole-fold-kill-flag-bug.mir | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir
diff --git a/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir b/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir
new file mode 100644
index 0000000000000..5840ee720e436
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir
@@ -0,0 +1,49 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=amdgcn-- -run-pass=peephole-opt %s -o - | FileCheck %s
+# RUN: not --crash llc -mtriple=amdgcn-- -run-pass=peephole-opt -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=VERIFY
+
+---
+name: coalescable_copy_kill_bug
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr0_sgpr1
+
+ ; CHECK-LABEL: name: coalescable_copy_kill_bug
+ ; CHECK: liveins: $sgpr0_sgpr1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
+ ; CHECK-NEXT: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 42, implicit $exec
+ ; CHECK-NEXT: [[V_MOV_B32_e32_2:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 43, implicit $exec
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_MOV_B32_e32_1]], %subreg.sub0, killed [[V_MOV_B32_e32_]], %subreg.sub1
+ ; CHECK-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_MOV_B32_e32_2]], %subreg.sub0, [[V_MOV_B32_e32_]], %subreg.sub1
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
+ ; CHECK-NEXT: [[V_MOV_B32_e32_3:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
+ ; CHECK-NEXT: $m0 = S_MOV_B32 -1
+ ; CHECK-NEXT: DS_WRITE_B64 [[V_MOV_B32_e32_3]], killed [[COPY]], 0, 0, implicit $m0, implicit $exec :: (store (s64), addrspace 3)
+ ; CHECK-NEXT: DS_WRITE_B64 [[V_MOV_B32_e32_3]], killed [[COPY1]], 8, 0, implicit $m0, implicit $exec :: (store (s64), addrspace 3)
+ ; CHECK-NEXT: S_ENDPGM 0
+ %0:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
+ %1:vgpr_32 = V_MOV_B32_e32 42, implicit $exec
+ %2:vgpr_32 = V_MOV_B32_e32 43, implicit $exec
+
+ %3:vgpr_32 = COPY %0:vgpr_32
+
+ %4:vreg_64 = REG_SEQUENCE %1:vgpr_32, %subreg.sub0, killed %3:vgpr_32, %subreg.sub1
+ %5:vreg_64 = REG_SEQUENCE %2:vgpr_32, %subreg.sub0, %0:vgpr_32, %subreg.sub1
+
+ %6:vreg_64 = COPY %4:vreg_64
+ %7:vreg_64 = COPY %5:vreg_64
+
+ %8:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
+ $m0 = S_MOV_B32 -1
+ DS_WRITE_B64 %8:vgpr_32, killed %6:vreg_64, 0, 0, implicit $m0, implicit $exec :: (store (s64), addrspace 3)
+ DS_WRITE_B64 %8:vgpr_32, killed %7:vreg_64, 8, 0, implicit $m0, implicit $exec :: (store (s64), addrspace 3)
+
+ S_ENDPGM 0
+
+# VERIFY: *** Bad machine code: Using a killed virtual register ***
+# VERIFY: - function: coalescable_copy_kill_bug
+# VERIFY: LLVM ERROR: Found 1 machine code errors.
+...
>From 22919b5c419a565053a53532cc4255b86f39b804 Mon Sep 17 00:00:00 2001
From: Frederik Harwath <fharwath at amd.com>
Date: Mon, 4 May 2026 08:56:25 -0400
Subject: [PATCH 2/2] PeepholeOpt: Clear kill flags in foldImmediate
When foldImmediate replaces a COPY destination with its source,
it extends the live range of the source, but it does not
update the kill flags.
Clear kill flags on the source register after replacement.
---
llvm/lib/CodeGen/PeepholeOptimizer.cpp | 2 ++
llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir | 9 ++-------
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/CodeGen/PeepholeOptimizer.cpp b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
index 9365ea883eec9..4d302c7f0b5ae 100644
--- a/llvm/lib/CodeGen/PeepholeOptimizer.cpp
+++ b/llvm/lib/CodeGen/PeepholeOptimizer.cpp
@@ -1440,6 +1440,8 @@ bool PeepholeOptimizer::foldImmediate(
if (DstReg.isVirtual() &&
MRI->getRegClass(DstReg) == MRI->getRegClass(Reg)) {
MRI->replaceRegWith(DstReg, Reg);
+ // We may have extended the live range of Reg, clear any kill flags.
+ MRI->clearKillFlags(Reg);
MI.eraseFromParent();
Deleted = true;
}
diff --git a/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir b/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir
index 5840ee720e436..3c92e15a85c1c 100644
--- a/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir
+++ b/llvm/test/CodeGen/AMDGPU/peephole-fold-kill-flag-bug.mir
@@ -1,6 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=amdgcn-- -run-pass=peephole-opt %s -o - | FileCheck %s
-# RUN: not --crash llc -mtriple=amdgcn-- -run-pass=peephole-opt -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefix=VERIFY
+# RUN: llc -mtriple=amdgcn-- -run-pass=peephole-opt -verify-machineinstrs %s -o - | FileCheck %s
---
name: coalescable_copy_kill_bug
@@ -15,7 +14,7 @@ body: |
; CHECK-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 0, implicit $exec
; CHECK-NEXT: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 42, implicit $exec
; CHECK-NEXT: [[V_MOV_B32_e32_2:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 43, implicit $exec
- ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_MOV_B32_e32_1]], %subreg.sub0, killed [[V_MOV_B32_e32_]], %subreg.sub1
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_MOV_B32_e32_1]], %subreg.sub0, [[V_MOV_B32_e32_]], %subreg.sub1
; CHECK-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_MOV_B32_e32_2]], %subreg.sub0, [[V_MOV_B32_e32_]], %subreg.sub1
; CHECK-NEXT: [[COPY:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
; CHECK-NEXT: [[COPY1:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
@@ -42,8 +41,4 @@ body: |
DS_WRITE_B64 %8:vgpr_32, killed %7:vreg_64, 8, 0, implicit $m0, implicit $exec :: (store (s64), addrspace 3)
S_ENDPGM 0
-
-# VERIFY: *** Bad machine code: Using a killed virtual register ***
-# VERIFY: - function: coalescable_copy_kill_bug
-# VERIFY: LLVM ERROR: Found 1 machine code errors.
...
More information about the llvm-commits
mailing list