1 //===- FunctionSpecialization.cpp - Function Specialization ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This specialises functions with constant parameters (e.g. functions,
10 // globals). Constant parameters like function pointers and constant globals
11 // are propagated to the callee by specializing the function.
12 //
13 // Current limitations:
14 // - It does not handle specialization of recursive functions,
15 // - It does not yet handle integer constants, and integer ranges,
16 // - Only 1 argument per function is specialised,
17 // - The cost-model could be further looked into,
18 // - We are not yet caching analysis results.
19 //
20 // Ideas:
21 // - With a function specialization attribute for arguments, we could have
22 //   a direct way to steer function specialization, avoiding the cost-model,
23 //   and thus control compile-times / code-size.
24 //
25 //===----------------------------------------------------------------------===//
26 
27 #include "llvm/ADT/Statistic.h"
28 #include "llvm/Analysis/AssumptionCache.h"
29 #include "llvm/Analysis/CodeMetrics.h"
30 #include "llvm/Analysis/DomTreeUpdater.h"
31 #include "llvm/Analysis/InlineCost.h"
32 #include "llvm/Analysis/LoopInfo.h"
33 #include "llvm/Analysis/TargetLibraryInfo.h"
34 #include "llvm/Analysis/TargetTransformInfo.h"
35 #include "llvm/Transforms/Scalar/SCCP.h"
36 #include "llvm/Transforms/Utils/Cloning.h"
37 #include "llvm/Transforms/Utils/SizeOpts.h"
38 #include <cmath>
39 
40 using namespace llvm;
41 
42 #define DEBUG_TYPE "function-specialization"
43 
44 STATISTIC(NumFuncSpecialized, "Number of functions specialized");
45 
46 static cl::opt<bool> ForceFunctionSpecialization(
47     "force-function-specialization", cl::init(false), cl::Hidden,
48     cl::desc("Force function specialization for every call site with a "
49              "constant argument"));
50 
51 static cl::opt<unsigned> FuncSpecializationMaxIters(
52     "func-specialization-max-iters", cl::Hidden,
53     cl::desc("The maximum number of iterations function specialization is run"),
54     cl::init(1));
55 
56 static cl::opt<unsigned> MaxConstantsThreshold(
57     "func-specialization-max-constants", cl::Hidden,
58     cl::desc("The maximum number of clones allowed for a single function "
59              "specialization"),
60     cl::init(3));
61 
62 static cl::opt<unsigned>
63     AvgLoopIterationCount("func-specialization-avg-iters-cost", cl::Hidden,
64                           cl::desc("Average loop iteration count cost"),
65                           cl::init(10));
66 
67 // Helper to check if \p LV is either overdefined or a constant int.
68 static bool isOverdefined(const ValueLatticeElement &LV) {
69   return !LV.isUnknownOrUndef() && !LV.isConstant();
70 }
71 
72 class FunctionSpecializer {
73 
74   /// The IPSCCP Solver.
75   SCCPSolver &Solver;
76 
77   /// Analyses used to help determine if a function should be specialized.
78   std::function<AssumptionCache &(Function &)> GetAC;
79   std::function<TargetTransformInfo &(Function &)> GetTTI;
80   std::function<TargetLibraryInfo &(Function &)> GetTLI;
81 
82   SmallPtrSet<Function *, 2> SpecializedFuncs;
83 
84 public:
85   FunctionSpecializer(SCCPSolver &Solver,
86                       std::function<AssumptionCache &(Function &)> GetAC,
87                       std::function<TargetTransformInfo &(Function &)> GetTTI,
88                       std::function<TargetLibraryInfo &(Function &)> GetTLI)
89       : Solver(Solver), GetAC(GetAC), GetTTI(GetTTI), GetTLI(GetTLI) {}
90 
91   /// Attempt to specialize functions in the module to enable constant
92   /// propagation across function boundaries.
93   ///
94   /// \returns true if at least one function is specialized.
95   bool
96   specializeFunctions(SmallVectorImpl<Function *> &FuncDecls,
97                       SmallVectorImpl<Function *> &CurrentSpecializations) {
98 
99     // Attempt to specialize the argument-tracked functions.
100     bool Changed = false;
101     for (auto *F : FuncDecls) {
102       if (specializeFunction(F, CurrentSpecializations)) {
103         Changed = true;
104         LLVM_DEBUG(dbgs() << "FnSpecialization: Can specialize this func.\n");
105       } else {
106         LLVM_DEBUG(
107             dbgs() << "FnSpecialization: Cannot specialize this func.\n");
108       }
109     }
110 
111     for (auto *SpecializedFunc : CurrentSpecializations) {
112       SpecializedFuncs.insert(SpecializedFunc);
113 
114       // TODO: If we want to support specializing specialized functions,
115       // initialize here the state of the newly created functions, marking
116       // them argument-tracked and executable.
117 
118       // Replace the function arguments for the specialized functions.
119       for (Argument &Arg : SpecializedFunc->args())
120         if (!Arg.use_empty() && tryToReplaceWithConstant(&Arg))
121           LLVM_DEBUG(dbgs() << "FnSpecialization: Replaced constant argument: "
122                             << Arg.getName() << "\n");
123     }
124 
125     NumFuncSpecialized += NbFunctionsSpecialized;
126     return Changed;
127   }
128 
129   bool tryToReplaceWithConstant(Value *V) {
130     if (!V->getType()->isSingleValueType() || isa<CallBase>(V) ||
131         V->user_empty())
132       return false;
133 
134     const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
135     if (isOverdefined(IV))
136       return false;
137     auto *Const = IV.isConstant() ? Solver.getConstant(IV)
138                                   : UndefValue::get(V->getType());
139     V->replaceAllUsesWith(Const);
140 
141     // TODO: Update the solver here if we want to specialize specialized
142     // functions.
143     return true;
144   }
145 
146 private:
147   // The number of functions specialised, used for collecting statistics and
148   // also in the cost model.
149   unsigned NbFunctionsSpecialized = 0;
150 
151   /// This function decides whether to specialize function \p F based on the
152   /// known constant values its arguments can take on. Specialization is
153   /// performed on the first interesting argument. Specializations based on
154   /// additional arguments will be evaluated on following iterations of the
155   /// main IPSCCP solve loop. \returns true if the function is specialized and
156   /// false otherwise.
157   bool specializeFunction(Function *F,
158                           SmallVectorImpl<Function *> &Specializations) {
159 
160     // Do not specialize the cloned function again.
161     if (SpecializedFuncs.contains(F)) {
162       return false;
163     }
164 
165     // If we're optimizing the function for size, we shouldn't specialize it.
166     if (F->hasOptSize() ||
167         shouldOptimizeForSize(F, nullptr, nullptr, PGSOQueryType::IRPass))
168       return false;
169 
170     // Exit if the function is not executable. There's no point in specializing
171     // a dead function.
172     if (!Solver.isBlockExecutable(&F->getEntryBlock()))
173       return false;
174 
175     LLVM_DEBUG(dbgs() << "FnSpecialization: Try function: " << F->getName()
176                       << "\n");
177     // Determine if we should specialize the function based on the values the
178     // argument can take on. If specialization is not profitable, we continue
179     // on to the next argument.
180     for (Argument &A : F->args()) {
181       LLVM_DEBUG(dbgs() << "FnSpecialization: Analysing arg: " << A.getName()
182                         << "\n");
183       // True if this will be a partial specialization. We will need to keep
184       // the original function around in addition to the added specializations.
185       bool IsPartial = true;
186 
187       // Determine if this argument is interesting. If we know the argument can
188       // take on any constant values, they are collected in Constants. If the
189       // argument can only ever equal a constant value in Constants, the
190       // function will be completely specialized, and the IsPartial flag will
191       // be set to false by isArgumentInteresting (that function only adds
192       // values to the Constants list that are deemed profitable).
193       SmallVector<Constant *, 4> Constants;
194       if (!isArgumentInteresting(&A, Constants, IsPartial)) {
195         LLVM_DEBUG(dbgs() << "FnSpecialization: Argument is not interesting\n");
196         continue;
197       }
198 
199       assert(!Constants.empty() && "No constants on which to specialize");
200       LLVM_DEBUG(dbgs() << "FnSpecialization: Argument is interesting!\n"
201                         << "FnSpecialization: Specializing '" << F->getName()
202                         << "' on argument: " << A << "\n"
203                         << "FnSpecialization: Constants are:\n\n";
204                  for (unsigned I = 0; I < Constants.size(); ++I) dbgs()
205                  << *Constants[I] << "\n";
206                  dbgs() << "FnSpecialization: End of constants\n\n");
207 
208       // Create a version of the function in which the argument is marked
209       // constant with the given value.
210       for (auto *C : Constants) {
211         // Clone the function. We leave the ValueToValueMap empty to allow
212         // IPSCCP to propagate the constant arguments.
213         ValueToValueMapTy EmptyMap;
214         Function *Clone = CloneFunction(F, EmptyMap);
215         Argument *ClonedArg = Clone->arg_begin() + A.getArgNo();
216 
217         // Rewrite calls to the function so that they call the clone instead.
218         rewriteCallSites(F, Clone, *ClonedArg, C);
219 
220         // Initialize the lattice state of the arguments of the function clone,
221         // marking the argument on which we specialized the function constant
222         // with the given value.
223         Solver.markArgInFuncSpecialization(F, ClonedArg, C);
224 
225         // Mark all the specialized functions
226         Specializations.push_back(Clone);
227         NbFunctionsSpecialized++;
228       }
229 
230       // TODO: if we want to support specialize specialized functions, and if
231       // the function has been completely specialized, the original function is
232       // no longer needed, so we would need to mark it unreachable here.
233 
234       // FIXME: Only one argument per function.
235       return true;
236     }
237 
238     return false;
239   }
240 
241   /// Compute the cost of specializing function \p F.
242   InstructionCost getSpecializationCost(Function *F) {
243     // Compute the code metrics for the function.
244     SmallPtrSet<const Value *, 32> EphValues;
245     CodeMetrics::collectEphemeralValues(F, &(GetAC)(*F), EphValues);
246     CodeMetrics Metrics;
247     for (BasicBlock &BB : *F)
248       Metrics.analyzeBasicBlock(&BB, (GetTTI)(*F), EphValues);
249 
250     // If the code metrics reveal that we shouldn't duplicate the function, we
251     // shouldn't specialize it. Set the specialization cost to Invalid.
252     if (Metrics.notDuplicatable) {
253       InstructionCost C{};
254       C.setInvalid();
255       return C;
256     }
257 
258     // Otherwise, set the specialization cost to be the cost of all the
259     // instructions in the function and penalty for specializing more functions.
260     unsigned Penalty = NbFunctionsSpecialized + 1;
261     return Metrics.NumInsts * InlineConstants::InstrCost * Penalty;
262   }
263 
264   InstructionCost getUserBonus(User *U, llvm::TargetTransformInfo &TTI,
265                                LoopInfo &LI) {
266     auto *I = dyn_cast_or_null<Instruction>(U);
267     // If not an instruction we do not know how to evaluate.
268     // Keep minimum possible cost for now so that it doesnt affect
269     // specialization.
270     if (!I)
271       return std::numeric_limits<unsigned>::min();
272 
273     auto Cost = TTI.getUserCost(U, TargetTransformInfo::TCK_SizeAndLatency);
274 
275     // Traverse recursively if there are more uses.
276     // TODO: Any other instructions to be added here?
277     if (I->mayReadFromMemory() || I->isCast())
278       for (auto *User : I->users())
279         Cost += getUserBonus(User, TTI, LI);
280 
281     // Increase the cost if it is inside the loop.
282     auto LoopDepth = LI.getLoopDepth(I->getParent());
283     Cost *= std::pow((double)AvgLoopIterationCount, LoopDepth);
284     return Cost;
285   }
286 
287   /// Compute a bonus for replacing argument \p A with constant \p C.
288   InstructionCost getSpecializationBonus(Argument *A, Constant *C) {
289     Function *F = A->getParent();
290     DominatorTree DT(*F);
291     LoopInfo LI(DT);
292     auto &TTI = (GetTTI)(*F);
293     LLVM_DEBUG(dbgs() << "FnSpecialization: Analysing bonus for: " << *A
294                       << "\n");
295 
296     InstructionCost TotalCost = 0;
297     for (auto *U : A->users()) {
298       TotalCost += getUserBonus(U, TTI, LI);
299       LLVM_DEBUG(dbgs() << "FnSpecialization: User cost ";
300                  TotalCost.print(dbgs()); dbgs() << " for: " << *U << "\n");
301     }
302 
303     // The below heuristic is only concerned with exposing inlining
304     // opportunities via indirect call promotion. If the argument is not a
305     // function pointer, give up.
306     if (!isa<PointerType>(A->getType()) ||
307         !isa<FunctionType>(A->getType()->getPointerElementType()))
308       return TotalCost;
309 
310     // Since the argument is a function pointer, its incoming constant values
311     // should be functions or constant expressions. The code below attempts to
312     // look through cast expressions to find the function that will be called.
313     Value *CalledValue = C;
314     while (isa<ConstantExpr>(CalledValue) &&
315            cast<ConstantExpr>(CalledValue)->isCast())
316       CalledValue = cast<User>(CalledValue)->getOperand(0);
317     Function *CalledFunction = dyn_cast<Function>(CalledValue);
318     if (!CalledFunction)
319       return TotalCost;
320 
321     // Get TTI for the called function (used for the inline cost).
322     auto &CalleeTTI = (GetTTI)(*CalledFunction);
323 
324     // Look at all the call sites whose called value is the argument.
325     // Specializing the function on the argument would allow these indirect
326     // calls to be promoted to direct calls. If the indirect call promotion
327     // would likely enable the called function to be inlined, specializing is a
328     // good idea.
329     int Bonus = 0;
330     for (User *U : A->users()) {
331       if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
332         continue;
333       auto *CS = cast<CallBase>(U);
334       if (CS->getCalledOperand() != A)
335         continue;
336 
337       // Get the cost of inlining the called function at this call site. Note
338       // that this is only an estimate. The called function may eventually
339       // change in a way that leads to it not being inlined here, even though
340       // inlining looks profitable now. For example, one of its called
341       // functions may be inlined into it, making the called function too large
342       // to be inlined into this call site.
343       //
344       // We apply a boost for performing indirect call promotion by increasing
345       // the default threshold by the threshold for indirect calls.
346       auto Params = getInlineParams();
347       Params.DefaultThreshold += InlineConstants::IndirectCallThreshold;
348       InlineCost IC =
349           getInlineCost(*CS, CalledFunction, Params, CalleeTTI, GetAC, GetTLI);
350 
351       // We clamp the bonus for this call to be between zero and the default
352       // threshold.
353       if (IC.isAlways())
354         Bonus += Params.DefaultThreshold;
355       else if (IC.isVariable() && IC.getCostDelta() > 0)
356         Bonus += IC.getCostDelta();
357     }
358 
359     return TotalCost + Bonus;
360   }
361 
362   /// Determine if we should specialize a function based on the incoming values
363   /// of the given argument.
364   ///
365   /// This function implements the goal-directed heuristic. It determines if
366   /// specializing the function based on the incoming values of argument \p A
367   /// would result in any significant optimization opportunities. If
368   /// optimization opportunities exist, the constant values of \p A on which to
369   /// specialize the function are collected in \p Constants. If the values in
370   /// \p Constants represent the complete set of values that \p A can take on,
371   /// the function will be completely specialized, and the \p IsPartial flag is
372   /// set to false.
373   ///
374   /// \returns true if the function should be specialized on the given
375   /// argument.
376   bool isArgumentInteresting(Argument *A,
377                              SmallVectorImpl<Constant *> &Constants,
378                              bool &IsPartial) {
379     Function *F = A->getParent();
380 
381     // For now, don't attempt to specialize functions based on the values of
382     // composite types.
383     if (!A->getType()->isSingleValueType() || A->user_empty())
384       return false;
385 
386     // If the argument isn't overdefined, there's nothing to do. It should
387     // already be constant.
388     if (!Solver.getLatticeValueFor(A).isOverdefined()) {
389       LLVM_DEBUG(dbgs() << "FnSpecialization: nothing to do, arg is already "
390                         << "constant?\n");
391       return false;
392     }
393 
394     // Collect the constant values that the argument can take on. If the
395     // argument can't take on any constant values, we aren't going to
396     // specialize the function. While it's possible to specialize the function
397     // based on non-constant arguments, there's likely not much benefit to
398     // constant propagation in doing so.
399     //
400     // TODO 1: currently it won't specialize if there are over the threshold of
401     // calls using the same argument, e.g foo(a) x 4 and foo(b) x 1, but it
402     // might be beneficial to take the occurrences into account in the cost
403     // model, so we would need to find the unique constants.
404     //
405     // TODO 2: this currently does not support constants, i.e. integer ranges.
406     //
407     SmallVector<Constant *, 4> PossibleConstants;
408     bool AllConstant = getPossibleConstants(A, PossibleConstants);
409     if (PossibleConstants.empty()) {
410       LLVM_DEBUG(dbgs() << "FnSpecialization: no possible constants found\n");
411       return false;
412     }
413     if (PossibleConstants.size() > MaxConstantsThreshold) {
414       LLVM_DEBUG(dbgs() << "FnSpecialization: number of constants found exceed "
415                         << "the maximum number of constants threshold.\n");
416       return false;
417     }
418 
419     // Determine if it would be profitable to create a specialization of the
420     // function where the argument takes on the given constant value. If so,
421     // add the constant to Constants.
422     auto FnSpecCost = getSpecializationCost(F);
423     if (!FnSpecCost.isValid()) {
424       LLVM_DEBUG(dbgs() << "FnSpecialization: Invalid specialisation cost.\n");
425       return false;
426     }
427 
428     LLVM_DEBUG(dbgs() << "FnSpecialization: func specialisation cost: ";
429                FnSpecCost.print(dbgs()); dbgs() << "\n");
430 
431     for (auto *C : PossibleConstants) {
432       LLVM_DEBUG(dbgs() << "FnSpecialization: Constant: " << *C << "\n");
433       if (ForceFunctionSpecialization) {
434         LLVM_DEBUG(dbgs() << "FnSpecialization: Forced!\n");
435         Constants.push_back(C);
436         continue;
437       }
438       if (getSpecializationBonus(A, C) > FnSpecCost) {
439         LLVM_DEBUG(dbgs() << "FnSpecialization: profitable!\n");
440         Constants.push_back(C);
441       } else {
442         LLVM_DEBUG(dbgs() << "FnSpecialization: not profitable\n");
443       }
444     }
445 
446     // None of the constant values the argument can take on were deemed good
447     // candidates on which to specialize the function.
448     if (Constants.empty())
449       return false;
450 
451     // This will be a partial specialization if some of the constants were
452     // rejected due to their profitability.
453     IsPartial = !AllConstant || PossibleConstants.size() != Constants.size();
454 
455     return true;
456   }
457 
458   /// Collect in \p Constants all the constant values that argument \p A can
459   /// take on.
460   ///
461   /// \returns true if all of the values the argument can take on are constant
462   /// (e.g., the argument's parent function cannot be called with an
463   /// overdefined value).
464   bool getPossibleConstants(Argument *A,
465                             SmallVectorImpl<Constant *> &Constants) {
466     Function *F = A->getParent();
467     bool AllConstant = true;
468 
469     // Iterate over all the call sites of the argument's parent function.
470     for (User *U : F->users()) {
471       if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
472         continue;
473       auto &CS = *cast<CallBase>(U);
474 
475       // If the parent of the call site will never be executed, we don't need
476       // to worry about the passed value.
477       if (!Solver.isBlockExecutable(CS.getParent()))
478         continue;
479 
480       auto *V = CS.getArgOperand(A->getArgNo());
481       // TrackValueOfGlobalVariable only tracks scalar global variables.
482       if (auto *GV = dyn_cast<GlobalVariable>(V)) {
483         if (!GV->getValueType()->isSingleValueType()) {
484           return false;
485         }
486       }
487 
488       // Get the lattice value for the value the call site passes to the
489       // argument. If this value is not constant, move on to the next call
490       // site. Additionally, set the AllConstant flag to false.
491       if (V != A && !Solver.getLatticeValueFor(V).isConstant()) {
492         AllConstant = false;
493         continue;
494       }
495 
496       // Add the constant to the set.
497       if (auto *C = dyn_cast<Constant>(CS.getArgOperand(A->getArgNo())))
498         Constants.push_back(C);
499     }
500 
501     // If the argument can only take on constant values, AllConstant will be
502     // true.
503     return AllConstant;
504   }
505 
506   /// Rewrite calls to function \p F to call function \p Clone instead.
507   ///
508   /// This function modifies calls to function \p F whose argument at index \p
509   /// ArgNo is equal to constant \p C. The calls are rewritten to call function
510   /// \p Clone instead.
511   void rewriteCallSites(Function *F, Function *Clone, Argument &Arg,
512                         Constant *C) {
513     unsigned ArgNo = Arg.getArgNo();
514     SmallVector<CallBase *, 4> CallSitesToRewrite;
515     for (auto *U : F->users()) {
516       if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
517         continue;
518       auto &CS = *cast<CallBase>(U);
519       if (!CS.getCalledFunction() || CS.getCalledFunction() != F)
520         continue;
521       CallSitesToRewrite.push_back(&CS);
522     }
523     for (auto *CS : CallSitesToRewrite) {
524       if ((CS->getFunction() == Clone && CS->getArgOperand(ArgNo) == &Arg) ||
525           CS->getArgOperand(ArgNo) == C) {
526         CS->setCalledFunction(Clone);
527         Solver.markOverdefined(CS);
528       }
529     }
530   }
531 };
532 
533 /// Function to clean up the left over intrinsics from SCCP util.
534 static void cleanup(Module &M) {
535   for (Function &F : M) {
536     for (BasicBlock &BB : F) {
537       for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E;) {
538         Instruction *Inst = &*BI++;
539         if (auto *II = dyn_cast<IntrinsicInst>(Inst)) {
540           if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
541             Value *Op = II->getOperand(0);
542             Inst->replaceAllUsesWith(Op);
543             Inst->eraseFromParent();
544           }
545         }
546       }
547     }
548   }
549 }
550 
551 bool llvm::runFunctionSpecialization(
552     Module &M, const DataLayout &DL,
553     std::function<TargetLibraryInfo &(Function &)> GetTLI,
554     std::function<TargetTransformInfo &(Function &)> GetTTI,
555     std::function<AssumptionCache &(Function &)> GetAC,
556     function_ref<AnalysisResultsForFn(Function &)> GetAnalysis) {
557   SCCPSolver Solver(DL, GetTLI, M.getContext());
558   FunctionSpecializer FS(Solver, GetAC, GetTTI, GetTLI);
559   bool Changed = false;
560 
561   // Loop over all functions, marking arguments to those with their addresses
562   // taken or that are external as overdefined.
563   for (Function &F : M) {
564     if (F.isDeclaration())
565       continue;
566     if (F.hasFnAttribute(Attribute::NoDuplicate))
567       continue;
568 
569     LLVM_DEBUG(dbgs() << "\nFnSpecialization: Analysing decl: " << F.getName()
570                       << "\n");
571     Solver.addAnalysis(F, GetAnalysis(F));
572 
573     // Determine if we can track the function's arguments. If so, add the
574     // function to the solver's set of argument-tracked functions.
575     if (canTrackArgumentsInterprocedurally(&F)) {
576       LLVM_DEBUG(dbgs() << "FnSpecialization: Can track arguments\n");
577       Solver.addArgumentTrackedFunction(&F);
578       continue;
579     } else {
580       LLVM_DEBUG(dbgs() << "FnSpecialization: Can't track arguments!\n"
581                         << "FnSpecialization: Doesn't have local linkage, or "
582                         << "has its address taken\n");
583     }
584 
585     // Assume the function is called.
586     Solver.markBlockExecutable(&F.front());
587 
588     // Assume nothing about the incoming arguments.
589     for (Argument &AI : F.args())
590       Solver.markOverdefined(&AI);
591   }
592 
593   // Determine if we can track any of the module's global variables. If so, add
594   // the global variables we can track to the solver's set of tracked global
595   // variables.
596   for (GlobalVariable &G : M.globals()) {
597     G.removeDeadConstantUsers();
598     if (canTrackGlobalVariableInterprocedurally(&G))
599       Solver.trackValueOfGlobalVariable(&G);
600   }
601 
602   // Solve for constants.
603   auto RunSCCPSolver = [&](auto &WorkList) {
604     bool ResolvedUndefs = true;
605 
606     while (ResolvedUndefs) {
607       LLVM_DEBUG(dbgs() << "FnSpecialization: Running solver\n");
608       Solver.solve();
609       LLVM_DEBUG(dbgs() << "FnSpecialization: Resolving undefs\n");
610       ResolvedUndefs = false;
611       for (Function *F : WorkList)
612         if (Solver.resolvedUndefsIn(*F))
613           ResolvedUndefs = true;
614     }
615 
616     for (auto *F : WorkList) {
617       for (BasicBlock &BB : *F) {
618         if (!Solver.isBlockExecutable(&BB))
619           continue;
620         for (auto &I : make_early_inc_range(BB))
621           FS.tryToReplaceWithConstant(&I);
622       }
623     }
624   };
625 
626   auto &TrackedFuncs = Solver.getArgumentTrackedFunctions();
627   SmallVector<Function *, 16> FuncDecls(TrackedFuncs.begin(),
628                                         TrackedFuncs.end());
629 #ifndef NDEBUG
630   LLVM_DEBUG(dbgs() << "FnSpecialization: Worklist fn decls:\n");
631   for (auto *F : FuncDecls)
632     LLVM_DEBUG(dbgs() << "FnSpecialization: *) " << F->getName() << "\n");
633 #endif
634 
635   // Initially resolve the constants in all the argument tracked functions.
636   RunSCCPSolver(FuncDecls);
637 
638   SmallVector<Function *, 2> CurrentSpecializations;
639   unsigned I = 0;
640   while (FuncSpecializationMaxIters != I++ &&
641          FS.specializeFunctions(FuncDecls, CurrentSpecializations)) {
642     // TODO: run the solver here for the specialized functions only if we want
643     // to specialize recursively.
644 
645     CurrentSpecializations.clear();
646     Changed = true;
647   }
648 
649   // Clean up the IR by removing ssa_copy intrinsics.
650   cleanup(M);
651   return Changed;
652 }
653