Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- InlineAdvisor.h - Inlining decision making abstraction -*- C++ ---*-===//
  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. #ifndef LLVM_ANALYSIS_INLINEADVISOR_H
  10. #define LLVM_ANALYSIS_INLINEADVISOR_H
  11.  
  12. #include "llvm/Analysis/CGSCCPassManager.h"
  13. #include "llvm/Analysis/InlineCost.h"
  14. #include "llvm/Analysis/LazyCallGraph.h"
  15. #include "llvm/Config/llvm-config.h"
  16. #include "llvm/IR/PassManager.h"
  17. #include <memory>
  18.  
  19. namespace llvm {
  20. class BasicBlock;
  21. class CallBase;
  22. class Function;
  23. class Module;
  24. class OptimizationRemark;
  25. class ImportedFunctionsInliningStatistics;
  26. class OptimizationRemarkEmitter;
  27. struct ReplayInlinerSettings;
  28.  
  29. /// There are 4 scenarios we can use the InlineAdvisor:
  30. /// - Default - use manual heuristics.
  31. ///
  32. /// - Release mode, the expected mode for production, day to day deployments.
  33. /// In this mode, when building the compiler, we also compile a pre-trained ML
  34. /// model to native code, and link it as a static library. This mode has low
  35. /// overhead and no additional dependencies for the compiler runtime.
  36. ///
  37. /// - Development mode, for training new models.
  38. /// In this mode, we trade off runtime performance for flexibility. This mode
  39. /// requires the full C Tensorflow API library, and evaluates models
  40. /// dynamically. This mode also permits generating training logs, for offline
  41. /// training.
  42. ///
  43. /// - Dynamically load an advisor via a plugin (PluginInlineAdvisorAnalysis)
  44. enum class InliningAdvisorMode : int { Default, Release, Development };
  45.  
  46. // Each entry represents an inline driver.
  47. enum class InlinePass : int {
  48.   AlwaysInliner,
  49.   CGSCCInliner,
  50.   EarlyInliner,
  51.   ModuleInliner,
  52.   MLInliner,
  53.   ReplayCGSCCInliner,
  54.   ReplaySampleProfileInliner,
  55.   SampleProfileInliner,
  56. };
  57.  
  58. /// Provides context on when an inline advisor is constructed in the pipeline
  59. /// (e.g., link phase, inline driver).
  60. struct InlineContext {
  61.   ThinOrFullLTOPhase LTOPhase;
  62.  
  63.   InlinePass Pass;
  64. };
  65.  
  66. std::string AnnotateInlinePassName(InlineContext IC);
  67.  
  68. class InlineAdvisor;
  69. /// Capture state between an inlining decision having had been made, and
  70. /// its impact being observable. When collecting model training data, this
  71. /// allows recording features/decisions/partial reward data sets.
  72. ///
  73. /// Derivations of this type are expected to be tightly coupled with their
  74. /// InliningAdvisors. The base type implements the minimal contractual
  75. /// obligations.
  76. class InlineAdvice {
  77. public:
  78.   InlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
  79.                OptimizationRemarkEmitter &ORE, bool IsInliningRecommended);
  80.  
  81.   InlineAdvice(InlineAdvice &&) = delete;
  82.   InlineAdvice(const InlineAdvice &) = delete;
  83.   virtual ~InlineAdvice() {
  84.     assert(Recorded && "InlineAdvice should have been informed of the "
  85.                        "inliner's decision in all cases");
  86.   }
  87.  
  88.   /// Exactly one of the record* APIs must be called. Implementers may extend
  89.   /// behavior by implementing the corresponding record*Impl.
  90.   ///
  91.   /// Call after inlining succeeded, and did not result in deleting the callee.
  92.   void recordInlining();
  93.  
  94.   /// Call after inlining succeeded, and results in the callee being
  95.   /// delete-able, meaning, it has no more users, and will be cleaned up
  96.   /// subsequently.
  97.   void recordInliningWithCalleeDeleted();
  98.  
  99.   /// Call after the decision for a call site was to not inline.
  100.   void recordUnsuccessfulInlining(const InlineResult &Result) {
  101.     markRecorded();
  102.     recordUnsuccessfulInliningImpl(Result);
  103.   }
  104.  
  105.   /// Call to indicate inlining was not attempted.
  106.   void recordUnattemptedInlining() {
  107.     markRecorded();
  108.     recordUnattemptedInliningImpl();
  109.   }
  110.  
  111.   /// Get the inlining recommendation.
  112.   bool isInliningRecommended() const { return IsInliningRecommended; }
  113.   const DebugLoc &getOriginalCallSiteDebugLoc() const { return DLoc; }
  114.   const BasicBlock *getOriginalCallSiteBasicBlock() const { return Block; }
  115.  
  116. protected:
  117.   virtual void recordInliningImpl() {}
  118.   virtual void recordInliningWithCalleeDeletedImpl() {}
  119.   virtual void recordUnsuccessfulInliningImpl(const InlineResult &Result) {}
  120.   virtual void recordUnattemptedInliningImpl() {}
  121.  
  122.   InlineAdvisor *const Advisor;
  123.   /// Caller and Callee are pre-inlining.
  124.   Function *const Caller;
  125.   Function *const Callee;
  126.  
  127.   // Capture the context of CB before inlining, as a successful inlining may
  128.   // change that context, and we want to report success or failure in the
  129.   // original context.
  130.   const DebugLoc DLoc;
  131.   const BasicBlock *const Block;
  132.   OptimizationRemarkEmitter &ORE;
  133.   const bool IsInliningRecommended;
  134.  
  135. private:
  136.   void markRecorded() {
  137.     assert(!Recorded && "Recording should happen exactly once");
  138.     Recorded = true;
  139.   }
  140.   void recordInlineStatsIfNeeded();
  141.  
  142.   bool Recorded = false;
  143. };
  144.  
  145. class DefaultInlineAdvice : public InlineAdvice {
  146. public:
  147.   DefaultInlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
  148.                       std::optional<InlineCost> OIC,
  149.                       OptimizationRemarkEmitter &ORE, bool EmitRemarks = true)
  150.       : InlineAdvice(Advisor, CB, ORE, OIC.has_value()), OriginalCB(&CB),
  151.         OIC(OIC), EmitRemarks(EmitRemarks) {}
  152.  
  153. private:
  154.   void recordUnsuccessfulInliningImpl(const InlineResult &Result) override;
  155.   void recordInliningWithCalleeDeletedImpl() override;
  156.   void recordInliningImpl() override;
  157.  
  158. private:
  159.   CallBase *const OriginalCB;
  160.   std::optional<InlineCost> OIC;
  161.   bool EmitRemarks;
  162. };
  163.  
  164. /// Interface for deciding whether to inline a call site or not.
  165. class InlineAdvisor {
  166. public:
  167.   InlineAdvisor(InlineAdvisor &&) = delete;
  168.   virtual ~InlineAdvisor();
  169.  
  170.   /// Get an InlineAdvice containing a recommendation on whether to
  171.   /// inline or not. \p CB is assumed to be a direct call. \p FAM is assumed to
  172.   /// be up-to-date wrt previous inlining decisions. \p MandatoryOnly indicates
  173.   /// only mandatory (always-inline) call sites should be recommended - this
  174.   /// allows the InlineAdvisor track such inlininings.
  175.   /// Returns:
  176.   /// - An InlineAdvice with the inlining recommendation.
  177.   /// - Null when no recommendation is made (https://reviews.llvm.org/D110658).
  178.   /// TODO: Consider removing the Null return scenario by incorporating the
  179.   /// SampleProfile inliner into an InlineAdvisor
  180.   std::unique_ptr<InlineAdvice> getAdvice(CallBase &CB,
  181.                                           bool MandatoryOnly = false);
  182.  
  183.   /// This must be called when the Inliner pass is entered, to allow the
  184.   /// InlineAdvisor update internal state, as result of function passes run
  185.   /// between Inliner pass runs (for the same module).
  186.   virtual void onPassEntry(LazyCallGraph::SCC *SCC = nullptr) {}
  187.  
  188.   /// This must be called when the Inliner pass is exited, as function passes
  189.   /// may be run subsequently. This allows an implementation of InlineAdvisor
  190.   /// to prepare for a partial update, based on the optional SCC.
  191.   virtual void onPassExit(LazyCallGraph::SCC *SCC = nullptr) {}
  192.  
  193.   /// Support for printer pass
  194.   virtual void print(raw_ostream &OS) const {
  195.     OS << "Unimplemented InlineAdvisor print\n";
  196.   }
  197.  
  198.   /// NOTE pass name is annotated only when inline advisor constructor provides InlineContext.
  199.   const char *getAnnotatedInlinePassName() const {
  200.     return AnnotatedInlinePassName.c_str();
  201.   }
  202.  
  203. protected:
  204.   InlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
  205.                 std::optional<InlineContext> IC = std::nullopt);
  206.   virtual std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) = 0;
  207.   virtual std::unique_ptr<InlineAdvice> getMandatoryAdvice(CallBase &CB,
  208.                                                            bool Advice);
  209.  
  210.   Module &M;
  211.   FunctionAnalysisManager &FAM;
  212.   const std::optional<InlineContext> IC;
  213.   const std::string AnnotatedInlinePassName;
  214.   std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats;
  215.  
  216.   enum class MandatoryInliningKind { NotMandatory, Always, Never };
  217.  
  218.   static MandatoryInliningKind getMandatoryKind(CallBase &CB,
  219.                                                 FunctionAnalysisManager &FAM,
  220.                                                 OptimizationRemarkEmitter &ORE);
  221.  
  222.   OptimizationRemarkEmitter &getCallerORE(CallBase &CB);
  223.  
  224. private:
  225.   friend class InlineAdvice;
  226. };
  227.  
  228. /// The default (manual heuristics) implementation of the InlineAdvisor. This
  229. /// implementation does not need to keep state between inliner pass runs, and is
  230. /// reusable as-is for inliner pass test scenarios, as well as for regular use.
  231. class DefaultInlineAdvisor : public InlineAdvisor {
  232. public:
  233.   DefaultInlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
  234.                        InlineParams Params, InlineContext IC)
  235.       : InlineAdvisor(M, FAM, IC), Params(Params) {}
  236.  
  237. private:
  238.   std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) override;
  239.  
  240.   InlineParams Params;
  241. };
  242.  
  243. /// Used for dynamically registering InlineAdvisors as plugins
  244. ///
  245. /// An advisor plugin adds a new advisor at runtime by registering an instance
  246. /// of PluginInlineAdvisorAnalysis in the current ModuleAnalysisManager.
  247. /// For example, the following code dynamically registers a
  248. /// DefaultInlineAdvisor:
  249. ///
  250. /// namespace {
  251. ///
  252. /// InlineAdvisor *defaultAdvisorFactory(Module &M, FunctionAnalysisManager
  253. /// &FAM,
  254. ///                                      InlineParams Params, InlineContext IC)
  255. ///                                      {
  256. ///   return new DefaultInlineAdvisor(M, FAM, Params, IC);
  257. /// }
  258. ///
  259. /// struct DefaultDynamicAdvisor : PassInfoMixin<DefaultDynamicAdvisor> {
  260. ///   PreservedAnalyses run(Module &, ModuleAnalysisManager &MAM) {
  261. ///     PluginInlineAdvisorAnalysis PA(defaultAdvisorFactory);
  262. ///     MAM.registerPass([&] { return PA; });
  263. ///     return PreservedAnalyses::all();
  264. ///   }
  265. /// };
  266. ///
  267. /// } // namespace
  268. ///
  269. /// extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
  270. /// llvmGetPassPluginInfo() {
  271. ///   return {LLVM_PLUGIN_API_VERSION, "DynamicDefaultAdvisor",
  272. ///   LLVM_VERSION_STRING,
  273. ///           [](PassBuilder &PB) {
  274. ///             PB.registerPipelineStartEPCallback(
  275. ///                 [](ModulePassManager &MPM, OptimizationLevel Level) {
  276. ///                   MPM.addPass(DefaultDynamicAdvisor());
  277. ///                 });
  278. ///           }};
  279. /// }
  280. ///
  281. /// A plugin must implement an AdvisorFactory and register it with a
  282. /// PluginInlineAdvisorAnlysis to the provided ModuleanAlysisManager.
  283. ///
  284. /// If such a plugin has been registered
  285. /// InlineAdvisorAnalysis::Result::tryCreate will return the dynamically loaded
  286. /// advisor.
  287. ///
  288. class PluginInlineAdvisorAnalysis
  289.     : public AnalysisInfoMixin<PluginInlineAdvisorAnalysis> {
  290. public:
  291.   static AnalysisKey Key;
  292.   static bool HasBeenRegistered;
  293.  
  294.   typedef InlineAdvisor *(*AdvisorFactory)(Module &M,
  295.                                            FunctionAnalysisManager &FAM,
  296.                                            InlineParams Params,
  297.                                            InlineContext IC);
  298.  
  299.   PluginInlineAdvisorAnalysis(AdvisorFactory Factory) : Factory(Factory) {
  300.     HasBeenRegistered = true;
  301.     assert(Factory != nullptr &&
  302.            "The plugin advisor factory should not be a null pointer.");
  303.   }
  304.  
  305.   struct Result {
  306.     AdvisorFactory Factory;
  307.   };
  308.  
  309.   Result run(Module &M, ModuleAnalysisManager &MAM) { return {Factory}; }
  310.   Result getResult() { return {Factory}; }
  311.  
  312. private:
  313.   AdvisorFactory Factory;
  314. };
  315.  
  316. /// The InlineAdvisorAnalysis is a module pass because the InlineAdvisor
  317. /// needs to capture state right before inlining commences over a module.
  318. class InlineAdvisorAnalysis : public AnalysisInfoMixin<InlineAdvisorAnalysis> {
  319. public:
  320.   static AnalysisKey Key;
  321.   InlineAdvisorAnalysis() = default;
  322.   struct Result {
  323.     Result(Module &M, ModuleAnalysisManager &MAM) : M(M), MAM(MAM) {}
  324.     bool invalidate(Module &, const PreservedAnalyses &PA,
  325.                     ModuleAnalysisManager::Invalidator &) {
  326.       // Check whether the analysis has been explicitly invalidated. Otherwise,
  327.       // it's stateless and remains preserved.
  328.       auto PAC = PA.getChecker<InlineAdvisorAnalysis>();
  329.       return !PAC.preservedWhenStateless();
  330.     }
  331.     bool tryCreate(InlineParams Params, InliningAdvisorMode Mode,
  332.                    const ReplayInlinerSettings &ReplaySettings,
  333.                    InlineContext IC);
  334.     InlineAdvisor *getAdvisor() const { return Advisor.get(); }
  335.  
  336.   private:
  337.     Module &M;
  338.     ModuleAnalysisManager &MAM;
  339.     std::unique_ptr<InlineAdvisor> Advisor;
  340.   };
  341.  
  342.   Result run(Module &M, ModuleAnalysisManager &MAM) { return Result(M, MAM); }
  343. };
  344.  
  345. /// Printer pass for the FunctionPropertiesAnalysis results.
  346. class InlineAdvisorAnalysisPrinterPass
  347.     : public PassInfoMixin<InlineAdvisorAnalysisPrinterPass> {
  348.   raw_ostream &OS;
  349.  
  350. public:
  351.   explicit InlineAdvisorAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {}
  352.  
  353.   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
  354.  
  355.   PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM,
  356.                         LazyCallGraph &CG, CGSCCUpdateResult &UR);
  357. };
  358.  
  359. std::unique_ptr<InlineAdvisor>
  360. getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM);
  361.  
  362. std::unique_ptr<InlineAdvisor>
  363. getDevelopmentModeAdvisor(Module &M, ModuleAnalysisManager &MAM,
  364.                           std::function<bool(CallBase &)> GetDefaultAdvice);
  365.  
  366. // Default (manual policy) decision making helper APIs. Shared with the legacy
  367. // pass manager inliner.
  368.  
  369. /// Return the cost only if the inliner should attempt to inline at the given
  370. /// CallSite. If we return the cost, we will emit an optimisation remark later
  371. /// using that cost, so we won't do so from this function. Return std::nullopt
  372. /// if inlining should not be attempted.
  373. std::optional<InlineCost>
  374. shouldInline(CallBase &CB, function_ref<InlineCost(CallBase &CB)> GetInlineCost,
  375.              OptimizationRemarkEmitter &ORE, bool EnableDeferral = true);
  376.  
  377. /// Emit ORE message.
  378. void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
  379.                      const BasicBlock *Block, const Function &Callee,
  380.                      const Function &Caller, bool IsMandatory,
  381.                      function_ref<void(OptimizationRemark &)> ExtraContext = {},
  382.                      const char *PassName = nullptr);
  383.  
  384. /// Emit ORE message based in cost (default heuristic).
  385. void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
  386.                                 const BasicBlock *Block, const Function &Callee,
  387.                                 const Function &Caller, const InlineCost &IC,
  388.                                 bool ForProfileContext = false,
  389.                                 const char *PassName = nullptr);
  390.  
  391. /// Add location info to ORE message.
  392. void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc);
  393.  
  394. /// Set the inline-remark attribute.
  395. void setInlineRemark(CallBase &CB, StringRef Message);
  396.  
  397. /// Utility for extracting the inline cost message to a string.
  398. std::string inlineCostStr(const InlineCost &IC);
  399. } // namespace llvm
  400. #endif // LLVM_ANALYSIS_INLINEADVISOR_H
  401.