[llvm] [CodeGen] Mark LIFETIME_START and LIFETIME_END as mayLoad/mayStore (PR #211179)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 22 02:05:43 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/3] 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/3] [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/3] 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.
More information about the llvm-commits
mailing list