[llvm-branch-commits] [mlir] 52586c4 - [mlir][CAPI] Add result type inference to the CAPI.
Author: Stella Laurenzo Date: 2021-01-23T14:30:51-08:00 New Revision: 52586c46b0883600a332fd64731dc5287981f980 URL: https://github.com/llvm/llvm-project/commit/52586c46b0883600a332fd64731dc5287981f980 DIFF: https://github.com/llvm/llvm-project/commit/52586c46b0883600a332fd64731dc5287981f980.diff LOG: [mlir][CAPI] Add result type inference to the CAPI. * Adds a flag to MlirOperationState to enable result type inference using the InferTypeOpInterface. * I chose this level of implementation for a couple of reasons: a) In the creation flow is naturally where generated and custom builder code will be invoking such a thing b) it is a bit more efficient to share the data structure and unpacking vs having a standalone entry-point c) we can always decide to expose more of these interfaces with first-class APIs, but that doesn't preclude that we will always want to use this one in this way (and less API surface area for common things is better for API stability and evolution). * I struggled to find an appropriate way to test it since we don't link the test dialect into anything CAPI accessible at present. I opted instead for one of the simplest ops I found in a regular dialect which implements the interface. * This does not do any trait-based type selection. That will be left to generated tablegen wrappers. Differential Revision: https://reviews.llvm.org/D95283 Added: Modified: mlir/include/mlir-c/IR.h mlir/lib/CAPI/IR/IR.cpp mlir/test/CAPI/ir.c Removed: diff --git a/mlir/include/mlir-c/IR.h b/mlir/include/mlir-c/IR.h index 13e32be049e4..39f42e4bf497 100644 --- a/mlir/include/mlir-c/IR.h +++ b/mlir/include/mlir-c/IR.h @@ -225,6 +225,7 @@ struct MlirOperationState { MlirBlock *successors; intptr_t nAttributes; MlirNamedAttribute *attributes; + bool enableResultTypeInference; }; typedef struct MlirOperationState MlirOperationState; @@ -249,6 +250,14 @@ MLIR_CAPI_EXPORTED void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n, MlirNamedAttribute const *attributes); +/// Enables result type inference for the operation under construction. If +/// enabled, then the caller must not have called +/// mlirOperationStateAddResults(). Note that if enabled, the +/// mlirOperationCreate() call is failable: it will return a null operation +/// on inference failure and will emit diagnostics. +MLIR_CAPI_EXPORTED void +mlirOperationStateEnableResultTypeInference(MlirOperationState *state); + //===--===// // Op Printing flags API. // While many of these are simple settings that could be represented in a @@ -293,8 +302,14 @@ mlirOpPrintingFlagsUseLocalScope(MlirOpPrintingFlags flags); //===--===// /// Creates an operation and transfers ownership to the caller. -MLIR_CAPI_EXPORTED MlirOperation -mlirOperationCreate(const MlirOperationState *state); +/// Note that caller owned child objects are transferred in this call and must +/// not be further used. Particularly, this applies to any regions added to +/// the state (the implementation may invalidate any such pointers). +/// +/// This call can fail under the following conditions, in which case, it will +/// return a null operation and emit diagnostics: +/// - Result type inference is enabled and cannot be performed. +MLIR_CAPI_EXPORTED MlirOperation mlirOperationCreate(MlirOperationState *state); /// Takes an operation owned by the caller and destroys it. MLIR_CAPI_EXPORTED void mlirOperationDestroy(MlirOperation op); diff --git a/mlir/lib/CAPI/IR/IR.cpp b/mlir/lib/CAPI/IR/IR.cpp index 30d4c8c41835..bf240046be25 100644 --- a/mlir/lib/CAPI/IR/IR.cpp +++ b/mlir/lib/CAPI/IR/IR.cpp @@ -18,6 +18,7 @@ #include "mlir/IR/Operation.h" #include "mlir/IR/Types.h" #include "mlir/IR/Verifier.h" +#include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Parser.h" using namespace mlir; @@ -188,6 +189,7 @@ MlirOperationState mlirOperationStateGet(MlirStringRef name, MlirLocation loc) { state.successors = nullptr; state.nAttributes = 0; state.attributes = nullptr; + state.enableResultTypeInference = false; return state; } @@ -219,11 +221,47 @@ void mlirOperationStateAddAttributes(MlirOperationState *state, intptr_t n, APPEND_ELEMS(MlirNamedAttribute, nAttributes, attributes); } +void mlirOperationStateEnableResultTypeInference(MlirOperationState *state) { + state->enableResultTypeInference = true; +} + //===--===// // Operation API. //===--===// -MlirOperation mlirOperationCreate(const MlirOperationState *state) { +static LogicalResult inferOperationTypes(OperationState &
[llvm-branch-commits] [mlir] fd226c9 - [mlir][Python] Roll up of python API fixes.
Author: Stella Laurenzo Date: 2021-01-24T19:02:59-08:00 New Revision: fd226c9b028d38145b446dddc50db64eb6012d22 URL: https://github.com/llvm/llvm-project/commit/fd226c9b028d38145b446dddc50db64eb6012d22 DIFF: https://github.com/llvm/llvm-project/commit/fd226c9b028d38145b446dddc50db64eb6012d22.diff LOG: [mlir][Python] Roll up of python API fixes. * As discussed, fixes the ordering or (operands, results) -> (results, operands) in various `create` like methods. * Fixes a syntax error in an ODS accessor method. * Removes the linalg example in favor of a test case that exercises the same. * Fixes FuncOp visibility to properly use None instead of the empty string and defaults it to None. * Implements what was documented for requiring that trailing __init__ args `loc` and `ip` are keyword only. * Adds a check to `InsertionPoint.insert` so that if attempting to insert past the terminator, an exception is raised telling you what to do instead. Previously, this would crash downstream (i.e. when trying to print the resultant module). * Renames `_ods_build_default` -> `build_generic` and documents it. * Removes `result` from the list of prohibited words and for single-result ops, defaults to naming the result `result`, thereby matching expectations and what is already implemented on the base class. * This was intended to be a relatively small set of changes to be inlined with the broader support for ODS generating the most specific builder, but it spidered out once actually testing various combinations, so rolling up separately. Differential Revision: https://reviews.llvm.org/D95320 Added: mlir/test/Bindings/Python/dialects/linalg.py Modified: mlir/docs/Bindings/Python.md mlir/lib/Bindings/Python/IRModules.cpp mlir/lib/Bindings/Python/IRModules.h mlir/lib/Bindings/Python/mlir/dialects/_builtin.py mlir/lib/Bindings/Python/mlir/dialects/_linalg.py mlir/test/Bindings/Python/insertion_point.py mlir/test/Bindings/Python/ods_helpers.py mlir/test/mlir-tblgen/op-python-bindings.td mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp Removed: mlir/examples/python/.style.yapf mlir/examples/python/linalg_matmul.py diff --git a/mlir/docs/Bindings/Python.md b/mlir/docs/Bindings/Python.md index 6bb9e7ebe2f6..7ea5d022b34f 100644 --- a/mlir/docs/Bindings/Python.md +++ b/mlir/docs/Bindings/Python.md @@ -439,8 +439,9 @@ defaults on `OpView`): Builders Presently, only a single, default builder is mapped to the `__init__` method. -Generalizing this facility is under active development. It currently accepts -arguments: +The intent is that this `__init__` method represents the *most specific* of +the builders typically generated for C++; however currently it is just the +generic form below. * One argument for each declared result: * For single-valued results: Each will accept an `mlir.ir.Type`. @@ -453,7 +454,11 @@ arguments: * `loc`: An explicit `mlir.ir.Location` to use. Defaults to the location bound to the thread (i.e. `with Location.unknown():`) or an error if none is bound nor specified. - * `context`: An explicit `mlir.ir.Context` to use. Default to the context -bound to the thread (i.e. `with Context():` or implicitly via `Location` or -`InsertionPoint` context managers) or an error if none is bound nor -specified. + * `ip`: An explicit `mlir.ir.InsertionPoint` to use. Default to the insertion +point bound to the thread (i.e. `with InsertionPoint(...):`). + +In addition, each `OpView` inherits a `build_generic` method which allows +construction via a (nested in the case of variadic) sequence of `results` and +`operands`. This can be used to get some default construction semantics for +operations that are otherwise unsupported in Python, at the expense of having +a very generic signature. diff --git a/mlir/examples/python/.style.yapf b/mlir/examples/python/.style.yapf deleted file mode 100644 index 9ef1dc15ba62.. --- a/mlir/examples/python/.style.yapf +++ /dev/null @@ -1,4 +0,0 @@ -[style] - based_on_style = google - column_limit = 80 - indent_width = 2 diff --git a/mlir/examples/python/linalg_matmul.py b/mlir/examples/python/linalg_matmul.py deleted file mode 100644 index 0bd3c12a0378.. --- a/mlir/examples/python/linalg_matmul.py +++ /dev/null @@ -1,81 +0,0 @@ -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -# This is a work in progress example to do end2end build and code generation -# of a small linalg program with configuration options. It is currently non -# functional and is being used to elaborate the APIs. - -from typing import Tuple - -from mlir.ir import * -from mlir.dialects import linalg -from mlir.dialects import std - - -# TODO: This should
[llvm-branch-commits] [mlir] d36a15d - [mlir][linalg] Memoize indexing map generation.
Author: Stella Laurenzo Date: 2021-03-01T21:15:40-08:00 New Revision: d36a15de1ff4d24e772233406d602c5f0b370f54 URL: https://github.com/llvm/llvm-project/commit/d36a15de1ff4d24e772233406d602c5f0b370f54 DIFF: https://github.com/llvm/llvm-project/commit/d36a15de1ff4d24e772233406d602c5f0b370f54.diff LOG: [mlir][linalg] Memoize indexing map generation. Differential Revision: https://reviews.llvm.org/D97602 Added: Modified: mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp Removed: diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp index acc8ff1807c1..46e5780e151f 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -2333,8 +2333,11 @@ static void printNamedStructuredOpResults(OpAsmPrinter &p, template static void printNamedStructuredOp(OpAsmPrinter &p, NamedStructuredOpType op) { p << op.getOperationName(); - p.printOptionalAttrDict(op->getAttrs(), - /*elidedAttrs=*/{"operand_segment_sizes"}); + p.printOptionalAttrDict( + op->getAttrs(), + /*elidedAttrs=*/{"operand_segment_sizes", + // See generated code in mlir-linalg-yaml-gen.cpp + "linalg.memoized_indexing_maps"}); // Printing is shared with generic ops, except for the region and // attributes. diff --git a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp index 5578ff52d477..1dddc57f25d3 100644 --- a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp +++ b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-yaml-gen.cpp @@ -651,11 +651,18 @@ static SmallVector getSymbolBindings({0} self) { // {2}: Statements static const char structuredOpIndexingMapsFormat[] = R"FMT( ArrayAttr {0}::indexing_maps() { + static const char memoizeAttr[] = "linalg.memoized_indexing_maps"; + ArrayAttr cached = getOperation()->getAttrOfType(memoizeAttr); + if (cached) +return cached; + MLIRContext *context = getContext(); auto symbolBindings = getSymbolBindings(*this); SmallVector maps; {2} - return Builder(context).getAffineMapArrayAttr(maps); + cached = Builder(context).getAffineMapArrayAttr(maps); + getOperation()->setAttr(memoizeAttr, cached); + return cached; } )FMT"; ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 594e0ba - [mlir][python] Add docs for op class extension mechanism.
Author: Stella Laurenzo Date: 2021-03-25T18:27:26-07:00 New Revision: 594e0ba969670a268e50e9f620cc04293ab9065b URL: https://github.com/llvm/llvm-project/commit/594e0ba969670a268e50e9f620cc04293ab9065b DIFF: https://github.com/llvm/llvm-project/commit/594e0ba969670a268e50e9f620cc04293ab9065b.diff LOG: [mlir][python] Add docs for op class extension mechanism. Differential Revision: https://reviews.llvm.org/D99387 Added: Modified: mlir/docs/Bindings/Python.md Removed: diff --git a/mlir/docs/Bindings/Python.md b/mlir/docs/Bindings/Python.md index e5e8e6d77c30..902c03916a8e 100644 --- a/mlir/docs/Bindings/Python.md +++ b/mlir/docs/Bindings/Python.md @@ -449,7 +449,7 @@ defaults on `OpView`): variadics. Used by `OpView._ods_build_default` to decode operand and result lists that contain lists. - Builders + Default Builder Presently, only a single, default builder is mapped to the `__init__` method. The intent is that this `__init__` method represents the *most specific* of @@ -475,3 +475,90 @@ construction via a (nested in the case of variadic) sequence of `results` and `operands`. This can be used to get some default construction semantics for operations that are otherwise unsupported in Python, at the expense of having a very generic signature. + + Extending Generated Op Classes + +Note that this is a rather complex mechanism and this section errs on the side +of explicitness. Users are encouraged to find an example and duplicate it if +they don't feel the need to understand the subtlety. The `builtin` dialect +provides some relatively simple examples. + +As mentioned above, the build system generates Python sources like +`_{DIALECT_NAMESPACE}_ops_gen.py` for each dialect with Python bindings. It +is often desirable to to use these generated classes as a starting point for +further customization, so an extension mechanism is provided to make this +easy (you are always free to do ad-hoc patching in your `{DIALECT_NAMESPACE}.py` +file but we prefer a more standard mechanism that is applied uniformly). + +To provide extensions, add a `_{DIALECT_NAMESPACE}_ops_ext.py` file to the +`dialects` module (i.e. adjacent to your `{DIALECT_NAMESPACE}.py` top-level +and the `*_ops_gen.py` file). Using the `builtin` dialect and `FuncOp` as an +example, the generated code will include an import like this: + +```python +try: + from . import _builtin_ops_ext as _ods_ext_module +except ImportError: + _ods_ext_module = None +``` + +Then for each generated concrete `OpView` subclass, it will apply a decorator +like: + +```python +@_ods_cext.register_operation(_Dialect) +@_ods_extend_opview_class(_ods_ext_module) +class FuncOp(_ods_ir.OpView): +``` + +See the `_ods_common.py` `extend_opview_class` function for details of the +mechanism. At a high level: + +* If the extension module exists, locate an extension class for the op (in + this example, `FuncOp`): + * First by looking for an attribute with the exact name in the extension +module. + * Falling back to calling a `select_opview_mixin(parent_opview_cls)` +function defined in the extension module. +* If a mixin class is found, a new subclass is dynamically created that multiply + inherits from `({_builtin_ops_ext.FuncOp}, _builtin_ops_gen.FuncOp)`. + +The mixin class should not inherit from anything (i.e. directly extends +`object` only). The facility is typically used to define custom `__init__` +methods, properties, instance methods and static methods. Due to the +inheritance ordering, the mixin class can act as though it extends the +generated `OpView` subclass in most contexts (i.e. +`issubclass(_builtin_ops_ext.FuncOp, OpView)` will return `False` but usage +generally allows you treat it as duck typed as an `OpView`). + +There are a couple of recommendations, given how the class hierarchy is +defined: + +* For static methods that need to instantiate the actual "leaf" op (which + is dynamically generated and would result in circular dependencies to try + to reference by name), prefer to use `@classmethod` and the concrete + subclass will be provided as your first `cls` argument. See + `_builtin_ops_ext.FuncOp.from_py_func` as an example. +* If seeking to replace the generated `__init__` method entirely, you may + actually want to invoke the super-super-class `mlir.ir.OpView` constructor + directly, as it takes an `mlir.ir.Operation`, which is likely what you + are constructing (i.e. the generated `__init__` method likely adds more + API constraints than you want to expose in a custom builder). + +A pattern that comes up frequently is wanting to provide a sugared `__init__` +method which has optional or type-polymorphism/implicit conversions but to +otherwise want to invoke the default op building logic. For such cases, +it is recommended to use an idiom such as: + +```python + def __init__(self, sugar, spice, *, loc
[llvm-branch-commits] [mlir] 417f613 - [NFC] Update some mlir python documentation.
Author: Stella Laurenzo Date: 2021-01-18T11:51:11-08:00 New Revision: 417f613743239a716d812443ba131207d78c6c9d URL: https://github.com/llvm/llvm-project/commit/417f613743239a716d812443ba131207d78c6c9d DIFF: https://github.com/llvm/llvm-project/commit/417f613743239a716d812443ba131207d78c6c9d.diff LOG: [NFC] Update some mlir python documentation. * Development setup recommendations. * Test updates to match what we actually do. * Update cmake variable `PYTHON_EXECUTABLE` -> `Python3_EXECUTABLE` to match the upgrade to python3 repo wide. Added: Modified: mlir/docs/Bindings/Python.md Removed: diff --git a/mlir/docs/Bindings/Python.md b/mlir/docs/Bindings/Python.md index 89f2742e2fad..ce8a09fb8573 100644 --- a/mlir/docs/Bindings/Python.md +++ b/mlir/docs/Bindings/Python.md @@ -17,6 +17,13 @@ Current status: Under development and not enabled by default Enables building the Python bindings. Defaults to `OFF`. +* **`Python3_EXECUTABLE`**:`STRING` + + Specifies the `python` executable used for the LLVM build, including for + determining header/link flags for the Python bindings. On systems with + multiple Python implementations, setting this explicitly to the preferred + `python3` executable is strongly recommended. + * **`MLIR_PYTHON_BINDINGS_VERSION_LOCKED`**`:BOOL` Links the native extension against the Python runtime library, which is @@ -25,12 +32,32 @@ Current status: Under development and not enabled by default compile time errors for unresolved symbols on all platforms, which makes for a smoother development workflow. Defaults to `ON`. -* **`PYTHON_EXECUTABLE`**:`STRING` +### Recommended development practices - Specifies the `python` executable used for the LLVM build, including for - determining header/link flags for the Python bindings. On systems with - multiple Python implementations, setting this explicitly to the preferred - `python3` executable is strongly recommended. +It is recommended to use a python virtual environment. Many ways exist for this, +but the following is the simplest: + +```shell +# Make sure your 'python' is what you expect. Note that on multi-python +# systems, this may have a version suffix, and on many Linuxes and MacOS where +# python2 and python3 co-exist, you may also want to use `python3`. +which python +python -m venv ~/.venv/mlirdev +source ~/.venv/mlirdev/bin/activate + +# Now the `python` command will resolve to your virtual environment and +# packages will be installed there. +python -m pip install pybind11 numpy + +# Now run `cmake`, `ninja`, et al. +``` + +For interactive use, it is sufficient to add the `python` directory in your +`build/` directory to the `PYTHONPATH`. Typically: + +```shell +export PYTHONPATH=$(cd build && pwd)/python +``` ## Design @@ -292,57 +319,16 @@ mutually exclusive with a more complete mapping of the backing constructs. Tests should be added in the `test/Bindings/Python` directory and should typically be `.py` files that have a lit run line. -While lit can run any python module, prefer to lay tests out according to these -rules: +We use `lit` and `FileCheck` based tests: -* For tests of the API surface area, prefer - [`doctest`](https://docs.python.org/3/library/doctest.html). * For generative tests (those that produce IR), define a Python module that constructs/prints the IR and pipe it through `FileCheck`. * Parsing should be kept self-contained within the module under test by use of raw constants and an appropriate `parse_asm` call. * Any file I/O code should be staged through a tempfile vs relying on file artifacts/paths outside of the test module. - -### Sample Doctest - -```python -# RUN: %PYTHON %s - -""" - >>> m = load_test_module() -Test basics: - >>> m.operation.name - "module" - >>> m.operation.is_registered - True - >>> ... etc ... - -Verify that repr prints: - >>> m.operation - -""" - -import mlir - -TEST_MLIR_ASM = r""" -func @test_operation_correct_regions() { - // ... -} -""" - -# TODO: Move to a test utility class once any of this actually exists. -def load_test_module(): - ctx = mlir.ir.Context() - ctx.allow_unregistered_dialects = True - module = ctx.parse_asm(TEST_MLIR_ASM) - return module - - -if __name__ == "__main__": - import doctest - doctest.testmod() -``` +* For convenience, we also test non-generative API interactions with the same + mechanisms, printing and `CHECK`ing as needed. ### Sample FileCheck test ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] d9b6e4d - NFC: Document current MLIR Python ODS conventions.
Author: Stella Laurenzo Date: 2021-01-18T12:24:41-08:00 New Revision: d9b6e4d583c5585b756680e6da3fbd0bb8f0a722 URL: https://github.com/llvm/llvm-project/commit/d9b6e4d583c5585b756680e6da3fbd0bb8f0a722 DIFF: https://github.com/llvm/llvm-project/commit/d9b6e4d583c5585b756680e6da3fbd0bb8f0a722.diff LOG: NFC: Document current MLIR Python ODS conventions. * We had let the documentation get stale and catching it up prior to proposing changes. Added: Modified: mlir/docs/Bindings/Python.md Removed: diff --git a/mlir/docs/Bindings/Python.md b/mlir/docs/Bindings/Python.md index ce8a09fb8573..b5595bc7010e 100644 --- a/mlir/docs/Bindings/Python.md +++ b/mlir/docs/Bindings/Python.md @@ -352,3 +352,93 @@ def create_my_op(): builder.my_op() return m ``` + +## Integration with ODS + +The MLIR Python bindings integrate with the tablegen-based ODS system for +providing user-friendly wrappers around MLIR dialects and operations. There +are multiple parts to this integration, outlined below. Most details have +been elided: refer to the build rules and python sources under `mlir.dialects` +for the canonical way to use this facility. + +### Generating `{DIALECT_NAMESPACE}.py` wrapper modules + +Each dialect with a mapping to python requires that an appropriate +`{DIALECT_NAMESPACE}.py` wrapper module is created. This is done by invoking +`mlir-tablegen` on a python-bindings specific tablegen wrapper that includes +the boilerplate and actual dialect specific `td` file. An example, for the +`StandardOps` (which is assigned the namespace `std` as a special case): + +```tablegen +#ifndef PYTHON_BINDINGS_STANDARD_OPS +#define PYTHON_BINDINGS_STANDARD_OPS + +include "mlir/Bindings/Python/Attributes.td" +include "mlir/Dialect/StandardOps/IR/Ops.td" + +#endif +``` + +In the main repository, building the wrapper is done via the CMake function +`add_mlir_dialect_python_bindings`, which invokes: + +``` +mlir-tablegen -gen-python-op-bindings -bind-dialect={DIALECT_NAMESPACE} \ +{PYTHON_BINDING_TD_FILE} +``` + +### Extending the search path for wrapper modules + +When the python bindings need to locate a wrapper module, they consult the +`dialect_search_path` and use it to find an appropriately named module. For +the main repository, this search path is hard-coded to include the +`mlir.dialects` module, which is where wrappers are emitted by the abobe build +rule. Out of tree dialects and add their modules to the search path by calling: + +```python +mlir._cext.append_dialect_search_prefix("myproject.mlir.dialects") +``` + +### Wrapper module code organization + +The wrapper module tablegen emitter outputs: + +* A `_Dialect` class (extending `mlir.ir.Dialect`) with a `DIALECT_NAMESPACE` + attribute. +* An `{OpName}` class for each operation (extending `mlir.ir.OpView`). +* Decorators for each of the above to register with the system. + +Note: In order to avoid naming conflicts, all internal names used by the wrapper +module are prefixed by `_ods_`. + +Each concrete `OpView` subclass further defines several attributes: + +* `OPERATION_NAME` attribute with the `str` fully qualified operation name + (i.e. `std.absf`). +* An `__init__` method for the *default builder* if one is defined or inferred + for the operation. +* `@property` getter for each operand or result (using an auto-generated name + for unnamed of each). +* `@property` getter, setter and deleter for each declared attribute. + + Builders + +Presently, only a single, default builder is mapped to the `__init__` method. +Generalizing this facility is under active development. It currently accepts +arguments: + +* One argument for each declared result: + * For single-valued results: Each will accept an `mlir.ir.Type`. + * For variadic results: Each will accept a `List[mlir.ir.Type]`. +* One argument for each declared operand or attribute: + * For single-valued operands: Each will accept an `mlir.ir.Value`. + * For variadic operands: Each will accept a `List[mlir.ir.Value]`. + * For attributes, it will accept an `mlir.ir.Attribute`. +* Trailing usage-specific, optional keyword arguments: + * `loc`: An explicit `mlir.ir.Location` to use. Defaults to the location +bound to the thread (i.e. `with Location.unknown():`) or an error if none +is bound nor specified. + * `context`: An explicit `mlir.ir.Context` to use. Default to the context +bound to the thread (i.e. `with Context():` or implicitly via `Location` or +`InsertionPoint` context managers) or an error if none is bound nor +specified. ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 71b6b01 - [mlir][python] Factor out standalone OpView._ods_build_default class method.
Author: Stella Laurenzo Date: 2021-01-19T09:29:57-08:00 New Revision: 71b6b010e6bc49caaec511195e33ac1f43f07c64 URL: https://github.com/llvm/llvm-project/commit/71b6b010e6bc49caaec511195e33ac1f43f07c64 DIFF: https://github.com/llvm/llvm-project/commit/71b6b010e6bc49caaec511195e33ac1f43f07c64.diff LOG: [mlir][python] Factor out standalone OpView._ods_build_default class method. * This allows us to hoist trait level information for regions and sized-variadic to class level attributes (_ODS_REGIONS, _ODS_OPERAND_SEGMENTS, _ODS_RESULT_SEGMENTS). * Eliminates some splicey python generated code in favor of a native helper for it. * Makes it possible to implement custom, variadic and region based builders with one line of python, without needing to manually code access to the segment attributes. * Needs follow-on work for region based callbacks and support for SingleBlockImplicitTerminator. * A follow-up will actually add ODS support for generating custom Python builders that delegate to this new method. * Also includes the start of an e2e sample for constructing linalg ops where this limitation was discovered (working progressively through this example and cleaning up as I go). Differential Revision: https://reviews.llvm.org/D94738 Added: mlir/examples/python/linalg_matmul.py mlir/test/Bindings/Python/ods_helpers.py Modified: mlir/docs/Bindings/Python.md mlir/lib/Bindings/Python/IRModules.cpp mlir/lib/Bindings/Python/IRModules.h mlir/test/mlir-tblgen/op-python-bindings.td mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp Removed: diff --git a/mlir/docs/Bindings/Python.md b/mlir/docs/Bindings/Python.md index b5595bc7010e..6bb9e7ebe2f6 100644 --- a/mlir/docs/Bindings/Python.md +++ b/mlir/docs/Bindings/Python.md @@ -365,7 +365,7 @@ for the canonical way to use this facility. Each dialect with a mapping to python requires that an appropriate `{DIALECT_NAMESPACE}.py` wrapper module is created. This is done by invoking -`mlir-tablegen` on a python-bindings specific tablegen wrapper that includes +`mlir-tblgen` on a python-bindings specific tablegen wrapper that includes the boilerplate and actual dialect specific `td` file. An example, for the `StandardOps` (which is assigned the namespace `std` as a special case): @@ -383,7 +383,7 @@ In the main repository, building the wrapper is done via the CMake function `add_mlir_dialect_python_bindings`, which invokes: ``` -mlir-tablegen -gen-python-op-bindings -bind-dialect={DIALECT_NAMESPACE} \ +mlir-tblgen -gen-python-op-bindings -bind-dialect={DIALECT_NAMESPACE} \ {PYTHON_BINDING_TD_FILE} ``` @@ -411,7 +411,8 @@ The wrapper module tablegen emitter outputs: Note: In order to avoid naming conflicts, all internal names used by the wrapper module are prefixed by `_ods_`. -Each concrete `OpView` subclass further defines several attributes: +Each concrete `OpView` subclass further defines several public-intended +attributes: * `OPERATION_NAME` attribute with the `str` fully qualified operation name (i.e. `std.absf`). @@ -421,6 +422,20 @@ Each concrete `OpView` subclass further defines several attributes: for unnamed of each). * `@property` getter, setter and deleter for each declared attribute. +It further emits additional private-intended attributes meant for subclassing +and customization (default cases omit these attributes in favor of the +defaults on `OpView`): + +* `_ODS_REGIONS`: A specification on the number and types of regions. + Currently a tuple of (min_region_count, has_no_variadic_regions). Note that + the API does some light validation on this but the primary purpose is to + capture sufficient information to perform other default building and region + accessor generation. +* `_ODS_OPERAND_SEGMENTS` and `_ODS_RESULT_SEGMENTS`: Black-box value which + indicates the structure of either the operand or results with respect to + variadics. Used by `OpView._ods_build_default` to decode operand and result + lists that contain lists. + Builders Presently, only a single, default builder is mapped to the `__init__` method. diff --git a/mlir/examples/python/linalg_matmul.py b/mlir/examples/python/linalg_matmul.py new file mode 100644 index ..83dc15eda9b6 --- /dev/null +++ b/mlir/examples/python/linalg_matmul.py @@ -0,0 +1,73 @@ +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# This is a work in progress example to do end2end build and code generation +# of a small linalg program with configuration options. It is currently non +# functional and is being used to elaborate the APIs. + +from typing import Tuple + +from mlir.ir import * +from mlir.dialects import linalg +from mlir.dialects import std + + +# TODO: This shoul
[llvm-branch-commits] [mlir] 894d88a - [mlir][python] Add facility for extending generated python ODS.
Author: Stella Laurenzo Date: 2021-01-19T13:20:26-08:00 New Revision: 894d88a759c9376de4a48ed99c965aac97839b6c URL: https://github.com/llvm/llvm-project/commit/894d88a759c9376de4a48ed99c965aac97839b6c DIFF: https://github.com/llvm/llvm-project/commit/894d88a759c9376de4a48ed99c965aac97839b6c.diff LOG: [mlir][python] Add facility for extending generated python ODS. * This isn't exclusive with other mechanisms for more ODS centric op definitions, but based on discussions, we feel that we will always benefit from a python escape hatch, and that is the most natural way to write things that don't fit the mold. * I suspect this facility needs further tweaking, and once it settles, I'll document it and add more tests. * Added extensions for linalg, since it is unusable without them and continued to evolve my e2e example. Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D94752 Added: mlir/examples/python/.style.yapf mlir/lib/Bindings/Python/.style.yapf mlir/lib/Bindings/Python/mlir/dialects/_linalg.py Modified: mlir/examples/python/linalg_matmul.py mlir/lib/Bindings/Python/CMakeLists.txt mlir/lib/Bindings/Python/mlir/dialects/__init__.py mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp Removed: diff --git a/mlir/examples/python/.style.yapf b/mlir/examples/python/.style.yapf new file mode 100644 index ..9ef1dc15ba62 --- /dev/null +++ b/mlir/examples/python/.style.yapf @@ -0,0 +1,4 @@ +[style] + based_on_style = google + column_limit = 80 + indent_width = 2 diff --git a/mlir/examples/python/linalg_matmul.py b/mlir/examples/python/linalg_matmul.py index 83dc15eda9b6..e9be189bfaaf 100644 --- a/mlir/examples/python/linalg_matmul.py +++ b/mlir/examples/python/linalg_matmul.py @@ -15,59 +15,69 @@ # TODO: This should be in the core API. def FuncOp(name: str, func_type: Type) -> Tuple[Operation, Block]: -"""Creates a |func| op. + """Creates a |func| op. TODO: This should really be in the MLIR API. Returns: (operation, entry_block) """ -attrs = { -"type": TypeAttr.get(func_type), -"sym_name": StringAttr.get(name), -} -op = Operation.create("func", regions=1, attributes=attrs) -body_region = op.regions[0] -entry_block = body_region.blocks.append(*func_type.inputs) -return op, entry_block + attrs = { + "type": TypeAttr.get(func_type), + "sym_name": StringAttr.get(name), + } + op = Operation.create("func", regions=1, attributes=attrs) + body_region = op.regions[0] + entry_block = body_region.blocks.append(*func_type.inputs) + return op, entry_block -# TODO: Generate customs builder vs patching one in. -def PatchMatmulOpInit(self, lhs, rhs, result, loc=None, ip=None): -super(linalg.MatmulOp, self).__init__( -self._ods_build_default(operands=[[lhs, rhs], [result]], -results=[], -loc=loc, -ip=ip)) +def build_matmul_buffers_func(func_name, m, k, n, dtype): + lhs_type = MemRefType.get(dtype, [m, k]) + rhs_type = MemRefType.get(dtype, [k, n]) + result_type = MemRefType.get(dtype, [m, n]) + # TODO: There should be a one-liner for this. + func_type = FunctionType.get([lhs_type, rhs_type, result_type], []) + _, entry = FuncOp(func_name, func_type) + lhs, rhs, result = entry.arguments + with InsertionPoint(entry): +op = linalg.MatmulOp([lhs, rhs], [result]) # TODO: Implement support for SingleBlockImplicitTerminator -block = self.regions[0].blocks.append() +block = op.regions[0].blocks.append() with InsertionPoint(block): linalg.YieldOp(values=[]) -linalg.MatmulOp.__init__ = PatchMatmulOpInit +std.ReturnOp([]) -def build_matmul_func(func_name, m, k, n, dtype): -lhs_type = MemRefType.get(dtype, [m, k]) -rhs_type = MemRefType.get(dtype, [k, n]) -result_type = MemRefType.get(dtype, [m, n]) -# TODO: There should be a one-liner for this. -func_type = FunctionType.get([lhs_type, rhs_type, result_type], []) -_, entry = FuncOp(func_name, func_type) -lhs, rhs, result = entry.arguments -with InsertionPoint(entry): -linalg.MatmulOp(lhs, rhs, result) -std.ReturnOp([]) +def build_matmul_tensors_func(func_name, m, k, n, dtype): + # TODO: MemRefType and TensorTypes should not have inverted dtype/shapes + # from each other. + lhs_type = RankedTensorType.get([m, k], dtype) + rhs_type = RankedTensorType.get([k, n], dtype) + result_type = RankedTensorType.get([m, n], dtype) + # TODO: There should be a one-liner for this. + func_type = FunctionType.get([lhs_type, rhs_type], [result_type]) + _, entry = FuncOp(func_name, func_type) + lhs, rhs = entry.arguments + with InsertionPoint(entry): +op = linalg.MatmulOp([lhs, rhs], results=[result_type]) +# TODO: Implement support for SingleB
[llvm-branch-commits] [mlir] b62c7e0 - [mlir][python] Swap shape and element_type order for MemRefType.
Author: Stella Laurenzo Date: 2021-01-19T16:03:19-08:00 New Revision: b62c7e047420026dcfe84ad66969f501698acbee URL: https://github.com/llvm/llvm-project/commit/b62c7e047420026dcfe84ad66969f501698acbee DIFF: https://github.com/llvm/llvm-project/commit/b62c7e047420026dcfe84ad66969f501698acbee.diff LOG: [mlir][python] Swap shape and element_type order for MemRefType. * Matches how all of the other shaped types are declared. * No super principled reason fro this ordering beyond that it makes the one that was different be like the rest. * Also matches ordering of things like ndarray, et al. Reviewed By: ftynse, nicolasvasilache Differential Revision: https://reviews.llvm.org/D94812 Added: Modified: mlir/examples/python/linalg_matmul.py mlir/lib/Bindings/Python/IRModules.cpp mlir/test/Bindings/Python/ir_types.py Removed: diff --git a/mlir/examples/python/linalg_matmul.py b/mlir/examples/python/linalg_matmul.py index e9be189bfaaf..0bd3c12a0378 100644 --- a/mlir/examples/python/linalg_matmul.py +++ b/mlir/examples/python/linalg_matmul.py @@ -31,9 +31,9 @@ def FuncOp(name: str, func_type: Type) -> Tuple[Operation, Block]: def build_matmul_buffers_func(func_name, m, k, n, dtype): - lhs_type = MemRefType.get(dtype, [m, k]) - rhs_type = MemRefType.get(dtype, [k, n]) - result_type = MemRefType.get(dtype, [m, n]) + lhs_type = MemRefType.get([m, k], dtype) + rhs_type = MemRefType.get([k, n], dtype) + result_type = MemRefType.get([m, n], dtype) # TODO: There should be a one-liner for this. func_type = FunctionType.get([lhs_type, rhs_type, result_type], []) _, entry = FuncOp(func_name, func_type) @@ -49,8 +49,6 @@ def build_matmul_buffers_func(func_name, m, k, n, dtype): def build_matmul_tensors_func(func_name, m, k, n, dtype): - # TODO: MemRefType and TensorTypes should not have inverted dtype/shapes - # from each other. lhs_type = RankedTensorType.get([m, k], dtype) rhs_type = RankedTensorType.get([k, n], dtype) result_type = RankedTensorType.get([m, n], dtype) diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index 63bdd0c7a184..3c9f79e2a17a 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -2832,7 +2832,7 @@ class PyMemRefType : public PyConcreteType { static void bindDerived(ClassTy &c) { c.def_static( "get", - [](PyType &elementType, std::vector shape, + [](std::vector shape, PyType &elementType, std::vector layout, unsigned memorySpace, DefaultingPyLocation loc) { SmallVector maps; @@ -2856,7 +2856,7 @@ class PyMemRefType : public PyConcreteType { } return PyMemRefType(elementType.getContext(), t); }, - py::arg("element_type"), py::arg("shape"), + py::arg("shape"), py::arg("element_type"), py::arg("layout") = py::list(), py::arg("memory_space") = 0, py::arg("loc") = py::none(), "Create a memref type") .def_property_readonly("layout", &PyMemRefType::getLayout, diff --git a/mlir/test/Bindings/Python/ir_types.py b/mlir/test/Bindings/Python/ir_types.py index 64b684ee99e9..7402c644a1c1 100644 --- a/mlir/test/Bindings/Python/ir_types.py +++ b/mlir/test/Bindings/Python/ir_types.py @@ -326,7 +326,7 @@ def testMemRefType(): f32 = F32Type.get() shape = [2, 3] loc = Location.unknown() -memref = MemRefType.get(f32, shape, memory_space=2) +memref = MemRefType.get(shape, f32, memory_space=2) # CHECK: memref type: memref<2x3xf32, 2> print("memref type:", memref) # CHECK: number of affine layout maps: 0 @@ -335,7 +335,7 @@ def testMemRefType(): print("memory space:", memref.memory_space) layout = AffineMap.get_permutation([1, 0]) -memref_layout = MemRefType.get(f32, shape, [layout]) +memref_layout = MemRefType.get(shape, f32, [layout]) # CHECK: memref type: memref<2x3xf32, affine_map<(d0, d1) -> (d1, d0)>> print("memref type:", memref_layout) assert len(memref_layout.layout) == 1 @@ -346,7 +346,7 @@ def testMemRefType(): none = NoneType.get() try: - memref_invalid = MemRefType.get(none, shape) + memref_invalid = MemRefType.get(shape, none) except ValueError as e: # CHECK: invalid 'Type(none)' and expected floating point, integer, vector # CHECK: or complex type. ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] df7ddee - [mlir][python] Add FlatSymbolRef attribute.
Author: Stella Laurenzo Date: 2020-12-29T12:24:28-08:00 New Revision: df7ddeea668af7b25ee01f282fd8e6b388155103 URL: https://github.com/llvm/llvm-project/commit/df7ddeea668af7b25ee01f282fd8e6b388155103 DIFF: https://github.com/llvm/llvm-project/commit/df7ddeea668af7b25ee01f282fd8e6b388155103.diff LOG: [mlir][python] Add FlatSymbolRef attribute. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D93909 Added: Modified: mlir/lib/Bindings/Python/IRModules.cpp mlir/test/Bindings/Python/ir_attributes.py Removed: diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index 8a77d60741b4..86d6f8206155 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -1643,6 +1643,33 @@ class PyBoolAttribute : public PyConcreteAttribute { } }; +class PyFlatSymbolRefAttribute +: public PyConcreteAttribute { +public: + static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAFlatSymbolRef; + static constexpr const char *pyClassName = "FlatSymbolRefAttr"; + using PyConcreteAttribute::PyConcreteAttribute; + + static void bindDerived(ClassTy &c) { +c.def_static( +"get", +[](std::string value, DefaultingPyMlirContext context) { + MlirAttribute attr = + mlirFlatSymbolRefAttrGet(context->get(), toMlirStringRef(value)); + return PyFlatSymbolRefAttribute(context->getRef(), attr); +}, +py::arg("value"), py::arg("context") = py::none(), +"Gets a uniqued FlatSymbolRef attribute"); +c.def_property_readonly( +"value", +[](PyFlatSymbolRefAttribute &self) { + MlirStringRef stringRef = mlirFlatSymbolRefAttrGetValue(self); + return py::str(stringRef.data, stringRef.length); +}, +"Returns the value of the FlatSymbolRef attribute as a string"); + } +}; + class PyStringAttribute : public PyConcreteAttribute { public: static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAString; @@ -3229,6 +3256,7 @@ void mlir::python::populateIRSubmodule(py::module &m) { PyArrayAttribute::PyArrayAttributeIterator::bind(m); PyIntegerAttribute::bind(m); PyBoolAttribute::bind(m); + PyFlatSymbolRefAttribute::bind(m); PyStringAttribute::bind(m); PyDenseElementsAttribute::bind(m); PyDenseIntElementsAttribute::bind(m); diff --git a/mlir/test/Bindings/Python/ir_attributes.py b/mlir/test/Bindings/Python/ir_attributes.py index 84f313912547..ce85dc3cf87a 100644 --- a/mlir/test/Bindings/Python/ir_attributes.py +++ b/mlir/test/Bindings/Python/ir_attributes.py @@ -165,6 +165,20 @@ def testBoolAttr(): run(testBoolAttr) +# CHECK-LABEL: TEST: testFlatSymbolRefAttr +def testFlatSymbolRefAttr(): + with Context() as ctx: +sattr = FlatSymbolRefAttr(Attribute.parse('@symbol')) +# CHECK: symattr value: symbol +print("symattr value:", sattr.value) + +# Test factory methods. +# CHECK: default_get: @foobar +print("default_get:", FlatSymbolRefAttr.get("foobar")) + +run(testFlatSymbolRefAttr) + + # CHECK-LABEL: TEST: testStringAttr def testStringAttr(): with Context() as ctx: ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] f5665a2 - [mlir][python] Add Operation.verify().
Author: Stella Laurenzo Date: 2020-12-29T14:10:31-08:00 New Revision: f5665a24862163e8783ccf3fd2d2cab62d539e93 URL: https://github.com/llvm/llvm-project/commit/f5665a24862163e8783ccf3fd2d2cab62d539e93 DIFF: https://github.com/llvm/llvm-project/commit/f5665a24862163e8783ccf3fd2d2cab62d539e93.diff LOG: [mlir][python] Add Operation.verify(). Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D93913 Added: Modified: mlir/lib/Bindings/Python/IRModules.cpp mlir/test/Bindings/Python/ir_operation.py Removed: diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index 86d6f8206155..cd58f291d2ec 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -3025,7 +3025,14 @@ void mlir::python::populateIRSubmodule(py::module &m) { py::arg("enable_debug_info") = false, py::arg("pretty_debug_info") = false, py::arg("print_generic_op_form") = false, - py::arg("use_local_scope") = false, kOperationGetAsmDocstring); + py::arg("use_local_scope") = false, kOperationGetAsmDocstring) + .def( + "verify", + [](PyOperationBase &self) { +return mlirOperationVerify(self.getOperation()); + }, + "Verify the operation and return true if it passes, false if it " + "fails."); py::class_(m, "Operation") .def_static("create", &PyOperation::create, py::arg("name"), diff --git a/mlir/test/Bindings/Python/ir_operation.py b/mlir/test/Bindings/Python/ir_operation.py index 1f6df8626a0a..1aa365a1f35d 100644 --- a/mlir/test/Bindings/Python/ir_operation.py +++ b/mlir/test/Bindings/Python/ir_operation.py @@ -31,6 +31,10 @@ def testTraverseOpRegionBlockIterators(): # CHECK: MODULE REGIONS=1 BLOCKS=1 print(f"MODULE REGIONS={len(regions)} BLOCKS={len(blocks)}") + # Should verify. + # CHECK: .verify = True + print(f".verify = {module.operation.verify()}") + # Get the regions and blocks from the default collections. default_regions = list(op) default_blocks = list(default_regions[0]) @@ -546,10 +550,12 @@ def testPrintInvalidOperation(): # This block does not have a terminator, it may crash the custom printer. # Verify that we fallback to the generic printer for safety. block = module.regions[0].blocks.append() -print(module) # CHECK: // Verification failed, printing generic form # CHECK: "module"() ( { # CHECK: }) : () -> () +print(module) +# CHECK: .verify = False +print(f".verify = {module.operation.verify()}") run(testPrintInvalidOperation) ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 14056c8 - [mlir][Python] Add an Operation.name property
Author: Siddharth Krishna Date: 2020-12-29T14:14:32-08:00 New Revision: 14056c88d668fe396eaa59439ddf56f59dd188ec URL: https://github.com/llvm/llvm-project/commit/14056c88d668fe396eaa59439ddf56f59dd188ec DIFF: https://github.com/llvm/llvm-project/commit/14056c88d668fe396eaa59439ddf56f59dd188ec.diff LOG: [mlir][Python] Add an Operation.name property Reviewed By: stellaraccident, mehdi_amini Differential Revision: https://reviews.llvm.org/D93474 Added: Modified: mlir/lib/Bindings/Python/IRModules.cpp mlir/test/Bindings/Python/ir_operation.py Removed: diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index cd58f291d2ec..8fe63f3d1a40 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -3042,6 +3042,13 @@ void mlir::python::populateIRSubmodule(py::module &m) { py::arg("successors") = py::none(), py::arg("regions") = 0, py::arg("loc") = py::none(), py::arg("ip") = py::none(), kOperationCreateDocstring) + .def_property_readonly("name", + [](PyOperation &self) { + MlirOperation operation = self.get(); + MlirStringRef name = mlirIdentifierStr( + mlirOperationGetName(operation)); + return py::str(name.data, name.length); + }) .def_property_readonly( "context", [](PyOperation &self) { return self.getContext().getObject(); }, diff --git a/mlir/test/Bindings/Python/ir_operation.py b/mlir/test/Bindings/Python/ir_operation.py index 1aa365a1f35d..ba54e83f65e8 100644 --- a/mlir/test/Bindings/Python/ir_operation.py +++ b/mlir/test/Bindings/Python/ir_operation.py @@ -584,3 +584,22 @@ def testCreateWithInvalidAttributes(): # CHECK: Found an invalid (`None`?) attribute value for the key "some_key" when attempting to create the operation "module" print(e) run(testCreateWithInvalidAttributes) + + +# CHECK-LABEL: TEST: testOperationName +def testOperationName(): + ctx = Context() + ctx.allow_unregistered_dialects = True + module = Module.parse(r""" +%0 = "custom.op1"() : () -> f32 +%1 = "custom.op2"() : () -> i32 +%2 = "custom.op1"() : () -> f32 + """, ctx) + + # CHECK: custom.op1 + # CHECK: custom.op2 + # CHECK: custom.op1 + for op in module.body.operations: +print(op.operation.name) + +run(testOperationName) ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 8a1f1a1 - [mlir][python] Aggressively avoid name collisions in generated python ODS code.
Author: Stella Laurenzo Date: 2020-12-29T17:43:04-08:00 New Revision: 8a1f1a100cce6ed9b52aedbbf03da887833508be URL: https://github.com/llvm/llvm-project/commit/8a1f1a100cce6ed9b52aedbbf03da887833508be DIFF: https://github.com/llvm/llvm-project/commit/8a1f1a100cce6ed9b52aedbbf03da887833508be.diff LOG: [mlir][python] Aggressively avoid name collisions in generated python ODS code. * When porting npcomp to use these bindings, I ran into enough patterns of collisions that I decided to be somewhat draconian about not polluting the namespace. * With these changes all of the npcomp dialects generate and pass what tests we have. Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D93920 Added: Modified: mlir/include/mlir/Bindings/Python/Attributes.td mlir/test/mlir-tblgen/op-python-bindings.td mlir/tools/mlir-tblgen/OpPythonBindingGen.cpp Removed: diff --git a/mlir/include/mlir/Bindings/Python/Attributes.td b/mlir/include/mlir/Bindings/Python/Attributes.td index 4fe746d2a737..f9a7fa703f50 100644 --- a/mlir/include/mlir/Bindings/Python/Attributes.td +++ b/mlir/include/mlir/Bindings/Python/Attributes.td @@ -22,13 +22,13 @@ class PythonAttr { } // Mappings between supported builtin attribtues and Python types. -def : PythonAttr<"::mlir::Attribute", "_ir.Attribute">; -def : PythonAttr<"::mlir::BoolAttr", "_ir.BoolAttr">; -def : PythonAttr<"::mlir::IntegerAttr", "_ir.IntegerAttr">; -def : PythonAttr<"::mlir::FloatAttr", "_ir.FloatAttr">; -def : PythonAttr<"::mlir::StringAttr", "_ir.StringAttr">; -def : PythonAttr<"::mlir::DenseElementsAttr", "_ir.DenseElementsAttr">; -def : PythonAttr<"::mlir::DenseIntElementsAttr", "_ir.DenseIntElementsAttr">; -def : PythonAttr<"::mlir::DenseFPElementsAttr", "_ir.DenseFPElementsAttr">; +def : PythonAttr<"::mlir::Attribute", "_ods_ir.Attribute">; +def : PythonAttr<"::mlir::BoolAttr", "_ods_ir.BoolAttr">; +def : PythonAttr<"::mlir::IntegerAttr", "_ods_ir.IntegerAttr">; +def : PythonAttr<"::mlir::FloatAttr", "_ods_ir.FloatAttr">; +def : PythonAttr<"::mlir::StringAttr", "_ods_ir.StringAttr">; +def : PythonAttr<"::mlir::DenseElementsAttr", "_ods_ir.DenseElementsAttr">; +def : PythonAttr<"::mlir::DenseIntElementsAttr", "_ods_ir.DenseIntElementsAttr">; +def : PythonAttr<"::mlir::DenseFPElementsAttr", "_ods_ir.DenseFPElementsAttr">; #endif diff --git a/mlir/test/mlir-tblgen/op-python-bindings.td b/mlir/test/mlir-tblgen/op-python-bindings.td index ef8b20fa2ccc..722cf9fb7e40 100644 --- a/mlir/test/mlir-tblgen/op-python-bindings.td +++ b/mlir/test/mlir-tblgen/op-python-bindings.td @@ -3,8 +3,8 @@ include "mlir/IR/OpBase.td" include "mlir/Bindings/Python/Attributes.td" -// CHECK: @_cext.register_dialect -// CHECK: class _Dialect(_ir.Dialect): +// CHECK: @_ods_cext.register_dialect +// CHECK: class _Dialect(_ods_ir.Dialect): // CHECK: DIALECT_NAMESPACE = "test" // CHECK: pass def Test_Dialect : Dialect { @@ -14,8 +14,8 @@ def Test_Dialect : Dialect { class TestOp traits = []> : Op; -// CHECK: @_cext.register_operation(_Dialect) -// CHECK: class AttrSizedOperandsOp(_ir.OpView): +// CHECK: @_ods_cext.register_operation(_Dialect) +// CHECK: class AttrSizedOperandsOp(_ods_ir.OpView): // CHECK-LABEL: OPERATION_NAME = "test.attr_sized_operands" def AttrSizedOperandsOp : TestOp<"attr_sized_operands", [AttrSizedOperandSegments]> { @@ -23,36 +23,36 @@ def AttrSizedOperandsOp : TestOp<"attr_sized_operands", // CHECK: operands = [] // CHECK: results = [] // CHECK: attributes = {} - // CHECK: operand_segment_sizes = array.array('L') + // CHECK: operand_segment_sizes_ods = _ods_array.array('L') // CHECK: operands += [*variadic1] - // CHECK: operand_segment_sizes.append(len(variadic1)) + // CHECK: operand_segment_sizes_ods.append(len(variadic1)) // CHECK: operands.append(non_variadic) - // CHECK: operand_segment_sizes.append(1) + // CHECK: operand_segment_sizes_ods.append(1) // CHECK: if variadic2 is not None: operands.append(variadic2) - // CHECK: operand_segment_sizes.append(0 if variadic2 is None else 1) - // CHECK: attributes["operand_segment_sizes"] = _ir.DenseElementsAttr.get(operand_segment_sizes, - // CHECK: context=_get_default_loc_context(loc)) - // CHECK: super().__init__(_ir.Operation.create( + // CHECK: operand_segment_sizes_ods.append(0 if variadic2 is None else 1) + // CHECK: attributes["operand_segment_sizes"] = _ods_ir.DenseElementsAttr.get(operand_segment_sizes_ods, + // CHECK: context=_ods_get_default_loc_context(loc)) + // CHECK: super().__init__(_ods_ir.Operation.create( // CHECK: "test.attr_sized_operands", attributes=attributes, operands=operands, results=results, // CHECK: loc=loc, ip=ip)) // CHECK: @property // CHECK: def variadic1(self): - // CHECK: operand_range = _segme
[llvm-branch-commits] [mlir] 11f41cd - [mlir][python] Install generated dialect sources.
Author: Stella Laurenzo Date: 2020-12-29T20:15:07-08:00 New Revision: 11f41cd4451554d6ad6065dc7cd6c9349159c567 URL: https://github.com/llvm/llvm-project/commit/11f41cd4451554d6ad6065dc7cd6c9349159c567 DIFF: https://github.com/llvm/llvm-project/commit/11f41cd4451554d6ad6065dc7cd6c9349159c567.diff LOG: [mlir][python] Install generated dialect sources. Differential Revision: https://reviews.llvm.org/D93928 Added: Modified: mlir/lib/Bindings/Python/CMakeLists.txt Removed: diff --git a/mlir/lib/Bindings/Python/CMakeLists.txt b/mlir/lib/Bindings/Python/CMakeLists.txt index 0f51ce54ed09..83e978a6e046 100644 --- a/mlir/lib/Bindings/Python/CMakeLists.txt +++ b/mlir/lib/Bindings/Python/CMakeLists.txt @@ -71,4 +71,23 @@ if (NOT LLVM_ENABLE_IDE) COMPONENT MLIRBindingsPythonSources) endif() +# Dialect sources are generated. Install separately. +# Note that __pycache__ directories may have been left by tests and other +# executions. And __init__.py is handled as a regular source file. +install( + DIRECTORY ${PROJECT_BINARY_DIR}/python/mlir/dialects + DESTINATION python/mlir + COMPONENT MLIRBindingsPythonDialects + FILES_MATCHING PATTERN "*.py" + PATTERN "__pycache__" EXCLUDE + PATTERN "__init__.py" EXCLUDE +) + +if (NOT LLVM_ENABLE_IDE) + add_llvm_install_targets( +install-MLIRBindingsPythonDialects +DEPENDS MLIRBindingsPythonSources +COMPONENT MLIRBindingsPythonDialects) +endif() + add_subdirectory(Transforms) ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 42c57dc - [mlir][python] Tweaks to make python extensions packagable/distributable.
Author: Stella Laurenzo Date: 2020-12-30T23:35:46-08:00 New Revision: 42c57dcc35ea9d6a09469c61473b17c95edcaa2e URL: https://github.com/llvm/llvm-project/commit/42c57dcc35ea9d6a09469c61473b17c95edcaa2e DIFF: https://github.com/llvm/llvm-project/commit/42c57dcc35ea9d6a09469c61473b17c95edcaa2e.diff LOG: [mlir][python] Tweaks to make python extensions packagable/distributable. * Works in tandem with prototype packaging scripts here: https://github.com/stellaraccident/mlir-py-release * The `mlir` top-level now differentiates between in-tree builds where all packages are co-located and distribution mode where all native components are under a top-level `_mlir_libs` package. * Also fixes the generated dialect python installation again. Hopefully the last tweak. * With this, I am able to install and generate archives with the above setup script on Linux. Archive size=31M with just host codegen and headers/shared-libraries. Will need more linker tweaks when wiring up the next dependent project. Differential Revision: https://reviews.llvm.org/D93936 Added: Modified: mlir/lib/Bindings/Python/CMakeLists.txt mlir/lib/Bindings/Python/mlir/__init__.py mlir/lib/Bindings/Python/mlir/transforms/__init__.py Removed: diff --git a/mlir/lib/Bindings/Python/CMakeLists.txt b/mlir/lib/Bindings/Python/CMakeLists.txt index 83e978a6e046..0c34f5b55415 100644 --- a/mlir/lib/Bindings/Python/CMakeLists.txt +++ b/mlir/lib/Bindings/Python/CMakeLists.txt @@ -1,15 +1,6 @@ include(AddMLIRPythonExtension) add_custom_target(MLIRBindingsPythonExtension) - -# Generate dialect-specific bindings. - - -add_mlir_dialect_python_bindings(MLIRBindingsPythonStandardOps - StandardOps.td - std) -add_dependencies(MLIRBindingsPythonExtension MLIRBindingsPythonStandardOps) - # Copy python source tree. @@ -40,6 +31,15 @@ foreach(PY_SRC_FILE ${PY_SRC_FILES}) ) endforeach() + +# Generate dialect-specific bindings. + + +add_mlir_dialect_python_bindings(MLIRBindingsPythonStandardOps + StandardOps.td + std) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonStandardOps) + # Build core python extension diff --git a/mlir/lib/Bindings/Python/mlir/__init__.py b/mlir/lib/Bindings/Python/mlir/__init__.py index 8e027f64bdb6..5ae8151e18f1 100644 --- a/mlir/lib/Bindings/Python/mlir/__init__.py +++ b/mlir/lib/Bindings/Python/mlir/__init__.py @@ -13,18 +13,35 @@ "passmanager", ] -# The _dlloader takes care of platform specific setup before we try to -# load a shared library. -from . import _dlloader -_dlloader.preload_dependency("MLIRPublicAPI") +# Packaged installs have a top-level _mlir_libs package with symbols: +# load_extension(name): Loads a named extension module +# preload_dependency(public_name): Loads a shared-library/DLL into the +# namespace. TODO: Remove this in favor of a more robust mechanism. +# Conditionally switch based on whether we are in a package context. +try: + import _mlir_libs +except ModuleNotFoundError: + # Assume that we are in-tree. + # The _dlloader takes care of platform specific setup before we try to + # load a shared library. + from ._dlloader import preload_dependency as _preload_dependency + def _load_extension(name): +import importlib +return importlib.import_module(name) # i.e. '_mlir' at the top level +else: + # Packaged distribution. + _load_extension = _mlir_libs.load_extension + _preload_dependency = _mlir_libs.preload_dependency + +_preload_dependency("MLIRPublicAPI") # Expose the corresponding C-Extension module with a well-known name at this # top-level module. This allows relative imports like the following to # function: # from .. import _cext # This reduces coupling, allowing embedding of the python sources into another # project that can just vary based on this top-level loader module. -import _mlir as _cext +_cext = _load_extension("_mlir") def _reexport_cext(cext_module_name, target_module_name): """Re-exports a named sub-module of the C-Extension into another module. diff --git a/mlir/lib/Bindings/Python/mlir/transforms/__init__.py b/mlir/lib/Bindings/Python/mlir/transforms/__init__.py index d6172521295a..1155c6392eb8 100644 --- a/mlir/lib/Bindings/Python/mlir/transforms/__init__.
[llvm-branch-commits] [mlir] a16c00a - [mlir][python] Fix python extension building on windows.
Author: Stella Laurenzo Date: 2020-12-31T00:11:39-08:00 New Revision: a16c00a7033df6863f3ecd77a9809790f8db286b URL: https://github.com/llvm/llvm-project/commit/a16c00a7033df6863f3ecd77a9809790f8db286b DIFF: https://github.com/llvm/llvm-project/commit/a16c00a7033df6863f3ecd77a9809790f8db286b.diff LOG: [mlir][python] Fix python extension building on windows. Added: Modified: mlir/cmake/modules/AddMLIRPythonExtension.cmake Removed: diff --git a/mlir/cmake/modules/AddMLIRPythonExtension.cmake b/mlir/cmake/modules/AddMLIRPythonExtension.cmake index eaba5214b5a8..290b4a23aa31 100644 --- a/mlir/cmake/modules/AddMLIRPythonExtension.cmake +++ b/mlir/cmake/modules/AddMLIRPythonExtension.cmake @@ -44,6 +44,10 @@ function(add_mlir_python_extension libname extname) "${pybind11_INCLUDE_DIR}" ) + target_link_directories(${libname} PRIVATE +"${Python3_LIBRARY_DIRS}" + ) + # The extension itself must be compiled with RTTI and exceptions enabled. # Also, some warning classes triggered by pybind11 are disabled. target_compile_options(${libname} PRIVATE ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 53c866c - Enable python bindings for tensor, shape and linalg dialects.
Author: Stella Laurenzo Date: 2021-01-11T12:35:49-08:00 New Revision: 53c866c286a7ca52bd09c7661d4c532ce5c0def8 URL: https://github.com/llvm/llvm-project/commit/53c866c286a7ca52bd09c7661d4c532ce5c0def8 DIFF: https://github.com/llvm/llvm-project/commit/53c866c286a7ca52bd09c7661d4c532ce5c0def8.diff LOG: Enable python bindings for tensor, shape and linalg dialects. * We've got significant missing features in order to use most of these effectively (i.e. custom builders, region-based builders). * We presently also lack a mechanism for actually registering these dialects but they can be use with contexts that allow unregistered dialects for further prototyping. Differential Revision: https://reviews.llvm.org/D94368 Added: mlir/lib/Bindings/Python/LinalgOps.td mlir/lib/Bindings/Python/ShapeOps.td mlir/lib/Bindings/Python/TensorOps.td Modified: mlir/cmake/modules/AddMLIRPythonExtension.cmake mlir/lib/Bindings/Python/CMakeLists.txt mlir/test/Bindings/Python/CMakeLists.txt Removed: diff --git a/mlir/cmake/modules/AddMLIRPythonExtension.cmake b/mlir/cmake/modules/AddMLIRPythonExtension.cmake index 290b4a23aa315..dbbe71e22b132 100644 --- a/mlir/cmake/modules/AddMLIRPythonExtension.cmake +++ b/mlir/cmake/modules/AddMLIRPythonExtension.cmake @@ -136,17 +136,27 @@ function(add_mlir_python_extension libname extname) endfunction() -function(add_mlir_dialect_python_bindings tblgen_target filename dialectname) - set(LLVM_TARGET_DEFINITIONS ${filename}) - mlir_tablegen("${dialectname}.py" -gen-python-op-bindings --bind-dialect=${dialectname}) - add_public_tablegen_target(${tblgen_target}) +function(add_mlir_dialect_python_bindings tblgen_target) + cmake_parse_arguments(ARG +"" +"TD_FILE;DIALECT_NAME" +"DEPENDS" +${ARGN}) + + set(LLVM_TARGET_DEFINITIONS ${ARG_TD_FILE}) + mlir_tablegen("${ARG_DIALECT_NAME}.py" -gen-python-op-bindings +-bind-dialect=${ARG_DIALECT_NAME}) + add_public_tablegen_target( +${tblgen_target}) + if(ARG_DEPENDS) +add_dependencies(${tblgen_target} ${ARG_DEPENDS}) + endif() add_custom_command( TARGET ${tblgen_target} POST_BUILD -COMMENT "Copying generated python source \"dialects/${dialectname}.py\"" +COMMENT "Copying generated python source \"dialects/${ARG_DIALECT_NAME}.py\"" COMMAND "${CMAKE_COMMAND}" -E copy_if_ diff erent - "${CMAKE_CURRENT_BINARY_DIR}/${dialectname}.py" - "${PROJECT_BINARY_DIR}/python/mlir/dialects/${dialectname}.py") + "${CMAKE_CURRENT_BINARY_DIR}/${ARG_DIALECT_NAME}.py" + "${PROJECT_BINARY_DIR}/python/mlir/dialects/${ARG_DIALECT_NAME}.py") endfunction() diff --git a/mlir/lib/Bindings/Python/CMakeLists.txt b/mlir/lib/Bindings/Python/CMakeLists.txt index 0c34f5b55415c..8273489137448 100644 --- a/mlir/lib/Bindings/Python/CMakeLists.txt +++ b/mlir/lib/Bindings/Python/CMakeLists.txt @@ -35,11 +35,27 @@ endforeach() # Generate dialect-specific bindings. +add_mlir_dialect_python_bindings(MLIRBindingsPythonLinalgOps + TD_FILE LinalgOps.td + DIALECT_NAME linalg + DEPENDS LinalgOdsGen) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonLinalgOps) + +add_mlir_dialect_python_bindings(MLIRBindingsPythonShapeOps + TD_FILE ShapeOps.td + DIALECT_NAME shape) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonShapeOps) + add_mlir_dialect_python_bindings(MLIRBindingsPythonStandardOps - StandardOps.td - std) + TD_FILE StandardOps.td + DIALECT_NAME std) add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonStandardOps) +add_mlir_dialect_python_bindings(MLIRBindingsPythonTensorOps + TD_FILE TensorOps.td + DIALECT_NAME tensor) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonTensorOps) + # Build core python extension diff --git a/mlir/lib/Bindings/Python/LinalgOps.td b/mlir/lib/Bindings/Python/LinalgOps.td new file mode 100644 index 0..7650e954d59ee --- /dev/null +++ b/mlir/lib/Bindings/Python/LinalgOps.td @@ -0,0 +1,16 @@ +//===-- LinalgOps.td - Entry point for linalg bind -*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef PYTHON_BINDINGS_LINALG_OPS +#define PYTHON_BINDINGS_LINALG_OPS + +include "mlir/Bindings/Python/Attributes.td" +include "mlir/Dialect/Linalg/IR/LinalgOps.td" +include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.td" + +#endif diff --git a/ml
[llvm-branch-commits] [mlir] cceb1bf - [mlir][CAPI] Introduce standard source layout for mlir-c dialect registration.
Author: Stella Laurenzo Date: 2021-01-11T12:35:49-08:00 New Revision: cceb1bfcbbc4ee2e9cc56b76a4acc4cd52968791 URL: https://github.com/llvm/llvm-project/commit/cceb1bfcbbc4ee2e9cc56b76a4acc4cd52968791 DIFF: https://github.com/llvm/llvm-project/commit/cceb1bfcbbc4ee2e9cc56b76a4acc4cd52968791.diff LOG: [mlir][CAPI] Introduce standard source layout for mlir-c dialect registration. * Registers a small set of sample dialects. * NFC with respect to existing C-API symbols but some headers have been moved down a level to the Dialect/ sub-directory. * Adds an additional entry point per dialect that is needed for dynamic discovery/loading. * See discussion: https://llvm.discourse.group/t/dialects-and-the-c-api/2306/16 Differential Revision: https://reviews.llvm.org/D94370 Added: mlir/include/mlir-c/Dialect/Linalg.h mlir/include/mlir-c/Dialect/SCF.h mlir/include/mlir-c/Dialect/Shape.h mlir/include/mlir-c/Dialect/Standard.h mlir/include/mlir-c/Dialect/Tensor.h mlir/include/mlir/CAPI/Registration.h mlir/lib/CAPI/Dialect/CMakeLists.txt mlir/lib/CAPI/Dialect/Linalg.cpp mlir/lib/CAPI/Dialect/SCF.cpp mlir/lib/CAPI/Dialect/Shape.cpp mlir/lib/CAPI/Dialect/Standard.cpp mlir/lib/CAPI/Dialect/Tensor.cpp Modified: mlir/include/mlir-c/Registration.h mlir/lib/CAPI/CMakeLists.txt mlir/test/CAPI/ir.c Removed: mlir/include/mlir-c/StandardDialect.h mlir/lib/CAPI/Standard/CMakeLists.txt mlir/lib/CAPI/Standard/StandardDialect.cpp diff --git a/mlir/include/mlir-c/Dialect/Linalg.h b/mlir/include/mlir-c/Dialect/Linalg.h new file mode 100644 index 0..56258ac19af45 --- /dev/null +++ b/mlir/include/mlir-c/Dialect/Linalg.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/Linalg.h - C API for Linalg dialect *- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef MLIR_C_DIALECT_LINALG_H +#define MLIR_C_DIALECT_LINALG_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Linalg, linalg); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_LINALG_H diff --git a/mlir/include/mlir-c/Dialect/SCF.h b/mlir/include/mlir-c/Dialect/SCF.h new file mode 100644 index 0..c1b25677969bf --- /dev/null +++ b/mlir/include/mlir-c/Dialect/SCF.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/SCF.h - C API for SCF dialect --*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef MLIR_C_DIALECT_SCF_H +#define MLIR_C_DIALECT_SCF_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(SCF, scf); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_SCF_H diff --git a/mlir/include/mlir-c/Dialect/Shape.h b/mlir/include/mlir-c/Dialect/Shape.h new file mode 100644 index 0..f64da801610b2 --- /dev/null +++ b/mlir/include/mlir-c/Dialect/Shape.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/Shape.h - C API for Shape dialect --*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef MLIR_C_DIALECT_SHAPE_H +#define MLIR_C_DIALECT_SHAPE_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Shape, shape); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_SHAPE_H diff --git a/mlir/include/mlir-c/StandardDialect.h b/mlir/include/mlir-c/Dialect/Standard.h similarity index 52% rename from mlir/include/mlir-c/StandardDialect.h rename to mlir/include/mlir-c/Dialect/Standard.h index 191872103104e..200962177cb95 100644 --- a/mlir/include/mlir-c/StandardDialect.h +++ b/mlir/include/mlir-c/Dialect/Standard.h @@ -1,4 +1,4 @@ -//===-- mlir-c/StandardDialect.h - C API for Standard dialect -*- C -*-===// +//===-- mlir-c/Dialect/Standard.h - C API for Standard dialect *- C -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM // Exceptions. @@ -15,29 +15,19 @@ // //===--===// -#ifndef MLIR_C_STANDARDDIALECT_H -#define MLIR_C_STANDARDDIALECT_H +#i
[llvm-branch-commits] [mlir] 76753a5 - Add FunctionType to MLIR C and Python bindings.
Author: Stella Laurenzo Date: 2020-09-28T09:56:48-07:00 New Revision: 76753a597b5d9bf4addf19399ae30c4b3870a4a6 URL: https://github.com/llvm/llvm-project/commit/76753a597b5d9bf4addf19399ae30c4b3870a4a6 DIFF: https://github.com/llvm/llvm-project/commit/76753a597b5d9bf4addf19399ae30c4b3870a4a6.diff LOG: Add FunctionType to MLIR C and Python bindings. Differential Revision: https://reviews.llvm.org/D88416 Added: Modified: mlir/include/mlir-c/StandardTypes.h mlir/lib/Bindings/Python/IRModules.cpp mlir/lib/CAPI/IR/StandardTypes.cpp mlir/test/Bindings/Python/ir_types.py mlir/test/CAPI/ir.c Removed: diff --git a/mlir/include/mlir-c/StandardTypes.h b/mlir/include/mlir-c/StandardTypes.h index 4bbcb23b8002e..3b667c9e0a1b0 100644 --- a/mlir/include/mlir-c/StandardTypes.h +++ b/mlir/include/mlir-c/StandardTypes.h @@ -270,6 +270,30 @@ intptr_t mlirTupleTypeGetNumTypes(MlirType type); /** Returns the pos-th type in the tuple type. */ MlirType mlirTupleTypeGetType(MlirType type, intptr_t pos); +/**/ +/* Function type. */ +/**/ + +/** Checks whether the given type is a function type. */ +int mlirTypeIsAFunction(MlirType type); + +/** Creates a function type, mapping a list of input types to result types. */ +MlirType mlirFunctionTypeGet(MlirContext ctx, intptr_t numInputs, + MlirType *inputs, intptr_t numResults, + MlirType *results); + +/** Returns the number of input types. */ +intptr_t mlirFunctionTypeGetNumInputs(MlirType type); + +/** Returns the number of result types. */ +intptr_t mlirFunctionTypeGetNumResults(MlirType type); + +/** Returns the pos-th input type. */ +MlirType mlirFunctionTypeGetInput(MlirType type, intptr_t pos); + +/** Returns the pos-th result type. */ +MlirType mlirFunctionTypeGetResult(MlirType type, intptr_t pos); + #ifdef __cplusplus } #endif diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index 99b00b96b974c..f3bd96856d090 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -1278,6 +1278,56 @@ class PyTupleType : public PyConcreteType { } }; +/// Function type. +class PyFunctionType : public PyConcreteType { +public: + static constexpr IsAFunctionTy isaFunction = mlirTypeIsAFunction; + static constexpr const char *pyClassName = "FunctionType"; + using PyConcreteType::PyConcreteType; + + static void bindDerived(ClassTy &c) { +c.def_static( +"get", +[](PyMlirContext &context, std::vector inputs, + std::vector results) { + SmallVector inputsRaw(inputs.begin(), inputs.end()); + SmallVector resultsRaw(results.begin(), results.end()); + MlirType t = mlirFunctionTypeGet(context.get(), inputsRaw.size(), + inputsRaw.data(), resultsRaw.size(), + resultsRaw.data()); + return PyFunctionType(context.getRef(), t); +}, +py::arg("context"), py::arg("inputs"), py::arg("results"), +"Gets a FunctionType from a list of input and result types"); +c.def_property_readonly( +"inputs", +[](PyFunctionType &self) { + MlirType t = self.type; + auto contextRef = self.getContext(); + py::list types; + for (intptr_t i = 0, e = mlirFunctionTypeGetNumInputs(self.type); + i < e; ++i) { +types.append(PyType(contextRef, mlirFunctionTypeGetInput(t, i))); + } + return types; +}, +"Returns the list of input types in the FunctionType."); +c.def_property_readonly( +"results", +[](PyFunctionType &self) { + MlirType t = self.type; + auto contextRef = self.getContext(); + py::list types; + for (intptr_t i = 0, e = mlirFunctionTypeGetNumResults(self.type); + i < e; ++i) { +types.append(PyType(contextRef, mlirFunctionTypeGetResult(t, i))); + } + return types; +}, +"Returns the list of result types in the FunctionType."); + } +}; + } // namespace //-- @@ -1613,6 +1663,7 @@ void mlir::python::populateIRSubmodule(py::module &m) { PyMemRefType::bind(m); PyUnrankedMemRefType::bind(m); PyTupleType::bind(m); + PyFunctionType::bind(m); // Container bindings. PyBlockIterator::bind(m); diff --git a/mlir/lib/CAPI/IR/StandardTypes.cpp b/mlir/lib/CAPI/IR/StandardTypes.cpp index ddd3a5e93147a..b4e37d38ace31 100644 --- a/mlir/lib/CAPI/IR/StandardTypes.cp
[llvm-branch-commits] [mlir] f4f8a67 - [mlir][Python] Support finding pybind11 from the python environment.
Author: Stella Laurenzo Date: 2020-11-22T12:52:01-08:00 New Revision: f4f8a67aaf13bc66a2b7d55561b14a3724a5e0de URL: https://github.com/llvm/llvm-project/commit/f4f8a67aaf13bc66a2b7d55561b14a3724a5e0de DIFF: https://github.com/llvm/llvm-project/commit/f4f8a67aaf13bc66a2b7d55561b14a3724a5e0de.diff LOG: [mlir][Python] Support finding pybind11 from the python environment. * Makes `pip install pybind11` do the right thing with no further config. * Since we now require a version of pybind11 greater than many LTS OS installs (>=2.6), a more convenient way to get a recent version is preferable. * Also adds the version spec to find_package so it will skip older versions that may be lying around. * Tested the full matrix of old system install, no system install, pip install and no pip install. Differential Revision: https://reviews.llvm.org/D91903 Added: mlir/cmake/modules/MLIRDetectPythonEnv.cmake Modified: mlir/CMakeLists.txt mlir/docs/Bindings/Python.md Removed: diff --git a/mlir/CMakeLists.txt b/mlir/CMakeLists.txt index 09ab67ff73dc..c10a169640ee 100644 --- a/mlir/CMakeLists.txt +++ b/mlir/CMakeLists.txt @@ -78,14 +78,12 @@ set(MLIR_PYTHON_BINDINGS_VERSION_LOCKED 1 CACHE BOOL "Links to specific python libraries, resolving all symbols.") if(MLIR_BINDINGS_PYTHON_ENABLED) + include(MLIRDetectPythonEnv) find_package(Python3 COMPONENTS Interpreter Development REQUIRED) message(STATUS "Found python include dirs: ${Python3_INCLUDE_DIRS}") message(STATUS "Found python libraries: ${Python3_LIBRARIES}") - find_package(pybind11 CONFIG REQUIRED) - # TODO: pybind11 v2.6 switched from pybind11_INCLUDE_DIRS (plural) to - # pybind11_INCLUDE_DIR (singular). A lot has changed in this area since this - # was written and overall python config and pybind11 should be modernized. - set(pybind11_INCLUDE_DIR ${pybind11_INCLUDE_DIR} ${pybind11_INCLUDE_DIRS}) + mlir_detect_pybind11_install() + find_package(pybind11 2.6 CONFIG REQUIRED) message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIR}") message(STATUS "Python prefix = '${PYTHON_MODULE_PREFIX}', " "suffix = '${PYTHON_MODULE_SUFFIX}', " diff --git a/mlir/cmake/modules/MLIRDetectPythonEnv.cmake b/mlir/cmake/modules/MLIRDetectPythonEnv.cmake new file mode 100644 index ..e3572c37f99e --- /dev/null +++ b/mlir/cmake/modules/MLIRDetectPythonEnv.cmake @@ -0,0 +1,26 @@ +# Macros and functions related to detecting details of the Python environment. + +# Detects a pybind11 package installed in the current python environment +# and sets variables to allow it to be found. This allows pybind11 to be +# installed via pip, which typically yields a much more recent version than +# the OS install, which will be available otherwise. +function(mlir_detect_pybind11_install) + if(pybind11_DIR) +message(STATUS "Using explicit pybind11 cmake directory: ${pybind11_DIR} (-Dpybind11_DIR to change)") + else() +message(CHECK_START "Checking for pybind11 in python path...") +execute_process( + COMMAND "${PYTHON_EXECUTABLE}" + -c "import pybind11;print(pybind11.get_cmake_dir(), end='')" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE STATUS + OUTPUT_VARIABLE PACKAGE_DIR + ERROR_QUIET) +if(NOT STATUS EQUAL "0") + message(CHECK_FAIL "not found (install via 'pip install pybind11' or set pybind11_DIR)") + return() +endif() +message(CHECK_PASS "found (${PACKAGE_DIR})") +set(pybind11_DIR "${PACKAGE_DIR}" PARENT_SCOPE) + endif() +endfunction() diff --git a/mlir/docs/Bindings/Python.md b/mlir/docs/Bindings/Python.md index a1626ea4505e..89f2742e2fad 100644 --- a/mlir/docs/Bindings/Python.md +++ b/mlir/docs/Bindings/Python.md @@ -6,9 +6,10 @@ Current status: Under development and not enabled by default ### Pre-requisites -* [`pybind11`](https://github.com/pybind/pybind11) must be installed and able to - be located by CMake. Note: minimum version required: :2.6.0 * A relatively recent Python3 installation +* [`pybind11`](https://github.com/pybind/pybind11) must be installed and able to + be located by CMake (auto-detected if installed via + `python -m pip install pybind11`). Note: minimum version required: :2.6.0. ### CMake variables ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] 2fb5f4a - [mlir][Python] Add additional capsule interop types.
Author: Stella Laurenzo Date: 2020-11-25T19:09:25-08:00 New Revision: 2fb5f4a1cf41af31eaf31ea90cdda7f644794b99 URL: https://github.com/llvm/llvm-project/commit/2fb5f4a1cf41af31eaf31ea90cdda7f644794b99 DIFF: https://github.com/llvm/llvm-project/commit/2fb5f4a1cf41af31eaf31ea90cdda7f644794b99.diff LOG: [mlir][Python] Add additional capsule interop types. Differential Revision: https://reviews.llvm.org/D92144 Added: Modified: mlir/include/mlir-c/Bindings/Python/Interop.h Removed: diff --git a/mlir/include/mlir-c/Bindings/Python/Interop.h b/mlir/include/mlir-c/Bindings/Python/Interop.h index dad51563a324..05519d804e31 100644 --- a/mlir/include/mlir-c/Bindings/Python/Interop.h +++ b/mlir/include/mlir-c/Bindings/Python/Interop.h @@ -26,8 +26,11 @@ #include "mlir-c/IR.h" #include "mlir-c/Pass.h" +#define MLIR_PYTHON_CAPSULE_ATTRIBUTE "mlir.ir.Attribute._CAPIPtr" #define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.Context._CAPIPtr" #define MLIR_PYTHON_CAPSULE_MODULE "mlir.ir.Module._CAPIPtr" +#define MLIR_PYTHON_CAPSULE_OPERATION "mlir.ir.Operation._CAPIPtr" +#define MLIR_PYTHON_CAPSULE_TYPE "mlir.ir.Type._CAPIPtr" #define MLIR_PYTHON_CAPSULE_PASS_MANAGER "mlir.passmanager.PassManager._CAPIPtr" /** Attribute on MLIR Python objects that expose their C-API pointer. @@ -66,6 +69,25 @@ extern "C" { #endif +/** Creates a capsule object encapsulating the raw C-API MlirAttribute. + * The returned capsule does not extend or affect ownership of any Python + * objects that reference the attribute in any way. + */ +static inline PyObject *mlirPythonAttributeToCapsule(MlirAttribute attribute) { + return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(attribute), + MLIR_PYTHON_CAPSULE_ATTRIBUTE, NULL); +} + +/** Extracts an MlirAttribute from a capsule as produced from + * mlirPythonAttributeToCapsule. If the capsule is not of the right type, then + * a null attribute is returned (as checked via mlirAttributeIsNull). In such a + * case, the Python APIs will have already set an error. */ +static inline MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule) { + void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_ATTRIBUTE); + MlirAttribute attr = {ptr}; + return attr; +} + /** Creates a capsule object encapsulating the raw C-API MlirContext. * The returned capsule does not extend or affect ownership of any Python * objects that reference the context in any way. @@ -120,6 +142,43 @@ mlirPythonCapsuleToPassManager(PyObject *capsule) { return pm; } +/** Creates a capsule object encapsulating the raw C-API MlirOperation. + * The returned capsule does not extend or affect ownership of any Python + * objects that reference the operation in any way. + */ +static inline PyObject *mlirPythonOperationToCapsule(MlirOperation operation) { + return PyCapsule_New(operation.ptr, MLIR_PYTHON_CAPSULE_OPERATION, NULL); +} + +/** Extracts an MlirOperations from a capsule as produced from + * mlirPythonOperationToCapsule. If the capsule is not of the right type, then + * a null type is returned (as checked via mlirOperationIsNull). In such a + * case, the Python APIs will have already set an error. */ +static inline MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule) { + void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_OPERATION); + MlirOperation op = {ptr}; + return op; +} + +/** Creates a capsule object encapsulating the raw C-API MlirType. + * The returned capsule does not extend or affect ownership of any Python + * objects that reference the type in any way. + */ +static inline PyObject *mlirPythonTypeToCapsule(MlirType type) { + return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(type), + MLIR_PYTHON_CAPSULE_TYPE, NULL); +} + +/** Extracts an MlirType from a capsule as produced from + * mlirPythonTypeToCapsule. If the capsule is not of the right type, then + * a null type is returned (as checked via mlirTypeIsNull). In such a + * case, the Python APIs will have already set an error. */ +static inline MlirType mlirPythonCapsuleToType(PyObject *capsule) { + void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPE); + MlirType type = {ptr}; + return type; +} + #ifdef __cplusplus } #endif ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [mlir] bd2083c - [mlir][Python] Python API cleanups and additions found during code audit.
Author: Stella Laurenzo Date: 2020-11-29T18:09:07-08:00 New Revision: bd2083c2fa7bb8769ca997a0303da54432e08519 URL: https://github.com/llvm/llvm-project/commit/bd2083c2fa7bb8769ca997a0303da54432e08519 DIFF: https://github.com/llvm/llvm-project/commit/bd2083c2fa7bb8769ca997a0303da54432e08519.diff LOG: [mlir][Python] Python API cleanups and additions found during code audit. * Add capsule get/create for Attribute and Type, which already had capsule interop defined. * Add capsule interop and get/create for Location. * Add Location __eq__. * Use get() and implicit cast to go from PyAttribute, PyType, PyLocation to MlirAttribute, MlirType, MlirLocation (bundled with this change because I didn't want to continue the pattern one more time). Differential Revision: https://reviews.llvm.org/D92283 Added: Modified: mlir/include/mlir-c/Bindings/Python/Interop.h mlir/include/mlir-c/IR.h mlir/lib/Bindings/Python/IRModules.cpp mlir/lib/Bindings/Python/IRModules.h mlir/lib/Bindings/Python/PybindUtils.h mlir/lib/CAPI/IR/IR.cpp mlir/test/Bindings/Python/ir_attributes.py mlir/test/Bindings/Python/ir_location.py mlir/test/Bindings/Python/ir_types.py Removed: diff --git a/mlir/include/mlir-c/Bindings/Python/Interop.h b/mlir/include/mlir-c/Bindings/Python/Interop.h index 05519d804e31..31265edfb550 100644 --- a/mlir/include/mlir-c/Bindings/Python/Interop.h +++ b/mlir/include/mlir-c/Bindings/Python/Interop.h @@ -28,6 +28,7 @@ #define MLIR_PYTHON_CAPSULE_ATTRIBUTE "mlir.ir.Attribute._CAPIPtr" #define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.Context._CAPIPtr" +#define MLIR_PYTHON_CAPSULE_LOCATION "mlir.ir.Location._CAPIPtr" #define MLIR_PYTHON_CAPSULE_MODULE "mlir.ir.Module._CAPIPtr" #define MLIR_PYTHON_CAPSULE_OPERATION "mlir.ir.Operation._CAPIPtr" #define MLIR_PYTHON_CAPSULE_TYPE "mlir.ir.Type._CAPIPtr" @@ -106,6 +107,24 @@ static inline MlirContext mlirPythonCapsuleToContext(PyObject *capsule) { return context; } +/** Creates a capsule object encapsulating the raw C-API MlirLocation. + * The returned capsule does not extend or affect ownership of any Python + * objects that reference the location in any way. */ +static inline PyObject *mlirPythonLocationToCapsule(MlirLocation loc) { + return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(loc), + MLIR_PYTHON_CAPSULE_LOCATION, NULL); +} + +/** Extracts an MlirLocation from a capsule as produced from + * mlirPythonLocationToCapsule. If the capsule is not of the right type, then + * a null module is returned (as checked via mlirLocationIsNull). In such a + * case, the Python APIs will have already set an error. */ +static inline MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule) { + void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_LOCATION); + MlirLocation loc = {ptr}; + return loc; +} + /** Creates a capsule object encapsulating the raw C-API MlirModule. * The returned capsule does not extend or affect ownership of any Python * objects that reference the module in any way. */ diff --git a/mlir/include/mlir-c/IR.h b/mlir/include/mlir-c/IR.h index 902b2b988622..e3bfe76560f1 100644 --- a/mlir/include/mlir-c/IR.h +++ b/mlir/include/mlir-c/IR.h @@ -153,6 +153,14 @@ MLIR_CAPI_EXPORTED MlirLocation mlirLocationUnknownGet(MlirContext context); /// Gets the context that a location was created with. MLIR_CAPI_EXPORTED MlirContext mlirLocationGetContext(MlirLocation location); +/// Checks if the location is null. +static inline int mlirLocationIsNull(MlirLocation location) { + return !location.ptr; +} + +/// Checks if two locations are equal. +MLIR_CAPI_EXPORTED int mlirLocationEqual(MlirLocation l1, MlirLocation l2); + /** Prints a location by sending chunks of the string representation and * forwarding `userData to `callback`. Note that the callback may be called * several times with consecutive chunks of the string. */ diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index e145a58d0d27..d34fe998583f 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -289,7 +289,7 @@ class PyBlockList { llvm::SmallVector argTypes; argTypes.reserve(pyArgTypes.size()); for (auto &pyArg : pyArgTypes) { - argTypes.push_back(pyArg.cast().type); + argTypes.push_back(pyArg.cast()); } MlirBlock block = mlirBlockCreate(argTypes.size(), argTypes.data()); @@ -640,6 +640,18 @@ MlirDialect PyDialects::getDialectForKey(const std::string &key, // PyLocation //-- +py::object PyLocation::getCapsule() { + return py::reinterpret_steal(mlirPythonLocationToCapsule(*this)); +} + +PyLocation PyLocation::createFromCapsule(py::object capsule) { + MlirLocation rawLoc = mlirPythonCapsuleToLocation(capsu
[llvm-branch-commits] [mlir] ba0fe76 - [mlir][Python] Add an Operation.result property.
Author: Stella Laurenzo Date: 2020-11-29T18:09:07-08:00 New Revision: ba0fe76b7eb87f91499931e76317ddd1cb493aa1 URL: https://github.com/llvm/llvm-project/commit/ba0fe76b7eb87f91499931e76317ddd1cb493aa1 DIFF: https://github.com/llvm/llvm-project/commit/ba0fe76b7eb87f91499931e76317ddd1cb493aa1.diff LOG: [mlir][Python] Add an Operation.result property. * If ODS redefines this, it is fine, but I have found this accessor to be universally useful in the old npcomp bindings and I'm closing gaps that will let me switch. Differential Revision: https://reviews.llvm.org/D92287 Added: Modified: mlir/lib/Bindings/Python/IRModules.cpp mlir/lib/Bindings/Python/IRModules.h mlir/test/Bindings/Python/ir_operation.py Removed: diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index d34fe998583f..d270e44debae 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -23,6 +23,8 @@ using namespace mlir; using namespace mlir::python; using llvm::SmallVector; +using llvm::StringRef; +using llvm::Twine; //-- // Docstrings (trivial, non-duplicated docstrings are included inline). @@ -631,7 +633,7 @@ MlirDialect PyDialects::getDialectForKey(const std::string &key, getContext()->get(), {canonKey->data(), canonKey->size()}); if (mlirDialectIsNull(dialect)) { throw SetPyError(attrError ? PyExc_AttributeError : PyExc_IndexError, - llvm::Twine("Dialect '") + key + "' not found"); + Twine("Dialect '") + key + "' not found"); } return dialect; } @@ -793,7 +795,7 @@ PyOperationRef PyOperation::createDetached(PyMlirContextRef contextRef, return created; } -void PyOperation::checkValid() { +void PyOperation::checkValid() const { if (!valid) { throw SetPyError(PyExc_RuntimeError, "the operation has been invalidated"); } @@ -817,7 +819,7 @@ void PyOperationBase::print(py::object fileObject, bool binary, PyFileAccumulator accum(fileObject, binary); py::gil_scoped_release(); - mlirOperationPrintWithFlags(operation.get(), flags, accum.getCallback(), + mlirOperationPrintWithFlags(operation, flags, accum.getCallback(), accum.getUserData()); mlirOpPrintingFlagsDestroy(flags); } @@ -975,7 +977,7 @@ py::object PyOperation::createOpView() { MlirIdentifier ident = mlirOperationGetName(get()); MlirStringRef identStr = mlirIdentifierStr(ident); auto opViewClass = PyGlobals::get().lookupRawOpViewClass( - llvm::StringRef(identStr.data, identStr.length)); + StringRef(identStr.data, identStr.length)); if (opViewClass) return (*opViewClass)(getRef().getObject()); return py::cast(PyOpView(getRef().getObject())); @@ -1044,7 +1046,7 @@ void PyInsertionPoint::insert(PyOperationBase &operationBase) { (*refOperation)->checkValid(); beforeOp = (*refOperation)->get(); } - mlirBlockInsertOwnedOperationBefore(block.get(), beforeOp, operation.get()); + mlirBlockInsertOwnedOperationBefore(block.get(), beforeOp, operation); operation.setAttached(); } @@ -1158,7 +1160,7 @@ class PyConcreteValue : public PyValue { static MlirValue castFrom(PyValue &orig) { if (!DerivedTy::isaFunction(orig.get())) { auto origRepr = py::repr(py::cast(orig)).cast(); - throw SetPyError(PyExc_ValueError, llvm::Twine("Cannot cast value to ") + + throw SetPyError(PyExc_ValueError, Twine("Cannot cast value to ") + DerivedTy::pyClassName + " (from " + origRepr + ")"); } @@ -1416,9 +1418,9 @@ class PyConcreteAttribute : public BaseTy { static MlirAttribute castFrom(PyAttribute &orig) { if (!DerivedTy::isaFunction(orig)) { auto origRepr = py::repr(py::cast(orig)).cast(); - throw SetPyError(PyExc_ValueError, - llvm::Twine("Cannot cast attribute to ") + - DerivedTy::pyClassName + " (from " + origRepr + ")"); + throw SetPyError(PyExc_ValueError, Twine("Cannot cast attribute to ") + + DerivedTy::pyClassName + + " (from " + origRepr + ")"); } return orig; } @@ -1449,7 +1451,7 @@ class PyFloatAttribute : public PyConcreteAttribute { // in C API. if (mlirAttributeIsNull(attr)) { throw SetPyError(PyExc_ValueError, - llvm::Twine("invalid '") + + Twine("invalid '") + py::repr(py::cast(type)).cast() + "' and expected floating point type."); } @@ -1943,7 +1945,7 @@ class PyConcreteType : public
[llvm-branch-commits] [mlir] 62195b7 - [mlir][CAPI] Convert the rest of the API int -> bool.
Author: Stella Laurenzo Date: 2020-11-29T20:36:42-08:00 New Revision: 62195b75481890f3d86422710338a15bfbc57bcf URL: https://github.com/llvm/llvm-project/commit/62195b75481890f3d86422710338a15bfbc57bcf DIFF: https://github.com/llvm/llvm-project/commit/62195b75481890f3d86422710338a15bfbc57bcf.diff LOG: [mlir][CAPI] Convert the rest of the API int -> bool. * Follows on https://reviews.llvm.org/D92193 * I had a mid-air collision with some additional occurrences and then noticed that there were a lot more. Think I got them all. Differential Revision: https://reviews.llvm.org/D92292 Added: Modified: mlir/include/mlir-c/AffineExpr.h mlir/include/mlir-c/AffineMap.h mlir/include/mlir-c/IR.h mlir/include/mlir-c/Pass.h mlir/include/mlir-c/StandardAttributes.h mlir/include/mlir-c/StandardTypes.h mlir/include/mlir-c/Support.h mlir/lib/Bindings/Python/IRModules.cpp mlir/lib/CAPI/IR/AffineExpr.cpp mlir/lib/CAPI/IR/AffineMap.cpp mlir/lib/CAPI/IR/IR.cpp mlir/lib/CAPI/IR/StandardAttributes.cpp mlir/lib/CAPI/IR/StandardTypes.cpp mlir/test/Bindings/Python/ir_attributes.py Removed: diff --git a/mlir/include/mlir-c/AffineExpr.h b/mlir/include/mlir-c/AffineExpr.h index 7ddd0289d8a5..93b8e832b44f 100644 --- a/mlir/include/mlir-c/AffineExpr.h +++ b/mlir/include/mlir-c/AffineExpr.h @@ -57,12 +57,12 @@ MLIR_CAPI_EXPORTED void mlirAffineExprDump(MlirAffineExpr affineExpr); /** Checks whether the given affine expression is made out of only symbols and * constants. */ -MLIR_CAPI_EXPORTED int +MLIR_CAPI_EXPORTED bool mlirAffineExprIsSymbolicOrConstant(MlirAffineExpr affineExpr); /** Checks whether the given affine expression is a pure affine expression, i.e. * mul, floordiv, ceildic, and mod is only allowed w.r.t constants. */ -MLIR_CAPI_EXPORTED int mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr); +MLIR_CAPI_EXPORTED bool mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr); /** Returns the greatest known integral divisor of this affine expression. The * result is always positive. */ @@ -70,13 +70,13 @@ MLIR_CAPI_EXPORTED int64_t mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr affineExpr); /// Checks whether the given affine expression is a multiple of 'factor'. -MLIR_CAPI_EXPORTED int mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr, - int64_t factor); +MLIR_CAPI_EXPORTED bool mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr, + int64_t factor); /** Checks whether the given affine expression involves AffineDimExpr * 'position'. */ -MLIR_CAPI_EXPORTED int mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, - intptr_t position); +MLIR_CAPI_EXPORTED bool mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, + intptr_t position); //===--===// // Affine Dimension Expression. @@ -119,7 +119,7 @@ mlirAffineConstantExprGetValue(MlirAffineExpr affineExpr); //===--===// /// Checks whether the given affine expression is an add expression. -MLIR_CAPI_EXPORTED int mlirAffineExprIsAAdd(MlirAffineExpr affineExpr); +MLIR_CAPI_EXPORTED bool mlirAffineExprIsAAdd(MlirAffineExpr affineExpr); /// Creates an affine add expression with 'lhs' and 'rhs'. MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineAddExprGet(MlirAffineExpr lhs, @@ -130,7 +130,7 @@ MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineAddExprGet(MlirAffineExpr lhs, //===--===// /// Checks whether the given affine expression is an mul expression. -MLIR_CAPI_EXPORTED int mlirAffineExprIsAMul(MlirAffineExpr affineExpr); +MLIR_CAPI_EXPORTED bool mlirAffineExprIsAMul(MlirAffineExpr affineExpr); /// Creates an affine mul expression with 'lhs' and 'rhs'. MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineMulExprGet(MlirAffineExpr lhs, @@ -141,7 +141,7 @@ MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineMulExprGet(MlirAffineExpr lhs, //===--===// /// Checks whether the given affine expression is an mod expression. -MLIR_CAPI_EXPORTED int mlirAffineExprIsAMod(MlirAffineExpr affineExpr); +MLIR_CAPI_EXPORTED bool mlirAffineExprIsAMod(MlirAffineExpr affineExpr); /// Creates an affine mod expression with 'lhs' and 'rhs'. MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineModExprGet(MlirAffineExpr lhs, @@ -152,7 +152,7 @@ MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineModExprGet(MlirAffineExpr lhs, //===--===// /// Checks whether the given affine expr
[llvm-branch-commits] [mlir] bff4e75 - [mlir][quantizer] Add gathering of per-axis statistics in quantizer.
Author: Dmitry Murygin Date: 2020-02-08T15:10:34-08:00 New Revision: bff4e752f3704b8668154cb922ac36792c7fe6aa URL: https://github.com/llvm/llvm-project/commit/bff4e752f3704b8668154cb922ac36792c7fe6aa DIFF: https://github.com/llvm/llvm-project/commit/bff4e752f3704b8668154cb922ac36792c7fe6aa.diff LOG: [mlir][quantizer] Add gathering of per-axis statistics in quantizer. Reviewers: stellaraccident, nicolasvasilache Reviewed By: stellaraccident Subscribers: Joonsoo, merge_guards_bot, denis13 Tags: #llvm Differential Revision: https://reviews.llvm.org/D73556 Added: Modified: mlir/include/mlir/Quantizer/Support/Statistics.h mlir/lib/Quantizer/Support/Statistics.cpp Removed: diff --git a/mlir/include/mlir/Quantizer/Support/Statistics.h b/mlir/include/mlir/Quantizer/Support/Statistics.h index a0d2417cca65..61f241603ff0 100644 --- a/mlir/include/mlir/Quantizer/Support/Statistics.h +++ b/mlir/include/mlir/Quantizer/Support/Statistics.h @@ -27,11 +27,25 @@ struct TensorAxisStatistics { double mean = 0; double variance = 0; + int64_t sampleSizePerAxis = 0; + SmallVector minValuePerAxis; + SmallVector maxValuePerAxis; + SmallVector meanPerAxis; + SmallVector variancePerAxis; + TensorAxisStatistics() {} TensorAxisStatistics(int64_t sampleSize, double minValue, double maxValue, double mean, double variance) : sampleSize(sampleSize), minValue(minValue), maxValue(maxValue), mean(mean), variance(variance) {} + TensorAxisStatistics(int64_t sampleSize, ArrayRef minValues, + ArrayRef maxValues, ArrayRef means, + ArrayRef variances) + : sampleSizePerAxis(sampleSize), +minValuePerAxis(minValues.begin(), minValues.end()), +maxValuePerAxis(maxValues.begin(), maxValues.end()), +meanPerAxis(means.begin(), means.end()), +variancePerAxis(variances.begin(), variances.end()) {} void clear() { *this = TensorAxisStatistics(); } }; @@ -70,7 +84,11 @@ class AttributeTensorStatistics : public AbstractTensorStatistics { bool get(TensorAxisStatistics &stats) const override; - // TODO: Implement per-axis. + bool supportsPerAxis() const override; + + unsigned getAxisCount() const override; + + bool getForAxis(unsigned axis, TensorAxisStatistics &stats) const override; private: Attribute attr; diff --git a/mlir/lib/Quantizer/Support/Statistics.cpp b/mlir/lib/Quantizer/Support/Statistics.cpp index dca4c8571098..8a6a00e212d3 100644 --- a/mlir/lib/Quantizer/Support/Statistics.cpp +++ b/mlir/lib/Quantizer/Support/Statistics.cpp @@ -50,12 +50,53 @@ static void collectElementsStatisticsDim(ElementsAttr attr, } } +static void collectElementsStatisticsDimForAxis( +unsigned axis, ElementsAttr attr, unsigned numElements, +ArrayRef shape, SmallVectorImpl &indices, uint64_t dim, +TensorAxisStatistics &statistics) { + // Recursive terminating condition. + if (dim >= shape.size()) +return; + + // Axis is passed separately + if (dim == axis) { +collectElementsStatisticsDimForAxis(axis, attr, numElements, shape, indices, +dim + 1, statistics); +return; + } + + // Go to last not axis dim + if (dim < (shape.size() - 2) || + (dim == (shape.size() - 2) && axis != (shape.size() - 1))) { +// Recurse past dim. +for (uint64_t i = 0, s = shape[dim]; i < s; ++i) { + indices[dim] = i; + collectElementsStatisticsDimForAxis(axis, attr, numElements, shape, + indices, dim + 1, statistics); +} +return; + } + + // Pass axis + uint64_t axisSize = shape[axis]; + for (uint64_t axisIdx = 0; axisIdx < axisSize; ++axisIdx) { +indices[axis] = axisIdx; +// Collection dim. +for (uint64_t i = 0, s = shape[dim]; i < s; ++i) { + indices[dim] = i; + double value = attr.getValue(indices).getValueAsDouble(); + statistics.minValuePerAxis[axisIdx] = + std::min(statistics.minValuePerAxis[axisIdx], value); + statistics.maxValuePerAxis[axisIdx] = + std::max(statistics.maxValuePerAxis[axisIdx], value); + statistics.meanPerAxis[axisIdx] += value / numElements; + // TODO: Calculate a running variance. +} + } +} + static bool getElementsStatistics(ElementsAttr attr, TensorAxisStatistics &statistics) { - statistics.clear(); - statistics.minValue = std::numeric_limits::infinity(); - statistics.maxValue = -std::numeric_limits::infinity(); - ShapedType sType = attr.getType(); if (!sType.hasStaticShape()) return false; @@ -67,6 +108,11 @@ static bool getElementsStatistics(ElementsAttr attr, indices.resize(sType.getRank()); ArrayRef shape = sType.getShape(); + statistics.minValue = std::numeric_limits::infinity(); + statistics.maxValue = -std::numeric_li