[llvm] d52e775 - [llvm][ModuleInliner] Add inline cost priority for module inliner

Liqiang Tao via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 28 07:44:36 PDT 2022


Author: Liqiang Tao
Date: 2022-07-28T22:44:03+08:00
New Revision: d52e775b05a4eb1217e0e007b702f46ea097c2a3

URL: https://github.com/llvm/llvm-project/commit/d52e775b05a4eb1217e0e007b702f46ea097c2a3
DIFF: https://github.com/llvm/llvm-project/commit/d52e775b05a4eb1217e0e007b702f46ea097c2a3.diff

LOG: [llvm][ModuleInliner] Add inline cost priority for module inliner

This patch introduces the inline cost priority into the
module inliner, which uses the same computation as
InlineCost.

Reviewed By: kazu

Differential Revision: https://reviews.llvm.org/D130012

Added: 
    llvm/lib/Analysis/InlineOrder.cpp

Modified: 
    llvm/include/llvm/Analysis/InlineOrder.h
    llvm/lib/Analysis/CMakeLists.txt
    llvm/lib/Transforms/IPO/ModuleInliner.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/InlineOrder.h b/llvm/include/llvm/Analysis/InlineOrder.h
index aabd86c987802..9111826d47b93 100644
--- a/llvm/include/llvm/Analysis/InlineOrder.h
+++ b/llvm/include/llvm/Analysis/InlineOrder.h
@@ -12,6 +12,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/InlineCost.h"
 #include "llvm/IR/InstrTypes.h"
 #include <algorithm>
 #include <utility>
@@ -20,6 +21,8 @@ namespace llvm {
 class CallBase;
 class Function;
 
+enum class InlinePriorityMode : int { NoPriority, Size, Cost, OptRatio };
+
 template <typename T> class InlineOrder {
 public:
   using reference = T &;
@@ -40,6 +43,10 @@ template <typename T> class InlineOrder {
   bool empty() { return !size(); }
 };
 
+std::unique_ptr<InlineOrder<std::pair<CallBase *, int>>>
+getInlineOrder(InlinePriorityMode UseInlinePriority,
+               FunctionAnalysisManager &FAM, const InlineParams &Params);
+
 template <typename T, typename Container = SmallVector<T, 16>>
 class DefaultInlineOrder : public InlineOrder<T> {
   using reference = T &;
@@ -82,15 +89,16 @@ class SizePriority : public InlinePriority {
   using PriorityT = unsigned;
   DenseMap<const CallBase *, PriorityT> Priorities;
 
-  static PriorityT evaluate(const CallBase *CB) {
+  PriorityT evaluate(const CallBase *CB) {
     Function *Callee = CB->getCalledFunction();
     return Callee->getInstructionCount();
   }
 
-  static bool isMoreDesirable(const PriorityT &P1, const PriorityT &P2) {
+  bool isMoreDesirable(const PriorityT &P1, const PriorityT &P2) const {
     return P1 < P2;
   }
 
+public:
   bool hasLowerPriority(const CallBase *L, const CallBase *R) const override {
     const auto I1 = Priorities.find(L);
     const auto I2 = Priorities.find(R);
@@ -98,7 +106,49 @@ class SizePriority : public InlinePriority {
     return isMoreDesirable(I2->second, I1->second);
   }
 
+  // Update the priority associated with CB.
+  void update(const CallBase *CB) override { Priorities[CB] = evaluate(CB); };
+
+  bool updateAndCheckDecreased(const CallBase *CB) override {
+    auto It = Priorities.find(CB);
+    const auto OldPriority = It->second;
+    It->second = evaluate(CB);
+    const auto NewPriority = It->second;
+    return isMoreDesirable(OldPriority, NewPriority);
+  }
+};
+
+class CostPriority : public InlinePriority {
+  using PriorityT = int;
+  DenseMap<const CallBase *, PriorityT> Priorities;
+  std::function<InlineCost(const CallBase *)> getInlineCost;
+
+  PriorityT evaluate(const CallBase *CB) {
+    auto IC = getInlineCost(CB);
+    int cost = 0;
+    if (IC.isVariable())
+      cost = IC.getCost();
+    else
+      cost = IC.isNever() ? INT_MAX : INT_MIN;
+    return cost;
+  }
+
+  bool isMoreDesirable(const PriorityT &P1, const PriorityT &P2) const {
+    return P1 < P2;
+  }
+
 public:
+  CostPriority() = delete;
+  CostPriority(std::function<InlineCost(const CallBase *)> getInlineCost)
+      : getInlineCost(getInlineCost){};
+
+  bool hasLowerPriority(const CallBase *L, const CallBase *R) const override {
+    const auto I1 = Priorities.find(L);
+    const auto I2 = Priorities.find(R);
+    assert(I1 != Priorities.end() && I2 != Priorities.end());
+    return isMoreDesirable(I2->second, I1->second);
+  }
+
   // Update the priority associated with CB.
   void update(const CallBase *CB) override { Priorities[CB] = evaluate(CB); };
 
@@ -184,5 +234,6 @@ class PriorityInlineOrder : public InlineOrder<std::pair<CallBase *, int>> {
   DenseMap<CallBase *, int> InlineHistoryMap;
   std::unique_ptr<InlinePriority> PriorityPtr;
 };
+
 } // namespace llvm
 #endif // LLVM_ANALYSIS_INLINEORDER_H

diff  --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index e59725c990170..529b522ac0ad6 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -72,6 +72,7 @@ add_llvm_component_library(LLVMAnalysis
   IndirectCallPromotionAnalysis.cpp
   InlineCost.cpp
   InlineAdvisor.cpp
+  InlineOrder.cpp
   InlineSizeEstimatorAnalysis.cpp
   InstCount.cpp
   InstructionPrecedenceTracking.cpp

diff  --git a/llvm/lib/Analysis/InlineOrder.cpp b/llvm/lib/Analysis/InlineOrder.cpp
new file mode 100644
index 0000000000000..a92cc6879b1ab
--- /dev/null
+++ b/llvm/lib/Analysis/InlineOrder.cpp
@@ -0,0 +1,77 @@
+//===- InlineOrder.cpp - Inlining order abstraction -*- C++ ---*-----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/InlineOrder.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/InlineAdvisor.h"
+#include "llvm/Analysis/InlineCost.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/Analysis/ProfileSummaryInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "inline-order"
+
+static llvm::InlineCost getInlineCostWrapper(CallBase &CB,
+                                             FunctionAnalysisManager &FAM,
+                                             const InlineParams &Params) {
+  Function &Caller = *CB.getCaller();
+  ProfileSummaryInfo *PSI =
+      FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Caller)
+          .getCachedResult<ProfileSummaryAnalysis>(
+              *CB.getParent()->getParent()->getParent());
+
+  auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
+  auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
+    return FAM.getResult<AssumptionAnalysis>(F);
+  };
+  auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
+    return FAM.getResult<BlockFrequencyAnalysis>(F);
+  };
+  auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
+    return FAM.getResult<TargetLibraryAnalysis>(F);
+  };
+
+  Function &Callee = *CB.getCalledFunction();
+  auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
+  bool RemarksEnabled =
+      Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
+          DEBUG_TYPE);
+  return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
+                       GetBFI, PSI, RemarksEnabled ? &ORE : nullptr);
+}
+
+std::unique_ptr<InlineOrder<std::pair<CallBase *, int>>>
+llvm::getInlineOrder(InlinePriorityMode UseInlinePriority,
+                     FunctionAnalysisManager &FAM, const InlineParams &Params) {
+  switch (UseInlinePriority) {
+  case InlinePriorityMode::NoPriority:
+    return std::make_unique<DefaultInlineOrder<std::pair<CallBase *, int>>>();
+
+  case InlinePriorityMode::Size:
+    LLVM_DEBUG(dbgs() << "    Current used priority: Size priority ---- \n");
+    return std::make_unique<PriorityInlineOrder>(
+        std::make_unique<SizePriority>());
+
+  case InlinePriorityMode::Cost:
+    LLVM_DEBUG(dbgs() << "    Current used priority: Cost priority ---- \n");
+    return std::make_unique<PriorityInlineOrder>(
+        std::make_unique<CostPriority>([&](const CallBase *CB) -> InlineCost {
+          return getInlineCostWrapper(const_cast<CallBase &>(*CB), FAM, Params);
+        }));
+
+  default:
+    llvm_unreachable("Unsupported Inline Priority Mode");
+    break;
+  }
+  return nullptr;
+}

diff  --git a/llvm/lib/Transforms/IPO/ModuleInliner.cpp b/llvm/lib/Transforms/IPO/ModuleInliner.cpp
index 1437150065120..b16ab6d46d376 100644
--- a/llvm/lib/Transforms/IPO/ModuleInliner.cpp
+++ b/llvm/lib/Transforms/IPO/ModuleInliner.cpp
@@ -49,9 +49,15 @@ using namespace llvm;
 STATISTIC(NumInlined, "Number of functions inlined");
 STATISTIC(NumDeleted, "Number of functions deleted because all callers found");
 
-static cl::opt<bool> InlineEnablePriorityOrder(
-    "module-inline-enable-priority-order", cl::Hidden, cl::init(true),
-    cl::desc("Enable the priority inline order for the module inliner"));
+static cl::opt<InlinePriorityMode> UseInlinePriority(
+    "inline-priority-mode", cl::init(InlinePriorityMode::Size), cl::Hidden,
+    cl::desc("Choose the priority mode to use in module inline"),
+    cl::values(clEnumValN(InlinePriorityMode::NoPriority, "no priority",
+                          "Use no priority, visit callsites in bottom-up."),
+               clEnumValN(InlinePriorityMode::Size, "size",
+                          "Use callee size priority."),
+               clEnumValN(InlinePriorityMode::Cost, "cost",
+                          "Use inline cost priority.")));
 
 /// Return true if the specified inline history ID
 /// indicates an inline history that includes the specified function.
@@ -145,12 +151,7 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
   //
   // TODO: Here is a huge amount duplicate code between the module inliner and
   // the SCC inliner, which need some refactoring.
-  std::unique_ptr<InlineOrder<std::pair<CallBase *, int>>> Calls;
-  if (InlineEnablePriorityOrder)
-    Calls = std::make_unique<PriorityInlineOrder>(
-              std::make_unique<SizePriority>());
-  else
-    Calls = std::make_unique<DefaultInlineOrder<std::pair<CallBase *, int>>>();
+  auto Calls = getInlineOrder(UseInlinePriority, FAM, Params);
   assert(Calls != nullptr && "Expected an initialized InlineOrder");
 
   // Populate the initial list of calls in this module.


        


More information about the llvm-commits mailing list