Skip to content

Commit 0110da5

Browse files
committed
[LLVM][PassBuilder] Extend the function signature of callback for optimizer pipeline extension point
These callbacks can be invoked in multiple places when building an optimization pipeline, both in compile time and link time. However, there is no indicator on what pipeline it is currently building. In this patch, an extra argument is added to indicate its (Thin)LTO stage such that the callback can check it if needed. There is no test expected from this, and the benefit of this change will be demonstrated in #66488.
1 parent b64ec3c commit 0110da5

File tree

7 files changed

+64
-46
lines changed

7 files changed

+64
-46
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
643643

644644
// Ensure we lower KCFI operand bundles with -O0.
645645
PB.registerOptimizerLastEPCallback(
646-
[&](ModulePassManager &MPM, OptimizationLevel Level) {
646+
[&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) {
647647
if (Level == OptimizationLevel::O0 &&
648648
LangOpts.Sanitize.has(SanitizerKind::KCFI))
649649
MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
@@ -662,8 +662,8 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
662662
static void addSanitizers(const Triple &TargetTriple,
663663
const CodeGenOptions &CodeGenOpts,
664664
const LangOptions &LangOpts, PassBuilder &PB) {
665-
auto SanitizersCallback = [&](ModulePassManager &MPM,
666-
OptimizationLevel Level) {
665+
auto SanitizersCallback = [&](ModulePassManager &MPM, OptimizationLevel Level,
666+
ThinOrFullLTOPhase) {
667667
if (CodeGenOpts.hasSanitizeCoverage()) {
668668
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
669669
MPM.addPass(SanitizerCoveragePass(
@@ -749,7 +749,7 @@ static void addSanitizers(const Triple &TargetTriple,
749749
PB.registerOptimizerEarlyEPCallback(
750750
[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) {
751751
ModulePassManager NewMPM;
752-
SanitizersCallback(NewMPM, Level);
752+
SanitizersCallback(NewMPM, Level, ThinOrFullLTOPhase::None);
753753
if (!NewMPM.isEmpty()) {
754754
// Sanitizers can abandon<GlobalsAA>.
755755
NewMPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());
@@ -1018,11 +1018,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
10181018
// TODO: Consider passing the MemoryProfileOutput to the pass builder via
10191019
// the PGOOptions, and set this up there.
10201020
if (!CodeGenOpts.MemoryProfileOutput.empty()) {
1021-
PB.registerOptimizerLastEPCallback(
1022-
[](ModulePassManager &MPM, OptimizationLevel Level) {
1023-
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
1024-
MPM.addPass(ModuleMemProfilerPass());
1025-
});
1021+
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
1022+
OptimizationLevel Level,
1023+
ThinOrFullLTOPhase) {
1024+
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
1025+
MPM.addPass(ModuleMemProfilerPass());
1026+
});
10261027
}
10271028

10281029
if (CodeGenOpts.FatLTO) {

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,9 @@ class PassBuilder {
246246
/// optimization and code generation without any link-time optimization. It
247247
/// typically correspond to frontend "-O[123]" options for optimization
248248
/// levels \c O1, \c O2 and \c O3 resp.
249-
ModulePassManager buildPerModuleDefaultPipeline(OptimizationLevel Level,
250-
bool LTOPreLink = false);
249+
ModulePassManager buildPerModuleDefaultPipeline(
250+
OptimizationLevel Level,
251+
ThinOrFullLTOPhase Phase = ThinOrFullLTOPhase::None);
251252

252253
/// Build a fat object default optimization pipeline.
253254
///
@@ -297,8 +298,9 @@ class PassBuilder {
297298
/// Build an O0 pipeline with the minimal semantically required passes.
298299
///
299300
/// This should only be used for non-LTO and LTO pre-link pipelines.
300-
ModulePassManager buildO0DefaultPipeline(OptimizationLevel Level,
301-
bool LTOPreLink = false);
301+
ModulePassManager
302+
buildO0DefaultPipeline(OptimizationLevel Level,
303+
ThinOrFullLTOPhase Phase = ThinOrFullLTOPhase::None);
302304

303305
/// Build the default `AAManager` with the default alias analysis pipeline
304306
/// registered.
@@ -497,7 +499,8 @@ class PassBuilder {
497499
/// This extension point allows adding optimizations at the very end of the
498500
/// function optimization pipeline.
499501
void registerOptimizerLastEPCallback(
500-
const std::function<void(ModulePassManager &, OptimizationLevel)> &C) {
502+
const std::function<void(ModulePassManager &, OptimizationLevel,
503+
ThinOrFullLTOPhase)> &C) {
501504
OptimizerLastEPCallbacks.push_back(C);
502505
}
503506

@@ -630,7 +633,8 @@ class PassBuilder {
630633
void invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM,
631634
OptimizationLevel Level);
632635
void invokeOptimizerLastEPCallbacks(ModulePassManager &MPM,
633-
OptimizationLevel Level);
636+
OptimizationLevel Level,
637+
ThinOrFullLTOPhase Phase);
634638
void invokeFullLinkTimeOptimizationEarlyEPCallbacks(ModulePassManager &MPM,
635639
OptimizationLevel Level);
636640
void invokeFullLinkTimeOptimizationLastEPCallbacks(ModulePassManager &MPM,
@@ -755,7 +759,9 @@ class PassBuilder {
755759
// Module callbacks
756760
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
757761
OptimizerEarlyEPCallbacks;
758-
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
762+
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel,
763+
ThinOrFullLTOPhase)>,
764+
2>
759765
OptimizerLastEPCallbacks;
760766
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
761767
FullLinkTimeOptimizationEarlyEPCallbacks;

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,10 @@ void PassBuilder::invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM,
369369
C(MPM, Level);
370370
}
371371
void PassBuilder::invokeOptimizerLastEPCallbacks(ModulePassManager &MPM,
372-
OptimizationLevel Level) {
372+
OptimizationLevel Level,
373+
ThinOrFullLTOPhase Phase) {
373374
for (auto &C : OptimizerLastEPCallbacks)
374-
C(MPM, Level);
375+
C(MPM, Level, Phase);
375376
}
376377
void PassBuilder::invokeFullLinkTimeOptimizationEarlyEPCallbacks(
377378
ModulePassManager &MPM, OptimizationLevel Level) {
@@ -1539,7 +1540,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
15391540
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM),
15401541
PTO.EagerlyInvalidateAnalyses));
15411542

1542-
invokeOptimizerLastEPCallbacks(MPM, Level);
1543+
invokeOptimizerLastEPCallbacks(MPM, Level, LTOPhase);
15431544

15441545
// Split out cold code. Splitting is done late to avoid hiding context from
15451546
// other optimizations and inadvertently regressing performance. The tradeoff
@@ -1581,9 +1582,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
15811582

15821583
ModulePassManager
15831584
PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
1584-
bool LTOPreLink) {
1585+
ThinOrFullLTOPhase Phase) {
15851586
if (Level == OptimizationLevel::O0)
1586-
return buildO0DefaultPipeline(Level, LTOPreLink);
1587+
return buildO0DefaultPipeline(Level, Phase);
15871588

15881589
ModulePassManager MPM;
15891590

@@ -1599,14 +1600,11 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
15991600
// Apply module pipeline start EP callback.
16001601
invokePipelineStartEPCallbacks(MPM, Level);
16011602

1602-
const ThinOrFullLTOPhase LTOPhase = LTOPreLink
1603-
? ThinOrFullLTOPhase::FullLTOPreLink
1604-
: ThinOrFullLTOPhase::None;
16051603
// Add the core simplification pipeline.
1606-
MPM.addPass(buildModuleSimplificationPipeline(Level, LTOPhase));
1604+
MPM.addPass(buildModuleSimplificationPipeline(Level, Phase));
16071605

16081606
// Now add the optimization pipeline.
1609-
MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPhase));
1607+
MPM.addPass(buildModuleOptimizationPipeline(Level, Phase));
16101608

16111609
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
16121610
PGOOpt->Action == PGOOptions::SampleUse)
@@ -1615,7 +1613,7 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
16151613
// Emit annotation remarks.
16161614
addAnnotationRemarksPass(MPM);
16171615

1618-
if (LTOPreLink)
1616+
if (isLTOPreLink(Phase))
16191617
addRequiredLTOPreLinkPasses(MPM);
16201618
return MPM;
16211619
}
@@ -1646,7 +1644,7 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
16461644
ModulePassManager
16471645
PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
16481646
if (Level == OptimizationLevel::O0)
1649-
return buildO0DefaultPipeline(Level, /*LTOPreLink*/true);
1647+
return buildO0DefaultPipeline(Level, ThinOrFullLTOPhase::ThinLTOPreLink);
16501648

16511649
ModulePassManager MPM;
16521650

@@ -1691,7 +1689,8 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
16911689
// optimization is going to be done in PostLink stage, but clang can't add
16921690
// callbacks there in case of in-process ThinLTO called by linker.
16931691
invokeOptimizerEarlyEPCallbacks(MPM, Level);
1694-
invokeOptimizerLastEPCallbacks(MPM, Level);
1692+
invokeOptimizerLastEPCallbacks(MPM, Level,
1693+
ThinOrFullLTOPhase::ThinLTOPreLink);
16951694

16961695
// Emit annotation remarks.
16971696
addAnnotationRemarksPass(MPM);
@@ -1760,7 +1759,7 @@ ModulePassManager
17601759
PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
17611760
// FIXME: We should use a customized pre-link pipeline!
17621761
return buildPerModuleDefaultPipeline(Level,
1763-
/* LTOPreLink */ true);
1762+
ThinOrFullLTOPhase::FullLTOPreLink);
17641763
}
17651764

17661765
ModulePassManager
@@ -2085,8 +2084,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
20852084
return MPM;
20862085
}
20872086

2088-
ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
2089-
bool LTOPreLink) {
2087+
ModulePassManager
2088+
PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
2089+
ThinOrFullLTOPhase Phase) {
20902090
assert(Level == OptimizationLevel::O0 &&
20912091
"buildO0DefaultPipeline should only be used with O0");
20922092

@@ -2179,9 +2179,9 @@ ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
21792179
CoroPM.addPass(GlobalDCEPass());
21802180
MPM.addPass(CoroConditionalWrapper(std::move(CoroPM)));
21812181

2182-
invokeOptimizerLastEPCallbacks(MPM, Level);
2182+
invokeOptimizerLastEPCallbacks(MPM, Level, Phase);
21832183

2184-
if (LTOPreLink)
2184+
if (isLTOPreLink(Phase))
21852185
addRequiredLTOPreLinkPasses(MPM);
21862186

21872187
MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass()));

llvm/lib/Target/AMDGPU/AMDGPU.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,13 @@ class AMDGPUAttributorPass : public PassInfoMixin<AMDGPUAttributorPass> {
287287
private:
288288
TargetMachine &TM;
289289

290+
/// Asserts whether we can assume whole program visibility.
291+
bool HasWholeProgramVisibility = false;
292+
290293
public:
291-
AMDGPUAttributorPass(TargetMachine &TM) : TM(TM){};
294+
AMDGPUAttributorPass(TargetMachine &TM,
295+
bool HasWholeProgramVisibility = false)
296+
: TM(TM), HasWholeProgramVisibility(HasWholeProgramVisibility) {};
292297
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
293298
};
294299

llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,8 @@ static void addPreloadKernArgHint(Function &F, TargetMachine &TM) {
10241024
}
10251025
}
10261026

1027-
static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
1027+
static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM,
1028+
bool HasWholeProgramVisibility) {
10281029
SetVector<Function *> Functions;
10291030
for (Function &F : M) {
10301031
if (!F.isIntrinsic())
@@ -1043,6 +1044,7 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
10431044
&AAInstanceInfo::ID});
10441045

10451046
AttributorConfig AC(CGUpdater);
1047+
AC.IsClosedWorldModule = HasWholeProgramVisibility;
10461048
AC.Allowed = &Allowed;
10471049
AC.IsModulePass = true;
10481050
AC.DefaultInitializeLiveInternals = false;
@@ -1112,7 +1114,7 @@ class AMDGPUAttributorLegacy : public ModulePass {
11121114

11131115
bool runOnModule(Module &M) override {
11141116
AnalysisGetter AG(this);
1115-
return runImpl(M, AG, *TM);
1117+
return runImpl(M, AG, *TM, /*HasWholeProgramVisibility=*/false);
11161118
}
11171119

11181120
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -1133,8 +1135,9 @@ PreservedAnalyses llvm::AMDGPUAttributorPass::run(Module &M,
11331135
AnalysisGetter AG(FAM);
11341136

11351137
// TODO: Probably preserves CFG
1136-
return runImpl(M, AG, TM) ? PreservedAnalyses::none()
1137-
: PreservedAnalyses::all();
1138+
return runImpl(M, AG, TM, HasWholeProgramVisibility)
1139+
? PreservedAnalyses::none()
1140+
: PreservedAnalyses::all();
11381141
}
11391142

11401143
char AMDGPUAttributorLegacy::ID = 0;

llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -735,12 +735,15 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
735735
});
736736

737737
// FIXME: Why is AMDGPUAttributor not in CGSCC?
738-
PB.registerOptimizerLastEPCallback(
739-
[this](ModulePassManager &MPM, OptimizationLevel Level) {
740-
if (Level != OptimizationLevel::O0) {
741-
MPM.addPass(AMDGPUAttributorPass(*this));
742-
}
743-
});
738+
PB.registerOptimizerLastEPCallback([this](ModulePassManager &MPM,
739+
OptimizationLevel Level,
740+
ThinOrFullLTOPhase Phase) {
741+
if (Level != OptimizationLevel::O0) {
742+
MPM.addPass(AMDGPUAttributorPass(
743+
*this, Phase == ThinOrFullLTOPhase::FullLTOPostLink ||
744+
Phase == ThinOrFullLTOPhase::ThinLTOPostLink));
745+
}
746+
});
744747

745748
PB.registerFullLinkTimeOptimizationLastEPCallback(
746749
[this](ModulePassManager &PM, OptimizationLevel Level) {

llvm/tools/opt/NewPMDriver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static void registerEPCallbacks(PassBuilder &PB) {
306306
});
307307
if (tryParsePipelineText<ModulePassManager>(PB, OptimizerLastEPPipeline))
308308
PB.registerOptimizerLastEPCallback(
309-
[&PB](ModulePassManager &PM, OptimizationLevel) {
309+
[&PB](ModulePassManager &PM, OptimizationLevel, ThinOrFullLTOPhase) {
310310
ExitOnError Err("Unable to parse OptimizerLastEP pipeline: ");
311311
Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline));
312312
});

0 commit comments

Comments
 (0)