[llvm] CallSiteSplitting: Replace -callsite-splitting-duplication-threshold cl::opt with pass parameter (PR #223479)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 10:57:29 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/223479
Migrate the pass-specific command-line option to a new pass manager
pass parameter, exposed as callsite-splitting<duplication-threshold=N>.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
>From 70235c38a8e1cca0f7e0a9fda90a17a25965f8a6 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 14 Sep 2026 16:48:30 +0200
Subject: [PATCH] CallSiteSplitting: Replace
-callsite-splitting-duplication-threshold cl::opt with pass parameter
Migrate the pass-specific command-line option to a new pass manager
pass parameter, exposed as callsite-splitting<duplication-threshold=N>.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
.../Transforms/Scalar/CallSiteSplitting.h | 15 +++++++-
llvm/lib/Passes/PassBuilder.cpp | 24 +++++++++++++
llvm/lib/Passes/PassRegistry.def | 7 +++-
.../Transforms/Scalar/CallSiteSplitting.cpp | 34 ++++++++++---------
llvm/test/Other/new-pm-print-pipeline.ll | 3 ++
.../callsite-instructions-before-call.ll | 2 +-
.../CallSiteSplitting/convergent.ll | 2 +-
.../CallSiteSplitting/noduplicate.ll | 2 +-
.../pass-param-parse-errors.ll | 7 ++++
9 files changed, 75 insertions(+), 21 deletions(-)
create mode 100644 llvm/test/Transforms/CallSiteSplitting/pass-param-parse-errors.ll
diff --git a/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h b/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h
index d1c47614656c5..56d318011dc26 100644
--- a/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h
+++ b/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h
@@ -15,9 +15,22 @@ namespace llvm {
class Function;
-struct CallSiteSplittingPass : OptionalPassInfoMixin<CallSiteSplittingPass> {
+class CallSiteSplittingPass
+ : public OptionalPassInfoMixin<CallSiteSplittingPass> {
+ /// Only allow instructions before a call, if their cost is below
+ /// DuplicationThreshold.
+ const unsigned DuplicationThreshold;
+
+public:
+ CallSiteSplittingPass(unsigned DuplicationThreshold = 5)
+ : DuplicationThreshold(DuplicationThreshold) {}
+
/// Run the pass over the function.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+ LLVM_ABI void
+ printPipeline(raw_ostream &OS,
+ function_ref<StringRef(StringRef)> MapClassName2PassName);
};
} // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 725ce2d589a31..1a72515fe4025 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -898,6 +898,30 @@ Expected<bool> parseInstCountOptions(StringRef Params) {
return PassBuilder::parseSinglePassOption(Params, "pre-opt", "InstCountPass");
}
+Expected<unsigned> parseCallSiteSplittingOptions(StringRef Params) {
+ unsigned DuplicationThreshold = 5;
+ while (!Params.empty()) {
+ StringRef ParamName;
+ std::tie(ParamName, Params) = Params.split(';');
+
+ if (ParamName.consume_front("duplication-threshold=")) {
+ if (ParamName.getAsInteger(0, DuplicationThreshold))
+ return make_error<StringError>(
+ formatv("invalid argument to CallSiteSplitting pass "
+ "duplication-threshold parameter: '{}'",
+ ParamName)
+ .str(),
+ inconvertibleErrorCode());
+ } else {
+ return make_error<StringError>(
+ formatv("invalid CallSiteSplitting pass parameter '{}'", ParamName)
+ .str(),
+ inconvertibleErrorCode());
+ }
+ }
+ return DuplicationThreshold;
+}
+
/// Parser of parameters for LoopUnroll pass.
Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
LoopUnrollOptions UnrollOpts;
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 43a15f4cf9ff3..ee786955d440a 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -417,7 +417,6 @@ FUNCTION_PASS("assume-simplify", AssumeSimplifyPass())
FUNCTION_PASS("atomic-expand", AtomicExpandPass(*TM))
FUNCTION_PASS("bdce", BDCEPass())
FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
-FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
FUNCTION_PASS("cfguard", CFGuardPass())
FUNCTION_PASS("chr", ControlHeightReductionPass())
FUNCTION_PASS("codegenprepare", CodeGenPreparePass(*TM))
@@ -581,6 +580,12 @@ FUNCTION_PASS("wasm-eh-prepare", WasmEHPreparePass())
#ifndef FUNCTION_PASS_WITH_PARAMS
#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS)
#endif
+FUNCTION_PASS_WITH_PARAMS(
+ "callsite-splitting", "CallSiteSplittingPass",
+ [](unsigned DuplicationThreshold) {
+ return CallSiteSplittingPass(DuplicationThreshold);
+ },
+ parseCallSiteSplittingOptions, "duplication-threshold=N")
FUNCTION_PASS_WITH_PARAMS(
"early-cse", "EarlyCSEPass",
[](bool UseMemorySSA) { return EarlyCSEPass(UseMemorySSA); },
diff --git a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
index ce73c44959a0e..12efd05e01952 100644
--- a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
+++ b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
@@ -62,7 +62,6 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
@@ -74,15 +73,6 @@ using namespace PatternMatch;
STATISTIC(NumCallSiteSplit, "Number of call-site split");
-/// Only allow instructions before a call, if their CodeSize cost is below
-/// DuplicationThreshold. Those instructions need to be duplicated in all
-/// split blocks.
-static cl::opt<unsigned>
- DuplicationThreshold("callsite-splitting-duplication-threshold", cl::Hidden,
- cl::desc("Only allow instructions before a call, if "
- "their cost is below DuplicationThreshold"),
- cl::init(5));
-
static void addNonNullAttribute(CallBase &CB, Value *Op) {
unsigned ArgNo = 0;
for (auto &I : CB.args()) {
@@ -181,7 +171,8 @@ static SmallVector<BasicBlock *, 2> getTwoPredecessors(BasicBlock *BB) {
return Preds;
}
-static bool canSplitCallSite(CallBase &CB, TargetTransformInfo &TTI) {
+static bool canSplitCallSite(CallBase &CB, TargetTransformInfo &TTI,
+ unsigned DuplicationThreshold) {
if (CB.isConvergent() || CB.cannotDuplicate())
return false;
@@ -485,9 +476,10 @@ static PredsWithCondsTy shouldSplitOnPredicatedArgument(CallBase &CB,
}
static bool tryToSplitCallSite(CallBase &CB, TargetTransformInfo &TTI,
- DomTreeUpdater &DTU) {
+ DomTreeUpdater &DTU,
+ unsigned DuplicationThreshold) {
// Check if we can split the call site.
- if (!CB.arg_size() || !canSplitCallSite(CB, TTI))
+ if (!CB.arg_size() || !canSplitCallSite(CB, TTI, DuplicationThreshold))
return false;
auto PredsWithConds = shouldSplitOnPredicatedArgument(CB, DTU);
@@ -501,7 +493,8 @@ static bool tryToSplitCallSite(CallBase &CB, TargetTransformInfo &TTI,
}
static bool doCallSiteSplitting(Function &F, TargetLibraryInfo &TLI,
- TargetTransformInfo &TTI, DominatorTree &DT) {
+ TargetTransformInfo &TTI, DominatorTree &DT,
+ unsigned DuplicationThreshold) {
DomTreeUpdater DTU(&DT, DomTreeUpdater::UpdateStrategy::Lazy);
bool Changed = false;
@@ -525,7 +518,7 @@ static bool doCallSiteSplitting(Function &F, TargetLibraryInfo &TLI,
// Check if such path is possible before attempting the splitting.
bool IsMustTail = CB->isMustTailCall();
- Changed |= tryToSplitCallSite(*CB, TTI, DTU);
+ Changed |= tryToSplitCallSite(*CB, TTI, DTU, DuplicationThreshold);
// There're no interesting instructions after this. The call site
// itself might have been erased on splitting.
@@ -542,9 +535,18 @@ PreservedAnalyses CallSiteSplittingPass::run(Function &F,
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
- if (!doCallSiteSplitting(F, TLI, TTI, DT))
+ if (!doCallSiteSplitting(F, TLI, TTI, DT, DuplicationThreshold))
return PreservedAnalyses::all();
PreservedAnalyses PA;
PA.preserve<DominatorTreeAnalysis>();
return PA;
}
+
+void CallSiteSplittingPass::printPipeline(
+ raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
+ static_cast<PassInfoMixin<CallSiteSplittingPass> *>(this)->printPipeline(
+ OS, MapClassName2PassName);
+ OS << '<';
+ OS << "duplication-threshold=" << DuplicationThreshold;
+ OS << '>';
+}
diff --git a/llvm/test/Other/new-pm-print-pipeline.ll b/llvm/test/Other/new-pm-print-pipeline.ll
index 2a1192b6b66bd..386be8ab90b40 100644
--- a/llvm/test/Other/new-pm-print-pipeline.ll
+++ b/llvm/test/Other/new-pm-print-pipeline.ll
@@ -123,3 +123,6 @@
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='drop-unnecessary-assumes,drop-unnecessary-assumes<drop-deref>' < %s | FileCheck %s --check-prefixes=CHECK-38
; CHECK-38: drop-unnecessary-assumes,drop-unnecessary-assumes<drop-deref>
+
+; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(callsite-splitting,callsite-splitting<duplication-threshold=10>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-39
+; CHECK-39: function(callsite-splitting<duplication-threshold=5>,callsite-splitting<duplication-threshold=10>)
diff --git a/llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll b/llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll
index 162751a1ce324..f6aada6d4aa06 100644
--- a/llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll
+++ b/llvm/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll
@@ -1,5 +1,5 @@
; RUN: opt -S -passes=callsite-splitting < %s | FileCheck --check-prefix=CHECK %s
-; RUN: opt -S -passes=callsite-splitting -callsite-splitting-duplication-threshold=0 < %s | FileCheck --check-prefix=NODUP %s
+; RUN: opt -S -passes='callsite-splitting<duplication-threshold=0>' < %s | FileCheck --check-prefix=NODUP %s
; Instructions before a call that will be pushed to its predecessors
; with uses after the callsite, must be patched up as PHI nodes in
diff --git a/llvm/test/Transforms/CallSiteSplitting/convergent.ll b/llvm/test/Transforms/CallSiteSplitting/convergent.ll
index 934f7e86157bd..447c3826f7be6 100644
--- a/llvm/test/Transforms/CallSiteSplitting/convergent.ll
+++ b/llvm/test/Transforms/CallSiteSplitting/convergent.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=callsite-splitting -callsite-splitting-duplication-threshold=100000000 < %s | FileCheck -enable-var-scope %s
+; RUN: opt -S -passes='callsite-splitting<duplication-threshold=100000000>' < %s | FileCheck -enable-var-scope %s
; Convergent calls should not be duplicated in this case
; CHECK-LABEL: define void @convergent_caller(
diff --git a/llvm/test/Transforms/CallSiteSplitting/noduplicate.ll b/llvm/test/Transforms/CallSiteSplitting/noduplicate.ll
index bdec9eb63e408..e9078bf76f1dd 100644
--- a/llvm/test/Transforms/CallSiteSplitting/noduplicate.ll
+++ b/llvm/test/Transforms/CallSiteSplitting/noduplicate.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=callsite-splitting -callsite-splitting-duplication-threshold=100000000 < %s | FileCheck -enable-var-scope %s
+; RUN: opt -S -passes='callsite-splitting<duplication-threshold=100000000>' < %s | FileCheck -enable-var-scope %s
; Noduplicate calls should not be duplicated
; CHECK-LABEL: define void @noduplicate_caller(
diff --git a/llvm/test/Transforms/CallSiteSplitting/pass-param-parse-errors.ll b/llvm/test/Transforms/CallSiteSplitting/pass-param-parse-errors.ll
new file mode 100644
index 0000000000000..8c5a827f7bdb4
--- /dev/null
+++ b/llvm/test/Transforms/CallSiteSplitting/pass-param-parse-errors.ll
@@ -0,0 +1,7 @@
+; RUN: not opt -passes='callsite-splitting<unknown>' -disable-output %s 2>&1 | FileCheck -check-prefix=UNKNOWNERR %s
+; RUN: not opt -passes='callsite-splitting<duplication-threshold=>' -disable-output %s 2>&1 | FileCheck -check-prefix=DUP-EMPTY-ERR %s
+; RUN: not opt -passes='callsite-splitting<duplication-threshold=x>' -disable-output %s 2>&1 | FileCheck -check-prefix=DUP-NOTINT-ERR %s
+
+; UNKNOWNERR: invalid CallSiteSplitting pass parameter '{{.*}}'
+; DUP-EMPTY-ERR: invalid argument to CallSiteSplitting pass duplication-threshold parameter: ''
+; DUP-NOTINT-ERR: invalid argument to CallSiteSplitting pass duplication-threshold parameter: 'x'
More information about the llvm-commits
mailing list