[llvm-branch-commits] [mlir] 52586c4 - [mlir][CAPI] Add result type inference to the CAPI.

2021-01-23 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-24 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-03-01 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-03-25 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-18 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-18 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-19 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-19 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-19 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-12-29 Thread Stella Laurenzo via llvm-branch-commits

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().

2020-12-29 Thread Stella Laurenzo via llvm-branch-commits

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

2020-12-29 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-12-29 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-12-29 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-12-30 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-12-31 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-11 Thread Stella Laurenzo via llvm-branch-commits

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.

2021-01-11 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-09-28 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-11-22 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-11-25 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-11-29 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-11-29 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-11-29 Thread Stella Laurenzo via llvm-branch-commits

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.

2020-02-08 Thread Stella Laurenzo via llvm-branch-commits

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