Skip to content

Commit

Permalink
[NPM][Inliner] Factor ImportedFunctionStats in the InlineAdvisor
Browse files Browse the repository at this point in the history
When using 2 InlinePass instances in the same CGSCC - one for other
mandatory inlinings, the other for the heuristic-driven ones - the order
in which the ImportedFunctionStats would be output-ed would depend on
the destruction order of the inline passes, which is not deterministic.

This patch moves the ImportedFunctionStats responsibility to the
InlineAdvisor to address this problem.

Differential Revision: https://reviews.llvm.org/D94982
  • Loading branch information
mtrofin committed Jan 20, 2021
1 parent a512260 commit e8aec76
Show file tree
Hide file tree
Showing 12 changed files with 77 additions and 56 deletions.
18 changes: 10 additions & 8 deletions llvm/include/llvm/Analysis/InlineAdvisor.h
Expand Up @@ -12,6 +12,7 @@
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h"
#include <memory>
#include <unordered_set>

Expand Down Expand Up @@ -65,10 +66,7 @@ class InlineAdvice {
/// behavior by implementing the corresponding record*Impl.
///
/// Call after inlining succeeded, and did not result in deleting the callee.
void recordInlining() {
markRecorded();
recordInliningImpl();
}
void recordInlining();

/// Call after inlining succeeded, and resulted in deleting the callee.
void recordInliningWithCalleeDeleted();
Expand Down Expand Up @@ -114,6 +112,7 @@ class InlineAdvice {
assert(!Recorded && "Recording should happen exactly once");
Recorded = true;
}
void recordInlineStatsIfNeeded();

bool Recorded = false;
};
Expand Down Expand Up @@ -141,7 +140,7 @@ class DefaultInlineAdvice : public InlineAdvice {
class InlineAdvisor {
public:
InlineAdvisor(InlineAdvisor &&) = delete;
virtual ~InlineAdvisor() { freeDeletedFunctions(); }
virtual ~InlineAdvisor();

/// Get an InlineAdvice containing a recommendation on whether to
/// inline or not. \p CB is assumed to be a direct call. \p FAM is assumed to
Expand All @@ -163,12 +162,14 @@ class InlineAdvisor {
virtual void onPassExit() {}

protected:
InlineAdvisor(FunctionAnalysisManager &FAM) : FAM(FAM) {}
InlineAdvisor(Module &M, FunctionAnalysisManager &FAM);
virtual std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) = 0;
virtual std::unique_ptr<InlineAdvice> getMandatoryAdvice(CallBase &CB,
bool Advice);

Module &M;
FunctionAnalysisManager &FAM;
std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats;

/// We may want to defer deleting functions to after the inlining for a whole
/// module has finished. This allows us to reliably use function pointers as
Expand Down Expand Up @@ -202,8 +203,9 @@ class InlineAdvisor {
/// reusable as-is for inliner pass test scenarios, as well as for regular use.
class DefaultInlineAdvisor : public InlineAdvisor {
public:
DefaultInlineAdvisor(FunctionAnalysisManager &FAM, InlineParams Params)
: InlineAdvisor(FAM), Params(Params) {}
DefaultInlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
InlineParams Params)
: InlineAdvisor(M, FAM), Params(Params) {}

private:
std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) override;
Expand Down
1 change: 0 additions & 1 deletion llvm/include/llvm/Analysis/MLInlineAdvisor.h
Expand Up @@ -50,7 +50,6 @@ class MLInlineAdvisor : public InlineAdvisor {
virtual std::unique_ptr<MLInlineAdvice>
getAdviceFromModel(CallBase &CB, OptimizationRemarkEmitter &ORE);

Module &M;
std::unique_ptr<MLModelRunner> ModelRunner;

private:
Expand Down
5 changes: 3 additions & 2 deletions llvm/include/llvm/Analysis/ReplayInlineAdvisor.h
Expand Up @@ -24,8 +24,9 @@ class OptimizationRemarkEmitter;
/// previous build to guide current inlining. This is useful for inliner tuning.
class ReplayInlineAdvisor : public InlineAdvisor {
public:
ReplayInlineAdvisor(FunctionAnalysisManager &FAM, LLVMContext &Context,
StringRef RemarksFile, bool EmitRemarks);
ReplayInlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
LLVMContext &Context, StringRef RemarksFile,
bool EmitRemarks);
std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) override;
bool areReplayRemarksLoaded() const { return HasReplayRemarks; }

Expand Down
2 changes: 0 additions & 2 deletions llvm/include/llvm/Transforms/IPO/Inliner.h
Expand Up @@ -97,7 +97,6 @@ struct LegacyInlinerBase : public CallGraphSCCPass {
class InlinerPass : public PassInfoMixin<InlinerPass> {
public:
InlinerPass(bool OnlyMandatory = false) : OnlyMandatory(OnlyMandatory) {}
~InlinerPass();
InlinerPass(InlinerPass &&Arg) = default;

PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
Expand All @@ -106,7 +105,6 @@ class InlinerPass : public PassInfoMixin<InlinerPass> {
private:
InlineAdvisor &getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM,
FunctionAnalysisManager &FAM, Module &M);
std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats;
std::unique_ptr<DefaultInlineAdvisor> OwnedDefaultAdvisor;
const bool OnlyMandatory;
};
Expand Down
Expand Up @@ -101,6 +101,12 @@ class ImportedFunctionsInliningStatistics {
StringRef ModuleName;
};

enum class InlinerFunctionImportStatsOpts {
No = 0,
Basic = 1,
Verbose = 2,
};

} // llvm

#endif // LLVM_TRANSFORMS_UTILS_IMPORTEDFUNCTIONSINLININGSTATISTICS_H
35 changes: 34 additions & 1 deletion llvm/lib/Analysis/InlineAdvisor.cpp
Expand Up @@ -48,6 +48,8 @@ static cl::opt<int>
cl::desc("Scale to limit the cost of inline deferral"),
cl::init(2), cl::Hidden);

extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;

void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
const InlineResult &Result) {
using namespace ore;
Expand Down Expand Up @@ -130,8 +132,20 @@ void InlineAdvisor::freeDeletedFunctions() {
DeletedFunctions.clear();
}

void InlineAdvice::recordInlineStatsIfNeeded() {
if (Advisor->ImportedFunctionsStats)
Advisor->ImportedFunctionsStats->recordInline(*Caller, *Callee);
}

void InlineAdvice::recordInlining() {
markRecorded();
recordInlineStatsIfNeeded();
recordInliningImpl();
}

void InlineAdvice::recordInliningWithCalleeDeleted() {
markRecorded();
recordInlineStatsIfNeeded();
Advisor->markFunctionAsDeleted(Callee);
recordInliningWithCalleeDeletedImpl();
}
Expand All @@ -143,7 +157,7 @@ bool InlineAdvisorAnalysis::Result::tryCreate(InlineParams Params,
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
switch (Mode) {
case InliningAdvisorMode::Default:
Advisor.reset(new DefaultInlineAdvisor(FAM, Params));
Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params));
break;
case InliningAdvisorMode::Development:
#ifdef LLVM_HAVE_TF_API
Expand Down Expand Up @@ -428,6 +442,25 @@ void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
});
}

InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM)
: M(M), FAM(FAM) {
if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
ImportedFunctionsStats =
std::make_unique<ImportedFunctionsInliningStatistics>();
ImportedFunctionsStats->setModuleInfo(M);
}
}

InlineAdvisor::~InlineAdvisor() {
if (ImportedFunctionsStats) {
assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No);
ImportedFunctionsStats->dump(InlinerFunctionImportStats ==
InlinerFunctionImportStatsOpts::Verbose);
}

freeDeletedFunctions();
}

std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB,
bool Advice) {
return std::make_unique<InlineAdvice>(this, CB, getCallerORE(CB), Advice);
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Analysis/MLInlineAdvisor.cpp
Expand Up @@ -66,8 +66,8 @@ CallBase *getInlinableCS(Instruction &I) {
MLInlineAdvisor::MLInlineAdvisor(Module &M, ModuleAnalysisManager &MAM,
std::unique_ptr<MLModelRunner> Runner)
: InlineAdvisor(
MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager()),
M(M), ModelRunner(std::move(Runner)), CG(new CallGraph(M)),
M, MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager()),
ModelRunner(std::move(Runner)), CG(new CallGraph(M)),
InitialIRSize(getModuleIRSize()), CurrentIRSize(InitialIRSize) {
assert(ModelRunner);

Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Analysis/ReplayInlineAdvisor.cpp
Expand Up @@ -22,11 +22,12 @@ using namespace llvm;

#define DEBUG_TYPE "inline-replay"

ReplayInlineAdvisor::ReplayInlineAdvisor(FunctionAnalysisManager &FAM,
ReplayInlineAdvisor::ReplayInlineAdvisor(Module &M,
FunctionAnalysisManager &FAM,
LLVMContext &Context,
StringRef RemarksFile,
bool EmitRemarks)
: InlineAdvisor(FAM), HasReplayRemarks(false), EmitRemarks(EmitRemarks) {
: InlineAdvisor(M, FAM), HasReplayRemarks(false), EmitRemarks(EmitRemarks) {
auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile);
std::error_code EC = BufferOrErr.getError();
if (EC) {
Expand Down
42 changes: 5 additions & 37 deletions llvm/lib/Transforms/IPO/Inliner.cpp
Expand Up @@ -90,24 +90,7 @@ static cl::opt<bool>
DisableInlinedAllocaMerging("disable-inlined-alloca-merging",
cl::init(false), cl::Hidden);

namespace {

enum class InlinerFunctionImportStatsOpts {
No = 0,
Basic = 1,
Verbose = 2,
};

} // end anonymous namespace

static cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats(
"inliner-function-import-stats",
cl::init(InlinerFunctionImportStatsOpts::No),
cl::values(clEnumValN(InlinerFunctionImportStatsOpts::Basic, "basic",
"basic statistics"),
clEnumValN(InlinerFunctionImportStatsOpts::Verbose, "verbose",
"printing of statistics for each inlined function")),
cl::Hidden, cl::desc("Enable inliner stats for imported functions"));
extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;

LegacyInlinerBase::LegacyInlinerBase(char &ID) : CallGraphSCCPass(ID) {}

Expand Down Expand Up @@ -647,17 +630,12 @@ bool LegacyInlinerBase::removeDeadFunctions(CallGraph &CG,
return true;
}

InlinerPass::~InlinerPass() {
if (ImportedFunctionsStats) {
assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No);
ImportedFunctionsStats->dump(InlinerFunctionImportStats ==
InlinerFunctionImportStatsOpts::Verbose);
}
}

InlineAdvisor &
InlinerPass::getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM,
FunctionAnalysisManager &FAM, Module &M) {
if (OwnedDefaultAdvisor)
return *OwnedDefaultAdvisor;

auto *IAA = MAM.getCachedResult<InlineAdvisorAnalysis>(M);
if (!IAA) {
// It should still be possible to run the inliner as a stand-alone SCC pass,
Expand All @@ -669,7 +647,7 @@ InlinerPass::getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM,
// The one we would get from the MAM can be invalidated as a result of the
// inliner's activity.
OwnedDefaultAdvisor =
std::make_unique<DefaultInlineAdvisor>(FAM, getInlineParams());
std::make_unique<DefaultInlineAdvisor>(M, FAM, getInlineParams());
return *OwnedDefaultAdvisor;
}
assert(IAA->getAdvisor() &&
Expand Down Expand Up @@ -698,13 +676,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,

auto AdvisorOnExit = make_scope_exit([&] { Advisor.onPassExit(); });

if (!ImportedFunctionsStats &&
InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
ImportedFunctionsStats =
std::make_unique<ImportedFunctionsInliningStatistics>();
ImportedFunctionsStats->setModuleInfo(M);
}

// We use a single common worklist for calls across the entire SCC. We
// process these in-order and append new calls introduced during inlining to
// the end.
Expand Down Expand Up @@ -879,9 +850,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
}
}

if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No)
ImportedFunctionsStats->recordInline(F, Callee);

// Merge the attributes based on the inlining.
AttributeFuncs::mergeAttributesForInlining(F, Callee);

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/IPO/SampleProfile.cpp
Expand Up @@ -1962,7 +1962,7 @@ bool SampleProfileLoader::doInitialization(Module &M,

if (FAM && !ProfileInlineReplayFile.empty()) {
ExternalInlineAdvisor = std::make_unique<ReplayInlineAdvisor>(
*FAM, Ctx, ProfileInlineReplayFile, /*EmitRemarks=*/false);
M, *FAM, Ctx, ProfileInlineReplayFile, /*EmitRemarks=*/false);
if (!ExternalInlineAdvisor->areReplayRemarksLoaded())
ExternalInlineAdvisor.reset();
}
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Transforms/Utils/ImportedFunctionsInliningStatistics.cpp
Expand Up @@ -13,13 +13,23 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <iomanip>
#include <sstream>
using namespace llvm;

cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats(
"inliner-function-import-stats",
cl::init(InlinerFunctionImportStatsOpts::No),
cl::values(clEnumValN(InlinerFunctionImportStatsOpts::Basic, "basic",
"basic statistics"),
clEnumValN(InlinerFunctionImportStatsOpts::Verbose, "verbose",
"printing of statistics for each inlined function")),
cl::Hidden, cl::desc("Enable inliner stats for imported functions"));

ImportedFunctionsInliningStatistics::InlineGraphNode &
ImportedFunctionsInliningStatistics::createInlineGraphNode(const Function &F) {

Expand Down
3 changes: 3 additions & 0 deletions llvm/test/Transforms/Inline/inline_stats.ll
Expand Up @@ -9,6 +9,9 @@
; RUN: opt -S -passes=inliner-wrapper-no-mandatory-first -inliner-function-import-stats=basic < %s 2>&1 | FileCheck %s --check-prefixes=CHECK-BASIC,CHECK
; RUN: opt -S -passes=inliner-wrapper-no-mandatory-first -inliner-function-import-stats=verbose < %s 2>&1 | FileCheck %s --check-prefixes="CHECK-VERBOSE",CHECK

; RUN: opt -S -passes=inliner-wrapper -inliner-function-import-stats=basic < %s 2>&1 | FileCheck %s --check-prefixes=CHECK-BASIC,CHECK
; RUN: opt -S -passes=inliner-wrapper -inliner-function-import-stats=verbose < %s 2>&1 | FileCheck %s --check-prefixes=CHECK-VERBOSE,CHECK

; CHECK: ------- Dumping inliner stats for [<stdin>] -------
; CHECK-BASIC-NOT: -- List of inlined functions:
; CHECK-BASIC-NOT: -- Inlined not imported function
Expand Down

0 comments on commit e8aec76

Please sign in to comment.