[llvm] [MLGO] Add EvolutionInlineAdvisor (PR #166386)

Hongzheng Chen via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 4 10:52:39 PST 2025


https://github.com/chhzh123 updated https://github.com/llvm/llvm-project/pull/166386

>From e9ba1fef1e2a010844eec2d295a6d70ce10c7e57 Mon Sep 17 00:00:00 2001
From: chhzh123 <hc676 at cornell.edu>
Date: Tue, 4 Nov 2025 15:35:30 +0000
Subject: [PATCH 1/4] Add EvolutionInlineAdvisor

---
 .../llvm/Analysis/EvolutionInlineAdvisor.h    | 35 ++++++++++
 llvm/include/llvm/Analysis/InlineAdvisor.h    |  7 +-
 llvm/lib/Analysis/CMakeLists.txt              |  1 +
 llvm/lib/Analysis/EvolutionInlineAdvisor.cpp  | 64 +++++++++++++++++++
 llvm/lib/Analysis/InlineAdvisor.cpp           |  5 ++
 llvm/lib/Passes/PassBuilderPipelines.cpp      |  4 +-
 .../Transforms/Inline/ML/default-evolution.ll | 20 ++++++
 .../gn/secondary/llvm/lib/Analysis/BUILD.gn   |  1 +
 8 files changed, 135 insertions(+), 2 deletions(-)
 create mode 100644 llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
 create mode 100644 llvm/lib/Analysis/EvolutionInlineAdvisor.cpp
 create mode 100644 llvm/test/Transforms/Inline/ML/default-evolution.ll

diff --git a/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
new file mode 100644
index 0000000000000..9c797e4ec1ca3
--- /dev/null
+++ b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
@@ -0,0 +1,35 @@
+//===- EvolutionInlineAdvisor.h - LLM+Evolution-based InlineAdvisor factories
+//---*- 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 <memory>
+
+namespace llvm {
+
+class EvolutionInlineAdvisor : public InlineAdvisor {
+public:
+  EvolutionInlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
+                         InlineContext IC)
+      : InlineAdvisor(M, FAM, IC) {}
+
+private:
+  std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) override;
+  std::unique_ptr<InlineAdvice> getEvolutionAdviceImpl(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..b99134b42fef9
--- /dev/null
+++ b/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp
@@ -0,0 +1,64 @@
+//-------------------===//
+//
+// 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<InlineAdvice>
+EvolutionInlineAdvisor::getEvolutionAdviceImpl(CallBase &CB) {
+  // Implementation of inlining strategy. Do not change the function interface.
+  bool IsInliningRecommended = false;
+  return std::make_unique<InlineAdvice>(
+      this, CB,
+      FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller()),
+      IsInliningRecommended);
+}
+
+// EVOLVE-BLOCK-END
+
+std::unique_ptr<InlineAdvice>
+EvolutionInlineAdvisor::getAdviceImpl(CallBase &CB) {
+  // legality check
+  // reference: MLInlineAdvisor::getAdviceImpl
+  auto &Caller = *CB.getCaller();
+  auto &Callee = *CB.getCalledFunction();
+  auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(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<InlineAdvice>(this, CB, ORE, false);
+
+  bool Mandatory =
+      MandatoryKind == InlineAdvisor::MandatoryInliningKind::Always;
+
+  if (Mandatory)
+    return std::make_unique<InlineAdvice>(this, CB, ORE, true);
+
+  return getEvolutionAdviceImpl(CB);
+}
diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp
index 0fa804f2959e8..48053161ff32e 100644
--- a/llvm/lib/Analysis/InlineAdvisor.cpp
+++ b/llvm/lib/Analysis/InlineAdvisor.cpp
@@ -14,6 +14,7 @@
 #include "llvm/Analysis/InlineAdvisor.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/EvolutionInlineAdvisor.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/EphemeralValuesCache.h"
 #include "llvm/Analysis/IR2Vec.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<InliningAdvisorMode> 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<bool>
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..81d16deeebbaf
--- /dev/null
+++ b/llvm/test/Transforms/Inline/ML/default-evolution.ll
@@ -0,0 +1,20 @@
+; RUN: opt -passes='default<O3>' \
+; RUN:   -S -enable-ml-inliner=evolution < %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
\ 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",

>From 6c6045547222217e0332dc3d5a46de10804537a9 Mon Sep 17 00:00:00 2001
From: chhzh123 <hc676 at cornell.edu>
Date: Tue, 4 Nov 2025 15:47:48 +0000
Subject: [PATCH 2/4] Fix format

---
 llvm/lib/Analysis/InlineAdvisor.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp
index 48053161ff32e..858e7e5ac5429 100644
--- a/llvm/lib/Analysis/InlineAdvisor.cpp
+++ b/llvm/lib/Analysis/InlineAdvisor.cpp
@@ -14,9 +14,9 @@
 #include "llvm/Analysis/InlineAdvisor.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
-#include "llvm/Analysis/EvolutionInlineAdvisor.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"

>From 3e162dd6ba2a1dc0706dfd28d5a9a27ed3778ff4 Mon Sep 17 00:00:00 2001
From: chhzh123 <hc676 at cornell.edu>
Date: Tue, 4 Nov 2025 15:53:52 +0000
Subject: [PATCH 3/4] Fix macro

---
 llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
index 9c797e4ec1ca3..a8fb1877a757c 100644
--- a/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
+++ b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
@@ -1,4 +1,4 @@
-//===- EvolutionInlineAdvisor.h - LLM+Evolution-based InlineAdvisor factories
+//===- EvolutionInlineAdvisor.h - LLM+Evolutionary Algorithm-based InlineAdvisor
 //---*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_ANALYSIS_EvolutionInlineAdvisor_H
-#define LLVM_ANALYSIS_EvolutionInlineAdvisor_H
+#ifndef LLVM_ANALYSIS_EVOLUTIONINLINEADVISOR_H
+#define LLVM_ANALYSIS_EVOLUTIONINLINEADVISOR_H
 
 #include "llvm/Analysis/FunctionPropertiesAnalysis.h"
 #include "llvm/Analysis/InlineAdvisor.h"
@@ -32,4 +32,4 @@ class EvolutionInlineAdvisor : public InlineAdvisor {
 
 } // namespace llvm
 
-#endif // LLVM_ANALYSIS_EvolutionInlineAdvisor_H
\ No newline at end of file
+#endif // LLVM_ANALYSIS_EVOLUTIONINLINEADVISOR_H
\ No newline at end of file

>From 360aa608d00f44c59051575d8f986407a7e63ee6 Mon Sep 17 00:00:00 2001
From: chhzh123 <hc676 at cornell.edu>
Date: Tue, 4 Nov 2025 18:52:18 +0000
Subject: [PATCH 4/4] fix

---
 llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h |  2 +-
 llvm/lib/Analysis/EvolutionInlineAdvisor.cpp        | 10 +++++-----
 llvm/test/Transforms/Inline/ML/default-evolution.ll |  6 ++++++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
index a8fb1877a757c..66311ecfe3174 100644
--- a/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
+++ b/llvm/include/llvm/Analysis/EvolutionInlineAdvisor.h
@@ -27,7 +27,7 @@ class EvolutionInlineAdvisor : public InlineAdvisor {
 
 private:
   std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) override;
-  std::unique_ptr<InlineAdvice> getEvolutionAdviceImpl(CallBase &CB);
+  std::unique_ptr<InlineAdvice> getEvolvableAdvice(CallBase &CB);
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp b/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp
index b99134b42fef9..57d8a41b4e4c4 100644
--- a/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp
+++ b/llvm/lib/Analysis/EvolutionInlineAdvisor.cpp
@@ -1,4 +1,4 @@
-//-------------------===//
+//===- 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.
@@ -22,7 +22,7 @@ using namespace llvm;
 // You can include additional LLVM headers here.
 
 std::unique_ptr<InlineAdvice>
-EvolutionInlineAdvisor::getEvolutionAdviceImpl(CallBase &CB) {
+EvolutionInlineAdvisor::getEvolvableAdvice(CallBase &CB) {
   // Implementation of inlining strategy. Do not change the function interface.
   bool IsInliningRecommended = false;
   return std::make_unique<InlineAdvice>(
@@ -35,8 +35,8 @@ EvolutionInlineAdvisor::getEvolutionAdviceImpl(CallBase &CB) {
 
 std::unique_ptr<InlineAdvice>
 EvolutionInlineAdvisor::getAdviceImpl(CallBase &CB) {
-  // legality check
-  // reference: MLInlineAdvisor::getAdviceImpl
+  // TODO: refactor the legality check to make them common with
+  // MLInlineAdvisor::getAdviceImpl
   auto &Caller = *CB.getCaller();
   auto &Callee = *CB.getCalledFunction();
   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
@@ -60,5 +60,5 @@ EvolutionInlineAdvisor::getAdviceImpl(CallBase &CB) {
   if (Mandatory)
     return std::make_unique<InlineAdvice>(this, CB, ORE, true);
 
-  return getEvolutionAdviceImpl(CB);
+  return getEvolvableAdvice(CB);
 }
diff --git a/llvm/test/Transforms/Inline/ML/default-evolution.ll b/llvm/test/Transforms/Inline/ML/default-evolution.ll
index 81d16deeebbaf..2761f07b8e219 100644
--- a/llvm/test/Transforms/Inline/ML/default-evolution.ll
+++ b/llvm/test/Transforms/Inline/ML/default-evolution.ll
@@ -1,5 +1,7 @@
 ; RUN: opt -passes='default<O3>' \
 ; RUN:   -S -enable-ml-inliner=evolution < %s 2>&1 | FileCheck %s
+; RUN: opt -passes='default<O3>' \
+; RUN:   -S -enable-ml-inliner=default < %s 2>&1 | FileCheck %s
 
 declare i32 @f1()
 
@@ -17,4 +19,8 @@ define i32 @f3() {
 ; 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



More information about the llvm-commits mailing list