Skip to content

Commit 913f6a7

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 52df8e6 commit 913f6a7

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
@@ -365,9 +365,10 @@ void PassBuilder::invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM,
365365
C(MPM, Level);
366366
}
367367
void PassBuilder::invokeOptimizerLastEPCallbacks(ModulePassManager &MPM,
368-
OptimizationLevel Level) {
368+
OptimizationLevel Level,
369+
ThinOrFullLTOPhase Phase) {
369370
for (auto &C : OptimizerLastEPCallbacks)
370-
C(MPM, Level);
371+
C(MPM, Level, Phase);
371372
}
372373
void PassBuilder::invokeFullLinkTimeOptimizationEarlyEPCallbacks(
373374
ModulePassManager &MPM, OptimizationLevel Level) {
@@ -1527,7 +1528,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
15271528
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM),
15281529
PTO.EagerlyInvalidateAnalyses));
15291530

1530-
invokeOptimizerLastEPCallbacks(MPM, Level);
1531+
invokeOptimizerLastEPCallbacks(MPM, Level, LTOPhase);
15311532

15321533
// Split out cold code. Splitting is done late to avoid hiding context from
15331534
// other optimizations and inadvertently regressing performance. The tradeoff
@@ -1569,9 +1570,9 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
15691570

15701571
ModulePassManager
15711572
PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
1572-
bool LTOPreLink) {
1573+
ThinOrFullLTOPhase Phase) {
15731574
if (Level == OptimizationLevel::O0)
1574-
return buildO0DefaultPipeline(Level, LTOPreLink);
1575+
return buildO0DefaultPipeline(Level, Phase);
15751576

15761577
ModulePassManager MPM;
15771578

@@ -1587,14 +1588,11 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
15871588
// Apply module pipeline start EP callback.
15881589
invokePipelineStartEPCallbacks(MPM, Level);
15891590

1590-
const ThinOrFullLTOPhase LTOPhase = LTOPreLink
1591-
? ThinOrFullLTOPhase::FullLTOPreLink
1592-
: ThinOrFullLTOPhase::None;
15931591
// Add the core simplification pipeline.
1594-
MPM.addPass(buildModuleSimplificationPipeline(Level, LTOPhase));
1592+
MPM.addPass(buildModuleSimplificationPipeline(Level, Phase));
15951593

15961594
// Now add the optimization pipeline.
1597-
MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPhase));
1595+
MPM.addPass(buildModuleOptimizationPipeline(Level, Phase));
15981596

15991597
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
16001598
PGOOpt->Action == PGOOptions::SampleUse)
@@ -1603,7 +1601,7 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
16031601
// Emit annotation remarks.
16041602
addAnnotationRemarksPass(MPM);
16051603

1606-
if (LTOPreLink)
1604+
if (isLTOPreLink(Phase))
16071605
addRequiredLTOPreLinkPasses(MPM);
16081606
return MPM;
16091607
}
@@ -1634,7 +1632,7 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
16341632
ModulePassManager
16351633
PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
16361634
if (Level == OptimizationLevel::O0)
1637-
return buildO0DefaultPipeline(Level, /*LTOPreLink*/true);
1635+
return buildO0DefaultPipeline(Level, ThinOrFullLTOPhase::ThinLTOPreLink);
16381636

16391637
ModulePassManager MPM;
16401638

@@ -1674,7 +1672,8 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
16741672
// optimization is going to be done in PostLink stage, but clang can't add
16751673
// callbacks there in case of in-process ThinLTO called by linker.
16761674
invokeOptimizerEarlyEPCallbacks(MPM, Level);
1677-
invokeOptimizerLastEPCallbacks(MPM, Level);
1675+
invokeOptimizerLastEPCallbacks(MPM, Level,
1676+
ThinOrFullLTOPhase::ThinLTOPreLink);
16781677

16791678
// Emit annotation remarks.
16801679
addAnnotationRemarksPass(MPM);
@@ -1743,7 +1742,7 @@ ModulePassManager
17431742
PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
17441743
// FIXME: We should use a customized pre-link pipeline!
17451744
return buildPerModuleDefaultPipeline(Level,
1746-
/* LTOPreLink */ true);
1745+
ThinOrFullLTOPhase::FullLTOPreLink);
17471746
}
17481747

17491748
ModulePassManager
@@ -2068,8 +2067,9 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level,
20682067
return MPM;
20692068
}
20702069

2071-
ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
2072-
bool LTOPreLink) {
2070+
ModulePassManager
2071+
PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
2072+
ThinOrFullLTOPhase Phase) {
20732073
assert(Level == OptimizationLevel::O0 &&
20742074
"buildO0DefaultPipeline should only be used with O0");
20752075

@@ -2162,9 +2162,9 @@ ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
21622162
CoroPM.addPass(GlobalDCEPass());
21632163
MPM.addPass(CoroConditionalWrapper(std::move(CoroPM)));
21642164

2165-
invokeOptimizerLastEPCallbacks(MPM, Level);
2165+
invokeOptimizerLastEPCallbacks(MPM, Level, Phase);
21662166

2167-
if (LTOPreLink)
2167+
if (isLTOPreLink(Phase))
21682168
addRequiredLTOPreLinkPasses(MPM);
21692169

21702170
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())
@@ -1042,6 +1043,7 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
10421043
&AAUnderlyingObjects::ID, &AAIndirectCallInfo::ID, &AAInstanceInfo::ID});
10431044

10441045
AttributorConfig AC(CGUpdater);
1046+
AC.IsClosedWorldModule = HasWholeProgramVisibility;
10451047
AC.Allowed = &Allowed;
10461048
AC.IsModulePass = true;
10471049
AC.DefaultInitializeLiveInternals = false;
@@ -1099,7 +1101,7 @@ class AMDGPUAttributorLegacy : public ModulePass {
10991101

11001102
bool runOnModule(Module &M) override {
11011103
AnalysisGetter AG(this);
1102-
return runImpl(M, AG, *TM);
1104+
return runImpl(M, AG, *TM, /*HasWholeProgramVisibility=*/false);
11031105
}
11041106

11051107
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -1120,8 +1122,9 @@ PreservedAnalyses llvm::AMDGPUAttributorPass::run(Module &M,
11201122
AnalysisGetter AG(FAM);
11211123

11221124
// TODO: Probably preserves CFG
1123-
return runImpl(M, AG, TM) ? PreservedAnalyses::none()
1124-
: PreservedAnalyses::all();
1125+
return runImpl(M, AG, TM, HasWholeProgramVisibility)
1126+
? PreservedAnalyses::none()
1127+
: PreservedAnalyses::all();
11251128
}
11261129

11271130
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)