[llvm] [Passes][Inliner] Handle optsize/minsize via attributes only (PR #190168)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 06:10:31 PDT 2026


https://github.com/nikic created https://github.com/llvm/llvm-project/pull/190168

InlineParams already has separate threshold for OptSize/MinSize functions that get applied based on the corresponding function attributes. As such, we should not also be changing the DefaultThreshold based on the pipeline Os/Oz levels as well.

>From 923e974740cccc631ec39d003aebe7b43386b44d Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 2 Apr 2026 14:50:50 +0200
Subject: [PATCH] [Passes][Inliner] Handle optsize/minsize via attributes only

InlineParams already has separate threshold for OptSize/MinSize
functions that get applied based on the corresponding function
attributes. As such, we should not also be changing the
DefaultThreshold based on the pipeline Os/Oz levels as well.
---
 llvm/include/llvm/Analysis/InlineCost.h        |  8 ++++----
 llvm/lib/Analysis/InlineCost.cpp               | 18 +++---------------
 llvm/lib/Passes/PassBuilderPipelines.cpp       | 14 +++++++-------
 .../Transforms/Inline/ML/Inputs/test-module.ll | 10 +++++-----
 .../Transforms/Inline/ML/interactive-mode.ll   |  2 +-
 .../Inline/always-inline-phase-ordering.ll     | 18 +++++++++---------
 .../PluginInlineAdvisorAnalysisTest.cpp        |  2 +-
 .../Analysis/PluginInlineOrderAnalysisTest.cpp |  2 +-
 8 files changed, 31 insertions(+), 43 deletions(-)

diff --git a/llvm/include/llvm/Analysis/InlineCost.h b/llvm/include/llvm/Analysis/InlineCost.h
index ae86f353f16d9..4bc89bc83b658 100644
--- a/llvm/include/llvm/Analysis/InlineCost.h
+++ b/llvm/include/llvm/Analysis/InlineCost.h
@@ -254,11 +254,11 @@ LLVM_ABI InlineParams getInlineParams(int Threshold);
 
 /// Generate the parameters to tune the inline cost analysis based on command
 /// line options. If -inline-threshold option is not explicitly passed,
-/// the default threshold is computed from \p OptLevel and \p SizeOptLevel.
+/// the default threshold is computed from \p OptLevel.
 /// An \p OptLevel value above 3 is considered an aggressive optimization mode.
-/// \p SizeOptLevel of 1 corresponds to the -Os flag and 2 corresponds to
-/// the -Oz flag.
-LLVM_ABI InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
+/// Optimization for size is handled via separate thresholds for
+/// optsize/minsize, rather than changes to the default threshold.
+LLVM_ABI InlineParams getInlineParamsFromOptLevel(unsigned OptLevel);
 
 /// Return the cost associated with a callsite, including parameter passing
 /// and the call/return instruction.
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index f0ce00b24704f..850c9cf5a1eb8 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -3432,22 +3432,10 @@ InlineParams llvm::getInlineParams() {
   return getInlineParams(DefaultThreshold);
 }
 
-// Compute the default threshold for inlining based on the opt level and the
-// size opt level.
-static int computeThresholdFromOptLevels(unsigned OptLevel,
-                                         unsigned SizeOptLevel) {
-  if (OptLevel > 2)
-    return InlineConstants::OptAggressiveThreshold;
-  if (SizeOptLevel == 1) // -Os
-    return InlineConstants::OptSizeThreshold;
-  if (SizeOptLevel == 2) // -Oz
-    return InlineConstants::OptMinSizeThreshold;
-  return DefaultThreshold;
-}
-
-InlineParams llvm::getInlineParams(unsigned OptLevel, unsigned SizeOptLevel) {
+InlineParams llvm::getInlineParamsFromOptLevel(unsigned OptLevel) {
   auto Params =
-      getInlineParams(computeThresholdFromOptLevels(OptLevel, SizeOptLevel));
+      getInlineParams(OptLevel > 2 ? InlineConstants::OptAggressiveThreshold
+                                   : DefaultThreshold);
   // At O3, use the value of -locally-hot-callsite-threshold option to populate
   // Params.LocallyHotCallSiteThreshold. Below O3, this flag has effect only
   // when it is specified explicitly.
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 255dfa8e4e9c6..b48ea6f4656a8 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -925,7 +925,7 @@ void PassBuilder::addPGOInstrPassesForO0(ModulePassManager &MPM,
 }
 
 static InlineParams getInlineParamsFromOptLevel(OptimizationLevel Level) {
-  return getInlineParams(Level.getSpeedupLevel(), Level.getSizeLevel());
+  return getInlineParamsFromOptLevel(Level.getSpeedupLevel());
 }
 
 ModuleInlinerWrapperPass
@@ -933,7 +933,7 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level,
                                   ThinOrFullLTOPhase Phase) {
   InlineParams IP;
   if (PTO.InlinerThreshold == -1)
-    IP = getInlineParamsFromOptLevel(Level);
+    IP = ::getInlineParamsFromOptLevel(Level);
   else
     IP = getInlineParams(PTO.InlinerThreshold);
   // For PreLinkThinLTO + SamplePGO or PreLinkFullLTO + SamplePGO,
@@ -1034,7 +1034,7 @@ PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level,
                                         ThinOrFullLTOPhase Phase) {
   ModulePassManager MPM;
 
-  InlineParams IP = getInlineParamsFromOptLevel(Level);
+  InlineParams IP = ::getInlineParamsFromOptLevel(Level);
   // For PreLinkThinLTO + SamplePGO or PreLinkFullLTO + SamplePGO,
   // set hot-caller threshold to 0 to disable hot
   // callsite inline (as much as possible [1]) because it makes
@@ -1691,12 +1691,12 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
     // devirtualization depends on the passes optimizing/eliminating vtable GVs
     // and those passes are only effective after inlining.
     if (EnableModuleInliner) {
-      MPM.addPass(ModuleInlinerPass(getInlineParamsFromOptLevel(Level),
+      MPM.addPass(ModuleInlinerPass(::getInlineParamsFromOptLevel(Level),
                                     UseInlineAdvisor,
                                     ThinOrFullLTOPhase::None));
     } else {
       MPM.addPass(ModuleInlinerWrapperPass(
-          getInlineParamsFromOptLevel(Level),
+          ::getInlineParamsFromOptLevel(Level),
           /* MandatoryFirst */ true,
           InlineContext{ThinOrFullLTOPhase::None, InlinePass::CGSCCInliner}));
     }
@@ -2110,12 +2110,12 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
   // invoke or a call.
   // Run the inliner now.
   if (EnableModuleInliner) {
-    MPM.addPass(ModuleInlinerPass(getInlineParamsFromOptLevel(Level),
+    MPM.addPass(ModuleInlinerPass(::getInlineParamsFromOptLevel(Level),
                                   UseInlineAdvisor,
                                   ThinOrFullLTOPhase::FullLTOPostLink));
   } else {
     MPM.addPass(ModuleInlinerWrapperPass(
-        getInlineParamsFromOptLevel(Level),
+        ::getInlineParamsFromOptLevel(Level),
         /* MandatoryFirst */ true,
         InlineContext{ThinOrFullLTOPhase::FullLTOPostLink,
                       InlinePass::CGSCCInliner}));
diff --git a/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll b/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll
index 005731fc18429..c73e4ac62ae46 100644
--- a/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll
+++ b/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll
@@ -3,7 +3,7 @@ target triple = "x86_64-grtev4-linux-gnu"
 
 declare void @external_fct(i32)
 
-define dso_local i32 @top() {
+define dso_local i32 @top() minsize {
   %a = call i32 @multiplier(i32 5)
   %b = call i32 @adder(i32 10)
   %ret = add nsw i32 %a, %b
@@ -11,7 +11,7 @@ define dso_local i32 @top() {
   ret i32 %ret
 }
 
-define internal dso_local i32 @adder(i32) {
+define internal dso_local i32 @adder(i32) minsize {
   %2 = alloca i32, align 4
   store i32 %0, ptr %2, align 4
   %3 = load i32, ptr %2, align 4
@@ -22,7 +22,7 @@ define internal dso_local i32 @adder(i32) {
   ret i32 %7
 }
 
-define internal i32 @multiplier(i32) {
+define internal i32 @multiplier(i32) minsize {
   %2 = alloca i32, align 4
   store i32 %0, ptr %2, align 4
   %3 = load i32, ptr %2, align 4
@@ -31,7 +31,7 @@ define internal i32 @multiplier(i32) {
   ret i32 %5
 }
 
-define i32 @switcher(i32) {
+define i32 @switcher(i32) minsize {
   %2 = alloca i32, align 4
   %3 = alloca i32, align 4
   store i32 %0, ptr %3, align 4
@@ -65,4 +65,4 @@ define i32 @switcher(i32) {
 
 ; CHECK-NOT: @adder
 ; DEFAULT-LABEL:        @adder
-; DEFAULT-NEXT:         %2 = mul
\ No newline at end of file
+; DEFAULT-NEXT:         %2 = mul
diff --git a/llvm/test/Transforms/Inline/ML/interactive-mode.ll b/llvm/test/Transforms/Inline/ML/interactive-mode.ll
index 28f87049b21db..fd7a85dce27ed 100644
--- a/llvm/test/Transforms/Inline/ML/interactive-mode.ll
+++ b/llvm/test/Transforms/Inline/ML/interactive-mode.ll
@@ -34,7 +34,7 @@
 ; CHECK:      observation: 4
 ; CHECK-DEFAULT: inlining_default: 1
 ; CHECK:      observation: 5
-; CHECK-DEFAULT: inlining_default: 1
+; CHECK-DEFAULT: inlining_default: 0
 
 ; CHECK:      inlining_decision: 1
 ; CHECK-NEXT: inlining_decision: 0
diff --git a/llvm/test/Transforms/Inline/always-inline-phase-ordering.ll b/llvm/test/Transforms/Inline/always-inline-phase-ordering.ll
index defd1f4fd426b..1815132bf419d 100644
--- a/llvm/test/Transforms/Inline/always-inline-phase-ordering.ll
+++ b/llvm/test/Transforms/Inline/always-inline-phase-ordering.ll
@@ -36,13 +36,13 @@ bb:
   ret void
 }
 
-define linkonce_odr void @widget() {
+define linkonce_odr void @widget() optsize {
 bb:
   call void @wibble.1()
   ret void
 }
 
-define linkonce_odr void @wibble.1() {
+define linkonce_odr void @wibble.1() optsize {
 bb:
   %0 = call i32 @foo.2()
   call void @blam()
@@ -51,7 +51,7 @@ bb:
 
 declare i32 @foo.2()
 
-define linkonce_odr void @blam() {
+define linkonce_odr void @blam() optsize {
 bb:
   %tmp = call i32 @snork()
   %tmpv1 = call ptr @wombat.3()
@@ -73,7 +73,7 @@ declare void @eggs()
 
 declare ptr @wombat.3()
 
-define linkonce_odr i32 @spam() {
+define linkonce_odr i32 @spam() optsize {
 bb:
   %tmpv1 = call i32 @wombat.6()
   %tmpv2 = call i64 @wobble.5(i8 0)
@@ -104,22 +104,22 @@ declare i32 @wombat.6()
 
 declare i64 @eggs.7()
 
-define linkonce_odr void @barney() {
+define linkonce_odr void @barney() optsize {
 bb:
   call void @bar.8()
   call void @pluto()
   unreachable
 }
 
-define linkonce_odr void @bar.8() {
+define linkonce_odr void @bar.8() optsize {
 bb:
   call void @wibble()
   ret void
 }
 
-attributes #0 = { "frame-pointer"="non-leaf" }
-attributes #1 = { "target-cpu"="apple-m1" }
-attributes #2 = { alwaysinline }
+attributes #0 = { optsize "frame-pointer"="non-leaf" }
+attributes #1 = { optsize "target-cpu"="apple-m1" }
+attributes #2 = { optsize alwaysinline }
 
 !llvm.module.flags = !{!0, !1, !30, !31, !32, !36, !37}
 
diff --git a/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp b/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp
index aaafaabe773eb..61ab1820373c3 100644
--- a/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp
+++ b/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp
@@ -75,7 +75,7 @@ struct CompilerInstance {
   }
 
   CompilerInstance() {
-    IP = getInlineParams(3, 0);
+    IP = getInlineParamsFromOptLevel(3);
     PB.registerModuleAnalyses(MAM);
     PB.registerCGSCCAnalyses(CGAM);
     PB.registerFunctionAnalyses(FAM);
diff --git a/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp b/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp
index 48f7bb0117a0d..e9e839904a2e6 100644
--- a/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp
+++ b/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp
@@ -51,7 +51,7 @@ struct CompilerInstance {
   }
 
   CompilerInstance() {
-    IP = getInlineParams(3, 0);
+    IP = getInlineParamsFromOptLevel(3);
     PB.registerModuleAnalyses(MAM);
     PB.registerCGSCCAnalyses(CGAM);
     PB.registerFunctionAnalyses(FAM);



More information about the llvm-commits mailing list