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