Skip to content

Commit 7f223d1

Browse files
authored
[PassBuilder] Treat pipeline aliases as normal passes (#146038)
Pipelines like `-passes="default<O3>"` are currently parsed in a special way. Switch them to work like normal, parameterized module passes.
1 parent 613804c commit 7f223d1

File tree

3 files changed

+68
-55
lines changed

3 files changed

+68
-55
lines changed

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 18 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,6 @@
374374

375375
using namespace llvm;
376376

377-
static const Regex DefaultAliasRegex(
378-
"^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");
379-
380377
cl::opt<bool> llvm::PrintPipelinePasses(
381378
"print-pipeline-passes",
382379
cl::desc("Print a '-passes' compatible string describing the pipeline "
@@ -618,6 +615,15 @@ static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {
618615
.Default(std::nullopt);
619616
}
620617

618+
static Expected<OptimizationLevel> parseOptLevelParam(StringRef S) {
619+
std::optional<OptimizationLevel> OptLevel = parseOptLevel(S);
620+
if (OptLevel)
621+
return *OptLevel;
622+
return make_error<StringError>(
623+
formatv("invalid optimization level '{}'", S).str(),
624+
inconvertibleErrorCode());
625+
}
626+
621627
Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,
622628
StringRef OptionName,
623629
StringRef PassName) {
@@ -1507,13 +1513,6 @@ Expected<bool> parseVirtRegRewriterPassOptions(StringRef Params) {
15071513

15081514
} // namespace
15091515

1510-
/// Tests whether a pass name starts with a valid prefix for a default pipeline
1511-
/// alias.
1512-
static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {
1513-
return Name.starts_with("default") || Name.starts_with("thinlto") ||
1514-
Name.starts_with("lto");
1515-
}
1516-
15171516
/// Tests whether registered callbacks will accept a given pass name.
15181517
///
15191518
/// When parsing a pipeline text, the type of the outermost pipeline may be
@@ -1535,10 +1534,6 @@ static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {
15351534

15361535
template <typename CallbacksT>
15371536
static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
1538-
// Manually handle aliases for pre-configured pipeline fragments.
1539-
if (startsWithDefaultPipelineAliasPrefix(Name))
1540-
return DefaultAliasRegex.match(Name);
1541-
15421537
StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });
15431538

15441539
// Explicitly handle pass manager names.
@@ -1737,6 +1732,15 @@ PassBuilder::parsePipelineText(StringRef Text) {
17371732
return {std::move(ResultPipeline)};
17381733
}
17391734

1735+
static void setupOptionsForPipelineAlias(PipelineTuningOptions &PTO,
1736+
OptimizationLevel L) {
1737+
// This is consistent with old pass manager invoked via opt, but
1738+
// inconsistent with clang. Clang doesn't enable loop vectorization
1739+
// but does enable slp vectorization at Oz.
1740+
PTO.LoopVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1741+
PTO.SLPVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1742+
}
1743+
17401744
Error PassBuilder::parseModulePass(ModulePassManager &MPM,
17411745
const PipelineElement &E) {
17421746
auto &Name = E.Name;
@@ -1789,47 +1793,6 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
17891793
;
17901794
}
17911795

1792-
// Manually handle aliases for pre-configured pipeline fragments.
1793-
if (startsWithDefaultPipelineAliasPrefix(Name)) {
1794-
SmallVector<StringRef, 3> Matches;
1795-
if (!DefaultAliasRegex.match(Name, &Matches))
1796-
return make_error<StringError>(
1797-
formatv("unknown default pipeline alias '{}'", Name).str(),
1798-
inconvertibleErrorCode());
1799-
1800-
assert(Matches.size() == 3 && "Must capture two matched strings!");
1801-
1802-
OptimizationLevel L = *parseOptLevel(Matches[2]);
1803-
1804-
// This is consistent with old pass manager invoked via opt, but
1805-
// inconsistent with clang. Clang doesn't enable loop vectorization
1806-
// but does enable slp vectorization at Oz.
1807-
PTO.LoopVectorization =
1808-
L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1809-
PTO.SLPVectorization =
1810-
L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1811-
1812-
if (Matches[1] == "default") {
1813-
MPM.addPass(buildPerModuleDefaultPipeline(L));
1814-
} else if (Matches[1] == "thinlto-pre-link") {
1815-
MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));
1816-
} else if (Matches[1] == "thinlto") {
1817-
MPM.addPass(buildThinLTODefaultPipeline(L, nullptr));
1818-
} else if (Matches[1] == "lto-pre-link") {
1819-
if (PTO.UnifiedLTO)
1820-
// When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This
1821-
// avoids compile-time performance regressions and keeps the pre-link
1822-
// LTO pipeline "unified" for both LTO modes.
1823-
MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));
1824-
else
1825-
MPM.addPass(buildLTOPreLinkDefaultPipeline(L));
1826-
} else {
1827-
assert(Matches[1] == "lto" && "Not one of the matched options!");
1828-
MPM.addPass(buildLTODefaultPipeline(L, nullptr));
1829-
}
1830-
return Error::success();
1831-
}
1832-
18331796
// Finally expand the basic registered passes from the .inc file.
18341797
#define MODULE_PASS(NAME, CREATE_PASS) \
18351798
if (Name == NAME) { \

llvm/lib/Passes/PassRegistry.def

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,43 @@ MODULE_PASS_WITH_PARAMS(
240240
},
241241
parseStructuralHashPrinterPassOptions, "detailed;call-target-ignored")
242242

243+
MODULE_PASS_WITH_PARAMS(
244+
"default", "", [&](OptimizationLevel L) {
245+
setupOptionsForPipelineAlias(PTO, L);
246+
return buildPerModuleDefaultPipeline(L);
247+
},
248+
parseOptLevelParam, "O0;O1;O2;O3;Os;Oz")
249+
MODULE_PASS_WITH_PARAMS(
250+
"thinlto-pre-link", "", [&](OptimizationLevel L) {
251+
setupOptionsForPipelineAlias(PTO, L);
252+
return buildThinLTOPreLinkDefaultPipeline(L);
253+
},
254+
parseOptLevelParam, "O0;O1;O2;O3;Os;Oz")
255+
MODULE_PASS_WITH_PARAMS(
256+
"thinlto", "", [&](OptimizationLevel L) {
257+
setupOptionsForPipelineAlias(PTO, L);
258+
return buildThinLTODefaultPipeline(L, nullptr);
259+
},
260+
parseOptLevelParam, "O0;O1;O2;O3;Os;Oz")
261+
MODULE_PASS_WITH_PARAMS(
262+
"lto-pre-link", "", [&](OptimizationLevel L) {
263+
setupOptionsForPipelineAlias(PTO, L);
264+
if (PTO.UnifiedLTO) {
265+
// When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This
266+
// avoids compile-time performance regressions and keeps the pre-link
267+
// LTO pipeline "unified" for both LTO modes.
268+
return buildThinLTOPreLinkDefaultPipeline(L);
269+
}
270+
return buildLTOPreLinkDefaultPipeline(L);
271+
},
272+
parseOptLevelParam, "O0;O1;O2;O3;Os;Oz")
273+
MODULE_PASS_WITH_PARAMS(
274+
"lto", "", [&](OptimizationLevel L) {
275+
setupOptionsForPipelineAlias(PTO, L);
276+
return buildLTODefaultPipeline(L, nullptr);
277+
},
278+
parseOptLevelParam, "O0;O1;O2;O3;Os;Oz")
279+
243280
#undef MODULE_PASS_WITH_PARAMS
244281

245282
#ifndef CGSCC_ANALYSIS
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: not opt -passes="default" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
2+
; RUN: not opt -passes="default<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL
3+
; RUN: not opt -passes="thinlto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
4+
; RUN: not opt -passes="thinlto-pre-link<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL
5+
; RUN: not opt -passes="thinlto" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
6+
; RUN: not opt -passes="thinlto<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL
7+
; RUN: not opt -passes="lto-pre-link" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
8+
; RUN: not opt -passes="lto-pre-link<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL
9+
; RUN: not opt -passes="lto" < %s 2>&1 | FileCheck %s --check-prefix=MISSING-OPT-LEVEL
10+
; RUN: not opt -passes="lto<foo>" < %s 2>&1 | FileCheck %s --check-prefix=INVALID-OPT-LEVEL
11+
12+
; MISSING-OPT-LEVEL: invalid optimization level ''
13+
; INVALID-OPT-LEVEL: invalid optimization level 'foo'

0 commit comments

Comments
 (0)