Port refprune pass to NewPassManager#1057
Conversation
|
Not relevant anymore |
|
I "checked" the last commit. LGTM. only has some minor format issues, but I feel don't need to bring it up. |
|
LGTM |
|
Rebased |
|
Clang format does not report anything for me locally. What version of clang-format is used in the checks? |
Based on the changes introduced in numba#1042 by @modiking
This reverts commit 2d9f8e6.
|
Edit: Ready for review |
It is clang-format-14, I think. |
|
using clang-format 14 made the tests pass, should llvmlite consider moving to a more recent clang-format? |
|
Gentle ping |
There was a problem hiding this comment.
I have added some inline comments to make the thought process behind the the changes more apparent to the reviewers.
The gist of the changes are:
- We prefix the old refprune passes with legacy keyword.
- We create a new refprune pass following the new pass manager syntax.
- Now that we have multiple instances of the same pass, to prevent duplication of code we move the computation functions to a more global scope(struct) so that both passes can share them.
Found this article online which comes very close to explaining what we did here https://www.neilhenning.dev/posts/llvm-new-pass-manager/
Examples from llvm codebase on porting a pass to NPM
| void initializeRefNormalizeLegacyPassPass(PassRegistry &Registry); | ||
| void initializeRefPruneLegacyPassPass(PassRegistry &Registry); |
There was a problem hiding this comment.
Prefix the pass name with "Legacy" to be used with legacy pass manager
| class RefPrunePass : public PassInfoMixin<RefPrunePass> { | ||
|
|
||
| public: | ||
| Subpasses flags; | ||
| size_t subgraph_limit; | ||
| RefPrunePass(Subpasses flags = Subpasses::All, size_t subgraph_limit = -1) | ||
| : flags(flags), subgraph_limit(subgraph_limit) {} | ||
|
|
||
| PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { | ||
| auto &DT = AM.getResult<DominatorTreeAnalysis>(F); | ||
| auto &PDT = AM.getResult<PostDominatorTreeAnalysis>(F); | ||
| if (RefPrune(DT, PDT, flags, subgraph_limit).runOnFunction(F)) { | ||
| return PreservedAnalyses::none(); | ||
| } | ||
|
|
||
| return PreservedAnalyses::all(); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Now that we have renamed the pass with "Legacy" keyword, we are free to create another pass with the name RefPrunePass, we will call this pass from NewPassManager . The passes for new pass manager follow this template mixin inheritance syntax that's visible here. There's also a difference in how we get the Analysis results needed for the pass to run, instead of explicitly specifying dependencies in getAnalysisUsage function we can directly query the NPM analysis manager for the result.
Note that wrapped in all this new pass manager syntax we are calling runOnFunction(F) which actually does the computation for this pass and is also used by legacy version of this pass.
| struct RefNormalize { | ||
|
|
||
| bool runOnFunction(Function &F) override { | ||
| bool runOnFunction(Function &F) { |
There was a problem hiding this comment.
This is the core of the RefNormalize pass, we will call this function from legacy and new version of RefNormalize pass.
| All = PerBasicBlock | Diamond | Fanout | FanoutRaise | ||
| } Subpasses; | ||
|
|
||
| struct RefPrune { |
There was a problem hiding this comment.
We have moved all the computation related functions from inside struct RefPrunePass : public FunctionPass to struct RefPrune so that we can re-use these functions from both the Legacy pass and the new pass.
| API_EXPORT(void) | ||
| LLVMPY_AddRefPrunePass_module(LLVMModulePassManagerRef MPM, int subpasses, | ||
| size_t subgraph_limit) { | ||
| llvm::unwrap(MPM)->addPass( | ||
| createModuleToFunctionPassAdaptor(RefNormalizePass())); | ||
| llvm::unwrap(MPM)->addPass(createModuleToFunctionPassAdaptor( | ||
| RefPrunePass((Subpasses)subpasses, subgraph_limit))); | ||
| } | ||
|
|
||
| API_EXPORT(void) | ||
| LLVMPY_AddRefPrunePass_function(LLVMFunctionPassManagerRef FPM, int subpasses, | ||
| size_t subgraph_limit) { | ||
| llvm::unwrap(FPM)->addPass(RefNormalizePass()); | ||
| llvm::unwrap(FPM)->addPass( | ||
| RefPrunePass((Subpasses)subpasses, subgraph_limit)); |
There was a problem hiding this comment.
API to register new passes in MPM and FPM respectively.
There was a problem hiding this comment.
Copied the APIs from passmanagers.py
There was a problem hiding this comment.
Creating new tests for refprune in new pass manager would have involved some duplication, so I migrated the old tests to NewPassManager. Let me know if you think that's not the best way forward.
gmarkall
left a comment
There was a problem hiding this comment.
Thanks for the PR - the code changes look good, and I was able to follow them well from the info you provided / linked to. I think there are two things that need adding:
- Documentation for the
add_refprune_passfunctions of the new module and function pass managers - Keep the tests for the legacy pass manager, as well as testing with the new pass manager. Although there's a low probability of issues with the legacy pass manager, the changes do touch their code (and other future changes might potentially as well, we never know) so keeping both paths in use tested is important.
|
Thanks for the review @gmarkall! I have addressed the comments. |
gmarkall
left a comment
There was a problem hiding this comment.
Thanks for the additions - I think this is now good to merge!
|
Resolved now, thanks! |
|
Ping |
|
Thank you for the patch! |
Based on the changes introduced in #1042 by @modiking