[llvm] [Passes][FuncSpec] Move optsize/minsize handling into pass (PR #189952)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 1 05:59:48 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-function-specialization

Author: Nikita Popov (nikic)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/189952.diff


3 Files Affected:

- (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+3-8) 
- (modified) llvm/lib/Transforms/IPO/FunctionSpecialization.cpp (+3) 
- (added) llvm/test/Transforms/FunctionSpecialization/function-specialization-optsize.ll (+39) 


``````````diff
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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/189952


More information about the llvm-commits mailing list