[clang] a67c8f2 - [Flang][Driver]Implemented support for option -momit-leaf-frame-pointer/-mno-omit-leaf-frame-pointer in flang (#216700)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 21:50:42 PDT 2026


Author: Kaviya Rajendiran
Date: 2026-09-12T10:20:36+05:30
New Revision: a67c8f208e8710ad8b6b6e2ca4de57e4e0db7178

URL: https://github.com/llvm/llvm-project/commit/a67c8f208e8710ad8b6b6e2ca4de57e4e0db7178
DIFF: https://github.com/llvm/llvm-project/commit/a67c8f208e8710ad8b6b6e2ca4de57e4e0db7178.diff

LOG: [Flang][Driver]Implemented support for option -momit-leaf-frame-pointer/-mno-omit-leaf-frame-pointer in flang (#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").

Added: 
    flang/test/Transforms/function-attr-frame-pointer.fir

Modified: 
    clang/include/clang/Options/Options.td
    flang/include/flang/Optimizer/Transforms/Passes.td
    flang/lib/Frontend/FrontendActions.cpp
    flang/test/Driver/frame-pointer-forwarding.f90

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 0e57c128210b3..56194af32f68f 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -6267,9 +6267,10 @@ 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 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>,
-  HelpText<"Omit frame pointer setup for leaf functions">;
+  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/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index a51fffdbc2b07..d7e271e1ed7b3 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -535,6 +535,7 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> {
               "Set LLVM readonly attribute on INTENT(IN) by-reference "
               "function arguments, if possible">,
   ];
+  let dependentDialects = ["mlir::LLVM::LLVMDialect"];
 }
 
 def AssumedRankOpConversion : Pass<"fir-assumed-rank-op", "mlir::ModuleOp"> {

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 648574fae18cf..35c2b9ec881e8 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -835,6 +835,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..5958becf4f244 100644
--- a/flang/test/Driver/frame-pointer-forwarding.f90
+++ b/flang/test/Driver/frame-pointer-forwarding.f90
@@ -1,4 +1,6 @@
-! Test that flang forwards -fno-omit-frame-pointer and -fomit-frame-pointer Flang frontend
+! Test that flang forwards -fno-omit-frame-pointer and -fomit-frame-pointer to Flang frontend
+
+! Default behavior in aarch64, -mframe-pointer=non-leaf-no-reserve.
 ! RUN: %flang --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1  | FileCheck %s --check-prefix=CHECK-NOVALUE
 ! CHECK-NOVALUE: "-fc1"{{.*}}"-mframe-pointer=non-leaf-no-reserve"
 
@@ -8,5 +10,31 @@
 ! RUN: %flang -fno-omit-frame-pointer --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1  | FileCheck %s --check-prefix=CHECK-NONLEAFFP
 ! CHECK-NONLEAFFP: "-fc1"{{.*}}"-mframe-pointer=non-leaf-no-reserve"
 
+! RUN: %flang -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer --target=aarch64-none-none -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-ALL
+
+! Default behavior in x86_64, -mframe-pointer=all at -O0 level.
 ! 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 -O0 --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-ALL
+! RUN: %flang -O0 -momit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-NON-LEAF
+! RUN: %flang -O0 -mno-omit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-ALL
+! RUN: %flang -O0 -fomit-frame-pointer -momit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-NONE
+! RUN: %flang -fno-omit-frame-pointer -momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-ALL
+
+! At -O1/-O2/-O3 level, default is -mframe-pointer=none.
+! RUN: %flang --target=x86_64-unknown-linux-gnu -O2 -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-NONE
+
+! With -fno-omit-frame-pointer and -mno-omit-leaf-frame-pointer, -mframe-pointer=all.
+! RUN: %flang -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -O2 -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-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 -### %s -o %t 2>&1  | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-NONE
+! RUN: %flang -fno-omit-frame-pointer --target=x86_64-unknown-linux-gnu -O2 -### %s -o %t 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-ALL
+
+! RUN: %flang -fno-omit-frame-pointer -momit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -O2 -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,FRAME-POINTER-NON-LEAF
+
+! FC1: "-fc1"
+! FRAME-POINTER-ALL-SAME: "-mframe-pointer=all"
+! FRAME-POINTER-NON-LEAF-SAME: "-mframe-pointer=non-leaf-no-reserve"
+! FRAME-POINTER-NONE-SAME: "-mframe-pointer=none"

diff  --git a/flang/test/Transforms/function-attr-frame-pointer.fir b/flang/test/Transforms/function-attr-frame-pointer.fir
new file mode 100644
index 0000000000000..b9c0288977cd2
--- /dev/null
+++ b/flang/test/Transforms/function-attr-frame-pointer.fir
@@ -0,0 +1,20 @@
+// RUN: fir-opt --function-attr="frame-pointer=All" %s | FileCheck %s --check-prefix=ALL
+// RUN: fir-opt --function-attr="frame-pointer=NonLeaf" %s | FileCheck %s --check-prefix=NONLEAF
+// RUN: fir-opt --function-attr="frame-pointer=NonLeafNoReserve" %s | FileCheck %s --check-prefix=NONLEAFNORESERVE
+// RUN: fir-opt --function-attr="frame-pointer=None" %s | FileCheck %s --check-prefix=NONE
+
+func.func @_QPtest() {
+  return
+}
+
+// ALL-LABEL: func.func @_QPtest()
+// ALL-SAME: llvm.frame_pointer = #llvm.framePointerKind<all>
+
+// NONLEAF-LABEL: func.func @_QPtest()
+// NONLEAF-SAME: llvm.frame_pointer = #llvm.framePointerKind<"non-leaf">
+
+// NONLEAFNORESERVE-LABEL: func.func @_QPtest()
+// NONLEAFNORESERVE-SAME: llvm.frame_pointer = #llvm.framePointerKind<"non-leaf-no-reserve">
+
+// NONE-LABEL: func.func @_QPtest()
+// NONE-NOT: llvm.frame_pointer


        


More information about the cfe-commits mailing list