Skip to content

Commit 91e9e31

Browse files
authored
[NewPM/CodeGen] Rewrite pass manager nesting (#81068)
Currently the new PM infra for codegen puts everything into a MachineFunctionPassManager. The MachineFunctionPassManager owns both Module passes and MachineFunction passes, and batches adjacent MachineFunction passes like a typical PassManager. The current MachineFunctionAnalysisManager also directly references a module and function analysis manager to get results. The initial argument was that the codegen pipeline is relatively "flat", meaning it's mostly machine function passes with a couple of module passes here and there. However, there are a couple of issues with this as compared to a more structured nesting more like the optimization pipeline. For example, it doesn't allow running function passes then machine function passes on a function and its machine function all at once. It also currently requires the caller to split out the IR passes into one pass manager and the MIR passes into another pass manager. This patch rewrites the new pass manager infra for the codegen pipeline to be more similar to the nesting in the optimization pipeline. Basically, a Function contains a MachineFunction. So we can have Module -> Function -> MachineFunction adaptors. It also rewrites the analysis managers to have inner/outer proxies like the ones in the optimization pipeline. The new pass managers/adaptors/analysis managers can be seen in use in PassManagerTest.cpp. This allows us to consolidate to just having to add to one ModulePassManager when using the codegen pipeline. I haven't added the Function -> MachineFunction adaptor in this patch, but it should be added when we merge AddIRPass/AddMachinePass so that we can run IR and MIR passes on a function before proceeding to the next function. The MachineFunctionProperties infra for MIR verification is still WIP.
1 parent 847048f commit 91e9e31

File tree

13 files changed

+681
-628
lines changed

13 files changed

+681
-628
lines changed

llvm/include/llvm/CodeGen/MachinePassManager.h

Lines changed: 218 additions & 187 deletions
Large diffs are not rendered by default.

llvm/include/llvm/Passes/CodeGenPassBuilder.h

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "llvm/CodeGen/InterleavedLoadCombine.h"
3838
#include "llvm/CodeGen/JMCInstrumenter.h"
3939
#include "llvm/CodeGen/LowerEmuTLS.h"
40+
#include "llvm/CodeGen/MIRPrinter.h"
4041
#include "llvm/CodeGen/MachinePassManager.h"
4142
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
4243
#include "llvm/CodeGen/ReplaceWithVeclib.h"
@@ -88,12 +89,8 @@ namespace llvm {
8889
#define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME) \
8990
struct PASS_NAME : public MachinePassInfoMixin<PASS_NAME> { \
9091
template <typename... Ts> PASS_NAME(Ts &&...) {} \
91-
Error run(Module &, MachineFunctionAnalysisManager &) { \
92-
return Error::success(); \
93-
} \
94-
PreservedAnalyses run(MachineFunction &, \
95-
MachineFunctionAnalysisManager &) { \
96-
llvm_unreachable("this api is to make new PM api happy"); \
92+
PreservedAnalyses run(Module &, ModuleAnalysisManager &) { \
93+
return PreservedAnalyses::all(); \
9794
} \
9895
};
9996
#define DUMMY_MACHINE_FUNCTION_PASS(NAME, PASS_NAME) \
@@ -132,8 +129,8 @@ template <typename DerivedT> class CodeGenPassBuilder {
132129
Opt.OptimizeRegAlloc = getOptLevel() != CodeGenOptLevel::None;
133130
}
134131

135-
Error buildPipeline(ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
136-
raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
132+
Error buildPipeline(ModulePassManager &MPM, raw_pwrite_stream &Out,
133+
raw_pwrite_stream *DwoOut,
137134
CodeGenFileType FileType) const;
138135

139136
PassInstrumentationCallbacks *getPassInstrumentationCallbacks() const {
@@ -149,7 +146,15 @@ template <typename DerivedT> class CodeGenPassBuilder {
149146
using is_function_pass_t = decltype(std::declval<PassT &>().run(
150147
std::declval<Function &>(), std::declval<FunctionAnalysisManager &>()));
151148

149+
template <typename PassT>
150+
using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
151+
std::declval<MachineFunction &>(),
152+
std::declval<MachineFunctionAnalysisManager &>()));
153+
152154
// Function object to maintain state while adding codegen IR passes.
155+
// TODO: add a Function -> MachineFunction adaptor and merge
156+
// AddIRPass/AddMachinePass so we can have a function pipeline that runs both
157+
// function passes and machine function passes.
153158
class AddIRPass {
154159
public:
155160
AddIRPass(ModulePassManager &MPM, const DerivedT &PB) : MPM(MPM), PB(PB) {}
@@ -196,31 +201,47 @@ template <typename DerivedT> class CodeGenPassBuilder {
196201
// Function object to maintain state while adding codegen machine passes.
197202
class AddMachinePass {
198203
public:
199-
AddMachinePass(MachineFunctionPassManager &PM, const DerivedT &PB)
200-
: PM(PM), PB(PB) {}
204+
AddMachinePass(ModulePassManager &MPM, const DerivedT &PB)
205+
: MPM(MPM), PB(PB) {}
206+
~AddMachinePass() {
207+
if (!MFPM.isEmpty())
208+
MPM.addPass(createModuleToMachineFunctionPassAdaptor(std::move(MFPM)));
209+
}
210+
211+
template <typename PassT>
212+
void operator()(PassT &&Pass, bool Force = false,
213+
StringRef Name = PassT::name()) {
214+
static_assert((is_detected<is_machine_function_pass_t, PassT>::value ||
215+
is_detected<is_module_pass_t, PassT>::value) &&
216+
"Only module pass and function pass are supported.");
201217

202-
template <typename PassT> void operator()(PassT &&Pass) {
203-
if (!PB.runBeforeAdding(PassT::name()))
218+
if (!Force && !PB.runBeforeAdding(Name))
204219
return;
205220

206-
PM.addPass(std::forward<PassT>(Pass));
221+
// Add Function Pass
222+
if constexpr (is_detected<is_machine_function_pass_t, PassT>::value) {
223+
MFPM.addPass(std::forward<PassT>(Pass));
207224

208-
for (auto &C : PB.AfterCallbacks)
209-
C(PassT::name());
210-
}
225+
for (auto &C : PB.AfterCallbacks)
226+
C(Name);
227+
} else {
228+
// Add Module Pass
229+
if (!MFPM.isEmpty()) {
230+
MPM.addPass(
231+
createModuleToMachineFunctionPassAdaptor(std::move(MFPM)));
232+
MFPM = MachineFunctionPassManager();
233+
}
211234

212-
template <typename PassT> void insertPass(StringRef PassName, PassT Pass) {
213-
PB.AfterCallbacks.emplace_back(
214-
[this, PassName, Pass = std::move(Pass)](StringRef Name) {
215-
if (PassName == Name)
216-
this->PM.addPass(std::move(Pass));
217-
});
218-
}
235+
MPM.addPass(std::forward<PassT>(Pass));
219236

220-
MachineFunctionPassManager releasePM() { return std::move(PM); }
237+
for (auto &C : PB.AfterCallbacks)
238+
C(Name);
239+
}
240+
}
221241

222242
private:
223-
MachineFunctionPassManager &PM;
243+
ModulePassManager &MPM;
244+
MachineFunctionPassManager MFPM;
224245
const DerivedT &PB;
225246
};
226247

@@ -467,30 +488,43 @@ template <typename DerivedT> class CodeGenPassBuilder {
467488

468489
template <typename Derived>
469490
Error CodeGenPassBuilder<Derived>::buildPipeline(
470-
ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
471-
raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
491+
ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
472492
CodeGenFileType FileType) const {
473493
auto StartStopInfo = TargetPassConfig::getStartStopInfo(*PIC);
474494
if (!StartStopInfo)
475495
return StartStopInfo.takeError();
476496
setStartStopPasses(*StartStopInfo);
477-
AddIRPass addIRPass(MPM, derived());
478-
// `ProfileSummaryInfo` is always valid.
479-
addIRPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
480-
addIRPass(RequireAnalysisPass<CollectorMetadataAnalysis, Module>());
481-
addISelPasses(addIRPass);
482497

483-
AddMachinePass addPass(MFPM, derived());
498+
bool PrintAsm = TargetPassConfig::willCompleteCodeGenPipeline();
499+
bool PrintMIR = !PrintAsm && FileType != CodeGenFileType::Null;
500+
501+
{
502+
AddIRPass addIRPass(MPM, derived());
503+
addIRPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
504+
addIRPass(RequireAnalysisPass<CollectorMetadataAnalysis, Module>());
505+
addISelPasses(addIRPass);
506+
}
507+
508+
AddMachinePass addPass(MPM, derived());
509+
510+
if (PrintMIR)
511+
addPass(PrintMIRPreparePass(Out), /*Force=*/true);
512+
484513
if (auto Err = addCoreISelPasses(addPass))
485514
return std::move(Err);
486515

487516
if (auto Err = derived().addMachinePasses(addPass))
488517
return std::move(Err);
489518

490-
derived().addAsmPrinter(
491-
addPass, [this, &Out, DwoOut, FileType](MCContext &Ctx) {
492-
return this->TM.createMCStreamer(Out, DwoOut, FileType, Ctx);
493-
});
519+
if (PrintAsm) {
520+
derived().addAsmPrinter(
521+
addPass, [this, &Out, DwoOut, FileType](MCContext &Ctx) {
522+
return this->TM.createMCStreamer(Out, DwoOut, FileType, Ctx);
523+
});
524+
}
525+
526+
if (PrintMIR)
527+
addPass(PrintMIRPass(Out), /*Force=*/true);
494528

495529
addPass(FreeMachineFunctionPass());
496530
return verifyStartStop(*StartStopInfo);

llvm/include/llvm/Passes/PassBuilder.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ class PassBuilder {
133133
void crossRegisterProxies(LoopAnalysisManager &LAM,
134134
FunctionAnalysisManager &FAM,
135135
CGSCCAnalysisManager &CGAM,
136-
ModuleAnalysisManager &MAM);
136+
ModuleAnalysisManager &MAM,
137+
MachineFunctionAnalysisManager *MFAM = nullptr);
137138

138139
/// Registers all available module analysis passes.
139140
///
@@ -569,9 +570,9 @@ class PassBuilder {
569570
ModulePipelineParsingCallbacks.push_back(C);
570571
}
571572
void registerPipelineParsingCallback(
572-
const std::function<bool(StringRef Name, MachineFunctionPassManager &)>
573-
&C) {
574-
MachinePipelineParsingCallbacks.push_back(C);
573+
const std::function<bool(StringRef Name, MachineFunctionPassManager &,
574+
ArrayRef<PipelineElement>)> &C) {
575+
MachineFunctionPipelineParsingCallbacks.push_back(C);
575576
}
576577
/// @}}
577578

@@ -733,8 +734,10 @@ class PassBuilder {
733734
// Machine pass callbackcs
734735
SmallVector<std::function<void(MachineFunctionAnalysisManager &)>, 2>
735736
MachineFunctionAnalysisRegistrationCallbacks;
736-
SmallVector<std::function<bool(StringRef, MachineFunctionPassManager &)>, 2>
737-
MachinePipelineParsingCallbacks;
737+
SmallVector<std::function<bool(StringRef, MachineFunctionPassManager &,
738+
ArrayRef<PipelineElement>)>,
739+
2>
740+
MachineFunctionPipelineParsingCallbacks;
738741
};
739742

740743
/// This utility template takes care of adding require<> and invalidate<>

llvm/include/llvm/Target/TargetMachine.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ using ModulePassManager = PassManager<Module>;
3434

3535
class Function;
3636
class GlobalValue;
37-
class MachineFunctionPassManager;
38-
class MachineFunctionAnalysisManager;
3937
class MachineModuleInfoWrapperPass;
4038
class Mangler;
4139
class MCAsmInfo;
@@ -455,11 +453,9 @@ class LLVMTargetMachine : public TargetMachine {
455453
bool DisableVerify = true,
456454
MachineModuleInfoWrapperPass *MMIWP = nullptr) override;
457455

458-
virtual Error buildCodeGenPipeline(ModulePassManager &,
459-
MachineFunctionPassManager &,
460-
MachineFunctionAnalysisManager &,
461-
raw_pwrite_stream &, raw_pwrite_stream *,
462-
CodeGenFileType, CGPassBuilderOption,
456+
virtual Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &,
457+
raw_pwrite_stream *, CodeGenFileType,
458+
CGPassBuilderOption,
463459
PassInstrumentationCallbacks *) {
464460
return make_error<StringError>("buildCodeGenPipeline is not overridden",
465461
inconvertibleErrorCode());

0 commit comments

Comments
 (0)