https://github.com/kaviya2510 created
https://github.com/llvm/llvm-project/pull/216700
Added support for `-momit-leaf-frame-pointer` / `-mno-omit-leaf-frame-pointer`
in the Flang compiler.
- The driver resolves the flags via `getFramePointerKind()` and forwards
`-mframe-pointer=<kind>` to flang -fc1, resulting in the LLVM IR function
attribute "frame-pointer"
- These options, used with `-fno-omit-frame-pointer`, control whether leaf
functions (functions that don't call other functions) retain or omit the frame
pointer.
- `fno-omit-frame-pointer -momit-leaf-frame-pointe`r : Keep the frame
pointer in non-leaf functions, but omit it in leaf functions (produces
"frame-pointer"="non-leaf").
- `fno-omit-frame-pointer -mno-omit-leaf-frame-pointe`r : Keep the frame
pointer in all functions, including leaf functions (produces
"frame-pointer"="all").
>From 06be8bf4b4fa75347b671f1582c0776e22e179d0 Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <[email protected]>
Date: Mon, 17 Aug 2026 16:52:45 +0530
Subject: [PATCH] [Flang][Driver]Implemented support for option
-momit-leaf-frame-pointer/-mno-omit-leaf-frame-pointer in flang
---
clang/include/clang/Options/Options.td | 13 +++--
flang/lib/Frontend/FrontendActions.cpp | 3 ++
.../test/Driver/frame-pointer-forwarding.f90 | 16 ++++++
.../Integration/omit-leaf-frame-pointer.f90 | 49 +++++++++++++++++++
4 files changed, 78 insertions(+), 3 deletions(-)
create mode 100644 flang/test/Integration/omit-leaf-frame-pointer.f90
diff --git a/clang/include/clang/Options/Options.td
b/clang/include/clang/Options/Options.td
index adc4224dd561c..399c84c9d8359 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6233,9 +6233,16 @@ defm zos_ppa1_name : BoolMOption<"zos-ppa1-name",
BothFlags<[TargetSpecific], [ClangOption, CC1Option]>>;
def mno_warn_nonportable_cfstrings : Flag<["-"],
"mno-warn-nonportable-cfstrings">, Group<m_Group>;
-def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">,
Group<m_Group>;
-def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">,
Group<m_Group>,
- HelpText<"Omit frame pointer setup for leaf functions">;
+def mno_omit_leaf_frame_pointer
+ : Flag<["-"], "mno-omit-leaf-frame-pointer">,
+ Group<m_Group>,
+ Visibility<[ClangOption, FlangOption]>,
+ HelpText<"Keep the frame pointer in leaf functions">;
+def momit_leaf_frame_pointer
+ : Flag<["-"], "momit-leaf-frame-pointer">,
+ Group<m_Group>,
+ Visibility<[ClangOption, FlangOption]>,
+ HelpText<"Omit frame pointer setup for leaf functions">;
def mno_reserve_frame_pointer_reg : Flag<["-"],
"mno-reserve-frame-pointer-reg">, Group<m_Group>;
def mreserve_frame_pointer_reg : Flag<["-"], "mreserve-frame-pointer-reg">,
Group<m_Group>,
HelpText<"Reserve the frame pointer register even if the function doesn't
have a frame">;
diff --git a/flang/lib/Frontend/FrontendActions.cpp
b/flang/lib/Frontend/FrontendActions.cpp
index e21590cc9fa7f..0972dfd0701b1 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -827,6 +827,9 @@ void CodeGenAction::generateLLVMIR() {
static_cast<llvm::PIELevel::Level>(opts.PICLevel));
}
+ if (opts.getFramePointer() != llvm::FramePointerKind::None)
+ llvmModule->setFramePointer(opts.getFramePointer());
+
const TargetOptions &targetOpts = ci.getInvocation().getTargetOpts();
const llvm::Triple triple(targetOpts.triple);
diff --git a/flang/test/Driver/frame-pointer-forwarding.f90
b/flang/test/Driver/frame-pointer-forwarding.f90
index 7e97c98d899f1..68ed84d0a35f3 100644
--- a/flang/test/Driver/frame-pointer-forwarding.f90
+++ b/flang/test/Driver/frame-pointer-forwarding.f90
@@ -10,3 +10,19 @@
! RUN: %flang -fno-omit-frame-pointer --target=x86-none-none -fsyntax-only
-### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-ALLFP
! CHECK-ALLFP: "-fc1"{{.*}}"-mframe-pointer=all"
+
+! RUN: %flang -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
--target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s
--check-prefix=CHECK-FRAME-POINTER-ALL
+! CHECK-FRAME-POINTER-ALL: "-fc1"{{.*}}"-mframe-pointer=all"
+
+! RUN: %flang -fno-omit-frame-pointer -momit-leaf-frame-pointer
--target=x86_64-unknown-linux-gnu -fsyntax-only -### %s -o %t 2>&1 | FileCheck
%s --check-prefix=CHECK-X86-NONLEAF
+! CHECK-X86-NONLEAF: "-fc1"{{.*}}"-mframe-pointer=non-leaf-no-reserve"
+
+! RUN: %flang -fno-omit-frame-pointer -momit-leaf-frame-pointer
-mno-omit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -fsyntax-only
-### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-LAST-WINS
+! CHECK-LAST-WINS: "-fc1"{{.*}}"-mframe-pointer=all"
+
+! Without -fno-omit-frame-pointer the leaf option is silently allowed but has
no effect, matching Clang's behavior.
+! RUN: %flang -momit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -O2
-fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-LEAF-ONLY
+! CHECK-LEAF-ONLY: "-fc1"{{.*}}"-mframe-pointer=none"
+
+subroutine test
+end subroutine test
diff --git a/flang/test/Integration/omit-leaf-frame-pointer.f90
b/flang/test/Integration/omit-leaf-frame-pointer.f90
new file mode 100644
index 0000000000000..bfe747b9d44bb
--- /dev/null
+++ b/flang/test/Integration/omit-leaf-frame-pointer.f90
@@ -0,0 +1,49 @@
+! Test to check the options -momit-leaf-frame-pointer and
-mno-omit-leaf-frame-pointer
+
+! REQUIRES: aarch64-registered-target, x86-registered-target
+
+! RUN: %flang --target=x86_64-unknown-linux-gnu -S -emit-llvm -o - %s |
FileCheck %s --check-prefix=X86-DEFAULT
+! RUN: %flang --target=x86_64-unknown-linux-gnu -fno-omit-frame-pointer
-mno-omit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s
--check-prefix=X86-ALL
+! RUN: %flang --target=x86_64-unknown-linux-gnu -fno-omit-frame-pointer
-momit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s
--check-prefix=X86-NONLEAF
+! RUN: %flang --target=aarch64-none-none -fno-omit-frame-pointer
-momit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s
--check-prefix=AARCH64-NONLEAF
+! RUN: %flang --target=aarch64-none-none -fno-omit-frame-pointer
-mno-omit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s
--check-prefix=AARCH64-ALL
+
+! X86-DEFAULT: define void @_QQmain() #[[ATTR:[0-9]+]]
+! X86-DEFAULT: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}})
#[[ATTR]]
+! X86-DEFAULT: attributes #[[ATTR]] = {{{.*}}"frame-pointer"="all"{{.*}}}
+! X86-DEFAULT: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 2}
+
+! X86-ALL: define void @_QQmain() #[[ATTR:[0-9]+]]
+! X86-ALL: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}}) #[[ATTR]]
+! X86-ALL: attributes #[[ATTR]] = {{{.*}}"frame-pointer"="all"{{.*}}}
+! X86-ALL: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 2}
+
+! With -momit-leaf-frame-pointer, all functions get "non-leaf-no-reserve" the
backend will keep the frame pointer only in functions that make calls.
+! X86-NONLEAF: define void @_QQmain() #[[ATTR:[0-9]+]]
+! X86-NONLEAF: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}})
#[[ATTR]]
+! X86-NONLEAF: attributes #[[ATTR]] =
{{{.*}}"frame-pointer"="non-leaf-no-reserve"{{.*}}}
+! X86-NONLEAF: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 4}
+
+! AArch64 differs from x86_64: useLeafFramePointerForTargetByDefault is false,
so -fno-omit-frame-pointer alone gives "non-leaf-no-reserve".
+! -mno-omit-leaf-frame-pointer is needed to promote it to "all".
+! AARCH64-NONLEAF: attributes #{{[0-9]+}} =
{{{.*}}"frame-pointer"="non-leaf-no-reserve"{{.*}}}
+! AARCH64-NONLEAF: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 4}
+
+! AARCH64-ALL: attributes #{{[0-9]+}} = {{{.*}}"frame-pointer"="all"{{.*}}}
+! AARCH64-ALL: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 2}
+
+program test
+ implicit none
+ integer :: result
+ result = leaf(3, 4)
+ print *, result
+contains
+ integer function leaf(a, b)
+ implicit none
+ integer, value :: a, b
+ integer :: temp
+ temp = a + b
+ leaf = temp
+ end function leaf
+end program test
+
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits