Skip to content

[LLVM][PassBuilder] Extend the function signature of callback for optimizer pipeline extension point #100945

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,

// Ensure we lower KCFI operand bundles with -O0.
PB.registerOptimizerLastEPCallback(
[&](ModulePassManager &MPM, OptimizationLevel Level) {
[&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) {
if (Level == OptimizationLevel::O0 &&
LangOpts.Sanitize.has(SanitizerKind::KCFI))
MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
Expand All @@ -662,8 +662,8 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
static void addSanitizers(const Triple &TargetTriple,
const CodeGenOptions &CodeGenOpts,
const LangOptions &LangOpts, PassBuilder &PB) {
auto SanitizersCallback = [&](ModulePassManager &MPM,
OptimizationLevel Level) {
auto SanitizersCallback = [&](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase) {
if (CodeGenOpts.hasSanitizeCoverage()) {
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
MPM.addPass(SanitizerCoveragePass(
Expand Down Expand Up @@ -749,7 +749,7 @@ static void addSanitizers(const Triple &TargetTriple,
PB.registerOptimizerEarlyEPCallback(
[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) {
ModulePassManager NewMPM;
SanitizersCallback(NewMPM, Level);
SanitizersCallback(NewMPM, Level, ThinOrFullLTOPhase::None);
if (!NewMPM.isEmpty()) {
// Sanitizers can abandon<GlobalsAA>.
NewMPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());
Expand Down Expand Up @@ -1018,11 +1018,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
// TODO: Consider passing the MemoryProfileOutput to the pass builder via
// the PGOOptions, and set this up there.
if (!CodeGenOpts.MemoryProfileOutput.empty()) {
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
MPM.addPass(ModuleMemProfilerPass());
});
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level,
ThinOrFullLTOPhase) {
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
MPM.addPass(ModuleMemProfilerPass());
});
}

if (CodeGenOpts.FatLTO) {
Expand Down
10 changes: 7 additions & 3 deletions llvm/include/llvm/Passes/PassBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,8 @@ class PassBuilder {
/// This extension point allows adding optimizations at the very end of the
/// function optimization pipeline.
void registerOptimizerLastEPCallback(
const std::function<void(ModulePassManager &, OptimizationLevel)> &C) {
const std::function<void(ModulePassManager &, OptimizationLevel,
ThinOrFullLTOPhase)> &C) {
OptimizerLastEPCallbacks.push_back(C);
}

Expand Down Expand Up @@ -630,7 +631,8 @@ class PassBuilder {
void invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM,
OptimizationLevel Level);
void invokeOptimizerLastEPCallbacks(ModulePassManager &MPM,
OptimizationLevel Level);
OptimizationLevel Level,
ThinOrFullLTOPhase Phase);
void invokeFullLinkTimeOptimizationEarlyEPCallbacks(ModulePassManager &MPM,
OptimizationLevel Level);
void invokeFullLinkTimeOptimizationLastEPCallbacks(ModulePassManager &MPM,
Expand Down Expand Up @@ -755,7 +757,9 @@ class PassBuilder {
// Module callbacks
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
OptimizerEarlyEPCallbacks;
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel,
ThinOrFullLTOPhase)>,
2>
OptimizerLastEPCallbacks;
SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2>
FullLinkTimeOptimizationEarlyEPCallbacks;
Expand Down
12 changes: 7 additions & 5 deletions llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,10 @@ void PassBuilder::invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM,
C(MPM, Level);
}
void PassBuilder::invokeOptimizerLastEPCallbacks(ModulePassManager &MPM,
OptimizationLevel Level) {
OptimizationLevel Level,
ThinOrFullLTOPhase Phase) {
for (auto &C : OptimizerLastEPCallbacks)
C(MPM, Level);
C(MPM, Level, Phase);
}
void PassBuilder::invokeFullLinkTimeOptimizationEarlyEPCallbacks(
ModulePassManager &MPM, OptimizationLevel Level) {
Expand Down Expand Up @@ -1524,7 +1525,7 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM),
PTO.EagerlyInvalidateAnalyses));

invokeOptimizerLastEPCallbacks(MPM, Level);
invokeOptimizerLastEPCallbacks(MPM, Level, LTOPhase);

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

// Emit annotation remarks.
addAnnotationRemarksPass(MPM);
Expand Down Expand Up @@ -2159,7 +2161,7 @@ ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level,
CoroPM.addPass(GlobalDCEPass());
MPM.addPass(CoroConditionalWrapper(std::move(CoroPM)));

invokeOptimizerLastEPCallbacks(MPM, Level);
invokeOptimizerLastEPCallbacks(MPM, Level, ThinOrFullLTOPhase::None);

if (LTOPreLink)
addRequiredLTOPreLinkPasses(MPM);
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/Target/AMDGPU/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,13 @@ class AMDGPUAttributorPass : public PassInfoMixin<AMDGPUAttributorPass> {
private:
TargetMachine &TM;

/// Asserts whether we can assume whole program visibility.
bool HasWholeProgramVisibility = false;

public:
AMDGPUAttributorPass(TargetMachine &TM) : TM(TM){};
AMDGPUAttributorPass(TargetMachine &TM,
bool HasWholeProgramVisibility = false)
: TM(TM), HasWholeProgramVisibility(HasWholeProgramVisibility) {};
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};

Expand Down
13 changes: 8 additions & 5 deletions llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,8 @@ static void addPreloadKernArgHint(Function &F, TargetMachine &TM) {
}
}

static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM,
bool HasWholeProgramVisibility) {
SetVector<Function *> Functions;
for (Function &F : M) {
if (!F.isIntrinsic())
Expand All @@ -1038,9 +1039,10 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) {
&AAPotentialValues::ID, &AAAMDFlatWorkGroupSize::ID,
&AAAMDWavesPerEU::ID, &AAAMDGPUNoAGPR::ID, &AACallEdges::ID,
&AAPointerInfo::ID, &AAPotentialConstantValues::ID,
&AAUnderlyingObjects::ID});
&AAUnderlyingObjects::ID, &AAIndirectCallInfo::ID});

AttributorConfig AC(CGUpdater);
AC.IsClosedWorldModule = HasWholeProgramVisibility;
AC.Allowed = &Allowed;
AC.IsModulePass = true;
AC.DefaultInitializeLiveInternals = false;
Expand Down Expand Up @@ -1086,7 +1088,7 @@ class AMDGPUAttributorLegacy : public ModulePass {

bool runOnModule(Module &M) override {
AnalysisGetter AG(this);
return runImpl(M, AG, *TM);
return runImpl(M, AG, *TM, /*HasWholeProgramVisibility=*/false);
}

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

// TODO: Probably preserves CFG
return runImpl(M, AG, TM) ? PreservedAnalyses::none()
: PreservedAnalyses::all();
return runImpl(M, AG, TM, HasWholeProgramVisibility)
? PreservedAnalyses::none()
: PreservedAnalyses::all();
}

char AMDGPUAttributorLegacy::ID = 0;
Expand Down
15 changes: 9 additions & 6 deletions llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,12 +735,15 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
});

// FIXME: Why is AMDGPUAttributor not in CGSCC?
PB.registerOptimizerLastEPCallback(
[this](ModulePassManager &MPM, OptimizationLevel Level) {
if (Level != OptimizationLevel::O0) {
MPM.addPass(AMDGPUAttributorPass(*this));
}
});
PB.registerOptimizerLastEPCallback([this](ModulePassManager &MPM,
OptimizationLevel Level,
ThinOrFullLTOPhase Phase) {
if (Level != OptimizationLevel::O0) {
MPM.addPass(AMDGPUAttributorPass(
*this, Phase == ThinOrFullLTOPhase::FullLTOPostLink ||
Phase == ThinOrFullLTOPhase::ThinLTOPostLink));
}
});

PB.registerFullLinkTimeOptimizationLastEPCallback(
[this](ModulePassManager &PM, OptimizationLevel Level) {
Expand Down
14 changes: 13 additions & 1 deletion llvm/test/CodeGen/AMDGPU/amdgpu-attributor-no-agpr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,19 @@ define amdgpu_kernel void @indirect_calls_none_agpr(i1 %cond) {
; CHECK-LABEL: define amdgpu_kernel void @indirect_calls_none_agpr(
; CHECK-SAME: i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[FPTR:%.*]] = select i1 [[COND]], ptr @empty, ptr @also_empty
; CHECK-NEXT: call void [[FPTR]]()
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FPTR]], @also_empty
; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
; CHECK: 2:
; CHECK-NEXT: call void @also_empty()
; CHECK-NEXT: br label [[TMP6:%.*]]
; CHECK: 3:
; CHECK-NEXT: br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]]
; CHECK: 4:
; CHECK-NEXT: call void @empty()
; CHECK-NEXT: br label [[TMP6]]
; CHECK: 5:
; CHECK-NEXT: unreachable
; CHECK: 6:
; CHECK-NEXT: ret void
;
%fptr = select i1 %cond, ptr @empty, ptr @also_empty
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/opt/NewPMDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ static void registerEPCallbacks(PassBuilder &PB) {
});
if (tryParsePipelineText<ModulePassManager>(PB, OptimizerLastEPPipeline))
PB.registerOptimizerLastEPCallback(
[&PB](ModulePassManager &PM, OptimizationLevel) {
[&PB](ModulePassManager &PM, OptimizationLevel, ThinOrFullLTOPhase) {
ExitOnError Err("Unable to parse OptimizerLastEP pipeline: ");
Err(PB.parsePassPipeline(PM, OptimizerLastEPPipeline));
});
Expand Down
Loading