-
Notifications
You must be signed in to change notification settings - Fork 12k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang] Add codegen option to add passbuilder callback functions #70171
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: William Moses (wsmoses) ChangesAdding passbuilder callbacks presently can be done one of two ways:
This prevents the use of such functionality for static builds on build systems that cannot be modified, as well as prevents such functionality from being usable when using llvm/clang as a library. This creates a third mechanism for adding these callbacks, an explicit list of said callbacks. It's otherwise identical to the plugin approach, except now instead of the list of plugins each being queried for the callback function, this just runs the callback function. Full diff: https://github.com/llvm/llvm-project/pull/70171.diff 4 Files Affected:
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 70accce456d3c07..8dbe4d942df278d 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -909,6 +909,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
#define HANDLE_EXTENSION(Ext) \
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
#include "llvm/Support/Extension.def"
+ for (auto PassCallback : ListRegisterPassBuilderCallbacks) {
+ PassCallback(PB);
+ }
// Register the target library analysis directly and give it a customized
// preset TLI.
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 2c7ceda7998eda1..d018dd1e69166f0 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -739,6 +739,11 @@ bool parseAnalysisUtilityPasses(
return false;
}
+
+//! List of pass builder callbacks to be applied, in addition to those imported
+//! from plugins or LLVM extensions.
+extern SmallVector<std::function<void(PassBuilder &)>>
+ ListRegisterPassBuilderCallbacks;
}
#endif
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index ccc4276e36dacf0..28aabf8bdebb4d6 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -187,6 +187,9 @@ static void RegisterPassPlugins(ArrayRef<std::string> PassPlugins,
#define HANDLE_EXTENSION(Ext) \
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
#include "llvm/Support/Extension.def"
+ for (auto PassCallback : ListRegisterPassBuilderCallbacks) {
+ PassCallback(PB);
+ }
// Load requested pass plugins and let them register pass builder callbacks
for (auto &PluginFN : PassPlugins) {
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 6ae3f87099afd64..595bc4acddee6c4 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -431,6 +431,9 @@ bool llvm::runPassPipeline(
#define HANDLE_EXTENSION(Ext) \
get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
#include "llvm/Support/Extension.def"
+ for (auto PassCallback : ListRegisterPassBuilderCallbacks) {
+ PassCallback(PB);
+ }
// Specially handle the alias analysis manager so that we can register
// a custom pipeline of AA passes with it.
@@ -546,3 +549,6 @@ void llvm::printPasses(raw_ostream &OS) {
PassBuilder PB;
PB.printPassNames(OS);
}
+
+llvm::SmallVector<std::function<void(PassBuilder &)>>
+ ListRegisterPassBuilderCallbacks;
\ No newline at end of file
|
8b0e093
to
fca61de
Compare
Can you make an example on how this is used now? Is there a way to test this? |
I don't think a global variable is the right interface for this; we've been trying to move away from global variables because they cause breakage when LLVM is used in multiple contexts in the same process. Functions that construct pass pipelines that are usable as libraries can take an array of PassPluginLibraryInfo as an argument. |
Will add later today |
fca61de
to
ad9ed02
Compare
@jdoerfert added the example test @efriedma-quic I've reworked the mechanism to not create a global variable within LLVM. Here this only applies to clang and enables two things:
|
227a494
to
a49b8e2
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
a49b8e2
to
547d498
Compare
The new option in CodeGenOptions.h seems fine. If your goal is to statically inject passes into the clang executable, I don't understand why the existing LLVM plugin infrastructure isn't sufficient for your needs. You mention "modifying Extension.def", but that file is generated by the build system based on the plugins found by CMake. |
Let me fork off the clang part off into a separate PR from the codegenoption. For context, I'm in an environment where I can't modify the LLVM build files (but I can import them), but want to produce the modified clang, without maintaining a separate fork just to add the pass. |
It should be possible to statically link a pass plugin without modifying any LLVM/clang build files. polly uses this infrastructure. (polly is actually referenced explicitly in a couple places, but only to pull it into the build in the first place; you can do something equivalent with LLVM_EXTERNAL_PROJECTS.) |
547d498
to
bb04e15
Compare
@efriedma-quic I've removed the non-options stuff, please review it at your convenience. Let me see if I can make the other stuff work in a different way. |
bump @efriedma-quic for reviewing this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from an internal chat, this is meant to be used by modifying PassBuilderCallbacks
from a statically linked clang plugin. that makes sense to me, could you update the description with this? as for a test, we can add a test similar to PluginsOrder
. and then manually verify that statically linking a clang plugin also works for this should be good enough
clang/lib/CodeGen/BackendUtil.cpp
Outdated
@@ -906,6 +906,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline( | |||
<< PluginFN << toString(PassPlugin.takeError()); | |||
} | |||
} | |||
for (auto PassCallback : CodeGenOpts.PassBuilderCallbacks) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no braces for single line loops
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
bb04e15
to
ee967e7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for adding the test!
ee967e7
to
ff6e93b
Compare
Adding passbuilder callbacks presently can be done one of two ways:
This prevents the use of such functionality for static builds on build systems that cannot be modified, as well as prevents such functionality from being usable when using llvm/clang as a library.
This creates a third mechanism for adding these callbacks, an explicit list of said callbacks in the CodegenOptions. It's otherwise identical to the plugin approach, except now instead of the list of plugins each being queried for the callback function, this just runs the callback function. This enables use of a clang plugin which can statically add the llvm plugin, without forcing a dsoload for the llvm plugin.