diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 4603eaff8ade9..f95c32d859d14 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -374,9 +374,6 @@ using namespace llvm; -static const Regex DefaultAliasRegex( - "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$"); - cl::opt llvm::PrintPipelinePasses( "print-pipeline-passes", cl::desc("Print a '-passes' compatible string describing the pipeline " @@ -618,6 +615,15 @@ static std::optional parseOptLevel(StringRef S) { .Default(std::nullopt); } +static Expected parseOptLevelParam(StringRef S) { + std::optional OptLevel = parseOptLevel(S); + if (OptLevel) + return *OptLevel; + return make_error( + formatv("invalid optimization level '{}'", S).str(), + inconvertibleErrorCode()); +} + Expected PassBuilder::parseSinglePassOption(StringRef Params, StringRef OptionName, StringRef PassName) { @@ -1507,13 +1513,6 @@ Expected parseVirtRegRewriterPassOptions(StringRef Params) { } // namespace -/// Tests whether a pass name starts with a valid prefix for a default pipeline -/// alias. -static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) { - return Name.starts_with("default") || Name.starts_with("thinlto") || - Name.starts_with("lto"); -} - /// Tests whether registered callbacks will accept a given pass name. /// /// When parsing a pipeline text, the type of the outermost pipeline may be @@ -1535,10 +1534,6 @@ static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) { template static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) { - // Manually handle aliases for pre-configured pipeline fragments. - if (startsWithDefaultPipelineAliasPrefix(Name)) - return DefaultAliasRegex.match(Name); - StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; }); // Explicitly handle pass manager names. @@ -1737,6 +1732,15 @@ PassBuilder::parsePipelineText(StringRef Text) { return {std::move(ResultPipeline)}; } +static void setupOptionsForPipelineAlias(PipelineTuningOptions &PTO, + OptimizationLevel L) { + // This is consistent with old pass manager invoked via opt, but + // inconsistent with clang. Clang doesn't enable loop vectorization + // but does enable slp vectorization at Oz. + PTO.LoopVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz; + PTO.SLPVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz; +} + Error PassBuilder::parseModulePass(ModulePassManager &MPM, const PipelineElement &E) { auto &Name = E.Name; @@ -1789,47 +1793,6 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, ; } - // Manually handle aliases for pre-configured pipeline fragments. - if (startsWithDefaultPipelineAliasPrefix(Name)) { - SmallVector Matches; - if (!DefaultAliasRegex.match(Name, &Matches)) - return make_error( - formatv("unknown default pipeline alias '{}'", Name).str(), - inconvertibleErrorCode()); - - assert(Matches.size() == 3 && "Must capture two matched strings!"); - - 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 - // but does enable slp vectorization at Oz. - PTO.LoopVectorization = - L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz; - PTO.SLPVectorization = - L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz; - - if (Matches[1] == "default") { - MPM.addPass(buildPerModuleDefaultPipeline(L)); - } else if (Matches[1] == "thinlto-pre-link") { - MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L)); - } else if (Matches[1] == "thinlto") { - MPM.addPass(buildThinLTODefaultPipeline(L, nullptr)); - } else if (Matches[1] == "lto-pre-link") { - if (PTO.UnifiedLTO) - // When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This - // avoids compile-time performance regressions and keeps the pre-link - // LTO pipeline "unified" for both LTO modes. - MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L)); - else - MPM.addPass(buildLTOPreLinkDefaultPipeline(L)); - } else { - assert(Matches[1] == "lto" && "Not one of the matched options!"); - MPM.addPass(buildLTODefaultPipeline(L, nullptr)); - } - return Error::success(); - } - // Finally expand the basic registered passes from the .inc file. #define MODULE_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index ec14c6a9211d9..1d924f38a47fb 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -240,6 +240,43 @@ MODULE_PASS_WITH_PARAMS( }, parseStructuralHashPrinterPassOptions, "detailed;call-target-ignored") +MODULE_PASS_WITH_PARAMS( + "default", "", [&](OptimizationLevel L) { + setupOptionsForPipelineAlias(PTO, L); + return buildPerModuleDefaultPipeline(L); + }, + parseOptLevelParam, "O0;O1;O2;O3;Os;Oz") +MODULE_PASS_WITH_PARAMS( + "thinlto-pre-link", "", [&](OptimizationLevel L) { + setupOptionsForPipelineAlias(PTO, L); + return buildThinLTOPreLinkDefaultPipeline(L); + }, + parseOptLevelParam, "O0;O1;O2;O3;Os;Oz") +MODULE_PASS_WITH_PARAMS( + "thinlto", "", [&](OptimizationLevel L) { + setupOptionsForPipelineAlias(PTO, L); + return buildThinLTODefaultPipeline(L, nullptr); + }, + parseOptLevelParam, "O0;O1;O2;O3;Os;Oz") +MODULE_PASS_WITH_PARAMS( + "lto-pre-link", "", [&](OptimizationLevel L) { + setupOptionsForPipelineAlias(PTO, L); + if (PTO.UnifiedLTO) { + // When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This + // avoids compile-time performance regressions and keeps the pre-link + // LTO pipeline "unified" for both LTO modes. + return buildThinLTOPreLinkDefaultPipeline(L); + } + return buildLTOPreLinkDefaultPipeline(L); + }, + parseOptLevelParam, "O0;O1;O2;O3;Os;Oz") +MODULE_PASS_WITH_PARAMS( + "lto", "", [&](OptimizationLevel L) { + setupOptionsForPipelineAlias(PTO, L); + return buildLTODefaultPipeline(L, nullptr); + }, + parseOptLevelParam, "O0;O1;O2;O3;Os;Oz") + #undef MODULE_PASS_WITH_PARAMS #ifndef CGSCC_ANALYSIS diff --git a/llvm/test/Other/pipeline-alias-errors.ll b/llvm/test/Other/pipeline-alias-errors.ll new file mode 100644 index 0000000000000..4d744144ed2ec --- /dev/null +++ b/llvm/test/Other/pipeline-alias-errors.ll @@ -0,0 +1,13 @@ +; RUN: not opt -passes="default" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL +; RUN: not opt -passes="default" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL +; RUN: not opt -passes="thinlto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL +; RUN: not opt -passes="thinlto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL +; RUN: not opt -passes="thinlto" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL +; RUN: not opt -passes="thinlto" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL +; RUN: not opt -passes="lto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL +; RUN: not opt -passes="lto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL +; RUN: not opt -passes="lto" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL +; RUN: not opt -passes="lto" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL + +; MISSING-OPT-LEVEL: invalid optimization level '' +; INVALID-OPT-LEVEL: invalid optimization level 'foo'