diff --git a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h --- a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h +++ b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @@ -111,7 +111,7 @@ public: FunctionPropertiesUpdater(FunctionPropertiesInfo &FPI, const CallBase &CB); - void finish(const LoopInfo &LI); + void finish(const LoopInfo &LI) const; private: FunctionPropertiesInfo &FPI; diff --git a/llvm/include/llvm/Analysis/MLInlineAdvisor.h b/llvm/include/llvm/Analysis/MLInlineAdvisor.h --- a/llvm/include/llvm/Analysis/MLInlineAdvisor.h +++ b/llvm/include/llvm/Analysis/MLInlineAdvisor.h @@ -44,7 +44,6 @@ int64_t getLocalCalls(Function &F); const MLModelRunner &getModelRunner() const { return *ModelRunner.get(); } FunctionPropertiesInfo &getCachedFPI(Function &) const; - const LoopInfo &getLoopInfo(Function &F) const; protected: std::unique_ptr getAdviceImpl(CallBase &CB) override; @@ -67,10 +66,7 @@ private: int64_t getModuleIRSize() const; - void print(raw_ostream &OS) const override { - OS << "[MLInlineAdvisor] Nodes: " << NodeCount << " Edges: " << EdgeCount - << "\n"; - } + void print(raw_ostream &OS) const override; mutable DenseMap FPICache; @@ -107,10 +103,10 @@ const int64_t CallerIRSize; const int64_t CalleeIRSize; const int64_t CallerAndCalleeEdges; + void updateCachedCallerFPI(const LoopInfo &LI) const; private: void reportContextForRemark(DiagnosticInfoOptimizationBase &OR); - void updateCachedCallerFPI(); MLInlineAdvisor *getAdvisor() const { return static_cast(Advisor); }; diff --git a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp --- a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp +++ b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp @@ -153,7 +153,7 @@ FPI.updateForBB(*BB, -1); } -void FunctionPropertiesUpdater::finish(const LoopInfo &LI) { +void FunctionPropertiesUpdater::finish(const LoopInfo &LI) const { DenseSet ReIncluded; std::deque Worklist; diff --git a/llvm/lib/Analysis/MLInlineAdvisor.cpp b/llvm/lib/Analysis/MLInlineAdvisor.cpp --- a/llvm/lib/Analysis/MLInlineAdvisor.cpp +++ b/llvm/lib/Analysis/MLInlineAdvisor.cpp @@ -51,6 +51,12 @@ "blocking any further inlining."), cl::init(2.0)); +static cl::opt KeepFPICache( + "ml-advisor-keep-fpi-cache", cl::Hidden, + cl::desc( + "For test - keep the ML Inline advisor's FunctionPropertiesInfo cache"), + cl::init(false)); + // clang-format off const std::array llvm::FeatureMap{ #define POPULATE_NAMES(_, NAME) TensorSpec::createSpec(NAME, {1} ), @@ -175,7 +181,8 @@ void MLInlineAdvisor::onPassExit(LazyCallGraph::SCC *LastSCC) { // No need to keep this around - function passes will invalidate it. - FPICache.clear(); + if (!KeepFPICache) + FPICache.clear(); if (!LastSCC || ForceStop) return; // Keep track of the nodes and edges we last saw. Then, in onPassEntry, @@ -206,13 +213,12 @@ assert(!ForceStop); Function *Caller = Advice.getCaller(); Function *Callee = Advice.getCallee(); - // The caller features aren't valid anymore. { - PreservedAnalyses PA = PreservedAnalyses::all(); - PA.abandon(); + PreservedAnalyses PA = PreservedAnalyses::none(); FAM.invalidate(*Caller, PA); } + Advice.updateCachedCallerFPI(FAM.getResult(*Caller)); int64_t IRSizeAfter = getIRSize(*Caller) + (CalleeWasDeleted ? 0 : Advice.CalleeIRSize); CurrentIRSize += IRSizeAfter - (Advice.CallerIRSize + Advice.CalleeIRSize); @@ -366,15 +372,23 @@ return std::make_unique(this, CB, getCallerORE(CB), Advice); } -const LoopInfo &MLInlineAdvisor::getLoopInfo(Function &F) const { - return FAM.getResult(F); -} - std::unique_ptr MLInlineAdvisor::getMandatoryAdviceImpl(CallBase &CB) { return std::make_unique(this, CB, getCallerORE(CB), true); } +void MLInlineAdvisor::print(raw_ostream &OS) const { + OS << "[MLInlineAdvisor] Nodes: " << NodeCount << " Edges: " << EdgeCount + << "\n"; + OS << "[MLInlineAdvisor] FPI:\n"; + for (auto I : FPICache) { + OS << I.getFirst()->getName() << ":\n"; + I.getSecond().print(OS); + OS << "\n"; + } + OS << "\n"; +} + MLInlineAdvice::MLInlineAdvice(MLInlineAdvisor *Advisor, CallBase &CB, OptimizationRemarkEmitter &ORE, bool Recommendation) @@ -400,12 +414,11 @@ OR << NV("ShouldInline", isInliningRecommended()); } -void MLInlineAdvice::updateCachedCallerFPI() { - FPU->finish(getAdvisor()->getLoopInfo(*Caller)); +void MLInlineAdvice::updateCachedCallerFPI(const LoopInfo &LI) const { + FPU->finish(LI); } void MLInlineAdvice::recordInliningImpl() { - updateCachedCallerFPI(); ORE.emit([&]() { OptimizationRemark R(DEBUG_TYPE, "InliningSuccess", DLoc, Block); reportContextForRemark(R); @@ -415,7 +428,6 @@ } void MLInlineAdvice::recordInliningWithCalleeDeletedImpl() { - updateCachedCallerFPI(); ORE.emit([&]() { OptimizationRemark R(DEBUG_TYPE, "InliningSuccessWithCalleeDeleted", DLoc, Block); diff --git a/llvm/test/Transforms/Inline/ML/fpi-update.ll b/llvm/test/Transforms/Inline/ML/fpi-update.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Inline/ML/fpi-update.ll @@ -0,0 +1,32 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-grtev4-linux-gnu" + +; TODO: we could instantiate the MLInliner with a non-model generated evaluator +; and drop the requirement +; REQUIRES: llvm_inliner_model_autogenerated + +; RUN: opt -enable-ml-inliner=release -passes='scc-oz-module-inliner,print' \ +; RUN: -keep-inline-advisor-for-printing -max-devirt-iterations=0 \ +; RUN: -mandatory-inlining-first=0 -S < %s 2>&1 | FileCheck %s + +define void @caller(i32 %i) #1 { + call void @callee(i32 %i) + ret void +} + +define void @callee(i32 %i) #0 { +entry: + br label %loop +loop: + %cond = icmp slt i32 %i, 0 + br i1 %cond, label %loop, label %exit +exit: + ret void +} + +attributes #0 = { alwaysinline } +attributes #1 = { noinline optnone } + +; CHECK: [MLInlineAdvisor] FPI: +; CHECK: caller: +; CHECK: MaxLoopDepth: 1