19907746fSSjoerd Meijer //===- FunctionSpecialization.cpp - Function Specialization ---------------===//
29907746fSSjoerd Meijer //
39907746fSSjoerd Meijer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49907746fSSjoerd Meijer // See https://llvm.org/LICENSE.txt for license information.
59907746fSSjoerd Meijer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69907746fSSjoerd Meijer //
79907746fSSjoerd Meijer //===----------------------------------------------------------------------===//
89907746fSSjoerd Meijer //
9fabf1de1SSjoerd Meijer // This specialises functions with constant parameters. Constant parameters
10fabf1de1SSjoerd Meijer // like function pointers and constant globals are propagated to the callee by
11fabf1de1SSjoerd Meijer // specializing the function. The main benefit of this pass at the moment is
12fabf1de1SSjoerd Meijer // that indirect calls are transformed into direct calls, which provides inline
13fabf1de1SSjoerd Meijer // opportunities that the inliner would not have been able to achieve. That's
14fabf1de1SSjoerd Meijer // why function specialisation is run before the inliner in the optimisation
15fabf1de1SSjoerd Meijer // pipeline; that is by design. Otherwise, we would only benefit from constant
16fabf1de1SSjoerd Meijer // passing, which is a valid use-case too, but hasn't been explored much in
17fabf1de1SSjoerd Meijer // terms of performance uplifts, cost-model and compile-time impact.
189907746fSSjoerd Meijer //
199907746fSSjoerd Meijer // Current limitations:
20fabf1de1SSjoerd Meijer // - It does not yet handle integer ranges. We do support "literal constants",
21fabf1de1SSjoerd Meijer //   but that's off by default under an option.
22fabf1de1SSjoerd Meijer // - The cost-model could be further looked into (it mainly focuses on inlining
23fabf1de1SSjoerd Meijer //   benefits),
249907746fSSjoerd Meijer //
259907746fSSjoerd Meijer // Ideas:
269907746fSSjoerd Meijer // - With a function specialization attribute for arguments, we could have
279907746fSSjoerd Meijer //   a direct way to steer function specialization, avoiding the cost-model,
289907746fSSjoerd Meijer //   and thus control compile-times / code-size.
299907746fSSjoerd Meijer //
3082ca845bSChuanqi Xu // Todos:
31ecff9e3dSSjoerd Meijer // - Specializing recursive functions relies on running the transformation a
32ecff9e3dSSjoerd Meijer //   number of times, which is controlled by option
33ecff9e3dSSjoerd Meijer //   `func-specialization-max-iters`. Thus, increasing this value and the
34ecff9e3dSSjoerd Meijer //   number of iterations, will linearly increase the number of times recursive
35ecff9e3dSSjoerd Meijer //   functions get specialized, see also the discussion in
36ecff9e3dSSjoerd Meijer //   https://reviews.llvm.org/D106426 for details. Perhaps there is a
37ecff9e3dSSjoerd Meijer //   compile-time friendlier way to control/limit the number of specialisations
38ecff9e3dSSjoerd Meijer //   for recursive functions.
39fabf1de1SSjoerd Meijer // - Don't transform the function if function specialization does not trigger;
40fabf1de1SSjoerd Meijer //   the SCCPSolver may make IR changes.
41fabf1de1SSjoerd Meijer //
42fabf1de1SSjoerd Meijer // References:
43fabf1de1SSjoerd Meijer // - 2021 LLVM Dev Mtg “Introducing function specialisation, and can we enable
44fabf1de1SSjoerd Meijer //   it by default?”, https://www.youtube.com/watch?v=zJiCjeXgV5Q
4582ca845bSChuanqi Xu //
469907746fSSjoerd Meijer //===----------------------------------------------------------------------===//
479907746fSSjoerd Meijer 
489907746fSSjoerd Meijer #include "llvm/ADT/Statistic.h"
499907746fSSjoerd Meijer #include "llvm/Analysis/CodeMetrics.h"
509907746fSSjoerd Meijer #include "llvm/Analysis/InlineCost.h"
519907746fSSjoerd Meijer #include "llvm/Analysis/LoopInfo.h"
529907746fSSjoerd Meijer #include "llvm/Analysis/TargetTransformInfo.h"
53a494ae43Sserge-sans-paille #include "llvm/Analysis/ValueLattice.h"
54a494ae43Sserge-sans-paille #include "llvm/Analysis/ValueLatticeUtils.h"
55a494ae43Sserge-sans-paille #include "llvm/IR/IntrinsicInst.h"
569907746fSSjoerd Meijer #include "llvm/Transforms/Scalar/SCCP.h"
579907746fSSjoerd Meijer #include "llvm/Transforms/Utils/Cloning.h"
5859630917Sserge-sans-paille #include "llvm/Transforms/Utils/SCCPSolver.h"
599907746fSSjoerd Meijer #include "llvm/Transforms/Utils/SizeOpts.h"
6086906304SChuanqi Xu #include <cmath>
619907746fSSjoerd Meijer 
629907746fSSjoerd Meijer using namespace llvm;
639907746fSSjoerd Meijer 
649907746fSSjoerd Meijer #define DEBUG_TYPE "function-specialization"
659907746fSSjoerd Meijer 
6649ab3b17SSjoerd Meijer STATISTIC(NumFuncSpecialized, "Number of functions specialized");
679907746fSSjoerd Meijer 
689907746fSSjoerd Meijer static cl::opt<bool> ForceFunctionSpecialization(
699907746fSSjoerd Meijer     "force-function-specialization", cl::init(false), cl::Hidden,
709907746fSSjoerd Meijer     cl::desc("Force function specialization for every call site with a "
719907746fSSjoerd Meijer              "constant argument"));
729907746fSSjoerd Meijer 
739907746fSSjoerd Meijer static cl::opt<unsigned> FuncSpecializationMaxIters(
749907746fSSjoerd Meijer     "func-specialization-max-iters", cl::Hidden,
759907746fSSjoerd Meijer     cl::desc("The maximum number of iterations function specialization is run"),
769907746fSSjoerd Meijer     cl::init(1));
779907746fSSjoerd Meijer 
789e3ae8d2SSjoerd Meijer static cl::opt<unsigned> MaxClonesThreshold(
799e3ae8d2SSjoerd Meijer     "func-specialization-max-clones", cl::Hidden,
809907746fSSjoerd Meijer     cl::desc("The maximum number of clones allowed for a single function "
819907746fSSjoerd Meijer              "specialization"),
829907746fSSjoerd Meijer     cl::init(3));
839907746fSSjoerd Meijer 
842556f581SChuanqi Xu static cl::opt<unsigned> SmallFunctionThreshold(
852556f581SChuanqi Xu     "func-specialization-size-threshold", cl::Hidden,
8688a20312SSjoerd Meijer     cl::desc("Don't specialize functions that have less than this theshold "
8788a20312SSjoerd Meijer              "number of instructions"),
882556f581SChuanqi Xu     cl::init(100));
892556f581SChuanqi Xu 
909907746fSSjoerd Meijer static cl::opt<unsigned>
919907746fSSjoerd Meijer     AvgLoopIterationCount("func-specialization-avg-iters-cost", cl::Hidden,
929907746fSSjoerd Meijer                           cl::desc("Average loop iteration count cost"),
939907746fSSjoerd Meijer                           cl::init(10));
949907746fSSjoerd Meijer 
9597cc678cSSjoerd Meijer static cl::opt<bool> SpecializeOnAddresses(
9697cc678cSSjoerd Meijer     "func-specialization-on-address", cl::init(false), cl::Hidden,
9797cc678cSSjoerd Meijer     cl::desc("Enable function specialization on the address of global values"));
9897cc678cSSjoerd Meijer 
998045bf9dSAlexandros Lamprineas // Disabled by default as it can significantly increase compilation times.
1008045bf9dSAlexandros Lamprineas // Running nikic's compile time tracker on x86 with instruction count as the
1018045bf9dSAlexandros Lamprineas // metric shows 3-4% regression for SPASS while being neutral for all other
1028045bf9dSAlexandros Lamprineas // benchmarks of the llvm test suite.
1038045bf9dSAlexandros Lamprineas //
1048045bf9dSAlexandros Lamprineas // https://llvm-compile-time-tracker.com
1058045bf9dSAlexandros Lamprineas // https://github.com/nikic/llvm-compile-time-tracker
106801c2b9bSChuanqi Xu static cl::opt<bool> EnableSpecializationForLiteralConstant(
107801c2b9bSChuanqi Xu     "function-specialization-for-literal-constant", cl::init(false), cl::Hidden,
10888a20312SSjoerd Meijer     cl::desc("Enable specialization of functions that take a literal constant "
10988a20312SSjoerd Meijer              "as an argument."));
110801c2b9bSChuanqi Xu 
11189bcfd16SSjoerd Meijer namespace {
11289bcfd16SSjoerd Meijer // Bookkeeping struct to pass data from the analysis and profitability phase
11389bcfd16SSjoerd Meijer // to the actual transform helper functions.
114910eb988SAlexandros Lamprineas struct SpecializationInfo {
1158045bf9dSAlexandros Lamprineas   SmallVector<ArgInfo, 8> Args; // Stores the {formal,actual} argument pairs.
11689bcfd16SSjoerd Meijer   InstructionCost Gain;         // Profitability: Gain = Bonus - Cost.
11789bcfd16SSjoerd Meijer };
11889bcfd16SSjoerd Meijer } // Anonymous namespace
11989bcfd16SSjoerd Meijer 
120b7b61fe0SSjoerd Meijer using FuncList = SmallVectorImpl<Function *>;
1218045bf9dSAlexandros Lamprineas using CallArgBinding = std::pair<CallBase *, Constant *>;
1228045bf9dSAlexandros Lamprineas using CallSpecBinding = std::pair<CallBase *, SpecializationInfo>;
1238045bf9dSAlexandros Lamprineas // We are using MapVector because it guarantees deterministic iteration
1248045bf9dSAlexandros Lamprineas // order across executions.
1258045bf9dSAlexandros Lamprineas using SpecializationMap = SmallMapVector<CallBase *, SpecializationInfo, 8>;
126b7b61fe0SSjoerd Meijer 
12730fbb069SSjoerd Meijer // Helper to check if \p LV is either a constant or a constant
12830fbb069SSjoerd Meijer // range with a single element. This should cover exactly the same cases as the
12930fbb069SSjoerd Meijer // old ValueLatticeElement::isConstant() and is intended to be used in the
13030fbb069SSjoerd Meijer // transition to ValueLatticeElement.
isConstant(const ValueLatticeElement & LV)13130fbb069SSjoerd Meijer static bool isConstant(const ValueLatticeElement &LV) {
13230fbb069SSjoerd Meijer   return LV.isConstant() ||
13330fbb069SSjoerd Meijer          (LV.isConstantRange() && LV.getConstantRange().isSingleElement());
13430fbb069SSjoerd Meijer }
13530fbb069SSjoerd Meijer 
1369907746fSSjoerd Meijer // Helper to check if \p LV is either overdefined or a constant int.
isOverdefined(const ValueLatticeElement & LV)1379907746fSSjoerd Meijer static bool isOverdefined(const ValueLatticeElement &LV) {
13830fbb069SSjoerd Meijer   return !LV.isUnknownOrUndef() && !isConstant(LV);
13930fbb069SSjoerd Meijer }
14030fbb069SSjoerd Meijer 
getPromotableAlloca(AllocaInst * Alloca,CallInst * Call)14130fbb069SSjoerd Meijer static Constant *getPromotableAlloca(AllocaInst *Alloca, CallInst *Call) {
14230fbb069SSjoerd Meijer   Value *StoreValue = nullptr;
14330fbb069SSjoerd Meijer   for (auto *User : Alloca->users()) {
14430fbb069SSjoerd Meijer     // We can't use llvm::isAllocaPromotable() as that would fail because of
14530fbb069SSjoerd Meijer     // the usage in the CallInst, which is what we check here.
14630fbb069SSjoerd Meijer     if (User == Call)
14730fbb069SSjoerd Meijer       continue;
14830fbb069SSjoerd Meijer     if (auto *Bitcast = dyn_cast<BitCastInst>(User)) {
14930fbb069SSjoerd Meijer       if (!Bitcast->hasOneUse() || *Bitcast->user_begin() != Call)
15030fbb069SSjoerd Meijer         return nullptr;
15130fbb069SSjoerd Meijer       continue;
15230fbb069SSjoerd Meijer     }
15330fbb069SSjoerd Meijer 
15430fbb069SSjoerd Meijer     if (auto *Store = dyn_cast<StoreInst>(User)) {
15530fbb069SSjoerd Meijer       // This is a duplicate store, bail out.
15630fbb069SSjoerd Meijer       if (StoreValue || Store->isVolatile())
15730fbb069SSjoerd Meijer         return nullptr;
15830fbb069SSjoerd Meijer       StoreValue = Store->getValueOperand();
15930fbb069SSjoerd Meijer       continue;
16030fbb069SSjoerd Meijer     }
16130fbb069SSjoerd Meijer     // Bail if there is any other unknown usage.
16230fbb069SSjoerd Meijer     return nullptr;
16330fbb069SSjoerd Meijer   }
16430fbb069SSjoerd Meijer   return dyn_cast_or_null<Constant>(StoreValue);
16530fbb069SSjoerd Meijer }
16630fbb069SSjoerd Meijer 
16730fbb069SSjoerd Meijer // A constant stack value is an AllocaInst that has a single constant
16830fbb069SSjoerd Meijer // value stored to it. Return this constant if such an alloca stack value
16930fbb069SSjoerd Meijer // is a function argument.
getConstantStackValue(CallInst * Call,Value * Val,SCCPSolver & Solver)17030fbb069SSjoerd Meijer static Constant *getConstantStackValue(CallInst *Call, Value *Val,
17130fbb069SSjoerd Meijer                                        SCCPSolver &Solver) {
17230fbb069SSjoerd Meijer   if (!Val)
17330fbb069SSjoerd Meijer     return nullptr;
17430fbb069SSjoerd Meijer   Val = Val->stripPointerCasts();
17530fbb069SSjoerd Meijer   if (auto *ConstVal = dyn_cast<ConstantInt>(Val))
17630fbb069SSjoerd Meijer     return ConstVal;
17730fbb069SSjoerd Meijer   auto *Alloca = dyn_cast<AllocaInst>(Val);
17830fbb069SSjoerd Meijer   if (!Alloca || !Alloca->getAllocatedType()->isIntegerTy())
17930fbb069SSjoerd Meijer     return nullptr;
18030fbb069SSjoerd Meijer   return getPromotableAlloca(Alloca, Call);
18130fbb069SSjoerd Meijer }
18230fbb069SSjoerd Meijer 
18330fbb069SSjoerd Meijer // To support specializing recursive functions, it is important to propagate
18430fbb069SSjoerd Meijer // constant arguments because after a first iteration of specialisation, a
18530fbb069SSjoerd Meijer // reduced example may look like this:
18630fbb069SSjoerd Meijer //
18730fbb069SSjoerd Meijer //     define internal void @RecursiveFn(i32* arg1) {
18830fbb069SSjoerd Meijer //       %temp = alloca i32, align 4
18930fbb069SSjoerd Meijer //       store i32 2 i32* %temp, align 4
19030fbb069SSjoerd Meijer //       call void @RecursiveFn.1(i32* nonnull %temp)
19130fbb069SSjoerd Meijer //       ret void
19230fbb069SSjoerd Meijer //     }
19330fbb069SSjoerd Meijer //
19430fbb069SSjoerd Meijer // Before a next iteration, we need to propagate the constant like so
19530fbb069SSjoerd Meijer // which allows further specialization in next iterations.
19630fbb069SSjoerd Meijer //
19730fbb069SSjoerd Meijer //     @funcspec.arg = internal constant i32 2
19830fbb069SSjoerd Meijer //
19930fbb069SSjoerd Meijer //     define internal void @someFunc(i32* arg1) {
20030fbb069SSjoerd Meijer //       call void @otherFunc(i32* nonnull @funcspec.arg)
20130fbb069SSjoerd Meijer //       ret void
20230fbb069SSjoerd Meijer //     }
20330fbb069SSjoerd Meijer //
constantArgPropagation(FuncList & WorkList,Module & M,SCCPSolver & Solver)204a687f96bSAlexandros Lamprineas static void constantArgPropagation(FuncList &WorkList, Module &M,
205a687f96bSAlexandros Lamprineas                                    SCCPSolver &Solver) {
20630fbb069SSjoerd Meijer   // Iterate over the argument tracked functions see if there
20730fbb069SSjoerd Meijer   // are any new constant values for the call instruction via
20830fbb069SSjoerd Meijer   // stack variables.
20930fbb069SSjoerd Meijer   for (auto *F : WorkList) {
21030fbb069SSjoerd Meijer 
21130fbb069SSjoerd Meijer     for (auto *User : F->users()) {
212b4417075SAlexandros Lamprineas 
21330fbb069SSjoerd Meijer       auto *Call = dyn_cast<CallInst>(User);
21430fbb069SSjoerd Meijer       if (!Call)
215b4417075SAlexandros Lamprineas         continue;
216b4417075SAlexandros Lamprineas 
217b4417075SAlexandros Lamprineas       bool Changed = false;
218b4417075SAlexandros Lamprineas       for (const Use &U : Call->args()) {
219b4417075SAlexandros Lamprineas         unsigned Idx = Call->getArgOperandNo(&U);
220b4417075SAlexandros Lamprineas         Value *ArgOp = Call->getArgOperand(Idx);
221b4417075SAlexandros Lamprineas         Type *ArgOpType = ArgOp->getType();
222b4417075SAlexandros Lamprineas 
223b4417075SAlexandros Lamprineas         if (!Call->onlyReadsMemory(Idx) || !ArgOpType->isPointerTy())
224b4417075SAlexandros Lamprineas           continue;
225b4417075SAlexandros Lamprineas 
22630fbb069SSjoerd Meijer         auto *ConstVal = getConstantStackValue(Call, ArgOp, Solver);
22730fbb069SSjoerd Meijer         if (!ConstVal)
228b4417075SAlexandros Lamprineas           continue;
22930fbb069SSjoerd Meijer 
23030fbb069SSjoerd Meijer         Value *GV = new GlobalVariable(M, ConstVal->getType(), true,
23130fbb069SSjoerd Meijer                                        GlobalValue::InternalLinkage, ConstVal,
23230fbb069SSjoerd Meijer                                        "funcspec.arg");
23330fbb069SSjoerd Meijer         if (ArgOpType != ConstVal->getType())
234b4417075SAlexandros Lamprineas           GV = ConstantExpr::getBitCast(cast<Constant>(GV), ArgOpType);
23530fbb069SSjoerd Meijer 
236b4417075SAlexandros Lamprineas         Call->setArgOperand(Idx, GV);
237b4417075SAlexandros Lamprineas         Changed = true;
238b4417075SAlexandros Lamprineas       }
23930fbb069SSjoerd Meijer 
24030fbb069SSjoerd Meijer       // Add the changed CallInst to Solver Worklist
241b4417075SAlexandros Lamprineas       if (Changed)
24230fbb069SSjoerd Meijer         Solver.visitCall(*Call);
24330fbb069SSjoerd Meijer     }
24430fbb069SSjoerd Meijer   }
24530fbb069SSjoerd Meijer }
24630fbb069SSjoerd Meijer 
24730fbb069SSjoerd Meijer // ssa_copy intrinsics are introduced by the SCCP solver. These intrinsics
24830fbb069SSjoerd Meijer // interfere with the constantArgPropagation optimization.
removeSSACopy(Function & F)24930fbb069SSjoerd Meijer static void removeSSACopy(Function &F) {
25030fbb069SSjoerd Meijer   for (BasicBlock &BB : F) {
251d9e46beaSKazu Hirata     for (Instruction &Inst : llvm::make_early_inc_range(BB)) {
252d9e46beaSKazu Hirata       auto *II = dyn_cast<IntrinsicInst>(&Inst);
25330fbb069SSjoerd Meijer       if (!II)
25430fbb069SSjoerd Meijer         continue;
25530fbb069SSjoerd Meijer       if (II->getIntrinsicID() != Intrinsic::ssa_copy)
25630fbb069SSjoerd Meijer         continue;
257d9e46beaSKazu Hirata       Inst.replaceAllUsesWith(II->getOperand(0));
258d9e46beaSKazu Hirata       Inst.eraseFromParent();
25930fbb069SSjoerd Meijer     }
26030fbb069SSjoerd Meijer   }
26130fbb069SSjoerd Meijer }
26230fbb069SSjoerd Meijer 
removeSSACopy(Module & M)26330fbb069SSjoerd Meijer static void removeSSACopy(Module &M) {
26430fbb069SSjoerd Meijer   for (Function &F : M)
26530fbb069SSjoerd Meijer     removeSSACopy(F);
2669907746fSSjoerd Meijer }
2679907746fSSjoerd Meijer 
2689b8b1645SBenjamin Kramer namespace {
2699907746fSSjoerd Meijer class FunctionSpecializer {
2709907746fSSjoerd Meijer 
2719907746fSSjoerd Meijer   /// The IPSCCP Solver.
2729907746fSSjoerd Meijer   SCCPSolver &Solver;
2739907746fSSjoerd Meijer 
2749907746fSSjoerd Meijer   /// Analyses used to help determine if a function should be specialized.
2759907746fSSjoerd Meijer   std::function<AssumptionCache &(Function &)> GetAC;
2769907746fSSjoerd Meijer   std::function<TargetTransformInfo &(Function &)> GetTTI;
2779907746fSSjoerd Meijer   std::function<TargetLibraryInfo &(Function &)> GetTLI;
2789907746fSSjoerd Meijer 
27933830326SAlexandros Lamprineas   SmallPtrSet<Function *, 4> SpecializedFuncs;
28033830326SAlexandros Lamprineas   SmallPtrSet<Function *, 4> FullySpecialized;
281438a81a2SAlexandros Lamprineas   SmallVector<Instruction *> ReplacedWithConstant;
282f364278cSAlexandros Lamprineas   DenseMap<Function *, CodeMetrics> FunctionMetrics;
2839907746fSSjoerd Meijer 
2849907746fSSjoerd Meijer public:
FunctionSpecializer(SCCPSolver & Solver,std::function<AssumptionCache & (Function &)> GetAC,std::function<TargetTransformInfo & (Function &)> GetTTI,std::function<TargetLibraryInfo & (Function &)> GetTLI)2859907746fSSjoerd Meijer   FunctionSpecializer(SCCPSolver &Solver,
2869907746fSSjoerd Meijer                       std::function<AssumptionCache &(Function &)> GetAC,
2879907746fSSjoerd Meijer                       std::function<TargetTransformInfo &(Function &)> GetTTI,
2889907746fSSjoerd Meijer                       std::function<TargetLibraryInfo &(Function &)> GetTLI)
2899907746fSSjoerd Meijer       : Solver(Solver), GetAC(GetAC), GetTTI(GetTTI), GetTLI(GetTLI) {}
2909907746fSSjoerd Meijer 
~FunctionSpecializer()29133830326SAlexandros Lamprineas   ~FunctionSpecializer() {
29233830326SAlexandros Lamprineas     // Eliminate dead code.
29333830326SAlexandros Lamprineas     removeDeadInstructions();
29433830326SAlexandros Lamprineas     removeDeadFunctions();
29533830326SAlexandros Lamprineas   }
29633830326SAlexandros Lamprineas 
2979907746fSSjoerd Meijer   /// Attempt to specialize functions in the module to enable constant
2989907746fSSjoerd Meijer   /// propagation across function boundaries.
2999907746fSSjoerd Meijer   ///
3009907746fSSjoerd Meijer   /// \returns true if at least one function is specialized.
specializeFunctions(FuncList & Candidates,FuncList & WorkList)3017b74123aSAlexandros Lamprineas   bool specializeFunctions(FuncList &Candidates, FuncList &WorkList) {
3029907746fSSjoerd Meijer     bool Changed = false;
3037b74123aSAlexandros Lamprineas     for (auto *F : Candidates) {
3047b74123aSAlexandros Lamprineas       if (!isCandidateFunction(F))
30589bcfd16SSjoerd Meijer         continue;
30689bcfd16SSjoerd Meijer 
30789bcfd16SSjoerd Meijer       auto Cost = getSpecializationCost(F);
30889bcfd16SSjoerd Meijer       if (!Cost.isValid()) {
3095b139a58SSjoerd Meijer         LLVM_DEBUG(
310a687f96bSAlexandros Lamprineas             dbgs() << "FnSpecialization: Invalid specialization cost.\n");
31189bcfd16SSjoerd Meijer         continue;
31289bcfd16SSjoerd Meijer       }
31389bcfd16SSjoerd Meijer 
314b803aee6SAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization: Specialization cost for "
315b803aee6SAlexandros Lamprineas                         << F->getName() << " is " << Cost << "\n");
316b803aee6SAlexandros Lamprineas 
3178045bf9dSAlexandros Lamprineas       SmallVector<CallSpecBinding, 8> Specializations;
3188045bf9dSAlexandros Lamprineas       if (!calculateGains(F, Cost, Specializations)) {
3198045bf9dSAlexandros Lamprineas         LLVM_DEBUG(dbgs() << "FnSpecialization: No possible constants found\n");
32089bcfd16SSjoerd Meijer         continue;
32189bcfd16SSjoerd Meijer       }
32289bcfd16SSjoerd Meijer 
32389bcfd16SSjoerd Meijer       Changed = true;
3248045bf9dSAlexandros Lamprineas       for (auto &Entry : Specializations)
3258045bf9dSAlexandros Lamprineas         specializeFunction(F, Entry.second, WorkList);
3269907746fSSjoerd Meijer     }
3279907746fSSjoerd Meijer 
3287b74123aSAlexandros Lamprineas     updateSpecializedFuncs(Candidates, WorkList);
32949ab3b17SSjoerd Meijer     NumFuncSpecialized += NbFunctionsSpecialized;
3309907746fSSjoerd Meijer     return Changed;
3319907746fSSjoerd Meijer   }
3329907746fSSjoerd Meijer 
removeDeadInstructions()333438a81a2SAlexandros Lamprineas   void removeDeadInstructions() {
334438a81a2SAlexandros Lamprineas     for (auto *I : ReplacedWithConstant) {
335a687f96bSAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization: Removing dead instruction " << *I
336a687f96bSAlexandros Lamprineas                         << "\n");
337438a81a2SAlexandros Lamprineas       I->eraseFromParent();
338438a81a2SAlexandros Lamprineas     }
339438a81a2SAlexandros Lamprineas     ReplacedWithConstant.clear();
340438a81a2SAlexandros Lamprineas   }
341438a81a2SAlexandros Lamprineas 
removeDeadFunctions()34233830326SAlexandros Lamprineas   void removeDeadFunctions() {
34333830326SAlexandros Lamprineas     for (auto *F : FullySpecialized) {
34433830326SAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization: Removing dead function "
34533830326SAlexandros Lamprineas                         << F->getName() << "\n");
34633830326SAlexandros Lamprineas       F->eraseFromParent();
34733830326SAlexandros Lamprineas     }
34833830326SAlexandros Lamprineas     FullySpecialized.clear();
34933830326SAlexandros Lamprineas   }
35033830326SAlexandros Lamprineas 
tryToReplaceWithConstant(Value * V)3519907746fSSjoerd Meijer   bool tryToReplaceWithConstant(Value *V) {
3529907746fSSjoerd Meijer     if (!V->getType()->isSingleValueType() || isa<CallBase>(V) ||
3539907746fSSjoerd Meijer         V->user_empty())
3549907746fSSjoerd Meijer       return false;
3559907746fSSjoerd Meijer 
3569907746fSSjoerd Meijer     const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
3579907746fSSjoerd Meijer     if (isOverdefined(IV))
3589907746fSSjoerd Meijer       return false;
35930fbb069SSjoerd Meijer     auto *Const =
36030fbb069SSjoerd Meijer         isConstant(IV) ? Solver.getConstant(IV) : UndefValue::get(V->getType());
361438a81a2SAlexandros Lamprineas 
362438a81a2SAlexandros Lamprineas     LLVM_DEBUG(dbgs() << "FnSpecialization: Replacing " << *V
363438a81a2SAlexandros Lamprineas                       << "\nFnSpecialization: with " << *Const << "\n");
364438a81a2SAlexandros Lamprineas 
365dfec0b30SBin Cheng     // Record uses of V to avoid visiting irrelevant uses of const later.
366dfec0b30SBin Cheng     SmallVector<Instruction *> UseInsts;
367dfec0b30SBin Cheng     for (auto *U : V->users())
36830fbb069SSjoerd Meijer       if (auto *I = dyn_cast<Instruction>(U))
36930fbb069SSjoerd Meijer         if (Solver.isBlockExecutable(I->getParent()))
370dfec0b30SBin Cheng           UseInsts.push_back(I);
371dfec0b30SBin Cheng 
372dfec0b30SBin Cheng     V->replaceAllUsesWith(Const);
373dfec0b30SBin Cheng 
374dfec0b30SBin Cheng     for (auto *I : UseInsts)
37530fbb069SSjoerd Meijer       Solver.visit(I);
37630fbb069SSjoerd Meijer 
37730fbb069SSjoerd Meijer     // Remove the instruction from Block and Solver.
37830fbb069SSjoerd Meijer     if (auto *I = dyn_cast<Instruction>(V)) {
37930fbb069SSjoerd Meijer       if (I->isSafeToRemove()) {
380438a81a2SAlexandros Lamprineas         ReplacedWithConstant.push_back(I);
38130fbb069SSjoerd Meijer         Solver.removeLatticeValueFor(I);
38230fbb069SSjoerd Meijer       }
38330fbb069SSjoerd Meijer     }
3849907746fSSjoerd Meijer     return true;
3859907746fSSjoerd Meijer   }
3869907746fSSjoerd Meijer 
3879907746fSSjoerd Meijer private:
38849ab3b17SSjoerd Meijer   // The number of functions specialised, used for collecting statistics and
38949ab3b17SSjoerd Meijer   // also in the cost model.
39049ab3b17SSjoerd Meijer   unsigned NbFunctionsSpecialized = 0;
39149ab3b17SSjoerd Meijer 
392f364278cSAlexandros Lamprineas   // Compute the code metrics for function \p F.
analyzeFunction(Function * F)393f364278cSAlexandros Lamprineas   CodeMetrics &analyzeFunction(Function *F) {
394f364278cSAlexandros Lamprineas     auto I = FunctionMetrics.insert({F, CodeMetrics()});
395f364278cSAlexandros Lamprineas     CodeMetrics &Metrics = I.first->second;
396f364278cSAlexandros Lamprineas     if (I.second) {
397f364278cSAlexandros Lamprineas       // The code metrics were not cached.
398f364278cSAlexandros Lamprineas       SmallPtrSet<const Value *, 32> EphValues;
399f364278cSAlexandros Lamprineas       CodeMetrics::collectEphemeralValues(F, &(GetAC)(*F), EphValues);
400f364278cSAlexandros Lamprineas       for (BasicBlock &BB : *F)
401f364278cSAlexandros Lamprineas         Metrics.analyzeBasicBlock(&BB, (GetTTI)(*F), EphValues);
402f364278cSAlexandros Lamprineas 
403f364278cSAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization: Code size of function "
404f364278cSAlexandros Lamprineas                         << F->getName() << " is " << Metrics.NumInsts
405f364278cSAlexandros Lamprineas                         << " instructions\n");
406f364278cSAlexandros Lamprineas     }
407f364278cSAlexandros Lamprineas     return Metrics;
408f364278cSAlexandros Lamprineas   }
409f364278cSAlexandros Lamprineas 
41030fbb069SSjoerd Meijer   /// Clone the function \p F and remove the ssa_copy intrinsics added by
41130fbb069SSjoerd Meijer   /// the SCCPSolver in the cloned version.
cloneCandidateFunction(Function * F,ValueToValueMapTy & Mappings)412910eb988SAlexandros Lamprineas   Function *cloneCandidateFunction(Function *F, ValueToValueMapTy &Mappings) {
413910eb988SAlexandros Lamprineas     Function *Clone = CloneFunction(F, Mappings);
41430fbb069SSjoerd Meijer     removeSSACopy(*Clone);
41530fbb069SSjoerd Meijer     return Clone;
41630fbb069SSjoerd Meijer   }
41730fbb069SSjoerd Meijer 
4188045bf9dSAlexandros Lamprineas   /// This function decides whether it's worthwhile to specialize function
4198045bf9dSAlexandros Lamprineas   /// \p F based on the known constant values its arguments can take on. It
4208045bf9dSAlexandros Lamprineas   /// only discovers potential specialization opportunities without actually
4218045bf9dSAlexandros Lamprineas   /// applying them.
4228045bf9dSAlexandros Lamprineas   ///
4238045bf9dSAlexandros Lamprineas   /// \returns true if any specializations have been found.
calculateGains(Function * F,InstructionCost Cost,SmallVectorImpl<CallSpecBinding> & WorkList)4248045bf9dSAlexandros Lamprineas   bool calculateGains(Function *F, InstructionCost Cost,
4258045bf9dSAlexandros Lamprineas                       SmallVectorImpl<CallSpecBinding> &WorkList) {
4268045bf9dSAlexandros Lamprineas     SpecializationMap Specializations;
42789bcfd16SSjoerd Meijer     // Determine if we should specialize the function based on the values the
42889bcfd16SSjoerd Meijer     // argument can take on. If specialization is not profitable, we continue
42989bcfd16SSjoerd Meijer     // on to the next argument.
43089bcfd16SSjoerd Meijer     for (Argument &FormalArg : F->args()) {
43189bcfd16SSjoerd Meijer       // Determine if this argument is interesting. If we know the argument can
432910eb988SAlexandros Lamprineas       // take on any constant values, they are collected in Constants.
4338045bf9dSAlexandros Lamprineas       SmallVector<CallArgBinding, 8> ActualArgs;
434910eb988SAlexandros Lamprineas       if (!isArgumentInteresting(&FormalArg, ActualArgs)) {
435b803aee6SAlexandros Lamprineas         LLVM_DEBUG(dbgs() << "FnSpecialization: Argument "
436b803aee6SAlexandros Lamprineas                           << FormalArg.getNameOrAsOperand()
437b803aee6SAlexandros Lamprineas                           << " is not interesting\n");
43889bcfd16SSjoerd Meijer         continue;
43989bcfd16SSjoerd Meijer       }
4405b139a58SSjoerd Meijer 
4418045bf9dSAlexandros Lamprineas       for (const auto &Entry : ActualArgs) {
4428045bf9dSAlexandros Lamprineas         CallBase *Call = Entry.first;
4438045bf9dSAlexandros Lamprineas         Constant *ActualArg = Entry.second;
44489bcfd16SSjoerd Meijer 
4458045bf9dSAlexandros Lamprineas         auto I = Specializations.insert({Call, SpecializationInfo()});
4468045bf9dSAlexandros Lamprineas         SpecializationInfo &S = I.first->second;
4478045bf9dSAlexandros Lamprineas 
4488045bf9dSAlexandros Lamprineas         if (I.second)
4498045bf9dSAlexandros Lamprineas           S.Gain = ForceFunctionSpecialization ? 1 : 0 - Cost;
4508045bf9dSAlexandros Lamprineas         if (!ForceFunctionSpecialization)
4518045bf9dSAlexandros Lamprineas           S.Gain += getSpecializationBonus(&FormalArg, ActualArg);
4528045bf9dSAlexandros Lamprineas         S.Args.push_back({&FormalArg, ActualArg});
4538045bf9dSAlexandros Lamprineas       }
45489bcfd16SSjoerd Meijer     }
45589bcfd16SSjoerd Meijer 
4568045bf9dSAlexandros Lamprineas     // Remove unprofitable specializations.
4578045bf9dSAlexandros Lamprineas     Specializations.remove_if(
4588045bf9dSAlexandros Lamprineas         [](const auto &Entry) { return Entry.second.Gain <= 0; });
4598045bf9dSAlexandros Lamprineas 
4608045bf9dSAlexandros Lamprineas     // Clear the MapVector and return the underlying vector.
4618045bf9dSAlexandros Lamprineas     WorkList = Specializations.takeVector();
46289bcfd16SSjoerd Meijer 
46389bcfd16SSjoerd Meijer     // Sort the candidates in descending order.
4648045bf9dSAlexandros Lamprineas     llvm::stable_sort(WorkList, [](const auto &L, const auto &R) {
4658045bf9dSAlexandros Lamprineas       return L.second.Gain > R.second.Gain;
46689bcfd16SSjoerd Meijer     });
46789bcfd16SSjoerd Meijer 
4688045bf9dSAlexandros Lamprineas     // Truncate the worklist to 'MaxClonesThreshold' candidates if necessary.
469910eb988SAlexandros Lamprineas     if (WorkList.size() > MaxClonesThreshold) {
470b803aee6SAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization: Number of candidates exceed "
4719e3ae8d2SSjoerd Meijer                         << "the maximum number of clones threshold.\n"
472b803aee6SAlexandros Lamprineas                         << "FnSpecialization: Truncating worklist to "
473b803aee6SAlexandros Lamprineas                         << MaxClonesThreshold << " candidates.\n");
474910eb988SAlexandros Lamprineas       WorkList.erase(WorkList.begin() + MaxClonesThreshold, WorkList.end());
47589bcfd16SSjoerd Meijer     }
47689bcfd16SSjoerd Meijer 
477910eb988SAlexandros Lamprineas     LLVM_DEBUG(dbgs() << "FnSpecialization: Specializations for function "
478b803aee6SAlexandros Lamprineas                       << F->getName() << "\n";
4798045bf9dSAlexandros Lamprineas                for (const auto &Entry
480a687f96bSAlexandros Lamprineas                     : WorkList) {
4818045bf9dSAlexandros Lamprineas                  dbgs() << "FnSpecialization:   Gain = " << Entry.second.Gain
4828045bf9dSAlexandros Lamprineas                         << "\n";
4838045bf9dSAlexandros Lamprineas                  for (const ArgInfo &Arg : Entry.second.Args)
484b803aee6SAlexandros Lamprineas                    dbgs() << "FnSpecialization:   FormalArg = "
4858045bf9dSAlexandros Lamprineas                           << Arg.Formal->getNameOrAsOperand()
486910eb988SAlexandros Lamprineas                           << ", ActualArg = "
4878045bf9dSAlexandros Lamprineas                           << Arg.Actual->getNameOrAsOperand() << "\n";
488910eb988SAlexandros Lamprineas                });
48989bcfd16SSjoerd Meijer 
4908045bf9dSAlexandros Lamprineas     return !WorkList.empty();
49189bcfd16SSjoerd Meijer   }
49289bcfd16SSjoerd Meijer 
isCandidateFunction(Function * F)4937b74123aSAlexandros Lamprineas   bool isCandidateFunction(Function *F) {
4949907746fSSjoerd Meijer     // Do not specialize the cloned function again.
495ecff9e3dSSjoerd Meijer     if (SpecializedFuncs.contains(F))
4969907746fSSjoerd Meijer       return false;
4979907746fSSjoerd Meijer 
4989907746fSSjoerd Meijer     // If we're optimizing the function for size, we shouldn't specialize it.
4999907746fSSjoerd Meijer     if (F->hasOptSize() ||
5009907746fSSjoerd Meijer         shouldOptimizeForSize(F, nullptr, nullptr, PGSOQueryType::IRPass))
5019907746fSSjoerd Meijer       return false;
5029907746fSSjoerd Meijer 
5039907746fSSjoerd Meijer     // Exit if the function is not executable. There's no point in specializing
5049907746fSSjoerd Meijer     // a dead function.
5059907746fSSjoerd Meijer     if (!Solver.isBlockExecutable(&F->getEntryBlock()))
5069907746fSSjoerd Meijer       return false;
5079907746fSSjoerd Meijer 
5082556f581SChuanqi Xu     // It wastes time to specialize a function which would get inlined finally.
5092556f581SChuanqi Xu     if (F->hasFnAttribute(Attribute::AlwaysInline))
5102556f581SChuanqi Xu       return false;
5112556f581SChuanqi Xu 
5129907746fSSjoerd Meijer     LLVM_DEBUG(dbgs() << "FnSpecialization: Try function: " << F->getName()
5139907746fSSjoerd Meijer                       << "\n");
51489bcfd16SSjoerd Meijer     return true;
515cc3f40bbSChuanqi Xu   }
516cc3f40bbSChuanqi Xu 
specializeFunction(Function * F,SpecializationInfo & S,FuncList & WorkList)517910eb988SAlexandros Lamprineas   void specializeFunction(Function *F, SpecializationInfo &S,
518910eb988SAlexandros Lamprineas                           FuncList &WorkList) {
519910eb988SAlexandros Lamprineas     ValueToValueMapTy Mappings;
520910eb988SAlexandros Lamprineas     Function *Clone = cloneCandidateFunction(F, Mappings);
5219907746fSSjoerd Meijer 
5229907746fSSjoerd Meijer     // Rewrite calls to the function so that they call the clone instead.
5238045bf9dSAlexandros Lamprineas     rewriteCallSites(Clone, S.Args, Mappings);
5249907746fSSjoerd Meijer 
5259907746fSSjoerd Meijer     // Initialize the lattice state of the arguments of the function clone,
5269907746fSSjoerd Meijer     // marking the argument on which we specialized the function constant
5279907746fSSjoerd Meijer     // with the given value.
5288045bf9dSAlexandros Lamprineas     Solver.markArgInFuncSpecialization(Clone, S.Args);
5299907746fSSjoerd Meijer 
5309907746fSSjoerd Meijer     // Mark all the specialized functions
5317b74123aSAlexandros Lamprineas     WorkList.push_back(Clone);
53249ab3b17SSjoerd Meijer     NbFunctionsSpecialized++;
5339907746fSSjoerd Meijer 
53430fbb069SSjoerd Meijer     // If the function has been completely specialized, the original function
53530fbb069SSjoerd Meijer     // is no longer needed. Mark it unreachable.
536910eb988SAlexandros Lamprineas     if (F->getNumUses() == 0 || all_of(F->users(), [F](User *U) {
53733830326SAlexandros Lamprineas           if (auto *CS = dyn_cast<CallBase>(U))
538910eb988SAlexandros Lamprineas             return CS->getFunction() == F;
53933830326SAlexandros Lamprineas           return false;
54033830326SAlexandros Lamprineas         })) {
541910eb988SAlexandros Lamprineas       Solver.markFunctionUnreachable(F);
542910eb988SAlexandros Lamprineas       FullySpecialized.insert(F);
54333830326SAlexandros Lamprineas     }
5449907746fSSjoerd Meijer   }
5459907746fSSjoerd Meijer 
54689bcfd16SSjoerd Meijer   /// Compute and return the cost of specializing function \p F.
getSpecializationCost(Function * F)5479907746fSSjoerd Meijer   InstructionCost getSpecializationCost(Function *F) {
548f364278cSAlexandros Lamprineas     CodeMetrics &Metrics = analyzeFunction(F);
5499907746fSSjoerd Meijer     // If the code metrics reveal that we shouldn't duplicate the function, we
550342bbb78SSjoerd Meijer     // shouldn't specialize it. Set the specialization cost to Invalid.
5512556f581SChuanqi Xu     // Or if the lines of codes implies that this function is easy to get
5522556f581SChuanqi Xu     // inlined so that we shouldn't specialize it.
553f85c5079SPhilip Reames     if (Metrics.notDuplicatable || !Metrics.NumInsts.isValid() ||
5542556f581SChuanqi Xu         (!ForceFunctionSpecialization &&
555f85c5079SPhilip Reames          *Metrics.NumInsts.getValue() < SmallFunctionThreshold)) {
556342bbb78SSjoerd Meijer       InstructionCost C{};
557342bbb78SSjoerd Meijer       C.setInvalid();
558342bbb78SSjoerd Meijer       return C;
559342bbb78SSjoerd Meijer     }
5609907746fSSjoerd Meijer 
5619907746fSSjoerd Meijer     // Otherwise, set the specialization cost to be the cost of all the
5629907746fSSjoerd Meijer     // instructions in the function and penalty for specializing more functions.
56349ab3b17SSjoerd Meijer     unsigned Penalty = NbFunctionsSpecialized + 1;
5649907746fSSjoerd Meijer     return Metrics.NumInsts * InlineConstants::InstrCost * Penalty;
5659907746fSSjoerd Meijer   }
5669907746fSSjoerd Meijer 
getUserBonus(User * U,llvm::TargetTransformInfo & TTI,LoopInfo & LI)5679907746fSSjoerd Meijer   InstructionCost getUserBonus(User *U, llvm::TargetTransformInfo &TTI,
5689907746fSSjoerd Meijer                                LoopInfo &LI) {
5699907746fSSjoerd Meijer     auto *I = dyn_cast_or_null<Instruction>(U);
5709907746fSSjoerd Meijer     // If not an instruction we do not know how to evaluate.
5719907746fSSjoerd Meijer     // Keep minimum possible cost for now so that it doesnt affect
5729907746fSSjoerd Meijer     // specialization.
5739907746fSSjoerd Meijer     if (!I)
5749907746fSSjoerd Meijer       return std::numeric_limits<unsigned>::min();
5759907746fSSjoerd Meijer 
5769907746fSSjoerd Meijer     auto Cost = TTI.getUserCost(U, TargetTransformInfo::TCK_SizeAndLatency);
5779907746fSSjoerd Meijer 
5789907746fSSjoerd Meijer     // Traverse recursively if there are more uses.
5799907746fSSjoerd Meijer     // TODO: Any other instructions to be added here?
5809907746fSSjoerd Meijer     if (I->mayReadFromMemory() || I->isCast())
5819907746fSSjoerd Meijer       for (auto *User : I->users())
5829907746fSSjoerd Meijer         Cost += getUserBonus(User, TTI, LI);
5839907746fSSjoerd Meijer 
5849907746fSSjoerd Meijer     // Increase the cost if it is inside the loop.
58586906304SChuanqi Xu     auto LoopDepth = LI.getLoopDepth(I->getParent());
58686906304SChuanqi Xu     Cost *= std::pow((double)AvgLoopIterationCount, LoopDepth);
5879907746fSSjoerd Meijer     return Cost;
5889907746fSSjoerd Meijer   }
5899907746fSSjoerd Meijer 
5909907746fSSjoerd Meijer   /// Compute a bonus for replacing argument \p A with constant \p C.
getSpecializationBonus(Argument * A,Constant * C)5919907746fSSjoerd Meijer   InstructionCost getSpecializationBonus(Argument *A, Constant *C) {
5929907746fSSjoerd Meijer     Function *F = A->getParent();
5939907746fSSjoerd Meijer     DominatorTree DT(*F);
5949907746fSSjoerd Meijer     LoopInfo LI(DT);
5959907746fSSjoerd Meijer     auto &TTI = (GetTTI)(*F);
596b803aee6SAlexandros Lamprineas     LLVM_DEBUG(dbgs() << "FnSpecialization: Analysing bonus for constant: "
597b803aee6SAlexandros Lamprineas                       << C->getNameOrAsOperand() << "\n");
5989907746fSSjoerd Meijer 
5999907746fSSjoerd Meijer     InstructionCost TotalCost = 0;
6009907746fSSjoerd Meijer     for (auto *U : A->users()) {
6019907746fSSjoerd Meijer       TotalCost += getUserBonus(U, TTI, LI);
6029907746fSSjoerd Meijer       LLVM_DEBUG(dbgs() << "FnSpecialization:   User cost ";
6039907746fSSjoerd Meijer                  TotalCost.print(dbgs()); dbgs() << " for: " << *U << "\n");
6049907746fSSjoerd Meijer     }
6059907746fSSjoerd Meijer 
6069907746fSSjoerd Meijer     // The below heuristic is only concerned with exposing inlining
6079907746fSSjoerd Meijer     // opportunities via indirect call promotion. If the argument is not a
6081b6663a1SNikita Popov     // (potentially casted) function pointer, give up.
6091b6663a1SNikita Popov     Function *CalledFunction = dyn_cast<Function>(C->stripPointerCasts());
6109907746fSSjoerd Meijer     if (!CalledFunction)
6119907746fSSjoerd Meijer       return TotalCost;
6129907746fSSjoerd Meijer 
6139907746fSSjoerd Meijer     // Get TTI for the called function (used for the inline cost).
6149907746fSSjoerd Meijer     auto &CalleeTTI = (GetTTI)(*CalledFunction);
6159907746fSSjoerd Meijer 
6169907746fSSjoerd Meijer     // Look at all the call sites whose called value is the argument.
6179907746fSSjoerd Meijer     // Specializing the function on the argument would allow these indirect
6189907746fSSjoerd Meijer     // calls to be promoted to direct calls. If the indirect call promotion
6199907746fSSjoerd Meijer     // would likely enable the called function to be inlined, specializing is a
6209907746fSSjoerd Meijer     // good idea.
6219907746fSSjoerd Meijer     int Bonus = 0;
6229907746fSSjoerd Meijer     for (User *U : A->users()) {
6239907746fSSjoerd Meijer       if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
6249907746fSSjoerd Meijer         continue;
6259907746fSSjoerd Meijer       auto *CS = cast<CallBase>(U);
6269907746fSSjoerd Meijer       if (CS->getCalledOperand() != A)
6279907746fSSjoerd Meijer         continue;
6289907746fSSjoerd Meijer 
6299907746fSSjoerd Meijer       // Get the cost of inlining the called function at this call site. Note
6309907746fSSjoerd Meijer       // that this is only an estimate. The called function may eventually
6319907746fSSjoerd Meijer       // change in a way that leads to it not being inlined here, even though
6329907746fSSjoerd Meijer       // inlining looks profitable now. For example, one of its called
6339907746fSSjoerd Meijer       // functions may be inlined into it, making the called function too large
6349907746fSSjoerd Meijer       // to be inlined into this call site.
6359907746fSSjoerd Meijer       //
6369907746fSSjoerd Meijer       // We apply a boost for performing indirect call promotion by increasing
6379907746fSSjoerd Meijer       // the default threshold by the threshold for indirect calls.
6389907746fSSjoerd Meijer       auto Params = getInlineParams();
6399907746fSSjoerd Meijer       Params.DefaultThreshold += InlineConstants::IndirectCallThreshold;
6409907746fSSjoerd Meijer       InlineCost IC =
6419907746fSSjoerd Meijer           getInlineCost(*CS, CalledFunction, Params, CalleeTTI, GetAC, GetTLI);
6429907746fSSjoerd Meijer 
6439907746fSSjoerd Meijer       // We clamp the bonus for this call to be between zero and the default
6449907746fSSjoerd Meijer       // threshold.
6459907746fSSjoerd Meijer       if (IC.isAlways())
6469907746fSSjoerd Meijer         Bonus += Params.DefaultThreshold;
6479907746fSSjoerd Meijer       else if (IC.isVariable() && IC.getCostDelta() > 0)
6489907746fSSjoerd Meijer         Bonus += IC.getCostDelta();
649b803aee6SAlexandros Lamprineas 
650b803aee6SAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization:   Inlining bonus " << Bonus
651b803aee6SAlexandros Lamprineas                         << " for user " << *U << "\n");
6529907746fSSjoerd Meijer     }
6539907746fSSjoerd Meijer 
6549907746fSSjoerd Meijer     return TotalCost + Bonus;
6559907746fSSjoerd Meijer   }
6569907746fSSjoerd Meijer 
6579907746fSSjoerd Meijer   /// Determine if we should specialize a function based on the incoming values
6589907746fSSjoerd Meijer   /// of the given argument.
6599907746fSSjoerd Meijer   ///
6609907746fSSjoerd Meijer   /// This function implements the goal-directed heuristic. It determines if
6619907746fSSjoerd Meijer   /// specializing the function based on the incoming values of argument \p A
6629907746fSSjoerd Meijer   /// would result in any significant optimization opportunities. If
6639907746fSSjoerd Meijer   /// optimization opportunities exist, the constant values of \p A on which to
664910eb988SAlexandros Lamprineas   /// specialize the function are collected in \p Constants.
6659907746fSSjoerd Meijer   ///
6669907746fSSjoerd Meijer   /// \returns true if the function should be specialized on the given
6679907746fSSjoerd Meijer   /// argument.
isArgumentInteresting(Argument * A,SmallVectorImpl<CallArgBinding> & Constants)6688045bf9dSAlexandros Lamprineas   bool isArgumentInteresting(Argument *A,
6698045bf9dSAlexandros Lamprineas                              SmallVectorImpl<CallArgBinding> &Constants) {
6709907746fSSjoerd Meijer     // For now, don't attempt to specialize functions based on the values of
6719907746fSSjoerd Meijer     // composite types.
6729907746fSSjoerd Meijer     if (!A->getType()->isSingleValueType() || A->user_empty())
6739907746fSSjoerd Meijer       return false;
6749907746fSSjoerd Meijer 
6759907746fSSjoerd Meijer     // If the argument isn't overdefined, there's nothing to do. It should
6769907746fSSjoerd Meijer     // already be constant.
6779907746fSSjoerd Meijer     if (!Solver.getLatticeValueFor(A).isOverdefined()) {
678b803aee6SAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization: Nothing to do, argument "
679b803aee6SAlexandros Lamprineas                         << A->getNameOrAsOperand()
680b803aee6SAlexandros Lamprineas                         << " is already constant?\n");
6819907746fSSjoerd Meijer       return false;
6829907746fSSjoerd Meijer     }
6839907746fSSjoerd Meijer 
6849907746fSSjoerd Meijer     // Collect the constant values that the argument can take on. If the
6859907746fSSjoerd Meijer     // argument can't take on any constant values, we aren't going to
6869907746fSSjoerd Meijer     // specialize the function. While it's possible to specialize the function
6879907746fSSjoerd Meijer     // based on non-constant arguments, there's likely not much benefit to
6889907746fSSjoerd Meijer     // constant propagation in doing so.
6899907746fSSjoerd Meijer     //
6909907746fSSjoerd Meijer     // TODO 1: currently it won't specialize if there are over the threshold of
6919907746fSSjoerd Meijer     // calls using the same argument, e.g foo(a) x 4 and foo(b) x 1, but it
6929907746fSSjoerd Meijer     // might be beneficial to take the occurrences into account in the cost
6939907746fSSjoerd Meijer     // model, so we would need to find the unique constants.
6949907746fSSjoerd Meijer     //
6959907746fSSjoerd Meijer     // TODO 2: this currently does not support constants, i.e. integer ranges.
6969907746fSSjoerd Meijer     //
697910eb988SAlexandros Lamprineas     getPossibleConstants(A, Constants);
698910eb988SAlexandros Lamprineas 
699910eb988SAlexandros Lamprineas     if (Constants.empty())
700910eb988SAlexandros Lamprineas       return false;
701910eb988SAlexandros Lamprineas 
702b803aee6SAlexandros Lamprineas     LLVM_DEBUG(dbgs() << "FnSpecialization: Found interesting argument "
703b803aee6SAlexandros Lamprineas                       << A->getNameOrAsOperand() << "\n");
7049907746fSSjoerd Meijer     return true;
7059907746fSSjoerd Meijer   }
7069907746fSSjoerd Meijer 
7079907746fSSjoerd Meijer   /// Collect in \p Constants all the constant values that argument \p A can
7089907746fSSjoerd Meijer   /// take on.
getPossibleConstants(Argument * A,SmallVectorImpl<CallArgBinding> & Constants)7098045bf9dSAlexandros Lamprineas   void getPossibleConstants(Argument *A,
7108045bf9dSAlexandros Lamprineas                             SmallVectorImpl<CallArgBinding> &Constants) {
7119907746fSSjoerd Meijer     Function *F = A->getParent();
7129907746fSSjoerd Meijer 
713*8b360c69SBin Cheng     // SCCP solver does not record an argument that will be constructed on
714*8b360c69SBin Cheng     // stack.
715*8b360c69SBin Cheng     if (A->hasByValAttr() && !F->onlyReadsMemory())
716*8b360c69SBin Cheng       return;
717*8b360c69SBin Cheng 
7189907746fSSjoerd Meijer     // Iterate over all the call sites of the argument's parent function.
7199907746fSSjoerd Meijer     for (User *U : F->users()) {
7209907746fSSjoerd Meijer       if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
7219907746fSSjoerd Meijer         continue;
7229907746fSSjoerd Meijer       auto &CS = *cast<CallBase>(U);
7234f9217c5SSjoerd Meijer       // If the call site has attribute minsize set, that callsite won't be
7244f9217c5SSjoerd Meijer       // specialized.
725910eb988SAlexandros Lamprineas       if (CS.hasFnAttr(Attribute::MinSize))
7264f9217c5SSjoerd Meijer         continue;
7279907746fSSjoerd Meijer 
7289907746fSSjoerd Meijer       // If the parent of the call site will never be executed, we don't need
7299907746fSSjoerd Meijer       // to worry about the passed value.
7309907746fSSjoerd Meijer       if (!Solver.isBlockExecutable(CS.getParent()))
7319907746fSSjoerd Meijer         continue;
7329907746fSSjoerd Meijer 
7339907746fSSjoerd Meijer       auto *V = CS.getArgOperand(A->getArgNo());
734eba76056SSjoerd Meijer       if (isa<PoisonValue>(V))
735910eb988SAlexandros Lamprineas         return;
736fc0fa851SSjoerd Meijer 
7379907746fSSjoerd Meijer       // TrackValueOfGlobalVariable only tracks scalar global variables.
73897cc678cSSjoerd Meijer       if (auto *GV = dyn_cast<GlobalVariable>(V)) {
73997cc678cSSjoerd Meijer         // Check if we want to specialize on the address of non-constant
74097cc678cSSjoerd Meijer         // global values.
74197cc678cSSjoerd Meijer         if (!GV->isConstant())
74297cc678cSSjoerd Meijer           if (!SpecializeOnAddresses)
743910eb988SAlexandros Lamprineas             return;
74497cc678cSSjoerd Meijer 
745ecff9e3dSSjoerd Meijer         if (!GV->getValueType()->isSingleValueType())
746910eb988SAlexandros Lamprineas           return;
74797cc678cSSjoerd Meijer       }
7489907746fSSjoerd Meijer 
749801c2b9bSChuanqi Xu       if (isa<Constant>(V) && (Solver.getLatticeValueFor(V).isConstant() ||
750801c2b9bSChuanqi Xu                                EnableSpecializationForLiteralConstant))
7518045bf9dSAlexandros Lamprineas         Constants.push_back({&CS, cast<Constant>(V)});
7529907746fSSjoerd Meijer     }
7539907746fSSjoerd Meijer   }
7549907746fSSjoerd Meijer 
7559907746fSSjoerd Meijer   /// Rewrite calls to function \p F to call function \p Clone instead.
7569907746fSSjoerd Meijer   ///
757910eb988SAlexandros Lamprineas   /// This function modifies calls to function \p F as long as the actual
7588045bf9dSAlexandros Lamprineas   /// arguments match those in \p Args. Note that for recursive calls we
7598045bf9dSAlexandros Lamprineas   /// need to compare against the cloned formal arguments.
7604f9217c5SSjoerd Meijer   ///
7614f9217c5SSjoerd Meijer   /// Callsites that have been marked with the MinSize function attribute won't
7624f9217c5SSjoerd Meijer   /// be specialized and rewritten.
rewriteCallSites(Function * Clone,const SmallVectorImpl<ArgInfo> & Args,ValueToValueMapTy & Mappings)7638045bf9dSAlexandros Lamprineas   void rewriteCallSites(Function *Clone, const SmallVectorImpl<ArgInfo> &Args,
764910eb988SAlexandros Lamprineas                         ValueToValueMapTy &Mappings) {
7658045bf9dSAlexandros Lamprineas     assert(!Args.empty() && "Specialization without arguments");
7668045bf9dSAlexandros Lamprineas     Function *F = Args[0].Formal->getParent();
7678045bf9dSAlexandros Lamprineas 
7688045bf9dSAlexandros Lamprineas     SmallVector<CallBase *, 8> CallSitesToRewrite;
7699907746fSSjoerd Meijer     for (auto *U : F->users()) {
7709907746fSSjoerd Meijer       if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
7719907746fSSjoerd Meijer         continue;
7729907746fSSjoerd Meijer       auto &CS = *cast<CallBase>(U);
7739907746fSSjoerd Meijer       if (!CS.getCalledFunction() || CS.getCalledFunction() != F)
7749907746fSSjoerd Meijer         continue;
7759907746fSSjoerd Meijer       CallSitesToRewrite.push_back(&CS);
7769907746fSSjoerd Meijer     }
777b803aee6SAlexandros Lamprineas 
778b803aee6SAlexandros Lamprineas     LLVM_DEBUG(dbgs() << "FnSpecialization: Replacing call sites of "
779a687f96bSAlexandros Lamprineas                       << F->getName() << " with " << Clone->getName() << "\n");
780b803aee6SAlexandros Lamprineas 
7819907746fSSjoerd Meijer     for (auto *CS : CallSitesToRewrite) {
782b803aee6SAlexandros Lamprineas       LLVM_DEBUG(dbgs() << "FnSpecialization:   "
783a687f96bSAlexandros Lamprineas                         << CS->getFunction()->getName() << " ->" << *CS
784a687f96bSAlexandros Lamprineas                         << "\n");
785910eb988SAlexandros Lamprineas       if (/* recursive call */
786910eb988SAlexandros Lamprineas           (CS->getFunction() == Clone &&
7878045bf9dSAlexandros Lamprineas            all_of(Args,
7888045bf9dSAlexandros Lamprineas                   [CS, &Mappings](const ArgInfo &Arg) {
7898045bf9dSAlexandros Lamprineas                     unsigned ArgNo = Arg.Formal->getArgNo();
7908045bf9dSAlexandros Lamprineas                     return CS->getArgOperand(ArgNo) == Mappings[Arg.Formal];
7918045bf9dSAlexandros Lamprineas                   })) ||
792910eb988SAlexandros Lamprineas           /* normal call */
7938045bf9dSAlexandros Lamprineas           all_of(Args, [CS](const ArgInfo &Arg) {
7948045bf9dSAlexandros Lamprineas             unsigned ArgNo = Arg.Formal->getArgNo();
7958045bf9dSAlexandros Lamprineas             return CS->getArgOperand(ArgNo) == Arg.Actual;
7968045bf9dSAlexandros Lamprineas           })) {
7979907746fSSjoerd Meijer         CS->setCalledFunction(Clone);
7989907746fSSjoerd Meijer         Solver.markOverdefined(CS);
7999907746fSSjoerd Meijer       }
8009907746fSSjoerd Meijer     }
8019907746fSSjoerd Meijer   }
802b7b61fe0SSjoerd Meijer 
updateSpecializedFuncs(FuncList & Candidates,FuncList & WorkList)8037b74123aSAlexandros Lamprineas   void updateSpecializedFuncs(FuncList &Candidates, FuncList &WorkList) {
8047b74123aSAlexandros Lamprineas     for (auto *F : WorkList) {
8057b74123aSAlexandros Lamprineas       SpecializedFuncs.insert(F);
806b7b61fe0SSjoerd Meijer 
807b7b61fe0SSjoerd Meijer       // Initialize the state of the newly created functions, marking them
808b7b61fe0SSjoerd Meijer       // argument-tracked and executable.
8097b74123aSAlexandros Lamprineas       if (F->hasExactDefinition() && !F->hasFnAttribute(Attribute::Naked))
8107b74123aSAlexandros Lamprineas         Solver.addTrackedFunction(F);
811b7b61fe0SSjoerd Meijer 
8127b74123aSAlexandros Lamprineas       Solver.addArgumentTrackedFunction(F);
8137b74123aSAlexandros Lamprineas       Candidates.push_back(F);
8147b74123aSAlexandros Lamprineas       Solver.markBlockExecutable(&F->front());
815b7b61fe0SSjoerd Meijer 
816b7b61fe0SSjoerd Meijer       // Replace the function arguments for the specialized functions.
8177b74123aSAlexandros Lamprineas       for (Argument &Arg : F->args())
818b7b61fe0SSjoerd Meijer         if (!Arg.use_empty() && tryToReplaceWithConstant(&Arg))
819b7b61fe0SSjoerd Meijer           LLVM_DEBUG(dbgs() << "FnSpecialization: Replaced constant argument: "
820b803aee6SAlexandros Lamprineas                             << Arg.getNameOrAsOperand() << "\n");
821b7b61fe0SSjoerd Meijer     }
822b7b61fe0SSjoerd Meijer   }
8239907746fSSjoerd Meijer };
8249b8b1645SBenjamin Kramer } // namespace
8259907746fSSjoerd Meijer 
runFunctionSpecialization(Module & M,const DataLayout & DL,std::function<TargetLibraryInfo & (Function &)> GetTLI,std::function<TargetTransformInfo & (Function &)> GetTTI,std::function<AssumptionCache & (Function &)> GetAC,function_ref<AnalysisResultsForFn (Function &)> GetAnalysis)8269907746fSSjoerd Meijer bool llvm::runFunctionSpecialization(
8279907746fSSjoerd Meijer     Module &M, const DataLayout &DL,
8289907746fSSjoerd Meijer     std::function<TargetLibraryInfo &(Function &)> GetTLI,
8299907746fSSjoerd Meijer     std::function<TargetTransformInfo &(Function &)> GetTTI,
8309907746fSSjoerd Meijer     std::function<AssumptionCache &(Function &)> GetAC,
8319907746fSSjoerd Meijer     function_ref<AnalysisResultsForFn(Function &)> GetAnalysis) {
8329907746fSSjoerd Meijer   SCCPSolver Solver(DL, GetTLI, M.getContext());
8339907746fSSjoerd Meijer   FunctionSpecializer FS(Solver, GetAC, GetTTI, GetTLI);
8349907746fSSjoerd Meijer   bool Changed = false;
8359907746fSSjoerd Meijer 
8369907746fSSjoerd Meijer   // Loop over all functions, marking arguments to those with their addresses
8379907746fSSjoerd Meijer   // taken or that are external as overdefined.
8389907746fSSjoerd Meijer   for (Function &F : M) {
8399907746fSSjoerd Meijer     if (F.isDeclaration())
8409907746fSSjoerd Meijer       continue;
841dcd23d87SSjoerd Meijer     if (F.hasFnAttribute(Attribute::NoDuplicate))
842dcd23d87SSjoerd Meijer       continue;
8439907746fSSjoerd Meijer 
8449907746fSSjoerd Meijer     LLVM_DEBUG(dbgs() << "\nFnSpecialization: Analysing decl: " << F.getName()
8459907746fSSjoerd Meijer                       << "\n");
8469907746fSSjoerd Meijer     Solver.addAnalysis(F, GetAnalysis(F));
8479907746fSSjoerd Meijer 
8489907746fSSjoerd Meijer     // Determine if we can track the function's arguments. If so, add the
8499907746fSSjoerd Meijer     // function to the solver's set of argument-tracked functions.
8509907746fSSjoerd Meijer     if (canTrackArgumentsInterprocedurally(&F)) {
8519907746fSSjoerd Meijer       LLVM_DEBUG(dbgs() << "FnSpecialization: Can track arguments\n");
8529907746fSSjoerd Meijer       Solver.addArgumentTrackedFunction(&F);
8539907746fSSjoerd Meijer       continue;
8549907746fSSjoerd Meijer     } else {
8559907746fSSjoerd Meijer       LLVM_DEBUG(dbgs() << "FnSpecialization: Can't track arguments!\n"
8569907746fSSjoerd Meijer                         << "FnSpecialization: Doesn't have local linkage, or "
8579907746fSSjoerd Meijer                         << "has its address taken\n");
8589907746fSSjoerd Meijer     }
8599907746fSSjoerd Meijer 
8609907746fSSjoerd Meijer     // Assume the function is called.
8619907746fSSjoerd Meijer     Solver.markBlockExecutable(&F.front());
8629907746fSSjoerd Meijer 
8639907746fSSjoerd Meijer     // Assume nothing about the incoming arguments.
8649907746fSSjoerd Meijer     for (Argument &AI : F.args())
8659907746fSSjoerd Meijer       Solver.markOverdefined(&AI);
8669907746fSSjoerd Meijer   }
8679907746fSSjoerd Meijer 
8689907746fSSjoerd Meijer   // Determine if we can track any of the module's global variables. If so, add
8699907746fSSjoerd Meijer   // the global variables we can track to the solver's set of tracked global
8709907746fSSjoerd Meijer   // variables.
8719907746fSSjoerd Meijer   for (GlobalVariable &G : M.globals()) {
8729907746fSSjoerd Meijer     G.removeDeadConstantUsers();
8739907746fSSjoerd Meijer     if (canTrackGlobalVariableInterprocedurally(&G))
8749907746fSSjoerd Meijer       Solver.trackValueOfGlobalVariable(&G);
8759907746fSSjoerd Meijer   }
8769907746fSSjoerd Meijer 
87767a58fa3SSjoerd Meijer   auto &TrackedFuncs = Solver.getArgumentTrackedFunctions();
87867a58fa3SSjoerd Meijer   SmallVector<Function *, 16> FuncDecls(TrackedFuncs.begin(),
87967a58fa3SSjoerd Meijer                                         TrackedFuncs.end());
88067a58fa3SSjoerd Meijer 
88167a58fa3SSjoerd Meijer   // No tracked functions, so nothing to do: don't run the solver and remove
88267a58fa3SSjoerd Meijer   // the ssa_copy intrinsics that may have been introduced.
88367a58fa3SSjoerd Meijer   if (TrackedFuncs.empty()) {
88467a58fa3SSjoerd Meijer     removeSSACopy(M);
88567a58fa3SSjoerd Meijer     return false;
88667a58fa3SSjoerd Meijer   }
88767a58fa3SSjoerd Meijer 
8889907746fSSjoerd Meijer   // Solve for constants.
8899907746fSSjoerd Meijer   auto RunSCCPSolver = [&](auto &WorkList) {
8909907746fSSjoerd Meijer     bool ResolvedUndefs = true;
8919907746fSSjoerd Meijer 
8929907746fSSjoerd Meijer     while (ResolvedUndefs) {
89367a58fa3SSjoerd Meijer       // Not running the solver unnecessary is checked in regression test
89467a58fa3SSjoerd Meijer       // nothing-to-do.ll, so if this debug message is changed, this regression
89567a58fa3SSjoerd Meijer       // test needs updating too.
8969907746fSSjoerd Meijer       LLVM_DEBUG(dbgs() << "FnSpecialization: Running solver\n");
89767a58fa3SSjoerd Meijer 
8989907746fSSjoerd Meijer       Solver.solve();
8999907746fSSjoerd Meijer       LLVM_DEBUG(dbgs() << "FnSpecialization: Resolving undefs\n");
9009907746fSSjoerd Meijer       ResolvedUndefs = false;
9019907746fSSjoerd Meijer       for (Function *F : WorkList)
9029907746fSSjoerd Meijer         if (Solver.resolvedUndefsIn(*F))
9039907746fSSjoerd Meijer           ResolvedUndefs = true;
9049907746fSSjoerd Meijer     }
9059907746fSSjoerd Meijer 
9069907746fSSjoerd Meijer     for (auto *F : WorkList) {
9079907746fSSjoerd Meijer       for (BasicBlock &BB : *F) {
9089907746fSSjoerd Meijer         if (!Solver.isBlockExecutable(&BB))
9099907746fSSjoerd Meijer           continue;
910ecff9e3dSSjoerd Meijer         // FIXME: The solver may make changes to the function here, so set
911ecff9e3dSSjoerd Meijer         // Changed, even if later function specialization does not trigger.
9129907746fSSjoerd Meijer         for (auto &I : make_early_inc_range(BB))
9130fd03febSChuanqi Xu           Changed |= FS.tryToReplaceWithConstant(&I);
9149907746fSSjoerd Meijer       }
9159907746fSSjoerd Meijer     }
9169907746fSSjoerd Meijer   };
9179907746fSSjoerd Meijer 
9189907746fSSjoerd Meijer #ifndef NDEBUG
9199907746fSSjoerd Meijer   LLVM_DEBUG(dbgs() << "FnSpecialization: Worklist fn decls:\n");
9209907746fSSjoerd Meijer   for (auto *F : FuncDecls)
9219907746fSSjoerd Meijer     LLVM_DEBUG(dbgs() << "FnSpecialization: *) " << F->getName() << "\n");
9229907746fSSjoerd Meijer #endif
9239907746fSSjoerd Meijer 
9249907746fSSjoerd Meijer   // Initially resolve the constants in all the argument tracked functions.
9259907746fSSjoerd Meijer   RunSCCPSolver(FuncDecls);
9269907746fSSjoerd Meijer 
9278045bf9dSAlexandros Lamprineas   SmallVector<Function *, 8> WorkList;
9289907746fSSjoerd Meijer   unsigned I = 0;
9299907746fSSjoerd Meijer   while (FuncSpecializationMaxIters != I++ &&
9307b74123aSAlexandros Lamprineas          FS.specializeFunctions(FuncDecls, WorkList)) {
931b803aee6SAlexandros Lamprineas     LLVM_DEBUG(dbgs() << "FnSpecialization: Finished iteration " << I << "\n");
93230fbb069SSjoerd Meijer 
93330fbb069SSjoerd Meijer     // Run the solver for the specialized functions.
9347b74123aSAlexandros Lamprineas     RunSCCPSolver(WorkList);
93530fbb069SSjoerd Meijer 
936ecff9e3dSSjoerd Meijer     // Replace some unresolved constant arguments.
93730fbb069SSjoerd Meijer     constantArgPropagation(FuncDecls, M, Solver);
9389907746fSSjoerd Meijer 
9397b74123aSAlexandros Lamprineas     WorkList.clear();
9409907746fSSjoerd Meijer     Changed = true;
9419907746fSSjoerd Meijer   }
9429907746fSSjoerd Meijer 
943b803aee6SAlexandros Lamprineas   LLVM_DEBUG(dbgs() << "FnSpecialization: Number of specializations = "
944b803aee6SAlexandros Lamprineas                     << NumFuncSpecialized << "\n");
945b803aee6SAlexandros Lamprineas 
94633830326SAlexandros Lamprineas   // Remove any ssa_copy intrinsics that may have been introduced.
94730fbb069SSjoerd Meijer   removeSSACopy(M);
9489907746fSSjoerd Meijer   return Changed;
9499907746fSSjoerd Meijer }
950