This is an archive of the discontinued LLVM Phabricator instance.

Add basic Python bindings for the PassManager and bind libTransforms
ClosedPublic

Authored by mehdi_amini on Nov 4 2020, 9:23 PM.

Details

Summary

This only exposes the ability to round-trip a textual pipeline at the
moment.
To exercise it, we also bind the libTransforms in a new Python extension. This
does not include any interesting bindings, but it includes all the
mechanism to add separate native extensions and load them dynamically.
As such passes in libTransforms are only registered after `import
mlir.transforms`.
To support this global registration, the TableGen backend is also
extended to bind to the C API the group registration for passes.

Diff Detail

Event Timeline

mehdi_amini created this revision.Nov 4 2020, 9:23 PM
mehdi_amini requested review of this revision.Nov 4 2020, 9:23 PM
mehdi_amini added inline comments.Nov 4 2020, 9:27 PM
mlir/lib/Bindings/Python/CMakeLists.txt
10

This is a bit unfortunate, but the way the tree is setup right now isn't very convenient for modularity

mlir/test/CMakeLists.txt
103

I've been wondering if we shouldn't:

  1. Rename MLIRBindingsPythonExtension to MLIRCoreBindingsPythonExtension
  2. Introduce MLIRBindingsPythonExtensions (Plural) to catch all of the Python extensions

Thoughts?

Minor tweak

stellaraccident accepted this revision.Nov 4 2020, 11:01 PM
stellaraccident added inline comments.
mlir/lib/Bindings/Python/Pass.h
2

Stale comment.

mlir/lib/Bindings/Python/Transforms/Transforms.cpp
2

Stale comment.

21

Stale docstring.

mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

I kind of suspect that we are going to want to just generate the .so file directly into this directory (probably with some kind of naming convention that lets us put other peer transform-extensions in here) instead of maintaining it at the top-level.

Aside from not cluttering up the global namespace when we add more, there are some other build/deploy environments that I have to support where it is extremely obnoxious to have a lot of stuff at the top level.

If it was nested here, you would just import ._builtinTransforms (or whatever you chose to call it).

(I also know you'd probably not like to deal with the rpath issues right now)

mlir/test/Bindings/Python/pass_manager.py
40

Indent.

mlir/test/CMakeLists.txt
103

Makes sense to me and the names sgtm.

This revision is now accepted and ready to land.Nov 4 2020, 11:01 PM
mehdi_amini marked 4 inline comments as done.

Address the minor comments

mehdi_amini added inline comments.Nov 5 2020, 11:56 AM
mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

I don't quite get what is the desired structure here?

For example right now we have:

$ find python/ | grep -v cache
python/
python/_mlir.cpython-38-x86_64-linux-gnu.so
python/_mlirTransforms.cpython-38-x86_64-linux-gnu.so
python/mlir
python/mlir/__init__.py
python/mlir/ir.py
python/mlir/transforms
python/mlir/transforms/__init__.py
python/mlir/dialects
python/mlir/dialects/std.py
python/mlir/dialects/__init__.py
python/mlir/passmanager.py

How do you suggest we structure the tree?

mehdi_amini added inline comments.Nov 6 2020, 1:22 PM
mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

Ping here @stellaraccident ?

stellaraccident added inline comments.Nov 9 2020, 9:43 PM
mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

The python/mlir/... tree should make sense to the user as a package tree of public APIs.

What I was trying to do (which may be a fool's errand) was to preserve the ability for everything below the top-level python/mlir/__init__.py file to be relocatable: if I had a downstream project that wanted to privately package a variant of the MLIR Python API, they could just copy the python files and replace the top-level "loader" init__.py, which is responsible for the minutae of how to find the backing extensions and dependencies. I was also leaving room here in case if we wanted fully static builds or such to just have the root init__.py be the point of customization vs having absolute imports everywhere. I will mention that aside from future projects, this is not just a hypothetical for you/me: Google's internal deployments of these things require loader customizations in order to associate with the c-extension, and I've worked in enough other weird, static-linking scenarios to know that this flexibility and relocatability pay off eventually (and is a pain to retrofit/sed-your-way-through downstream when needed).

We can keep it the way you have it for now. What we may want to do is expose a top-level _import_extension(name) that imports the _mlir or _mlirTransforms (or whatever other) extensions in an installation specific way. Then instead of an absolute import here, you would:

from . import _import_extension
_cextTransforms = _import_extension("_mlirTransforms")

That is easy enough to do in a followup.

mehdi_amini added inline comments.Nov 10 2020, 10:05 AM
mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

Would we avoid the need to set a PYTHONPATH and get a simpler loader with a layout that would look like the following?

python/mlir/_mlir.cpython-38-x86_64-linux-gnu.so
python/mlir/__init__.py
python/mlir/transforms/_mlirTransforms.cpython-38-x86_64-linux-gnu.so
python/mlir/transforms/__init__.py
mehdi_amini added inline comments.Nov 10 2020, 10:38 AM
mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

Actually that does not prevent the need for PYTHONPATH to find the mlir folder, but it makes it more "self-contained".
There is still a dependency on libMLIRPublicAPI.so though.

mlir/lib/Bindings/Python/mlir/transforms/__init__.py
8

We went back and forth on this a long time ago. There are some nice characteristics that come from *not* making it self contained. Namely, once you "open" a package with an __init__.py, you lose the ability to treat any part of it as a "Namespace Package", which further restricts your ability to have a separate wheel for it. This stems from the fact that the Python import machinery stops at the first directory it finds that is a package, regardless of whether what you are looking for is located there (i.e. it does not "overlay" PYTHONPATH directories in the same way that C++ include paths are).

Again, this can be done either way and the preference of one vs the other stems mostly from experience of having been burned by packaging concerns. It remains unclear whether we will use the flexibility provided by not deeply co-mingling the extensions with the Python code, but I would advocate for keeping it as separable as possible when the choice has no clear benefits either way.

This revision was landed with ongoing or failed builds.Nov 10 2020, 11:55 AM
This revision was automatically updated to reflect the committed changes.