[llvm] [CodeGen] Mark LIFETIME_START and LIFETIME_END as not safe to move (PR #211179)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 22 18:46:28 PDT 2026
https://github.com/lukel97 updated https://github.com/llvm/llvm-project/pull/211179
>From 84a649ba86a58257c66ac3e32ee93a7b4d12f36c Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 22 Jul 2026 14:02:07 +0800
Subject: [PATCH 1/7] Precommit test
---
llvm/test/CodeGen/RISCV/lifetime-licm.mir | 43 +++++++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/lifetime-licm.mir
diff --git a/llvm/test/CodeGen/RISCV/lifetime-licm.mir b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
new file mode 100644
index 0000000000000..daeaa6c05e34a
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
@@ -0,0 +1,43 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=riscv32 -run-pass=early-machinelicm -verify-machineinstrs -o - %s | FileCheck %s
+# RUN: llc -mtriple=riscv64 -run-pass=early-machinelicm -verify-machineinstrs -o - %s | FileCheck %s
+---
+name: dont_hoist_lifetime_start_end
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 4 }
+body: |
+ ; CHECK-LABEL: name: dont_hoist_lifetime_start_end
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %start:gpr = ADDI $x0, 10
+ ; CHECK-NEXT: LIFETIME_START %stack.0
+ ; CHECK-NEXT: LIFETIME_END %stack.0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %iv:gpr = PHI %start, %bb.0, %ivnext, %bb.1
+ ; CHECK-NEXT: %ivnext:gpr = ADDI %iv, -1
+ ; CHECK-NEXT: BNE %ivnext, $x0, %bb.1
+ ; CHECK-NEXT: PseudoBR %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ %start:gpr = ADDI $x0, 10
+ PseudoBR %bb.1
+
+ bb.1:
+ %iv:gpr = PHI %start, %bb.0, %ivnext, %bb.1
+ LIFETIME_START %stack.0
+ LIFETIME_END %stack.0
+ %ivnext:gpr = ADDI %iv, -1
+ BNE %ivnext, $x0, %bb.1
+ PseudoBR %bb.2
+
+ bb.2:
+ PseudoRET
+...
>From 1e955319ccf3f95d014e6f949cd32bda62ba3d39 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 22 Jul 2026 14:17:58 +0800
Subject: [PATCH 2/7] [CodeGen] Mark LIFETIME_START and LIFETIME_END as
mayLoad/mayStore
PR #210028 added a run of EarlyMachineLICM before StackColoring removed LIFETIME_START/LIFETIME_END markers, and it ended up hoisting them which led to miscompiles. This adds the mayLoad/mayStore flags to match how the lifetime_start/lifetime_end intrinsics are marked as reading and writing from memory, which prevents them from being reordered by LICM.
---
llvm/include/llvm/Target/Target.td | 4 ++++
llvm/test/CodeGen/RISCV/lifetime-licm.mir | 4 ++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index cb97ab5d1bae4..f527ca880a64b 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1498,6 +1498,8 @@ def LIFETIME_START : StandardPseudoInstruction {
let AsmString = "LIFETIME_START";
let hasSideEffects = false;
let isMeta = true;
+ let mayLoad = true;
+ let mayStore = true;
}
def LIFETIME_END : StandardPseudoInstruction {
let OutOperandList = (outs);
@@ -1505,6 +1507,8 @@ def LIFETIME_END : StandardPseudoInstruction {
let AsmString = "LIFETIME_END";
let hasSideEffects = false;
let isMeta = true;
+ let mayLoad = true;
+ let mayStore = true;
}
def PSEUDO_PROBE : StandardPseudoInstruction {
let OutOperandList = (outs);
diff --git a/llvm/test/CodeGen/RISCV/lifetime-licm.mir b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
index daeaa6c05e34a..f4aef364eefb6 100644
--- a/llvm/test/CodeGen/RISCV/lifetime-licm.mir
+++ b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
@@ -12,14 +12,14 @@ body: |
; CHECK-NEXT: successors: %bb.1(0x80000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %start:gpr = ADDI $x0, 10
- ; CHECK-NEXT: LIFETIME_START %stack.0
- ; CHECK-NEXT: LIFETIME_END %stack.0
; CHECK-NEXT: PseudoBR %bb.1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %iv:gpr = PHI %start, %bb.0, %ivnext, %bb.1
+ ; CHECK-NEXT: LIFETIME_START %stack.0
+ ; CHECK-NEXT: LIFETIME_END %stack.0
; CHECK-NEXT: %ivnext:gpr = ADDI %iv, -1
; CHECK-NEXT: BNE %ivnext, $x0, %bb.1
; CHECK-NEXT: PseudoBR %bb.2
>From a35280945498a737583b3e8869abbb21aee8f688 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 22 Jul 2026 17:03:29 +0800
Subject: [PATCH 3/7] Mark isLifetimeMarker as unsafe to move instead
---
llvm/include/llvm/Target/Target.td | 4 ----
llvm/lib/CodeGen/MachineInstr.cpp | 2 +-
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index f527ca880a64b..cb97ab5d1bae4 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -1498,8 +1498,6 @@ def LIFETIME_START : StandardPseudoInstruction {
let AsmString = "LIFETIME_START";
let hasSideEffects = false;
let isMeta = true;
- let mayLoad = true;
- let mayStore = true;
}
def LIFETIME_END : StandardPseudoInstruction {
let OutOperandList = (outs);
@@ -1507,8 +1505,6 @@ def LIFETIME_END : StandardPseudoInstruction {
let AsmString = "LIFETIME_END";
let hasSideEffects = false;
let isMeta = true;
- let mayLoad = true;
- let mayStore = true;
}
def PSEUDO_PROBE : StandardPseudoInstruction {
let OutOperandList = (outs);
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index 0fbeea153d3c9..ced2b5f60a0b5 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -1360,7 +1360,7 @@ bool MachineInstr::isSafeToMove(bool &SawStore) const {
// Don't touch instructions that have non-trivial invariants. For example,
// terminators have to be at the end of a basic block.
if (isPosition() || isDebugInstr() || isTerminator() ||
- isJumpTableDebugInfo())
+ isJumpTableDebugInfo() || isLifetimeMarker())
return false;
// Don't touch instructions which can have non-load/store effects.
>From c56ae46668c5e46f7f9ddccdd58001db40789baa Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 22 Jul 2026 17:06:28 +0800
Subject: [PATCH 4/7] Remove riscv32 RUN
---
llvm/test/CodeGen/RISCV/lifetime-licm.mir | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/test/CodeGen/RISCV/lifetime-licm.mir b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
index f4aef364eefb6..3f810a6e4da32 100644
--- a/llvm/test/CodeGen/RISCV/lifetime-licm.mir
+++ b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
@@ -1,5 +1,4 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=riscv32 -run-pass=early-machinelicm -verify-machineinstrs -o - %s | FileCheck %s
# RUN: llc -mtriple=riscv64 -run-pass=early-machinelicm -verify-machineinstrs -o - %s | FileCheck %s
---
name: dont_hoist_lifetime_start_end
>From 3c543e647862408179c6f05ed86e8449bae0f4e1 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 22 Jul 2026 17:24:29 +0800
Subject: [PATCH 5/7] Remove isLifetimeMarker check from wouldBeTriviallyDead
---
llvm/lib/CodeGen/MachineInstr.cpp | 5 -----
1 file changed, 5 deletions(-)
diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp
index ced2b5f60a0b5..1067f186208c4 100644
--- a/llvm/lib/CodeGen/MachineInstr.cpp
+++ b/llvm/lib/CodeGen/MachineInstr.cpp
@@ -1403,11 +1403,6 @@ bool MachineInstr::wouldBeTriviallyDead() const {
if (isFakeUse())
return false;
- // LIFETIME markers should be preserved.
- // FIXME: Why are LIFETIME markers not considered in MachineInstr::isPosition?
- if (isLifetimeMarker())
- return false;
-
// If we can move an instruction, we can remove it. Otherwise, it has
// a side-effect of some sort.
bool SawStore = false;
>From 72fe3db47c440f489c46aeb700745de52f676841 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke_lau at icloud.com>
Date: Wed, 22 Jul 2026 17:26:41 +0800
Subject: [PATCH 6/7] Remove -verify-machineinstrs
Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
llvm/test/CodeGen/RISCV/lifetime-licm.mir | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/RISCV/lifetime-licm.mir b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
index 3f810a6e4da32..66b8c22c1ba72 100644
--- a/llvm/test/CodeGen/RISCV/lifetime-licm.mir
+++ b/llvm/test/CodeGen/RISCV/lifetime-licm.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=riscv64 -run-pass=early-machinelicm -verify-machineinstrs -o - %s | FileCheck %s
+# RUN: llc -mtriple=riscv64 -run-pass=early-machinelicm -o - %s | FileCheck %s
---
name: dont_hoist_lifetime_start_end
tracksRegLiveness: true
>From f61a14ef2958bc427509c125828122b4673f2cde Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Thu, 23 Jul 2026 09:43:28 +0800
Subject: [PATCH 7/7] Move FIXME
---
llvm/include/llvm/CodeGen/MachineInstr.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h
index 2efd3d4d6f095..b04018e43bbe0 100644
--- a/llvm/include/llvm/CodeGen/MachineInstr.h
+++ b/llvm/include/llvm/CodeGen/MachineInstr.h
@@ -1368,6 +1368,7 @@ class MachineInstr
}
// True if the instruction represents a position in the function.
+ // FIXME: Why are LIFETIME markers not considered in MachineInstr::isPosition?
bool isPosition() const { return isLabel() || isCFIInstruction(); }
bool isNonListDebugValue() const {
More information about the llvm-commits
mailing list