https://github.com/shivaramaarao updated 
https://github.com/llvm/llvm-project/pull/230007

>From 02240de6f933a6ecfcc2e6d05fa933dcb678e402 Mon Sep 17 00:00:00 2001
From: Shivarama Rao <[email protected]>
Date: Sat, 17 Oct 2026 13:38:07 +0530
Subject: [PATCH] [flang] Add -f[no]keep-inline-functions option

Treat definitions marked alwaysinline (!dir$ inlinealways) as the functions 
inlined, and
keep those definitions after they are inlined into every caller. Also
keep the definitions when it has no callers.

Restrict definition retention to the current translation unit, ensuring
that definitions from linked bitcode (BC) files are not preserved.

added testcases to test this functionality.

Assisted by Cursor to generate the testcases.

Fixes #223359

Co-authored-by: Cursor <[email protected]>
---
 clang/include/clang/Options/Options.td        |  2 +-
 clang/lib/Driver/ToolChains/Flang.cpp         | 12 +--
 flang/docs/Directives.md                      | 13 +++
 flang/docs/ReleaseNotes.md                    |  6 ++
 .../include/flang/Frontend/CodeGenOptions.def |  1 +
 flang/include/flang/Lower/LoweringOptions.def |  5 ++
 flang/lib/Frontend/CompilerInvocation.cpp     |  6 ++
 flang/lib/Frontend/FrontendActions.cpp        | 33 ++++++++
 flang/lib/Lower/Bridge.cpp                    | 25 ++++++
 flang/test/Driver/flang-f-opts.f90            | 26 +++++-
 .../Integration/Inputs/keep-inline-lib.f90    |  5 ++
 .../{inputs => Inputs}/pgo-sample.prof        |  0
 .../keep-inline-functions-link.f90            | 29 +++++++
 .../Integration/keep-inline-functions.f90     | 80 +++++++++++++++++++
 flang/test/Integration/profile-sample-use.f90 |  2 +-
 flang/test/Lower/inlinealways-directive.f90   |  8 ++
 16 files changed, 237 insertions(+), 16 deletions(-)
 create mode 100644 flang/test/Integration/Inputs/keep-inline-lib.f90
 rename flang/test/Integration/{inputs => Inputs}/pgo-sample.prof (100%)
 create mode 100644 flang/test/Integration/keep-inline-functions-link.f90
 create mode 100644 flang/test/Integration/keep-inline-functions.f90

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 41afddd0ffe82..1834392a15d90 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2613,7 +2613,7 @@ defm keep_persistent_storage_variables : 
BoolFOption<"keep-persistent-storage-va
           " keeping all variables that have a persistent storage duration, 
including global, static and thread-local variables, to guarantee that they can 
be directly addressed">>;
 defm keep_inline_functions : BoolFOption<"keep-inline-functions",
   CodeGenOpts<"KeepInlineFunctions">, DefaultFalse,
-  PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption], "Keep">,
+  PosFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option], 
"Keep">,
   NegFlag<SetFalse, [], [ClangOption, FlangOption], "Don't keep">,
   BothFlags<[], [],
           " inline functions whose definition is owned by this translation 
unit, even if they are inlined into all callers.">>;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index a13c69a5b2a50..59112b67d74a3 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -357,6 +357,8 @@ void Flang::addCodegenOptions(const ArgList &Args,
 
   Args.addOptInFlag(CmdArgs, options::OPT_fexperimental_loop_fusion,
                     options::OPT_fno_experimental_loop_fusion);
+  Args.addOptInFlag(CmdArgs, options::OPT_fkeep_inline_functions,
+                    options::OPT_fno_keep_inline_functions);
   Args.AddLastArg(CmdArgs, options::OPT_ffp_sum_reassociation,
                   options::OPT_fno_fp_sum_reassociation);
 
@@ -1339,16 +1341,6 @@ void Flang::ConstructJob(Compilation &C, const JobAction 
&JA,
     A->claim();
   }
 
-  // -fkeep-inline-functions/-fno-keep-inline-functions are real Clang options
-  // but are not supported by Flang; warn and ignore them.
-  for (options::ID Opt : {options::OPT_fkeep_inline_functions,
-                          options::OPT_fno_keep_inline_functions}) {
-    if (const Arg *A = Args.getLastArg(Opt)) {
-      D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args);
-      A->claim();
-    }
-  }
-
   const InputInfo &Input = Inputs[0];
   types::ID InputType = Input.getType();
 
diff --git a/flang/docs/Directives.md b/flang/docs/Directives.md
index f2f4078c479a2..6317cc7ec2a96 100644
--- a/flang/docs/Directives.md
+++ b/flang/docs/Directives.md
@@ -154,6 +154,19 @@ contains
     ...
   end function
   ```
+  By default, once an internal procedure has been inlined into every caller,
+  its definition may be removed. Module procedures, including `PRIVATE` ones,
+  and external procedures keep their definitions without the flag. With
+  `-fkeep-inline-functions`, the definition of an internal procedure is kept
+  as well. On ELF targets it is added to `llvm.compiler.used`, so the
+  compiler keeps it but the linker may still discard it; other object formats
+  use `llvm.used`. For a module or external procedure, the flag only adds
+  that reference. Unlike Clang, where the flag applies to all inline
+  functions, in Flang it applies only to procedures that name themselves in
+  `!dir$ inlinealways <name>`. The call-site forms (`!dir$ inline`,
+  `!dir$ forceinline`, and `!dir$ inlinealways` without a name) do not make
+  the callee eligible. A procedure with no callers at all is also kept, at
+  every optimization level, matching Clang.
 * `!dir$ noinline` works in the same way as the `inline` directive, but 
prevents
   any attempt of inlining by the compiler on a function call statement.
 
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index 609ca499da396..ea8a09f5275d1 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -158,6 +158,12 @@ page](https://llvm.org/releases/).
   Both modes fill every storage byte including struct padding.
   PowerPC vector locals (`vector(real(4))` etc.) are not initialized.
 
+- Added `-fkeep-inline-functions` and `-fno-keep-inline-functions`. With
+  `-fkeep-inline-functions`, a procedure marked with
+  `!dir$ inlinealways <name>` keeps its definition, even if it has been
+  inlined into every caller or has no callers at all. Call-site inlining
+  directives do not count. See [Directives](Directives.md) for details.
+
 ## Windows Support
 
 ## Fortran Language Changes in Flang
diff --git a/flang/include/flang/Frontend/CodeGenOptions.def 
b/flang/include/flang/Frontend/CodeGenOptions.def
index 86994f7710576..86006b0f8387b 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.def
+++ b/flang/include/flang/Frontend/CodeGenOptions.def
@@ -30,6 +30,7 @@ ENUM_CODEGENOPT(ProfileInstr, llvm::driver::ProfileInstrKind, 
2, llvm::driver::P
 /// Choose profile kind for PGO use compilation.
 ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, 
llvm::driver::ProfileInstrKind::ProfileNone)
 
+CODEGENOPT(KeepInlineFunctions, 1, 0) ///< -fkeep-inline-functions.
 CODEGENOPT(InstrumentFunctions, 1, 0) ///< Set when -finstrument_functions is
                                       ///< enabled on the compile step.
 CODEGENOPT(DisableTailCalls, 1, 0) ///< Do not emit tail calls
diff --git a/flang/include/flang/Lower/LoweringOptions.def 
b/flang/include/flang/Lower/LoweringOptions.def
index 4590df1c8a6f8..252e847740145 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -114,5 +114,10 @@ ENUM_LOWERINGOPT(InitLocalMode, 
Fortran::lower::InitLocalKind, 3,
 /// -f[no-]openacc-acc-kernels-do-concurrent-independent.
 ENUM_LOWERINGOPT(OpenACCKernelsDoConcurrentIndependent, unsigned, 1, 1)
 
+/// If true, a procedure named in !dir$ inlinealways <name> is marked so that
+/// it survives the MLIR inliner even with no remaining callers.
+/// Controlled by -fkeep-inline-functions. Off by default.
+ENUM_LOWERINGOPT(KeepInlineFunctions, unsigned, 1, 0)
+
 #undef LOWERINGOPT
 #undef ENUM_LOWERINGOPT
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index d4c6b44e11477..e495ea1979bf9 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -384,6 +384,10 @@ static void 
parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
   if (args.hasArg(clang::options::OPT_finstrument_functions))
     opts.InstrumentFunctions = 1;
 
+  // -fkeep-inline-functions. The driver forwards only the positive flag.
+  opts.KeepInlineFunctions =
+      args.hasArg(clang::options::OPT_fkeep_inline_functions);
+
   if (args.hasArg(clang::options::OPT_fno_optimize_sibling_calls))
     opts.DisableTailCalls = 1;
 
@@ -2189,4 +2193,6 @@ void CompilerInvocation::setLoweringOptions() {
     loweringOpts.setComplexDivisionToRuntime(false);
 
   loweringOpts.setFPExceptionTraps(langOptions.FPExceptionTraps);
+
+  loweringOpts.setKeepInlineFunctions(codegenOpts.KeepInlineFunctions);
 }
diff --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 62dd3fb054863..ed5f6202cde9e 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1447,6 +1447,39 @@ void CodeGenAction::executeAction() {
   llvmModule->setTargetTriple(theTriple);
   llvmModule->setDataLayout(theTriple.computeDataLayout(targetOpts.abi));
 
+  // -fkeep-inline-functions: retain definitions of alwaysinline functions
+  // after they have been inlined into every caller. On ELF this uses
+  // llvm.compiler.used so the compiler keeps the definition but the linker may
+  // still drop it. Other object formats use llvm.used. Only functions defined
+  // in this translation unit are considered.
+  //
+  // This covers less than Clang's flag. The function-level alwaysinline
+  // attribute comes only from a named !dir$ inlinealways <name>, so call-site
+  // inlining directives do not count. See flang/docs/Directives.md.
+  //
+  // A procedure that is never called survives up to this point too: without
+  // this flag, the FIR inliner (mlir::createInlinerPass) would otherwise
+  // erase such a procedure as dead code before it ever reaches LLVM IR, which
+  // is too late for the scan below to see it. markCurrentFuncAsAlwaysInline()
+  // in Bridge.cpp protects it from that, by attaching a self-referencing
+  // symbol attribute at the point llvm.always_inline itself is set.
+  if (codeGenOpts.KeepInlineFunctions) {
+    llvm::SmallVector<llvm::GlobalValue *, 8> kept;
+    for (llvm::Function &func : *llvmModule) {
+      if (func.isDeclaration() || func.hasAvailableExternallyLinkage())
+        continue;
+      if (!func.hasFnAttribute(llvm::Attribute::AlwaysInline))
+        continue;
+      kept.push_back(&func);
+    }
+    if (!kept.empty()) {
+      if (theTriple.isOSBinFormatELF())
+        llvm::appendToCompilerUsed(*llvmModule, kept);
+      else
+        llvm::appendToUsed(*llvmModule, kept);
+    }
+  }
+
   // Link in builtin bitcode libraries
   if (!codeGenOpts.BuiltinBCLibs.empty())
     linkBuiltinBCLibs();
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 7d25d89d3b0ab..f5dba9533bc28 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -3720,6 +3720,31 @@ class FirConverter : public 
Fortran::lower::AbstractConverter {
           currentFunctionUnit->getSubprogramSymbol().name().ToString();
       if (dir.v.value().ToString() == symName) {
         func->setAttr("llvm.always_inline", builder->getUnitAttr());
+        if (getLoweringOptions().getKeepInlineFunctions()) {
+          // With -fkeep-inline-functions, this procedure must survive even if
+          // it ends up with no callers. That is normally checked much later,
+          // in CodeGenAction::executeAction(), by scanning the generated LLVM
+          // IR, but that scan is too late for a procedure that is never
+          // called: the FIR inliner pass (mlir::createInlinerPass) treats any
+          // discardable (non-public) procedure with zero remaining symbol
+          // uses as dead and erases it once it is done inlining, and it does
+          // this regardless of -fkeep-inline-functions and even at -O0. A
+          // procedure with no callers has zero uses before that pass even
+          // starts, so it would be gone long before the later scan has a
+          // chance to see it.
+          //
+          // Attaching a self-referencing symbol attribute here protects it:
+          // the inliner's own use analysis scans every operation's attribute
+          // dictionary for symbol references, exactly as it would for a real
+          // call, so the procedure is never considered dead. Unlike an SSA
+          // value (e.g. a dead, self-referencing func.constant), a plain
+          // attribute is not touched by dead-code elimination, so it survives
+          // the many canonicalization and simplification passes that run
+          // between here and the inliner, including the inliner's own
+          // internal per-SCC canonicalizer.
+          func->setAttr("flang.keep_inline_functions_ref",
+                        mlir::SymbolRefAttr::get(func));
+        }
       }
     }
   }
diff --git a/flang/test/Driver/flang-f-opts.f90 
b/flang/test/Driver/flang-f-opts.f90
index a082545206ea3..14037460cf413 100644
--- a/flang/test/Driver/flang-f-opts.f90
+++ b/flang/test/Driver/flang-f-opts.f90
@@ -59,6 +59,28 @@
 ! UNKNOWN-NO-SUGGEST: error: unknown argument: '-not-an-option'{{$}}
 !
 ! 
------------------------------------------------------------------------------
+! -fkeep-inline-functions and -fno-keep-inline-functions are implemented by 
Flang, so
+! using them must not produce the "optimization flag ... is not supported" 
warning, or
+! any other warning. -fno-keep-inline-functions is the default. The driver 
forwards only
+! the last occurrence of -fkeep-inline-functions to fc1, if that flag happens 
to be the
+! final one specified.
+!
+!
+! RUN: %flang -### -fkeep-inline-functions %s 2>&1 | FileCheck %s 
--check-prefix=DRIVER-KEEP
+! RUN: %flang -### %s 2>&1 | FileCheck %s --check-prefix=DRIVER-NOKEEP
+! RUN: %flang -### -fno-keep-inline-functions %s 2>&1 | FileCheck %s 
--check-prefix=DRIVER-NOKEEP
+! RUN: %flang -### -fkeep-inline-functions -fno-keep-inline-functions %s 2>&1 
| FileCheck %s --check-prefix=DRIVER-NOKEEP
+! RUN: %flang -### -fno-keep-inline-functions -fkeep-inline-functions %s 2>&1 
| FileCheck %s --check-prefix=DRIVER-KEEP
+
+! DRIVER-KEEP-NOT: warning:
+! DRIVER-KEEP: "-fc1"
+! DRIVER-KEEP-SAME: "-fkeep-inline-functions"
+
+! DRIVER-NOKEEP-NOT: warning:
+! DRIVER-NOKEEP: "-fc1"
+! DRIVER-NOKEEP-NOT: "-fkeep-inline-functions"
+!
+! 
------------------------------------------------------------------------------
 ! The options in the command below are gfortran-specific optimization flags 
that
 ! are accepted by flang's driver but ignored. Check that the correct warning
 ! message is displayed when these are used.
@@ -68,8 +90,6 @@
 ! RUN:     -fexpensive-optimizations                                        \
 ! RUN:     -fno-expensive-optimizations                                     \
 ! RUN:     -fno-defer-pop                                                   \
-! RUN:     -fkeep-inline-functions                                          \
-! RUN:     -fno-keep-inline-functions                                       \
 ! RUN:     -freorder-blocks                                                 \
 ! RUN:     -ffloat-store                                                    \
 ! RUN:     -fgcse                                                           \
@@ -122,8 +142,6 @@
 ! CHECK-WARNING-DAG: optimization flag '-fexpensive-optimizations' is not 
supported
 ! CHECK-WARNING-DAG: optimization flag '-fno-expensive-optimizations' is not 
supported
 ! CHECK-WARNING-DAG: optimization flag '-fno-defer-pop' is not supported
-! CHECK-WARNING-DAG: optimization flag '-fkeep-inline-functions' is not 
supported
-! CHECK-WARNING-DAG: optimization flag '-fno-keep-inline-functions' is not 
supported
 ! CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported
 ! CHECK-WARNING-DAG: optimization flag '-ffloat-store' is not supported
 ! CHECK-WARNING-DAG: optimization flag '-fgcse' is not supported
diff --git a/flang/test/Integration/Inputs/keep-inline-lib.f90 
b/flang/test/Integration/Inputs/keep-inline-lib.f90
new file mode 100644
index 0000000000000..6bdd17faf26f5
--- /dev/null
+++ b/flang/test/Integration/Inputs/keep-inline-lib.f90
@@ -0,0 +1,5 @@
+integer function lib_add_two(n)
+  !dir$ inlinealways lib_add_two
+  integer :: n
+  lib_add_two = n + 2
+end function
diff --git a/flang/test/Integration/inputs/pgo-sample.prof 
b/flang/test/Integration/Inputs/pgo-sample.prof
similarity index 100%
rename from flang/test/Integration/inputs/pgo-sample.prof
rename to flang/test/Integration/Inputs/pgo-sample.prof
diff --git a/flang/test/Integration/keep-inline-functions-link.f90 
b/flang/test/Integration/keep-inline-functions-link.f90
new file mode 100644
index 0000000000000..ebe47cfd79cc2
--- /dev/null
+++ b/flang/test/Integration/keep-inline-functions-link.f90
@@ -0,0 +1,29 @@
+! -fkeep-inline-functions must only record alwaysinline definitions that
+! belong to this translation unit. A builtin bitcode library brought in via
+! -mlink-builtin-bitcode can itself contain an alwaysinline function (for
+! its own, unrelated reasons); that function was never named by a
+! !DIR$ INLINEALWAYS in this file and must not be added to llvm.used /
+! llvm.compiler.used because of this flag. This requires the check to run
+! before the builtin bitcode library is linked into the module.
+
+! RUN: %flang -emit-llvm -c -o %t.bc %S/Inputs/keep-inline-lib.f90
+! RUN: %flang_fc1 -emit-llvm -O2 -fkeep-inline-functions 
-mlink-builtin-bitcode %t.bc -o - %s | FileCheck %s
+
+program main
+  external lib_add_two
+  integer :: lib_add_two
+  integer :: n
+  n = lib_add_two(5)
+  n = own_add_three(n)
+  print *, n
+contains
+  integer function own_add_three(n)
+    !dir$ inlinealways own_add_three
+    integer :: n
+    own_add_three = n + 3
+  end function
+end program
+
+! The list has exactly one entry: this translation unit's own
+! own_add_three, and not the linked library's lib_add_two.
+! CHECK: @llvm.{{(compiler.)?}}used = appending global [1 x ptr] [ptr 
@_QFPown_add_three]
diff --git a/flang/test/Integration/keep-inline-functions.f90 
b/flang/test/Integration/keep-inline-functions.f90
new file mode 100644
index 0000000000000..ed60ab2898e33
--- /dev/null
+++ b/flang/test/Integration/keep-inline-functions.f90
@@ -0,0 +1,80 @@
+! The driver-only checks (-### forwarding, no warning) live in
+! flang/test/Driver/flang-f-opts.f90; this file checks the generated IR.
+
+! Without the flag, an alwaysinline contained procedure is inlined and deleted.
+! RUN: %flang_fc1 -emit-llvm -O2 -o - %s | FileCheck %s --check-prefix=DEFAULT 
\
+! RUN:     --implicit-check-not="@_QFtest_alwaysPadd_two("
+! -fkeep-inline-functions retains that definition, matching Clang's retention
+! of inline functions owned by this translation unit.
+! RUN: %flang_fc1 -emit-llvm -O2 -fkeep-inline-functions -o - %s | FileCheck 
%s --check-prefix=KEEP \
+! RUN:     --implicit-check-not="@_QFtest_plainPadd_one("
+
+! A procedure that is never called is still kept, and at every optimization
+! level: the FIR inliner pass runs even at -O0 and would otherwise erase an
+! uncalled procedure as dead code before it ever reaches LLVM IR, which is too
+! late for the scan below to see it.
+! RUN: %flang_fc1 -emit-llvm -O0 -o - %s | FileCheck %s 
--check-prefix=UNUSED-DEFAULT \
+! RUN:     --implicit-check-not="@_QFtest_neverPunused("
+! RUN: %flang_fc1 -emit-llvm -O0 -fkeep-inline-functions -o - %s | FileCheck 
%s --check-prefix=UNUSED-KEEP
+! RUN: %flang_fc1 -emit-llvm -O2 -fkeep-inline-functions -o - %s | FileCheck 
%s --check-prefix=UNUSED-KEEP
+
+! Check retention immediately after the FIR inliner, before LLVM IR
+! translation. This needs the driver to forward MLIR diagnostic options.
+! RUN: %flang -S -O0 -mmlir --mlir-disable-threading \
+! RUN:     -mmlir --mlir-print-ir-after=inline %s -o /dev/null 2>&1 | \
+! RUN:     FileCheck %s --check-prefix=MLIR-DEFAULT \
+! RUN:     --implicit-check-not="@_QFtest_neverPunused"
+! RUN: %flang -S -O0 -fkeep-inline-functions -mmlir --mlir-disable-threading \
+! RUN:     -mmlir --mlir-print-ir-after=inline %s -o /dev/null 2>&1 | \
+! RUN:     FileCheck %s --check-prefix=MLIR-KEEP
+
+subroutine test_always(n)
+  integer :: n
+  n = add_two(n)
+contains
+  integer function add_two(n)
+    !dir$ inlinealways add_two
+    integer :: n
+    add_two = n + 2
+  end function
+end subroutine
+
+subroutine test_plain(n)
+  integer :: n
+  n = add_one(n)
+contains
+  integer function add_one(n)
+    integer :: n
+    add_one = n + 1
+  end function
+end subroutine
+
+subroutine test_never(n)
+  integer :: n
+  n = n + 1
+contains
+  integer function unused(k)
+    !dir$ inlinealways unused
+    integer :: k
+    unused = k - 1
+  end function
+end subroutine
+
+! DEFAULT-LABEL: define void @test_always_(
+
+! KEEP: @llvm.{{(compiler.)?}}used = {{.*}}@_QFtest_alwaysPadd_two
+! KEEP-LABEL: define void @test_always_(
+! KEEP-NOT: call {{.*}}@_QFtest_alwaysPadd_two(
+! KEEP: define internal {{.*}}@_QFtest_alwaysPadd_two(
+! A contained procedure that is not marked inline is still deleted.
+! KEEP-LABEL: define void @test_plain_(
+
+! UNUSED-DEFAULT-LABEL: define void @test_never_(
+
+! UNUSED-KEEP: @llvm.{{(compiler.)?}}used = {{.*}}@_QFtest_neverPunused
+! UNUSED-KEEP-LABEL: define void @test_never_(
+! UNUSED-KEEP: define internal {{.*}}@_QFtest_neverPunused(
+
+! MLIR-DEFAULT-LABEL: IR Dump After InlinerPass:
+! MLIR-KEEP-LABEL: IR Dump After InlinerPass:
+! MLIR-KEEP: func.func private @_QFtest_neverPunused{{.*}}attributes 
{{.*}}flang.keep_inline_functions_ref = 
@_QFtest_neverPunused{{.*}}llvm.always_inline
diff --git a/flang/test/Integration/profile-sample-use.f90 
b/flang/test/Integration/profile-sample-use.f90
index 6292ef817077c..8c377eca2ba9d 100644
--- a/flang/test/Integration/profile-sample-use.f90
+++ b/flang/test/Integration/profile-sample-use.f90
@@ -1,5 +1,5 @@
 ! Test to check the working of option "-fprofile-sample-use".
-! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone 
-fprofile-sample-use=%S/inputs/pgo-sample.prof -o - %s | FileCheck %s
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone 
-fprofile-sample-use=%S/Inputs/pgo-sample.prof -o - %s | FileCheck %s
 
 ! CHECK: attributes #[[A:.*]] = { {{.*}}"use-sample-profile"{{.*}} }
 ! CHECK: !{i32 {{.*}}, !"ProfileSummary"{{.*}}}
diff --git a/flang/test/Lower/inlinealways-directive.f90 
b/flang/test/Lower/inlinealways-directive.f90
index 4848fd9ec4864..0aa3f55f09a25 100644
--- a/flang/test/Lower/inlinealways-directive.f90
+++ b/flang/test/Lower/inlinealways-directive.f90
@@ -1,16 +1,24 @@
 ! Check the appropriate flags are added to inline functions when inlinealways 
is used, or ignored when the name is incorrect.
 
 ! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+! -fkeep-inline-functions additionally attaches a self-referencing symbol
+! attribute to a named INLINEALWAYS procedure, so it still has a use once the
+! MLIR inliner runs even with no callers left; see 
markCurrentFuncAsAlwaysInline()
+! in Bridge.cpp and flang/test/Integration/keep-inline-functions.f90 for
+! the end-to-end behavior.
+! RUN: %flang_fc1 -emit-hlfir -fkeep-inline-functions %s -o - | FileCheck %s 
--check-prefix=KEEP
 
 subroutine test_subroutine()
   !DIR$ INLINEALWAYS test_subroutine
 end subroutine
 ! CHECK: func.func @_QPtest_subroutine() attributes {llvm.always_inline} {
+! KEEP: func.func @_QPtest_subroutine() attributes 
{flang.keep_inline_functions_ref = @_QPtest_subroutine, llvm.always_inline} {
 
 subroutine test_subroutine2()
   !DIR$ INLINEALWAYS wrong_subroutine
 end subroutine
 ! CHECK: func.func @_QPtest_subroutine2() {
+! KEEP: func.func @_QPtest_subroutine2() {
 
 subroutine test_subroutine3()
 end subroutine

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to