https://github.com/xgupta updated 
https://github.com/llvm/llvm-project/pull/223315

>From 947084c95b9e1f0b0e7713760525a48309c1c59d Mon Sep 17 00:00:00 2001
From: Shivam Gupta <[email protected]>
Date: Wed, 2 Sep 2026 08:35:24 +0530
Subject: [PATCH 1/3] [Clang] Add -fno-inline-functions-called-once

GCC provides -fno-inline-functions-called-once to inhibit inlining
of TU-local functions that are called exactly once. Clang currently
accepts the corresponding option only as an ignored GCC optimization flag.

This patch makes the option a real Clang driver option and forwards
it to LLVM as -mllvm -no-inline-functions-called-once. The LLVM
inliner disables the special bonus normally applied to internal
functions with a single call site and assigns the call a
prohibitively high cost, preventing it from being inlined.

As alternative one can use __attribute__((noinline)) but that requires
application changes and not feasible for large codebases.

Rework of #160343.
---
 clang/include/clang/Options/Options.td        |  5 +++-
 clang/lib/Driver/ToolChains/Clang.cpp         |  8 ++++++
 .../no-inline-functions-called-once.cpp       | 27 +++++++++++++++++++
 clang/test/Driver/clang_f_opts.c              |  3 ---
 .../Driver/no-inline-functions-called-once.c  | 13 +++++++++
 llvm/lib/Analysis/InlineCost.cpp              | 17 ++++++++++--
 6 files changed, 67 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/CodeGen/no-inline-functions-called-once.cpp
 create mode 100644 clang/test/Driver/no-inline-functions-called-once.c

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 3b88dce9c822b..34f63855e9dc4 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -7694,7 +7694,10 @@ defm modulo_sched : BooleanFFlag<"modulo-sched">, 
Group<clang_ignored_gcc_optimi
 defm modulo_sched_allow_regmoves : BooleanFFlag<"modulo-sched-allow-regmoves">,
     Group<clang_ignored_gcc_optimization_f_Group>;
 defm inline_functions_called_once : 
BooleanFFlag<"inline-functions-called-once">,
-    Group<clang_ignored_gcc_optimization_f_Group>;
+    Group<f_Group>,
+    Visibility<[ClangOption]>,
+    HelpText<"Control inlining of TU-local functions called exactly once "
+             "(Use -fno-inline-functions-called-once to inhibit it)">;
 def finline_limit_EQ : Joined<["-"], "finline-limit=">, 
Group<clang_ignored_gcc_optimization_f_Group>;
 defm finline_limit : BooleanFFlag<"inline-limit">, 
Group<clang_ignored_gcc_optimization_f_Group>;
 defm inline_small_functions : BooleanFFlag<"inline-small-functions">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 072664e6040f3..fb70f75c83b2d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5414,6 +5414,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
                                                 << TripleStr;
   }
 
+  // Respect the last -f[no-]inline-functions-called-once option.
+  if (!Args.hasFlag(options::OPT_finline_functions_called_once,
+                    options::OPT_fno_inline_functions_called_once,
+                    /*Default=*/true)) {
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back("-no-inline-functions-called-once");
+  }
+
   // Push all default warning arguments that are specific to
   // the given target.  These come before user provided warning options
   // are provided.
diff --git a/clang/test/CodeGen/no-inline-functions-called-once.cpp 
b/clang/test/CodeGen/no-inline-functions-called-once.cpp
new file mode 100644
index 0000000000000..049ec28643f06
--- /dev/null
+++ b/clang/test/CodeGen/no-inline-functions-called-once.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang -O2 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=INLINE
+// RUN: %clang -O2 -S -emit-llvm %s -fno-inline-functions-called-once -o - | 
FileCheck %s --check-prefix=NOINLINE
+
+// INLINE-LABEL: define{{.*}}@main
+// INLINE-NOT: call{{.*}}@_ZL12bad_functionv
+// INLINE: ret void
+
+// NOINLINE-LABEL: define{{.*}}@_ZL4testv
+// NOINLINE: call{{.*}}@_ZL12bad_functionv
+// NOINLINE: ret void
+
+// NOINLINE: define internal{{.*}}@_ZL12bad_functionv
+
+volatile int G;
+
+static void bad_function(void) {
+  G++;
+}
+
+static void test(void) {
+  bad_function();
+}
+
+int main(void) {
+  test();
+  return 0;
+}
diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c
index 5871f1580d6b7..0b29fc5920552 100644
--- a/clang/test/Driver/clang_f_opts.c
+++ b/clang/test/Driver/clang_f_opts.c
@@ -283,7 +283,6 @@
 // RUN:     -fgcse-las                                                        \
 // RUN:     -fgcse-sm                                                         \
 // RUN:     -fipa-cp                                                          \
-// RUN:     -finline-functions-called-once                                    \
 // RUN:     -fmodulo-sched                                                    \
 // RUN:     -fmodulo-sched-allow-regmoves                                     \
 // RUN:     -fpeel-loops                                                      \
@@ -355,7 +354,6 @@
 // RUN: -fgcse-las                                                            \
 // RUN: -fgcse-sm                                                             \
 // RUN: -fipa-cp                                                              \
-// RUN: -finline-functions-called-once                                        \
 // RUN: -fmodulo-sched                                                        \
 // RUN: -fmodulo-sched-allow-regmoves                                         \
 // RUN: -fpeel-loops                                                          \
@@ -414,7 +412,6 @@
 // CHECK-WARNING-DAG: optimization flag '-fgcse-las' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fgcse-sm' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fipa-cp' is not supported
-// CHECK-WARNING-DAG: optimization flag '-finline-functions-called-once' is 
not supported
 // CHECK-WARNING-DAG: optimization flag '-fmodulo-sched' is not supported
 // CHECK-WARNING-DAG: optimization flag '-fmodulo-sched-allow-regmoves' is not 
supported
 // CHECK-WARNING-DAG: optimization flag '-fpeel-loops' is not supported
diff --git a/clang/test/Driver/no-inline-functions-called-once.c 
b/clang/test/Driver/no-inline-functions-called-once.c
new file mode 100644
index 0000000000000..402fdaa11254c
--- /dev/null
+++ b/clang/test/Driver/no-inline-functions-called-once.c
@@ -0,0 +1,13 @@
+// RUN: %clang -### -c %s 2>&1 | FileCheck %s --check-prefix=DEFAULT
+// DEFAULT-NOT: "-no-inline-functions-called-once"
+
+// RUN: %clang -### -c -fno-inline-functions-called-once %s 2>&1 | FileCheck 
%s --check-prefix=DISABLED
+// DISABLED: "-mllvm" "-no-inline-functions-called-once"
+
+// RUN: %clang -### -c -fno-inline-functions-called-once 
-finline-functions-called-once %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=REENABLED
+// REENABLED-NOT: "-no-inline-functions-called-once"
+
+// RUN: %clang -### -c -finline-functions-called-once 
-fno-inline-functions-called-once %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=DISABLED
+// DISABLED: "-mllvm" "-no-inline-functions-called-once"
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index d4f4d937aa06a..8645bee789d4a 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -183,6 +183,11 @@ static cl::opt<bool> InlineAllViableCalls(
     "inline-all-viable-calls", cl::Hidden, cl::init(false),
     cl::desc("Inline all viable calls, even if they exceed the inlining "
              "threshold"));
+
+static cl::opt<bool> NoInlineFunctionsCalledOnce(
+    "no-inline-functions-called-once", cl::Hidden, cl::init(false),
+    cl::desc("Disable inlining of functions with internal linkage that are "
+             "called only once"));
 namespace llvm {
 std::optional<int> getStringFnAttrAsInt(const Attribute &Attr) {
   if (Attr.isValid()) {
@@ -2197,9 +2202,17 @@ void InlineCostCallAnalyzer::updateThreshold(CallBase 
&Call, Function &Callee) {
   // If there is only one call of the function, and it has internal linkage,
   // the cost of inlining it drops dramatically. It may seem odd to update
   // Cost in updateThreshold, but the bonus depends on the logic in this 
method.
+  // When -fno-inline-functions-called-once is enabled, disable this bonus
+  // and instead apply a large cost penalty to prevent inlining of such
+  // functions.
   if (isSoleCallToLocalFunction(Call, F)) {
-    addCost(-LastCallToStaticBonus);
-    StaticBonusApplied = LastCallToStaticBonus;
+    if (NoInlineFunctionsCalledOnce) {
+      addCost(INT_MAX);
+      StaticBonusApplied = 0;
+    } else {
+      addCost(-LastCallToStaticBonus);
+      StaticBonusApplied = LastCallToStaticBonus;
+    }
   }
 }
 

>From 305a1590e7345ae03ab4722318b76d554a802b59 Mon Sep 17 00:00:00 2001
From: Shivam Gupta <[email protected]>
Date: Mon, 14 Sep 2026 16:33:46 +0530
Subject: [PATCH 2/3] fix test cases

---
 clang/test/CodeGen/no-inline-functions-called-once.cpp | 2 +-
 clang/test/Driver/no-inline-functions-called-once.c    | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/CodeGen/no-inline-functions-called-once.cpp 
b/clang/test/CodeGen/no-inline-functions-called-once.cpp
index 049ec28643f06..3867f0a646358 100644
--- a/clang/test/CodeGen/no-inline-functions-called-once.cpp
+++ b/clang/test/CodeGen/no-inline-functions-called-once.cpp
@@ -3,7 +3,7 @@
 
 // INLINE-LABEL: define{{.*}}@main
 // INLINE-NOT: call{{.*}}@_ZL12bad_functionv
-// INLINE: ret void
+// INLINE: ret i32 0
 
 // NOINLINE-LABEL: define{{.*}}@_ZL4testv
 // NOINLINE: call{{.*}}@_ZL12bad_functionv
diff --git a/clang/test/Driver/no-inline-functions-called-once.c 
b/clang/test/Driver/no-inline-functions-called-once.c
index 402fdaa11254c..8c7b286479810 100644
--- a/clang/test/Driver/no-inline-functions-called-once.c
+++ b/clang/test/Driver/no-inline-functions-called-once.c
@@ -2,12 +2,12 @@
 // DEFAULT-NOT: "-no-inline-functions-called-once"
 
 // RUN: %clang -### -c -fno-inline-functions-called-once %s 2>&1 | FileCheck 
%s --check-prefix=DISABLED
-// DISABLED: "-mllvm" "-no-inline-functions-called-once"
+// DISABLED: {{.*}} "-mllvm" "-no-inline-functions-called-once"
 
 // RUN: %clang -### -c -fno-inline-functions-called-once 
-finline-functions-called-once %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=REENABLED
 // REENABLED-NOT: "-no-inline-functions-called-once"
 
 // RUN: %clang -### -c -finline-functions-called-once 
-fno-inline-functions-called-once %s 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=DISABLED
-// DISABLED: "-mllvm" "-no-inline-functions-called-once"
+// RUN:   | FileCheck %s --check-prefix=DISABLED2
+// DISABLED2: {{.*}} "-mllvm" "-no-inline-functions-called-once"

>From 43a34c2a7767cb1e2ac79b764d6083291dc80aae Mon Sep 17 00:00:00 2001
From: Shivam Gupta <[email protected]>
Date: Mon, 14 Sep 2026 19:35:11 +0530
Subject: [PATCH 3/3] fix flang test case

---
 flang/test/Driver/flang-f-opts.f90 | 2 --
 1 file changed, 2 deletions(-)

diff --git a/flang/test/Driver/flang-f-opts.f90 
b/flang/test/Driver/flang-f-opts.f90
index a082545206ea3..ee82fd0e44f23 100644
--- a/flang/test/Driver/flang-f-opts.f90
+++ b/flang/test/Driver/flang-f-opts.f90
@@ -94,7 +94,6 @@
 ! RUN:     -fgcse-las                                                       \
 ! RUN:     -fgcse-sm                                                        \
 ! RUN:     -fipa-cp                                                         \
-! RUN:     -finline-functions-called-once                                   \
 ! RUN:     -fmodulo-sched                                                   \
 ! RUN:     -fmodulo-sched-allow-regmoves                                    \
 ! RUN:     -fpeel-loops                                                     \
@@ -148,7 +147,6 @@
 ! CHECK-WARNING-DAG: optimization flag '-fgcse-las' is not supported
 ! CHECK-WARNING-DAG: optimization flag '-fgcse-sm' is not supported
 ! CHECK-WARNING-DAG: optimization flag '-fipa-cp' is not supported
-! CHECK-WARNING-DAG: optimization flag '-finline-functions-called-once' is not 
supported
 ! CHECK-WARNING-DAG: optimization flag '-fmodulo-sched' is not supported
 ! CHECK-WARNING-DAG: optimization flag '-fmodulo-sched-allow-regmoves' is not 
supported
 ! CHECK-WARNING-DAG: optimization flag '-fpeel-loops' is not supported

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

Reply via email to