-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[CodeGen] Support start/stop in CodeGenPassBuilder #70912
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
Conversation
@llvm/pr-subscribers-llvm-ir Author: None (paperchalice) ChangesAdd a special hook to support Full diff: https://github.com/llvm/llvm-project/pull/70912.diff 3 Files Affected:
diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h
index 519a5e46b4373b7..3f70fcf180af81a 100644
--- a/llvm/include/llvm/IR/PassInstrumentation.h
+++ b/llvm/include/llvm/IR/PassInstrumentation.h
@@ -84,6 +84,23 @@ class PassInstrumentationCallbacks {
using AfterAnalysisFunc = void(StringRef, Any);
using AnalysisInvalidatedFunc = void(StringRef, Any);
using AnalysesClearedFunc = void(StringRef);
+ using StartStopFunc = bool(StringRef, Any);
+
+ struct CodeGenStartStopInfo {
+ StringRef Start;
+ StringRef Stop;
+
+ bool IsStopMachinePass = false;
+
+ llvm::unique_function<StartStopFunc> StartStopCallback;
+
+ bool operator()(StringRef PassID, Any IR) {
+ return StartStopCallback(PassID, IR);
+ }
+ bool isStopMachineFunctionPass() const { return IsStopMachinePass; }
+ bool willCompleteCodeGenPipeline() const { return Stop.empty(); }
+ StringRef getStop() const { return Stop; }
+ };
public:
PassInstrumentationCallbacks() = default;
@@ -148,6 +165,17 @@ class PassInstrumentationCallbacks {
AnalysesClearedCallbacks.emplace_back(std::move(C));
}
+ void registerStartStopInfo(CodeGenStartStopInfo &&C) {
+ StartStopInfo = std::move(C);
+ }
+
+ bool isStartStopInfoRegistered() const { return StartStopInfo.has_value(); }
+
+ CodeGenStartStopInfo &getStartStopInfo() {
+ assert(StartStopInfo.has_value() && "StartStopInfo is unregistered!");
+ return *StartStopInfo;
+ }
+
/// Add a class name to pass name mapping for use by pass instrumentation.
void addClassToPassName(StringRef ClassName, StringRef PassName);
/// Get the pass name for a given pass class name.
@@ -183,6 +211,8 @@ class PassInstrumentationCallbacks {
/// These are run on analyses that have been cleared.
SmallVector<llvm::unique_function<AnalysesClearedFunc>, 4>
AnalysesClearedCallbacks;
+ /// For `llc` -start-* -stop-* options.
+ std::optional<CodeGenStartStopInfo> StartStopInfo;
StringMap<std::string> ClassToPassName;
};
@@ -236,6 +266,9 @@ class PassInstrumentation {
ShouldRun &= C(Pass.name(), llvm::Any(&IR));
}
+ if (Callbacks->StartStopInfo)
+ ShouldRun &= (*Callbacks->StartStopInfo)(Pass.name(), llvm::Any(&IR));
+
if (ShouldRun) {
for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks)
C(Pass.name(), llvm::Any(&IR));
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index e6ecbc9b03f7149..bea8590a14080ca 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -508,6 +508,9 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
unsigned StopBeforeInstanceNum = 0;
unsigned StopAfterInstanceNum = 0;
+ bool IsStopBeforeMachinePass = false;
+ bool IsStopAfterMachinePass = false;
+
std::tie(StartBefore, StartBeforeInstanceNum) =
getPassNameAndInstanceNum(StartBeforeOpt);
std::tie(StartAfter, StartAfterInstanceNum) =
@@ -536,7 +539,15 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
report_fatal_error(Twine(StopBeforeOptName) + Twine(" and ") +
Twine(StopAfterOptName) + Twine(" specified!"));
- PIC.registerShouldRunOptionalPassCallback(
+ std::vector<StringRef> SpecialPasses = {"PassManager", "PassAdaptor",
+ "PrintMIRPass", "PrintModulePass"};
+
+ PassInstrumentationCallbacks::CodeGenStartStopInfo Info;
+ Info.Start = StartBefore.empty() ? StartAfter : StartBefore;
+ Info.Stop = StopBefore.empty() ? StopAfter : StopBefore;
+
+ Info.IsStopMachinePass = IsStopBeforeMachinePass || IsStopAfterMachinePass;
+ Info.StartStopCallback =
[=, EnableCurrent = StartBefore.empty() && StartAfter.empty(),
EnableNext = std::optional<bool>(), StartBeforeCount = 0u,
StartAfterCount = 0u, StopBeforeCount = 0u,
@@ -567,8 +578,10 @@ static void registerPartialPipelineCallback(PassInstrumentationCallbacks &PIC,
EnableCurrent = true;
if (StopBeforePass && StopBeforeCount++ == StopBeforeInstanceNum)
EnableCurrent = false;
- return EnableCurrent;
- });
+ return EnableCurrent || isSpecialPass(P, SpecialPasses);
+ };
+
+ PIC.registerStartStopInfo(std::move(Info));
}
void llvm::registerCodeGenCallback(PassInstrumentationCallbacks &PIC,
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 06cc58c0219632d..c6ec1c34d74418d 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -1036,9 +1036,10 @@ void PrintPassInstrumentation::registerCallbacks(
SpecialPasses.emplace_back("PassAdaptor");
}
- PIC.registerBeforeSkippedPassCallback([this, SpecialPasses](StringRef PassID,
- Any IR) {
- assert(!isSpecialPass(PassID, SpecialPasses) &&
+ PIC.registerBeforeSkippedPassCallback([this, SpecialPasses,
+ &PIC](StringRef PassID, Any IR) {
+ assert((!isSpecialPass(PassID, SpecialPasses) ||
+ PIC.isStartStopInfoRegistered()) &&
"Unexpectedly skipping special pass");
print() << "Skipping pass: " << PassID << " on " << getIRName(IR) << "\n";
|
d7b90d6
to
9a4d24c
Compare
instead of doing this in the instrumentation, can we do this by not adding the pass to begin with? that seems cleaner. e.g. |
1cbce28
to
5e9c1dc
Compare
Update for this now. Add a callback to The work of determining whether a pass is a machine pass will be completed by the pass builder, which requires #76320. Update: In this way, it may not recognize some passes which is added by adaptor class, like |
sorry, been swamped with unbreaking things this week, will try to review next week |
5e9c1dc
to
b14ba16
Compare
150903d
to
ab89ac7
Compare
ab89ac7
to
351462a
Compare
351462a
to
16d2498
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I think this makes more sense, thanks
LoopStrengthReducePass(), /*UseMemorySSA*/ true, Opt.DebugPM)); | ||
addPass(createFunctionToLoopPassAdaptor(LoopStrengthReducePass(), | ||
/*UseMemorySSA*/ true, Opt.DebugPM), | ||
LoopStrengthReducePass::name()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is unfortunate, I wonder if we should just make this a function pass, but we can do that in the future
llvm/lib/IR/PassInstrumentation.cpp
Outdated
@@ -28,6 +28,14 @@ PassInstrumentationCallbacks::getPassNameForClassName(StringRef ClassName) { | |||
return ClassToPassName[ClassName]; | |||
} | |||
|
|||
StringRef | |||
PassInstrumentationCallbacks::getClassNameForPassName(StringRef PassName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than adding this reverse map, let's be consistent with existing instrumentation like here where we check the pass name against PIC->getPassNameForClassName(PassID)
in the callbacks. even if this is slower it doesn't really matter since this is just used for testing iiuc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we may need #76320 to populate pass names.
StringRef getClassNameForPassName(StringRef PassName); | ||
|
||
/// Helper callback to support options like start-before. | ||
llvm::unique_function<StartStopFunc> StartStopCallback; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm missing where this is being used.
Also, PassInstrumentationCallbacks
doesn't really seem like the right place to put this. The only reason we interact with PIC is to get the class/pass name map. If we can somehow separate that out, that would be ideal, but perhaps that's too hard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I forgot to remove this, this implementation doesn't need this any more, sorry.
d7fa9a8
to
6eb14fe
Compare
6eb14fe
to
5ef19fa
Compare
5ef19fa
to
509b1cf
Compare
Add simple unit test and will move to lit test in future. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lg with some comments
we really should get basic llc support soon
static_assert((is_detected<is_function_pass_t, PassT>::value || | ||
is_detected<is_module_pass_t, PassT>::value) && | ||
"Only module pass and function pass are supported."); | ||
|
||
// Add Function Pass | ||
if constexpr (is_detected<is_function_pass_t, PassT>::value) { | ||
if (!PB.runBeforeAdding(Name)) | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can factor this out of if/else branches
C(&PassT::Key); | ||
|
||
for (auto &C : PB.AfterCallbacks) | ||
C(PassT::name()); | ||
} | ||
|
||
template <typename PassT> void insertPass(MachinePassKey *ID, PassT Pass) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unrelated, and I think I mentioned this before, but I'd like to see if we can come up with a nicer way of doing this, perhaps with something like PassBuilder
extension points (e.g. PassBuilder::registerPeepholeEPCallback()
). it seems in line with various per-target TargetMachines adding their own passes anyway. do you know if we could potentially replace insertPass()
with the various TargetMachines simply adding passes in the right place, or are the passes they add too ad hoc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently AMDGPU, Hexagon, PowerPC and RISCV uses insertPass
to adjust the regalloc pipeline, we need add extension points after PHIElimination
, TwoAddressInstruction
, MachineScheduler
, RenameIndependentSubregs
, LiveVariables
and DetectDeadLanes
. They inject passes between these passes directly and only happens in regalloc pipeline.
@@ -123,6 +124,13 @@ namespace llvm { | |||
/// all of the built-in passes, and those may reference these members during | |||
/// construction. | |||
template <typename DerivedT> class CodeGenPassBuilder { | |||
bool runBeforeAdding(StringRef Name) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you move this definition somewhere else in the class? it doesn't belong right at the top
|
||
Error verifyStartStop(const TargetPassConfig::StartStopInfo &Info) const; | ||
|
||
mutable SmallVector<llvm::unique_function<bool(StringRef)>, 4> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems nicer to keep this in AddPass
. is the reason that these are moved out of AddPass
because it references Started
/Stopped
in CodeGenPassBuilder
? and there's no way to easily validate them if these are somewhere else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently IR passes and machine function passes are handled by different classes, and -start/stop
options should support both IR and machine function passes, but it's OK to merge them into one class, because only buildPipeline
creates instance of AddIRPass
and AddMachinePass
, but IMHO keeping these in CodeGenPassBuilder
can let target disable passes in constructor.
509b1cf
to
ce88f2b
Compare
Address some comments. |
Reverts #70912. This breaks some bazel tests.
Add `-start/stop-before/after` support for CodeGenPassBuilder. Part of llvm#69879.
Add `-start/stop-before/after` support for CodeGenPassBuilder. Part of llvm#69879.
…78570) Unfortunately the legacy pass system can't recognize `no-op-module` and `no-op-function` so it causes test failure in `CodeGenTests`. Add a workaround in function `PassInfo *getPassInfo(StringRef PassName)`, `TargetPassConfig.cpp`.
Add
-start/stop-before/after
support for CodeGenPassBuilder.Part of #69879.