[flang-commits] [clang] [flang] [llvm] [polly] [Plugins] Pass options to a pass plugin in -load-pass-plugin (PR #226773)
Fangrui Song via flang-commits
flang-commits at lists.llvm.org
Sun Sep 27 01:43:11 PDT 2026
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/226773
A pass plugin's cl::opt is global, so opt, llc, and clang-linker-wrapper
load plugins from a cl::opt callback while parsing argv, so that the
plugin's options later on the command line are recognized.
Accept `-load-pass-plugin=plugin.so,-opt1,-opt2`: the plugin loads after
cl::ParseCommandLineOptions and its options are parsed after it loads.
A plugin's options elsewhere on the command line are rejected.
Rename PassPlugin::Load to PassPlugin::load, which accepts
"<file>[,<option>...]".
Polly's tests pass `-polly-*` options after `%loadNPMPolly`. When Polly
is not linked into tools, also load LLVMPolly with -load, which
registers its options while parsing.
cl::callback will be removed to enable migration to TableGen based
representation
https://discourse.llvm.org/t/rfc-declare-library-command-line-options-in-tablegen-one-struct-per-library/91877/5
LLM-aided
>From 2dac70bbc0b5f91f79a7ca096ceed50234b443a4 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 27 Sep 2026 00:02:07 -0700
Subject: [PATCH] [Plugins] Pass options to a pass plugin in -load-pass-plugin
A pass plugin's cl::opt is global, so opt, llc, and clang-linker-wrapper
load plugins from a cl::opt callback while parsing argv, so that the
plugin's options later on the command line are recognized.
Accept `-load-pass-plugin=plugin.so,-opt1,-opt2`: the plugin loads after
cl::ParseCommandLineOptions and its options are parsed after it loads.
A plugin's options elsewhere on the command line are rejected.
Rename PassPlugin::Load to PassPlugin::load, which accepts
"<file>[,<option>...]".
Polly's tests pass `-polly-*` options after `%loadNPMPolly`. When Polly
is not linked into tools, also load LLVMPolly with -load, which
registers its options while parsing.
cl::callback will be removed to enable migration to TableGen based
representation
https://discourse.llvm.org/t/rfc-declare-library-command-line-options-in-tablegen-one-struct-per-library/91877/5
LLM-aided
---
clang/docs/InternalsManual.md | 2 +-
clang/lib/Frontend/CompilerInstance.cpp | 2 +-
.../linker-wrapper-llvm-help.c | 2 +-
.../ClangLinkerWrapper.cpp | 18 +++++-----
.../ExecuteCompilerInvocation.cpp | 2 +-
llvm/docs/NewPassManager.md | 5 +--
llvm/docs/ReleaseNotes.md | 6 ++++
llvm/docs/WritingAnLLVMNewPMPass.md | 2 +-
llvm/include/llvm/Plugins/PassPlugin.h | 9 ++---
llvm/lib/LTO/LTOBackend.cpp | 2 +-
llvm/lib/Plugins/PassPlugin.cpp | 19 +++++++++-
.../tut-simplify-cfg-blockaddress.ll | 6 ++--
.../SimplifyCFG/tut-simplify-cfg1.ll | 6 ++--
.../tut-simplify-cfg2-dead-block-order.ll | 6 ++--
.../SimplifyCFG/tut-simplify-cfg3-phis.ll | 6 ++--
...ify-cfg4-multiple-duplicate-cfg-updates.ll | 6 ++--
...t-simplify-cfg5-del-phis-for-dead-block.ll | 6 ++--
.../tut-simplify-cfg6-dead-self-loop.ll | 6 ++--
llvm/test/Feature/codegen-plugin-passes.mir | 2 +-
llvm/test/Feature/codegen-plugin.ll | 4 +--
llvm/test/Feature/load_extension.ll | 2 +-
llvm/test/lit.cfg.py | 35 +++++++++----------
llvm/tools/llc/lib/llcdriver.cpp | 23 ++++++------
llvm/tools/opt/optdriver.cpp | 24 +++++++------
.../PluginInlineAdvisorAnalysisTest.cpp | 2 +-
.../PluginInlineOrderAnalysisTest.cpp | 2 +-
llvm/unittests/Passes/Plugins/PluginsTest.cpp | 10 +++---
polly/test/lit.site.cfg.in | 7 ++--
28 files changed, 125 insertions(+), 97 deletions(-)
diff --git a/clang/docs/InternalsManual.md b/clang/docs/InternalsManual.md
index 8d5549cb168be..53144018be55e 100644
--- a/clang/docs/InternalsManual.md
+++ b/clang/docs/InternalsManual.md
@@ -883,7 +883,7 @@ desired.
void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(/*...*/) {
// ...
+ for (auto &PluginFN : CodeGenOpts.PassPlugins)
-+ if (auto PassPlugin = PassPlugin::Load(PluginFN))
++ if (auto PassPlugin = PassPlugin::load(PluginFN))
+ PassPlugin->registerPassBuilderCallbacks(PB);
}
```
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 87abcd38c1a92..28f61b7cff9f6 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1115,7 +1115,7 @@ void CompilerInstance::LoadRequestedPlugins() {
// Load and store pass plugins for the back-end.
for (const std::string &Path : getCodeGenOpts().PassPlugins) {
- if (auto PassPlugin = llvm::PassPlugin::Load(Path)) {
+ if (auto PassPlugin = llvm::PassPlugin::load(Path)) {
PassPlugins.emplace_back(std::make_unique<llvm::PassPlugin>(*PassPlugin));
} else {
getDiagnostics().Report(diag::err_fe_unable_to_load_plugin)
diff --git a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-llvm-help.c b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-llvm-help.c
index ffd1cf78bcd9a..a4a65a81bb892 100644
--- a/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-llvm-help.c
+++ b/clang/test/OffloadTools/clang-linker-wrapper/linker-wrapper-llvm-help.c
@@ -7,4 +7,4 @@
// Look for a few options supported only after -mllvm and --offload-opt.
// CHECK: OPTIONS:
// CHECK-DAG: --passes=<string>
-// CHECK-DAG: --load-pass-plugin=<string>
+// CHECK-DAG: --load-pass-plugin=<file[,option...]>
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index a5ebd7d2ad06b..33e10ba797691 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -91,9 +91,11 @@ static cl::opt<std::string> RemarksFormat(
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));
-static cl::list<std::string>
- PassPlugins("load-pass-plugin",
- cl::desc("Load passes from plugin library"));
+static cl::list<std::string> PassPlugins(
+ "load-pass-plugin",
+ cl::desc("Load passes from plugin library. The plugin's options follow "
+ "its file name, separated by commas"),
+ cl::value_desc("file[,option...]"));
static cl::opt<std::string> PassPipeline(
"passes",
@@ -1532,14 +1534,10 @@ int main(int Argc, char **Argv) {
NewArgv.push_back(Arg->getValue());
for (const opt::Arg *Arg : Args.filtered(OPT_offload_opt_eq_minus))
NewArgv.push_back(Arg->getValue());
- SmallVector<PassPlugin, 1> PluginList;
- PassPlugins.setCallback([&](const std::string &PluginPath) {
- auto Plugin = PassPlugin::Load(PluginPath);
- if (!Plugin)
- reportFatalUsageError(Plugin.takeError());
- PluginList.emplace_back(Plugin.get());
- });
cl::ParseCommandLineOptions(NewArgv.size(), &NewArgv[0]);
+ for (const std::string &Spec : PassPlugins)
+ if (Error E = PassPlugin::load(Spec).takeError())
+ reportFatalUsageError(std::move(E));
Verbose = Args.hasArg(OPT_verbose);
DryRun = Args.hasArg(OPT_dry_run);
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 0396889fc57a4..aa06cc6ebb036 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -182,7 +182,7 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
for (const std::string &path :
flang->getInvocation().getCodeGenOpts().LLVMPassPlugins) {
if (llvm::Expected<llvm::PassPlugin> passPlugin =
- llvm::PassPlugin::Load(path)) {
+ llvm::PassPlugin::load(path)) {
flang->addPassPlugin(std::make_unique<llvm::PassPlugin>(*passPlugin));
} else {
unsigned diagID = flang->getDiagnostics().getCustomDiagID(
diff --git a/llvm/docs/NewPassManager.md b/llvm/docs/NewPassManager.md
index f9b819c2591c8..78b88baf0dff9 100644
--- a/llvm/docs/NewPassManager.md
+++ b/llvm/docs/NewPassManager.md
@@ -174,8 +174,9 @@ backend adding passes to various parts of the pipeline.
Pass plugins can also add passes into default pipelines. Different tools have
different ways of loading dynamic pass plugins. For example, `opt
--load-pass-plugin=path/to/plugin.so` loads a pass plugin into `opt`. For
-information on writing a pass plugin, see {doc}`WritingAnLLVMNewPMPass`.
+-load-pass-plugin=path/to/plugin.so` loads a pass plugin into `opt`, and
+`-load-pass-plugin=path/to/plugin.so,-opt1,-opt2` also passes the plugin's
+options `-opt1` and `-opt2`. For information on writing a pass plugin, see {doc}`WritingAnLLVMNewPMPass`.
## Using Analyses
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 41b2fa83d380f..ed5af868daa8f 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -330,6 +330,12 @@ Makes programs 10x faster by doing Special New Thing.
### Changes to the LLVM tools
+* `opt`, `llc`, and `clang-linker-wrapper` accept
+ `-load-pass-plugin=plugin.so,-opt1,-opt2`, which passes options to the pass
+ plugin after it is loaded. A plugin's options elsewhere on the command line
+ are no longer accepted. `PassPlugin::Load` is renamed to `PassPlugin::load`,
+ which accepts the same specification.
+
* llvm-mca no longer defaults -mcpu to "native"
* llvm-rc now supports `/showIncludes` to report header and resource-file
diff --git a/llvm/docs/WritingAnLLVMNewPMPass.md b/llvm/docs/WritingAnLLVMNewPMPass.md
index 065c6b5bb0238..4ea4578ae53b9 100644
--- a/llvm/docs/WritingAnLLVMNewPMPass.md
+++ b/llvm/docs/WritingAnLLVMNewPMPass.md
@@ -273,7 +273,7 @@ To make `PassBuilder` aware of dynamically linked pass plugins:
```c++
// Load plugin dynamically.
-auto Plugin = PassPlugin::Load(PathToPlugin);
+auto Plugin = PassPlugin::load(PathToPlugin);
if (!Plugin)
report_error();
// Register plugin extensions in PassBuilder.
diff --git a/llvm/include/llvm/Plugins/PassPlugin.h b/llvm/include/llvm/Plugins/PassPlugin.h
index e8da9c51c0a85..0f1fbb21b74ae 100644
--- a/llvm/include/llvm/Plugins/PassPlugin.h
+++ b/llvm/include/llvm/Plugins/PassPlugin.h
@@ -70,12 +70,13 @@ struct PassPluginLibraryInfo {
/// its interface defined by the \c PassPluginLibraryInfo it exposes.
class PassPlugin {
public:
- /// Attempts to load a pass plugin from a given file.
+ /// Attempts to load a pass plugin specified as "<file>[,<option>...]", then
+ /// parses the options, which the plugin defines as cl::opt.
///
/// \returns Returns an error if either the library cannot be found or loaded,
- /// there is no public entry point, or the plugin implements the wrong API
- /// version.
- LLVM_ABI static Expected<PassPlugin> Load(const std::string &Filename);
+ /// there is no public entry point, the plugin implements the wrong API
+ /// version, or an option is invalid.
+ LLVM_ABI static Expected<PassPlugin> load(StringRef Spec);
/// Get the filename of the loaded plugin.
StringRef getFilename() const { return Filename; }
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index d9a6551139d37..0d253647ae46c 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -207,7 +207,7 @@ static void RegisterPassPlugins(const Config &Conf, PassBuilder &PB) {
// Load requested pass plugins and let them register pass builder callbacks
for (auto &PluginFN : Conf.PassPluginFilenames) {
- auto PassPlugin = PassPlugin::Load(PluginFN);
+ auto PassPlugin = PassPlugin::load(PluginFN);
if (!PassPlugin)
reportFatalUsageError(PassPlugin.takeError());
PassPlugin->registerPassBuilderCallbacks(PB);
diff --git a/llvm/lib/Plugins/PassPlugin.cpp b/llvm/lib/Plugins/PassPlugin.cpp
index 84d55fc513b78..f56f2d7d1b767 100644
--- a/llvm/lib/Plugins/PassPlugin.cpp
+++ b/llvm/lib/Plugins/PassPlugin.cpp
@@ -7,13 +7,19 @@
//===----------------------------------------------------------------------===//
#include "llvm/Plugins/PassPlugin.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/StringSaver.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
using namespace llvm;
-Expected<PassPlugin> PassPlugin::Load(const std::string &Filename) {
+Expected<PassPlugin> PassPlugin::load(StringRef Spec) {
+ SmallVector<StringRef, 0> Parts;
+ Spec.split(Parts, ',');
+ std::string Filename = Parts[0].str();
std::string Error;
auto Library =
sys::DynamicLibrary::getPermanentLibrary(Filename.c_str(), &Error);
@@ -45,5 +51,16 @@ Expected<PassPlugin> PassPlugin::Load(const std::string &Filename) {
Twine(LLVM_PLUGIN_API_VERSION) + ".",
inconvertibleErrorCode());
+ if (Parts.size() == 1)
+ return P;
+ BumpPtrAllocator Alloc;
+ StringSaver Saver(Alloc);
+ SmallVector<const char *, 0> Argv = {Filename.c_str()};
+ for (StringRef Option : drop_begin(Parts))
+ Argv.push_back(Saver.save(Option).data());
+ std::string Msg;
+ raw_string_ostream OS(Msg);
+ if (!cl::ParseCommandLineOptions(Argv.size(), Argv.data(), "", &OS))
+ return createStringError(StringRef(Msg).trim());
return P;
}
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg-blockaddress.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg-blockaddress.ll
index f9cf6472a4c31..ef0ca4d6be37c 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg-blockaddress.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg-blockaddress.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg -S < %s | FileCheck %s
define ptr @simp1(i32 %x) {
; CHECK-LABEL: @simp1(
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg1.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg1.ll
index 35dac1dba927b..9ea6661010c19 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg1.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg1.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg -S < %s | FileCheck %s
define i32 @simp1() {
; CHECK-LABEL: @simp1(
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg2-dead-block-order.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg2-dead-block-order.ll
index aa078179d2e3b..d0e2e95ff79c8 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg2-dead-block-order.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg2-dead-block-order.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg -S < %s | FileCheck %s
define i32 @remove_dead_blocks() {
; CHECK-LABEL: @remove_dead_blocks(
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg3-phis.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg3-phis.ll
index a4474d09df320..e50ba55f74bde 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg3-phis.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg3-phis.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg -S < %s | FileCheck %s
define i32 @phi_cond_branch_eliminated() {
; CHECK-LABEL: @phi_cond_branch_eliminated(
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg4-multiple-duplicate-cfg-updates.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg4-multiple-duplicate-cfg-updates.ll
index 13ccb8b10dc41..5bae31e62e958 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg4-multiple-duplicate-cfg-updates.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg4-multiple-duplicate-cfg-updates.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg < %s -S -verify-dom-info | FileCheck %s
; Check that we do not crash when we remove edges multiple times in
; the DomTreeUpdater.
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg5-del-phis-for-dead-block.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg5-del-phis-for-dead-block.ll
index 1f1c1016b3fc8..d0109a7537ead 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg5-del-phis-for-dead-block.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg5-del-phis-for-dead-block.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg < %s -S -verify-dom-info | FileCheck %s
define void @test() {
; CHECK-LABEL: @test(
diff --git a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg6-dead-self-loop.ll b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg6-dead-self-loop.ll
index e40076e6de3aa..ba190cdf10d07 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg6-dead-self-loop.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg6-dead-self-loop.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v1 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v2 -passes=tut-simplifycfg -S < %s | FileCheck %s
+; RUN: opt %{loadexampleirtransforms,}-tut-simplifycfg-version=v3 -passes=tut-simplifycfg -S < %s | FileCheck %s
define i32 @simp1() {
; CHECK-LABEL: @simp1(
diff --git a/llvm/test/Feature/codegen-plugin-passes.mir b/llvm/test/Feature/codegen-plugin-passes.mir
index 4b4ac5c54e59c..2de83968eeb79 100644
--- a/llvm/test/Feature/codegen-plugin-passes.mir
+++ b/llvm/test/Feature/codegen-plugin-passes.mir
@@ -4,7 +4,7 @@
# UNSUPPORTED: target={{.*windows.*}}
# Plugins are currently broken on AIX, at least in the CI.
# XFAIL: target={{.*}}-aix{{.*}}
-# RUN: llc -mtriple=x86_64-- %loadnewpmbye -passes=goodbye -wave-goodbye %s -o /dev/null 2>&1 | FileCheck %s
+# RUN: llc -mtriple=x86_64-- %{loadnewpmbye,}-wave-goodbye -passes=goodbye %s -o /dev/null 2>&1 | FileCheck %s
# RUN: llc -mtriple=x86_64-- %loadnewpmbye -passes=goodbye --print-pipeline-passes -filetype=null %s | FileCheck %s --check-prefix=PIPELINE
# CHECK: Bye: somefunk
diff --git a/llvm/test/Feature/codegen-plugin.ll b/llvm/test/Feature/codegen-plugin.ll
index cd36ef14d8ec3..74d4e1de3cc05 100644
--- a/llvm/test/Feature/codegen-plugin.ll
+++ b/llvm/test/Feature/codegen-plugin.ll
@@ -1,7 +1,7 @@
; REQUIRES: x86-registered-target
; RUN: llc < %s %loadnewpmbye | FileCheck %s --check-prefix=CHECK-ASM
-; RUN: llc < %s %loadnewpmbye -last-words | FileCheck %s --check-prefix=CHECK-ACTIVE
-; RUN: not llc < %s %loadnewpmbye -last-words -filetype=obj 2>&1 | FileCheck %s --check-prefix=CHECK-ERR
+; RUN: llc < %s %{loadnewpmbye,}-last-words | FileCheck %s --check-prefix=CHECK-ACTIVE
+; RUN: not llc < %s %{loadnewpmbye,}-last-words -filetype=obj 2>&1 | FileCheck %s --check-prefix=CHECK-ERR
; REQUIRES: plugins, examples
; UNSUPPORTED: target={{.*windows.*}}
; Plugins are currently broken on AIX, at least in the CI.
diff --git a/llvm/test/Feature/load_extension.ll b/llvm/test/Feature/load_extension.ll
index 6f99e99cb6345..6ceb9c2534f01 100644
--- a/llvm/test/Feature/load_extension.ll
+++ b/llvm/test/Feature/load_extension.ll
@@ -1,6 +1,6 @@
; REQUIRES: x86-registered-target
; RUN: opt %s %loadnewpmbye %loadbye -passes="goodbye" -wave-goodbye -disable-output 2>&1 | FileCheck %s
-; RUN: opt %s %loadnewpmbye -passes="goodbye" -wave-goodbye -disable-output 2>&1 | FileCheck %s
+; RUN: opt %s %{loadnewpmbye,}-wave-goodbye -passes="goodbye" -disable-output 2>&1 | FileCheck %s
; RUN: opt -module-summary %s -o %t.o
; RUN: llvm-lto2 run %t.o %loadbye %loadnewpmbye -wave-goodbye -o %t -r %t.o,somefunk,plx -r %t.o,junk,plx 2>&1 | FileCheck %s
; RUN: llvm-lto2 run %t.o %loadbye %loadnewpmbye -opt-pipeline="goodbye" -wave-goodbye -o %t -r %t.o,somefunk,plx -r %t.o,junk,plx 2>&1 | FileCheck %s
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index d8913b1fbdc87..4758ed12a0b7c 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -536,7 +536,6 @@ def enable_ptxas(ptxas_executable):
if config.linked_bye_extension:
config.substitutions.append(("%llvmcheckext", "CHECK-EXT"))
config.substitutions.append(("%loadbye", ""))
- config.substitutions.append(("%loadnewpmbye", ""))
else:
config.substitutions.append(("%llvmcheckext", "CHECK-NOEXT"))
config.substitutions.append(
@@ -545,26 +544,24 @@ def enable_ptxas(ptxas_executable):
"-load={}/Bye{}".format(config.llvm_shlib_dir, config.llvm_shlib_ext),
)
)
- config.substitutions.append(
- (
- "%loadnewpmbye",
- "-load-pass-plugin={}/Bye{}".format(
- config.llvm_shlib_dir, config.llvm_shlib_ext
- ),
- )
- )
-if config.linked_exampleirtransforms_extension:
- config.substitutions.append(("%loadexampleirtransforms", ""))
-else:
- config.substitutions.append(
- (
- "%loadexampleirtransforms",
- "-load-pass-plugin={}/ExampleIRTransforms{}".format(
- config.llvm_shlib_dir, config.llvm_shlib_ext
- ),
+# %{loadX,} is followed by one option of the extension, e.g.
+# %{loadnewpmbye,}-wave-goodbye.
+for name, lib, linked in [
+ ("loadnewpmbye", "Bye", config.linked_bye_extension),
+ (
+ "loadexampleirtransforms",
+ "ExampleIRTransforms",
+ config.linked_exampleirtransforms_extension,
+ ),
+]:
+ load = ""
+ if not linked:
+ load = "-load-pass-plugin={}/{}{}".format(
+ config.llvm_shlib_dir, lib, config.llvm_shlib_ext
)
- )
+ config.substitutions.append(("%{" + name + ",}", load and load + ","))
+ config.substitutions.append(("%" + name, load))
# Static libraries are not built if BUILD_SHARED_LIBS is ON.
if not config.build_shared_libs and not config.link_llvm_dylib:
diff --git a/llvm/tools/llc/lib/llcdriver.cpp b/llvm/tools/llc/lib/llcdriver.cpp
index 7f0ee013cd947..b205743d15b80 100644
--- a/llvm/tools/llc/lib/llcdriver.cpp
+++ b/llvm/tools/llc/lib/llcdriver.cpp
@@ -213,8 +213,11 @@ static cl::opt<std::string> RemarksFormat(
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));
-static cl::list<std::string> PassPlugins("load-pass-plugin",
- cl::desc("Load plugin library"));
+static cl::list<std::string> PassPlugins(
+ "load-pass-plugin",
+ cl::desc("Load passes from plugin library. The plugin's options follow "
+ "its file name, separated by commas"),
+ cl::value_desc("file[,option...]"));
static cl::opt<bool> EnableNewPassManager(
"enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false));
@@ -394,14 +397,6 @@ extern "C" int llcMain(int argc, char **argv) {
// Initialize debugging passes.
initializeScavengerTestPass(*Registry);
- SmallVector<PassPlugin, 1> PluginList;
- PassPlugins.setCallback([&](const std::string &PluginPath) {
- auto Plugin = PassPlugin::Load(PluginPath);
- if (!Plugin)
- reportFatalUsageError(Plugin.takeError());
- PluginList.emplace_back(Plugin.get());
- });
-
// Register the Target and CPU printer for --version.
cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
// Register the target printer for --version.
@@ -409,6 +404,14 @@ extern "C" int llcMain(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
+ SmallVector<PassPlugin, 1> PluginList;
+ for (const std::string &Spec : PassPlugins) {
+ auto Plugin = PassPlugin::load(Spec);
+ if (!Plugin)
+ reportFatalUsageError(Plugin.takeError());
+ PluginList.emplace_back(Plugin.get());
+ }
+
if (!PassPipeline.empty() && !getRunPassNames().empty()) {
errs() << "The `llc -run-pass=...` syntax for the new pass manager is "
"not supported, please use `llc -passes=<pipeline>` (or the `-p` "
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index 46c6833515e18..a9456ef940dee 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -281,9 +281,11 @@ static cl::opt<std::string> RemarksFormat(
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));
-static cl::list<std::string>
- PassPlugins("load-pass-plugin",
- cl::desc("Load passes from plugin library"));
+static cl::list<std::string> PassPlugins(
+ "load-pass-plugin",
+ cl::desc("Load passes from plugin library. The plugin's options follow "
+ "its file name, separated by commas"),
+ cl::value_desc("file[,option...]"));
//===----------------------------------------------------------------------===//
// CodeGen-related helper functions.
@@ -443,20 +445,20 @@ optMain(int argc, char **argv,
initializeReplaceWithVeclibLegacyPass(Registry);
initializeJMCInstrumenterPass(Registry);
- SmallVector<PassPlugin, 1> PluginList;
- PassPlugins.setCallback([&](const std::string &PluginPath) {
- auto Plugin = PassPlugin::Load(PluginPath);
- if (!Plugin)
- reportFatalUsageError(Plugin.takeError());
- PluginList.emplace_back(Plugin.get());
- });
-
// Register the Target and CPU printer for --version.
cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
cl::ParseCommandLineOptions(
argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n");
+ SmallVector<PassPlugin, 1> PluginList;
+ for (const std::string &Spec : PassPlugins) {
+ auto Plugin = PassPlugin::load(Spec);
+ if (!Plugin)
+ reportFatalUsageError(Plugin.takeError());
+ PluginList.emplace_back(Plugin.get());
+ }
+
LLVMContext Context;
// TODO: remove shouldForceLegacyPM().
diff --git a/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp b/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp
index 61ab1820373c3..34c6dce215f20 100644
--- a/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp
+++ b/llvm/unittests/Analysis/PluginInlineAdvisorAnalysisTest.cpp
@@ -63,7 +63,7 @@ struct CompilerInstance {
void setupPlugin() {
auto PluginPath = libPath();
ASSERT_NE("", PluginPath);
- Expected<PassPlugin> Plugin = PassPlugin::Load(PluginPath);
+ Expected<PassPlugin> Plugin = PassPlugin::load(PluginPath);
ASSERT_TRUE(!!Plugin) << "Plugin path: " << PluginPath;
Plugin->registerPassBuilderCallbacks(PB);
}
diff --git a/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp b/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp
index e9e839904a2e6..f5431cd7fdc85 100644
--- a/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp
+++ b/llvm/unittests/Analysis/PluginInlineOrderAnalysisTest.cpp
@@ -45,7 +45,7 @@ struct CompilerInstance {
void setupPlugin() {
auto PluginPath = libPath();
ASSERT_NE("", PluginPath);
- Expected<PassPlugin> Plugin = PassPlugin::Load(PluginPath);
+ Expected<PassPlugin> Plugin = PassPlugin::load(PluginPath);
ASSERT_TRUE(!!Plugin) << "Plugin path: " << PluginPath;
Plugin->registerPassBuilderCallbacks(PB);
}
diff --git a/llvm/unittests/Passes/Plugins/PluginsTest.cpp b/llvm/unittests/Passes/Plugins/PluginsTest.cpp
index d4d519eb52a53..c2ef01c14dc73 100644
--- a/llvm/unittests/Passes/Plugins/PluginsTest.cpp
+++ b/llvm/unittests/Passes/Plugins/PluginsTest.cpp
@@ -48,7 +48,7 @@ TEST(PluginsTests, LoadPlugin) {
auto PluginPath = LibPath();
ASSERT_NE("", PluginPath);
- Expected<PassPlugin> Plugin = PassPlugin::Load(PluginPath);
+ Expected<PassPlugin> Plugin = PassPlugin::load(PluginPath);
ASSERT_TRUE(!!Plugin) << "Plugin path: " << PluginPath;
ASSERT_EQ(TEST_PLUGIN_NAME, Plugin->getPluginName());
@@ -76,18 +76,18 @@ TEST(PluginsTests, LoadMultiplePlugins) {
ASSERT_NE("", DoublerPluginPath);
ASSERT_NE("", TestPluginPath);
- Expected<PassPlugin> DoublerPlugin1 = PassPlugin::Load(DoublerPluginPath);
+ Expected<PassPlugin> DoublerPlugin1 = PassPlugin::load(DoublerPluginPath);
ASSERT_TRUE(!!DoublerPlugin1)
<< "Plugin path: " << DoublerPlugin1->getFilename();
- Expected<PassPlugin> TestPlugin = PassPlugin::Load(TestPluginPath);
+ Expected<PassPlugin> TestPlugin = PassPlugin::load(TestPluginPath);
ASSERT_TRUE(!!TestPlugin) << "Plugin path: " << TestPlugin->getFilename();
// If llvmGetPassPluginInfo is resolved as a weak symbol taking into account
- // all loaded symbols, the second call to PassPlugin::Load will actually
+ // all loaded symbols, the second call to PassPlugin::load will actually
// return the llvmGetPassPluginInfo from the most recently loaded plugin, in
// this case TestPlugin.
- Expected<PassPlugin> DoublerPlugin2 = PassPlugin::Load(DoublerPluginPath);
+ Expected<PassPlugin> DoublerPlugin2 = PassPlugin::load(DoublerPluginPath);
ASSERT_TRUE(!!DoublerPlugin2)
<< "Plugin path: " << DoublerPlugin2->getFilename();
diff --git a/polly/test/lit.site.cfg.in b/polly/test/lit.site.cfg.in
index 56448f27ba6dc..29c41671f053c 100644
--- a/polly/test/lit.site.cfg.in
+++ b/polly/test/lit.site.cfg.in
@@ -40,8 +40,11 @@ if config.llvm_polly_link_into_tools == '' or \
config.llvm_polly_link_into_tools.lower() == 'false' or \
config.llvm_polly_link_into_tools.lower() == 'notfound' or \
config.llvm_polly_link_into_tools.lower() == 'llvm_polly_link_into_tools-notfound':
- config.substitutions.append(('%loadNPMPolly', '-load-pass-plugin '
- + config.polly_lib_dir + '/LLVMPolly at LLVM_SHLIBEXT@'
+ # -load registers Polly's options while opt parses the -polly-* options
+ # that follow; -load-pass-plugin registers its passes after parsing.
+ pollyLib = config.polly_lib_dir + '/LLVMPolly at LLVM_SHLIBEXT@'
+ config.substitutions.append(('%loadNPMPolly', '-load=' + pollyLib
+ + ' -load-pass-plugin=' + pollyLib
+ commonOpts ))
else:
config.substitutions.append(('%loadNPMPolly', commonOpts ))
More information about the flang-commits
mailing list