Skip to content

Commit 6cad45d

Browse files
committed
[llvm][Inline] Add a module level inliner
Add module level inliner, which is a minimum viable product at this point. Also add some tests for it. RFC: https://lists.llvm.org/pipermail/llvm-dev/2021-August/152297.html Reviewed By: kazu Differential Revision: https://reviews.llvm.org/D106448
1 parent b3267bb commit 6cad45d

23 files changed

+461
-1
lines changed

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Support/PGOOptions.h"
2424
#include "llvm/Support/raw_ostream.h"
2525
#include "llvm/Transforms/IPO/Inliner.h"
26+
#include "llvm/Transforms/IPO/ModuleInliner.h"
2627
#include "llvm/Transforms/Instrumentation.h"
2728
#include "llvm/Transforms/Scalar/LoopPassManager.h"
2829
#include <vector>
@@ -196,6 +197,11 @@ class PassBuilder {
196197
ModuleInlinerWrapperPass buildInlinerPipeline(OptimizationLevel Level,
197198
ThinOrFullLTOPhase Phase);
198199

200+
/// Construct the module pipeline that performs inlining with
201+
/// module inliner pass.
202+
ModuleInlinerPass buildModuleInlinerPipeline(OptimizationLevel Level,
203+
ThinOrFullLTOPhase Phase);
204+
199205
/// Construct the core LLVM module optimization pipeline.
200206
///
201207
/// This pipeline focuses on optimizing the execution speed of the IR. It
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===- ModuleInliner.h - Module level Inliner pass --------------*- 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_TRANSFORMS_IPO_MODULEINLINER_H
10+
#define LLVM_TRANSFORMS_IPO_MODULEINLINER_H
11+
12+
#include "llvm/Analysis/InlineAdvisor.h"
13+
#include "llvm/Analysis/InlineCost.h"
14+
#include "llvm/Analysis/ReplayInlineAdvisor.h"
15+
#include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h"
16+
#include "llvm/IR/PassManager.h"
17+
#include <utility>
18+
19+
namespace llvm {
20+
21+
class AssumptionCacheTracker;
22+
class ProfileSummaryInfo;
23+
24+
/// The module inliner pass for the new pass manager.
25+
///
26+
/// This pass wires together the inlining utilities and the inline cost
27+
/// analysis into a module pass. Different from SCC inliner, it considers every
28+
/// call in every function in the whole module and tries to inline if
29+
/// profitable. With this module level inliner, it is possible to evaluate more
30+
/// heuristics in the module level such like PriorityInlineOrder. It can be
31+
/// tuned with a number of parameters to control what cost model is used and
32+
/// what tradeoffs are made when making the decision.
33+
class ModuleInlinerPass : public PassInfoMixin<ModuleInlinerPass> {
34+
public:
35+
ModuleInlinerPass(InlineParams Params = getInlineParams(),
36+
InliningAdvisorMode Mode = InliningAdvisorMode::Default)
37+
: Params(Params), Mode(Mode){};
38+
ModuleInlinerPass(ModuleInlinerPass &&Arg) = default;
39+
40+
PreservedAnalyses run(Module &, ModuleAnalysisManager &);
41+
42+
private:
43+
InlineAdvisor &getAdvisor(const ModuleAnalysisManager &MAM,
44+
FunctionAnalysisManager &FAM, Module &M);
45+
std::unique_ptr<InlineAdvisor> OwnedAdvisor;
46+
const InlineParams Params;
47+
const InliningAdvisorMode Mode;
48+
};
49+
} // end namespace llvm
50+
51+
#endif // LLVM_TRANSFORMS_IPO_MODULEINLINER_H

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
#include "llvm/Transforms/IPO/LoopExtractor.h"
111111
#include "llvm/Transforms/IPO/LowerTypeTests.h"
112112
#include "llvm/Transforms/IPO/MergeFunctions.h"
113+
#include "llvm/Transforms/IPO/ModuleInliner.h"
113114
#include "llvm/Transforms/IPO/OpenMPOpt.h"
114115
#include "llvm/Transforms/IPO/PartialInlining.h"
115116
#include "llvm/Transforms/IPO/SCCP.h"

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "llvm/Transforms/IPO/Inliner.h"
5656
#include "llvm/Transforms/IPO/LowerTypeTests.h"
5757
#include "llvm/Transforms/IPO/MergeFunctions.h"
58+
#include "llvm/Transforms/IPO/ModuleInliner.h"
5859
#include "llvm/Transforms/IPO/OpenMPOpt.h"
5960
#include "llvm/Transforms/IPO/PartialInlining.h"
6061
#include "llvm/Transforms/IPO/SCCP.h"
@@ -153,6 +154,10 @@ static cl::opt<bool> EnableMemProfiler("enable-mem-prof", cl::init(false),
153154
cl::Hidden, cl::ZeroOrMore,
154155
cl::desc("Enable memory profiler"));
155156

157+
static cl::opt<bool> EnableModuleInliner("enable-module-inliner",
158+
cl::init(false), cl::Hidden,
159+
cl::desc("Enable module inliner"));
160+
156161
static cl::opt<bool> PerformMandatoryInliningsFirst(
157162
"mandatory-inlining-first", cl::init(true), cl::Hidden, cl::ZeroOrMore,
158163
cl::desc("Perform mandatory inlinings module-wide, before performing "
@@ -738,6 +743,28 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level,
738743
return MIWP;
739744
}
740745

746+
ModuleInlinerPass
747+
PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level,
748+
ThinOrFullLTOPhase Phase) {
749+
InlineParams IP = getInlineParamsFromOptLevel(Level);
750+
if (Phase == ThinOrFullLTOPhase::ThinLTOPreLink && PGOOpt &&
751+
PGOOpt->Action == PGOOptions::SampleUse)
752+
IP.HotCallSiteThreshold = 0;
753+
754+
if (PGOOpt)
755+
IP.EnableDeferral = EnablePGOInlineDeferral;
756+
757+
// The inline deferral logic is used to avoid losing some
758+
// inlining chance in future. It is helpful in SCC inliner, in which
759+
// inlining is processed in bottom-up order.
760+
// While in module inliner, the inlining order is a priority-based order
761+
// by default. The inline deferral is unnecessary there. So we disable the
762+
// inline deferral logic in module inliner.
763+
IP.EnableDeferral = false;
764+
765+
return ModuleInlinerPass(IP, UseInlineAdvisor);
766+
}
767+
741768
ModulePassManager
742769
PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
743770
ThinOrFullLTOPhase Phase) {
@@ -896,7 +923,10 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
896923
if (EnableSyntheticCounts && !PGOOpt)
897924
MPM.addPass(SyntheticCountsPropagation());
898925

899-
MPM.addPass(buildInlinerPipeline(Level, Phase));
926+
if (EnableModuleInliner)
927+
MPM.addPass(buildModuleInlinerPipeline(Level, Phase));
928+
else
929+
MPM.addPass(buildInlinerPipeline(Level, Phase));
900930

901931
if (EnableMemProfiler && Phase != ThinOrFullLTOPhase::ThinLTOPreLink) {
902932
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ MODULE_PASS("verify", VerifierPass())
110110
MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass())
111111
MODULE_PASS("dfsan", DataFlowSanitizerPass())
112112
MODULE_PASS("msan-module", ModuleMemorySanitizerPass({}))
113+
MODULE_PASS("module-inline", ModuleInlinerPass())
113114
MODULE_PASS("tsan-module", ModuleThreadSanitizerPass())
114115
MODULE_PASS("sancov-module", ModuleSanitizerCoveragePass())
115116
MODULE_PASS("memprof-module", ModuleMemProfilerPass())

llvm/lib/Transforms/IPO/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ add_llvm_component_library(LLVMipo
2929
LoopExtractor.cpp
3030
LowerTypeTests.cpp
3131
MergeFunctions.cpp
32+
ModuleInliner.cpp
3233
OpenMPOpt.cpp
3334
PartialInlining.cpp
3435
PassManagerBuilder.cpp

0 commit comments

Comments
 (0)