[llvm] [StackColoring] Do not merge stack slots with `returns_twice` call-sites (PR #196542)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Fri May 8 10:53:43 PDT 2026
https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/196542
>From b85e2db8fe50a52427a5248ecf92d83d6087ff2d Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 8 May 2026 15:28:32 +0200
Subject: [PATCH 1/3] [StackColoring] Introduce test (NFC)
---
.../X86/sjlj-do-not-merge-stack-slots.ll | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll
diff --git a/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll b/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll
new file mode 100644
index 0000000000000..c59ca19ea1550
--- /dev/null
+++ b/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=x86_64-- < %s | FileCheck %s
+
+define void @sjlj_do_not_merge_stack_slots() nounwind {
+; CHECK-LABEL: sjlj_do_not_merge_stack_slots:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: subq $24, %rsp
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq setjmp at PLT
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: je .LBB0_1
+; CHECK-NEXT: # %bb.2: # %else
+; CHECK-NEXT: callq opaque at PLT
+; CHECK-NEXT: addq $24, %rsp
+; CHECK-NEXT: retq
+; CHECK-NEXT: .LBB0_1: # %then
+; CHECK-NEXT: callq escape at PLT
+; CHECK-NEXT: addq $24, %rsp
+; CHECK-NEXT: retq
+entry:
+ %obj = alloca [8 x i8], align 4
+ %buf = alloca [12 x i8], align 4
+ %obj.1 = alloca [8 x i8], align 4
+ call void @llvm.lifetime.start.p0(ptr %obj)
+ call void @llvm.lifetime.start.p0(ptr %buf)
+ %rv = call i32 @setjmp(ptr %buf)
+ %c = icmp eq i32 %rv, 0
+ br i1 %c, label %then, label %else
+
+then:
+ call void @escape(ptr %obj)
+ br label %exit
+
+else:
+ call void @llvm.lifetime.start.p0(ptr %obj.1)
+ call void @opaque(ptr %obj.1)
+ call void @llvm.lifetime.end.p0(ptr %obj.1)
+ br label %exit
+
+exit:
+ call void @llvm.lifetime.end.p0(ptr %buf)
+ call void @llvm.lifetime.end.p0(ptr %obj)
+ ret void
+}
+
+declare i32 @setjmp(ptr) returns_twice
+declare void @escape(ptr)
+declare void @opaque(ptr)
>From d02ca444d2e89419a394017755082f732cf2efeb Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 8 May 2026 15:45:06 +0200
Subject: [PATCH 2/3] [StackColoring] Do not merge stack slots with
`returns_twice` call-sites
Do not merge stack slots on disjoint paths if the function may call
setjmp/sigsetjmp, as the current algorithm defaults to computing
liveness analysis from the actual uses propagated through the CFG,
rather than leveraging lifetime markers, thus making it unsound with
`returns_twice` calls.
Fixes: https://github.com/llvm/llvm-project/issues/196468.
---
llvm/lib/CodeGen/StackColoring.cpp | 6 ++++++
llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll | 9 +++++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/StackColoring.cpp b/llvm/lib/CodeGen/StackColoring.cpp
index 65f9ae5433195..2d708f72f15ed 100644
--- a/llvm/lib/CodeGen/StackColoring.cpp
+++ b/llvm/lib/CodeGen/StackColoring.cpp
@@ -1221,6 +1221,12 @@ bool StackColoring::run(MachineFunction &Func, bool OnlyRemoveMarkers) {
if (!NumSlots)
return false;
+ // Conservatively do not merge stack slots on disjoint paths if we have calls
+ // to setjmp/sigsetjmp, as longjmp may re-enter the function on a different
+ // path.
+ if (MF->exposesReturnsTwice())
+ return false;
+
SmallVector<int, 8> SortedSlots;
SortedSlots.reserve(NumSlots);
Intervals.reserve(NumSlots);
diff --git a/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll b/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll
index c59ca19ea1550..ef2da73bbbf5b 100644
--- a/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll
+++ b/llvm/test/CodeGen/X86/sjlj-do-not-merge-stack-slots.ll
@@ -4,19 +4,20 @@
define void @sjlj_do_not_merge_stack_slots() nounwind {
; CHECK-LABEL: sjlj_do_not_merge_stack_slots:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: subq $24, %rsp
+; CHECK-NEXT: subq $40, %rsp
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq setjmp at PLT
-; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: testl %eax, %eax
; CHECK-NEXT: je .LBB0_1
; CHECK-NEXT: # %bb.2: # %else
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq opaque at PLT
-; CHECK-NEXT: addq $24, %rsp
+; CHECK-NEXT: addq $40, %rsp
; CHECK-NEXT: retq
; CHECK-NEXT: .LBB0_1: # %then
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq escape at PLT
-; CHECK-NEXT: addq $24, %rsp
+; CHECK-NEXT: addq $40, %rsp
; CHECK-NEXT: retq
entry:
%obj = alloca [8 x i8], align 4
>From da135cb9884d524acd6452e02d288a56ab0e8735 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 8 May 2026 19:45:51 +0200
Subject: [PATCH 3/3] !fixup disable applyFirstUse
---
llvm/lib/CodeGen/StackColoring.cpp | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/CodeGen/StackColoring.cpp b/llvm/lib/CodeGen/StackColoring.cpp
index 2d708f72f15ed..cdb0ca5147728 100644
--- a/llvm/lib/CodeGen/StackColoring.cpp
+++ b/llvm/lib/CodeGen/StackColoring.cpp
@@ -719,6 +719,11 @@ unsigned StackColoring::collectMarkers(unsigned NumSlot) {
H.CatchObj.FrameIndex >= 0)
ConservativeSlots.set(H.CatchObj.FrameIndex);
+ // Treat all stack slots as conservative if we happen to have calls to
+ // setjmp/sigsetjmp, as longjmp may re-enter the function on a different path.
+ if (MF->exposesReturnsTwice())
+ ConservativeSlots.set();
+
LLVM_DEBUG(dumpBV("Conservative slots", ConservativeSlots));
// Step 2: compute begin/end sets for each block
@@ -1221,12 +1226,6 @@ bool StackColoring::run(MachineFunction &Func, bool OnlyRemoveMarkers) {
if (!NumSlots)
return false;
- // Conservatively do not merge stack slots on disjoint paths if we have calls
- // to setjmp/sigsetjmp, as longjmp may re-enter the function on a different
- // path.
- if (MF->exposesReturnsTwice())
- return false;
-
SmallVector<int, 8> SortedSlots;
SortedSlots.reserve(NumSlots);
Intervals.reserve(NumSlots);
More information about the llvm-commits
mailing list