[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