1 //===- InlineAdvisor.cpp - analysis pass implementation -------------------===// 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 file implements InlineAdvisorAnalysis and DefaultInlineAdvisor, and 10 // related types. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Analysis/InlineAdvisor.h" 15 #include "llvm/ADT/Statistic.h" 16 #include "llvm/Analysis/InlineCost.h" 17 #include "llvm/Analysis/OptimizationRemarkEmitter.h" 18 #include "llvm/Analysis/ProfileSummaryInfo.h" 19 #include "llvm/Analysis/ReplayInlineAdvisor.h" 20 #include "llvm/Analysis/TargetLibraryInfo.h" 21 #include "llvm/Analysis/TargetTransformInfo.h" 22 #include "llvm/IR/DebugInfoMetadata.h" 23 #include "llvm/IR/Instructions.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Support/raw_ostream.h" 26 27 #include <sstream> 28 29 using namespace llvm; 30 #define DEBUG_TYPE "inline" 31 32 // This weirdly named statistic tracks the number of times that, when attempting 33 // to inline a function A into B, we analyze the callers of B in order to see 34 // if those would be more profitable and blocked inline steps. 35 STATISTIC(NumCallerCallersAnalyzed, "Number of caller-callers analyzed"); 36 37 /// Flag to add inline messages as callsite attributes 'inline-remark'. 38 static cl::opt<bool> 39 InlineRemarkAttribute("inline-remark-attribute", cl::init(false), 40 cl::Hidden, 41 cl::desc("Enable adding inline-remark attribute to" 42 " callsites processed by inliner but decided" 43 " to be not inlined")); 44 45 // An integer used to limit the cost of inline deferral. The default negative 46 // number tells shouldBeDeferred to only take the secondary cost into account. 47 static cl::opt<int> 48 InlineDeferralScale("inline-deferral-scale", 49 cl::desc("Scale to limit the cost of inline deferral"), 50 cl::init(2), cl::Hidden); 51 52 extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats; 53 54 void DefaultInlineAdvice::recordUnsuccessfulInliningImpl( 55 const InlineResult &Result) { 56 using namespace ore; 57 llvm::setInlineRemark(*OriginalCB, std::string(Result.getFailureReason()) + 58 "; " + inlineCostStr(*OIC)); 59 ORE.emit([&]() { 60 return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block) 61 << NV("Callee", Callee) << " will not be inlined into " 62 << NV("Caller", Caller) << ": " 63 << NV("Reason", Result.getFailureReason()); 64 }); 65 } 66 67 void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() { 68 if (EmitRemarks) 69 emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC); 70 } 71 72 void DefaultInlineAdvice::recordInliningImpl() { 73 if (EmitRemarks) 74 emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC); 75 } 76 77 llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice( 78 CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params) { 79 Function &Caller = *CB.getCaller(); 80 ProfileSummaryInfo *PSI = 81 FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Caller) 82 .getCachedResult<ProfileSummaryAnalysis>( 83 *CB.getParent()->getParent()->getParent()); 84 85 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller); 86 auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & { 87 return FAM.getResult<AssumptionAnalysis>(F); 88 }; 89 auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & { 90 return FAM.getResult<BlockFrequencyAnalysis>(F); 91 }; 92 auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & { 93 return FAM.getResult<TargetLibraryAnalysis>(F); 94 }; 95 96 auto GetInlineCost = [&](CallBase &CB) { 97 Function &Callee = *CB.getCalledFunction(); 98 auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee); 99 bool RemarksEnabled = 100 Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled( 101 DEBUG_TYPE); 102 return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI, 103 GetBFI, PSI, RemarksEnabled ? &ORE : nullptr); 104 }; 105 return llvm::shouldInline(CB, GetInlineCost, ORE, 106 Params.EnableDeferral.getValueOr(false)); 107 } 108 109 std::unique_ptr<InlineAdvice> 110 DefaultInlineAdvisor::getAdviceImpl(CallBase &CB) { 111 auto OIC = getDefaultInlineAdvice(CB, FAM, Params); 112 return std::make_unique<DefaultInlineAdvice>( 113 this, CB, OIC, 114 FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller())); 115 } 116 117 InlineAdvice::InlineAdvice(InlineAdvisor *Advisor, CallBase &CB, 118 OptimizationRemarkEmitter &ORE, 119 bool IsInliningRecommended) 120 : Advisor(Advisor), Caller(CB.getCaller()), Callee(CB.getCalledFunction()), 121 DLoc(CB.getDebugLoc()), Block(CB.getParent()), ORE(ORE), 122 IsInliningRecommended(IsInliningRecommended) {} 123 124 void InlineAdvisor::markFunctionAsDeleted(Function *F) { 125 assert((!DeletedFunctions.count(F)) && 126 "Cannot put cause a function to become dead twice!"); 127 DeletedFunctions.insert(F); 128 } 129 130 void InlineAdvisor::freeDeletedFunctions() { 131 for (auto *F : DeletedFunctions) 132 delete F; 133 DeletedFunctions.clear(); 134 } 135 136 void InlineAdvice::recordInlineStatsIfNeeded() { 137 if (Advisor->ImportedFunctionsStats) 138 Advisor->ImportedFunctionsStats->recordInline(*Caller, *Callee); 139 } 140 141 void InlineAdvice::recordInlining() { 142 markRecorded(); 143 recordInlineStatsIfNeeded(); 144 recordInliningImpl(); 145 } 146 147 void InlineAdvice::recordInliningWithCalleeDeleted() { 148 markRecorded(); 149 recordInlineStatsIfNeeded(); 150 Advisor->markFunctionAsDeleted(Callee); 151 recordInliningWithCalleeDeletedImpl(); 152 } 153 154 AnalysisKey InlineAdvisorAnalysis::Key; 155 156 bool InlineAdvisorAnalysis::Result::tryCreate(InlineParams Params, 157 InliningAdvisorMode Mode, 158 StringRef ReplayFile) { 159 auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 160 switch (Mode) { 161 case InliningAdvisorMode::Default: 162 Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params)); 163 // Restrict replay to default advisor, ML advisors are stateful so 164 // replay will need augmentations to interleave with them correctly. 165 if (!ReplayFile.empty()) { 166 Advisor = std::make_unique<ReplayInlineAdvisor>( 167 M, FAM, M.getContext(), std::move(Advisor), ReplayFile, 168 /* EmitRemarks =*/true); 169 } 170 break; 171 case InliningAdvisorMode::Development: 172 #ifdef LLVM_HAVE_TF_API 173 Advisor = 174 llvm::getDevelopmentModeAdvisor(M, MAM, [&FAM, Params](CallBase &CB) { 175 auto OIC = getDefaultInlineAdvice(CB, FAM, Params); 176 return OIC.hasValue(); 177 }); 178 #endif 179 break; 180 case InliningAdvisorMode::Release: 181 #ifdef LLVM_HAVE_TF_AOT 182 Advisor = llvm::getReleaseModeAdvisor(M, MAM); 183 #endif 184 break; 185 } 186 187 return !!Advisor; 188 } 189 190 /// Return true if inlining of CB can block the caller from being 191 /// inlined which is proved to be more beneficial. \p IC is the 192 /// estimated inline cost associated with callsite \p CB. 193 /// \p TotalSecondaryCost will be set to the estimated cost of inlining the 194 /// caller if \p CB is suppressed for inlining. 195 static bool 196 shouldBeDeferred(Function *Caller, InlineCost IC, int &TotalSecondaryCost, 197 function_ref<InlineCost(CallBase &CB)> GetInlineCost) { 198 // For now we only handle local or inline functions. 199 if (!Caller->hasLocalLinkage() && !Caller->hasLinkOnceODRLinkage()) 200 return false; 201 // If the cost of inlining CB is non-positive, it is not going to prevent the 202 // caller from being inlined into its callers and hence we don't need to 203 // defer. 204 if (IC.getCost() <= 0) 205 return false; 206 // Try to detect the case where the current inlining candidate caller (call 207 // it B) is a static or linkonce-ODR function and is an inlining candidate 208 // elsewhere, and the current candidate callee (call it C) is large enough 209 // that inlining it into B would make B too big to inline later. In these 210 // circumstances it may be best not to inline C into B, but to inline B into 211 // its callers. 212 // 213 // This only applies to static and linkonce-ODR functions because those are 214 // expected to be available for inlining in the translation units where they 215 // are used. Thus we will always have the opportunity to make local inlining 216 // decisions. Importantly the linkonce-ODR linkage covers inline functions 217 // and templates in C++. 218 // 219 // FIXME: All of this logic should be sunk into getInlineCost. It relies on 220 // the internal implementation of the inline cost metrics rather than 221 // treating them as truly abstract units etc. 222 TotalSecondaryCost = 0; 223 // The candidate cost to be imposed upon the current function. 224 int CandidateCost = IC.getCost() - 1; 225 // If the caller has local linkage and can be inlined to all its callers, we 226 // can apply a huge negative bonus to TotalSecondaryCost. 227 bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse(); 228 // This bool tracks what happens if we DO inline C into B. 229 bool InliningPreventsSomeOuterInline = false; 230 unsigned NumCallerUsers = 0; 231 for (User *U : Caller->users()) { 232 CallBase *CS2 = dyn_cast<CallBase>(U); 233 234 // If this isn't a call to Caller (it could be some other sort 235 // of reference) skip it. Such references will prevent the caller 236 // from being removed. 237 if (!CS2 || CS2->getCalledFunction() != Caller) { 238 ApplyLastCallBonus = false; 239 continue; 240 } 241 242 InlineCost IC2 = GetInlineCost(*CS2); 243 ++NumCallerCallersAnalyzed; 244 if (!IC2) { 245 ApplyLastCallBonus = false; 246 continue; 247 } 248 if (IC2.isAlways()) 249 continue; 250 251 // See if inlining of the original callsite would erase the cost delta of 252 // this callsite. We subtract off the penalty for the call instruction, 253 // which we would be deleting. 254 if (IC2.getCostDelta() <= CandidateCost) { 255 InliningPreventsSomeOuterInline = true; 256 TotalSecondaryCost += IC2.getCost(); 257 NumCallerUsers++; 258 } 259 } 260 261 if (!InliningPreventsSomeOuterInline) 262 return false; 263 264 // If all outer calls to Caller would get inlined, the cost for the last 265 // one is set very low by getInlineCost, in anticipation that Caller will 266 // be removed entirely. We did not account for this above unless there 267 // is only one caller of Caller. 268 if (ApplyLastCallBonus) 269 TotalSecondaryCost -= InlineConstants::LastCallToStaticBonus; 270 271 // If InlineDeferralScale is negative, then ignore the cost of primary 272 // inlining -- IC.getCost() multiplied by the number of callers to Caller. 273 if (InlineDeferralScale < 0) 274 return TotalSecondaryCost < IC.getCost(); 275 276 int TotalCost = TotalSecondaryCost + IC.getCost() * NumCallerUsers; 277 int Allowance = IC.getCost() * InlineDeferralScale; 278 return TotalCost < Allowance; 279 } 280 281 namespace llvm { 282 static std::basic_ostream<char> &operator<<(std::basic_ostream<char> &R, 283 const ore::NV &Arg) { 284 return R << Arg.Val; 285 } 286 287 template <class RemarkT> 288 RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) { 289 using namespace ore; 290 if (IC.isAlways()) { 291 R << "(cost=always)"; 292 } else if (IC.isNever()) { 293 R << "(cost=never)"; 294 } else { 295 R << "(cost=" << ore::NV("Cost", IC.getCost()) 296 << ", threshold=" << ore::NV("Threshold", IC.getThreshold()) << ")"; 297 } 298 if (const char *Reason = IC.getReason()) 299 R << ": " << ore::NV("Reason", Reason); 300 return R; 301 } 302 } // namespace llvm 303 304 std::string llvm::inlineCostStr(const InlineCost &IC) { 305 std::stringstream Remark; 306 Remark << IC; 307 return Remark.str(); 308 } 309 310 void llvm::setInlineRemark(CallBase &CB, StringRef Message) { 311 if (!InlineRemarkAttribute) 312 return; 313 314 Attribute Attr = Attribute::get(CB.getContext(), "inline-remark", Message); 315 CB.addAttribute(AttributeList::FunctionIndex, Attr); 316 } 317 318 /// Return the cost only if the inliner should attempt to inline at the given 319 /// CallSite. If we return the cost, we will emit an optimisation remark later 320 /// using that cost, so we won't do so from this function. Return None if 321 /// inlining should not be attempted. 322 Optional<InlineCost> 323 llvm::shouldInline(CallBase &CB, 324 function_ref<InlineCost(CallBase &CB)> GetInlineCost, 325 OptimizationRemarkEmitter &ORE, bool EnableDeferral) { 326 using namespace ore; 327 328 InlineCost IC = GetInlineCost(CB); 329 Instruction *Call = &CB; 330 Function *Callee = CB.getCalledFunction(); 331 Function *Caller = CB.getCaller(); 332 333 if (IC.isAlways()) { 334 LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC) 335 << ", Call: " << CB << "\n"); 336 return IC; 337 } 338 339 if (!IC) { 340 LLVM_DEBUG(dbgs() << " NOT Inlining " << inlineCostStr(IC) 341 << ", Call: " << CB << "\n"); 342 if (IC.isNever()) { 343 ORE.emit([&]() { 344 return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call) 345 << NV("Callee", Callee) << " not inlined into " 346 << NV("Caller", Caller) << " because it should never be inlined " 347 << IC; 348 }); 349 } else { 350 ORE.emit([&]() { 351 return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call) 352 << NV("Callee", Callee) << " not inlined into " 353 << NV("Caller", Caller) << " because too costly to inline " 354 << IC; 355 }); 356 } 357 setInlineRemark(CB, inlineCostStr(IC)); 358 return None; 359 } 360 361 int TotalSecondaryCost = 0; 362 if (EnableDeferral && 363 shouldBeDeferred(Caller, IC, TotalSecondaryCost, GetInlineCost)) { 364 LLVM_DEBUG(dbgs() << " NOT Inlining: " << CB 365 << " Cost = " << IC.getCost() 366 << ", outer Cost = " << TotalSecondaryCost << '\n'); 367 ORE.emit([&]() { 368 return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts", 369 Call) 370 << "Not inlining. Cost of inlining " << NV("Callee", Callee) 371 << " increases the cost of inlining " << NV("Caller", Caller) 372 << " in other contexts"; 373 }); 374 setInlineRemark(CB, "deferred"); 375 // IC does not bool() to false, so get an InlineCost that will. 376 // This will not be inspected to make an error message. 377 return None; 378 } 379 380 LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC) << ", Call: " << CB 381 << '\n'); 382 return IC; 383 } 384 385 std::string llvm::getCallSiteLocation(DebugLoc DLoc) { 386 std::ostringstream CallSiteLoc; 387 bool First = true; 388 for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) { 389 if (!First) 390 CallSiteLoc << " @ "; 391 // Note that negative line offset is actually possible, but we use 392 // unsigned int to match line offset representation in remarks so 393 // it's directly consumable by relay advisor. 394 uint32_t Offset = 395 DIL->getLine() - DIL->getScope()->getSubprogram()->getLine(); 396 uint32_t Discriminator = DIL->getBaseDiscriminator(); 397 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); 398 if (Name.empty()) 399 Name = DIL->getScope()->getSubprogram()->getName(); 400 CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset) << ":" 401 << llvm::utostr(DIL->getColumn()); 402 if (Discriminator) 403 CallSiteLoc << "." << llvm::utostr(Discriminator); 404 First = false; 405 } 406 407 return CallSiteLoc.str(); 408 } 409 410 void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) { 411 if (!DLoc.get()) { 412 return; 413 } 414 415 bool First = true; 416 Remark << " at callsite "; 417 for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) { 418 if (!First) 419 Remark << " @ "; 420 unsigned int Offset = DIL->getLine(); 421 Offset -= DIL->getScope()->getSubprogram()->getLine(); 422 unsigned int Discriminator = DIL->getBaseDiscriminator(); 423 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); 424 if (Name.empty()) 425 Name = DIL->getScope()->getSubprogram()->getName(); 426 Remark << Name << ":" << ore::NV("Line", Offset) << ":" 427 << ore::NV("Column", DIL->getColumn()); 428 if (Discriminator) 429 Remark << "." << ore::NV("Disc", Discriminator); 430 First = false; 431 } 432 433 Remark << ";"; 434 } 435 436 void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, 437 const BasicBlock *Block, const Function &Callee, 438 const Function &Caller, const InlineCost &IC, 439 bool ForProfileContext, const char *PassName) { 440 ORE.emit([&]() { 441 bool AlwaysInline = IC.isAlways(); 442 StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined"; 443 OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName, 444 DLoc, Block); 445 Remark << ore::NV("Callee", &Callee) << " inlined into "; 446 Remark << ore::NV("Caller", &Caller); 447 if (ForProfileContext) 448 Remark << " to match profiling context"; 449 Remark << " with " << IC; 450 addLocationToRemarks(Remark, DLoc); 451 return Remark; 452 }); 453 } 454 455 InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM) 456 : M(M), FAM(FAM) { 457 if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) { 458 ImportedFunctionsStats = 459 std::make_unique<ImportedFunctionsInliningStatistics>(); 460 ImportedFunctionsStats->setModuleInfo(M); 461 } 462 } 463 464 InlineAdvisor::~InlineAdvisor() { 465 if (ImportedFunctionsStats) { 466 assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No); 467 ImportedFunctionsStats->dump(InlinerFunctionImportStats == 468 InlinerFunctionImportStatsOpts::Verbose); 469 } 470 471 freeDeletedFunctions(); 472 } 473 474 std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB, 475 bool Advice) { 476 return std::make_unique<InlineAdvice>(this, CB, getCallerORE(CB), Advice); 477 } 478 479 InlineAdvisor::MandatoryInliningKind 480 InlineAdvisor::getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM, 481 OptimizationRemarkEmitter &ORE) { 482 auto &Callee = *CB.getCalledFunction(); 483 484 auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & { 485 return FAM.getResult<TargetLibraryAnalysis>(F); 486 }; 487 488 auto &TIR = FAM.getResult<TargetIRAnalysis>(Callee); 489 490 auto TrivialDecision = 491 llvm::getAttributeBasedInliningDecision(CB, &Callee, TIR, GetTLI); 492 493 if (TrivialDecision.hasValue()) { 494 if (TrivialDecision->isSuccess()) 495 return MandatoryInliningKind::Always; 496 else 497 return MandatoryInliningKind::Never; 498 } 499 return MandatoryInliningKind::NotMandatory; 500 } 501 502 std::unique_ptr<InlineAdvice> InlineAdvisor::getAdvice(CallBase &CB, 503 bool MandatoryOnly) { 504 if (!MandatoryOnly) 505 return getAdviceImpl(CB); 506 bool Advice = CB.getCaller() != CB.getCalledFunction() && 507 MandatoryInliningKind::Always == 508 getMandatoryKind(CB, FAM, getCallerORE(CB)); 509 return getMandatoryAdvice(CB, Advice); 510 } 511 512 OptimizationRemarkEmitter &InlineAdvisor::getCallerORE(CallBase &CB) { 513 return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller()); 514 } 515