[llvm] [ARM] Fix not saving FP when required to in frame-pointer=non-leaf. (PR #165128)

Amara Emerson via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 25 20:24:48 PDT 2025


https://github.com/aemerson created https://github.com/llvm/llvm-project/pull/165128

[ARM] Fix not saving FP when required to in frame-pointer=non-leaf.

When the stars align to conspire against stack alignment, when we have
frame-pointer=non-leaf we can incorrectly skip preserving fp/r7 in the prolog.
The fix here first makes sure we're using the right frame pointer register in
the context of preserving the incoming FP, and then make sure that we save
the FP when re-alignment is known to be necessary.

rdar://162462271

[MC] Fix accidentally eating the newline when handling a comment char at the end of the line.

If we have a target where both # and ## are valid comment strings,
a line ending in # would trigger the lexer to eat 2 characters
and therefore lex the *next* line as a comment. Oops. This was introduced
in 4946db15a74b761c5ac4ead18873639236b4ab5d

>From fd756cbd6eb335024239221a3ca98e201ac02798 Mon Sep 17 00:00:00 2001
From: Amara Emerson <amara at apple.com>
Date: Wed, 15 Oct 2025 14:50:52 -0700
Subject: [PATCH 1/2] [ARM] Fix not saving FP when required to in
 frame-pointer=non-leaf.

When the stars align to conspire against stack alignment, when we have
frame-pointer=non-leaf we can incorrectly skip preserving fp/r7 in the prolog.
The fix here first makes sure we're using the right frame pointer register in
the context of preserving the incoming FP, and then make sure that we save
the FP when re-alignment is known to be necessary.

rdar://162462271
---
 llvm/lib/Target/ARM/ARMFrameLowering.cpp      |  8 +++-
 .../test/CodeGen/ARM/save-fp-with-non-leaf.ll | 37 +++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/ARM/save-fp-with-non-leaf.ll

diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
index 138981ad92a87..a6c40e5212132 100644
--- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
@@ -2537,7 +2537,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
   MachineRegisterInfo &MRI = MF.getRegInfo();
   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
   (void)TRI;  // Silence unused warning in non-assert builds.
-  Register FramePtr = RegInfo->getFrameRegister(MF);
+  Register FramePtr = STI.getFramePointerReg();
   ARMSubtarget::PushPopSplitVariation PushPopSplit =
       STI.getPushPopSplitVariation(MF);
 
@@ -2784,7 +2784,11 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
       !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) {
     AFI->setHasStackFrame(true);
 
-    if (HasFP) {
+    // Save the FP if:
+    // 1. We currently need it (HasFP), OR
+    // 2. We might need it later due to stack realignment from aligned DPRCS2
+    //    saves (which will make hasFP() become true in emitPrologue).
+    if (HasFP || (isFPReserved(MF) && AFI->getNumAlignedDPRCS2Regs() > 0)) {
       SavedRegs.set(FramePtr);
       // If the frame pointer is required by the ABI, also spill LR so that we
       // emit a complete frame record.
diff --git a/llvm/test/CodeGen/ARM/save-fp-with-non-leaf.ll b/llvm/test/CodeGen/ARM/save-fp-with-non-leaf.ll
new file mode 100644
index 0000000000000..fefa5a0a68020
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/save-fp-with-non-leaf.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc %s -o - | FileCheck %s --check-prefix=CHECK
+target datalayout = "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+target triple = "thumbv7-apple-darwin"
+
+; This test checks that even with NEON register induced stack re-alignment, and
+; with the frame-pointer=non-leaf option, that we still save fp aka r7 in the
+; prolog as required.
+
+define fastcc i32 @test_save_fp() #0 {
+; CHECK-LABEL: test_save_fp:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    push {r4, r7, lr}
+; CHECK-NEXT:    add r7, sp, #4
+; CHECK-NEXT:    sub.w r4, sp, #64
+; CHECK-NEXT:    bfc r4, #0, #4
+; CHECK-NEXT:    mov sp, r4
+; CHECK-NEXT:    vst1.64 {d8, d9, d10, d11}, [r4:128]!
+; CHECK-NEXT:    movs r0, #0
+; CHECK-NEXT:    vst1.64 {d12, d13, d14, d15}, [r4:128]
+; CHECK-NEXT:    mov r4, sp
+; CHECK-NEXT:    @ InlineAsm Start
+; CHECK-NEXT:    vld1.16 {d0, d1, d2, d3}, [r0]
+; CHECK-NEXT:    vld1.16 {d4, d5, d6, d7}, [r0]
+; CHECK-NEXT:    vabdl.s16 q4, d0, d4
+; CHECK-EMPTY:
+; CHECK-NEXT:    @ InlineAsm End
+; CHECK-NEXT:    vld1.64 {d8, d9, d10, d11}, [r4:128]!
+; CHECK-NEXT:    vld1.64 {d12, d13, d14, d15}, [r4:128]
+; CHECK-NEXT:    subs r4, r7, #4
+; CHECK-NEXT:    mov sp, r4
+; CHECK-NEXT:    pop {r4, r7, pc}
+  tail call void asm sideeffect "vld1.i16 {q0,q1}, [$0]\0Avld1.i16 {q2,q3}, [$1]\0Avabdl.s16 q4, d0, d4\0A", "r,r,r,~{q0},~{q1},~{q2},~{q3},~{q4},~{q5},~{q6},~{q7},~{memory}"(ptr null, ptr null, ptr null)
+  ret i32 0
+}
+
+attributes #0 = { "frame-pointer"="non-leaf" }

>From 07be0d30a8b866755c9420dcdad7b75ed20ed626 Mon Sep 17 00:00:00 2001
From: Amara Emerson <amara at apple.com>
Date: Sat, 25 Oct 2025 19:58:13 -0700
Subject: [PATCH 2/2] [MC] Fix accidentally eating the newline when handling a
 comment char at the end of the line.

If we have a target where both # and ## are valid comment strings,
a line ending in # would trigger the lexer to eat 2 characters
and therefore lex the *next* line as a comment. Oops. This was introduced
in 4946db15a74b761c5ac4ead18873639236b4ab5d
---
 llvm/lib/MC/MCParser/AsmLexer.cpp                      |  9 ++++++++-
 .../MC/AsmParser/comments-x86-darwin-eol-dropped.s     | 10 ++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/MC/AsmParser/comments-x86-darwin-eol-dropped.s

diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp
index 968ccf776440b..8062ce88a154b 100644
--- a/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -835,7 +835,14 @@ AsmToken AsmLexer::LexToken() {
   }
 
   if (isAtStartOfComment(TokStart)) {
-    CurPtr += MAI.getCommentString().size() - 1;
+    StringRef CommentString = MAI.getCommentString();
+    // For multi-char comment strings, advance CurPtr only if we matched the full
+    // string. This stops us from accidentally eating the newline if the current
+    // line ends in a single comment char.
+    if (CommentString.size() > 1 &&
+        StringRef(TokStart, CommentString.size()) == CommentString) {
+      CurPtr += CommentString.size() - 1;
+    }
     return LexLineComment();
   }
 
diff --git a/llvm/test/MC/AsmParser/comments-x86-darwin-eol-dropped.s b/llvm/test/MC/AsmParser/comments-x86-darwin-eol-dropped.s
new file mode 100644
index 0000000000000..662e5987db6e2
--- /dev/null
+++ b/llvm/test/MC/AsmParser/comments-x86-darwin-eol-dropped.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc -triple i386-apple-darwin %s 2>&1 | FileCheck %s
+.p2align 3
+// CHECK: .p2align 3
+test:
+// CHECK-LABEL: test:
+// CHECK: pushl %ebp
+// CHECK: movl %esp, %ebp
+# Check that the following line's comment # doesn't drop the movl after
+   pushl %ebp #
+   movl %esp, %ebp



More information about the llvm-commits mailing list