Skip to content

Commit 3666b42

Browse files
nikicmacurtis-amd
authored andcommitted
[PassBuilder] Treat pipeline aliases as normal passes (llvm#146038)
Pipelines like `-passes="default<O3>"` are currently parsed in a special way. Switch them to work like normal, parameterized module passes.
1 parent 905f987 commit 3666b42

File tree

3 files changed

+77
-59
lines changed

3 files changed

+77
-59
lines changed

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,6 @@ static cl::opt<bool> DoFunctionSpecialize("function-specialize",
485485

486486
// AOCC end
487487

488-
static const Regex DefaultAliasRegex(
489-
"^(default|default-post-link|thinlto-pre-link|thinlto|lto-pre-link|lto)"
490-
"<(O[0123sz])>$");
491-
492488
cl::opt<bool> llvm::PrintPipelinePasses(
493489
"print-pipeline-passes",
494490
cl::desc("Print a '-passes' compatible string describing the pipeline "
@@ -730,6 +726,15 @@ static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {
730726
.Default(std::nullopt);
731727
}
732728

729+
static Expected<OptimizationLevel> parseOptLevelParam(StringRef S) {
730+
std::optional<OptimizationLevel> OptLevel = parseOptLevel(S);
731+
if (OptLevel)
732+
return *OptLevel;
733+
return make_error<StringError>(
734+
formatv("invalid optimization level '{}'", S).str(),
735+
inconvertibleErrorCode());
736+
}
737+
733738
Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,
734739
StringRef OptionName,
735740
StringRef PassName) {
@@ -1619,13 +1624,6 @@ Expected<bool> parseVirtRegRewriterPassOptions(StringRef Params) {
16191624

16201625
} // namespace
16211626

1622-
/// Tests whether a pass name starts with a valid prefix for a default pipeline
1623-
/// alias.
1624-
static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {
1625-
return Name.starts_with("default") || Name.starts_with("thinlto") ||
1626-
Name.starts_with("lto");
1627-
}
1628-
16291627
/// Tests whether registered callbacks will accept a given pass name.
16301628
///
16311629
/// When parsing a pipeline text, the type of the outermost pipeline may be
@@ -1647,10 +1645,6 @@ static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {
16471645

16481646
template <typename CallbacksT>
16491647
static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
1650-
// Manually handle aliases for pre-configured pipeline fragments.
1651-
if (startsWithDefaultPipelineAliasPrefix(Name))
1652-
return DefaultAliasRegex.match(Name);
1653-
16541648
StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });
16551649

16561650
// Explicitly handle pass manager names.
@@ -1849,6 +1843,15 @@ PassBuilder::parsePipelineText(StringRef Text) {
18491843
return {std::move(ResultPipeline)};
18501844
}
18511845

1846+
static void setupOptionsForPipelineAlias(PipelineTuningOptions &PTO,
1847+
OptimizationLevel L) {
1848+
// This is consistent with old pass manager invoked via opt, but
1849+
// inconsistent with clang. Clang doesn't enable loop vectorization
1850+
// but does enable slp vectorization at Oz.
1851+
PTO.LoopVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1852+
PTO.SLPVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1853+
}
1854+
18521855
Error PassBuilder::parseModulePass(ModulePassManager &MPM,
18531856
const PipelineElement &E) {
18541857
auto &Name = E.Name;
@@ -1901,50 +1904,6 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM,
19011904
;
19021905
}
19031906

1904-
// Manually handle aliases for pre-configured pipeline fragments.
1905-
if (startsWithDefaultPipelineAliasPrefix(Name)) {
1906-
SmallVector<StringRef, 3> Matches;
1907-
if (!DefaultAliasRegex.match(Name, &Matches))
1908-
return make_error<StringError>(
1909-
formatv("unknown default pipeline alias '{}'", Name).str(),
1910-
inconvertibleErrorCode());
1911-
1912-
assert(Matches.size() == 3 && "Must capture two matched strings!");
1913-
1914-
OptimizationLevel L = *parseOptLevel(Matches[2]);
1915-
1916-
// This is consistent with old pass manager invoked via opt, but
1917-
// inconsistent with clang. Clang doesn't enable loop vectorization
1918-
// but does enable slp vectorization at Oz.
1919-
PTO.LoopVectorization =
1920-
L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1921-
PTO.SLPVectorization =
1922-
L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1923-
1924-
if (Matches[1] == "default") {
1925-
MPM.addPass(buildPerModuleDefaultPipeline(L));
1926-
} else if (Matches[1] == "default-post-link") {
1927-
MPM.addPass(buildPerModuleDefaultPipeline(
1928-
L, ThinOrFullLTOPhase::CustomLTOPostLink));
1929-
} else if (Matches[1] == "thinlto-pre-link") {
1930-
MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));
1931-
} else if (Matches[1] == "thinlto") {
1932-
MPM.addPass(buildThinLTODefaultPipeline(L, nullptr));
1933-
} else if (Matches[1] == "lto-pre-link") {
1934-
if (PTO.UnifiedLTO)
1935-
// When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This
1936-
// avoids compile-time performance regressions and keeps the pre-link
1937-
// LTO pipeline "unified" for both LTO modes.
1938-
MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));
1939-
else
1940-
MPM.addPass(buildLTOPreLinkDefaultPipeline(L));
1941-
} else {
1942-
assert(Matches[1] == "lto" && "Not one of the matched options!");
1943-
MPM.addPass(buildLTODefaultPipeline(L, nullptr));
1944-
}
1945-
return Error::success();
1946-
}
1947-
19481907
// Finally expand the basic registered passes from the .inc file.
19491908
#define MODULE_PASS(NAME, CREATE_PASS) \
19501909
if (Name == NAME) { \

llvm/lib/Passes/PassRegistry.def

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,50 @@ MODULE_PASS_WITH_PARAMS(
241241
},
242242
parseStructuralHashPrinterPassOptions, "detailed;call-target-ignored")
243243

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

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

0 commit comments

Comments
 (0)