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