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 the maximum. 252 if (Metrics.notDuplicatable) 253 return std::numeric_limits<unsigned>::max(); 254 255 // Otherwise, set the specialization cost to be the cost of all the 256 // instructions in the function and penalty for specializing more functions. 257 unsigned Penalty = NbFunctionsSpecialized + 1; 258 return Metrics.NumInsts * InlineConstants::InstrCost * Penalty; 259 } 260 261 InstructionCost getUserBonus(User *U, llvm::TargetTransformInfo &TTI, 262 LoopInfo &LI) { 263 auto *I = dyn_cast_or_null<Instruction>(U); 264 // If not an instruction we do not know how to evaluate. 265 // Keep minimum possible cost for now so that it doesnt affect 266 // specialization. 267 if (!I) 268 return std::numeric_limits<unsigned>::min(); 269 270 auto Cost = TTI.getUserCost(U, TargetTransformInfo::TCK_SizeAndLatency); 271 272 // Traverse recursively if there are more uses. 273 // TODO: Any other instructions to be added here? 274 if (I->mayReadFromMemory() || I->isCast()) 275 for (auto *User : I->users()) 276 Cost += getUserBonus(User, TTI, LI); 277 278 // Increase the cost if it is inside the loop. 279 auto LoopDepth = LI.getLoopDepth(I->getParent()); 280 Cost *= std::pow((double)AvgLoopIterationCount, LoopDepth); 281 return Cost; 282 } 283 284 /// Compute a bonus for replacing argument \p A with constant \p C. 285 InstructionCost getSpecializationBonus(Argument *A, Constant *C) { 286 Function *F = A->getParent(); 287 DominatorTree DT(*F); 288 LoopInfo LI(DT); 289 auto &TTI = (GetTTI)(*F); 290 LLVM_DEBUG(dbgs() << "FnSpecialization: Analysing bonus for: " << *A 291 << "\n"); 292 293 InstructionCost TotalCost = 0; 294 for (auto *U : A->users()) { 295 TotalCost += getUserBonus(U, TTI, LI); 296 LLVM_DEBUG(dbgs() << "FnSpecialization: User cost "; 297 TotalCost.print(dbgs()); dbgs() << " for: " << *U << "\n"); 298 } 299 300 // The below heuristic is only concerned with exposing inlining 301 // opportunities via indirect call promotion. If the argument is not a 302 // function pointer, give up. 303 if (!isa<PointerType>(A->getType()) || 304 !isa<FunctionType>(A->getType()->getPointerElementType())) 305 return TotalCost; 306 307 // Since the argument is a function pointer, its incoming constant values 308 // should be functions or constant expressions. The code below attempts to 309 // look through cast expressions to find the function that will be called. 310 Value *CalledValue = C; 311 while (isa<ConstantExpr>(CalledValue) && 312 cast<ConstantExpr>(CalledValue)->isCast()) 313 CalledValue = cast<User>(CalledValue)->getOperand(0); 314 Function *CalledFunction = dyn_cast<Function>(CalledValue); 315 if (!CalledFunction) 316 return TotalCost; 317 318 // Get TTI for the called function (used for the inline cost). 319 auto &CalleeTTI = (GetTTI)(*CalledFunction); 320 321 // Look at all the call sites whose called value is the argument. 322 // Specializing the function on the argument would allow these indirect 323 // calls to be promoted to direct calls. If the indirect call promotion 324 // would likely enable the called function to be inlined, specializing is a 325 // good idea. 326 int Bonus = 0; 327 for (User *U : A->users()) { 328 if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) 329 continue; 330 auto *CS = cast<CallBase>(U); 331 if (CS->getCalledOperand() != A) 332 continue; 333 334 // Get the cost of inlining the called function at this call site. Note 335 // that this is only an estimate. The called function may eventually 336 // change in a way that leads to it not being inlined here, even though 337 // inlining looks profitable now. For example, one of its called 338 // functions may be inlined into it, making the called function too large 339 // to be inlined into this call site. 340 // 341 // We apply a boost for performing indirect call promotion by increasing 342 // the default threshold by the threshold for indirect calls. 343 auto Params = getInlineParams(); 344 Params.DefaultThreshold += InlineConstants::IndirectCallThreshold; 345 InlineCost IC = 346 getInlineCost(*CS, CalledFunction, Params, CalleeTTI, GetAC, GetTLI); 347 348 // We clamp the bonus for this call to be between zero and the default 349 // threshold. 350 if (IC.isAlways()) 351 Bonus += Params.DefaultThreshold; 352 else if (IC.isVariable() && IC.getCostDelta() > 0) 353 Bonus += IC.getCostDelta(); 354 } 355 356 return TotalCost + Bonus; 357 } 358 359 /// Determine if we should specialize a function based on the incoming values 360 /// of the given argument. 361 /// 362 /// This function implements the goal-directed heuristic. It determines if 363 /// specializing the function based on the incoming values of argument \p A 364 /// would result in any significant optimization opportunities. If 365 /// optimization opportunities exist, the constant values of \p A on which to 366 /// specialize the function are collected in \p Constants. If the values in 367 /// \p Constants represent the complete set of values that \p A can take on, 368 /// the function will be completely specialized, and the \p IsPartial flag is 369 /// set to false. 370 /// 371 /// \returns true if the function should be specialized on the given 372 /// argument. 373 bool isArgumentInteresting(Argument *A, 374 SmallVectorImpl<Constant *> &Constants, 375 bool &IsPartial) { 376 Function *F = A->getParent(); 377 378 // For now, don't attempt to specialize functions based on the values of 379 // composite types. 380 if (!A->getType()->isSingleValueType() || A->user_empty()) 381 return false; 382 383 // If the argument isn't overdefined, there's nothing to do. It should 384 // already be constant. 385 if (!Solver.getLatticeValueFor(A).isOverdefined()) { 386 LLVM_DEBUG(dbgs() << "FnSpecialization: nothing to do, arg is already " 387 << "constant?\n"); 388 return false; 389 } 390 391 // Collect the constant values that the argument can take on. If the 392 // argument can't take on any constant values, we aren't going to 393 // specialize the function. While it's possible to specialize the function 394 // based on non-constant arguments, there's likely not much benefit to 395 // constant propagation in doing so. 396 // 397 // TODO 1: currently it won't specialize if there are over the threshold of 398 // calls using the same argument, e.g foo(a) x 4 and foo(b) x 1, but it 399 // might be beneficial to take the occurrences into account in the cost 400 // model, so we would need to find the unique constants. 401 // 402 // TODO 2: this currently does not support constants, i.e. integer ranges. 403 // 404 SmallVector<Constant *, 4> PossibleConstants; 405 bool AllConstant = getPossibleConstants(A, PossibleConstants); 406 if (PossibleConstants.empty()) { 407 LLVM_DEBUG(dbgs() << "FnSpecialization: no possible constants found\n"); 408 return false; 409 } 410 if (PossibleConstants.size() > MaxConstantsThreshold) { 411 LLVM_DEBUG(dbgs() << "FnSpecialization: number of constants found exceed " 412 << "the maximum number of constants threshold.\n"); 413 return false; 414 } 415 416 // Determine if it would be profitable to create a specialization of the 417 // function where the argument takes on the given constant value. If so, 418 // add the constant to Constants. 419 auto FnSpecCost = getSpecializationCost(F); 420 LLVM_DEBUG(dbgs() << "FnSpecialization: func specialisation cost: "; 421 FnSpecCost.print(dbgs()); dbgs() << "\n"); 422 423 for (auto *C : PossibleConstants) { 424 LLVM_DEBUG(dbgs() << "FnSpecialization: Constant: " << *C << "\n"); 425 if (ForceFunctionSpecialization) { 426 LLVM_DEBUG(dbgs() << "FnSpecialization: Forced!\n"); 427 Constants.push_back(C); 428 continue; 429 } 430 if (getSpecializationBonus(A, C) > FnSpecCost) { 431 LLVM_DEBUG(dbgs() << "FnSpecialization: profitable!\n"); 432 Constants.push_back(C); 433 } else { 434 LLVM_DEBUG(dbgs() << "FnSpecialization: not profitable\n"); 435 } 436 } 437 438 // None of the constant values the argument can take on were deemed good 439 // candidates on which to specialize the function. 440 if (Constants.empty()) 441 return false; 442 443 // This will be a partial specialization if some of the constants were 444 // rejected due to their profitability. 445 IsPartial = !AllConstant || PossibleConstants.size() != Constants.size(); 446 447 return true; 448 } 449 450 /// Collect in \p Constants all the constant values that argument \p A can 451 /// take on. 452 /// 453 /// \returns true if all of the values the argument can take on are constant 454 /// (e.g., the argument's parent function cannot be called with an 455 /// overdefined value). 456 bool getPossibleConstants(Argument *A, 457 SmallVectorImpl<Constant *> &Constants) { 458 Function *F = A->getParent(); 459 bool AllConstant = true; 460 461 // Iterate over all the call sites of the argument's parent function. 462 for (User *U : F->users()) { 463 if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) 464 continue; 465 auto &CS = *cast<CallBase>(U); 466 467 // If the parent of the call site will never be executed, we don't need 468 // to worry about the passed value. 469 if (!Solver.isBlockExecutable(CS.getParent())) 470 continue; 471 472 auto *V = CS.getArgOperand(A->getArgNo()); 473 // TrackValueOfGlobalVariable only tracks scalar global variables. 474 if (auto *GV = dyn_cast<GlobalVariable>(V)) { 475 if (!GV->getValueType()->isSingleValueType()) { 476 return false; 477 } 478 } 479 480 // Get the lattice value for the value the call site passes to the 481 // argument. If this value is not constant, move on to the next call 482 // site. Additionally, set the AllConstant flag to false. 483 if (V != A && !Solver.getLatticeValueFor(V).isConstant()) { 484 AllConstant = false; 485 continue; 486 } 487 488 // Add the constant to the set. 489 if (auto *C = dyn_cast<Constant>(CS.getArgOperand(A->getArgNo()))) 490 Constants.push_back(C); 491 } 492 493 // If the argument can only take on constant values, AllConstant will be 494 // true. 495 return AllConstant; 496 } 497 498 /// Rewrite calls to function \p F to call function \p Clone instead. 499 /// 500 /// This function modifies calls to function \p F whose argument at index \p 501 /// ArgNo is equal to constant \p C. The calls are rewritten to call function 502 /// \p Clone instead. 503 void rewriteCallSites(Function *F, Function *Clone, Argument &Arg, 504 Constant *C) { 505 unsigned ArgNo = Arg.getArgNo(); 506 SmallVector<CallBase *, 4> CallSitesToRewrite; 507 for (auto *U : F->users()) { 508 if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) 509 continue; 510 auto &CS = *cast<CallBase>(U); 511 if (!CS.getCalledFunction() || CS.getCalledFunction() != F) 512 continue; 513 CallSitesToRewrite.push_back(&CS); 514 } 515 for (auto *CS : CallSitesToRewrite) { 516 if ((CS->getFunction() == Clone && CS->getArgOperand(ArgNo) == &Arg) || 517 CS->getArgOperand(ArgNo) == C) { 518 CS->setCalledFunction(Clone); 519 Solver.markOverdefined(CS); 520 } 521 } 522 } 523 }; 524 525 /// Function to clean up the left over intrinsics from SCCP util. 526 static void cleanup(Module &M) { 527 for (Function &F : M) { 528 for (BasicBlock &BB : F) { 529 for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E;) { 530 Instruction *Inst = &*BI++; 531 if (auto *II = dyn_cast<IntrinsicInst>(Inst)) { 532 if (II->getIntrinsicID() == Intrinsic::ssa_copy) { 533 Value *Op = II->getOperand(0); 534 Inst->replaceAllUsesWith(Op); 535 Inst->eraseFromParent(); 536 } 537 } 538 } 539 } 540 } 541 } 542 543 bool llvm::runFunctionSpecialization( 544 Module &M, const DataLayout &DL, 545 std::function<TargetLibraryInfo &(Function &)> GetTLI, 546 std::function<TargetTransformInfo &(Function &)> GetTTI, 547 std::function<AssumptionCache &(Function &)> GetAC, 548 function_ref<AnalysisResultsForFn(Function &)> GetAnalysis) { 549 SCCPSolver Solver(DL, GetTLI, M.getContext()); 550 FunctionSpecializer FS(Solver, GetAC, GetTTI, GetTLI); 551 bool Changed = false; 552 553 // Loop over all functions, marking arguments to those with their addresses 554 // taken or that are external as overdefined. 555 for (Function &F : M) { 556 if (F.isDeclaration()) 557 continue; 558 if (F.hasFnAttribute(Attribute::NoDuplicate)) 559 continue; 560 561 LLVM_DEBUG(dbgs() << "\nFnSpecialization: Analysing decl: " << F.getName() 562 << "\n"); 563 Solver.addAnalysis(F, GetAnalysis(F)); 564 565 // Determine if we can track the function's arguments. If so, add the 566 // function to the solver's set of argument-tracked functions. 567 if (canTrackArgumentsInterprocedurally(&F)) { 568 LLVM_DEBUG(dbgs() << "FnSpecialization: Can track arguments\n"); 569 Solver.addArgumentTrackedFunction(&F); 570 continue; 571 } else { 572 LLVM_DEBUG(dbgs() << "FnSpecialization: Can't track arguments!\n" 573 << "FnSpecialization: Doesn't have local linkage, or " 574 << "has its address taken\n"); 575 } 576 577 // Assume the function is called. 578 Solver.markBlockExecutable(&F.front()); 579 580 // Assume nothing about the incoming arguments. 581 for (Argument &AI : F.args()) 582 Solver.markOverdefined(&AI); 583 } 584 585 // Determine if we can track any of the module's global variables. If so, add 586 // the global variables we can track to the solver's set of tracked global 587 // variables. 588 for (GlobalVariable &G : M.globals()) { 589 G.removeDeadConstantUsers(); 590 if (canTrackGlobalVariableInterprocedurally(&G)) 591 Solver.trackValueOfGlobalVariable(&G); 592 } 593 594 // Solve for constants. 595 auto RunSCCPSolver = [&](auto &WorkList) { 596 bool ResolvedUndefs = true; 597 598 while (ResolvedUndefs) { 599 LLVM_DEBUG(dbgs() << "FnSpecialization: Running solver\n"); 600 Solver.solve(); 601 LLVM_DEBUG(dbgs() << "FnSpecialization: Resolving undefs\n"); 602 ResolvedUndefs = false; 603 for (Function *F : WorkList) 604 if (Solver.resolvedUndefsIn(*F)) 605 ResolvedUndefs = true; 606 } 607 608 for (auto *F : WorkList) { 609 for (BasicBlock &BB : *F) { 610 if (!Solver.isBlockExecutable(&BB)) 611 continue; 612 for (auto &I : make_early_inc_range(BB)) 613 FS.tryToReplaceWithConstant(&I); 614 } 615 } 616 }; 617 618 auto &TrackedFuncs = Solver.getArgumentTrackedFunctions(); 619 SmallVector<Function *, 16> FuncDecls(TrackedFuncs.begin(), 620 TrackedFuncs.end()); 621 #ifndef NDEBUG 622 LLVM_DEBUG(dbgs() << "FnSpecialization: Worklist fn decls:\n"); 623 for (auto *F : FuncDecls) 624 LLVM_DEBUG(dbgs() << "FnSpecialization: *) " << F->getName() << "\n"); 625 #endif 626 627 // Initially resolve the constants in all the argument tracked functions. 628 RunSCCPSolver(FuncDecls); 629 630 SmallVector<Function *, 2> CurrentSpecializations; 631 unsigned I = 0; 632 while (FuncSpecializationMaxIters != I++ && 633 FS.specializeFunctions(FuncDecls, CurrentSpecializations)) { 634 // TODO: run the solver here for the specialized functions only if we want 635 // to specialize recursively. 636 637 CurrentSpecializations.clear(); 638 Changed = true; 639 } 640 641 // Clean up the IR by removing ssa_copy intrinsics. 642 cleanup(M); 643 return Changed; 644 } 645