class Module;
+/// A set of parameters to control various transforms performed by IPSCCP pass.
+/// Each of the boolean parameters can be set to:
+/// true - enabling the transformation.
+/// false - disabling the transformation.
+/// Intended use is to create a default object, modify parameters with
+/// additional setters and then pass it to IPSCCP.
+struct IPSCCPOptions {
+ bool AllowFuncSpec;
+
+ IPSCCPOptions(bool AllowFuncSpec = false) : AllowFuncSpec(AllowFuncSpec) {}
+
+ /// Enables or disables Specialization of Functions.
+ IPSCCPOptions &setFuncSpec(bool FuncSpec) {
+ AllowFuncSpec = FuncSpec;
+ return *this;
+ }
+};
+
/// Pass to perform interprocedural constant propagation.
class IPSCCPPass : public PassInfoMixin<IPSCCPPass> {
+ IPSCCPOptions Options;
+
public:
+ IPSCCPPass() = default;
+
+ IPSCCPPass(IPSCCPOptions Options) : Options(Options) {}
+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+
+ bool isFuncSpecEnabled() const { return Options.AllowFuncSpec; }
};
} // end namespace llvm
return Result;
}
+Expected<IPSCCPOptions> parseIPSCCPOptions(StringRef Params) {
+ IPSCCPOptions Result;
+ while (!Params.empty()) {
+ StringRef ParamName;
+ std::tie(ParamName, Params) = Params.split(';');
+
+ bool Enable = !ParamName.consume_front("no-");
+ if (ParamName == "func-spec")
+ Result.setFuncSpec(Enable);
+ else
+ return make_error<StringError>(
+ formatv("invalid IPSCCP pass parameter '{0}' ", ParamName).str(),
+ inconvertibleErrorCode());
+ }
+ return Result;
+}
+
Expected<SROAOptions> parseSROAOptions(StringRef Params) {
if (Params.empty() || Params == "modify-cfg")
return SROAOptions::ModifyCFG;
MODULE_PASS("instrprof", InstrProfiling())
MODULE_PASS("internalize", InternalizePass())
MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass())
-MODULE_PASS("ipsccp", IPSCCPPass())
MODULE_PASS("iroutliner", IROutlinerPass())
MODULE_PASS("print-ir-similarity", IRSimilarityAnalysisPrinterPass(dbgs()))
MODULE_PASS("lower-global-dtors", LowerGlobalDtorsPass())
},
parseMSanPassOptions,
"recover;kernel;eager-checks;track-origins=N")
+MODULE_PASS_WITH_PARAMS("ipsccp",
+ "IPSCCPPass",
+ [](IPSCCPOptions Opts) {
+ return IPSCCPPass(Opts);
+ },
+ parseIPSCCPOptions,
+ "no-func-spec;func-spec")
#undef MODULE_PASS_WITH_PARAMS
#ifndef CGSCC_ANALYSIS
STATISTIC(NumInstReplaced,
"Number of instructions replaced with (simpler) instruction");
-static cl::opt<bool> SpecializeFunctions("specialize-functions",
- cl::init(false), cl::Hidden, cl::desc("Enable function specialization"));
-
static cl::opt<unsigned> FuncSpecializationMaxIters(
"func-specialization-max-iters", cl::init(1), cl::Hidden, cl::desc(
"The maximum number of iterations function specialization is run"));
std::function<const TargetLibraryInfo &(Function &)> GetTLI,
std::function<TargetTransformInfo &(Function &)> GetTTI,
std::function<AssumptionCache &(Function &)> GetAC,
- function_ref<AnalysisResultsForFn(Function &)> getAnalysis) {
+ function_ref<AnalysisResultsForFn(Function &)> getAnalysis,
+ bool IsFuncSpecEnabled) {
SCCPSolver Solver(DL, GetTLI, M.getContext());
FunctionSpecializer Specializer(Solver, M, FAM, GetTLI, GetTTI, GetAC);
// Solve for constants.
Solver.solveWhileResolvedUndefsIn(M);
- if (SpecializeFunctions) {
+ if (IsFuncSpecEnabled) {
unsigned Iters = 0;
while (Iters++ < FuncSpecializationMaxIters && Specializer.run());
}
NumInstRemoved, NumInstReplaced);
}
- DomTreeUpdater DTU = SpecializeFunctions && Specializer.isClonedFunction(&F)
+ DomTreeUpdater DTU = IsFuncSpecEnabled && Specializer.isClonedFunction(&F)
? DomTreeUpdater(DomTreeUpdater::UpdateStrategy::Lazy)
: Solver.getDTU(F);
auto GetAC = [&FAM](Function &F) -> AssumptionCache & {
return FAM.getResult<AssumptionAnalysis>(F);
};
- auto getAnalysis = [&FAM](Function &F) -> AnalysisResultsForFn {
+ auto getAnalysis = [&FAM, this](Function &F) -> AnalysisResultsForFn {
DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
return {
std::make_unique<PredicateInfo>(F, DT, FAM.getResult<AssumptionAnalysis>(F)),
&DT, FAM.getCachedResult<PostDominatorTreeAnalysis>(F),
- SpecializeFunctions ? &FAM.getResult<LoopAnalysis>(F) : nullptr };
+ isFuncSpecEnabled() ? &FAM.getResult<LoopAnalysis>(F) : nullptr };
};
- if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, getAnalysis))
+ if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, getAnalysis,
+ isFuncSpecEnabled()))
return PreservedAnalyses::all();
PreservedAnalyses PA;
nullptr};
};
- return runIPSCCP(M, DL, nullptr, GetTLI, GetTTI, GetAC, getAnalysis);
+ return runIPSCCP(M, DL, nullptr, GetTLI, GetTTI, GetAC, getAnalysis, false);
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -S < %s | FileCheck %s
%mystruct = type { i32, [2 x i64] }
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-max-iters=2 -func-specialization-max-clones=1 -function-specialization-for-literal-constant=true -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-max-iters=2 -func-specialization-max-clones=1 -function-specialization-for-literal-constant=true -S < %s | FileCheck %s
declare hidden i1 @compare(ptr) align 2
declare hidden { i8, ptr } @getType(ptr) align 2
-; RUN: opt -S --passes='default<O3>' -specialize-functions < %s | FileCheck %s
+; RUN: opt -S --passes="default<O3>,ipsccp<func-spec>" < %s | FileCheck %s
define dso_local i32 @g0(i32 noundef %x) local_unnamed_addr {
entry:
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-avg-iters-cost=3 -func-specialization-size-threshold=10 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-avg-iters-cost=3 -func-specialization-size-threshold=10 -S < %s | FileCheck %s
; CHECK-NOT: foo.{{[0-9]+}}
; Note that this test case shows that function specialization pass would
; transform the function even if no specialization happened.
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
%struct = type { i8, i16, i32, i64, i64}
@Global = internal constant %struct {i8 0, i16 1, i32 2, i64 3, i64 4}
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; Check that we don't crash and specialise on a constant expression.
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
define i32 @main() {
; CHECK-LABEL: @main(
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; Check that we don't crash and specialise on a function call with byval attribute.
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-on-address -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-on-address -S < %s | FileCheck %s
; Check that we don't crash and specialise on a scalar global variable with byval attribute.
-; RUN: opt -passes=ipsccp -specialize-functions -function-specialization-for-literal-constant=true -func-specialization-size-threshold=10 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -function-specialization-for-literal-constant=true -func-specialization-size-threshold=10 -S < %s | FileCheck %s
; Check that the literal constant parameter could be specialized.
; CHECK: @foo.1(
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-avg-iters-cost=5 -func-specialization-size-threshold=10 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-avg-iters-cost=5 -func-specialization-size-threshold=10 -S < %s | FileCheck %s
; Check that the loop depth results in a larger specialization bonus.
; CHECK: @foo.1(
-; RUN: opt -passes=ipsccp -specialize-functions -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -S < %s | FileCheck %s
; CHECK-NOT: @compute.1
; CHECK-NOT: @compute.2
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-size-threshold=3 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-size-threshold=3 -S < %s | FileCheck %s
; Checks for callsites that have been annotated with MinSize. No specialisation
; expected here:
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-size-threshold=3 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-size-threshold=3 -S < %s | FileCheck %s
; Checks for callsites that have been annotated with MinSize. We only expect
; specialisation for the call that does not have the attribute:
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; Function @foo has function attribute 'noduplicate', so check that we don't
; specialize it:
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; Check that function foo does not gets specialised as it contains an intrinsic
; that is marked as NoDuplicate.
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; The if.then block is not executed, so check that we don't specialise here.
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-on-address=0 -S < %s | FileCheck %s
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-on-address=1 -S < %s | FileCheck %s --check-prefix=ON-ADDRESS
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-on-address=0 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-on-address=1 -S < %s | FileCheck %s --check-prefix=ON-ADDRESS
; Global B is not constant. We do not specialise on addresses unless we
; enable that:
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; Check that we don't crash and specialise on a poison value.
-; RUN: opt -passes=ipsccp,inline,instcombine -specialize-functions -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s --check-prefix=ITERS2
-; RUN: opt -passes=ipsccp,inline,instcombine -specialize-functions -force-function-specialization -func-specialization-max-iters=3 -S < %s | FileCheck %s --check-prefix=ITERS3
-; RUN: opt -passes=ipsccp,inline,instcombine -specialize-functions -force-function-specialization -func-specialization-max-iters=4 -S < %s | FileCheck %s --check-prefix=ITERS4
+; RUN: opt -passes="ipsccp<func-spec>,inline,instcombine" -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s --check-prefix=ITERS2
+; RUN: opt -passes="ipsccp<func-spec>,inline,instcombine" -force-function-specialization -func-specialization-max-iters=3 -S < %s | FileCheck %s --check-prefix=ITERS3
+; RUN: opt -passes="ipsccp<func-spec>,inline,instcombine" -force-function-specialization -func-specialization-max-iters=4 -S < %s | FileCheck %s --check-prefix=ITERS4
@low = internal constant i32 0, align 4
@high = internal constant i32 6, align 4
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
; Volatile store preventing recursive specialisation:
;
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
; Duplicate store preventing recursive specialisation:
;
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -func-specialization-max-iters=2 -S < %s | FileCheck %s
; Alloca is not an integer type:
;
; REQUIRES: asserts
-; RUN: opt -stats -passes=ipsccp -specialize-functions -S -force-function-specialization < %s 2>&1 | FileCheck %s
+; RUN: opt -stats -passes="ipsccp<func-spec>" -S -force-function-specialization < %s 2>&1 | FileCheck %s
; CHECK: 2 function-specialization - Number of functions specialized
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-size-threshold=3 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-size-threshold=3 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<no-func-spec>" -func-specialization-size-threshold=3 -S < %s | FileCheck %s --check-prefix=NOFSPEC
define i64 @main(i64 %x, i1 %flag) {
;
; CHECK-NEXT: ret i64 [[TMP2]]
; CHECK-NEXT: }
;
+; NOFSPEC-LABEL: @main(i64 %x, i1 %flag) {
+; NOFSPEC-NOT: call i64 @compute.{{[0-9]+}}(
+; NOFSPEC: call i64 @compute(
+;
entry:
br i1 %flag, label %plus, label %minus
; CHECK-NEXT: ret i64 [[TMP0]]
; CHECK-NEXT: }
;
+; NOFSPEC: define internal i64 @compute(
+; NOFSPEC-NOT: define internal i64 @compute.{{[0-9]+}}(
+;
define internal i64 @compute(i64 %x, ptr %binop) {
entry:
%tmp0 = call i64 %binop(i64 %x)
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp,deadargelim -specialize-functions -force-function-specialization -S < %s | FileCheck %s
-; RUN: opt -passes=ipsccp,deadargelim -specialize-functions -func-specialization-max-iters=1 -force-function-specialization -S < %s | FileCheck %s
-; RUN: opt -passes=ipsccp,deadargelim -specialize-functions -func-specialization-max-iters=0 -force-function-specialization -S < %s | FileCheck %s --check-prefix=DISABLED
-; RUN: opt -passes=ipsccp,deadargelim -specialize-functions -func-specialization-avg-iters-cost=1 -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>,deadargelim" -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>,deadargelim" -func-specialization-max-iters=1 -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>,deadargelim" -func-specialization-max-iters=0 -force-function-specialization -S < %s | FileCheck %s --check-prefix=DISABLED
+; RUN: opt -passes="ipsccp<func-spec>,deadargelim" -func-specialization-avg-iters-cost=1 -force-function-specialization -S < %s | FileCheck %s
; DISABLED-NOT: @func.1(
; DISABLED-NOT: @func.2(
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-avg-iters-cost=3 -S < %s | \
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-avg-iters-cost=3 -S < %s | \
; RUN: FileCheck %s --check-prefixes=COMMON,DISABLED
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | \
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | \
; RUN: FileCheck %s --check-prefixes=COMMON,FORCE
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-avg-iters-cost=3 -force-function-specialization -S < %s | \
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-avg-iters-cost=3 -force-function-specialization -S < %s | \
; RUN: FileCheck %s --check-prefixes=COMMON,FORCE
; Test for specializing a constant global.
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization \
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization \
; RUN: -func-specialization-max-clones=2 -S < %s | FileCheck %s
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization \
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization \
; RUN: -func-specialization-max-clones=1 -S < %s | FileCheck %s --check-prefix=CONST1
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
; There's nothing to specialize here as both calls are the same, so check that:
;
-; RUN: opt -S --passes=ipsccp -specialize-functions < %s | FileCheck %s
+; RUN: opt -S --passes="ipsccp<func-spec>" < %s | FileCheck %s
define dso_local i32 @p0(i32 noundef %x) {
entry:
%add = add nsw i32 %x, 1
-; RUN: opt -S --passes=ipsccp -specialize-functions -func-specialization-max-clones=1 < %s | FileCheck %s
+; RUN: opt -S --passes="ipsccp<func-spec>" -func-specialization-max-clones=1 < %s | FileCheck %s
define internal i32 @f(i32 noundef %x, ptr nocapture noundef readonly %p, ptr nocapture noundef readonly %q) noinline {
entry:
%call = tail call i32 %p(i32 noundef %x)
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -force-function-specialization -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -force-function-specialization -S < %s | FileCheck %s
define i64 @main(i64 %x, i64 %y, i1 %flag) {
; CHECK-LABEL: @main(
-; RUN: opt -S --passes=ipsccp -specialize-functions \
+; RUN: opt -S --passes="ipsccp<func-spec>" \
; RUN: -force-function-specialization < %s | FileCheck %s -check-prefix CHECK-NOLIT
-; RUN: opt -S --passes=ipsccp -specialize-functions \
+; RUN: opt -S --passes="ipsccp<func-spec>" \
; RUN: -function-specialization-for-literal-constant \
; RUN: -force-function-specialization < %s | FileCheck %s -check-prefix CHECK-LIT
-; RUN: opt -S --passes=ipsccp -specialize-functions -force-function-specialization -function-specialization-for-literal-constant < %s | FileCheck %s
+; RUN: opt -S --passes="ipsccp<func-spec>" -force-function-specialization -function-specialization-for-literal-constant < %s | FileCheck %s
define internal i32 @f(i32 %x, i32 %y) noinline {
ret i32 %x
}
-; RUN: opt -S --passes=ipsccp -specialize-functions < %s | FileCheck %s
+; RUN: opt -S --passes="ipsccp<func-spec>" < %s | FileCheck %s
define dso_local i32 @p0(i32 noundef %x) {
entry:
%add = add nsw i32 %x, 1
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-size-threshold=3 -S < %s | FileCheck %s
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-size-threshold=3 -S < %s | FileCheck %s
define i64 @main(i64 %x, i1 %flag) {
entry:
-; RUN: opt -S --passes=ipsccp,deadargelim -specialize-functions -force-function-specialization < %s | FileCheck %s
+; RUN: opt -S --passes="ipsccp<func-spec>,deadargelim" -force-function-specialization < %s | FileCheck %s
define dso_local i32 @add(i32 %x, i32 %y) {
entry:
%add = add nsw i32 %y, %x
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-max-clones=0 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=NONE
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-max-clones=1 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=ONE
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-max-clones=2 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=TWO
-; RUN: opt -passes=ipsccp -specialize-functions -func-specialization-max-clones=3 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=THREE
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-max-clones=0 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=NONE
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-max-clones=1 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=ONE
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-max-clones=2 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=TWO
+; RUN: opt -passes="ipsccp<func-spec>" -func-specialization-max-clones=3 -func-specialization-size-threshold=14 -S < %s | FileCheck %s --check-prefix=THREE
; Make sure that we iterate correctly after sorting the specializations:
; FnSpecialization: Specializations for function compute