Created
September 20, 2026 21:58
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 *> ¤tOptions() { | |
| + 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