diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -80,6 +80,7 @@ #include "llvm/IR/SafepointIRVerifier.h" #include "llvm/IR/Verifier.h" #include "llvm/IRPrinter/IRPrintingPasses.h" +#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -527,6 +528,17 @@ return Name.startswith("<") && Name.endswith(">"); } +static std::optional parseOptLevel(StringRef S) { + return StringSwitch>(S) + .Case("O0", OptimizationLevel::O0) + .Case("O1", OptimizationLevel::O1) + .Case("O2", OptimizationLevel::O2) + .Case("O3", OptimizationLevel::O3) + .Case("Os", OptimizationLevel::Os) + .Case("Oz", OptimizationLevel::Oz) + .Default(std::nullopt); +} + namespace { /// This performs customized parsing of pass name with parameters. @@ -613,14 +625,10 @@ while (!Params.empty()) { StringRef ParamName; std::tie(ParamName, Params) = Params.split(';'); - int OptLevel = StringSwitch(ParamName) - .Case("O0", 0) - .Case("O1", 1) - .Case("O2", 2) - .Case("O3", 3) - .Default(-1); - if (OptLevel >= 0) { - UnrollOpts.setOptLevel(OptLevel); + std::optional OptLevel = parseOptLevel(ParamName); + // Don't accept -Os/-Oz. + if (OptLevel && !OptLevel->isOptimizingForSize()) { + UnrollOpts.setOptLevel(OptLevel->getSpeedupLevel()); continue; } if (ParamName.consume_front("full-unroll-max=")) { @@ -1046,6 +1054,18 @@ "SeparateConstOffsetFromGEP"); } +Expected +parseFunctionSimplificationPipelineOptions(StringRef Params) { + std::optional L = parseOptLevel(Params); + if (!L || *L == OptimizationLevel::O0) { + return make_error( + formatv("invalid function-simplification parameter '{0}' ", Params) + .str(), + inconvertibleErrorCode()); + }; + return *L; +} + } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline @@ -1342,13 +1362,7 @@ assert(Matches.size() == 3 && "Must capture two matched strings!"); - OptimizationLevel L = StringSwitch(Matches[2]) - .Case("O0", OptimizationLevel::O0) - .Case("O1", OptimizationLevel::O1) - .Case("O2", OptimizationLevel::O2) - .Case("O3", OptimizationLevel::O3) - .Case("Os", OptimizationLevel::Os) - .Case("Oz", OptimizationLevel::Oz); + OptimizationLevel L = *parseOptLevel(Matches[2]); // This is consistent with old pass manager invoked via opt, but // inconsistent with clang. Clang doesn't enable loop vectorization diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -550,6 +550,13 @@ }, parseSeparateConstOffsetFromGEPPassOptions, "lower-gep") +FUNCTION_PASS_WITH_PARAMS("function-simplification", + "", + [this](OptimizationLevel OL) { + return buildFunctionSimplificationPipeline(OL, ThinOrFullLTOPhase::None); + }, + parseFunctionSimplificationPipelineOptions, + "O1;O2;O3;Os;Oz") #undef FUNCTION_PASS_WITH_PARAMS #ifndef LOOPNEST_PASS diff --git a/llvm/test/Other/function-simplification.ll b/llvm/test/Other/function-simplification.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Other/function-simplification.ll @@ -0,0 +1,18 @@ +; RUN: opt -passes='function-simplification' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O1 +; RUN: opt -passes='function-simplification' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ +; RUN: opt -passes='function-simplification' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ +; RUN: opt -passes='function-simplification' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ +; RUN: opt -passes='function-simplification' -debug-pass-manager -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O23SZ +; RUN: not opt -passes='function-simplification' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=O0 + +; O1: Running pass: EarlyCSEPass +; O1-NOT: Running pass: GVNPass + +; O23SZ: Running pass: EarlyCSEPass +; O23SZ: Running pass: GVNPass + +; O0: invalid function-simplification parameter 'O0' + +define void @f() { + ret void +} \ No newline at end of file