InlineAdvisor.cpp 21 KB

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