[llvm] [PassBuilder] Add callback invoking to PassBuilder string API (PR #157153)

Gabriel Baraldi via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 5 11:00:33 PDT 2025


https://github.com/gbaraldi created https://github.com/llvm/llvm-project/pull/157153

This is a very rough state of what this can look like, but I didn't want to spend too much time on what could be a dead end. 

Currently the only way to invoke callbacks is by using the default pipelines, this is an issue if you want to define your own pipeline using the C string API (we do that in LLVM.jl in julia) so I extended the api to allow for invoking those callbacks just like one would call a pass of that kind.

There are some questions about the params that these callbacks take and also I'm missing some of them (some of them are also invoked by the backend so we may not want to expose them) 

>From cebd0a9a5341e51ffa7774e1960a8de385011a27 Mon Sep 17 00:00:00 2001
From: gbaraldi <baraldigabriel at gmail.com>
Date: Fri, 5 Sep 2025 14:55:28 -0300
Subject: [PATCH] Initial stage of callback invoking with PassBuilder

---
 .../llvm/Passes/TargetPassRegistry.inc        | 36 +++++++++++++++++++
 llvm/lib/Passes/PassRegistry.def              | 28 ++++++++++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Passes/TargetPassRegistry.inc b/llvm/include/llvm/Passes/TargetPassRegistry.inc
index 068b27794191c..2d76db006e4a1 100644
--- a/llvm/include/llvm/Passes/TargetPassRegistry.inc
+++ b/llvm/include/llvm/Passes/TargetPassRegistry.inc
@@ -133,6 +133,42 @@ PB.registerPipelineParsingCallback([=](StringRef Name, LoopPassManager &PM,
   return false;
 });
 
+PB.registerPipelineParsingCallback([=](StringRef Name, ModulePassManager &PM,
+                                       ArrayRef<PassBuilder::PipelineElement>) {
+#define MODULE_CALLBACK(NAME, INVOKE) if (Name == NAME) { PB.INVOKE(PM, OptimizationLevel::O2); return true; }
+#include GET_PASS_REGISTRY
+#undef MODULE_CALLBACK
+#define MODULE_LTO_CALLBACK(NAME, INVOKE) if (Name == NAME) { PB.INVOKE(PM, OptimizationLevel::O2, ThinOrFullLTOPhase::None); return true; }
+#include GET_PASS_REGISTRY
+#undef MODULE_LTO_CALLBACK
+  return false;
+});
+
+PB.registerPipelineParsingCallback([=](StringRef Name, FunctionPassManager &PM,
+                                       ArrayRef<PassBuilder::PipelineElement>) {
+#define FUNCTION_CALLBACK(NAME, INVOKE) if (Name == NAME) { PB.INVOKE(PM, OptimizationLevel::O2); return true; }
+#include GET_PASS_REGISTRY
+#undef FUNCTION_CALLBACK
+  return false;
+});
+
+
+PB.registerPipelineParsingCallback([=](StringRef Name, CGSCCPassManager &CGPM,
+                                       ArrayRef<PassBuilder::PipelineElement>) {
+#define CGSCC_CALLBACK(NAME, INVOKE) if (Name == NAME) { PB.INVOKE(CGPM, OptimizationLevel::O2); return true; }
+#include GET_PASS_REGISTRY
+#undef CGSCC_CALLBACK
+  return false;
+});
+PB.registerPipelineParsingCallback([=](StringRef Name, LoopPassManager &PM,
+                                       ArrayRef<PassBuilder::PipelineElement>) {
+#define LOOP_CALLBACK(NAME, INVOKE) if (Name == NAME) { PB.INVOKE(PM, OptimizationLevel::O2); return true; }
+#include GET_PASS_REGISTRY
+#undef LOOP_CALLBACK
+  return false;
+});
+
+
 PB.registerPipelineParsingCallback([=](StringRef Name,
                                        MachineFunctionPassManager &PM,
                                        ArrayRef<PassBuilder::PipelineElement>) {
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 299aaa801439b..dfa41d618643e 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -725,7 +725,6 @@ FUNCTION_PASS_WITH_PARAMS(
       return ExpandFpPass(TM, OL);
     },
     parseExpandFpOptions, "opt-level=N")
-    
 #undef FUNCTION_PASS_WITH_PARAMS
 
 #ifndef LOOPNEST_PASS
@@ -804,3 +803,30 @@ LOOP_PASS_WITH_PARAMS(
     },
     parseLoopUnswitchOptions, "nontrivial;no-nontrivial;trivial;no-trivial")
 #undef LOOP_PASS_WITH_PARAMS
+
+#ifdef MODULE_CALLBACK
+MODULE_CALLBACK("PipelineStartCallbacks", invokePipelineStartEPCallbacks)
+#endif
+
+// There are some full lto specific ones that are ignored here for now
+#ifdef MODULE_LTO_CALLBACK
+MODULE_LTO_CALLBACK("PipelineEarlySimplificationCallbacks", invokePipelineEarlySimplificationEPCallbacks)
+MODULE_LTO_CALLBACK("OptimizerEarlyCallbacks", invokeOptimizerEarlyEPCallbacks)
+MODULE_LTO_CALLBACK("OptimizerLastCallbacks", invokeOptimizerLastEPCallbacks)
+#endif
+
+#ifdef FUNCTION_CALLBACK
+FUNCTION_CALLBACK("PeepholeCallbacks", invokePeepholeEPCallbacks)
+FUNCTION_CALLBACK("ScalarOptimizerLateCallbacks", invokeScalarOptimizerLateEPCallbacks)
+FUNCTION_CALLBACK("VectorizerStartCallbacks", invokeVectorizerStartEPCallbacks)
+#endif
+
+#ifdef LOOP_CALLBACK
+LOOP_CALLBACK("LateLoopOptimizationsCallbacks", invokeLateLoopOptimizationsEPCallbacks)
+LOOP_CALLBACK("LoopOptimizerEndCallbacks", invokeLoopOptimizerEndEPCallbacks)
+#endif
+
+#ifdef CGSCC_CALLBACK
+CGSCC_CALLBACK("CGSCCOptimizerLateCallbacks", invokeCGSCCOptimizerLateEPCallbacks)
+#endif
+



More information about the llvm-commits mailing list