InlineAdvisor.cpp 24 KB

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