https://github.com/kaviya2510 updated https://github.com/llvm/llvm-project/pull/216700
>From be57380889d5076266cf902b9a614f1acd73bf59 Mon Sep 17 00:00:00 2001 From: Kaviya Rajendiran <[email protected]> Date: Mon, 17 Aug 2026 16:52:45 +0530 Subject: [PATCH 1/2] [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 | 39 +++++++++++++++++++ 4 files changed, 68 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 7ecda651027e2..6bc8880ca759e 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..56f23e9e09f4f --- /dev/null +++ b/flang/test/Integration/omit-leaf-frame-pointer.f90 @@ -0,0 +1,39 @@ +! Test to check the options -momit-leaf-frame-pointer and -mno-omit-leaf-frame-pointer + +! REQUIRES: aarch64-registered-target, x86-registered-target + +! AArch64 differs from x86_64: useLeafFramePointerForTargetByDefault is false, so -fno-omit-frame-pointer alone already gives "non-leaf-no-reserve" on AArch64. + +! RUN: %flang --target=x86_64-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ALL +! 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=CHECK-ALL +! RUN: %flang --target=aarch64-none-none -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-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=CHECK-NONLEAF +! RUN: %flang --target=aarch64-none-none -fno-omit-frame-pointer -momit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONLEAF + + +! CHECK-ALL: define void @_QQmain() #[[ATTR:[0-9]+]] +! CHECK-ALL: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}}) #[[ATTR]] +! CHECK-ALL: attributes #[[ATTR]] = {{{.*}}"frame-pointer"="all"{{.*}}} +! CHECK-ALL: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 2} + +! CHECK-NONLEAF: define void @_QQmain() #[[ATTR:[0-9]+]] +! CHECK-NONLEAF: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}}) #[[ATTR]] +! CHECK-NONLEAF: attributes #[[ATTR]] = {{{.*}}"frame-pointer"="non-leaf-no-reserve"{{.*}}} +! CHECK-NONLEAF: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 4} + +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 + >From 9efe9430a80145bd258795c6fc4e798ab12c71aa Mon Sep 17 00:00:00 2001 From: Kaviya Rajendiran <[email protected]> Date: Thu, 20 Aug 2026 11:58:38 +0530 Subject: [PATCH 2/2] [flang] Modified testcases and addressed review comments --- .../flang/Optimizer/Transforms/Passes.td | 1 + .../test/Driver/frame-pointer-forwarding.f90 | 37 +++++++++++++----- .../Integration/omit-leaf-frame-pointer.f90 | 39 ------------------- .../function-attr-frame-pointer.fir | 20 ++++++++++ 4 files changed, 48 insertions(+), 49 deletions(-) delete mode 100644 flang/test/Integration/omit-leaf-frame-pointer.f90 create mode 100644 flang/test/Transforms/function-attr-frame-pointer.fir diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index 98090fefeeedc..f8a5f1b1679a0 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -501,6 +501,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/test/Driver/frame-pointer-forwarding.f90 b/flang/test/Driver/frame-pointer-forwarding.f90 index 68ed84d0a35f3..62c5d19d6f86d 100644 --- a/flang/test/Driver/frame-pointer-forwarding.f90 +++ b/flang/test/Driver/frame-pointer-forwarding.f90 @@ -11,18 +11,35 @@ ! 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" +! Default behavior in x86_64-unknown-linux-gnu, -mframe-pointer=all at -O0 level. -! 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" +! RUN: %flang -O0 --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-FRAME-POINTER-ALL +! RUN: %flang -O0 -momit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-FRAME-POINTER-NON-LEAF +! RUN: %flang -O0 -mno-omit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-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-prefix=CHECK-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-prefix=CHECK-FRAME-POINTER-ALL + +! Default behavior in x86_64-unknown-linux-gnu, -mframe-pointer=none at -O1/-O2/-O3 level. +! RUN: %flang --target=x86_64-unknown-linux-gnu -O2 -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-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-prefix=CHECK-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 -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-LEAF-ONLY -! CHECK-LEAF-ONLY: "-fc1"{{.*}}"-mframe-pointer=none" +! RUN: %flang -momit-leaf-frame-pointer --target=x86_64-unknown-linux-gnu -O2 -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-FRAME-POINTER-NONE +! RUN: %flang -fno-omit-frame-pointer --target=x86_64-unknown-linux-gnu -O2 -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-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-prefix=CHECK-FRAME-POINTER-NON-LEAF + +! Default behavior in aarch64-none-none, -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-prefix=CHECK-FRAME-POINTER-ALL + +! CHECK-FRAME-POINTER-ALL: "-fc1" +! CHECK-FRAME-POINTER-ALL-SAME: "-mframe-pointer=all" +! CHECK-FRAME-POINTER-NON-LEAF: "-fc1" +! CHECK-FRAME-POINTER-NON-LEAF-SAME: "-mframe-pointer=non-leaf-no-reserve" +! CHECK-FRAME-POINTER-NONE: "-fc1" +! CHECK-FRAME-POINTER-NONE-SAME: "-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 deleted file mode 100644 index 56f23e9e09f4f..0000000000000 --- a/flang/test/Integration/omit-leaf-frame-pointer.f90 +++ /dev/null @@ -1,39 +0,0 @@ -! Test to check the options -momit-leaf-frame-pointer and -mno-omit-leaf-frame-pointer - -! REQUIRES: aarch64-registered-target, x86-registered-target - -! AArch64 differs from x86_64: useLeafFramePointerForTargetByDefault is false, so -fno-omit-frame-pointer alone already gives "non-leaf-no-reserve" on AArch64. - -! RUN: %flang --target=x86_64-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ALL -! 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=CHECK-ALL -! RUN: %flang --target=aarch64-none-none -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-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=CHECK-NONLEAF -! RUN: %flang --target=aarch64-none-none -fno-omit-frame-pointer -momit-leaf-frame-pointer -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-NONLEAF - - -! CHECK-ALL: define void @_QQmain() #[[ATTR:[0-9]+]] -! CHECK-ALL: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}}) #[[ATTR]] -! CHECK-ALL: attributes #[[ATTR]] = {{{.*}}"frame-pointer"="all"{{.*}}} -! CHECK-ALL: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 2} - -! CHECK-NONLEAF: define void @_QQmain() #[[ATTR:[0-9]+]] -! CHECK-NONLEAF: define internal i32 @_QFPleaf(i32 %{{.*}}, i32 %{{.*}}) #[[ATTR]] -! CHECK-NONLEAF: attributes #[[ATTR]] = {{{.*}}"frame-pointer"="non-leaf-no-reserve"{{.*}}} -! CHECK-NONLEAF: !{{[0-9]+}} = !{i32 7, !"frame-pointer", i32 4} - -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 - 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
