Skip to content

[MLIR][Python] Add optional arguments to PassManager IR printing #89301

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

vraspar
Copy link

@vraspar vraspar commented Apr 18, 2024

This MR adds support for more granular IR printing for python pass manager by exposing existing parameters Pass Manager available through the C++ API.

Specifically, it adds following arguments:

print_before_pass
print_after_pass
print_after_only_on_change
print_after_only_on_failure

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added mlir:python MLIR Python bindings mlir labels Apr 18, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 18, 2024

@llvm/pr-subscribers-mlir

Author: None (vraspar)

Changes

This MR adds support for more granular ir printing for python pass manager by exposing existing parameters Pass Manager CPP API.

Specifically, it adds followng arguments:

print_before_pass
print_after_pass
print_after_only_on_change
print_after_only_on_failure

Full diff: https://github.com/llvm/llvm-project/pull/89301.diff

4 Files Affected:

  • (modified) mlir/include/mlir-c/Pass.h (+9-1)
  • (modified) mlir/lib/Bindings/Python/Pass.cpp (+19-2)
  • (modified) mlir/lib/CAPI/IR/Pass.cpp (+17-2)
  • (modified) mlir/python/mlir/_mlir_libs/_mlir/passmanager.pyi (+9-1)
diff --git a/mlir/include/mlir-c/Pass.h b/mlir/include/mlir-c/Pass.h
index 35db138305d1e2..47edaecd5ed8d8 100644
--- a/mlir/include/mlir-c/Pass.h
+++ b/mlir/include/mlir-c/Pass.h
@@ -76,7 +76,15 @@ mlirPassManagerRunOnOp(MlirPassManager passManager, MlirOperation op);
 
 /// Enable mlir-print-ir-after-all.
 MLIR_CAPI_EXPORTED void
-mlirPassManagerEnableIRPrinting(MlirPassManager passManager);
+mlirPassManagerEnableIRPrinting(MlirPassManager passManager,
+                                bool shouldPrintBeforePass,
+                                bool shouldPrintAfterPass,
+                                bool printAfterOnlyOnChange,
+                                bool printAfterOnlyOnFailure);
+
+// Enable timing of passes
+MLIR_CAPI_EXPORTED void
+mlirPassManagerEnableTiming(MlirPassManager passManager);
 
 /// Enable / disable verify-each.
 MLIR_CAPI_EXPORTED void
diff --git a/mlir/lib/Bindings/Python/Pass.cpp b/mlir/lib/Bindings/Python/Pass.cpp
index a68421b61641f6..60694fa00782a3 100644
--- a/mlir/lib/Bindings/Python/Pass.cpp
+++ b/mlir/lib/Bindings/Python/Pass.cpp
@@ -74,10 +74,27 @@ void mlir::python::populatePassManagerSubmodule(py::module &m) {
            "Releases (leaks) the backing pass manager (testing)")
       .def(
           "enable_ir_printing",
-          [](PyPassManager &passManager) {
-            mlirPassManagerEnableIRPrinting(passManager.get());
+          [](PyPassManager &passManager,
+            bool print_before_pass,
+            bool print_after_pass,
+            bool print_after_only_on_change,
+            bool print_after_only_on_failure) {
+            mlirPassManagerEnableIRPrinting(passManager.get(),
+                                            print_before_pass,
+                                            print_after_pass,
+                                            print_after_only_on_change,
+                                            print_after_only_on_failure);
           },
+          "print_before_pass"_a = true, "print_after_pass"_a = true, 
+          "print_after_only_on_change"_a = true, "print_after_only_on_failure"_a = false,
           "Enable mlir-print-ir-after-all.")
+      .def(
+          "enable_timing",
+          [](PyPassManager &PyPassManager) {
+            mlirPassManagerEnableTiming(PyPassManager.get());
+          },
+          "Enable timing of passes"
+      )
       .def(
           "enable_verifier",
           [](PyPassManager &passManager, bool enable) {
diff --git a/mlir/lib/CAPI/IR/Pass.cpp b/mlir/lib/CAPI/IR/Pass.cpp
index d242baae99c086..a499b1cdbf501f 100644
--- a/mlir/lib/CAPI/IR/Pass.cpp
+++ b/mlir/lib/CAPI/IR/Pass.cpp
@@ -44,8 +44,23 @@ MlirLogicalResult mlirPassManagerRunOnOp(MlirPassManager passManager,
   return wrap(unwrap(passManager)->run(unwrap(op)));
 }
 
-void mlirPassManagerEnableIRPrinting(MlirPassManager passManager) {
-  return unwrap(passManager)->enableIRPrinting();
+void mlirPassManagerEnableIRPrinting(MlirPassManager passManager,
+                                bool shouldPrintBeforePass,
+                                bool shouldPrintAfterPass,
+                                bool printAfterOnlyOnChange,
+                                bool printAfterOnlyOnFailure) {
+  auto shouldPrintBeforeFn = [shouldPrintBeforePass](Pass *, Operation *) {return shouldPrintBeforePass;};
+  auto shouldPrintAfterFn = [shouldPrintAfterPass](Pass *, Operation *) {return shouldPrintAfterPass;};
+ 
+  return unwrap(passManager)->enableIRPrinting(shouldPrintBeforeFn,
+                                                shouldPrintAfterFn,
+                                                true,
+                                                printAfterOnlyOnChange,
+                                                printAfterOnlyOnFailure); 
+}
+
+void mlirPassManagerEnableTiming(MlirPassManager passManager) {
+  return unwrap(passManager)->enableTiming();
 }
 
 void mlirPassManagerEnableVerifier(MlirPassManager passManager, bool enable) {
diff --git a/mlir/python/mlir/_mlir_libs/_mlir/passmanager.pyi b/mlir/python/mlir/_mlir_libs/_mlir/passmanager.pyi
index c072d5e0fb86f3..1c0e7d4d0f6151 100644
--- a/mlir/python/mlir/_mlir_libs/_mlir/passmanager.pyi
+++ b/mlir/python/mlir/_mlir_libs/_mlir/passmanager.pyi
@@ -4,6 +4,7 @@
 #   * Relative imports for cross-module references.
 #   * Add __all__
 
+from pickle import TRUE
 from typing import Any, Optional
 
 from . import ir as _ir
@@ -16,7 +17,14 @@ class PassManager:
     def __init__(self, context: Optional[_ir.Context] = None) -> None: ...
     def _CAPICreate(self) -> object: ...
     def _testing_release(self) -> None: ...
-    def enable_ir_printing(self) -> None: ...
+    def enable_ir_printing(
+        self,
+        print_before_pass=True,
+        print_after_pass=True,
+        print_after_only_on_change=True,
+        print_after_only_on_failure=False,
+    ) -> None: ...
+    def enable_timing(self) -> None: ...
     def enable_verifier(self, enable: bool) -> None: ...
     @staticmethod
     def parse(pipeline: str, context: Optional[_ir.Context] = None) -> PassManager: ...

@vraspar vraspar force-pushed the vrajangp/pass-manager branch from caff7d4 to 43a4862 Compare April 18, 2024 21:02
Copy link

github-actions bot commented Apr 18, 2024

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff 4759890f859277cd798648a9a333573cd088d98a dd062a077de06018cd765526696f6e7200b66c10 -- mlir/include/mlir-c/Pass.h mlir/lib/Bindings/Python/Pass.cpp mlir/lib/CAPI/IR/Pass.cpp
View the diff from clang-format here.
diff --git a/mlir/lib/CAPI/IR/Pass.cpp b/mlir/lib/CAPI/IR/Pass.cpp
index 6d63b6519bd..fdee1077526 100644
--- a/mlir/lib/CAPI/IR/Pass.cpp
+++ b/mlir/lib/CAPI/IR/Pass.cpp
@@ -50,8 +50,12 @@ void mlirPassManagerEnableIRPrinting(MlirPassManager passManager,
                                      bool printModuleScope,
                                      bool printAfterOnlyOnChange,
                                      bool printAfterOnlyOnFailure) {
-  auto shouldPrintBeforeFn = [shouldPrintBeforePass](Pass *, Operation *) {return shouldPrintBeforePass;};
-  auto shouldPrintAfterFn = [shouldPrintAfterPass](Pass *, Operation *) {return shouldPrintAfterPass;};
+  auto shouldPrintBeforeFn = [shouldPrintBeforePass](Pass *, Operation *) {
+    return shouldPrintBeforePass;
+  };
+  auto shouldPrintAfterFn = [shouldPrintAfterPass](Pass *, Operation *) {
+    return shouldPrintAfterPass;
+  };
 
   return unwrap(passManager)
       ->enableIRPrinting(shouldPrintBeforeFn, shouldPrintAfterFn,

@makslevental
Copy link
Contributor

makslevental commented Apr 18, 2024

Overall this is cool - just those small things and I'll approve (and then we wait for 2 days for Windows pre-commit CI workers lol). But I'll keep hitting "approve and run" for you.

@joker-eph joker-eph changed the title Add optional arguments to passmanger ir printing [MLIR][Python] Add optional arguments to PassManager IR printing Apr 18, 2024

Unverified

The committer email address is not verified.
@vraspar vraspar force-pushed the vrajangp/pass-manager branch from 43a4862 to dd062a0 Compare April 21, 2024 23:47
Copy link
Member

@ftynse ftynse left a comment

Choose a reason for hiding this comment

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

I wonder if this would be the right time to introduce a PassManager::PrintConfig struct, or even a more general PassManagerConfig, that would take care of all these API flags. This way, we won't break C API unnecessarily and sparse C and C++ clients the pain on passing a list of mostly useless options.

Comment on lines +53 to +54
auto shouldPrintBeforeFn = [shouldPrintBeforePass](Pass *, Operation *) {return shouldPrintBeforePass;};
auto shouldPrintAfterFn = [shouldPrintAfterPass](Pass *, Operation *) {return shouldPrintAfterPass;};
Copy link
Member

Choose a reason for hiding this comment

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

Can't we actually take a C function pointer instead? On the Python side, we can then do a dispatch based on the actual type and accept bool as well as a py::function.

Copy link
Author

Choose a reason for hiding this comment

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

Hi! I am so sorry for the delay.

I am new to the MLIR world, so my understanding might be incorrect. But, I believe useful implementation from py::function to std::function<bool(Pass *, Operation *)> will need additional wrappers around the Pass and Operation class. Should we add these changes to this pull request?

Thank you so much!

Copy link
Member

Choose a reason for hiding this comment

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

Wrappers are already available. This can take a bool (*shouldPrintAfterPass)(MlirPass, MlirOperation, void *userData). Python binding side can define two overloads: one that takes a bool and another that takes a std::function<bool (MlirPass, MlirOperation)>, both using lambdas to delegate further. I believe we have type casters in place for this to work pretty much out of the box.

@vraspar
Copy link
Author

vraspar commented Apr 22, 2024

The implementation of PassManager::PrintConfig sounds like a great idea. I am planning of adding more options for ir printing from IRPrinterConfing in future.

@Andrew-Cain
Copy link

Hi @vraspar, just checking in to see if you're still working on this PR. It's been a month since the last update. Enabling the additional IR printing functionality through the Python extension is something we care about. Let me know if you need any help.

@vraspar
Copy link
Author

vraspar commented May 26, 2024

Hi @vraspar, just checking in to see if you're still working on this PR. It's been a month since the last update. Enabling the additional IR printing functionality through the Python extension is something we care about. Let me know if you need any help.

Hi @Andrew-Cain. I am so sorry, I just saw this message. I was on vacation since beginnning of May and did not bring my laptop. I will implement suggested changes and update the PR. Thank you!

@makslevental
Copy link
Contributor

vacation since beginnning of May and did not bring my laptop

man what a great vacation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mlir:python MLIR Python bindings mlir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants