[llvm] [Passes][FuncSpec] Move optsize/minsize handling into pass (PR #189952)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 1 05:59:16 PDT 2026
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/189952
Instead of using the Os/Oz level during pass pipeline construction, query the optsize/minsize attribute on the function to determine whether specialization is allowed to take place. This ensures consistent behavior for per-function attributes.
It's worth noting that FuncSpec *already* checks for minsize, but at the call-site level.
>From 409fdae8a87a0bcf656b8848da5a05b3f3e3a249 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 1 Apr 2026 14:53:46 +0200
Subject: [PATCH] [Passes][FuncSpec] Move optsize/minsize handling into pass
Instead of using the Os/Oz level during pass pipeline construction,
query the optsize/minsize attribute on the function to determine
whether specialization is allowed to take place. This ensures
consistent behavior for per-function attributes.
It's worth noting that FuncSpec *already* checks for minsize, but
at the call-site level.
---
llvm/lib/Passes/PassBuilderPipelines.cpp | 11 ++----
.../Transforms/IPO/FunctionSpecialization.cpp | 3 ++
.../function-specialization-optsize.ll | 39 +++++++++++++++++++
3 files changed, 45 insertions(+), 8 deletions(-)
create mode 100644 llvm/test/Transforms/FunctionSpecialization/function-specialization-optsize.ll
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 6f5b1c2e2fcc7..5ce71899f34ab 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -1192,11 +1192,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
// and prior to optimizing globals.
// FIXME: This position in the pipeline hasn't been carefully considered in
// years, it should be re-analyzed.
- MPM.addPass(IPSCCPPass(
- IPSCCPOptions(/*AllowFuncSpec=*/
- Level != OptimizationLevel::Os &&
- Level != OptimizationLevel::Oz &&
- !isLTOPreLink(Phase))));
+ MPM.addPass(
+ IPSCCPPass(IPSCCPOptions(/*AllowFuncSpec=*/!isLTOPreLink(Phase))));
// Attach metadata to indirect call sites indicating the set of functions
// they may target at run-time. This should follow IPSCCP.
@@ -2032,9 +2029,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
// Propagate constants at call sites into the functions they call. This
// opens opportunities for globalopt (and inlining) by substituting function
// pointers passed as arguments to direct uses of functions.
- MPM.addPass(IPSCCPPass(IPSCCPOptions(/*AllowFuncSpec=*/
- Level != OptimizationLevel::Os &&
- Level != OptimizationLevel::Oz)));
+ MPM.addPass(IPSCCPPass(IPSCCPOptions(/*AllowFuncSpec=*/true)));
// Attach metadata to indirect call sites indicating the set of functions
// they may target at run-time. This should follow IPSCCP.
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index cd914db8434ef..1367940ad8ef8 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -1044,6 +1044,9 @@ bool FunctionSpecializer::isCandidateFunction(Function *F) {
if (F->hasFnAttribute(Attribute::NoDuplicate))
return false;
+ if (F->hasOptSize())
+ return false;
+
// Do not specialize the cloned function again.
if (Specializations.contains(F))
return false;
diff --git a/llvm/test/Transforms/FunctionSpecialization/function-specialization-optsize.ll b/llvm/test/Transforms/FunctionSpecialization/function-specialization-optsize.ll
new file mode 100644
index 0000000000000..9a2be2865428a
--- /dev/null
+++ b/llvm/test/Transforms/FunctionSpecialization/function-specialization-optsize.ll
@@ -0,0 +1,39 @@
+; RUN: opt -passes="ipsccp<func-spec>" -S < %s | FileCheck %s
+
+; CHECK-NOT: @compute.specialized.1
+; CHECK-NOT: @compute.specialized.2
+
+define i64 @main(i64 %x, i1 %flag) {
+entry:
+ br i1 %flag, label %plus, label %minus
+
+plus:
+ %tmp0 = call i64 @compute(i64 %x, ptr @plus)
+ br label %merge
+
+minus:
+ %tmp1 = call i64 @compute(i64 %x, ptr @minus)
+ br label %merge
+
+merge:
+ %tmp2 = phi i64 [ %tmp0, %plus ], [ %tmp1, %minus]
+ ret i64 %tmp2
+}
+
+define internal i64 @compute(i64 %x, ptr %binop) optsize {
+entry:
+ %tmp0 = call i64 %binop(i64 %x)
+ ret i64 %tmp0
+}
+
+define internal i64 @plus(i64 %x) {
+entry:
+ %tmp0 = add i64 %x, 1
+ ret i64 %tmp0
+}
+
+define internal i64 @minus(i64 %x) {
+entry:
+ %tmp0 = sub i64 %x, 1
+ ret i64 %tmp0
+}
More information about the llvm-commits
mailing list