diff --git a/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h new file mode 100644 index 0000000000000..66311ecfe3174 --- /dev/null +++ b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h @@ -0,0 +1,35 @@ +//===- EvolutionInlineAdvisor.h - LLM+Evolutionary Algorithm-based InlineAdvisor +//---*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_EVOLUTIONINLINEADVISOR_H +#define LLVM_ANALYSIS_EVOLUTIONINLINEADVISOR_H + +#include "llvm/Analysis/FunctionPropertiesAnalysis.h" +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/PassManager.h" + +#include + +namespace llvm { + +class EvolutionInlineAdvisor : public InlineAdvisor { +public: + EvolutionInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, + InlineContext IC) + : InlineAdvisor(M, FAM, IC) {} + +private: + std::unique_ptr getAdviceImpl(CallBase &CB) override; + std::unique_ptr getEvolvableAdvice(CallBase &CB); +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_EVOLUTIONINLINEADVISOR_H \ No newline at end of file diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h index 50ba3c13da70f..b0380635b920d 100644 --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -40,7 +40,12 @@ struct ReplayInlinerSettings; /// also permits generating training logs, for offline training. /// /// - Dynamically load an advisor via a plugin (PluginInlineAdvisorAnalysis) -enum class InliningAdvisorMode : int { Default, Release, Development }; +enum class InliningAdvisorMode : int { + Default, + Release, + Development, + Evolution +}; // Each entry represents an inline driver. enum class InlinePass : int { diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 16dd6f8b86006..46a31af4725da 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -74,6 +74,7 @@ add_llvm_component_library(LLVMAnalysis DXILResource.cpp DXILMetadataAnalysis.cpp EphemeralValuesCache.cpp + EvolutionInlineAdvisor.cpp FloatingPointPredicateUtils.cpp FunctionPropertiesAnalysis.cpp GlobalsModRef.cpp diff --git a/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp b/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp new file mode 100644 index 0000000000000..57d8a41b4e4c4 --- /dev/null +++ b/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp @@ -0,0 +1,64 @@ +//===- EvolutionInlineAdvisor.cpp - skeleton implementation ------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements EvolutionInlineAdvisor. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/EvolutionInlineAdvisor.h" +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +// EVOLVE-BLOCK-START +// You can include additional LLVM headers here. + +std::unique_ptr +EvolutionInlineAdvisor::getEvolvableAdvice(CallBase &CB) { + // Implementation of inlining strategy. Do not change the function interface. + bool IsInliningRecommended = false; + return std::make_unique( + this, CB, + FAM.getResult(*CB.getCaller()), + IsInliningRecommended); +} + +// EVOLVE-BLOCK-END + +std::unique_ptr +EvolutionInlineAdvisor::getAdviceImpl(CallBase &CB) { + // TODO: refactor the legality check to make them common with + // MLInlineAdvisor::getAdviceImpl + auto &Caller = *CB.getCaller(); + auto &Callee = *CB.getCalledFunction(); + auto &ORE = FAM.getResult(Caller); + + auto MandatoryKind = InlineAdvisor::getMandatoryKind(CB, FAM, ORE); + // If this is a "never inline" case, there won't be any changes to internal + // state we need to track, so we can just return the base InlineAdvice, which + // will do nothing interesting. + // Same thing if this is a recursive case. + if (MandatoryKind == InlineAdvisor::MandatoryInliningKind::Never || + &Caller == &Callee) + return getMandatoryAdvice(CB, false); + + auto IsViable = isInlineViable(Callee); + if (!IsViable.isSuccess()) + return std::make_unique(this, CB, ORE, false); + + bool Mandatory = + MandatoryKind == InlineAdvisor::MandatoryInliningKind::Always; + + if (Mandatory) + return std::make_unique(this, CB, ORE, true); + + return getEvolvableAdvice(CB); +} diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index 0fa804f2959e8..858e7e5ac5429 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/EphemeralValuesCache.h" +#include "llvm/Analysis/EvolutionInlineAdvisor.h" #include "llvm/Analysis/IR2Vec.h" #include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" @@ -270,6 +271,10 @@ bool InlineAdvisorAnalysis::Result::tryCreate( return false; Advisor = llvm::getReleaseModeAdvisor(M, MAM, GetDefaultAdvice); break; + case InliningAdvisorMode::Evolution: + LLVM_DEBUG(dbgs() << "Using evolution-mode inliner policy.\n"); + Advisor.reset(new EvolutionInlineAdvisor(M, FAM, IC)); + break; } return !!Advisor; diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index bd03ac090721c..51f26e219f3fd 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -160,7 +160,9 @@ static cl::opt UseInlineAdvisor( clEnumValN(InliningAdvisorMode::Development, "development", "Use development mode (runtime-loadable model)"), clEnumValN(InliningAdvisorMode::Release, "release", - "Use release mode (AOT-compiled model)"))); + "Use release mode (AOT-compiled model)"), + clEnumValN(InliningAdvisorMode::Evolution, "evolution", + "Use evolution mode (AlphaEvolve-like framework)"))); /// Flag to enable inline deferral during PGO. static cl::opt diff --git a/llvm/test/Transforms/Inline/ML/default-evolution.ll b/llvm/test/Transforms/Inline/ML/default-evolution.ll new file mode 100644 index 0000000000000..2761f07b8e219 --- /dev/null +++ b/llvm/test/Transforms/Inline/ML/default-evolution.ll @@ -0,0 +1,26 @@ +; RUN: opt -passes='default' \ +; RUN: -S -enable-ml-inliner=evolution < %s 2>&1 | FileCheck %s +; RUN: opt -passes='default' \ +; RUN: -S -enable-ml-inliner=default < %s 2>&1 | FileCheck %s + +declare i32 @f1() + +define i32 @f2() { + ret i32 1 +} + +define i32 @f3() { + %a = call i32 @f1() + %b = call i32 @f2() + %c = add i32 %a, %b + ret i32 %c +} + +; all the functions are not inlined by default +; CHECK-LABEL: @f1 +; CHECK-LABEL: @f2 +; CHECK-LABEL: @f3 +; default inlining policy may inline @f2 +; CHECK-LABEL: @f1 +; CHECK-NOT-LABEL: @f2 +; CHECK-LABEL: @f3 \ No newline at end of file diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn index ab25c263095fa..6cb46067d7c8c 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn @@ -53,6 +53,7 @@ static_library("Analysis") { "DomTreeUpdater.cpp", "DominanceFrontier.cpp", "EphemeralValuesCache.cpp", + "EvolutionInlineAdvisor.cpp", "FloatingPointPredicateUtils.cpp", "FunctionPropertiesAnalysis.cpp", "GlobalsModRef.cpp",