Skip to content

Commit d2bea2b

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 44df89c commit d2bea2b

File tree

7 files changed

+47
-29
lines changed

7 files changed

+47
-29
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: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ class PassBuilder {
497497
/// This extension point allows adding optimizations at the very end of the
498498
/// function optimization pipeline.
499499
void registerOptimizerLastEPCallback(
500-
const std::function<void(ModulePassManager &, OptimizationLevel)> &C) {
500+
const std::function<void(ModulePassManager &, OptimizationLevel,
501+
ThinOrFullLTOPhase)> &C) {
501502
OptimizerLastEPCallbacks.push_back(C);
502503
}
503504

@@ -630,7 +631,8 @@ class PassBuilder {
630631
void invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM,
631632
OptimizationLevel Level);
632633
void invokeOptimizerLastEPCallbacks(ModulePassManager &MPM,
633-
OptimizationLevel Level);
634+
OptimizationLevel Level,
635+
ThinOrFullLTOPhase Phase);
634636
void invokeFullLinkTimeOptimizationEarlyEPCallbacks(ModulePassManager &MPM,
635637
OptimizationLevel Level);
636638
void invokeFullLinkTimeOptimizationLastEPCallbacks(ModulePassManager &MPM,
@@ -755,7 +757,9 @@ class PassBuilder {
755757
// Module callbacks
756758
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
757759
OptimizerEarlyEPCallbacks;
758-
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
760+
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel,
761+
ThinOrFullLTOPhase)>,
762+
2>
759763
OptimizerLastEPCallbacks;
760764
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
761765
FullLinkTimeOptimizationEarlyEPCallbacks;

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 7 additions & 5 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) {
@@ -1524,7 +1525,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
15241525
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM),
15251526
PTO.EagerlyInvalidateAnalyses));
15261527

1527-
invokeOptimizerLastEPCallbacks(MPM, Level);
1528+
invokeOptimizerLastEPCallbacks(MPM, Level, LTOPhase);
15281529

15291530
// Split out cold code. Splitting is done late to avoid hiding context from
15301531
// other optimizations and inadvertently regressing performance. The tradeoff
@@ -1671,7 +1672,8 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
16711672
// optimization is going to be done in PostLink stage, but clang can't add
16721673
// callbacks there in case of in-process ThinLTO called by linker.
16731674
invokeOptimizerEarlyEPCallbacks(MPM, Level);
1674-
invokeOptimizerLastEPCallbacks(MPM, Level);
1675+
invokeOptimizerLastEPCallbacks(MPM, Level,
1676+
ThinOrFullLTOPhase::ThinLTOPreLink);
16751677

16761678
// Emit annotation remarks.
16771679
addAnnotationRemarksPass(MPM);
@@ -2159,7 +2161,7 @@ ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
21592161
CoroPM.addPass(GlobalDCEPass());
21602162
MPM.addPass(CoroConditionalWrapper(std::move(CoroPM)));
21612163

2162-
invokeOptimizerLastEPCallbacks(MPM, Level);
2164+
invokeOptimizerLastEPCallbacks(MPM, Level, ThinOrFullLTOPhase::None);
21632165

21642166
if (LTOPreLink)
21652167
addRequiredLTOPreLinkPasses(MPM);

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
@@ -1023,7 +1023,8 @@ static void addPreloadKernArgHint(Function &F, TargetMachine &TM) {
10231023
}
10241024
}
10251025

1026-
static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
1026+
static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM,
1027+
bool HasWholeProgramVisibility) {
10271028
SetVector<Function *> Functions;
10281029
for (Function &F : M) {
10291030
if (!F.isIntrinsic())
@@ -1041,6 +1042,7 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
10411042
&AAUnderlyingObjects::ID});
10421043

10431044
AttributorConfig AC(CGUpdater);
1045+
AC.IsClosedWorldModule = HasWholeProgramVisibility;
10441046
AC.Allowed = &Allowed;
10451047
AC.IsModulePass = true;
10461048
AC.DefaultInitializeLiveInternals = false;
@@ -1086,7 +1088,7 @@ class AMDGPUAttributorLegacy : public ModulePass {
10861088

10871089
bool runOnModule(Module &M) override {
10881090
AnalysisGetter AG(this);
1089-
return runImpl(M, AG, *TM);
1091+
return runImpl(M, AG, *TM, /*HasWholeProgramVisibility=*/false);
10901092
}
10911093

10921094
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -1107,8 +1109,9 @@ PreservedAnalyses llvm::AMDGPUAttributorPass::run(Module &M,
11071109
AnalysisGetter AG(FAM);
11081110

11091111
// TODO: Probably preserves CFG
1110-
return runImpl(M, AG, TM) ? PreservedAnalyses::none()
1111-
: PreservedAnalyses::all();
1112+
return runImpl(M, AG, TM, HasWholeProgramVisibility)
1113+
? PreservedAnalyses::none()
1114+
: PreservedAnalyses::all();
11121115
}
11131116

11141117
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
@@ -310,7 +310,7 @@ static void registerEPCallbacks(PassBuilder &PB) {
310310
});
311311
if (tryParsePipelineText<ModulePassManager>(PB, OptimizerLastEPPipeline))
312312
PB.registerOptimizerLastEPCallback(
313-
[&PB](ModulePassManager &PM, OptimizationLevel) {
313+
[&PB](ModulePassManager &PM, OptimizationLevel, ThinOrFullLTOPhase) {
314314
ExitOnError Err("Unable to parse OptimizerLastEP pipeline: ");
315315
Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline));
316316
});

0 commit comments

Comments
 (0)