Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 18 additions & 55 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,6 @@

using namespace llvm;

static const Regex DefaultAliasRegex(
"^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");

cl::opt<bool> llvm::PrintPipelinePasses(
"print-pipeline-passes",
cl::desc("Print a '-passes' compatible string describing the pipeline "
Expand Down Expand Up @@ -618,6 +615,15 @@ static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {
.Default(std::nullopt);
}

static Expected<OptimizationLevel> parseOptLevelParam(StringRef S) {
std::optional<OptimizationLevel> OptLevel = parseOptLevel(S);
if (OptLevel)
return *OptLevel;
return make_error<StringError>(
formatv("invalid optimization level '{}'", S).str(),
inconvertibleErrorCode());
}

Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,
StringRef OptionName,
StringRef PassName) {
Expand Down Expand Up @@ -1507,13 +1513,6 @@ Expected<bool> 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
Expand All @@ -1535,10 +1534,6 @@ static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {

template <typename CallbacksT>
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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1789,47 +1793,6 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
;
}

// Manually handle aliases for pre-configured pipeline fragments.
if (startsWithDefaultPipelineAliasPrefix(Name)) {
SmallVector<StringRef, 3> Matches;
if (!DefaultAliasRegex.match(Name, &Matches))
return make_error<StringError>(
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) { \
Expand Down
37 changes: 37 additions & 0 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions llvm/test/Other/pipeline-alias-errors.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; RUN: not opt -passes="default" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
; RUN: not opt -passes="default<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL
Comment on lines +1 to +2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check errors with the other names too?

; RUN: not opt -passes="thinlto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
; RUN: not opt -passes="thinlto-pre-link<foo>" < %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<foo>" < %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<foo>" < %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<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL

; MISSING-OPT-LEVEL: invalid optimization level ''
; INVALID-OPT-LEVEL: invalid optimization level 'foo'