Skip to content

[CodeGen] Let PassBuilder support machine passes #76320

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

Merged
merged 2 commits into from
Jan 13, 2024
Merged
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
39 changes: 39 additions & 0 deletions llvm/include/llvm/Passes/PassBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define LLVM_PASSES_PASSBUILDER_H

#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/OptimizationLevel.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -165,6 +166,14 @@ class PassBuilder {
/// additional analyses.
void registerLoopAnalyses(LoopAnalysisManager &LAM);

/// Registers all available machine function analysis passes.
///
/// This is an interface that can be used to populate a \c
/// MachineFunctionAnalysisManager with all registered function analyses.
/// Callers can still manually register any additional analyses. Callers can
/// also pre-register analyses and this will not override those.
void registerMachineFunctionAnalyses(MachineFunctionAnalysisManager &MFAM);

/// Construct the core LLVM function canonicalization and simplification
/// pipeline.
///
Expand Down Expand Up @@ -352,6 +361,18 @@ class PassBuilder {
Error parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText);
/// @}}

/// Parse a textual MIR pipeline into the provided \c MachineFunctionPass
/// manager.
/// The format of the textual machine pipeline is a comma separated list of
/// machine pass names:
///
/// machine-funciton-pass,machine-module-pass,...
///
/// There is no need to specify the pass nesting, and this function
/// currently cannot handle the pass nesting.
Error parsePassPipeline(MachineFunctionPassManager &MFPM,
StringRef PipelineText);

/// Parse a textual alias analysis pipeline into the provided AA manager.
///
/// The format of the textual AA pipeline is a comma separated list of AA
Expand Down Expand Up @@ -520,6 +541,10 @@ class PassBuilder {
const std::function<void(ModuleAnalysisManager &)> &C) {
ModuleAnalysisRegistrationCallbacks.push_back(C);
}
void registerAnalysisRegistrationCallback(
const std::function<void(MachineFunctionAnalysisManager &)> &C) {
MachineFunctionAnalysisRegistrationCallbacks.push_back(C);
}
/// @}}

/// {{@ Register pipeline parsing callbacks with this pass builder instance.
Expand All @@ -546,6 +571,11 @@ class PassBuilder {
ArrayRef<PipelineElement>)> &C) {
ModulePipelineParsingCallbacks.push_back(C);
}
void registerPipelineParsingCallback(
const std::function<bool(StringRef Name, MachineFunctionPassManager &)>
&C) {
MachinePipelineParsingCallbacks.push_back(C);
}
/// @}}

/// Register a callback for a top-level pipeline entry.
Expand Down Expand Up @@ -616,8 +646,12 @@ class PassBuilder {
Error parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E);
Error parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E);
Error parseLoopPass(LoopPassManager &LPM, const PipelineElement &E);
Error parseMachinePass(MachineFunctionPassManager &MFPM,
const PipelineElement &E);
bool parseAAPassName(AAManager &AA, StringRef Name);

Error parseMachinePassPipeline(MachineFunctionPassManager &MFPM,
ArrayRef<PipelineElement> Pipeline);
Error parseLoopPassPipeline(LoopPassManager &LPM,
ArrayRef<PipelineElement> Pipeline);
Error parseFunctionPassPipeline(FunctionPassManager &FPM,
Expand Down Expand Up @@ -699,6 +733,11 @@ class PassBuilder {
// AA callbacks
SmallVector<std::function<bool(StringRef Name, AAManager &AA)>, 2>
AAParsingCallbacks;
// Machine pass callbackcs
SmallVector<std::function<void(MachineFunctionAnalysisManager &)>, 2>
MachineFunctionAnalysisRegistrationCallbacks;
SmallVector<std::function<bool(StringRef, MachineFunctionPassManager &)>, 2>
MachinePipelineParsingCallbacks;
};

/// This utility template takes care of adding require<> and invalidate<>
Expand Down
82 changes: 82 additions & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,12 @@ PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
#include "PassRegistry.def"

#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
PIC->addClassToPassName(PASS_NAME::name(), NAME);
#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
PIC->addClassToPassName(PASS_NAME::name(), NAME);
#include "llvm/CodeGen/MachinePassRegistry.def"
}
}

Expand Down Expand Up @@ -523,6 +529,17 @@ void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
C(FAM);
}

void PassBuilder::registerMachineFunctionAnalyses(
MachineFunctionAnalysisManager &MFAM) {

#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
MFAM.registerPass([&] { return PASS_NAME(); });
#include "llvm/CodeGen/MachinePassRegistry.def"

for (auto &C : MachineFunctionAnalysisRegistrationCallbacks)
C(MFAM);
}

void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
LAM.registerPass([&] { return CREATE_PASS; });
Expand Down Expand Up @@ -1877,6 +1894,33 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM,
inconvertibleErrorCode());
}

Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,
const PipelineElement &E) {
StringRef Name = E.Name;
if (!E.InnerPipeline.empty())
return make_error<StringError>("invalid pipeline",
inconvertibleErrorCode());

#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) { \
MFPM.addPass(PASS_NAME()); \
return Error::success(); \
}
Comment on lines +1904 to +1908
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does a machine module pass mean? If it's to mean module pass but for codegen, isn't MFPM.addPass() wrong as it assumes the MACHINE_MODULE_PASS pass to be a MachineFunction pass?

@paperchalice

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's just a placeholder as there are no "MachineModulePasses"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops the code is wrong here now. Initially when I took over this part, the original designer want to use machine function pass manager to manage both machine function pass and "machine module pass", but now I realized "machine module pass" is just a special kind of module pass that modifies all MachineFunctionAnalysis::Result i.e. MachineFunciton...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get what modifies all MachineFunctionAnalysis::Result mean? I see that MachineModuleAnalysis and PassInstrumentationAnalysis are in this category.

Copy link
Contributor Author

@paperchalice paperchalice Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get what modifies all MachineFunctionAnalysis::Result mean? I see that MachineModuleAnalysis and PassInstrumentationAnalysis are in this category.

Code is here: MachineFunctionAnalysis. It is just a simple wrapper of MachineFunction (may convert MachineFunction to a real analysis result in future). The owner of machine functions in new pass manager is FunctionAnalysisManager rather than MachineModuleInfo in legacy pass manager.

Machine module pass can manipulate all machine functions via FunctionAnalysisManager. For example machine outliner will create some dummy IR functions and corresponding machine functions, then modify machine functions to compress the module size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, yes. To summarize, Machine module passes are Module passes that modify MachineFunctions via MAM.getResult<Function...Proxy>(M)..getResult<MachineFunctionAnalysis>(F).

#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
if (Name == NAME) { \
MFPM.addPass(PASS_NAME()); \
return Error::success(); \
}
#include "llvm/CodeGen/MachinePassRegistry.def"

for (auto &C : MachinePipelineParsingCallbacks)
if (C(Name, MFPM))
return Error::success();
return make_error<StringError>(
formatv("unknown machine pass '{0}'", Name).str(),
inconvertibleErrorCode());
}

bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
if (Name == NAME) { \
Expand All @@ -1898,6 +1942,15 @@ bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
return false;
}

Error PassBuilder::parseMachinePassPipeline(
MachineFunctionPassManager &MFPM, ArrayRef<PipelineElement> Pipeline) {
for (const auto &Element : Pipeline) {
if (auto Err = parseMachinePass(MFPM, Element))
return Err;
}
return Error::success();
}

Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,
ArrayRef<PipelineElement> Pipeline) {
for (const auto &Element : Pipeline) {
Expand Down Expand Up @@ -2057,6 +2110,20 @@ Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
return Error::success();
}

Error PassBuilder::parsePassPipeline(MachineFunctionPassManager &MFPM,
StringRef PipelineText) {
auto Pipeline = parsePipelineText(PipelineText);
if (!Pipeline || Pipeline->empty())
return make_error<StringError>(
formatv("invalid machine pass pipeline '{0}'", PipelineText).str(),
inconvertibleErrorCode());

if (auto Err = parseMachinePassPipeline(MFPM, *Pipeline))
return Err;

return Error::success();
}

Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
// If the pipeline just consists of the word 'default' just replace the AA
// manager with our default one.
Expand Down Expand Up @@ -2151,6 +2218,21 @@ void PassBuilder::printPassNames(raw_ostream &OS) {
OS << "Loop analyses:\n";
#define LOOP_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
#include "PassRegistry.def"

OS << "Machine module passes (WIP):\n";
#define MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
printPassName(NAME, OS);
#include "llvm/CodeGen/MachinePassRegistry.def"

OS << "Machine function passes (WIP):\n";
#define MACHINE_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) \
printPassName(NAME, OS);
#include "llvm/CodeGen/MachinePassRegistry.def"

OS << "Machine function analyses (WIP):\n";
#define MACHINE_FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) \
printPassName(NAME, OS);
#include "llvm/CodeGen/MachinePassRegistry.def"
}

void PassBuilder::registerParseTopLevelPipelineCallback(
Expand Down
2 changes: 2 additions & 0 deletions llvm/unittests/MIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ set(LLVM_LINK_COMPONENTS
FileCheck
MC
MIRParser
Passes
Support
Target
TargetParser
)

add_llvm_unittest(MIRTests
MachineMetadata.cpp
PassBuilderCallbacksTest.cpp
)

target_link_libraries(MIRTests PRIVATE LLVMTestingSupport)
Loading