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