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.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
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:
Thoughts? |
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. |
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? |
mlir/lib/Bindings/Python/mlir/transforms/__init__.py | ||
---|---|---|
8 | Ping here @stellaraccident ? |
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. |
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 |
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". |
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 is a bit unfortunate, but the way the tree is setup right now isn't very convenient for modularity