[llvm] [polly] [Plugins] Address review comments on -plugin-arg (PR #227545)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 20:03:51 PDT 2026


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/227545

Address comments after #226773:

* Accept an empty argument again (-plugin-arg=<plugin>,). Tested by
  tut-simplify-cfg1.ll
* Reject an argument for a name shared by several plugins.
* Remove parsePassPluginCommandLine. Polly and the Bye example, which
  keep cl::opt, call cl::ParseCommandLineOptions from ParseArguments.
* Drop cl::opt from the IRTransforms example: ParseArguments takes v1,
  v2 or v3.
* Test -plugin-arg diagnostics.

LLM-aided

>From 38c9725246c5eb8b913a30a38da0b2ad63ae406c Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Tue, 29 Sep 2026 18:53:57 -0700
Subject: [PATCH] [Plugins] Address review comments on -plugin-arg

Address comments after #226773:

* Accept an empty argument again (-plugin-arg=<plugin>,). Tested by
  tut-simplify-cfg1.ll
* Reject an argument for a name shared by several plugins.
* Remove parsePassPluginCommandLine. Polly and the Bye example, which
  keep cl::opt, call cl::ParseCommandLineOptions from ParseArguments.
* Drop cl::opt from the IRTransforms example: ParseArguments takes v1,
  v2 or v3.
* Test -plugin-arg diagnostics.

LLM-aided
---
 llvm/docs/ReleaseNotes.md                     |  2 +-
 llvm/examples/Bye/Bye.cpp                     |  8 ++++-
 llvm/examples/IRTransforms/SimplifyCFG.cpp    | 25 +++++++++-------
 llvm/include/llvm/Plugins/PassPlugin.h        | 11 +++----
 llvm/lib/Plugins/PassPlugin.cpp               | 29 +++++++++----------
 .../tut-simplify-cfg-blockaddress.ll          |  6 ++--
 .../SimplifyCFG/tut-simplify-cfg1.ll          | 10 +++++--
 .../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/load_extension.ll           |  8 ++++-
 llvm/test/lit.cfg.py                          |  1 +
 polly/docs/ReleaseNotes.rst                   |  2 +-
 polly/lib/Support/RegisterPasses.cpp          |  8 ++++-
 polly/test/lit.site.cfg.in                    |  2 ++
 17 files changed, 83 insertions(+), 59 deletions(-)

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 3b344fe96bc32..85072e4c619a4 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -331,7 +331,7 @@ Makes programs 10x faster by doing Special New Thing.
 ### Changes to the LLVM tools
 
 * `opt` and `llc` accept `-plugin-arg=<plugin>,<arg>`, which passes `<arg>` to the new `PassPluginLibraryInfo::ParseArguments` callback of the pass plugin named `<plugin>`.
-  A plugin that defines `cl::opt` can call `parsePassPluginCommandLine` from `ParseArguments`, as the `Bye` example and Polly do.
+  A plugin that defines `cl::opt` has to call `cl::ParseCommandLineOptions` itself inside `ParseArguments`.
   `LLVM_PLUGIN_API_VERSION` is now 3.
 
 * `opt` and `llc` load `-load-pass-plugin` plugins after parsing the command line, so a loaded plugin's options are no longer accepted as ordinary options.
diff --git a/llvm/examples/Bye/Bye.cpp b/llvm/examples/Bye/Bye.cpp
index a328993a163ec..f201e36453055 100644
--- a/llvm/examples/Bye/Bye.cpp
+++ b/llvm/examples/Bye/Bye.cpp
@@ -85,7 +85,13 @@ static RegisterPass<LegacyBye> X("goodbye", "Good Bye World Pass",
                                  false /* Analysis Pass */);
 
 static Error parseArguments(ArrayRef<const char *> Args) {
-  return parsePassPluginCommandLine("Bye", Args);
+  SmallVector<const char *, 0> Argv = {"Bye"};
+  append_range(Argv, Args);
+  std::string Msg;
+  raw_string_ostream OS(Msg);
+  if (!cl::ParseCommandLineOptions(Argv.size(), Argv.data(), "", &OS))
+    return createStringError(StringRef(Msg).trim());
+  return Error::success();
 }
 
 /* New PM Registration */
diff --git a/llvm/examples/IRTransforms/SimplifyCFG.cpp b/llvm/examples/IRTransforms/SimplifyCFG.cpp
index e964663f99212..e62181b3451b2 100644
--- a/llvm/examples/IRTransforms/SimplifyCFG.cpp
+++ b/llvm/examples/IRTransforms/SimplifyCFG.cpp
@@ -32,6 +32,7 @@
 //  * Add implementation using reachability to discover dead blocks.
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
@@ -39,21 +40,13 @@
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Plugins/PassPlugin.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 using namespace PatternMatch;
 
 enum TutorialVersion { V1, V2, V3 };
-static cl::opt<TutorialVersion>
-    Version("tut-simplifycfg-version", cl::desc("Select tutorial version"),
-            cl::Hidden, cl::ValueOptional, cl::init(V1),
-            cl::values(clEnumValN(V1, "v1", "version 1"),
-                       clEnumValN(V2, "v2", "version 2"),
-                       clEnumValN(V3, "v3", "version 3"),
-                       // Sentinel value for unspecified option.
-                       clEnumValN(V3, "", "")));
+static TutorialVersion Version = V1;
 
 #define DEBUG_TYPE "tut-simplifycfg"
 
@@ -392,8 +385,20 @@ struct SimplifyCFGPass : public OptionalPassInfoMixin<SimplifyCFGPass> {
 };
 } // namespace
 
+// Selects the tutorial version with -plugin-arg=SimplifyCFG,v1 (or v2, v3).
 static Error parseArguments(ArrayRef<const char *> Args) {
-  return parsePassPluginCommandLine("SimplifyCFG", Args);
+  std::optional<TutorialVersion> V;
+  if (Args.size() == 1)
+    V = StringSwitch<std::optional<TutorialVersion>>(Args[0])
+            .Case("v1", V1)
+            .Case("v2", V2)
+            .Case("v3", V3)
+            .Default(std::nullopt);
+  if (!V)
+    return createStringError(
+        "SimplifyCFG: expected one argument, v1, v2 or v3");
+  Version = *V;
+  return Error::success();
 }
 
 /* New PM Registration */
diff --git a/llvm/include/llvm/Plugins/PassPlugin.h b/llvm/include/llvm/Plugins/PassPlugin.h
index 82f8bf3ef51a6..9ae714a41528e 100644
--- a/llvm/include/llvm/Plugins/PassPlugin.h
+++ b/llvm/include/llvm/Plugins/PassPlugin.h
@@ -47,7 +47,8 @@ struct PassPluginLibraryInfo {
   /// The API version understood by this plugin, usually \c
   /// LLVM_PLUGIN_API_VERSION
   uint32_t APIVersion;
-  /// A meaningful name of the plugin.
+  /// A meaningful name of the plugin. -plugin-arg=<PluginName>,<arg> passes
+  /// <arg> to the plugin with this name.
   const char *PluginName;
   /// The version of the plugin.
   const char *PluginVersion;
@@ -121,14 +122,10 @@ class PassPlugin {
 };
 
 /// Passes each "<PluginName>,<arg>" in \p Args to the \c ParseArguments
-/// callback of the extension in \p Infos with that name. If two extensions have
-/// the same name, the last one receives the arguments.
+/// callback of the extension in \p Infos with that name. An argument for a name
+/// shared by several extensions is an error.
 LLVM_ABI Error passPluginArguments(ArrayRef<PassPluginLibraryInfo> Infos,
                                    ArrayRef<std::string> Args);
-
-// Deprecated: a migration aid for plugins that still use cl::opt.
-LLVM_ABI Error parsePassPluginCommandLine(const char *PluginName,
-                                          ArrayRef<const char *> Args);
 } // namespace llvm
 
 // The function returns a struct with default initializers.
diff --git a/llvm/lib/Plugins/PassPlugin.cpp b/llvm/lib/Plugins/PassPlugin.cpp
index 03d18d931376f..156d5ff28b907 100644
--- a/llvm/lib/Plugins/PassPlugin.cpp
+++ b/llvm/lib/Plugins/PassPlugin.cpp
@@ -9,7 +9,6 @@
 #include "llvm/Plugins/PassPlugin.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <cstdint>
@@ -53,19 +52,28 @@ Expected<PassPlugin> PassPlugin::load(StringRef Filename) {
 
 Error llvm::passPluginArguments(ArrayRef<PassPluginLibraryInfo> Infos,
                                 ArrayRef<std::string> Args) {
+  constexpr unsigned Ambiguous = -1u;
   DenseMap<StringRef, unsigned> Index;
-  for (auto [I, Info] : enumerate(Infos))
-    Index[Info.PluginName] = I;
-  // The argument follows the first comma, so it is NUL-terminated.
+  for (auto [I, Info] : enumerate(Infos)) {
+    auto [It, Inserted] = Index.try_emplace(Info.PluginName, I);
+    if (!Inserted)
+      It->second = Ambiguous;
+  }
+  // ParseArguments takes argv-style C strings. The argument is the suffix of
+  // Arg after the first comma, so it is NUL-terminated and needs no copy.
   SmallVector<SmallVector<const char *, 0>, 0> PluginArgs(Infos.size());
   for (const std::string &Arg : Args) {
     auto [Name, Rest] = StringRef(Arg).split(',');
-    if (Rest.empty())
+    // Rest is null without a comma and empty for an empty argument.
+    if (!Rest.data())
       return createStringError("expected <plugin>,<arg> in -plugin-arg=" + Arg);
     auto It = Index.find(Name);
     if (It == Index.end())
       return createStringError("no pass plugin named '" + Name +
                                "' is loaded, in -plugin-arg=" + Arg);
+    if (It->second == Ambiguous)
+      return createStringError("multiple pass plugins are named '" + Name +
+                               "', in -plugin-arg=" + Arg);
     PluginArgs[It->second].push_back(Rest.data());
   }
   for (auto [Info, PArgs] : zip_equal(Infos, PluginArgs)) {
@@ -79,14 +87,3 @@ Error llvm::passPluginArguments(ArrayRef<PassPluginLibraryInfo> Infos,
   }
   return Error::success();
 }
-
-Error llvm::parsePassPluginCommandLine(const char *PluginName,
-                                       ArrayRef<const char *> Args) {
-  SmallVector<const char *, 0> Argv = {PluginName};
-  append_range(Argv, Args);
-  std::string Msg;
-  raw_string_ostream OS(Msg);
-  if (!cl::ParseCommandLineOptions(Argv.size(), Argv.data(), "", &OS))
-    return createStringError(StringRef(Msg).trim());
-  return Error::success();
-}
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 c4c7dcfb19044..47f85d315a71d 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 -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 -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 9b21d41b5add8..086c69946d402 100644
--- a/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg1.ll
+++ b/llvm/test/Examples/IRTransforms/SimplifyCFG/tut-simplify-cfg1.ll
@@ -1,7 +1,11 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 -S < %s | FileCheck %s
+;; An empty argument reaches the plugin.
+; RUN: not opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG, -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ERR
+; RUN: not opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 -plugin-arg=SimplifyCFG,v2 -disable-output < %s 2>&1 | FileCheck %s --check-prefix=ERR
+; ERR: SimplifyCFG: expected one argument, v1, v2 or v3
 
 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 9c6770140a955..7077bc44f62b4 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 -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 -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 928f196291f36..ed0c5369b63f9 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 -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 -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 e31d2b453455a..27e93aa601684 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 -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 < %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 9add47f25e0e7..27c808da53d16 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 -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 < %s -S -verify-dom-info | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 < %s -S -verify-dom-info | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 < %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 30cc9f061ba9c..ac9873aec79af 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 -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v1 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v2 -S < %s | FileCheck %s
-; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,-tut-simplifycfg-version=v3 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v1 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v2 -S < %s | FileCheck %s
+; RUN: opt %loadexampleirtransforms -passes=tut-simplifycfg -plugin-arg=SimplifyCFG,v3 -S < %s | FileCheck %s
 
 define i32 @simp1() {
 ; CHECK-LABEL: @simp1(
diff --git a/llvm/test/Feature/load_extension.ll b/llvm/test/Feature/load_extension.ll
index 80f0ca8a33c8a..6db95548928e8 100644
--- a/llvm/test/Feature/load_extension.ll
+++ b/llvm/test/Feature/load_extension.ll
@@ -1,9 +1,12 @@
 ; 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" -plugin-arg=Bye,-wave-goodbye -disable-output 2>&1 | FileCheck %s
 ;; A plugin receives all of its -plugin-arg arguments. -plugin-arg splits at
 ;; the first comma only, so the value may contain commas.
 ; RUN: opt %s %loadnewpmbye -passes="goodbye" -plugin-arg=Bye,-wave-goodbye -plugin-arg=Bye,-bye-greeting=See,you -disable-output 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: not opt %s %loadnewpmbye -plugin-arg=Bye -disable-output 2>&1 | FileCheck %s --check-prefix=NOCOMMA
+; RUN: not opt %s %loadnewpmbye -plugin-arg=Nope,-x -disable-output 2>&1 | FileCheck %s --check-prefix=UNKNOWN
+;; Loading the plugin twice makes its name ambiguous.
+; RUN: %if !linked-bye %{ not opt %s %loadnewpmbye %loadnewpmbye -plugin-arg=Bye,-x -disable-output 2>&1 | FileCheck %s --check-prefix=DUP %}
 ; 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
@@ -14,6 +17,9 @@
 ; CHECK: Bye
 ; BOTH:      Bye: somefunk
 ; BOTH-NEXT: See,you: somefunk
+; NOCOMMA: expected <plugin>,<arg> in -plugin-arg=Bye{{$}}
+; UNKNOWN: no pass plugin named 'Nope' is loaded, in -plugin-arg=Nope,-x
+; DUP: multiple pass plugins are named 'Bye', in -plugin-arg=Bye,-x
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index a362629df0dc9..01fe48d86ed27 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -542,6 +542,7 @@ def enable_ptxas(ptxas_executable):
     config.available_features.add("examples")
 
 if config.linked_bye_extension:
+    config.available_features.add("linked-bye")
     config.substitutions.append(("%llvmcheckext", "CHECK-EXT"))
     config.substitutions.append(("%loadbye", ""))
 else:
diff --git a/polly/docs/ReleaseNotes.rst b/polly/docs/ReleaseNotes.rst
index 68608f059b296..716afca7eef16 100644
--- a/polly/docs/ReleaseNotes.rst
+++ b/polly/docs/ReleaseNotes.rst
@@ -23,5 +23,5 @@ In Polly |version| the following important changes have been incorporated.
    whether Polly is linked into ``opt`` or loaded as a plugin, e.g.
    ``opt -load-pass-plugin=LLVMPolly.so -plugin-arg=Polly,-polly-process-unprofitable``.
    When Polly is linked into ``opt``, the plain ``-polly-*`` options remain
-   accepted.
+   accepted for now.
 
diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp
index a0480d9f936b2..e7ca2c4672479 100644
--- a/polly/lib/Support/RegisterPasses.cpp
+++ b/polly/lib/Support/RegisterPasses.cpp
@@ -692,7 +692,13 @@ void registerPollyPasses(PassBuilder &PB) {
 } // namespace polly
 
 static Error parseArguments(ArrayRef<const char *> Args) {
-  return parsePassPluginCommandLine("Polly", Args);
+  SmallVector<const char *, 0> Argv = {"Polly"};
+  append_range(Argv, Args);
+  std::string Msg;
+  raw_string_ostream OS(Msg);
+  if (!cl::ParseCommandLineOptions(Argv.size(), Argv.data(), "", &OS))
+    return createStringError(StringRef(Msg).trim());
+  return Error::success();
 }
 
 llvm::PassPluginLibraryInfo getPollyPluginInfo() {
diff --git a/polly/test/lit.site.cfg.in b/polly/test/lit.site.cfg.in
index d808c5ff04475..c6163fb806306 100644
--- a/polly/test/lit.site.cfg.in
+++ b/polly/test/lit.site.cfg.in
@@ -27,6 +27,8 @@ for arch in config.targets_to_build.split():
 # directories.
 config.excludes = ['Inputs']
 
+# TODO: Let tests spell out -load-pass-plugin and these options, and remove
+# %loadNPMPolly.
 commonOpts = ''.join(' -plugin-arg=Polly,' + opt for opt in [
     '-polly-process-unprofitable',
     '-polly-remarks-minimal',



More information about the llvm-commits mailing list