Skip to content

Instantly share code, notes, and snippets.

@MaskRay
Created September 20, 2026 21:58
Show Gist options
  • Select an option

  • Save MaskRay/6712e97733a3746f9d88fb4e1ce65aea to your computer and use it in GitHub Desktop.

Select an option

Save MaskRay/6712e97733a3746f9d88fb4e1ce65aea to your computer and use it in GitHub Desktop.
[Option] Declare a library's command line options in TableGen, one struct per library
From 822ab47500b62fac9647f8360b2b9af87ddf8201 Mon Sep 17 00:00:00 2001
From: Fangrui Song <hidden>
Date: Sun, 20 Sep 2026 12:35:19 -0700
Subject: [PATCH] [Option] Declare a library's command line options in
TableGen, one struct per library
RFC: https://discourse.llvm.org/t/91877
A library declares its options in a .td file beside its sources:
def PassesOptions : OptionsStruct; defm RunNewGVN :
BoolField<"enable-newgvn", "0", "Run the NewGVN pass">;
-gen-opt-parser-defs emits struct PassesOptions with a member per
option (OPTIONS_STRUCT_DECL) and its table, Current, Slot, apply()
and parse() (OPTIONS_STRUCT_DEFS). The library's .cpp includes the
latter and defines a RegisterLibraryOptions<PassesOptions>, which
allots the struct's slot in OptionsRegistry and registers its names,
parser, help and reset with cl::. ParseCommandLineOptions indexes the
names at the first parse and hands a matching argument to the
library's table from its own loop, so "--", subcommands and positional
arguments keep cl::'s rules; a plugin loaded by an earlier argument
registers mid-parse. Every option is -help-hidden. A bool is -x or
-no-x rather than cl::opt's -x=<bool>; tests move to the new spelling.
Reads: PassesOptions::Current.X is the process-wide instance cl::
fills; Ctx.getOptions<PassesOptions>() is the copy a tool attached
with Ctx.setOptions(), else Current. LLVMContext embeds the registry.
LLVMPasses' 33 pipeline options move first, public under
include/llvm/Passes since PassBuilder and PipelineTuningOptions take
the struct; LLVMCGData's 13 move as a private home in lib/CGData, its
two extern cl::opts becoming cgdata::thinLTOTwoRounds() and a
CodeGenDataReader::create parameter. llvm/docs/CommandLine.md
describes the recipe.
Aided by Opus 5
---
clang/test/Frontend/optimization-remark.c | 2 +-
cross-project-tests/dtlto/remote-options.test | 4 +-
llvm/docs/CommandLine.md | 43 +++
llvm/include/llvm/ADT/StringExtras.h | 13 +
llvm/include/llvm/CGData/CodeGenData.h | 4 +
llvm/include/llvm/CGData/CodeGenDataReader.h | 15 +-
llvm/include/llvm/CMakeLists.txt | 1 +
llvm/include/llvm/IR/LLVMContext.h | 8 +
llvm/include/llvm/Option/LibraryOptions.h | 118 +++++++
llvm/include/llvm/Option/OptParser.td | 60 ++++
llvm/include/llvm/Option/OptTable.h | 33 +-
llvm/include/llvm/Passes/CMakeLists.txt | 5 +
llvm/include/llvm/Passes/PassBuilder.h | 11 +-
llvm/include/llvm/Passes/PassesOptions.h | 34 ++
llvm/include/llvm/Passes/PassesOptions.td | 108 +++++++
llvm/include/llvm/Support/CommandLine.h | 19 ++
llvm/include/llvm/Support/OptionsRegistry.h | 52 ++++
llvm/include/llvm/Transforms/IPO/Attributor.h | 12 -
llvm/lib/CGData/CGDataOptions.cpp | 15 +
llvm/lib/CGData/CGDataOptions.h | 17 +
llvm/lib/CGData/CGDataOptions.td | 62 ++++
llvm/lib/CGData/CMakeLists.txt | 7 +
llvm/lib/CGData/CodeGenData.cpp | 31 +-
llvm/lib/CGData/CodeGenDataReader.cpp | 32 +-
llvm/lib/CGData/StableFunctionMap.cpp | 56 +---
llvm/lib/LTO/LTO.cpp | 3 +-
llvm/lib/Option/OptTable.cpp | 76 ++++-
llvm/lib/Passes/CMakeLists.txt | 3 +
llvm/lib/Passes/PassBuilder.cpp | 7 +-
llvm/lib/Passes/PassBuilderPipelines.cpp | 292 ++++--------------
llvm/lib/Passes/PassesOptions.cpp | 15 +
llvm/lib/Support/CMakeLists.txt | 1 +
llvm/lib/Support/CommandLine.cpp | 82 ++++-
llvm/lib/Support/OptionsRegistry.cpp | 40 +++
.../CodeGen/AArch64/cgdata-global-hash.ll | 4 +-
.../AArch64/cgdata-merge-gvar-nsconst.ll | 2 +-
.../CodeGen/AArch64/cgdata-merge-gvar-objc.ll | 2 +-
.../AArch64/cgdata-merge-gvar-string.ll | 2 +-
.../CodeGen/AArch64/cgdata-merge-no-params.ll | 4 +-
.../CodeGen/AArch64/cgdata-outlined-name.ll | 4 +-
.../AArch64/cgdata-read-double-outline.ll | 2 +-
.../AArch64/cgdata-read-lto-outline.ll | 2 +-
.../CodeGen/AArch64/cgdata-read-priority.ll | 4 +-
.../cgdata-read-single-outline-suffix.ll | 4 +-
.../AArch64/cgdata-read-single-outline.ll | 2 +-
.../CodeGen/AArch64/cgdata-write-outline.ll | 4 +-
llvm/test/Other/X86/lto-hot-cold-split.ll | 4 +-
llvm/test/Other/new-pm-defaults.ll | 38 +--
llvm/test/Other/new-pm-eager-invalidate.ll | 4 +-
llvm/test/Other/new-pm-lto-defaults.ll | 18 +-
llvm/test/Other/new-pm-pgo-preinline.ll | 2 +-
.../Other/new-pm-thinlto-postlink-defaults.ll | 14 +-
.../new-pm-thinlto-postlink-pgo-defaults.ll | 8 +-
...-pm-thinlto-postlink-samplepgo-defaults.ll | 8 +-
.../Other/new-pm-thinlto-prelink-defaults.ll | 24 +-
.../new-pm-thinlto-prelink-pgo-defaults.ll | 8 +-
...w-pm-thinlto-prelink-samplepgo-defaults.ll | 8 +-
llvm/test/Other/opt-hot-cold-split.ll | 10 +-
.../test/ThinLTO/AArch64/cgdata-merge-read.ll | 8 +-
.../AArch64/cgdata-merge-two-rounds.ll | 4 +-
.../ThinLTO/AArch64/cgdata-merge-write.ll | 4 +-
.../GlobalOpt/disable-globals-aa.ll | 2 +-
.../ML/enable-inline-advisor-printing-ml.ll | 4 +-
llvm/test/Transforms/Inline/ML/fpi-update.ll | 2 +-
llvm/tools/llvm-cgdata/llvm-cgdata.cpp | 8 +-
llvm/unittests/Option/OptionParsingTest.cpp | 38 +++
llvm/unittests/Passes/CMakeLists.txt | 8 +
llvm/unittests/Passes/PassesOptionsTest.cpp | 96 ++++++
llvm/unittests/Support/CMakeLists.txt | 1 +
llvm/unittests/Support/CommandLineTest.cpp | 68 ++++
.../unittests/Support/OptionsRegistryTest.cpp | 53 ++++
llvm/utils/TableGen/OptionParserEmitter.cpp | 177 ++++++++++-
.../llvm/include/llvm/Passes/BUILD.gn | 5 +
.../gn/secondary/llvm/lib/CGData/BUILD.gn | 10 +
.../gn/secondary/llvm/lib/Passes/BUILD.gn | 6 +
.../gn/secondary/llvm/lib/Support/BUILD.gn | 1 +
.../gn/secondary/llvm/unittests/BUILD.gn | 1 +
.../secondary/llvm/unittests/Passes/BUILD.gn | 10 +
.../secondary/llvm/unittests/Support/BUILD.gn | 1 +
.../llvm-project-overlay/llvm/BUILD.bazel | 21 ++
80 files changed, 1514 insertions(+), 477 deletions(-)
create mode 100644 llvm/include/llvm/Option/LibraryOptions.h
create mode 100644 llvm/include/llvm/Passes/CMakeLists.txt
create mode 100644 llvm/include/llvm/Passes/PassesOptions.h
create mode 100644 llvm/include/llvm/Passes/PassesOptions.td
create mode 100644 llvm/include/llvm/Support/OptionsRegistry.h
create mode 100644 llvm/lib/CGData/CGDataOptions.cpp
create mode 100644 llvm/lib/CGData/CGDataOptions.h
create mode 100644 llvm/lib/CGData/CGDataOptions.td
create mode 100644 llvm/lib/Passes/PassesOptions.cpp
create mode 100644 llvm/lib/Support/OptionsRegistry.cpp
create mode 100644 llvm/unittests/Passes/PassesOptionsTest.cpp
create mode 100644 llvm/unittests/Support/OptionsRegistryTest.cpp
create mode 100644 llvm/utils/gn/secondary/llvm/include/llvm/Passes/BUILD.gn
create mode 100644 llvm/utils/gn/secondary/llvm/unittests/Passes/BUILD.gn
diff --git a/clang/test/Frontend/optimization-remark.c b/clang/test/Frontend/optimization-remark.c
index 0cade6ffccfb..d0379f631e18 100644
--- a/clang/test/Frontend/optimization-remark.c
+++ b/clang/test/Frontend/optimization-remark.c
@@ -14,7 +14,7 @@
// RUN: %clang_cc1 %s -Rpass=inline -Rno-pass -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
// RUN: %clang_cc1 %s -Rpass=inline -Rno-everything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
// RUN: %clang_cc1 %s -Rpass=inline -Rno-everything -Reverything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
-// RUN: %clang_cc1 %s -Rpass -Rno-pass -round-trip-args -mllvm -mandatory-inlining-first=false -O1 -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
+// RUN: %clang_cc1 %s -Rpass -Rno-pass -round-trip-args -mllvm -no-mandatory-inlining-first -O1 -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
//
// The inliner for the new PM does not seem to be enabled at O0, but we still
// get the same remarks with at least O1.
diff --git a/cross-project-tests/dtlto/remote-options.test b/cross-project-tests/dtlto/remote-options.test
index ddc9883199c4..5cb72856893d 100644
--- a/cross-project-tests/dtlto/remote-options.test
+++ b/cross-project-tests/dtlto/remote-options.test
@@ -48,11 +48,11 @@ NO-SECTIONS-NOT: "-ffunction-sections"
NO-SECTIONS-NOT: "-fdata-sections"
## Loop interchange.
-RUN: %{lto2-elf} -enable-loopinterchange=true 2>&1 | \
+RUN: %{lto2-elf} -enable-loopinterchange 2>&1 | \
RUN: FileCheck %s --check-prefixes=ARGS,LOOP-INTERCHANGE,ERR
LOOP-INTERCHANGE: "-floop-interchange"
-RUN: %{lto2-elf} -enable-loopinterchange=false 2>&1 | \
+RUN: %{lto2-elf} -no-enable-loopinterchange 2>&1 | \
RUN: FileCheck %s --check-prefixes=ARGS,NO-LOOP-INTERCHANGE,ERR
NO-LOOP-INTERCHANGE-NOT: "-floop-interchange"
diff --git a/llvm/docs/CommandLine.md b/llvm/docs/CommandLine.md
index 2cf37ebc52d4..7ce0bf2d60c1 100644
--- a/llvm/docs/CommandLine.md
+++ b/llvm/docs/CommandLine.md
@@ -1706,3 +1706,46 @@ TODO: complete this section
:::{todo}
TODO: fill in this section
:::
+
+## Declaring a Library's Options in TableGen
+
+A library can declare its options in a `.td` file instead of as `cl::opt`
+globals; `llvm-tblgen -gen-opt-parser-defs` generates a struct with a member
+per option, its parsing table, and its registration with
+`cl::ParseCommandLineOptions` and `-help-hidden`.
+
+```text
+include "llvm/Option/OptParser.td"
+
+def FooOptions : OptionsStruct;
+def FooMode : OptionEnum<"FooMode", [EnumMember<"Fast", "fast">,
+ EnumMember<"Small", "small">]>;
+
+defm Enable : BoolField<"foo-enable", "1", "Enable foo">;
+defm Threshold : ValueField<"foo-threshold", "unsigned", "8", "The threshold">;
+defm Mode : EnumField<"foo-mode", FooMode, "FooMode::Fast", "Foo's mode">;
+```
+
+A `defm` names the member and gives the spelling, type, default and help.
+`BoolField` accepts `-foo-enable` and `-no-foo-enable`; the others accept
+`-name=value` and `-name value`. A member may also be a `double`, a
+`std::string`, a `std::optional<T>` (was the option given) or a
+`std::vector<T>` (every occurrence).
+
+`FooOptions.h` defines `OPTIONS_STRUCT_DECL` and includes `FooOptions.inc`;
+`FooOptions.cpp` includes the header and `llvm/Option/LibraryOptions.h`,
+defines `OPTIONS_STRUCT_DEFS`, includes `FooOptions.inc`, and registers the
+struct with `static opt::RegisterLibraryOptions<FooOptions> R;`. `CMakeLists.txt`
+runs `tablegen(LLVM FooOptions.inc -gen-opt-parser-defs)` and the library
+depends on that target and on `Option`.
+
+Like a `static cl::opt`, an option is private to its library: the files live
+beside the sources, and a knob another library needs is exported through a
+function or a parameter. The struct goes under `include/llvm/` only when
+tools or other libraries are meant to read or set it, as `PassesOptions` is.
+
+`FooOptions::Current` is the instance `cl::ParseCommandLineOptions` fills, so
+`FooOptions::Current.Threshold` replaces a `cl::opt` global.
+`Ctx.getOptions<FooOptions>()` is what an `LLVMContext` reads: the copy a tool
+attached with `Ctx.setOptions(...)`, else `Current`. A tool without `cl::`
+fills a struct with `parse(Args, Rest, Errs)`.
diff --git a/llvm/include/llvm/ADT/StringExtras.h b/llvm/include/llvm/ADT/StringExtras.h
index 71e0c14c977a..5f1b1c5b5a35 100644
--- a/llvm/include/llvm/ADT/StringExtras.h
+++ b/llvm/include/llvm/ADT/StringExtras.h
@@ -293,6 +293,19 @@ template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) {
return !S.getAsInteger(Base, Num);
}
+/// Convert a command line boolean spelling to \p B: "true", "TRUE", "True" or
+/// "1", their false counterparts, or the empty string for true. Returns true
+/// if \p S was one of these.
+inline bool to_bool(StringRef S, bool &B) {
+ if (S == "" || S == "true" || S == "TRUE" || S == "True" || S == "1")
+ B = true;
+ else if (S == "false" || S == "FALSE" || S == "False" || S == "0")
+ B = false;
+ else
+ return false;
+ return true;
+}
+
namespace detail {
template <typename N>
inline bool to_float(const Twine &T, N &Num, N (*StrTo)(const char *, char **)) {
diff --git a/llvm/include/llvm/CGData/CodeGenData.h b/llvm/include/llvm/CGData/CodeGenData.h
index e44497a40824..058198fab7ca 100644
--- a/llvm/include/llvm/CGData/CodeGenData.h
+++ b/llvm/include/llvm/CGData/CodeGenData.h
@@ -187,6 +187,10 @@ inline const StableFunctionMap *getStableFunctionMap() {
inline bool emitCGData() { return CodeGenData::getInstance().emitCGData(); }
+/// Whether ThinLTO runs code generation twice, the first round emitting
+/// codegen data for the second (-codegen-data-thinlto-two-rounds).
+LLVM_ABI bool thinLTOTwoRounds();
+
inline void
publishOutlinedHashTree(std::unique_ptr<OutlinedHashTree> HashTree) {
CodeGenData::getInstance().publishOutlinedHashTree(std::move(HashTree));
diff --git a/llvm/include/llvm/CGData/CodeGenDataReader.h b/llvm/include/llvm/CGData/CodeGenDataReader.h
index a656147a4861..82c1ea74ca08 100644
--- a/llvm/include/llvm/CGData/CodeGenDataReader.h
+++ b/llvm/include/llvm/CGData/CodeGenDataReader.h
@@ -16,7 +16,6 @@
#include "llvm/CGData/CodeGenData.h"
#include "llvm/CGData/OutlinedHashTreeRecord.h"
#include "llvm/CGData/StableFunctionMapRecord.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -51,13 +50,15 @@ public:
/// Factory method to create an appropriately typed reader for the given
/// codegen data file path and file system.
+ /// With \p LazyLoading, an indexed reader deserializes the stable function
+ /// map on demand.
LLVM_ABI static Expected<std::unique_ptr<CodeGenDataReader>>
- create(const Twine &Path, vfs::FileSystem &FS);
+ create(const Twine &Path, vfs::FileSystem &FS, bool LazyLoading = false);
/// Factory method to create an appropriately typed reader for the given
/// memory buffer.
LLVM_ABI static Expected<std::unique_ptr<CodeGenDataReader>>
- create(std::unique_ptr<MemoryBuffer> Buffer);
+ create(std::unique_ptr<MemoryBuffer> Buffer, bool LazyLoading = false);
/// Extract the cgdata embedded in sections from the given object file and
/// merge them into the GlobalOutlineRecord. This is a static helper that
@@ -100,17 +101,17 @@ protected:
Error success() { return error(cgdata_error::success); }
};
-LLVM_ABI extern cl::opt<bool> IndexedCodeGenDataLazyLoading;
-
class LLVM_ABI IndexedCodeGenDataReader : public CodeGenDataReader {
/// The codegen data file contents.
std::unique_ptr<MemoryBuffer> DataBuffer;
/// The header
IndexedCGData::Header Header;
+ bool LazyLoading;
public:
- IndexedCodeGenDataReader(std::unique_ptr<MemoryBuffer> DataBuffer)
- : DataBuffer(std::move(DataBuffer)) {}
+ IndexedCodeGenDataReader(std::unique_ptr<MemoryBuffer> DataBuffer,
+ bool LazyLoading = false)
+ : DataBuffer(std::move(DataBuffer)), LazyLoading(LazyLoading) {}
IndexedCodeGenDataReader(const IndexedCodeGenDataReader &) = delete;
IndexedCodeGenDataReader &
operator=(const IndexedCodeGenDataReader &) = delete;
diff --git a/llvm/include/llvm/CMakeLists.txt b/llvm/include/llvm/CMakeLists.txt
index c66bfda4c1f6..976f9b9e5949 100644
--- a/llvm/include/llvm/CMakeLists.txt
+++ b/llvm/include/llvm/CMakeLists.txt
@@ -14,6 +14,7 @@ configure_file(
add_subdirectory(Analysis)
add_subdirectory(CodeGen)
add_subdirectory(IR)
+add_subdirectory(Passes)
add_subdirectory(Support)
add_subdirectory(Frontend)
add_subdirectory(TargetParser)
diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index ced9b9227538..6b81aee60e0c 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -18,6 +18,7 @@
#include "llvm/IR/DiagnosticHandler.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/OptionsRegistry.h"
#include <cstdint>
#include <memory>
#include <optional>
@@ -353,7 +354,14 @@ public:
/// the global tracker.
LLVM_ABI uint64_t incNextDILocationAtomGroup();
+ /// The command line options of a library, as code working on this context
+ /// reads them; see OptionsRegistry.
+ template <class T> const T &getOptions() const { return Options.get<T>(); }
+ template <class T> T &setOptions(T O) { return Options.set(std::move(O)); }
+
private:
+ OptionsRegistry Options;
+
// Module needs access to the add/removeModule methods.
friend class Module;
diff --git a/llvm/include/llvm/Option/LibraryOptions.h b/llvm/include/llvm/Option/LibraryOptions.h
new file mode 100644
index 000000000000..7d85207bceca
--- /dev/null
+++ b/llvm/include/llvm/Option/LibraryOptions.h
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Support for a library that keeps its command line options in a struct
+// generated from its .td file: conversions from an option's string value to
+// the field types a struct uses, and registration with OptionsRegistry and
+// cl::. A library's .cpp defines OPTIONS_STRUCT_DEFS and includes its .inc
+// after this header.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OPTION_LIBRARYOPTIONS_H
+#define LLVM_OPTION_LIBRARYOPTIONS_H
+
+#include "llvm/ADT/STLForwardCompat.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/OptionsRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+#include <initializer_list>
+#include <optional>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace llvm::opt {
+
+inline bool parseArgValue(StringRef S, bool &V) { return to_bool(S, V); }
+
+inline bool parseArgValue(StringRef S, std::string &V) {
+ V = S.str();
+ return true;
+}
+
+template <class T>
+std::enable_if_t<std::is_integral_v<T> && !std::is_same_v<T, bool>, bool>
+parseArgValue(StringRef S, T &V) {
+ return to_integer(S, V);
+}
+
+inline bool parseArgValue(StringRef S, double &V) { return !S.getAsDouble(V); }
+
+inline bool parseArgValue(StringRef S, float &V) {
+ double D;
+ if (S.getAsDouble(D))
+ return false;
+ V = D;
+ return true;
+}
+
+template <class T> bool parseArgValue(StringRef S, std::optional<T> &V) {
+ return parseArgValue(S, V.emplace());
+}
+
+template <class T> bool parseArgValue(StringRef S, std::vector<T> &V) {
+ return parseArgValue(S, V.emplace_back());
+}
+
+/// Looks \p S up in \p Values, the spellings of an enumeration's values.
+template <class T>
+bool parseEnumValue(
+ StringRef S, T &V,
+ std::initializer_list<std::pair<StringRef, type_identity_t<T>>> Values) {
+ for (const auto &[Name, Value] : Values) {
+ if (S == Name) {
+ V = Value;
+ return true;
+ }
+ }
+ return false;
+}
+
+/// Registers T, an OptionsStruct, with OptionsRegistry and cl::; a library's
+/// .cpp defines a RegisterLibraryOptions<T>. The Joined spelling ValueField
+/// and its siblings declare, "name=", is cl::'s "name".
+template <class T> void registerLibraryOptions() {
+ T::Slot = OptionsRegistry::allocateSlot(&T::Current);
+ cl::registerLibraryOptions(
+ {[](function_ref<void(StringRef)> F) {
+ T::table().forEachOptionName(
+ [&](StringRef Name) { F(Name.rtrim('=')); });
+ },
+ [](ArrayRef<const char *> Argv, unsigned &Index, raw_ostream &Errs) {
+ // A Flag, Joined or Separate option spans at most two arguments.
+ unsigned I = 0;
+ bool Ok = T::table().applyOneArg(
+ Argv.slice(Index).take_front(2), I, Errs,
+ [](const Arg &A) { return T::Current.apply(A); });
+ Index += I;
+ return Ok;
+ },
+ [](raw_ostream &OS, bool ShowHidden) {
+ if (!ShowHidden)
+ return;
+ OS << '\n';
+ T::table().printHelpOptions(OS, ShowHidden);
+ },
+ [] { T::Current = T(); }});
+}
+
+template <class T> struct RegisterLibraryOptions {
+ RegisterLibraryOptions() { registerLibraryOptions<T>(); }
+};
+
+} // namespace llvm::opt
+
+#endif // LLVM_OPTION_LIBRARYOPTIONS_H
diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td
index 7adb2cf6fa5d..2a31080c8d0e 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -98,6 +98,16 @@ class HelpTextVariant<list<OptionVisibility> visibilities, string text> {
string Text = text;
}
+// The spellings of a C++ enumeration's enumerators.
+class EnumMember<string name, string spelling> {
+ string Name = name;
+ string Spelling = spelling;
+}
+class OptionEnum<string name, list<EnumMember> members> {
+ string Name = name;
+ list<EnumMember> Members = members;
+}
+
// Class definition for positional subcommands.
class SubCommand<string name, string helpText, string usage = ""> {
string Name = name;
@@ -136,6 +146,12 @@ class Option<list<string> prefixes, string name, OptionKind kind,
code Denormalizer = "";
list<code> NormalizedValues = ?;
list<SubCommand> SubCommands = subcommands;
+ // With KeyPath, the type of the struct member that stores the option's
+ // value, which a Flag sets to AssignValue.
+ code FieldType = ?;
+ OptionEnum FieldEnum = ?;
+ code AssignMember = ?;
+ code AssignValue = ?;
}
// Helpers for defining options.
@@ -167,6 +183,28 @@ class JoinedAndSeparate<list<string> prefixes, string name,
// Mix-ins for adding optional attributes.
class Alias<Option alias> { Option Alias = alias; }
+// Store the option's value in the struct member `name`.
+class Field<code type, code name, code default = ""> {
+ code FieldType = type;
+ code KeyPath = name;
+ code DefaultValue = default;
+}
+
+class FieldEnum<OptionEnum e> { OptionEnum FieldEnum = e; }
+
+// A Flag that stores `value` in the struct member `name`.
+class Assign<code name, code value> {
+ code AssignMember = name;
+ code AssignValue = value;
+}
+
+// The struct, named after the def, holding every option with a Field;
+// -gen-opt-parser-defs declares it under OPTIONS_STRUCT_DECL and defines it,
+// with its table, parser and registration, under OPTIONS_STRUCT_DEFS.
+class OptionsStruct<string ns = "llvm"> {
+ string Namespace = ns;
+}
+
class AliasArgs<list<string> aliasargs> { list<string> AliasArgs = aliasargs; }
class EnumName<string name> { string EnumName = name; }
class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
@@ -278,4 +316,26 @@ class NormalizedValues<list<code> definitions> { list<code> NormalizedValues = d
def INPUT : Option<[], "<input>", KIND_INPUT>;
def UNKNOWN : Option<[], "<unknown>", KIND_UNKNOWN>;
+// An option stored in the struct member named after the defm: -name=<v> or
+// -name <v>; -name or -no-name; -name=<enumerator> or -name <enumerator>. A
+// std::optional<T> member records whether the option was given; a
+// std::vector<T> member collects every occurrence. Like the developer cl::opts
+// they replace, the options are hidden from -help.
+multiclass ValueField<string name, code type, code default, string help> {
+ def NAME#_EQ : Joined<["-", "--"], name#"=">, HelpText<help>,
+ Flags<[HelpHidden]>, Field<type, NAME, default>;
+ def NAME : Separate<["-", "--"], name>, Alias<!cast<Option>(NAME#"_EQ")>;
+}
+multiclass BoolField<string name, code default, string help> {
+ def NAME : Flag<["-", "--"], name>, HelpText<help>, Flags<[HelpHidden]>,
+ Field<"bool", NAME, default>, Assign<NAME, "true">;
+ def NAME#_no : Flag<["-", "--"], "no-"#name>, Assign<NAME, "false">;
+}
+multiclass EnumField<string name, OptionEnum e, code default, string help> {
+ def NAME#_EQ : Joined<["-", "--"], name#"=">, HelpText<help>,
+ Flags<[HelpHidden]>, Field<e.Name, NAME, default>,
+ FieldEnum<e>;
+ def NAME : Separate<["-", "--"], name>, Alias<!cast<Option>(NAME#"_EQ")>;
+}
+
#endif // LLVM_OPTION_OPTPARSER_TD
diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index a8232e400c22..1d89ccb72be4 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -254,11 +254,10 @@ private:
unsigned &Index) const;
protected:
- OptTable(const Tables &Tables, bool IgnoreCase = false);
-
void setValuesCodeFn(ValuesCodeFnTy Fn) { ValuesCodeFn = Fn; }
public:
+ OptTable(const Tables &Tables, bool IgnoreCase = false);
virtual ~OptTable();
/// Return the string table used for option names.
@@ -508,12 +507,42 @@ public:
unsigned FlagsToInclude, unsigned FlagsToExclude,
bool ShowAllAliases) const;
+ /// Print the option lists of printHelp, without its header.
+ LLVM_ABI void printHelpOptions(raw_ostream &OS, bool ShowHidden) const;
+
+ /// Calls \p F with the name of each option that has a prefix, as spelled
+ /// after it.
+ LLVM_ABI void forEachOptionName(function_ref<void(StringRef)> F) const;
+
+ /// Parses \p Args, calling \p Apply on each option and appending every
+ /// other argument to \p Rest in order; reports a missing value, or a value
+ /// \p Apply rejects, to \p Errs and returns false.
+ LLVM_ABI bool applyArgs(ArrayRef<const char *> Args,
+ SmallVectorImpl<const char *> &Rest,
+ raw_ostream &Errs,
+ function_ref<bool(const Arg &)> Apply) const;
+
+ /// Parses the option at Argv[Index] and any value it takes, advancing
+ /// \p Index past them, and calls \p Apply on it; reports an unknown
+ /// option, a missing value, or a value \p Apply rejects, to \p Errs and
+ /// returns false.
+ LLVM_ABI bool applyOneArg(ArrayRef<const char *> Argv, unsigned &Index,
+ raw_ostream &Errs,
+ function_ref<bool(const Arg &)> Apply) const;
+
private:
+ bool applyOne(const ArgList &AL, unsigned &Index,
+ SmallVectorImpl<const char *> *Rest, raw_ostream &Errs,
+ function_ref<bool(const Arg &)> Apply) const;
void internalPrintHelp(raw_ostream &OS, const char *Usage, const char *Title,
StringRef SubCommand, bool ShowHidden,
bool ShowAllAliases,
std::function<bool(const Info &)> ExcludeOption,
Visibility VisibilityMask) const;
+ void printHelpOptions(raw_ostream &OS, StringRef SubCommand, bool ShowHidden,
+ bool ShowAllAliases,
+ std::function<bool(const Info &)> ExcludeOption,
+ Visibility VisibilityMask) const;
};
} // end namespace opt
diff --git a/llvm/include/llvm/Passes/CMakeLists.txt b/llvm/include/llvm/Passes/CMakeLists.txt
new file mode 100644
index 000000000000..3b40dd982f0c
--- /dev/null
+++ b/llvm/include/llvm/Passes/CMakeLists.txt
@@ -0,0 +1,5 @@
+# -gen-opt-parser-defs is in llvm-tblgen, not llvm-min-tblgen.
+set(LLVM_TABLEGEN_PROJECT "")
+set(LLVM_TARGET_DEFINITIONS PassesOptions.td)
+tablegen(LLVM PassesOptions.inc -gen-opt-parser-defs)
+add_public_tablegen_target(passes_options_gen)
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 879e78fae4bf..1df169f1e5cc 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -36,13 +36,16 @@ class StringRef;
class AAManager;
class TargetMachine;
class ModuleSummaryIndex;
+struct PassesOptions;
/// Tunable parameters for passes in the default pipelines.
class PipelineTuningOptions {
public:
- /// Constructor sets pipeline tuning defaults based on cl::opts. Each option
- /// can be set in the PassBuilder when using a LLVM as a library.
+ /// Constructor sets pipeline tuning defaults based on \p Opts, by default
+ /// PassesOptions::Current. Each option can be set in the PassBuilder when
+ /// using a LLVM as a library.
LLVM_ABI PipelineTuningOptions();
+ LLVM_ABI explicit PipelineTuningOptions(const PassesOptions &Opts);
/// Tuning option to set loop interleaving on/off, set based on opt level.
bool LoopInterleaving;
@@ -117,6 +120,7 @@ class PassBuilder {
std::optional<PGOOptions> PGOOpt;
PassInstrumentationCallbacks *PIC;
IntrusiveRefCntPtr<vfs::FileSystem> FS;
+ const PassesOptions &Opts;
public:
/// A struct to capture parsed pass pipeline names.
@@ -137,7 +141,8 @@ public:
PipelineTuningOptions PTO = PipelineTuningOptions(),
std::optional<PGOOptions> PGOOpt = std::nullopt,
PassInstrumentationCallbacks *PIC = nullptr,
- IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem());
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getRealFileSystem(),
+ const PassesOptions *Opts = nullptr);
/// Cross register the analysis managers through their proxies.
///
diff --git a/llvm/include/llvm/Passes/PassesOptions.h b/llvm/include/llvm/Passes/PassesOptions.h
new file mode 100644
index 000000000000..bbe3c446f8d2
--- /dev/null
+++ b/llvm/include/llvm/Passes/PassesOptions.h
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_PASSES_PASSESOPTIONS_H
+#define LLVM_PASSES_PASSESOPTIONS_H
+
+#include "llvm/Analysis/InlineAdvisor.h"
+
+namespace llvm {
+
+/// The Attributor runs of the default pipelines.
+enum AttributorRunOption {
+ NONE = 0,
+ MODULE = 1 << 0,
+ CGSCC = 1 << 1,
+ MODULE_LIGHT = 1 << 2,
+ CGSCC_LIGHT = 1 << 3,
+
+ FULL = MODULE | CGSCC,
+ LIGHT = MODULE_LIGHT | CGSCC_LIGHT
+};
+
+} // namespace llvm
+
+// struct PassesOptions, from llvm/Passes/PassesOptions.td.
+#define OPTIONS_STRUCT_DECL
+#include "llvm/Passes/PassesOptions.inc"
+
+#endif // LLVM_PASSES_PASSESOPTIONS_H
diff --git a/llvm/include/llvm/Passes/PassesOptions.td b/llvm/include/llvm/Passes/PassesOptions.td
new file mode 100644
index 000000000000..4139a134776e
--- /dev/null
+++ b/llvm/include/llvm/Passes/PassesOptions.td
@@ -0,0 +1,108 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// The command line options of LLVMPasses, stored in struct PassesOptions
+// (llvm/Passes/PassesOptions.h).
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/Option/OptParser.td"
+
+def PassesOptions : OptionsStruct;
+
+// llvm/Analysis/InlineAdvisor.h
+def InliningAdvisorMode : OptionEnum<"InliningAdvisorMode", [
+ EnumMember<"Default", "default">,
+ EnumMember<"Release", "release">,
+ EnumMember<"Development", "development">]>;
+
+// llvm/Passes/PassesOptions.h
+def AttributorRunOption : OptionEnum<"AttributorRunOption", [
+ EnumMember<"NONE", "none">,
+ EnumMember<"MODULE", "module">,
+ EnumMember<"CGSCC", "cgscc">,
+ EnumMember<"MODULE_LIGHT", "module-light">,
+ EnumMember<"CGSCC_LIGHT", "cgscc-light">,
+ EnumMember<"FULL", "full">,
+ EnumMember<"LIGHT", "light">]>;
+
+def pipeline_group : OptionGroup<"pipeline">, HelpText<"PASS PIPELINE OPTIONS">;
+
+let Group = pipeline_group in {
+defm AttributorRun : EnumField<"attributor-enable", AttributorRunOption,
+ "AttributorRunOption::NONE",
+ "Enable the attributor inter-procedural deduction pass">;
+defm DisablePreInliner : BoolField<"disable-preinline", "0",
+ "Disable pre-instrumentation inliner">;
+defm EagerlyInvalidateAnalyses : BoolField<"eagerly-invalidate-analyses", "1",
+ "Eagerly invalidate more analyses in default pipelines">;
+defm EnableCHR : BoolField<"enable-chr", "1",
+ "Enable control height reduction optimization (CHR)">;
+defm EnableConstraintElimination : BoolField<"enable-constraint-elimination",
+ "1", "Enable pass to eliminate conditions based on linear constraints">;
+defm DevirtualizeSpeculatively : BoolField<"enable-devirtualize-speculatively",
+ "0", "Enable speculative devirtualization optimization">;
+defm EnableDFAJumpThreading : BoolField<"enable-dfa-jump-thread", "1",
+ "Enable DFA jump threading">;
+defm EnableGlobalAnalyses : BoolField<"enable-global-analyses", "1",
+ "Enable inter-procedural analyses">;
+defm EnableGVNHoist : BoolField<"enable-gvn-hoist", "0",
+ "Enable the GVN hoisting pass (default = off)">;
+defm EnableGVNSink : BoolField<"enable-gvn-sink", "0",
+ "Enable the GVN sinking pass (default = off)">;
+defm EnableInstrumentor : BoolField<"enable-instrumentor", "0",
+ "Enable the Instrumentor Pass">;
+defm EnableJumpTableToSwitch : BoolField<"enable-jump-table-to-switch", "1",
+ "Enable JumpTableToSwitch pass (default = true)">;
+defm EnableLoopFlatten : BoolField<"enable-loop-flatten", "0",
+ "Enable the LoopFlatten Pass">;
+defm UseLoopVersioningLICM : BoolField<"enable-loop-versioning-licm", "0",
+ "Enable the experimental Loop Versioning LICM pass">;
+defm LoopInterchange : BoolField<"enable-loopinterchange", "1",
+ "Enable the LoopInterchange Pass">;
+defm EnableMatrix : BoolField<"enable-matrix", "0",
+ "Enable lowering of the matrix intrinsics">;
+defm MergeFunctions : BoolField<"enable-merge-functions", "0",
+ "Enable function merging as part of the optimization pipeline">;
+defm EnableMergeICmps : BoolField<"enable-mergeicmps", "1",
+ "Enable MergeICmps pass in the optimization pipeline">;
+defm UseInlineAdvisor : EnumField<"enable-ml-inliner", InliningAdvisorMode,
+ "InliningAdvisorMode::Default",
+ "Enable ML policy for inliner. Currently trained for -Oz only">;
+defm EnableModuleInliner : BoolField<"enable-module-inliner", "0",
+ "Enable module inliner">;
+defm RunNewGVN : BoolField<"enable-newgvn", "0", "Run the NewGVN pass">;
+defm EnablePGOInlineDeferral : BoolField<"enable-npm-pgo-inline-deferral", "1",
+ "Enable inline deferral during PGO">;
+defm RunPartialInlining : BoolField<"enable-partial-inlining", "0",
+ "Run Partial inlining pass">;
+defm EnablePostPGOLoopRotation : BoolField<"enable-post-pgo-loop-rotation", "1",
+ "Run the loop rotation transformation after PGO instrumentation">;
+defm EnableSampledInstr : BoolField<"enable-sampled-instrumentation", "0",
+ "Enable profile instrumentation sampling (default = off)">;
+defm EnableUnrollAndJam : BoolField<"enable-unroll-and-jam", "0",
+ "Enable Unroll And Jam Pass">;
+defm ExtraVectorizerPasses : BoolField<"extra-vectorizer-passes", "0",
+ "Run cleanup optimization passes after vectorization">;
+defm FlattenedProfileUsed : BoolField<"flattened-profile-used", "0",
+ "Indicate the sample profile being used is flattened, i.e., no inline "
+ "hierarchy exists in the profile">;
+defm EnableHotColdSplit : BoolField<"hot-cold-split", "0",
+ "Enable hot-cold splitting pass">;
+defm PerformMandatoryInliningsFirst : BoolField<"mandatory-inlining-first", "0",
+ "Perform mandatory inlinings module-wide, before performing inlining">;
+defm TriggerCrash : BoolField<"opt-pipeline-trigger-crash", "0",
+ "Trigger crash in optimization pipeline">;
+defm PreInlineThreshold : ValueField<"preinline-threshold", "int", "75",
+ "Control the amount of inlining in pre-instrumentation inliner (default = "
+ "75)">;
+defm InstrumentColdFuncOnlyPath
+ : ValueField<"instrument-cold-function-only-path", "std::string", "",
+ "File path for cold function only instrumentation(requires use with --pgo-"
+ "instrument-cold-function-only)">;
+}
diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h
index dd42c4bfb7f4..86c9b3078f52 100644
--- a/llvm/include/llvm/Support/CommandLine.h
+++ b/llvm/include/llvm/Support/CommandLine.h
@@ -49,6 +49,25 @@ class ElementCount;
/// It is intentionally a short name to make qualified usage concise.
namespace cl {
+/// The command line interface of a library whose options live in a struct
+/// rather than in cl::opt globals. ParseCommandLineOptions indexes the names
+/// of the registered libraries, rejecting a name that a cl:: option or another
+/// library declares, and hands each argument spelling one to its library;
+/// --help prints the libraries' options after cl::'s, and
+/// ResetAllOptionOccurrences resets them.
+struct LibraryOptions {
+ /// Calls \p F with each option name, as cl:: spells it: no prefix or '='.
+ void (*ForEachName)(function_ref<void(StringRef)> F);
+ /// Parses the option at Argv[Index], one of the names given to ForEachName,
+ /// and any value that follows it, advancing \p Index past them; reports
+ /// errors to \p Errs and returns false.
+ bool (*ParseOne)(ArrayRef<const char *> Argv, unsigned &Index,
+ raw_ostream &Errs);
+ void (*PrintHelp)(raw_ostream &OS, bool ShowHidden);
+ void (*Reset)();
+};
+LLVM_ABI void registerLibraryOptions(const LibraryOptions &L);
+
//===----------------------------------------------------------------------===//
// Command line option processing entry point.
//
diff --git a/llvm/include/llvm/Support/OptionsRegistry.h b/llvm/include/llvm/Support/OptionsRegistry.h
new file mode 100644
index 000000000000..00daf56f30f2
--- /dev/null
+++ b/llvm/include/llvm/Support/OptionsRegistry.h
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_SUPPORT_OPTIONSREGISTRY_H
+#define LLVM_SUPPORT_OPTIONSREGISTRY_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Compiler.h"
+#include <memory>
+#include <utility>
+
+namespace llvm {
+
+/// The command line options of each library, as code working on a context
+/// (an LLVMContext, say) reads them: the copy a tool attached with set, else
+/// the process-wide instance cl::ParseCommandLineOptions fills. A library's
+/// struct T has static members Current and Slot, from allocateSlot().
+class OptionsRegistry {
+ SmallVector<std::unique_ptr<void, void (*)(void *)>, 4> Slots;
+
+public:
+ LLVM_ABI OptionsRegistry();
+
+ template <class T> const T &get() const {
+ if (LLVM_LIKELY(T::Slot < Slots.size()))
+ return *static_cast<const T *>(Slots[T::Slot].get());
+ return T::Current;
+ }
+ /// Attaches a copy of \p O, which the registry owns, and returns it.
+ template <class T> T &set(T O) {
+ T *Copy = new T(std::move(O));
+ set(T::Slot, Copy, [](void *P) { delete static_cast<T *>(P); });
+ return *Copy;
+ }
+
+ /// Allots a slot to a struct whose process-wide instance is \p Current;
+ /// registries created afterwards start with it in the slot. Called at
+ /// static initialization or when a plugin loads.
+ LLVM_ABI static unsigned allocateSlot(void *Current);
+
+private:
+ LLVM_ABI void set(unsigned Slot, void *O, void (*Delete)(void *));
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_OPTIONSREGISTRY_H
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 066883afafb9..7a0d352c6e54 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -6588,18 +6588,6 @@ struct AADenormalFPMath
LLVM_ABI static const char ID;
};
-/// Run options, used by the pass manager.
-enum AttributorRunOption {
- NONE = 0,
- MODULE = 1 << 0,
- CGSCC = 1 << 1,
- MODULE_LIGHT = 1 << 2,
- CGSCC_LIGHT = 1 << 3,
-
- FULL = MODULE | CGSCC,
- LIGHT = MODULE_LIGHT | CGSCC_LIGHT
-};
-
namespace AA {
/// Helper to avoid creating an AA for IR Attributes that might already be set.
template <Attribute::AttrKind AK, typename AAType = AbstractAttribute>
diff --git a/llvm/lib/CGData/CGDataOptions.cpp b/llvm/lib/CGData/CGDataOptions.cpp
new file mode 100644
index 000000000000..5154719dcb3f
--- /dev/null
+++ b/llvm/lib/CGData/CGDataOptions.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDataOptions.h"
+#include "llvm/Option/LibraryOptions.h"
+
+#define OPTIONS_STRUCT_DEFS
+#include "CGDataOptions.inc"
+
+static llvm::opt::RegisterLibraryOptions<llvm::CGDataOptions> Registration;
diff --git a/llvm/lib/CGData/CGDataOptions.h b/llvm/lib/CGData/CGDataOptions.h
new file mode 100644
index 000000000000..b2430ad000f3
--- /dev/null
+++ b/llvm/lib/CGData/CGDataOptions.h
@@ -0,0 +1,17 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_LIB_CGDATA_CGDATAOPTIONS_H
+#define LLVM_LIB_CGDATA_CGDATAOPTIONS_H
+
+#include <limits>
+
+#define OPTIONS_STRUCT_DECL
+#include "CGDataOptions.inc"
+
+#endif // LLVM_LIB_CGDATA_CGDATAOPTIONS_H
diff --git a/llvm/lib/CGData/CGDataOptions.td b/llvm/lib/CGData/CGDataOptions.td
new file mode 100644
index 000000000000..f0284da2a9b8
--- /dev/null
+++ b/llvm/lib/CGData/CGDataOptions.td
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// The command line options of LLVMCGData, stored in struct CGDataOptions
+// (CGDataOptions.h).
+//
+//===----------------------------------------------------------------------===//
+
+include "llvm/Option/OptParser.td"
+
+def CGDataOptions : OptionsStruct;
+
+defm CodeGenDataGenerate : BoolField<"codegen-data-generate", "0",
+ "Emit CodeGen Data into custom sections">;
+defm CodeGenDataThinLTOTwoRounds : BoolField<"codegen-data-thinlto-two-rounds",
+ "0",
+ "Enable two-round ThinLTO code generation. The first round emits codegen "
+ "data, while the second round uses the emitted codegen data for further "
+ "optimizations.">;
+defm CodeGenDataUsePath : ValueField<"codegen-data-use-path", "std::string", "",
+ "File path to where .cgdata file is read">;
+defm GlobalMergingCallOverhead : ValueField<"global-merging-call-overhead",
+ "double", "1.0",
+ "The overhead cost associated with each function call when merging "
+ "functions.">;
+defm GlobalMergingExtraThreshold : ValueField<"global-merging-extra-threshold",
+ "double", "0.0",
+ "An additional cost threshold that must be exceeded for merging to be "
+ "considered beneficial.">;
+defm GlobalMergingInstOverhead : ValueField<"global-merging-inst-overhead",
+ "double", "1.2",
+ "The overhead cost associated with each instruction when lowering to "
+ "machine instruction.">;
+defm GlobalMergingMaxParams : ValueField<"global-merging-max-params",
+ "unsigned", "std::numeric_limits<unsigned>::max()",
+ "The maximum number of parameters allowed when merging functions.">;
+defm GlobalMergingMinInstrs : ValueField<"global-merging-min-instrs",
+ "unsigned", "1",
+ "The minimum instruction count required when merging functions.">;
+defm GlobalMergingMinMerges : ValueField<"global-merging-min-merges",
+ "unsigned", "2",
+ "Minimum number of similar functions with the same hash required for "
+ "merging.">;
+defm GlobalMergingParamOverhead : ValueField<"global-merging-param-overhead",
+ "double", "2.0",
+ "The overhead cost associated with each parameter when merging functions.">;
+defm GlobalMergingSkipNoParams : BoolField<"global-merging-skip-no-params", "1",
+ "Skip merging functions with no parameters.">;
+defm IndexedCodeGenDataReadFunctionMapNames
+ : BoolField<"indexed-codegen-data-read-function-map-names", "true",
+ "Read function map names in indexed CodeGenData. Can be disabled to save "
+ "memory and time for final consumption of the indexed CodeGenData in "
+ "production.">;
+defm IndexedCodeGenDataLazyLoading
+ : BoolField<"indexed-codegen-data-lazy-loading", "false",
+ "Lazily load indexed CodeGenData. Enable to save memory and time for "
+ "final consumption of the indexed CodeGenData in production.">;
diff --git a/llvm/lib/CGData/CMakeLists.txt b/llvm/lib/CGData/CMakeLists.txt
index 003173139f36..854bd085041c 100644
--- a/llvm/lib/CGData/CMakeLists.txt
+++ b/llvm/lib/CGData/CMakeLists.txt
@@ -1,4 +1,9 @@
+set(LLVM_TARGET_DEFINITIONS CGDataOptions.td)
+tablegen(LLVM CGDataOptions.inc -gen-opt-parser-defs)
+add_public_tablegen_target(CGDataOptionsTableGen)
+
add_llvm_component_library(LLVMCGData
+ CGDataOptions.cpp
CodeGenData.cpp
CodeGenDataReader.cpp
CodeGenDataWriter.cpp
@@ -11,12 +16,14 @@ add_llvm_component_library(LLVMCGData
${LLVM_MAIN_INCLUDE_DIR}/llvm/CGData
DEPENDS
+ CGDataOptionsTableGen
intrinsics_gen
LINK_COMPONENTS
BitReader
BitWriter
Core
+ Option
Support
Object
)
diff --git a/llvm/lib/CGData/CodeGenData.cpp b/llvm/lib/CGData/CodeGenData.cpp
index 7900dc7653c0..2711a852f774 100644
--- a/llvm/lib/CGData/CodeGenData.cpp
+++ b/llvm/lib/CGData/CodeGenData.cpp
@@ -11,13 +11,13 @@
//
//===----------------------------------------------------------------------===//
+#include "CGDataOptions.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/CGData/CodeGenDataReader.h"
#include "llvm/CGData/OutlinedHashTreeRecord.h"
#include "llvm/CGData/StableFunctionMapRecord.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Caching.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/WithColor.h"
#define DEBUG_TYPE "cg-data"
@@ -25,21 +25,6 @@
using namespace llvm;
using namespace cgdata;
-static cl::opt<bool>
- CodeGenDataGenerate("codegen-data-generate", cl::init(false), cl::Hidden,
- cl::desc("Emit CodeGen Data into custom sections"));
-static cl::opt<std::string>
- CodeGenDataUsePath("codegen-data-use-path", cl::init(""), cl::Hidden,
- cl::desc("File path to where .cgdata file is read"));
-
-namespace llvm {
-cl::opt<bool> CodeGenDataThinLTOTwoRounds(
- "codegen-data-thinlto-two-rounds", cl::init(false), cl::Hidden,
- cl::desc("Enable two-round ThinLTO code generation. The first round "
- "emits codegen data, while the second round uses the emitted "
- "codegen data for further optimizations."));
-} // end namespace llvm
-
static std::string getCGDataErrString(cgdata_error Err,
const std::string &ErrMsg = "") {
std::string Msg;
@@ -141,6 +126,10 @@ std::string getCodeGenDataSectionName(CGDataSectKind CGSK,
return SectName;
}
+bool cgdata::thinLTOTwoRounds() {
+ return CGDataOptions::Current.CodeGenDataThinLTOTwoRounds;
+}
+
std::unique_ptr<CodeGenData> CodeGenData::Instance = nullptr;
std::once_flag CodeGenData::OnceFlag;
@@ -148,17 +137,19 @@ CodeGenData &CodeGenData::getInstance() {
std::call_once(CodeGenData::OnceFlag, []() {
Instance = std::unique_ptr<CodeGenData>(new CodeGenData());
- if (CodeGenDataGenerate || CodeGenDataThinLTOTwoRounds)
+ const CGDataOptions &Opts = CGDataOptions::Current;
+ if (Opts.CodeGenDataGenerate || Opts.CodeGenDataThinLTOTwoRounds)
Instance->EmitCGData = true;
- else if (!CodeGenDataUsePath.empty()) {
+ else if (!Opts.CodeGenDataUsePath.empty()) {
// Initialize the global CGData if the input file name is given.
// We do not error-out when failing to parse the input file.
// Instead, just emit an warning message and fall back as if no CGData
// were available.
auto FS = vfs::getRealFileSystem();
- auto ReaderOrErr = CodeGenDataReader::create(CodeGenDataUsePath, *FS);
+ auto ReaderOrErr = CodeGenDataReader::create(
+ Opts.CodeGenDataUsePath, *FS, Opts.IndexedCodeGenDataLazyLoading);
if (Error E = ReaderOrErr.takeError()) {
- warn(std::move(E), CodeGenDataUsePath);
+ warn(std::move(E), Opts.CodeGenDataUsePath);
return;
}
// Publish each CGData based on the data type in the header.
diff --git a/llvm/lib/CGData/CodeGenDataReader.cpp b/llvm/lib/CGData/CodeGenDataReader.cpp
index aeb4a4d0d4b9..d2c00c1d706e 100644
--- a/llvm/lib/CGData/CodeGenDataReader.cpp
+++ b/llvm/lib/CGData/CodeGenDataReader.cpp
@@ -11,29 +11,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/CGData/CodeGenDataReader.h"
+#include "CGDataOptions.h"
#include "llvm/CGData/OutlinedHashTreeRecord.h"
#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#define DEBUG_TYPE "cg-data-reader"
using namespace llvm;
-static cl::opt<bool> IndexedCodeGenDataReadFunctionMapNames(
- "indexed-codegen-data-read-function-map-names", cl::init(true), cl::Hidden,
- cl::desc("Read function map names in indexed CodeGenData. Can be "
- "disabled to save memory and time for final consumption of the "
- "indexed CodeGenData in production."));
-
-namespace llvm {
-
-cl::opt<bool> IndexedCodeGenDataLazyLoading(
- "indexed-codegen-data-lazy-loading", cl::init(false), cl::Hidden,
- cl::desc(
- "Lazily load indexed CodeGenData. Enable to save memory and time "
- "for final consumption of the indexed CodeGenData in production."));
-
static Expected<std::unique_ptr<MemoryBuffer>>
setupMemoryBuffer(const Twine &Filename, vfs::FileSystem &FS) {
auto BufferOrErr = Filename.str() == "-" ? MemoryBuffer::getSTDIN()
@@ -123,8 +109,8 @@ Error IndexedCodeGenDataReader::read() {
if (Ptr >= End)
return error(cgdata_error::eof);
FunctionMapRecord.setReadStableFunctionMapNames(
- IndexedCodeGenDataReadFunctionMapNames);
- if (IndexedCodeGenDataLazyLoading)
+ CGDataOptions::Current.IndexedCodeGenDataReadFunctionMapNames);
+ if (LazyLoading)
FunctionMapRecord.lazyDeserialize(std::move(SharedDataBuffer),
Header.StableFunctionMapOffset);
else
@@ -135,23 +121,26 @@ Error IndexedCodeGenDataReader::read() {
}
Expected<std::unique_ptr<CodeGenDataReader>>
-CodeGenDataReader::create(const Twine &Path, vfs::FileSystem &FS) {
+CodeGenDataReader::create(const Twine &Path, vfs::FileSystem &FS,
+ bool LazyLoading) {
// Set up the buffer to read.
auto BufferOrError = setupMemoryBuffer(Path, FS);
if (Error E = BufferOrError.takeError())
return std::move(E);
- return CodeGenDataReader::create(std::move(BufferOrError.get()));
+ return CodeGenDataReader::create(std::move(BufferOrError.get()), LazyLoading);
}
Expected<std::unique_ptr<CodeGenDataReader>>
-CodeGenDataReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
+CodeGenDataReader::create(std::unique_ptr<MemoryBuffer> Buffer,
+ bool LazyLoading) {
if (Buffer->getBufferSize() == 0)
return make_error<CGDataError>(cgdata_error::empty_cgdata);
std::unique_ptr<CodeGenDataReader> Reader;
// Create the reader.
if (IndexedCodeGenDataReader::hasFormat(*Buffer))
- Reader = std::make_unique<IndexedCodeGenDataReader>(std::move(Buffer));
+ Reader = std::make_unique<IndexedCodeGenDataReader>(std::move(Buffer),
+ LazyLoading);
else if (TextCodeGenDataReader::hasFormat(*Buffer))
Reader = std::make_unique<TextCodeGenDataReader>(std::move(Buffer));
else
@@ -220,4 +209,3 @@ Error TextCodeGenDataReader::read() {
return Error::success();
}
-} // end namespace llvm
diff --git a/llvm/lib/CGData/StableFunctionMap.cpp b/llvm/lib/CGData/StableFunctionMap.cpp
index d0fae3a9d32f..226f80406cfa 100644
--- a/llvm/lib/CGData/StableFunctionMap.cpp
+++ b/llvm/lib/CGData/StableFunctionMap.cpp
@@ -14,53 +14,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/CGData/StableFunctionMap.h"
+#include "CGDataOptions.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CGData/StableFunctionMapRecord.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "stable-function-map"
using namespace llvm;
-static cl::opt<unsigned>
- GlobalMergingMinMerges("global-merging-min-merges",
- cl::desc("Minimum number of similar functions with "
- "the same hash required for merging."),
- cl::init(2), cl::Hidden);
-static cl::opt<unsigned> GlobalMergingMinInstrs(
- "global-merging-min-instrs",
- cl::desc("The minimum instruction count required when merging functions."),
- cl::init(1), cl::Hidden);
-static cl::opt<unsigned> GlobalMergingMaxParams(
- "global-merging-max-params",
- cl::desc(
- "The maximum number of parameters allowed when merging functions."),
- cl::init(std::numeric_limits<unsigned>::max()), cl::Hidden);
-static cl::opt<bool> GlobalMergingSkipNoParams(
- "global-merging-skip-no-params",
- cl::desc("Skip merging functions with no parameters."), cl::init(true),
- cl::Hidden);
-static cl::opt<double> GlobalMergingInstOverhead(
- "global-merging-inst-overhead",
- cl::desc("The overhead cost associated with each instruction when lowering "
- "to machine instruction."),
- cl::init(1.2), cl::Hidden);
-static cl::opt<double> GlobalMergingParamOverhead(
- "global-merging-param-overhead",
- cl::desc("The overhead cost associated with each parameter when merging "
- "functions."),
- cl::init(2.0), cl::Hidden);
-static cl::opt<double>
- GlobalMergingCallOverhead("global-merging-call-overhead",
- cl::desc("The overhead cost associated with each "
- "function call when merging functions."),
- cl::init(1.0), cl::Hidden);
-static cl::opt<double> GlobalMergingExtraThreshold(
- "global-merging-extra-threshold",
- cl::desc("An additional cost threshold that must be exceeded for merging "
- "to be considered beneficial."),
- cl::init(0.0), cl::Hidden);
unsigned StableFunctionMap::getIdOrCreateForName(StringRef Name) {
auto It = NameToId.find(Name);
@@ -201,12 +163,13 @@ removeIdenticalIndexPair(StableFunctionMap::StableFunctionEntries &SFS) {
}
static bool isProfitable(const StableFunctionMap::StableFunctionEntries &SFS) {
+ const CGDataOptions &Opts = CGDataOptions::Current;
unsigned StableFunctionCount = SFS.size();
- if (StableFunctionCount < GlobalMergingMinMerges)
+ if (StableFunctionCount < Opts.GlobalMergingMinMerges)
return false;
unsigned InstCount = SFS[0]->InstCount;
- if (InstCount < GlobalMergingMinInstrs)
+ if (InstCount < Opts.GlobalMergingMinInstrs)
return false;
double Cost = 0.0;
@@ -216,21 +179,22 @@ static bool isProfitable(const StableFunctionMap::StableFunctionEntries &SFS) {
for (auto &[IndexPair, Hash] : *SF->IndexOperandHashMap)
UniqueHashVals.insert(Hash);
unsigned ParamCount = UniqueHashVals.size();
- if (ParamCount > GlobalMergingMaxParams)
+ if (ParamCount > Opts.GlobalMergingMaxParams)
return false;
// Theoretically, if ParamCount is 0, it results in identical code folding
// (ICF), which we can skip merging here since the linker already handles
// ICF. This pass would otherwise introduce unnecessary thunks that are
// merely direct jumps. However, enabling this could be beneficial depending
// on downstream passes, so we provide an option for it.
- if (GlobalMergingSkipNoParams && ParamCount == 0)
+ if (Opts.GlobalMergingSkipNoParams && ParamCount == 0)
return false;
- Cost += ParamCount * GlobalMergingParamOverhead + GlobalMergingCallOverhead;
+ Cost += ParamCount * Opts.GlobalMergingParamOverhead +
+ Opts.GlobalMergingCallOverhead;
}
- Cost += GlobalMergingExtraThreshold;
+ Cost += Opts.GlobalMergingExtraThreshold;
double Benefit =
- InstCount * (StableFunctionCount - 1) * GlobalMergingInstOverhead;
+ InstCount * (StableFunctionCount - 1) * Opts.GlobalMergingInstOverhead;
bool Result = Benefit > Cost;
LLVM_DEBUG(dbgs() << "isProfitable: Hash = " << SFS[0]->Hash << ", "
<< "StableFunctionCount = " << StableFunctionCount
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4594c52fb5f6..5f6edf88ce3e 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -108,7 +108,6 @@ static cl::opt<bool>
DumpThinCGSCCs("dump-thin-cg-sccs", cl::init(false), cl::Hidden,
cl::desc("Dump the SCCs in the ThinLTO index's callgraph"));
namespace llvm {
-extern cl::opt<bool> CodeGenDataThinLTOTwoRounds;
extern cl::opt<bool> ForceImportAll;
extern cl::opt<bool> AlwaysRenamePromotedLocals;
} // end namespace llvm
@@ -2297,7 +2296,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
return BackendProcess->wait();
};
- if (!CodeGenDataThinLTOTwoRounds) {
+ if (!cgdata::thinLTOTwoRounds()) {
std::unique_ptr<ThinBackendProc> BackendProc =
ThinLTO.Backend(Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
AddStream, Cache, BitcodeLibFuncs);
diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp
index 5725639eeb77..be9641426d3a 100644
--- a/llvm/lib/Option/OptTable.cpp
+++ b/llvm/lib/Option/OptTable.cpp
@@ -17,6 +17,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/OptionStrCmp.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -746,10 +747,6 @@ void OptTable::internalPrintHelp(
Visibility VisibilityMask) const {
OS << "OVERVIEW: " << Title << "\n\n";
- // Render help text into a map of group-name to a list of (option, help)
- // pairs.
- std::map<StringRef, std::vector<OptionInfo>> GroupedOptionHelp;
-
auto ActiveSubCommand = llvm::find_if(
SubCommands, [&](const auto &C) { return SubCommand == C.Name; });
if (!SubCommand.empty()) {
@@ -767,6 +764,77 @@ void OptTable::internalPrintHelp(
OS << "\n";
}
}
+ printHelpOptions(OS, SubCommand, ShowHidden, ShowAllAliases,
+ std::move(ExcludeOption), VisibilityMask);
+}
+
+void OptTable::printHelpOptions(raw_ostream &OS, bool ShowHidden) const {
+ printHelpOptions(
+ OS, {}, ShowHidden, /*ShowAllAliases=*/false,
+ [](const Info &) { return false; }, Visibility());
+}
+
+void OptTable::forEachOptionName(function_ref<void(StringRef)> F) const {
+ for (const Info &I : OptionInfos.drop_front(FirstSearchableIndex))
+ if (!I.hasNoPrefix())
+ F(I.getName(StrTable, PrefixesTable));
+}
+
+// Rest takes an input or unknown argument; without it, one is an error.
+bool OptTable::applyOne(const ArgList &AL, unsigned &Index,
+ SmallVectorImpl<const char *> *Rest, raw_ostream &Errs,
+ function_ref<bool(const Arg &)> Apply) const {
+ const char *Str = AL.getArgString(Index);
+ std::unique_ptr<Arg> A = ParseOneArg(AL, Index);
+ if (!A) {
+ WithColor::error(Errs) << "option '" << Str << "' requires an argument\n";
+ return false;
+ }
+ Option::OptionClass Kind = A->getOption().getKind();
+ if (Kind == Option::InputClass || Kind == Option::UnknownClass) {
+ if (Rest) {
+ Rest->push_back(Str);
+ return true;
+ }
+ WithColor::error(Errs) << "unknown argument '" << Str << "'\n";
+ return false;
+ }
+ if (Apply(*A))
+ return true;
+ WithColor::error(Errs) << "invalid value '" << A->getValue() << "' in '"
+ << A->getAsString(AL) << "'\n";
+ return false;
+}
+
+bool OptTable::applyArgs(ArrayRef<const char *> Args,
+ SmallVectorImpl<const char *> &Rest, raw_ostream &Errs,
+ function_ref<bool(const Arg &)> Apply) const {
+ InputArgList AL(Args.begin(), Args.end());
+ for (unsigned I = 0, E = Args.size(); I != E;)
+ if (!applyOne(AL, I, &Rest, Errs, Apply))
+ return false;
+ return true;
+}
+
+bool OptTable::applyOneArg(ArrayRef<const char *> Argv, unsigned &Index,
+ raw_ostream &Errs,
+ function_ref<bool(const Arg &)> Apply) const {
+ InputArgList AL(Argv.begin() + Index, Argv.end());
+ unsigned I = 0;
+ bool Ok = applyOne(AL, I, nullptr, Errs, Apply);
+ Index += I;
+ return Ok;
+}
+
+void OptTable::printHelpOptions(raw_ostream &OS, StringRef SubCommand,
+ bool ShowHidden, bool ShowAllAliases,
+ std::function<bool(const Info &)> ExcludeOption,
+ Visibility VisibilityMask) const {
+ // Render help text into a map of group-name to a list of (option, help)
+ // pairs.
+ std::map<StringRef, std::vector<OptionInfo>> GroupedOptionHelp;
+ auto ActiveSubCommand = llvm::find_if(
+ SubCommands, [&](const auto &C) { return SubCommand == C.Name; });
auto DoesOptionBelongToSubcommand = [&](const Info &CandidateInfo) {
// Retrieve the SubCommandIDs registered to the given current CandidateInfo
diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt
index 6a966d582b63..da1fa8a173c6 100644
--- a/llvm/lib/Passes/CMakeLists.txt
+++ b/llvm/lib/Passes/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_component_library(LLVMPasses
PassBuilder.cpp
PassBuilderBindings.cpp
PassBuilderPipelines.cpp
+ PassesOptions.cpp
RunCodeGen.cpp
StandardInstrumentations.cpp
TriggerCrashPasses.cpp
@@ -13,6 +14,7 @@ add_llvm_component_library(LLVMPasses
DEPENDS
intrinsics_gen
+ passes_options_gen
LINK_COMPONENTS
AggressiveInstCombine
@@ -28,6 +30,7 @@ add_llvm_component_library(LLVMPasses
InstCombine
IRPrinter
ObjCARC
+ Option
Scalar
Support
Target
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 858c76706427..7ffe999df819 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -216,6 +216,7 @@
#include "llvm/IR/Verifier.h"
#include "llvm/IRPrinter/IRPrintingPasses.h"
#include "llvm/Passes/OptimizationLevel.h"
+#include "llvm/Passes/PassesOptions.h"
#include "llvm/Passes/TriggerCrashPasses.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
@@ -590,8 +591,10 @@ static Expected<OptimizationLevel> parseOptLevelParam(StringRef S) {
PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
std::optional<PGOOptions> PGOOpt,
PassInstrumentationCallbacks *PIC,
- IntrusiveRefCntPtr<vfs::FileSystem> FS)
- : TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC), FS(std::move(FS)) {
+ IntrusiveRefCntPtr<vfs::FileSystem> FS,
+ const PassesOptions *Opts)
+ : TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC), FS(std::move(FS)),
+ Opts(Opts ? *Opts : PassesOptions::Current) {
if (TM)
TM->registerPassBuilderCallbacks(*this);
if (PIC) {
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 8e532b5980e7..25053654d793 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -30,6 +30,7 @@
#include "llvm/Pass.h"
#include "llvm/Passes/OptimizationLevel.h"
#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/PassesOptions.h"
#include "llvm/Passes/TriggerCrashPasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
@@ -159,192 +160,35 @@ using namespace llvm;
namespace llvm {
-static cl::opt<InliningAdvisorMode> UseInlineAdvisor(
- "enable-ml-inliner", cl::init(InliningAdvisorMode::Default), cl::Hidden,
- cl::desc("Enable ML policy for inliner. Currently trained for -Oz only"),
- cl::values(clEnumValN(InliningAdvisorMode::Default, "default",
- "Heuristics-based inliner version"),
- clEnumValN(InliningAdvisorMode::Development, "development",
- "Use development mode (runtime-loadable model)"),
- clEnumValN(InliningAdvisorMode::Release, "release",
- "Use release mode (AOT-compiled model)")));
-
-/// Flag to enable inline deferral during PGO.
-static cl::opt<bool>
- EnablePGOInlineDeferral("enable-npm-pgo-inline-deferral", cl::init(true),
- cl::Hidden,
- cl::desc("Enable inline deferral during PGO"));
-
-static cl::opt<bool> EnableModuleInliner("enable-module-inliner",
- cl::init(false), cl::Hidden,
- cl::desc("Enable module inliner"));
-
-static cl::opt<bool> PerformMandatoryInliningsFirst(
- "mandatory-inlining-first", cl::init(false), cl::Hidden,
- cl::desc("Perform mandatory inlinings module-wide, before performing "
- "inlining"));
-
-static cl::opt<bool> EnableEagerlyInvalidateAnalyses(
- "eagerly-invalidate-analyses", cl::init(true), cl::Hidden,
- cl::desc("Eagerly invalidate more analyses in default pipelines"));
-
-static cl::opt<bool> EnableMergeFunctions(
- "enable-merge-functions", cl::init(false), cl::Hidden,
- cl::desc("Enable function merging as part of the optimization pipeline"));
-
-static cl::opt<bool> EnablePostPGOLoopRotation(
- "enable-post-pgo-loop-rotation", cl::init(true), cl::Hidden,
- cl::desc("Run the loop rotation transformation after PGO instrumentation"));
-
-static cl::opt<bool>
- TriggerCrash("opt-pipeline-trigger-crash", cl::init(false), cl::Hidden,
- cl::desc("Trigger crash in optimization pipeline"));
-
-static cl::opt<bool> EnableGlobalAnalyses(
- "enable-global-analyses", cl::init(true), cl::Hidden,
- cl::desc("Enable inter-procedural analyses"));
-
-static cl::opt<bool> RunPartialInlining("enable-partial-inlining",
- cl::init(false), cl::Hidden,
- cl::desc("Run Partial inlining pass"));
-
-static cl::opt<bool> ExtraVectorizerPasses(
- "extra-vectorizer-passes", cl::init(false), cl::Hidden,
- cl::desc("Run cleanup optimization passes after vectorization"));
-
-static cl::opt<bool> RunNewGVN("enable-newgvn", cl::init(false), cl::Hidden,
- cl::desc("Run the NewGVN pass"));
-
-static cl::opt<bool>
- EnableLoopInterchange("enable-loopinterchange", cl::init(true), cl::Hidden,
- cl::desc("Enable the LoopInterchange Pass"));
-
-static cl::opt<bool> EnableUnrollAndJam("enable-unroll-and-jam",
- cl::init(false), cl::Hidden,
- cl::desc("Enable Unroll And Jam Pass"));
-
-static cl::opt<bool> EnableLoopFlatten("enable-loop-flatten", cl::init(false),
- cl::Hidden,
- cl::desc("Enable the LoopFlatten Pass"));
-
-static cl::opt<bool>
- EnableInstrumentor("enable-instrumentor", cl::init(false), cl::Hidden,
- cl::desc("Enable the Instrumentor Pass"));
-
-static cl::opt<bool>
- EnableDFAJumpThreading("enable-dfa-jump-thread",
- cl::desc("Enable DFA jump threading"),
- cl::init(true), cl::Hidden);
-
-static cl::opt<bool>
- EnableHotColdSplit("hot-cold-split",
- cl::desc("Enable hot-cold splitting pass"));
-
-static cl::opt<bool>
- DisablePreInliner("disable-preinline", cl::init(false), cl::Hidden,
- cl::desc("Disable pre-instrumentation inliner"));
-
-static cl::opt<int> PreInlineThreshold(
- "preinline-threshold", cl::Hidden, cl::init(75),
- cl::desc("Control the amount of inlining in pre-instrumentation inliner "
- "(default = 75)"));
-
-static cl::opt<bool>
- EnableGVNHoist("enable-gvn-hoist",
- cl::desc("Enable the GVN hoisting pass (default = off)"));
-
-static cl::opt<bool>
- EnableGVNSink("enable-gvn-sink",
- cl::desc("Enable the GVN sinking pass (default = off)"));
-
-static cl::opt<bool> EnableJumpTableToSwitch(
- "enable-jump-table-to-switch", cl::init(true),
- cl::desc("Enable JumpTableToSwitch pass (default = true)"));
-
// This option is used in simplifying testing SampleFDO optimizations for
// profile loading.
-static cl::opt<bool>
- EnableCHR("enable-chr", cl::init(true), cl::Hidden,
- cl::desc("Enable control height reduction optimization (CHR)"));
-
-static cl::opt<bool> FlattenedProfileUsed(
- "flattened-profile-used", cl::init(false), cl::Hidden,
- cl::desc("Indicate the sample profile being used is flattened, i.e., "
- "no inline hierarchy exists in the profile"));
-
-static cl::opt<bool>
- EnableMatrix("enable-matrix", cl::init(false), cl::Hidden,
- cl::desc("Enable lowering of the matrix intrinsics"));
-
-static cl::opt<bool> EnableMergeICmps(
- "enable-mergeicmps", cl::init(true), cl::Hidden,
- cl::desc("Enable MergeICmps pass in the optimization pipeline"));
-
-static cl::opt<bool> EnableConstraintElimination(
- "enable-constraint-elimination", cl::init(true), cl::Hidden,
- cl::desc(
- "Enable pass to eliminate conditions based on linear constraints"));
-
-static cl::opt<AttributorRunOption> AttributorRun(
- "attributor-enable", cl::Hidden, cl::init(AttributorRunOption::NONE),
- cl::desc("Enable the attributor inter-procedural deduction pass"),
- cl::values(clEnumValN(AttributorRunOption::FULL, "full",
- "enable all full attributor runs"),
- clEnumValN(AttributorRunOption::LIGHT, "light",
- "enable all attributor-light runs"),
- clEnumValN(AttributorRunOption::MODULE, "module",
- "enable module-wide attributor runs"),
- clEnumValN(AttributorRunOption::MODULE_LIGHT, "module-light",
- "enable module-wide attributor-light runs"),
- clEnumValN(AttributorRunOption::CGSCC, "cgscc",
- "enable call graph SCC attributor runs"),
- clEnumValN(AttributorRunOption::CGSCC_LIGHT, "cgscc-light",
- "enable call graph SCC attributor-light runs"),
- clEnumValN(AttributorRunOption::NONE, "none",
- "disable attributor runs")));
-
-static cl::opt<bool> EnableSampledInstr(
- "enable-sampled-instrumentation", cl::init(false), cl::Hidden,
- cl::desc("Enable profile instrumentation sampling (default = off)"));
-static cl::opt<bool> UseLoopVersioningLICM(
- "enable-loop-versioning-licm", cl::init(false), cl::Hidden,
- cl::desc("Enable the experimental Loop Versioning LICM pass"));
-
-static cl::opt<std::string> InstrumentColdFuncOnlyPath(
- "instrument-cold-function-only-path", cl::init(""),
- cl::desc("File path for cold function only instrumentation(requires use "
- "with --pgo-instrument-cold-function-only)"),
- cl::Hidden);
-
// TODO: There is a similar flag in WPD pass, we should consolidate them by
// parsing the option only once in PassBuilder and share it across both places.
-static cl::opt<bool> EnableDevirtualizeSpeculatively(
- "enable-devirtualize-speculatively",
- cl::desc("Enable speculative devirtualization optimization"),
- cl::init(false));
-
extern cl::opt<std::string> UseCtxProfile;
extern cl::opt<bool> PGOInstrumentColdFunctionOnly;
extern cl::opt<bool> EnableMemProfContextDisambiguation;
} // namespace llvm
-PipelineTuningOptions::PipelineTuningOptions() {
+PipelineTuningOptions::PipelineTuningOptions()
+ : PipelineTuningOptions(PassesOptions::Current) {}
+
+PipelineTuningOptions::PipelineTuningOptions(const PassesOptions &Opts) {
LoopInterleaving = true;
LoopVectorization = true;
SLPVectorization = false;
LoopUnrolling = true;
- LoopInterchange = EnableLoopInterchange;
+ LoopInterchange = Opts.LoopInterchange;
LoopFusion = false;
ForgetAllSCEVInLoopUnroll = ForgetSCEVInLoopUnroll;
LicmMssaOptCap = SetLicmMssaOptCap;
LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap;
CallGraphProfile = true;
UnifiedLTO = false;
- MergeFunctions = EnableMergeFunctions;
+ MergeFunctions = Opts.MergeFunctions;
InlinerThreshold = -1;
- EagerlyInvalidateAnalyses = EnableEagerlyInvalidateAnalyses;
- DevirtualizeSpeculatively = EnableDevirtualizeSpeculatively;
+ EagerlyInvalidateAnalyses = Opts.EagerlyInvalidateAnalyses;
+ DevirtualizeSpeculatively = Opts.DevirtualizeSpeculatively;
}
namespace llvm {
@@ -556,7 +400,7 @@ PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level,
LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap,
/*AllowSpeculation=*/true));
LPM1.addPass(SimpleLoopUnswitchPass());
- if (EnableLoopFlatten)
+ if (Opts.EnableLoopFlatten)
LPM1.addPass(LoopFlattenPass());
LPM2.addPass(LoopIdiomRecognizePass());
@@ -651,11 +495,11 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
FPM.addPass(AssumeSimplifyPass());
// Hoisting of scalars and load expressions.
- if (EnableGVNHoist)
+ if (Opts.EnableGVNHoist)
FPM.addPass(GVNHoistPass());
// Global value numbering based sinking.
- if (EnableGVNSink) {
+ if (Opts.EnableGVNSink) {
FPM.addPass(GVNSinkPass());
FPM.addPass(
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
@@ -669,7 +513,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
FPM.addPass(CorrelatedValuePropagationPass());
// Jump table to switch conversion.
- if (EnableJumpTableToSwitch)
+ if (Opts.EnableJumpTableToSwitch)
FPM.addPass(JumpTableToSwitchPass(/*InLTO=*/isLTOPostLink(Phase)));
FPM.addPass(
@@ -695,7 +539,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
// minimal multiplication trees.
FPM.addPass(ReassociatePass());
- if (EnableConstraintElimination)
+ if (Opts.EnableConstraintElimination)
FPM.addPass(ConstraintEliminationPass());
// Add the primary loop simplification pipeline.
@@ -731,7 +575,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
/*AllowSpeculation=*/true));
LPM1.addPass(
SimpleLoopUnswitchPass(/* NonTrivial */ Level == OptimizationLevel::O3));
- if (EnableLoopFlatten)
+ if (Opts.EnableLoopFlatten)
LPM1.addPass(LoopFlattenPass());
LPM2.addPass(LoopIdiomRecognizePass());
@@ -781,7 +625,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
// Eliminate redundancies.
FPM.addPass(MergedLoadStoreMotionPass());
- if (RunNewGVN)
+ if (Opts.RunNewGVN)
FPM.addPass(NewGVNPass());
else
FPM.addPass(GVNPass());
@@ -803,7 +647,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
// Re-consider control flow based optimizations after redundancy elimination,
// redo DCE, etc.
- if (EnableDFAJumpThreading)
+ if (Opts.EnableDFAJumpThreading)
FPM.addPass(DFAJumpThreadingPass());
FPM.addPass(JumpThreadingPass());
@@ -850,18 +694,18 @@ void PassBuilder::addPreInlinerPasses(ModulePassManager &MPM,
OptimizationLevel Level,
ThinOrFullLTOPhase LTOPhase) {
assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!");
- if (DisablePreInliner)
+ if (Opts.DisablePreInliner)
return;
InlineParams IP;
- IP.DefaultThreshold = PreInlineThreshold;
+ IP.DefaultThreshold = Opts.PreInlineThreshold;
// FIXME: The hint threshold has the same value used by the regular inliner
// when not optimzing for size. This should probably be lowered after
// performance testing.
// FIXME: this comment is cargo culted from the old pass manager, revisit).
IP.HintThreshold = 325;
- IP.OptSizeHintThreshold = PreInlineThreshold;
+ IP.OptSizeHintThreshold = Opts.PreInlineThreshold;
ModuleInlinerWrapperPass MIWP(
IP, /* MandatoryFirst */ true,
InlineContext{LTOPhase, InlinePass::EarlyInliner});
@@ -888,7 +732,7 @@ void PassBuilder::addPreInlinerPasses(ModulePassManager &MPM,
void PassBuilder::addPostPGOLoopRotation(ModulePassManager &MPM,
OptimizationLevel Level) {
- if (EnablePostPGOLoopRotation) {
+ if (Opts.EnablePostPGOLoopRotation) {
// Disable header duplication in loop rotation at -Oz.
MPM.addPass(createModuleToFunctionPassAdaptor(
createFunctionToLoopPassAdaptor(LoopRotatePass(),
@@ -926,7 +770,7 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM,
// Do counter promotion at Level greater than O0.
Options.DoCounterPromotion = true;
Options.UseBFIInPromotion = IsCS;
- if (EnableSampledInstr) {
+ if (Opts.EnableSampledInstr) {
Options.Sampling = true;
// With sampling, there is little beneifit to enable counter promotion.
// But note that sampling does work with counter promotion.
@@ -988,15 +832,15 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level,
IP.HotCallSiteThreshold = 0;
if (PGOOpt)
- IP.EnableDeferral = EnablePGOInlineDeferral;
+ IP.EnableDeferral = Opts.EnablePGOInlineDeferral;
- ModuleInlinerWrapperPass MIWP(IP, PerformMandatoryInliningsFirst,
+ ModuleInlinerWrapperPass MIWP(IP, Opts.PerformMandatoryInliningsFirst,
InlineContext{Phase, InlinePass::CGSCCInliner},
- UseInlineAdvisor, MaxDevirtIterations);
+ Opts.UseInlineAdvisor, MaxDevirtIterations);
// Require the GlobalsAA analysis for the module so we can query it within
// the CGSCC pipeline.
- if (EnableGlobalAnalyses) {
+ if (Opts.EnableGlobalAnalyses) {
MIWP.addModulePass(RequireAnalysisPass<GlobalsAA, Module>());
// Invalidate AAManager so it can be recreated and pick up the newly
// available GlobalsAA.
@@ -1019,9 +863,9 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level,
// valuable as the inliner doesn't currently care whether it is inlining an
// invoke or a call.
- if (AttributorRun & AttributorRunOption::CGSCC)
+ if (Opts.AttributorRun & AttributorRunOption::CGSCC)
MainCGPipeline.addPass(AttributorCGSCCPass());
- else if (AttributorRun & AttributorRunOption::CGSCC_LIGHT)
+ else if (Opts.AttributorRun & AttributorRunOption::CGSCC_LIGHT)
MainCGPipeline.addPass(AttributorLightCGSCCPass());
// Deduce function attributes. We do another run of this after the function
@@ -1087,7 +931,7 @@ PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level,
IP.HotCallSiteThreshold = 0;
if (PGOOpt)
- IP.EnableDeferral = EnablePGOInlineDeferral;
+ IP.EnableDeferral = Opts.EnablePGOInlineDeferral;
// The inline deferral logic is used to avoid losing some
// inlining chance in future. It is helpful in SCC inliner, in which
@@ -1097,7 +941,7 @@ PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level,
// inline deferral logic in module inliner.
IP.EnableDeferral = false;
- MPM.addPass(ModuleInlinerPass(IP, UseInlineAdvisor, Phase));
+ MPM.addPass(ModuleInlinerPass(IP, Opts.UseInlineAdvisor, Phase));
if (!UseCtxProfile.empty() && Phase == ThinOrFullLTOPhase::ThinLTOPostLink) {
MPM.addPass(GlobalOptPass());
MPM.addPass(GlobalDCEPass());
@@ -1140,8 +984,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
// In ThinLTO mode, when flattened profile is used, all the available
// profile information will be annotated in PreLink phase so there is
// no need to load the profile again in PostLink.
- bool LoadSampleProfile =
- HasSampleProfile && !(FlattenedProfileUsed && isThinLTOPostLink(Phase));
+ bool LoadSampleProfile = HasSampleProfile && !(Opts.FlattenedProfileUsed &&
+ isThinLTOPostLink(Phase));
// During the ThinLTO backend phase we perform early indirect call promotion
// here, before globalopt. Otherwise imported available_externally functions
@@ -1207,9 +1051,9 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
// (quick!) no-op if there are no OpenMP runtime calls present in the module.
MPM.addPass(OpenMPOptPass(Phase));
- if (AttributorRun & AttributorRunOption::MODULE)
+ if (Opts.AttributorRun & AttributorRunOption::MODULE)
MPM.addPass(AttributorPass());
- else if (AttributorRun & AttributorRunOption::MODULE_LIGHT)
+ else if (Opts.AttributorRun & AttributorRunOption::MODULE_LIGHT)
MPM.addPass(AttributorLightPass());
// Lower type metadata and the type.test intrinsic in the ThinLTO
@@ -1264,13 +1108,13 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
"supported.");
const bool IsCtxProfUse = !UseCtxProfile.empty() && isThinLTOPreLink(Phase);
- assert(
- (InstrumentColdFuncOnlyPath.empty() || PGOInstrumentColdFunctionOnly) &&
- "--instrument-cold-function-only-path is provided but "
- "--pgo-instrument-cold-function-only is not enabled");
+ assert((Opts.InstrumentColdFuncOnlyPath.empty() ||
+ PGOInstrumentColdFunctionOnly) &&
+ "--instrument-cold-function-only-path is provided but "
+ "--pgo-instrument-cold-function-only is not enabled");
const bool IsColdFuncOnlyInstrGen = PGOInstrumentColdFunctionOnly &&
IsPGOPreLink &&
- !InstrumentColdFuncOnlyPath.empty();
+ !Opts.InstrumentColdFuncOnlyPath.empty();
if (IsPGOInstrGen || IsPGOInstrUse || IsMemprofUse || IsCtxProfGen ||
IsCtxProfUse || IsColdFuncOnlyInstrGen)
@@ -1305,7 +1149,7 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
} else if (IsColdFuncOnlyInstrGen) {
addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, /* IsCS */ false,
/* AtomicCounterUpdate */ false,
- InstrumentColdFuncOnlyPath,
+ Opts.InstrumentColdFuncOnlyPath,
/* ProfileRemappingFile */ "");
}
@@ -1314,7 +1158,7 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
if (IsPGOPreLink && PGOOpt->CSAction == PGOOptions::CSIRInstr)
MPM.addPass(PGOInstrumentationGenCreateVar(PGOOpt->CSProfileGenFile,
- EnableSampledInstr));
+ Opts.EnableSampledInstr));
if (IsMemprofUse)
MPM.addPass(MemProfUsePass(PGOOpt->MemoryProfile, FS));
@@ -1325,7 +1169,7 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/true));
- if (EnableModuleInliner)
+ if (Opts.EnableModuleInliner)
MPM.addPass(buildModuleInlinerPipeline(Level, Phase));
else
MPM.addPass(buildInlinerPipeline(Level, Phase));
@@ -1369,7 +1213,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
// combiner for cleanup here so that the unrolling and LICM can be pipelined
// across the loop nests.
// We do UnrollAndJam in a separate LPM to ensure it happens before unroll
- if (EnableUnrollAndJam && PTO.LoopUnrolling)
+ if (Opts.EnableUnrollAndJam && PTO.LoopUnrolling)
FPM.addPass(createFunctionToLoopPassAdaptor(
LoopUnrollAndJamPass(static_cast<int>(Level))));
FPM.addPass(LoopUnrollPass(LoopUnrollOptions(
@@ -1402,7 +1246,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
// Cleanup after the loop optimization passes.
FPM.addPass(InstCombinePass());
- if (Level > OptimizationLevel::O1 && ExtraVectorizerPasses) {
+ if (Level > OptimizationLevel::O1 && Opts.ExtraVectorizerPasses) {
ExtraFunctionPassManager<ShouldRunExtraVectorPasses> ExtraPasses;
// At higher optimization levels, try to clean up any runtime overlap and
// alignment checks inserted by the vectorizer. We want to track correlated
@@ -1453,7 +1297,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
// Optimize parallel scalar instruction chains into SIMD instructions.
if (PTO.SLPVectorization) {
FPM.addPass(SLPVectorizerPass());
- if (Level >= OptimizationLevel::O2 && ExtraVectorizerPasses) {
+ if (Level >= OptimizationLevel::O2 && Opts.ExtraVectorizerPasses) {
FPM.addPass(EarlyCSEPass());
}
}
@@ -1469,7 +1313,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
// combiner for cleanup here so that the unrolling and LICM can be pipelined
// across the loop nests.
// We do UnrollAndJam in a separate LPM to ensure it happens before unroll
- if (EnableUnrollAndJam && PTO.LoopUnrolling) {
+ if (Opts.EnableUnrollAndJam && PTO.LoopUnrolling) {
FPM.addPass(createFunctionToLoopPassAdaptor(
LoopUnrollAndJamPass(static_cast<int>(Level))));
}
@@ -1521,7 +1365,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
// Run partial inlining pass to partially inline functions that have
// large bodies.
- if (RunPartialInlining)
+ if (Opts.RunPartialInlining)
MPM.addPass(PartialInlinerPass());
// Remove avail extern fns and globals definitions since we aren't compiling
@@ -1563,7 +1407,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
// information for all local globals here, the late loop passes and notably
// the vectorizer will be able to use them to help recognize vectorizable
// memory operations.
- if (EnableGlobalAnalyses)
+ if (Opts.EnableGlobalAnalyses)
MPM.addPass(RecomputeGlobalsAAPass());
invokeOptimizerEarlyEPCallbacks(MPM, Level, LTOPhase);
@@ -1581,7 +1425,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
// early versioning may prevent further inlining due to increase of code
// size. Other optimizations which runs later might get benefit of no-alias
// assumption in clone loop.
- if (UseLoopVersioningLICM) {
+ if (Opts.UseLoopVersioningLICM) {
OptimizePM.addPass(
createFunctionToLoopPassAdaptor(LoopVersioningLICMPass()));
// LoopVersioningLICM pass might increase new LICM opportunities.
@@ -1596,14 +1440,14 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
if (!isLTOPreLink(LTOPhase))
OptimizePM.addPass(LowerConstantIntrinsicsPass());
- if (EnableMatrix) {
+ if (Opts.EnableMatrix) {
OptimizePM.addPass(LowerMatrixIntrinsicsPass());
OptimizePM.addPass(EarlyCSEPass());
}
// CHR pass should only be applied with the profile information.
// The check is to check the profile summary information in CHR.
- if (EnableCHR && Level == OptimizationLevel::O3)
+ if (Opts.EnableCHR && Level == OptimizationLevel::O3)
OptimizePM.addPass(ControlHeightReductionPass());
// FIXME: We need to run some loop optimizations to re-rotate loops after
@@ -1668,7 +1512,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
// Merge adjacent icmps into memcmp, then expand memcmp to loads/compares.
// TODO: move this furter up so that it can be optimized by GVN, etc.
- if (EnableMergeICmps)
+ if (Opts.EnableMergeICmps)
OptimizePM.addPass(MergeICmpsPass());
OptimizePM.addPass(ExpandMemCmpPass());
@@ -1697,13 +1541,13 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
invokeOptimizerLastEPCallbacks(MPM, Level, LTOPhase);
// Run the Instrumentor pass late.
- if (EnableInstrumentor)
+ if (Opts.EnableInstrumentor)
MPM.addPass(InstrumentorPass(FS));
// Split out cold code. Splitting is done late to avoid hiding context from
// other optimizations and inadvertently regressing performance. The tradeoff
// is that this has a higher code size cost than splitting early.
- if (EnableHotColdSplit && !isLTOPreLink(LTOPhase))
+ if (Opts.EnableHotColdSplit && !isLTOPreLink(LTOPhase))
MPM.addPass(HotColdSplittingPass());
// Now we need to do some global optimization transforms.
@@ -1743,9 +1587,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
// Also, we can't run devirtualization before inlining because the
// devirtualization depends on the passes optimizing/eliminating vtable GVs
// and those passes are only effective after inlining.
- if (EnableModuleInliner) {
+ if (Opts.EnableModuleInliner) {
MPM.addPass(ModuleInlinerPass(::getInlineParamsFromOptLevel(Level),
- UseInlineAdvisor,
+ Opts.UseInlineAdvisor,
ThinOrFullLTOPhase::None));
} else {
MPM.addPass(ModuleInlinerWrapperPass(
@@ -1785,7 +1629,7 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
// Force any function attributes we want the rest of the pipeline to observe.
MPM.addPass(ForceFunctionAttrsPass());
- if (TriggerCrash)
+ if (Opts.TriggerCrash)
MPM.addPass(createModuleToFunctionPassAdaptor(TriggerCrashFunctionPass()));
if (PGOOpt && PGOOpt->DebugInfoForProfiling)
@@ -1916,7 +1760,7 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
// phase that will run after the thin link, running this here ends up with
// less information than will be available later and it may grow functions in
// ways that aren't beneficial.
- if (RunPartialInlining)
+ if (Opts.RunPartialInlining)
MPM.addPass(PartialInlinerPass());
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
@@ -2205,9 +2049,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
// valuable as the inliner doesn't currently care whether it is inlining an
// invoke or a call.
// Run the inliner now.
- if (EnableModuleInliner) {
+ if (Opts.EnableModuleInliner) {
MPM.addPass(ModuleInlinerPass(::getInlineParamsFromOptLevel(Level),
- UseInlineAdvisor,
+ Opts.UseInlineAdvisor,
ThinOrFullLTOPhase::FullLTOPostLink));
} else {
MPM.addPass(ModuleInlinerWrapperPass(
@@ -2248,7 +2092,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
FPM.addPass(InstCombinePass());
invokePeepholeEPCallbacks(FPM, Level);
- if (EnableConstraintElimination)
+ if (Opts.EnableConstraintElimination)
FPM.addPass(ConstraintEliminationPass());
FPM.addPass(JumpThreadingPass());
@@ -2283,7 +2127,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
// Require the GlobalsAA analysis for the module so we can query it within
// MainFPM.
- if (EnableGlobalAnalyses) {
+ if (Opts.EnableGlobalAnalyses) {
MPM.addPass(RequireAnalysisPass<GlobalsAA, Module>());
// Invalidate AAManager so it can be recreated and pick up the newly
// available GlobalsAA.
@@ -2297,7 +2141,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
/*AllowSpeculation=*/true),
/*USeMemorySSA=*/true));
- if (RunNewGVN)
+ if (Opts.RunNewGVN)
MainFPM.addPass(NewGVNPass());
else
MainFPM.addPass(GVNPass());
@@ -2315,7 +2159,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
invokeVectorizerStartEPCallbacks(MainFPM, Level);
LoopPassManager LPM;
- if (EnableLoopFlatten && Level >= OptimizationLevel::O2)
+ if (Opts.EnableLoopFlatten && Level >= OptimizationLevel::O2)
LPM.addPass(LoopFlattenPass());
LPM.addPass(IndVarSimplifyPass());
LPM.addPass(LoopDeletionPass());
@@ -2355,7 +2199,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
MPM.addPass(DropTypeTestsPass());
// Enable splitting late in the FullLTO post-link pipeline.
- if (EnableHotColdSplit)
+ if (Opts.EnableHotColdSplit)
MPM.addPass(HotColdSplittingPass());
// Add late LTO optimization passes.
@@ -2469,7 +2313,7 @@ PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
if (PTO.MergeFunctions)
MPM.addPass(MergeFunctionsPass());
- if (EnableMatrix)
+ if (Opts.EnableMatrix)
MPM.addPass(
createModuleToFunctionPassAdaptor(LowerMatrixIntrinsicsPass(true)));
@@ -2527,7 +2371,7 @@ PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
invokeOptimizerLastEPCallbacks(MPM, Level, Phase);
- if (EnableInstrumentor)
+ if (Opts.EnableInstrumentor)
MPM.addPass(InstrumentorPass(FS));
// Attach !implicit.ref metadata from all functions to copyright strings.
@@ -2568,7 +2412,7 @@ AAManager PassBuilder::buildDefaultAAPipeline() {
// Because the `AAManager` is a function analysis and `GlobalsAA` is a module
// analysis, all that the `AAManager` can do is query for any *cached*
// results from `GlobalsAA` through a readonly proxy.
- if (EnableGlobalAnalyses)
+ if (Opts.EnableGlobalAnalyses)
AA.registerModuleAnalysis<GlobalsAA>();
// Add target-specific alias analyses.
diff --git a/llvm/lib/Passes/PassesOptions.cpp b/llvm/lib/Passes/PassesOptions.cpp
new file mode 100644
index 000000000000..cd31536ed3e0
--- /dev/null
+++ b/llvm/lib/Passes/PassesOptions.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Passes/PassesOptions.h"
+#include "llvm/Option/LibraryOptions.h"
+
+#define OPTIONS_STRUCT_DEFS
+#include "llvm/Passes/PassesOptions.inc"
+
+static llvm::opt::RegisterLibraryOptions<llvm::PassesOptions> Registration;
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 6e4cd1502520..4e7e31875440 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -244,6 +244,7 @@ add_llvm_component_library(LLVMSupport
OptimizedStructLayout.cpp
Optional.cpp
OptionStrCmp.cpp
+ OptionsRegistry.cpp
PGOOptions.cpp
Parallel.cpp
PluginLoader.cpp
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 03ef86bb225d..c72ad2dc9631 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -176,6 +176,13 @@ public:
// This collects additional help to be printed.
std::vector<StringRef> MoreHelp;
+ // Libraries whose options live in a struct rather than here, and the index
+ // of their option names, extended when ParseCommandLineOptions finds
+ // libraries registered since it last ran.
+ SmallVector<LibraryOptions, 4> Libraries;
+ StringMap<unsigned> LibraryOptionsMap;
+ unsigned NumIndexedLibraries = 0;
+
// This collects Options added with the cl::DefaultOption flag. Since they can
// be overridden, they are not added to the appropriate SubCommands until
// ParseCommandLineOptions actually runs.
@@ -237,7 +244,9 @@ public:
return;
// Add argument to the argument map!
- if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
+ if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second ||
+ (!LibraryOptionsMap.empty() &&
+ LibraryOptionsMap.contains(O->ArgStr))) {
errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
<< "' registered more than once!\n";
HadErrors = true;
@@ -409,6 +418,9 @@ public:
registerSubCommand(&SubCommand::getTopLevel());
DefaultOptions.clear();
+ Libraries.clear();
+ LibraryOptionsMap.clear();
+ NumIndexedLibraries = 0;
}
private:
@@ -423,6 +435,8 @@ private:
return Opt;
}
SubCommand *LookupSubCommand(StringRef Name, std::string &NearestString);
+
+ void indexLibraryOptions();
};
} // namespace
@@ -439,18 +453,12 @@ static CommandLineParser &globalParser() {
template <typename T, T TrueVal, T FalseVal>
static bool parseBool(Option &O, StringRef ArgName, StringRef Arg, T &Value) {
- if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||
- Arg == "1") {
- Value = TrueVal;
- return false;
- }
-
- if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {
- Value = FalseVal;
- return false;
- }
- return O.error("'" + Arg +
- "' is invalid value for boolean argument! Try 0 or 1");
+ bool B;
+ if (!to_bool(Arg, B))
+ return O.error("'" + Arg +
+ "' is invalid value for boolean argument! Try 0 or 1");
+ Value = B ? TrueVal : FalseVal;
+ return false;
}
void cl::AddLiteralOption(Option &O, StringRef Name) {
@@ -1530,6 +1538,33 @@ void CommandLineParser::ResetAllOptionOccurrences() {
if (SC->ConsumeAfterOpt)
SC->ConsumeAfterOpt->reset();
}
+ for (const LibraryOptions &L : Libraries)
+ L.Reset();
+}
+
+void cl::registerLibraryOptions(const LibraryOptions &L) {
+ globalParser().Libraries.push_back(L);
+}
+
+void CommandLineParser::indexLibraryOptions() {
+ bool HadErrors = false;
+ for (unsigned I = NumIndexedLibraries, E = Libraries.size(); I != E; ++I) {
+ Libraries[I].ForEachName([&](StringRef Name) {
+ auto [It, New] = LibraryOptionsMap.try_emplace(Name, I);
+ if (New && none_of(RegisteredSubCommands, [&](SubCommand *SC) {
+ return SC->OptionsMap.contains(Name);
+ }))
+ return;
+ if (!New && It->second == I)
+ return;
+ errs() << ProgramName << ": CommandLine Error: Option '" << Name
+ << "' registered more than once!\n";
+ HadErrors = true;
+ });
+ }
+ NumIndexedLibraries = Libraries.size();
+ if (HadErrors)
+ report_fatal_error("inconsistency in registered CommandLine options");
}
bool CommandLineParser::ParseCommandLineOptions(
@@ -1558,6 +1593,8 @@ bool CommandLineParser::ParseCommandLineOptions(
*Errs << toString(std::move(Err)) << '\n';
return false;
}
+ if (NumIndexedLibraries != Libraries.size())
+ indexLibraryOptions();
argv = &newArgv[0];
argc = static_cast<int>(newArgv.size());
@@ -1718,6 +1755,23 @@ bool CommandLineParser::ParseCommandLineOptions(
Handler = LookupLongOption(SubCommand::getTopLevel(), ArgName, Value,
LongOptionsUseDoubleDash, HaveDoubleDash);
+ // A library's option: the library parses it and any value it takes. A
+ // plugin an earlier argument loaded (-load-pass-plugin) registers its
+ // library here, mid-parse.
+ if (!Handler && !(LongOptionsUseDoubleDash && !HaveDoubleDash)) {
+ if (NumIndexedLibraries != Libraries.size())
+ indexLibraryOptions();
+ auto It = LibraryOptionsMap.find(ArgName.split('=').first);
+ if (It != LibraryOptionsMap.end()) {
+ unsigned Index = i;
+ if (!Libraries[It->second].ParseOne(ArrayRef(argv, argc), Index,
+ *Errs))
+ ErrorParsing = true;
+ i = Index - 1;
+ continue;
+ }
+ }
+
// Check to see if this "option" is really a prefixed or grouped argument.
if (!Handler && !(LongOptionsUseDoubleDash && HaveDoubleDash))
Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,
@@ -2518,6 +2572,8 @@ public:
outs() << "OPTIONS:\n";
printOptions(Opts, MaxArgLen);
+ for (const LibraryOptions &L : globalParser().Libraries)
+ L.PrintHelp(outs(), ShowHidden);
// Print any extra help the user has declared.
for (const auto &I : globalParser().MoreHelp)
diff --git a/llvm/lib/Support/OptionsRegistry.cpp b/llvm/lib/Support/OptionsRegistry.cpp
new file mode 100644
index 000000000000..a8a03fc79366
--- /dev/null
+++ b/llvm/lib/Support/OptionsRegistry.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/OptionsRegistry.h"
+#include <vector>
+
+using namespace llvm;
+
+// The process-wide instance of each struct allocateSlot allotted a slot, by
+// slot. Like a target's registration, a slot is allotted at static
+// initialization or when a plugin loads, before registries read it from other
+// threads.
+static std::vector<void *> &currentOptions() {
+ static std::vector<void *> Current;
+ return Current;
+}
+
+static void noDelete(void *) {}
+
+OptionsRegistry::OptionsRegistry() {
+ for (void *O : currentOptions())
+ Slots.emplace_back(O, noDelete);
+}
+
+unsigned OptionsRegistry::allocateSlot(void *Current) {
+ currentOptions().push_back(Current);
+ return currentOptions().size() - 1;
+}
+
+void OptionsRegistry::set(unsigned Slot, void *O, void (*Delete)(void *)) {
+ // A registry older than the struct's registration lacks its slot.
+ for (unsigned I = Slots.size(); I <= Slot; ++I)
+ Slots.emplace_back(currentOptions()[I], noDelete);
+ Slots[Slot] = {O, Delete};
+}
diff --git a/llvm/test/CodeGen/AArch64/cgdata-global-hash.ll b/llvm/test/CodeGen/AArch64/cgdata-global-hash.ll
index c425eda56f5d..34f281f9b959 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-global-hash.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-global-hash.ll
@@ -5,10 +5,10 @@
; RUN: split-file %s %t
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/local-g.ll -o %t/local-g.o
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/local-g.ll -o %t/local-g.o
; RUN: llvm-cgdata --merge %t/local-g.o -o %t/local-g.cgdata
; RUN: llvm-cgdata --convert %t/local-g.cgdata -o %t/local-g.cgtext
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/local-h.ll -o %t/local-h.o
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/local-h.ll -o %t/local-h.o
; RUN: llvm-cgdata --merge %t/local-h.o -o %t/local-h.cgdata
; RUN: llvm-cgdata --convert %t/local-h.cgdata -o %t/local-h.cgtext
diff --git a/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-nsconst.ll b/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-nsconst.ll
index 490a778f69e2..ca2e767bb664 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-nsconst.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-nsconst.ll
@@ -2,7 +2,7 @@
; allowing them to be merged even if they appear different due to their names.
; Now they become identical functions that can be merged without creating a parameter
-; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -global-merging-skip-no-params=false < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -no-global-merging-skip-no-params < %s | FileCheck %s
; CHECK: _f1.Tgm
; CHECK: _f2.Tgm
diff --git a/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-objc.ll b/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-objc.ll
index 007311494150..b6631fc174ab 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-objc.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-objc.ll
@@ -2,7 +2,7 @@
; allowing them to be merged even if they appear different due to their names.
; Now they become identical functions that can be merged without creating a parameter
-; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -global-merging-skip-no-params=false < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -no-global-merging-skip-no-params < %s | FileCheck %s
; CHECK: _f1.Tgm
; CHECK: _f2.Tgm
diff --git a/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-string.ll b/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-string.ll
index 1e67425f0b84..e11cc71a682d 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-string.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-merge-gvar-string.ll
@@ -2,7 +2,7 @@
; allowing them to be merged even if they appear different due to their names.
; Now they become identical functions that can be merged without creating a parameter.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -global-merging-skip-no-params=false < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -no-global-merging-skip-no-params < %s | FileCheck %s
; CHECK: _f1.Tgm
; CHECK: _f2.Tgm
diff --git a/llvm/test/CodeGen/AArch64/cgdata-merge-no-params.ll b/llvm/test/CodeGen/AArch64/cgdata-merge-no-params.ll
index a9da1253de01..2ed1c3d9828e 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-merge-no-params.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-merge-no-params.ll
@@ -6,8 +6,8 @@
; canonical form can be beneficial in downstream passes. This merging process
; can be controlled by the -global-merging-skip-no-params option.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -global-merging-skip-no-params=false < %s | FileCheck %s --check-prefix=MERGE
-; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -global-merging-skip-no-params=true < %s | FileCheck %s --implicit-check-not=".Tgm"
+; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -no-global-merging-skip-no-params < %s | FileCheck %s --check-prefix=MERGE
+; RUN: llc -mtriple=arm64-apple-darwin -enable-global-merge-func=true -global-merging-skip-no-params < %s | FileCheck %s --implicit-check-not=".Tgm"
; MERGE: _f1.Tgm
; MERGE: _f2.Tgm
diff --git a/llvm/test/CodeGen/AArch64/cgdata-outlined-name.ll b/llvm/test/CodeGen/AArch64/cgdata-outlined-name.ll
index 69f1ecd6515e..e945ac37679a 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-outlined-name.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-outlined-name.ll
@@ -3,9 +3,9 @@
; RUN: split-file %s %t
; Check if the outlined function name has the content hash depending the flag.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -append-content-hash-outlined-name=false -filetype=obj %t/local-two.ll -o %t_write_base
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -append-content-hash-outlined-name=false -filetype=obj %t/local-two.ll -o %t_write_base
; RUN: llvm-objdump -d %t_write_base | FileCheck %s --check-prefix=BASE
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -append-content-hash-outlined-name=true -filetype=obj %t/local-two.ll -o %t_write_suffix
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -append-content-hash-outlined-name=true -filetype=obj %t/local-two.ll -o %t_write_suffix
; RUN: llvm-objdump -d %t_write_suffix | FileCheck %s --check-prefix=SUFFIX
; BASE-NOT: _OUTLINED_FUNCTION_{{.*}}.content.{{[0-9]+}}
; SUFFIX: _OUTLINED_FUNCTION_{{.*}}.content.{{[0-9]+}}
diff --git a/llvm/test/CodeGen/AArch64/cgdata-read-double-outline.ll b/llvm/test/CodeGen/AArch64/cgdata-read-double-outline.ll
index 6e027308c170..219522570ca1 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-read-double-outline.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-read-double-outline.ll
@@ -6,7 +6,7 @@
; RUN: split-file %s %t
; First, we generate the cgdata file from a local outline instance present in local-two.ll.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/local-two.ll -o %t_write
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/local-two.ll -o %t_write
; RUN: llvm-cgdata --merge %t_write -o %t_cgdata
; RUN: llvm-cgdata --show %t_cgdata | FileCheck %s --check-prefix=SHOW
diff --git a/llvm/test/CodeGen/AArch64/cgdata-read-lto-outline.ll b/llvm/test/CodeGen/AArch64/cgdata-read-lto-outline.ll
index f1a5d1a0ccc7..b6477e1e8b2b 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-read-lto-outline.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-read-lto-outline.ll
@@ -10,7 +10,7 @@
; RUN: opt -module-summary %t/local-two.ll -o %t/write.bc
; RUN: llvm-lto2 run %t/write.bc -o %t/write \
; RUN: -r %t/write.bc,_f1,px -r %t/write.bc,_f2,px -r %t/write.bc,_g,p \
-; RUN: -codegen-data-generate=true
+; RUN: -codegen-data-generate
; RUN: llvm-cgdata --merge %t/write.1 -o %t_cgdata
; RUN: llvm-cgdata --show %t_cgdata | FileCheck %s --check-prefix=SHOW
diff --git a/llvm/test/CodeGen/AArch64/cgdata-read-priority.ll b/llvm/test/CodeGen/AArch64/cgdata-read-priority.ll
index affeea8c71ac..5bb421d94af8 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-read-priority.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-read-priority.ll
@@ -5,8 +5,8 @@
; RUN: split-file %s %t
; First, we generate the cgdata file from local outline instances present in write1.ll and write2.ll
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/write1.ll -o %t_write1
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/write2.ll -o %t_write2
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/write1.ll -o %t_write1
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/write2.ll -o %t_write2
; RUN: llvm-cgdata --merge %t_write1 %t_write2 -o %t_cgdata
; RUN: llvm-cgdata --show %t_cgdata | FileCheck %s --check-prefix=SHOW
diff --git a/llvm/test/CodeGen/AArch64/cgdata-read-single-outline-suffix.ll b/llvm/test/CodeGen/AArch64/cgdata-read-single-outline-suffix.ll
index 11bee02c0be5..d4ce77a43e52 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-read-single-outline-suffix.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-read-single-outline-suffix.ll
@@ -9,7 +9,7 @@
; RUN: split-file %s %t
; First, we generate the cgdata file from a local outline instance present in local-two.ll.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/local-two.ll -o %t_write
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/local-two.ll -o %t_write
; RUN: llvm-cgdata --merge %t_write -o %t_cgdata
; RUN: llvm-cgdata --show %t_cgdata | FileCheck %s --check-prefix=SHOW
@@ -72,7 +72,7 @@ define i32 @f5() minsize {
; Similarly, we outline functions that have already been processed in previous outliner runs.
; Assuming `-machine-outliner-reruns` is locally enabled, we might already have `OUTLINED_FUNCTION*` instances.
; First, we generate the cgdata file from a local outline instance found in local-two-content.ll.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/local-two-content.ll -o %t_write_content
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/local-two-content.ll -o %t_write_content
; RUN: llvm-cgdata --merge %t_write_content -o %t_cgdata_content
; RUN: llvm-cgdata --show %t_cgdata_content | FileCheck %s --check-prefix=SHOW
diff --git a/llvm/test/CodeGen/AArch64/cgdata-read-single-outline.ll b/llvm/test/CodeGen/AArch64/cgdata-read-single-outline.ll
index 7725648a6bc3..6e7ccb9047a4 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-read-single-outline.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-read-single-outline.ll
@@ -4,7 +4,7 @@
; RUN: split-file %s %t
; First, we generate the cgdata file from a local outline instance present in local-two.ll.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %t/local-two.ll -o %t_write
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %t/local-two.ll -o %t_write
; RUN: llvm-cgdata --merge %t_write -o %t_cgdata
; RUN: llvm-cgdata --show %t_cgdata | FileCheck %s --check-prefix=SHOW
diff --git a/llvm/test/CodeGen/AArch64/cgdata-write-outline.ll b/llvm/test/CodeGen/AArch64/cgdata-write-outline.ll
index 09ad499190ee..6e1cf15d33b4 100644
--- a/llvm/test/CodeGen/AArch64/cgdata-write-outline.ll
+++ b/llvm/test/CodeGen/AArch64/cgdata-write-outline.ll
@@ -2,10 +2,10 @@
; when the -codegen-data-generate flag is used.
; Verify whether an outlined function is always created, but only encoded into the section when the flag is used.
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=true -filetype=obj %s -o %t_save
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate -filetype=obj %s -o %t_save
; RUN: llvm-objdump -d %t_save | FileCheck %s
; RUN: llvm-objdump -h %t_save | FileCheck %s --check-prefix=SECTNAME
-; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -codegen-data-generate=false -filetype=obj %s -o %t_nosave
+; RUN: llc -mtriple=arm64-apple-darwin -enable-machine-outliner -no-codegen-data-generate -filetype=obj %s -o %t_nosave
; RUN: llvm-objdump -d %t_nosave | FileCheck %s
; RUN: llvm-objdump -h %t_nosave | FileCheck %s --check-prefix=NOSECTNAME
diff --git a/llvm/test/Other/X86/lto-hot-cold-split.ll b/llvm/test/Other/X86/lto-hot-cold-split.ll
index 24903f34ed07..05bcfe953d97 100644
--- a/llvm/test/Other/X86/lto-hot-cold-split.ll
+++ b/llvm/test/Other/X86/lto-hot-cold-split.ll
@@ -1,7 +1,7 @@
; RUN: opt -module-summary %s -o %t.bc
-; RUN: llvm-lto -hot-cold-split=true \
+; RUN: llvm-lto -hot-cold-split \
; RUN: -thinlto-action=run %t.bc -debug-pass-manager 2>&1 | FileCheck %s -check-prefix=OLDPM-ANYLTO-POSTLINK-Os
-; RUN: llvm-lto -hot-cold-split=true \
+; RUN: llvm-lto -hot-cold-split \
; RUN: %t.bc -debug-pass-manager 2>&1 | FileCheck %s -check-prefix=OLDPM-ANYLTO-POSTLINK-Os
; REQUIRES: asserts
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index 0eb201432132..a2f749f0d814 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -7,77 +7,77 @@
; Any invalidation that shows up here is a bug, unless we started modifying
; the IR, in which case we need to make it immutable harder.
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='default<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O1,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='default<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O2,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-LTO,CHECK-O2,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-peephole='no-op-function' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-PEEPHOLE,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-late-loop-optimizations='no-op-loop' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-LOOP-LATE,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-loop-optimizer-end='no-op-loop' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-LOOP-END,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-scalar-optimizer-late='no-op-function' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-SCALAR-LATE,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-cgscc-optimizer-late='no-op-cgscc' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-CGSCC-LATE,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-vectorizer-start='no-op-function' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-VECTORIZER-START,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-vectorizer-end='no-op-function' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-VECTORIZER-END,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-pipeline-start='no-op-module' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-PIPELINE-START,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-pipeline-early-simplification='no-op-module' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-PIPELINE-EARLY-SIMPLIFICATION,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-pipeline-start='no-op-module' \
; RUN: -passes='lto-pre-link<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-LTO,CHECK-O3,%llvmcheckext,CHECK-EP-PIPELINE-START,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-optimizer-early='no-op-module' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-OPTIMIZER-EARLY,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes-ep-optimizer-last='no-op-module' \
; RUN: -passes='default<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,%llvmcheckext,CHECK-EP-OPTIMIZER-LAST,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='default<O3>' -enable-matrix -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext,CHECK-MATRIX
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='default<O3>' -enable-merge-functions -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext,CHECK-MERGE-FUNCS
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='default<O3>' -hot-cold-split -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-DEFAULT,CHECK-O3,CHECK-O23,%llvmcheckext,CHECK-HOT-COLD-SPLIT
diff --git a/llvm/test/Other/new-pm-eager-invalidate.ll b/llvm/test/Other/new-pm-eager-invalidate.ll
index 87a6d9587b07..7cb14d1dcb54 100644
--- a/llvm/test/Other/new-pm-eager-invalidate.ll
+++ b/llvm/test/Other/new-pm-eager-invalidate.ll
@@ -3,8 +3,8 @@
; RUN: opt -disable-verify -debug-pass-manager -passes='function<eager-inv>(require<no-op-function>)' -disable-output %s 2>&1 | FileCheck %s --check-prefix=EAGER
; RUN: opt -disable-verify -debug-pass-manager -passes='cgscc(function<eager-inv>(require<no-op-function>))' -disable-output %s 2>&1 | FileCheck %s --check-prefix=EAGER
-; RUN: opt -disable-verify -debug-pass-manager -passes='default<O2>' -eagerly-invalidate-analyses=0 -disable-output %s 2>&1 | FileCheck %s --check-prefix=PIPELINE
-; RUN: opt -disable-verify -debug-pass-manager -passes='default<O2>' -eagerly-invalidate-analyses=1 -disable-output %s 2>&1 | FileCheck %s --check-prefix=PIPELINE-EAGER
+; RUN: opt -disable-verify -debug-pass-manager -passes='default<O2>' -no-eagerly-invalidate-analyses -disable-output %s 2>&1 | FileCheck %s --check-prefix=PIPELINE
+; RUN: opt -disable-verify -debug-pass-manager -passes='default<O2>' -eagerly-invalidate-analyses -disable-output %s 2>&1 | FileCheck %s --check-prefix=PIPELINE-EAGER
; NORMAL-NOT: Invalidating analysis: NoOpFunctionAnalysis
; EAGER: Invalidating analysis: NoOpFunctionAnalysis
diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll
index 97bc3e5ce758..de5313d352f4 100644
--- a/llvm/test/Other/new-pm-lto-defaults.ll
+++ b/llvm/test/Other/new-pm-lto-defaults.ll
@@ -1,32 +1,32 @@
; Basic test for the new LTO pipeline.
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O1>' -S %s -passes-ep-full-link-time-optimization-early=no-op-module \
; RUN: -passes-ep-full-link-time-optimization-last=no-op-module 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-EP
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O2>' -S %s -passes-ep-full-link-time-optimization-early=no-op-module \
; RUN: -passes-ep-full-link-time-optimization-last=no-op-module 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23,CHECK-EP
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O3>' -S %s -passes-ep-vectorizer-start='no-op-function' 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23,CHECK-EP-VECTORIZER-START
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O3>' -S %s -passes-ep-vectorizer-end='no-op-function' 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23,CHECK-EP-VECTORIZER-END
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O3>' -S %s -passes-ep-peephole='no-op-function' 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23,CHECK-EP-PEEPHOLE
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='lto<O3>' -S %s -passes-ep-cgscc-optimizer-late='no-op-cgscc' 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O23,CHECK-EP-CGSCC-LATE
diff --git a/llvm/test/Other/new-pm-pgo-preinline.ll b/llvm/test/Other/new-pm-pgo-preinline.ll
index 5d5f6fcd0f00..27c16837f38c 100644
--- a/llvm/test/Other/new-pm-pgo-preinline.ll
+++ b/llvm/test/Other/new-pm-pgo-preinline.ll
@@ -1,4 +1,4 @@
-; RUN: opt -disable-verify -eagerly-invalidate-analyses=0 -debug-pass-manager -pgo-kind=pgo-instr-gen-pipeline -passes='default<O2>' -S %s 2>&1 | FileCheck %s --check-prefixes=CHECK-O2
+; RUN: opt -disable-verify -no-eagerly-invalidate-analyses -debug-pass-manager -pgo-kind=pgo-instr-gen-pipeline -passes='default<O2>' -S %s 2>&1 | FileCheck %s --check-prefixes=CHECK-O2
; CHECK-O2: Running pass: ModuleInlinerWrapperPass
; CHECK-O2-NEXT: Running analysis: InlineAdvisorAnalysis
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
index 204f3eb8beb5..505083293a30 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
@@ -8,25 +8,25 @@
; the IR, in which case we need to make it immutable harder.
;
; Postlink pipelines:
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-POSTLINK-O,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,CHECK-POSTLINK-O,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \
; RUN: -passes='thinlto<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-POSTLINK-O,%llvmcheckext,CHECK-POSTLINK-O3
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -passes-ep-optimizer-early='no-op-module' \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -passes-ep-optimizer-early='no-op-module' \
; RUN: -passes='thinlto<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-POSTLINK-O,%llvmcheckext,CHECK-POSTLINK-O3,CHECK-POST-EP-OPT-EARLY
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -passes-ep-optimizer-last='no-op-module' \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -passes-ep-optimizer-last='no-op-module' \
; RUN: -passes='thinlto<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-POSTLINK-O,%llvmcheckext,CHECK-POSTLINK-O3,CHECK-POST-EP-OPT-LAST
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -passes='thinlto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,CHECK-POSTLINK-O,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto<O1>' -S %s -passes-ep-thin-link-time-optimization-early=no-op-module \
; RUN: -passes-ep-thin-link-time-optimization-last=no-op-module 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-POSTLINK-O,%llvmcheckext,CHECK-EP-THINLTO-EARLY,CHECK-EP-THINLTO-LAST
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
index 441344250e2f..99cec746a26d 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
@@ -1,16 +1,16 @@
; Validate ThinLTO post link pipeline when we have instrumentation PGO
;
; Postlink pipelines:
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \
; RUN: -passes='thinlto<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -passes='thinlto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,%llvmcheckext
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
index 477e36e8d9ab..f1050cc37a01 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
@@ -1,18 +1,18 @@
; Validate ThinLTO postlink pipeline when we have Sample PGO
;
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -passes-ep-pipeline-start='no-op-module' \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto<O3>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,%llvmcheckext
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,%llvmcheckext
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
index b07825faaa87..189a26a15523 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
@@ -8,40 +8,40 @@
; the IR, in which case we need to make it immutable harder.
;
; Prelink pipelines:
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto-pre-link<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-O-NODIS
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -unified-lto -passes='lto-pre-link<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1,CHECK-O-NODIS
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,CHECK-O-NODIS
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -unified-lto -passes='lto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23,CHECK-O-NODIS
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto-pre-link<O3>' -S -passes-ep-pipeline-start='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-O-NODIS,CHECK-EP-PIPELINE-START
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -unified-lto -passes='lto-pre-link<O3>' -S -passes-ep-pipeline-start='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-O-NODIS,CHECK-EP-PIPELINE-START
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto-pre-link<O3>' -S -passes-ep-optimizer-early='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-O-NODIS,CHECK-EP-OPT-EARLY
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -unified-lto -passes='lto-pre-link<O3>' -S -passes-ep-optimizer-early='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-O-NODIS,CHECK-EP-OPT-EARLY
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -passes='thinlto-pre-link<O3>' -S -passes-ep-optimizer-last='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-O-NODIS,CHECK-EP-OPT-LAST
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -unified-lto -passes='lto-pre-link<O3>' -S -passes-ep-optimizer-last='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-O-NODIS,CHECK-EP-OPT-LAST
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -passes='thinlto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-DIS,CHECK-O,CHECK-O2,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -unified-lto -passes='lto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-DIS,CHECK-O,CHECK-O2,CHECK-O23
;
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
index eafd8aad98e7..942dca59ee61 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
@@ -2,19 +2,19 @@
;
; RUN: llvm-profdata merge %S/Inputs/new-pm-thinlto-prelink-pgo-defaults.proftext -o %t.profdata
;
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' \
; RUN: -passes='thinlto-pre-link<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' \
; RUN: -passes='thinlto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' \
; RUN: -passes='thinlto-pre-link<O3>' -S -passes-ep-pipeline-start='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-EP-PIPELINE-START
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -pgo-kind=pgo-instr-use-pipeline -profile-file='%t.profdata' \
; RUN: -passes='thinlto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
index 8d42a45475c2..c3d25193c234 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
@@ -1,18 +1,18 @@
; Validate ThinLTO prelink pipeline when we have Sample PGO
;
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto-pre-link<O1>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O1
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto-pre-link<O3>' -S -passes-ep-pipeline-start='no-op-module' %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O3,CHECK-O23,CHECK-EP-PIPELINE-START
-; RUN: opt -disable-verify -verify-analysis-invalidation=0 -eagerly-invalidate-analyses=0 -debug-pass-manager -debug-info-for-profiling \
+; RUN: opt -disable-verify -verify-analysis-invalidation=0 -no-eagerly-invalidate-analyses -debug-pass-manager -debug-info-for-profiling \
; RUN: -pgo-kind=pgo-sample-use-pipeline -profile-file='%S/Inputs/new-pm-thinlto-samplepgo-defaults.prof' \
; RUN: -passes='thinlto-pre-link<O2>' -S %s 2>&1 \
; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-O23
diff --git a/llvm/test/Other/opt-hot-cold-split.ll b/llvm/test/Other/opt-hot-cold-split.ll
index 4948733a7d98..0d42b5aa6af8 100644
--- a/llvm/test/Other/opt-hot-cold-split.ll
+++ b/llvm/test/Other/opt-hot-cold-split.ll
@@ -1,8 +1,8 @@
-; RUN: opt -mtriple=x86_64-- -hot-cold-split=true -passes='default<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=DEFAULT-O2
-; RUN: opt -mtriple=x86_64-- -hot-cold-split=true -passes='lto-pre-link<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=LTO-PRELINK-O2
-; RUN: opt -mtriple=x86_64-- -hot-cold-split=true -passes='thinlto-pre-link<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=THINLTO-PRELINK-O2
-; RUN: opt -mtriple=x86_64-- -hot-cold-split=true -passes='lto<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=LTO-POSTLINK-O2
-; RUN: opt -mtriple=x86_64-- -hot-cold-split=true -passes='thinlto<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=THINLTO-POSTLINK-O2
+; RUN: opt -mtriple=x86_64-- -hot-cold-split -passes='default<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=DEFAULT-O2
+; RUN: opt -mtriple=x86_64-- -hot-cold-split -passes='lto-pre-link<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=LTO-PRELINK-O2
+; RUN: opt -mtriple=x86_64-- -hot-cold-split -passes='thinlto-pre-link<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=THINLTO-PRELINK-O2
+; RUN: opt -mtriple=x86_64-- -hot-cold-split -passes='lto<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=LTO-POSTLINK-O2
+; RUN: opt -mtriple=x86_64-- -hot-cold-split -passes='thinlto<O2>' -debug-pass-manager < %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=THINLTO-POSTLINK-O2
; REQUIRES: asserts
diff --git a/llvm/test/ThinLTO/AArch64/cgdata-merge-read.ll b/llvm/test/ThinLTO/AArch64/cgdata-merge-read.ll
index 9eb9bda0b54d..e0cc495c3385 100644
--- a/llvm/test/ThinLTO/AArch64/cgdata-merge-read.ll
+++ b/llvm/test/ThinLTO/AArch64/cgdata-merge-read.ll
@@ -7,9 +7,9 @@
; RUN: opt -module-summary -module-hash %t/foo.ll -o %t-foo.bc
; RUN: opt -module-summary -module-hash %t/goo.ll -o %t-goo.bc
-; First, run with -codegen-data-generate=true to generate the cgdata in the object files.
+; First, run with -codegen-data-generate to generate the cgdata in the object files.
; Using llvm-cgdata, merge the cg data.
-; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-generate=true %t-foo.bc %t-goo.bc -o %tout-write \
+; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-generate %t-foo.bc %t-goo.bc -o %tout-write \
; RUN: -r %t-foo.bc,_f1,px \
; RUN: -r %t-goo.bc,_f2,px \
; RUN: -r %t-foo.bc,_g,l -r %t-foo.bc,_g1,l -r %t-foo.bc,_g2,l \
@@ -30,9 +30,9 @@
; RUN: llvm-objdump -d %tout-read.1 | FileCheck %s --check-prefix=THUNK1
; RUN: llvm-objdump -d %tout-read.2 | FileCheck %s --check-prefix=THUNK2
-; It runs the same if we use -indexed-codegen-data-read-function-map-names=false.
+; It runs the same if we use -no-indexed-codegen-data-read-function-map-names.
; RUN: llvm-lto2 run -enable-global-merge-func=true \
-; RUN: -indexed-codegen-data-read-function-map-names=false \
+; RUN: -no-indexed-codegen-data-read-function-map-names \
; RUN: -codegen-data-use-path=%tout.cgdata \
; RUN: %t-foo.bc %t-goo.bc -o %tout-read \
; RUN: -r %t-foo.bc,_f1,px \
diff --git a/llvm/test/ThinLTO/AArch64/cgdata-merge-two-rounds.ll b/llvm/test/ThinLTO/AArch64/cgdata-merge-two-rounds.ll
index 06880e3d2681..99607227ba26 100644
--- a/llvm/test/ThinLTO/AArch64/cgdata-merge-two-rounds.ll
+++ b/llvm/test/ThinLTO/AArch64/cgdata-merge-two-rounds.ll
@@ -1,12 +1,12 @@
; TODO: This test checks if the how similar functions are handled during global outlining
-; by repeating the codegen via -codegen-data-thinlto-two-rounds=true.
+; by repeating the codegen via -codegen-data-thinlto-two-rounds.
; RUN: rm -rf %t; split-file %s %t
; RUN: opt -module-summary -module-hash %t/foo.ll -o %t-foo.bc
; RUN: opt -module-summary -module-hash %t/goo.ll -o %t-goo.bc
-; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-thinlto-two-rounds=true %t-foo.bc %t-goo.bc -o %tout \
+; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-thinlto-two-rounds %t-foo.bc %t-goo.bc -o %tout \
; RUN: -r %t-foo.bc,_f1,px \
; RUN: -r %t-goo.bc,_f2,px \
; RUN: -r %t-foo.bc,_g,l -r %t-foo.bc,_g1,l -r %t-foo.bc,_g2,l \
diff --git a/llvm/test/ThinLTO/AArch64/cgdata-merge-write.ll b/llvm/test/ThinLTO/AArch64/cgdata-merge-write.ll
index 47042d23cc2c..ee3fb56f445e 100644
--- a/llvm/test/ThinLTO/AArch64/cgdata-merge-write.ll
+++ b/llvm/test/ThinLTO/AArch64/cgdata-merge-write.ll
@@ -6,7 +6,7 @@
; RUN: opt -module-summary -module-hash %t/foo.ll -o %t-foo.bc
; RUN: opt -module-summary -module-hash %t/goo.ll -o %t-goo.bc
-; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-generate=false %t-foo.bc %t-goo.bc -o %tout-nowrite \
+; RUN: llvm-lto2 run -enable-global-merge-func=true -no-codegen-data-generate %t-foo.bc %t-goo.bc -o %tout-nowrite \
; RUN: -r %t-foo.bc,_f1,px \
; RUN: -r %t-goo.bc,_f2,px \
; RUN: -r %t-foo.bc,_g,l -r %t-foo.bc,_g1,l -r %t-foo.bc,_g2,l \
@@ -18,7 +18,7 @@
; NOWRITE-NOT: _f1.Tgm
; NOWRITE-NOT: _f2.Tgm
-; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-generate=true %t-foo.bc %t-goo.bc -o %tout-nowrite \
+; RUN: llvm-lto2 run -enable-global-merge-func=true -codegen-data-generate %t-foo.bc %t-goo.bc -o %tout-nowrite \
; RUN: -r %t-foo.bc,_f1,px \
; RUN: -r %t-goo.bc,_f2,px \
; RUN: -r %t-foo.bc,_g,l -r %t-foo.bc,_g1,l -r %t-foo.bc,_g2,l \
diff --git a/llvm/test/Transforms/GlobalOpt/disable-globals-aa.ll b/llvm/test/Transforms/GlobalOpt/disable-globals-aa.ll
index df620416154d..a5160d744ef7 100644
--- a/llvm/test/Transforms/GlobalOpt/disable-globals-aa.ll
+++ b/llvm/test/Transforms/GlobalOpt/disable-globals-aa.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
; RUN: opt -O2 -S %s | FileCheck %s --check-prefix=WITHGLOBALSAA
-; RUN: opt -O2 -enable-global-analyses=0 -S %s | FileCheck %s --check-prefix=NOGLOBALSAA
+; RUN: opt -O2 -no-enable-global-analyses -S %s | FileCheck %s --check-prefix=NOGLOBALSAA
@glb = internal global i8 0
diff --git a/llvm/test/Transforms/Inline/ML/enable-inline-advisor-printing-ml.ll b/llvm/test/Transforms/Inline/ML/enable-inline-advisor-printing-ml.ll
index de414f0bcb45..a2785c149515 100644
--- a/llvm/test/Transforms/Inline/ML/enable-inline-advisor-printing-ml.ll
+++ b/llvm/test/Transforms/Inline/ML/enable-inline-advisor-printing-ml.ll
@@ -1,11 +1,11 @@
; REQUIRES: llvm_inliner_model_autogenerated || have_mlir_lowering_inliner
; RUN: opt %if have_mlir_lowering_inliner %{ -enable-ml-inliner=release -mlgo-model=inliner %} %else %{ -enable-ml-inliner=release %} -passes=scc-oz-module-inliner \
-; RUN: -keep-inline-advisor-for-printing -mandatory-inlining-first=1 \
+; RUN: -keep-inline-advisor-for-printing -mandatory-inlining-first \
; RUN: -enable-scc-inline-advisor-printing -S < %s 2>&1 | FileCheck %s
; RUN: opt %if have_mlir_lowering_inliner %{ -enable-ml-inliner=release -mlgo-model=inliner %} %else %{ -enable-ml-inliner=release %} -passes=scc-oz-module-inliner \
-; RUN: -keep-inline-advisor-for-printing -mandatory-inlining-first=0 \
+; RUN: -keep-inline-advisor-for-printing -no-mandatory-inlining-first \
; RUN: -enable-scc-inline-advisor-printing -S < %s 2>&1 \
; RUN: | FileCheck %s --check-prefix=TWO
diff --git a/llvm/test/Transforms/Inline/ML/fpi-update.ll b/llvm/test/Transforms/Inline/ML/fpi-update.ll
index 0799bb9edc0a..63387c7eb4c2 100644
--- a/llvm/test/Transforms/Inline/ML/fpi-update.ll
+++ b/llvm/test/Transforms/Inline/ML/fpi-update.ll
@@ -7,7 +7,7 @@ target triple = "x86_64-grtev4-linux-gnu"
; RUN: opt %if have_mlir_lowering_inliner %{ -enable-ml-inliner=release -mlgo-model=inliner %} %else %{ -enable-ml-inliner=release %} -passes='scc-oz-module-inliner,print<inline-advisor>' \
; RUN: -keep-inline-advisor-for-printing -max-devirt-iterations=0 \
-; RUN: -mandatory-inlining-first=0 -S < %s 2>&1 | FileCheck %s
+; RUN: -no-mandatory-inlining-first -S < %s 2>&1 | FileCheck %s
define void @caller(i32 %i) #1 {
call void @callee(i32 %i)
diff --git a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp
index f06119a24e6f..9cb7b1657aa0 100644
--- a/llvm/tools/llvm-cgdata/llvm-cgdata.cpp
+++ b/llvm/tools/llvm-cgdata/llvm-cgdata.cpp
@@ -67,6 +67,7 @@ static std::string OutputFilename = "-";
static std::string Filename;
static bool ShowCGDataVersion;
static bool SkipTrim;
+static bool LazyLoading;
static CGDataAction Action;
static std::optional<CGDataFormat> OutputFormat;
static std::vector<std::string> InputFilenames;
@@ -107,7 +108,7 @@ static int convert_main(int argc, const char *argv[]) {
exitWithErrorCode(EC, OutputFilename);
auto FS = vfs::getRealFileSystem();
- auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS);
+ auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS, LazyLoading);
if (Error E = ReaderOrErr.takeError())
exitWithError(std::move(E), Filename);
@@ -239,7 +240,7 @@ static int show_main(int argc, const char *argv[]) {
exitWithErrorCode(EC, OutputFilename);
auto FS = vfs::getRealFileSystem();
- auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS);
+ auto ReaderOrErr = CodeGenDataReader::create(Filename, *FS, LazyLoading);
if (Error E = ReaderOrErr.takeError())
exitWithError(std::move(E), Filename);
@@ -350,8 +351,7 @@ static void parseArgs(int argc, char **argv) {
llvm_unreachable("unrecognized action");
}
- IndexedCodeGenDataLazyLoading =
- Args.hasArg(OPT_indexed_codegen_data_lazy_loading);
+ LazyLoading = Args.hasArg(OPT_indexed_codegen_data_lazy_loading);
}
int llvm_cgdata_main(int argc, char **argvNonConst, const llvm::ToolContext &) {
diff --git a/llvm/unittests/Option/OptionParsingTest.cpp b/llvm/unittests/Option/OptionParsingTest.cpp
index 6b45ea5ea8aa..f71a862ba76c 100644
--- a/llvm/unittests/Option/OptionParsingTest.cpp
+++ b/llvm/unittests/Option/OptionParsingTest.cpp
@@ -566,3 +566,41 @@ OPTIONS:
multiple lines in it
)");
}
+
+TEST(OptTableTest, ForEachOptionName) {
+ TestOptTable T;
+ std::vector<std::string> Names;
+ T.forEachOptionName([&](StringRef Name) { Names.push_back(Name.str()); });
+ EXPECT_EQ(Names.size(), T.getNumOptions() - 3u); // input, unknown, my_group
+ EXPECT_TRUE(is_contained(Names, "C="));
+ EXPECT_FALSE(is_contained(Names, "my group"));
+}
+
+TEST(OptTableTest, ApplyArgs) {
+ TestOptTable T;
+ std::vector<std::string> Applied;
+ SmallVector<const char *> Rest;
+ std::string Err;
+ raw_string_ostream ErrOS(Err);
+ auto Apply = [&](const Arg &A) {
+ Applied.push_back(A.getSpelling().str() +
+ (A.getNumValues() ? A.getValue() : ""));
+ return A.getOption().getID() != OPT_B;
+ };
+
+ const char *Ok[] = {"-A", "in.o", "-C", "v", "-unknown", "-Fx"};
+ EXPECT_TRUE(T.applyArgs(Ok, Rest, ErrOS, Apply));
+ EXPECT_EQ(Applied, (std::vector<std::string>{"-A", "-Cv", "-Fx"}));
+ EXPECT_EQ(Rest.size(), 2u);
+ EXPECT_STREQ(Rest[0], "in.o");
+ EXPECT_STREQ(Rest[1], "-unknown");
+
+ const char *Rejected[] = {"-Bv"};
+ EXPECT_FALSE(T.applyArgs(Rejected, Rest, ErrOS, Apply));
+ EXPECT_EQ(Err, "error: invalid value 'v' in '-Bv'\n");
+
+ Err.clear();
+ const char *Missing[] = {"-C"};
+ EXPECT_FALSE(T.applyArgs(Missing, Rest, ErrOS, Apply));
+ EXPECT_EQ(Err, "error: option '-C' requires an argument\n");
+}
diff --git a/llvm/unittests/Passes/CMakeLists.txt b/llvm/unittests/Passes/CMakeLists.txt
index e96a4e12b94b..d0bdf1a7b33e 100644
--- a/llvm/unittests/Passes/CMakeLists.txt
+++ b/llvm/unittests/Passes/CMakeLists.txt
@@ -6,3 +6,11 @@ endif()
add_subdirectory(PassBuilderBindings)
add_subdirectory(Plugins)
+
+set(LLVM_LINK_COMPONENTS Core Passes Support)
+add_llvm_unittest(PassesTests
+ PassesOptionsTest.cpp
+
+ DEPENDS
+ passes_options_gen
+ )
diff --git a/llvm/unittests/Passes/PassesOptionsTest.cpp b/llvm/unittests/Passes/PassesOptionsTest.cpp
new file mode 100644
index 000000000000..9a39fe80e14b
--- /dev/null
+++ b/llvm/unittests/Passes/PassesOptionsTest.cpp
@@ -0,0 +1,96 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Passes/PassesOptions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using testing::ElementsAre;
+using testing::StrEq;
+
+TEST(PassesOptionsTest, Parse) {
+ PassesOptions O;
+ SmallVector<const char *> Rest;
+ const char *Args[] = {"opt",
+ "-enable-module-inliner",
+ "-o",
+ "out.bc",
+ "--preinline-threshold",
+ "7",
+ "-no-enable-chr",
+ "-enable-ml-inliner=release",
+ "-attributor-enable",
+ "cgscc-light",
+ "in.ll"};
+ EXPECT_TRUE(O.parse(Args, Rest, errs()));
+ EXPECT_TRUE(O.EnableModuleInliner);
+ EXPECT_EQ(O.PreInlineThreshold, 7);
+ EXPECT_FALSE(O.EnableCHR);
+ EXPECT_EQ(O.UseInlineAdvisor, InliningAdvisorMode::Release);
+ EXPECT_EQ(O.AttributorRun, AttributorRunOption::CGSCC_LIGHT);
+ EXPECT_TRUE(O.EnableGlobalAnalyses);
+ EXPECT_THAT(Rest, ElementsAre(StrEq("opt"), StrEq("-o"), StrEq("out.bc"),
+ StrEq("in.ll")));
+
+ std::string Err;
+ raw_string_ostream ErrOS(Err);
+ const char *BadArgs[] = {"opt", "-enable-ml-inliner=sometimes"};
+ EXPECT_FALSE(O.parse(BadArgs, Rest, ErrOS));
+ EXPECT_EQ(Err, "error: invalid value 'sometimes' in "
+ "'-enable-ml-inliner=sometimes'\n");
+}
+
+TEST(PassesOptionsTest, ThroughCommandLine) {
+ cl::ResetAllOptionOccurrences();
+ const char *Args[] = {"opt", "-enable-newgvn", "-preinline-threshold=3"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(Args), Args, "", &errs()));
+ EXPECT_TRUE(PassesOptions::Current.RunNewGVN);
+ EXPECT_EQ(PassesOptions::Current.PreInlineThreshold, 3);
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(PassesOptions::Current.RunNewGVN);
+ EXPECT_EQ(PassesOptions::Current.PreInlineThreshold, 75);
+}
+
+TEST(PassesOptionsTest, PerContext) {
+ LLVMContext CtxA, CtxNone;
+ PassesOptions &A = CtxA.setOptions(PassesOptions::Current);
+ A.PreInlineThreshold = 1;
+ EXPECT_EQ(&CtxA.getOptions<PassesOptions>(), &A);
+ EXPECT_EQ(A.PreInlineThreshold, 1);
+ EXPECT_EQ(&CtxNone.getOptions<PassesOptions>(), &PassesOptions::Current);
+ EXPECT_EQ(PassesOptions::Current.PreInlineThreshold, 75);
+}
+
+TEST(PassesOptionsTest, PerPipeline) {
+ PassesOptions A, B;
+ A.EnableModuleInliner = true;
+ B.EnableModuleInliner = false;
+ A.MergeFunctions = true;
+ auto Pipeline = [](const PassesOptions &O) {
+ PipelineTuningOptions PTO(O);
+ EXPECT_EQ(PTO.MergeFunctions, O.MergeFunctions);
+ PassBuilder PB(nullptr, PTO, std::nullopt, nullptr,
+ vfs::getRealFileSystem(), &O);
+ ModulePassManager MPM =
+ PB.buildPerModuleDefaultPipeline(OptimizationLevel::O2);
+ std::string S;
+ raw_string_ostream OS(S);
+ MPM.printPipeline(OS, [](StringRef Name) { return Name; });
+ return S;
+ };
+ EXPECT_TRUE(StringRef(Pipeline(A)).contains("ModuleInlinerPass"));
+ EXPECT_TRUE(StringRef(Pipeline(A)).contains("MergeFunctionsPass"));
+ EXPECT_FALSE(StringRef(Pipeline(B)).contains("ModuleInlinerPass"));
+ EXPECT_FALSE(StringRef(Pipeline(B)).contains("MergeFunctionsPass"));
+}
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index f9732ff4e0e4..00de35a1ffff 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -72,6 +72,7 @@ add_llvm_unittest(SupportTests
ModRefTest.cpp
NativeFormatTests.cpp
OptimizedStructLayoutTest.cpp
+ OptionsRegistryTest.cpp
ParallelTest.cpp
Path.cpp
PerThreadBumpPtrAllocatorTest.cpp
diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp
index 956d5b97c270..b9253cb446e0 100644
--- a/llvm/unittests/Support/CommandLineTest.cpp
+++ b/llvm/unittests/Support/CommandLineTest.cpp
@@ -2502,4 +2502,72 @@ TEST(CommandLineTest, HelpWithEmptyCategory) {
cl::ResetCommandLineParser();
}
+std::vector<std::string> LibraryArgs;
+const cl::LibraryOptions TestLibrary = {
+ [](function_ref<void(StringRef)> F) {
+ F("library-flag");
+ F("library-int");
+ },
+ [](ArrayRef<const char *> Argv, unsigned &Index, raw_ostream &) {
+ StringRef Arg = Argv[Index++];
+ LibraryArgs.push_back(Arg.str());
+ if (Arg == "-library-int" && Index != Argv.size())
+ LibraryArgs.push_back(Argv[Index++]);
+ return true;
+ },
+ [](raw_ostream &OS, bool) { OS << "\nLIBRARY OPTIONS:\n"; },
+ [] { LibraryArgs.clear(); }};
+
+TEST(CommandLineTest, LibraryOptions) {
+ cl::ResetCommandLineParser();
+ cl::registerLibraryOptions(TestLibrary);
+ StackOption<int> Local("local");
+
+ const char *Args[] = {"prog", "-library-flag", "--local=3", "-library-int",
+ "4"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(Args), Args, StringRef(),
+ &llvm::nulls()));
+ EXPECT_EQ(Local, 3);
+ EXPECT_THAT(LibraryArgs,
+ testing::ElementsAre("-library-flag", "-library-int", "4"));
+ cl::ResetAllOptionOccurrences();
+ EXPECT_TRUE(LibraryArgs.empty());
+
+ auto Output = interceptStdout(
+ []() { cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/false); });
+ EXPECT_NE(std::string::npos, Output.find("LIBRARY OPTIONS:"));
+ cl::ResetCommandLineParser();
+}
+
+// A library registered while parsing, as a plugin that an argument loads
+// does, serves the arguments after it.
+TEST(CommandLineTest, LibraryOptionsRegisteredWhileParsing) {
+ cl::ResetCommandLineParser();
+ StackOption<std::string> Load("load", cl::callback([](const std::string &) {
+ cl::registerLibraryOptions(TestLibrary);
+ }));
+
+ const char *Args[] = {"prog", "-load=plugin", "-library-flag"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(Args), Args, StringRef(),
+ &llvm::nulls()));
+ EXPECT_THAT(LibraryArgs, testing::ElementsAre("-library-flag"));
+ cl::ResetAllOptionOccurrences();
+ cl::ResetCommandLineParser();
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(CommandLineTest, LibraryOptionsConflict) {
+ cl::ResetCommandLineParser();
+ cl::registerLibraryOptions(TestLibrary);
+ const char *Args[] = {"prog"};
+ EXPECT_DEATH(
+ {
+ StackOption<int> Clash("library-int");
+ cl::ParseCommandLineOptions(std::size(Args), Args);
+ },
+ "Option 'library-int' registered more than once");
+ cl::ResetCommandLineParser();
+}
+#endif
+
} // anonymous namespace
diff --git a/llvm/unittests/Support/OptionsRegistryTest.cpp b/llvm/unittests/Support/OptionsRegistryTest.cpp
new file mode 100644
index 000000000000..b63f430bc201
--- /dev/null
+++ b/llvm/unittests/Support/OptionsRegistryTest.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/OptionsRegistry.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+struct AOptions {
+ int A = 1;
+ static AOptions Current;
+ static unsigned Slot;
+};
+AOptions AOptions::Current;
+unsigned AOptions::Slot = OptionsRegistry::allocateSlot(&AOptions::Current);
+
+struct BOptions {
+ int B = 2;
+ static BOptions Current;
+ static unsigned Slot;
+};
+BOptions BOptions::Current;
+unsigned BOptions::Slot;
+} // namespace
+
+TEST(OptionsRegistryTest, SetAndGet) {
+ OptionsRegistry Old;
+ EXPECT_EQ(&Old.get<AOptions>(), &AOptions::Current);
+
+ // A registry created before a struct's registration reads Current, and
+ // gains the slot on set.
+ BOptions::Slot = OptionsRegistry::allocateSlot(&BOptions::Current);
+ EXPECT_EQ(&Old.get<BOptions>(), &BOptions::Current);
+ AOptions &A = Old.set(AOptions{3});
+ EXPECT_EQ(&Old.get<AOptions>(), &A);
+ EXPECT_EQ(Old.get<AOptions>().A, 3);
+ BOptions &B = Old.set(BOptions{4});
+ EXPECT_EQ(&Old.get<BOptions>(), &B);
+ EXPECT_EQ(Old.get<AOptions>().A, 3);
+
+ OptionsRegistry New;
+ EXPECT_EQ(&New.get<AOptions>(), &AOptions::Current);
+ EXPECT_EQ(&New.get<BOptions>(), &BOptions::Current);
+ New.set(BOptions{5});
+ EXPECT_EQ(New.get<BOptions>().B, 5);
+ EXPECT_EQ(&New.get<AOptions>(), &AOptions::Current);
+}
diff --git a/llvm/utils/TableGen/OptionParserEmitter.cpp b/llvm/utils/TableGen/OptionParserEmitter.cpp
index 2718f801c229..69a554f462be 100644
--- a/llvm/utils/TableGen/OptionParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptionParserEmitter.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/raw_ostream.h"
@@ -231,6 +232,142 @@ static MarshallingInfo createMarshallingInfo(const Record &R) {
/// OptionParserEmitter - This tablegen backend takes an input .td file
/// describing a list of options and emits a data structure for parsing and
/// working with those options when given an input command line.
+// Dump the struct of OptionsStruct, and its members and registration, which
+// use the tables emitted above under OPTIONS_STRUCT_DEFS.
+static void emitOptionsStruct(const Record &S, ArrayRef<const Record *> Groups,
+ ArrayRef<const Record *> Opts, raw_ostream &OS) {
+ StringRef NS = S.getValueAsString("Namespace");
+ StringRef Name = S.getName();
+ std::string Q = NS.str() + "::" + Name.str();
+ auto Fields = make_filter_range(Opts, [](const Record *R) {
+ return !isa<UnsetInit>(R->getValueInit("FieldType"));
+ });
+ // registerLibraryOptions hands the table at most two arguments.
+ for (const Record *R : Opts) {
+ StringRef Kind = R->getValueAsDef("Kind")->getValueAsString("Name");
+ if (!is_contained({"Flag", "Joined", "Separate", "Input", "Unknown"}, Kind))
+ PrintFatalError(
+ R->getLoc(),
+ "an OptionsStruct's option is a Flag, Joined or Separate");
+ }
+
+ auto UsesType = [&](StringRef Type) {
+ return any_of(Fields, [&](const Record *R) {
+ return R->getValueAsString("FieldType").contains(Type);
+ });
+ };
+
+ OS << "/////////\n";
+ OS << "// Struct\n\n";
+ OS << "#ifdef OPTIONS_STRUCT_DECL\n";
+ OS << "#include \"llvm/Support/Compiler.h\"\n";
+ if (UsesType("std::optional"))
+ OS << "#include <optional>\n";
+ if (UsesType("std::string"))
+ OS << "#include <string>\n";
+ if (UsesType("std::vector"))
+ OS << "#include <vector>\n";
+ OS << "namespace llvm {\n"
+ "class raw_ostream;\n"
+ "template <typename T> class ArrayRef;\n"
+ "template <typename T> class SmallVectorImpl;\n"
+ "namespace opt {\n"
+ "class Arg;\n"
+ "class OptTable;\n"
+ "} // namespace opt\n"
+ "} // namespace llvm\n\n";
+ OS << "namespace " << NS << " {\n";
+ OS << "struct " << Name << " {\n";
+ for (const Record *R : Fields)
+ OS << " " << R->getValueAsString("FieldType") << ' '
+ << R->getValueAsString("KeyPath") << '{'
+ << getOptionalString(*R, "DefaultValue") << "};\n";
+ OS << "\n /// The process-wide instance: cl::ParseCommandLineOptions fills "
+ "it, and\n"
+ " /// a context reads it until a tool attaches its own copy.\n";
+ OS << " LLVM_ABI static " << Name << " Current;\n";
+ OS << " /// The struct's slot in an OptionsRegistry.\n"
+ " LLVM_ABI static unsigned Slot;\n"
+ " /// The options' table, for parsing and help.\n"
+ " LLVM_ABI static const llvm::opt::OptTable &table();\n"
+ " /// Stores the value of \\p A, an option of table(); false if it is "
+ "invalid.\n"
+ " LLVM_ABI bool apply(const llvm::opt::Arg &A);\n"
+ " /// Parses the options this struct declares out of \\p Args, "
+ "appending every\n"
+ " /// other argument to \\p Rest in order; reports errors to \\p Errs "
+ "and\n"
+ " /// returns false.\n"
+ " LLVM_ABI bool parse(llvm::ArrayRef<const char *> Args,\n"
+ " llvm::SmallVectorImpl<const char *> &Rest,\n"
+ " llvm::raw_ostream &Errs);\n";
+ OS << "};\n";
+ OS << "} // namespace " << NS << "\n";
+ OS << "#undef OPTIONS_STRUCT_DECL\n";
+ OS << "#endif // OPTIONS_STRUCT_DECL\n\n";
+
+ OS << "#ifdef OPTIONS_STRUCT_DEFS\n";
+ OS << Q << ' ' << Q << "::Current;\n";
+ OS << "unsigned " << Q << "::Slot;\n\n";
+ OS << "namespace {\n";
+ OS << "enum ID {\n OPT_INVALID = 0,\n";
+ for (const Record *R : Groups)
+ OS << " OPT_" << getOptionName(*R) << ",\n";
+ for (const Record *R : Opts)
+ OS << " OPT_" << getOptionName(*R) << ",\n";
+ OS << "};\n"
+ "} // namespace\n\n";
+
+ OS << "const llvm::opt::OptTable &" << Q
+ << "::table() {\n"
+ " static const llvm::opt::OptTable Table(optionTables());\n"
+ " return Table;\n"
+ "}\n\n";
+
+ OS << "bool " << Q
+ << "::apply(const llvm::opt::Arg &A) {\n"
+ " switch (A.getOption().getID()) {\n";
+ for (const Record *R : Opts) {
+ if (!isa<UnsetInit>(R->getValueInit("AssignValue"))) {
+ OS << " case OPT_" << getOptionName(*R) << ":\n "
+ << R->getValueAsString("AssignMember") << " = "
+ << R->getValueAsString("AssignValue") << ";\n return true;\n";
+ continue;
+ }
+ if (isa<UnsetInit>(R->getValueInit("FieldType")))
+ continue;
+ OS << " case OPT_" << getOptionName(*R) << ":\n return llvm::opt::";
+ StringRef Member = R->getValueAsString("KeyPath");
+ if (const Record *E = R->getValueAsOptionalDef("FieldEnum")) {
+ OS << "parseEnumValue(A.getValue(), " << Member << ", {";
+ ListSeparator Sep;
+ for (const Record *M : E->getValueAsListOfDefs("Members")) {
+ OS << Sep << '{';
+ writeCstring(OS, M->getValueAsString("Spelling"));
+ OS << ", " << E->getValueAsString("Name")
+ << "::" << M->getValueAsString("Name") << '}';
+ }
+ OS << "});\n";
+ } else {
+ OS << "parseArgValue(A.getValue(), " << Member << ");\n";
+ }
+ }
+ OS << " }\n"
+ " llvm_unreachable(\"option without a field\");\n"
+ "}\n\n";
+
+ OS << "bool " << Q
+ << "::parse(llvm::ArrayRef<const char *> Args,\n"
+ " llvm::SmallVectorImpl<const char *> &Rest,\n"
+ " llvm::raw_ostream &Errs) {\n"
+ " return table().applyArgs(Args, Rest, Errs,\n"
+ " [&](const llvm::opt::Arg &A) { return "
+ "apply(A); });\n"
+ "}\n";
+ OS << "#undef OPTIONS_STRUCT_DEFS\n";
+ OS << "#endif // OPTIONS_STRUCT_DEFS\n";
+}
+
static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
// Get the option groups and options.
ArrayRef<const Record *> Groups =
@@ -294,17 +431,27 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
Table.GetOrAddStringOffset(V->getValueAsString("Text"));
}
- // Flags and Visibility name enumerators of the including tool. An option
- // inherits its group's.
+ // Flags and Visibility name enumerators of the including tool, except the
+ // ones OptParser.td defines, which are LLVMOption's. An option inherits its
+ // group's.
auto GetMask = [](const Record &R, StringRef Field) {
std::string Mask;
raw_string_ostream MaskOS(Mask);
ListSeparator Sep(" | ");
+ auto Add = [&](const Init *I) {
+ StringRef Name = cast<DefInit>(I)->getDef()->getName();
+ bool Own = StringSwitch<bool>(Name)
+ .Cases({"HelpHidden", "RenderAsInput", "RenderJoined",
+ "RenderSeparate", "DefaultVis"},
+ true)
+ .Default(false);
+ MaskOS << Sep << (Own ? "llvm::opt::" : "") << Name;
+ };
for (const Init *I : *R.getValueAsListInit(Field))
- MaskOS << Sep << cast<DefInit>(I)->getDef()->getName();
+ Add(I);
if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
for (const Init *I : *DI->getDef()->getValueAsListInit(Field))
- MaskOS << Sep << cast<DefInit>(I)->getDef()->getName();
+ Add(I);
return Mask.empty() ? std::string("0") : Mask;
};
@@ -323,14 +470,16 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
// Dump string table.
OS << "/////////\n";
OS << "// String table\n\n";
- OS << "#if defined(OPTTABLE_STR_TABLE_CODE) || defined(OPTTABLE_CODE)\n";
+ OS << "#if defined(OPTTABLE_STR_TABLE_CODE) || defined(OPTTABLE_CODE) || "
+ "defined(OPTIONS_STRUCT_DEFS)\n";
Table.EmitStringTableDef(OS, "OptionStrTable");
OS << "#undef OPTTABLE_STR_TABLE_CODE\n";
- OS << "#endif // OPTTABLE_STR_TABLE_CODE || OPTTABLE_CODE\n\n";
+ OS << "#endif // OPTTABLE_STR_TABLE_CODE || OPTTABLE_CODE || "
+ "OPTIONS_STRUCT_DEFS\n\n";
OS << "/////////\n";
OS << "// Tables\n\n";
- OS << "#ifdef OPTTABLE_CODE\n";
+ OS << "#if defined(OPTTABLE_CODE) || defined(OPTIONS_STRUCT_DEFS)\n";
// A function rather than an object: the object needs dynamic relocations.
OS << "static llvm::opt::OptTable::Tables optionTables() {\n";
@@ -488,7 +637,7 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
<< ", OptionSubCommandIDsTable};\n";
OS << "}\n";
OS << "#undef OPTTABLE_CODE\n";
- OS << "#endif // OPTTABLE_CODE\n\n";
+ OS << "#endif // OPTTABLE_CODE || OPTIONS_STRUCT_DEFS\n\n";
// Dump ValuesCode.
OS << "/////////\n";
@@ -630,7 +779,8 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
auto IsMarshallingOption = [](const Record &R) {
return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
- !R.getValueAsString("KeyPath").empty();
+ !R.getValueAsString("KeyPath").empty() &&
+ isa<UnsetInit>(R.getValueInit("FieldType"));
};
std::vector<const Record *> OptsWithMarshalling;
@@ -642,7 +792,14 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
if (IsMarshallingOption(R))
OptsWithMarshalling.push_back(&R);
}
- OS << "#endif // OPTION\n";
+ OS << "#endif // OPTION\n\n";
+
+ ArrayRef<const Record *> Structs =
+ Records.getAllDerivedDefinitions("OptionsStruct");
+ if (Structs.size() > 1)
+ PrintFatalError(Structs[1]->getLoc(), "one OptionsStruct per file");
+ if (!Structs.empty())
+ emitOptionsStruct(*Structs[0], Groups, Opts, OS);
auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) {
unsigned AID = (*A)->getID();
diff --git a/llvm/utils/gn/secondary/llvm/include/llvm/Passes/BUILD.gn b/llvm/utils/gn/secondary/llvm/include/llvm/Passes/BUILD.gn
new file mode 100644
index 000000000000..33f3f15e8ec3
--- /dev/null
+++ b/llvm/utils/gn/secondary/llvm/include/llvm/Passes/BUILD.gn
@@ -0,0 +1,5 @@
+import("//llvm/utils/TableGen/tablegen.gni")
+
+tablegen("PassesOptions") {
+ args = [ "-gen-opt-parser-defs" ]
+}
diff --git a/llvm/utils/gn/secondary/llvm/lib/CGData/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/CGData/BUILD.gn
index 9947c68a319d..cf2b6997540b 100644
--- a/llvm/utils/gn/secondary/llvm/lib/CGData/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/CGData/BUILD.gn
@@ -1,10 +1,20 @@
+import("//llvm/utils/TableGen/tablegen.gni")
+
+tablegen("CGDataOptions") {
+ visibility = [ ":CGData" ]
+ args = [ "-gen-opt-parser-defs" ]
+}
+
static_library("CGData") {
output_name = "LLVMCGData"
deps = [
+ ":CGDataOptions",
"//llvm/lib/IR",
+ "//llvm/lib/Option",
"//llvm/lib/Support",
]
sources = [
+ "CGDataOptions.cpp",
"CodeGenData.cpp",
"CodeGenDataReader.cpp",
"CodeGenDataWriter.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn
index 7f60735acfd6..675990e2f82f 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn
@@ -1,5 +1,9 @@
static_library("Passes") {
output_name = "LLVMPasses"
+ public_deps = [
+ # Must be a public_dep because Passes's headers include PassesOptions.inc.
+ "//llvm/include/llvm/Passes:PassesOptions",
+ ]
deps = [
"//llvm/lib/Analysis",
"//llvm/lib/CodeGen",
@@ -7,6 +11,7 @@ static_library("Passes") {
"//llvm/lib/CodeGen/GlobalISel",
"//llvm/lib/IR",
"//llvm/lib/IRPrinter",
+ "//llvm/lib/Option",
"//llvm/lib/Support",
"//llvm/lib/Target",
"//llvm/lib/Transforms/AggressiveInstCombine",
@@ -26,6 +31,7 @@ static_library("Passes") {
"PassBuilder.cpp",
"PassBuilderBindings.cpp",
"PassBuilderPipelines.cpp",
+ "PassesOptions.cpp",
"RunCodeGen.cpp",
"StandardInstrumentations.cpp",
"TriggerCrashPasses.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
index d07b119464c0..c4e8650fa96c 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
@@ -127,6 +127,7 @@ static_library("Support") {
"NativeFormatting.cpp",
"OptimizedStructLayout.cpp",
"OptionStrCmp.cpp",
+ "OptionsRegistry.cpp",
"Optional.cpp",
"PGOOptions.cpp",
"Parallel.cpp",
diff --git a/llvm/utils/gn/secondary/llvm/unittests/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/BUILD.gn
index d489ce6bed2c..d7d5c1e09803 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/BUILD.gn
@@ -46,6 +46,7 @@ group("unittests") {
"Object:ObjectTests",
"ObjectYAML:ObjectYAMLTests",
"Option:OptionTests",
+ "Passes:PassesTests",
"Passes/PassBuilderBindings:PassesBindingsTests",
"Passes/Plugins:PluginsTests",
"ProfileData:ProfileDataTests",
diff --git a/llvm/utils/gn/secondary/llvm/unittests/Passes/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Passes/BUILD.gn
new file mode 100644
index 000000000000..aa3b5f35cd64
--- /dev/null
+++ b/llvm/utils/gn/secondary/llvm/unittests/Passes/BUILD.gn
@@ -0,0 +1,10 @@
+import("//third-party/unittest/unittest.gni")
+
+unittest("PassesTests") {
+ deps = [
+ "//llvm/lib/IR",
+ "//llvm/lib/Passes",
+ "//llvm/lib/Support",
+ ]
+ sources = [ "PassesOptionsTest.cpp" ]
+}
diff --git a/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn
index 168b609279ca..aa1818101ecc 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/Support/BUILD.gn
@@ -76,6 +76,7 @@ unittest("SupportTests") {
"MustacheTest.cpp",
"NativeFormatTests.cpp",
"OptimizedStructLayoutTest.cpp",
+ "OptionsRegistryTest.cpp",
"ParallelTest.cpp",
"Path.cpp",
"PerThreadBumpPtrAllocatorTest.cpp",
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index b7765075c72f..3c23b7060c86 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -2351,6 +2351,15 @@ cc_library(
],
)
+gentbl_cc_library(
+ name = "CGDataOptionsTableGen",
+ strip_include_prefix = "lib/CGData",
+ tbl_outs = {"lib/CGData/CGDataOptions.inc": ["-gen-opt-parser-defs"]},
+ tblgen = ":llvm-tblgen",
+ td_file = "lib/CGData/CGDataOptions.td",
+ deps = [":OptParserTdFiles"],
+)
+
cc_library(
name = "CGData",
srcs = glob(["lib/CGData/**/*.cpp"]),
@@ -2362,9 +2371,11 @@ cc_library(
deps = [
":BitReader",
":BitWriter",
+ ":CGDataOptionsTableGen",
":Core",
":Object",
":ObjectYAML",
+ ":Option",
":Support",
":TargetParser",
],
@@ -4233,6 +4244,14 @@ cc_library(
textual_hdrs = ["lib/Passes/PassRegistry.def"],
)
+gentbl_cc_library(
+ name = "passes_options_gen",
+ tbl_outs = {"include/llvm/Passes/PassesOptions.inc": ["-gen-opt-parser-defs"]},
+ tblgen = ":llvm-tblgen",
+ td_file = "include/llvm/Passes/PassesOptions.td",
+ deps = [":OptParserTdFiles"],
+)
+
cc_library(
name = "Passes",
srcs = glob([
@@ -4258,6 +4277,7 @@ cc_library(
":Instrumentation",
":MC",
":ObjCARC",
+ ":Option",
":Plugins",
":Scalar",
":Support",
@@ -4267,6 +4287,7 @@ cc_library(
":common_transforms",
":config",
":pass_registry_def",
+ ":passes_options_gen",
],
)
base-commit: 27ba493781215910f560b36cd5b3b2f6c93ec5a3
--
2.55.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment