Commit Graph

168 Commits

Author SHA1 Message Date
Mehdi Amini aeb4b1a9d8 Add facilities to print/parse a pass pipeline through the C API
This also includes and exercise a register function for individual
passes.

Differential Revision: https://reviews.llvm.org/D90728
2020-11-04 17:29:49 +00:00
Stella Laurenzo ebe12df896 Fix linkage error on mlirLogicalResultIsFailure.
* For C, this needs to be inline static like the others.

Differential Revision: https://reviews.llvm.org/D90740
2020-11-03 22:47:07 -08:00
Mehdi Amini f61d1028fa Add a basic C API for the MLIR PassManager as well as a basic TableGen backend for creating passes
This is exposing the basic functionalities (create, nest, addPass, run) of
the PassManager through the C API in the new header: `include/mlir-c/Pass.h`.

In order to exercise it in the unit-test, a basic TableGen backend is
also provided to generate a simple C wrapper around the pass
constructor. It is used to expose the libTransforms passes to the C API.

Reviewed By: stellaraccident, ftynse

Differential Revision: https://reviews.llvm.org/D90667
2020-11-04 06:36:31 +00:00
Mehdi Amini 0aaa2a4cb1 Remove mlir-c/Core.h which is superseded by the new API in mlir-c/IR.h
This header was an initial early attempt at a crude C API for bindings,
but it isn't used and redundant with the new API. At this point it only
contributes to more confusion.

Differential Revision: https://reviews.llvm.org/D90643
2020-11-03 11:15:32 +00:00
Mehdi Amini 9be3c01eb9 Undef the `DEFINE_C_API_STRUCT` macro after using it in the MLIR C API header (NFC)
Leaking macros isn't a good practice when defining headers. This
requires to duplicate the macro definition in every header though, but
that seems like a better tradeoff right now.

Differential Revision: https://reviews.llvm.org/D90633
2020-11-02 19:18:32 +00:00
Stella Laurenzo b85f2f5c5f [mlir][CAPI] Add APIs for mlirOperationGetName and Identifier.
Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D90583
2020-11-02 18:52:13 +00:00
Stella Laurenzo c645ea5e29 Add InsertionPoint and context managers to the Python API.
* Removes index based insertion. All insertion now happens through the insertion point.
* Introduces thread local context managers for implicit creation relative to an insertion point.
* Introduces (but does not yet use) binding the Context to the thread local context stack. Intent is to refactor all methods to take context optionally and have them use the default if available.
* Adds C APIs for mlirOperationGetParentOperation(), mlirOperationGetBlock() and mlirBlockGetTerminator().
* Removes an assert in PyOperation creation that was incorrectly constraining. There is already a TODO to rework the keepAlive field that it was guarding and without the assert, it is no worse than the current state.

Differential Revision: https://reviews.llvm.org/D90368
2020-10-29 17:50:13 -07:00
Kazuaki Ishizaki 41b09f4eff [mlir] NFC: fix trivial typos
fix typos in comments and documents

Reviewed By: jpienaar

Differential Revision: https://reviews.llvm.org/D90089
2020-10-29 04:05:22 +09:00
Mehdi Amini 72023442c1 Add a `mlirModuleGetBody()` accessor to the C API and bind it in Python
Getting the body of a Module is a common need which justifies a
dedicated accessor instead of forcing users to go through the
region->blocks->front unwrapping manually.

Differential Revision: https://reviews.llvm.org/D90287
2020-10-28 17:53:52 +00:00
zhanghb97 448f25c86b [mlir] Expose affine expression to C API
This patch provides C API for MLIR affine expression.
- Implement C API for methods of AffineExpr class.
- Implement C API for methods of derived classes (AffineBinaryOpExpr, AffineDimExpr, AffineSymbolExpr, and AffineConstantExpr).

Differential Revision: https://reviews.llvm.org/D89856
2020-10-23 20:06:32 +08:00
Stella Laurenzo 74a58ec9c2 [mlir][CAPI][Python] Plumb OpPrintingFlags to C and Python APIs.
* Adds a new MlirOpPrintingFlags type and supporting accessors.
* Adds a new mlirOperationPrintWithFlags function.
* Adds a full featured python Operation.print method with all options and the ability to print directly to files/stdout in text or binary.
* Adds an Operation.get_asm which delegates to print and returns a str or bytes.
* Reworks Operation.__str__ to be based on get_asm.

Differential Revision: https://reviews.llvm.org/D89848
2020-10-21 12:14:06 -07:00
Alex Zinenko 580915d6a2 [mlir] Expose Value hierarchy to Python bindings
Values are ubiquitous in the IR, in particular block argument and operation
results are Values. Define Python classes for BlockArgument, OpResult and their
common ancestor Value. Define pseudo-container classes for lists of block
arguments and operation results, and use these containers to access the
corresponding values in blocks and operations.

Differential Revision: https://reviews.llvm.org/D89778
2020-10-21 09:49:22 +02:00
Alex Zinenko 39613c2cbc [mlir] Expose Value hierarchy to C API
The Value hierarchy consists of BlockArgument and OpResult, both of which
derive Value. Introduce IsA functions and functions specific to each class,
similarly to other class hierarchies. Also, introduce functions for
pointer-comparison of Block and Operation that are necessary for testing and
are generally useful.

Reviewed By: stellaraccident, mehdi_amini

Differential Revision: https://reviews.llvm.org/D89714
2020-10-20 09:39:08 +02:00
Stella Laurenzo 6771b98c4e [mlir][CAPI] Add mlirAttributeGetType function.
* Also fixes the const-ness of the various DenseElementsAttr construction functions.
* Both issues identified when trying to use the DenseElementsAttr functions.

Differential Revision: https://reviews.llvm.org/D89517
2020-10-15 18:33:50 -07:00
Stella Laurenzo ad958f648e [mlir][Python] Add missing capsule->module and Context.create_module.
* Extends Context/Operation interning to cover Module as well.
* Implements Module.context, Attribute.context, Type.context, and Location.context back-references (facilitated testing and also on the TODO list).
* Adds method to create an empty Module.
* Discovered missing in npcomp.

Differential Revision: https://reviews.llvm.org/D89294
2020-10-13 13:10:33 -07:00
Stella Laurenzo 4aa217160e [mlir][CAPI] Attribute set/remove on operations.
* New functions: mlirOperationSetAttributeByName, mlirOperationRemoveAttributeByName
* Also adds some *IsNull checks and standardizes the rest to use "static inline" form, which makes them all non-opaque and not part of the ABI (which is desirable).
* Changes needed to resolve TODOs in npcomp PyTorch capture.

Differential Revision: https://reviews.llvm.org/D88946
2020-10-07 10:03:23 -07:00
Alex Zinenko 7b5dfb400a [mlir] Add support for diagnostics in C API.
Add basic support for registering diagnostic handlers with the context
(actually, the diagnostic engine contained in the context) and processing
diagnostic messages from the C API.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D88736
2020-10-07 14:42:02 +02:00
zhanghb97 2fc0d4a8e8 [mlir] Add Float Attribute, Integer Attribute and Bool Attribute subclasses to python bindings.
Based on PyAttribute and PyConcreteAttribute classes, this patch implements the bindings of Float Attribute, Integer Attribute and Bool Attribute subclasses.
This patch also defines the `mlirFloatAttrDoubleGetChecked` C API which is bound with the `FloatAttr.get_typed` python method.

Differential Revision: https://reviews.llvm.org/D88531
2020-10-03 00:32:51 +08:00
Stella Laurenzo 543922cd36 Adds MLIR C-API for marshaling Python capsules.
* Providing stable, C-accessible definitions for bridging MLIR Python<->C APIs, we eliminate inter-extension dependencies (i.e. they can all share a diamond dependency on the MLIR C-API).
* Just provides accessors for context and module right now.
* Needed in NPComp in ~a week or so for high level Torch APIs.

Differential Revision: https://reviews.llvm.org/D88426
2020-09-29 10:48:53 -07:00
Alex Zinenko 64c0c9f015 [mlir] Expose Dialect class and registration/loading to C API
- Add a minimalist C API for mlir::Dialect.
- Allow one to query the context about registered and loaded dialects.
- Add API for loading dialects.
- Provide functions to register the Standard dialect.

When used naively, this will require to separately register each dialect. When
we have more than one exposed, we can add variadic macros that expand to
individual calls.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D88162
2020-09-29 16:30:08 +02:00
Stella Laurenzo 76753a597b Add FunctionType to MLIR C and Python bindings.
Differential Revision: https://reviews.llvm.org/D88416
2020-09-28 09:56:48 -07:00
Alex Zinenko c538169ee9 [mlir] Add insert before/after to list-like constructs in C API
Blocks in a region and operations in a block are organized in a linked list.
The C API only provides functions to append or to insert elements at the
specified numeric position in the list. The latter is expensive since it
requires to traverse the list. Add insert before/after functionality with low
cost that relies on the iplist elements being convertible to iterators.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D88148
2020-09-23 17:29:30 +02:00
Stella Laurenzo 4cf754c4bc Implement python iteration over the operation/region/block hierarchy.
* Removes the half-completed prior attempt at region/block mutation in favor of new approach to ownership.
* Will re-add mutation more correctly in a follow-on.
* Eliminates the detached state on blocks and regions, simplifying the ownership hierarchy.
* Adds both iterator and index based access at each level.

Differential Revision: https://reviews.llvm.org/D87982
2020-09-23 07:57:50 -07:00
Kazuaki Ishizaki d7336ad5ff [mlir] NFC: fix trivial typos under include directory
Reviewed By: mravishankar, jpienaar

Differential Revision: https://reviews.llvm.org/D88040
2020-09-23 02:02:15 +09:00
Stella Laurenzo 85185b61b6 First pass on MLIR python context lifetime management.
* Per thread https://llvm.discourse.group/t/revisiting-ownership-and-lifetime-in-the-python-bindings/1769
* Reworks contexts so it is always possible to get back to a py::object that holds the reference count for an arbitrary MlirContext.
* Retrofits some of the base classes to automatically take a reference to the context, elimintating keep_alives.
* More needs to be done, as discussed, when moving on to the operations/blocks/regions.

Differential Revision: https://reviews.llvm.org/D87886
2020-09-18 12:17:50 -07:00
zhanghb97 b76f523be6 [mlir] expose affine map to C API
This patch provides C API for MLIR affine map.
- Implement C API for AffineMap class.
- Add Utils.h to include/mlir/CAPI/, and move the definition of the CallbackOstream to Utils.h to make sure mlirAffineMapPrint work correct.
- Add TODO for exposing the C API related to AffineExpr and mutable affine map.

Differential Revision: https://reviews.llvm.org/D87617
2020-09-17 09:50:45 +08:00
Alex Zinenko 855ec517a3 [mlir] Model StringRef in C API
Numerous MLIR functions return instances of `StringRef` to refer to a
non-owning fragment of a string (usually owned by the context). This is a
relatively simple class that is defined in LLVM. Provide a simple wrapper in
the MLIR C API that contains the pointer and length of the string fragment and
use it for Standard attribute functions that return StringRef instead of the
previous, callback-based mechanism.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D87677
2020-09-16 16:04:36 +02:00
zhanghb97 54d432aa6b [mlir] Add Shaped Type, Tensor Type and MemRef Type to python bindings.
Based on the PyType and PyConcreteType classes, this patch implements the bindings of Shaped Type, Tensor Type and MemRef Type subclasses.
The Tensor Type and MemRef Type are bound as ranked and unranked separately.
This patch adds the ***GetChecked C API to make sure the python side can get a valid type or a nullptr.
Shaped type is not a kind of standard types, it is the base class for vectors, memrefs and tensors, this patch binds the PyShapedType class as the base class of Vector Type, Tensor Type and MemRef Type subclasses.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D87091
2020-09-06 11:45:54 -07:00
Stella Laurenzo 2d1362e09a Add Location, Region and Block to MLIR Python bindings.
* This is just enough to create regions/blocks and iterate over them.
* Does not yet implement the preferred iteration strategy (python pseudo containers).
* Refinements need to come after doing basic mappings of operations and values so that the whole hierarchy can be used.

Differential Revision: https://reviews.llvm.org/D86683
2020-08-28 15:26:05 -07:00
Stella Laurenzo 3137c29926 Add initial python bindings for attributes.
* Generic mlir.ir.Attribute class.
* First standard attribute (mlir.ir.StringAttr), following the same pattern as generic vs standard types.
* NamedAttribute class.

Differential Revision: https://reviews.llvm.org/D86250
2020-08-23 22:16:23 -07:00
Alex Zinenko da56297462 [mlir] expose standard attributes to C API
Provide C API for MLIR standard attributes. Since standard attributes live
under lib/IR in core MLIR, place the C APIs in the IR library as well (standard
ops will go in a separate library).

Affine map and integer set attributes are only exposed as placeholder types
with IsA support due to the lack of C APIs for the corresponding types.

Integer and floating point attribute APIs expecting APInt and APFloat are not
exposed pending decision on how to support APInt and APFloat.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D86143
2020-08-19 18:50:19 +02:00
Stella Laurenzo d29d1e2ffd Add python bindings for Type and IntegerType.
* The binding for Type is trivial and should be non-controversial.
* The way that I define the IntegerType should serve as a pattern for what I want to do next.
* I propose defining the rest of the standard types in this fashion and then generalizing for dialect types as necessary.
* Essentially, creating/accessing a concrete Type (vs interacting with the string form) is done by "casting" to the concrete type (i.e. IntegerType can be constructed with a Type and will throw if the cast is illegal).
* This deviates from some of our previous discussions about global objects but I think produces a usable API and we should go this way.

Differential Revision: https://reviews.llvm.org/D86179
2020-08-19 09:23:44 -07:00
Mehdi Amini f9dc2b7079 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.

To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.

1) For passes, you need to override the method:

virtual void getDependentDialects(DialectRegistry &registry) const {}

and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.

2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.

3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:

  mlir::DialectRegistry registry;
  registry.insert<mlir::standalone::StandaloneDialect>();
  registry.insert<mlir::StandardOpsDialect>();

Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:

  mlir::registerAllDialects(registry);

4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()

Differential Revision: https://reviews.llvm.org/D85622
2020-08-19 01:19:03 +00:00
Mehdi Amini e75bc5c791 Revert "Separate the Registration from Loading dialects in the Context"
This reverts commit d14cf45735.
The build is broken with GCC-5.
2020-08-19 01:19:03 +00:00
Mehdi Amini d14cf45735 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.

To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.

1) For passes, you need to override the method:

virtual void getDependentDialects(DialectRegistry &registry) const {}

and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.

2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.

3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:

  mlir::DialectRegistry registry;
  registry.insert<mlir::standalone::StandaloneDialect>();
  registry.insert<mlir::StandardOpsDialect>();

Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:

  mlir::registerAllDialects(registry);

4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()

Differential Revision: https://reviews.llvm.org/D85622
2020-08-18 23:23:56 +00:00
Mehdi Amini d84fe55e0d Revert "Separate the Registration from Loading dialects in the Context"
This reverts commit e1de2b7550.
Broke a build bot.
2020-08-18 22:16:34 +00:00
Mehdi Amini e1de2b7550 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally
registered dialects on construction. Instead Dialects are only loaded explicitly
on demand:
- the Parser is lazily loading Dialects in the context as it encounters them
during parsing. This is the only purpose for registering dialects and not load
them in the context.
- Passes are expected to declare the dialects they will create entity from
(Operations, Attributes, or Types), and the PassManager is loading Dialects into
the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only
need to load the dialect for the IR it will emit, and the optimizer is
self-contained and load the required Dialects. For example in the Toy tutorial,
the compiler only needs to load the Toy dialect in the Context, all the others
(linalg, affine, std, LLVM, ...) are automatically loaded depending on the
optimization pipeline enabled.

To adjust to this change, stop using the existing dialect registration: the
global registry will be removed soon.

1) For passes, you need to override the method:

virtual void getDependentDialects(DialectRegistry &registry) const {}

and registery on the provided registry any dialect that this pass can produce.
Passes defined in TableGen can provide this list in the dependentDialects list
field.

2) For dialects, on construction you can register dependent dialects using the
provided MLIRContext: `context.getOrLoadDialect<DialectName>()`
This is useful if a dialect may canonicalize or have interfaces involving
another dialect.

3) For loading IR, dialect that can be in the input file must be explicitly
registered with the context. `MlirOptMain()` is taking an explicit registry for
this purpose. See how the standalone-opt.cpp example is setup:

  mlir::DialectRegistry registry;
  mlir::registerDialect<mlir::standalone::StandaloneDialect>();
  mlir::registerDialect<mlir::StandardOpsDialect>();

Only operations from these two dialects can be in the input file. To include all
of the dialects in MLIR Core, you can populate the registry this way:

  mlir::registerAllDialects(registry);

4) For `mlir-translate` callback, as well as frontend, Dialects can be loaded in
the context before emitting the IR: context.getOrLoadDialect<ToyDialect>()
2020-08-18 21:14:39 +00:00
Alex Zinenko 74f577845e [mlir] expose standard types to C API
Provide C API for MLIR standard types. Since standard types live under lib/IR
in core MLIR, place the C APIs in the IR library as well (standard ops will go
into a separate library). This also defines a placeholder for affine maps that
are necessary to construct a memref, but are not yet exposed to the C API.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D86094
2020-08-18 13:11:37 +02:00
Mehdi Amini 25ee851746 Revert "Separate the Registration from Loading dialects in the Context"
This reverts commit 2056393387.

Build is broken on a few bots
2020-08-15 09:21:47 +00:00
Mehdi Amini 2056393387 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally registered dialects on construction. Instead Dialects are only loaded explicitly on demand:
- the Parser is lazily loading Dialects in the context as it encounters them during parsing. This is the only purpose for registering dialects and not load them in the context.
- Passes are expected to declare the dialects they will create entity from (Operations, Attributes, or Types), and the PassManager is loading Dialects into the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only need to load the dialect for the IR it will emit, and the optimizer is self-contained and load the required Dialects. For example in the Toy tutorial, the compiler only needs to load the Toy dialect in the Context, all the others (linalg, affine, std, LLVM, ...) are automatically loaded depending on the optimization pipeline enabled.

Differential Revision: https://reviews.llvm.org/D85622
2020-08-15 08:07:31 +00:00
Mehdi Amini ba92dadf05 Revert "Separate the Registration from Loading dialects in the Context"
This was landed by accident, will reland with the right comments
addressed from the reviews.
Also revert dependent build fixes.
2020-08-15 07:35:10 +00:00
Mehdi Amini ebf521e784 Separate the Registration from Loading dialects in the Context
This changes the behavior of constructing MLIRContext to no longer load globally registered dialects on construction. Instead Dialects are only loaded explicitly on demand:
- the Parser is lazily loading Dialects in the context as it encounters them during parsing. This is the only purpose for registering dialects and not load them in the context.
- Passes are expected to declare the dialects they will create entity from (Operations, Attributes, or Types), and the PassManager is loading Dialects into the Context when starting a pipeline.

This changes simplifies the configuration of the registration: a compiler only need to load the dialect for the IR it will emit, and the optimizer is self-contained and load the required Dialects. For example in the Toy tutorial, the compiler only needs to load the Toy dialect in the Context, all the others (linalg, affine, std, LLVM, ...) are automatically loaded depending on the optimization pipeline enabled.
2020-08-14 09:40:27 +00:00
Alex Zinenko 321aa19ec8 [mlir] Expose printing functions in C API
Provide printing functions for most IR objects in C API (except Region that
does not have a `print` function, and Module that is expected to be printed as
Operation instead). The printing is based on a callback that is called with
chunks of the string representation and forwarded user-defined data.

Reviewed By: stellaraccident, Jing, mehdi_amini

Differential Revision: https://reviews.llvm.org/D85748
2020-08-12 13:07:34 +02:00
Alex Zinenko af838584ec [mlir] use intptr_t in C API
Using intptr_t is a consensus for MLIR C API, but the change was missing
from 75f239e975 (that was using unsigned initially) due to a
misrebase.

Reviewed By: stellaraccident, mehdi_amini

Differential Revision: https://reviews.llvm.org/D85751
2020-08-12 11:11:25 +02:00
Alex Zinenko 75f239e975 [mlir] Initial version of C APIs
Introduce an initial version of C API for MLIR core IR components: Value, Type,
    Attribute, Operation, Region, Block, Location. These APIs allow for both
    inspection and creation of the IR in the generic form and intended for wrapping
    in high-level library- and language-specific constructs. At this point, there
    is no stability guarantee provided for the API.

Reviewed By: stellaraccident, lattner

Differential Revision: https://reviews.llvm.org/D83310
2020-08-05 15:04:08 +02:00
River Riddle 9db53a1827 [mlir][NFC] Remove usernames and google bug numbers from TODO comments.
These were largely leftover from when MLIR was a google project, and don't really follow LLVM guidelines.
2020-07-07 01:40:52 -07:00
Mehdi Amini 308571074c Mass update the MLIR license header to mention "Part of the LLVM project"
This is an artifact from merging MLIR into LLVM, the file headers are
now aligned with the rest of the project.
2020-01-26 03:58:30 +00:00
Mehdi Amini 56222a0694 Adjust License.txt file to use the LLVM license
PiperOrigin-RevId: 286906740
2019-12-23 15:33:37 -08:00
MLIR Team c6c6a74d55 Add support for float and string attributes to the C API and python bindings
PiperOrigin-RevId: 286115042
2019-12-17 20:19:16 -08:00
Alex Zinenko c50e53c109 Expose mlir::parseType to bindings
Python bindings currently currently provide a makeScalarType function that
constructs one of the predefined types. It was implemented in the bindings
directly to circumvent the absence of standalone type parsing function. Now
that mlir::parseType has been made available, rely on the core parsing
procedure to construct types from strings in the bindings.

This changes includes a library reshuffling that splits out "CoreAPIs"
implementing the binding helper APIs into a separate library and makes that
dependent on the Parser library.

PiperOrigin-RevId: 274794516
2019-10-15 06:52:04 -07:00
River Riddle 8c44367891 NFC: Rename Function to FuncOp.
PiperOrigin-RevId: 257293379
2019-07-10 10:10:53 -07:00
Alex Zinenko f50edc65cd Drop MLIREmitter-based version of the EDSC
This version has been deprecated and can now be removed completely since the
    last remaining user (Python bindings) migrated to declarative builders.
    Several functions in lib/EDSC/Types.cpp construct core IR objects for the C
    bindings.  Move these functions into lib/EDSC/CoreAPIs.cpp until we decide
    where they should live.

    This completes the migration from the delayed-construction EDSC to Declarative
    Builders.

--

PiperOrigin-RevId: 241716729
2019-04-03 08:30:38 -07:00
Jacques Pienaar 52b10474a7 Remove index free function
Avoids including function in C++ side that resulted in OSS C++ errors:

include/mlir-c/Core.h:228:16: error: functions that differ only in their
return type cannot be overloaded
edsc_indexed_t index(edsc_indexed_t indexed, edsc_expr_list_t indices);
~~~~~~~~~~~~~~ ^
/usr/include/string.h:484:14: note: previous declaration is here
extern char *index (const char *__s, int __c)

And as these are going away soon, just removing the function requires the least changes.

PiperOrigin-RevId: 239110470
2019-03-29 17:24:24 -07:00
Alex Zinenko 4bd5d28391 EDSC bindings: expose generic Op construction interface
EDSC Expressions can now be used to build arbitrary MLIR operations identified
by their canonical name, i.e. the name obtained from
`OpClass::getOperationName()` for registered operations.  Expose this
functionality to the C API and Python bindings.  This exposes builder-level
interface to Python and avoids the need for experimental Python code to
implement EDSC free function calls for constructing each op type.

This modification required exposing mlir::Attribute to the C API and Python
bindings, which only supports integer attributes for now.

This is step 4/n to making EDSCs more generalizable.

PiperOrigin-RevId: 236306776
2019-03-29 16:51:32 -07:00
Alex Zinenko e7193a70f8 EDSC: support conditional branch instructions
Leverage the recently introduced support for multiple argument groups and
multiple destination blocks in EDSC Expressions to implement conditional
branches in EDSC.  Conditional branches have two successors and three argument
groups.  The first group contains a single expression of i1 type that
corresponds to the condition of the branch.  The two following groups contain
arguments of the two successors of the conditional branch instruction, in the
same order as the successors.  Expose this instruction to the C API and Python
bindings.

PiperOrigin-RevId: 235542768
2019-03-29 16:41:05 -07:00
Alex Zinenko 83e8db2193 EDSC: support branch instructions
The new implementation of blocks was designed to support blocks with arguments.
More specifically, StmtBlock can be constructed with a list of Bindables that
will be bound to block aguments upon construction.  Leverage this functionality
to implement branch instructions with arguments.

This additionally requires the statement storage to have a list of successors,
similarly to core IR operations.

Becauase successor chains can form loops, we need a possibility to decouple
block declaration, after which it becomes usable by branch instructions, from
block body definition.  This is achieved by creating an empty block and by
resetting its body with a new list of instructions.  Note that assigning a
block from another block will not affect any instructions that may have
designated this block as their successor (this behavior is necessary to make
value-type semantics of EDSC types consistent).  Combined, one can now write
generators like

    EDSCContext context;
    Type indexType = ...;
    Bindable i(indexType), ii(indexType), zero(indexType), one(indexType);
    StmtBlock loopBlock({i}, {});
    loopBlock.set({ii = i + one,
                   Branch(loopBlock, {ii})});
    MLIREmitter(&builder)
        .bindConstant<ConstantIndexOp>(zero, 0)
        .bindConstant<ConstantIndexOp>(one, 1)
	.emitStmt(Branch(loopBlock, {zero}));

where the emitter will emit the statement and its successors, if present.

PiperOrigin-RevId: 235541892
2019-03-29 16:40:50 -07:00
Sergei Lebedev 1cc9305c71 Exposed division and remainder operations in EDSC
This change introduces three new operators in EDSC: Div (also exposed
via Expr.__div__ aka /) -- floating-point division, FloorDiv and CeilDiv
for flooring/ceiling index division.

The lowering to LLVM will be implemented in b/124872679.

PiperOrigin-RevId: 234963217
2019-03-29 16:36:41 -07:00
Alex Zinenko 59a209721e EDSC: support call instructions
Introduce support for binding MLIR functions as constant expressions.  Standard
constant operation supports functions as possible constant values.

Provide C APIs to look up existing named functions in an MLIR module and expose
them to the Python bindings.  Provide Python bindings to declare a function in
an MLIR module without defining it and to add a definition given a function
declaration.  These declarations are useful when attempting to link MLIR
modules with, e.g., the standard library.

Introduce EDSC support for direct and indirect calls to other MLIR functions.
Internally, an indirect call is always emitted to leverage existing support for
delayed construction of MLIR Values using EDSC Exprs.  If the expression is
bound to a constant function (looked up or declared beforehand), MLIR constant
folding will be able to replace an indirect call by a direct call.  Currently,
only zero- and one-result functions are supported since we don't have support
for multi-valued expressions in EDSC.

Expose function calling interface to Python bindings on expressions by defining
a `__call__` function accepting a variable number of arguments.

PiperOrigin-RevId: 234959444
2019-03-29 16:36:26 -07:00
Alex Zinenko 21bd4540f3 EDSC: introduce min/max only usable inside for upper/lower bounds of a loop
Introduce a type-safe way of building a 'for' loop with max/min bounds in EDSC.
Define new types MaxExpr and MinExpr in C++ EDSC API and expose them to Python
bindings.  Use values of these type to construct 'for' loops with max/min in
newly introduced overloads of the `edsc::For` factory function.  Note that in C
APIs, we still must expose MaxMinFor as a different function because C has no
overloads.  Also note that MaxExpr and MinExpr do _not_ derive from Expr
because they are not allowed to be used in a regular Expr context (which may
produce `affine.apply` instructions not expecting `min` or `max`).

Factory functions `Min` and `Max` in Python can be further overloaded to
produce chains of comparisons and selects on non-index types.  This is not
trivial in C++ since overloaded functions cannot differ by the return type only
(`MaxExpr` or `Expr`) and making `MaxExpr` derive from `Expr` defies the
purpose of type-safe construction.

PiperOrigin-RevId: 234786131
2019-03-29 16:34:11 -07:00
Alex Zinenko d055a4e100 EDSC: support multi-expression loop bounds
MLIR supports 'for' loops with lower(upper) bound defined by taking a
maximum(minimum) of a list of expressions, but does not have first-class affine
constructs for the maximum(minimum).  All these expressions must have affine
provenance, similarly to a single-expression bound.  Add support for
constructing such loops using EDSC.  The expression factory function is called
`edsc::MaxMinFor` to (1) highlight that the maximum(minimum) operation is
applied to the lower(upper) bound expressions and (2) differentiate it from a
`edsc::For` that creates multiple perfectly nested loops (and should arguably
be called `edsc::ForNest`).

PiperOrigin-RevId: 234785996
2019-03-29 16:33:56 -07:00
Alex Zinenko a2a433652d EDSC: create constants as expressions
Introduce a functionality to create EDSC expressions from typed constants.
This complements the current functionality that uses "unbound" expressions and
binds them to a specific constant before emission.  It comes in handy in cases
where we want to check if something is a constant early during construciton
rather than late during emission, for example multiplications and divisions in
affine expressions.  This is also consistent with MLIR vision of constants
being defined by an operation (rather than being special kinds of values in the
IR) by exposing this operation as EDSC expression.

PiperOrigin-RevId: 234758020
2019-03-29 16:33:41 -07:00
Alex Zinenko b4dba895a6 EDSC: make Expr typed and extensible
Expose the result types of edsc::Expr, which are now stored for all types of
Exprs and not only for the variadic ones.  Require return types when an Expr is
constructed, if it will ever have some.  An empty return type list is
interpreted as an Expr that does not create a value (e.g. `return` or `store`).

Conceptually, all edss::Exprs are now typed, with the type being a (potentially
empty) tuple of return types.  Unbound expressions and Bindables must now be
constructed with a specific type they will take.  This makes EDSC less
evidently type-polymorphic, but we can still write generic code such as

    Expr sumOfSquares(Expr lhs, Expr rhs) { return lhs * lhs + rhs * rhs; }

and use it to construct different typed expressions as

    sumOfSquares(Bindable(IndexType::get(ctx)), Bindable(IndexType::get(ctx)));
    sumOfSquares(Bindable(FloatType::getF32(ctx)),
                 Bindable(FloatType::getF32(ctx)));

On the positive side, we get the following.
1. We can now perform type checking when constructing Exprs rather than during
   MLIR emission.  Nevertheless, this is still duplicates the Op::verify()
   until we can factor out type checking from that.
2. MLIREmitter is significantly simplified.
3. ExprKind enum is only used for actual kinds of expressions.  Data structures
   are converging with AbstractOperation, and the users can now create a
   VariadicExpr("canonical_op_name", {types}, {exprs}) for any operation, even
   an unregistered one without having to extend the enum and make pervasive
   changes to EDSCs.

On the negative side, we get the following.
1. Typed bindables are more verbose, even in Python.
2. We lose the ability to do print debugging for higher-level EDSC abstractions
   that are implemented as multiple MLIR Ops, for example logical disjunction.

This is the step 2/n towards making EDSC extensible.

***

Move MLIR Op construction from MLIREmitter::emitExpr to Expr::build since Expr
now has sufficient information to build itself.

This is the step 3/n towards making EDSC extensible.

Both of these strive to minimize the amount of irrelevant changes.  In
particular, this introduces more complex pretty-printing for affine and binary
expression to make sure tests continue to pass.  It also relies on string
comparison to identify specific operations that an Expr produces.

PiperOrigin-RevId: 234609882
2019-03-29 16:31:26 -07:00
Alex Zinenko 0a4c940c1b EDSC: introduce support for blocks
EDSC currently implement a block as a statement that is itself a list of
statements.  This suffers from two modeling problems: (1) these blocks are not
addressable, i.e. one cannot create an instruction where thus constructed block
is a successor; (2) they support block nesting, which is not supported by MLIR
blocks.  Furthermore, emitting such "compound statement" (misleadingly named
`Block` in Python bindings) does not actually produce a new Block in the IR.

Implement support for creating actual IR Blocks in EDSC.  In particular, define
a new StmtBlock EDSC class that is neither an Expr nor a Stmt but contains a
list of Stmts.  Additionally, StmtBlock may have (early-) typed arguments.
These arguments are Bindable expressions that can be used inside the block.
Provide two calls in the MLIREmitter, `emitBlock` that actually emits a new
block and `emitBlockBody` that only emits the instructions contained in the
block without creating a new block.  In the latter case, the instructions must
not use block arguments.

Update Python bindings to make it clear when instruction emission happens
without creating a new block.

PiperOrigin-RevId: 234556474
2019-03-29 16:30:56 -07:00
River Riddle 4755774d16 Make IndexType a standard type instead of a builtin. This also cleans up some unnecessary factory methods on the Type class.
PiperOrigin-RevId: 233640730
2019-03-29 16:25:38 -07:00
Sergei Lebedev 52ec65c85e Implemented __eq__ and __ne__ in EDSC Python bindings
PiperOrigin-RevId: 232473201
2019-03-29 16:13:34 -07:00
Dimitrios Vytiniotis 9ca0691b06 Exposing logical operators in EDSC all the way up to Python.
PiperOrigin-RevId: 232299839
2019-03-29 16:10:08 -07:00
Nicolas Vasilache 0353ef99eb Cleanup EDSCs and start a functional auto-generated library of custom Ops
This CL applies the following simplifications to EDSCs:
1. Rename Block to StmtList because an MLIR Block is a different, not yet
supported, notion;
2. Rework Bindable to drop specific storage and just use it as a simple wrapper
around Expr. The only value of Bindable is to force a static cast when used by
the user to bind into the emitter. For all intended purposes, Bindable is just
a lightweight check that an Expr is Unbound. This simplifies usage and reduces
the API footprint. After playing with it for some time, it wasn't worth the API
cognition overhead;
3. Replace makeExprs and makeBindables by makeNewExprs and copyExprs which is
more explicit and less easy to misuse;
4. Add generally useful functionality to MLIREmitter:
  a. expose zero and one for the ubiquitous common lower bounds and step;
  b. add support to create already bound Exprs for all function arguments as
  well as shapes and views for Exprs bound to memrefs.
5. Delete Stmt::operator= and replace by a `Stmt::set` method which is more
explicit.
6. Make Stmt::operator Expr() explicit.
7. Indexed.indices assertions are removed to pave the way for expressing slices
and views as well as to work with 0-D memrefs.

The CL plugs those simplifications with TableGen and allows emitting a full MLIR function for
pointwise add.

This "x.add" op is both type and rank-agnostic (by allowing ArrayRef of Expr
passed to For loops) and opens the door to spinning up a composable library of
existing and custom ops that should automate a lot of the tedious work in
TF/XLA -> MLIR.

Testing needs to be significantly improved but can be done in a separate CL.

PiperOrigin-RevId: 231982325
2019-03-29 16:05:23 -07:00
Nicolas Vasilache cacf05892e Add a C API for EDSCs in other languages + python
This CL adds support for calling EDSCs from other languages than C++.
Following the LLVM convention this CL:
1. declares simple opaque types and a C API in mlir-c/Core.h;
2. defines the implementation directly in lib/EDSC/Types.cpp and
lib/EDSC/MLIREmitter.cpp.

Unlike LLVM however the nomenclature for these types and API functions is not
well-defined, naming suggestions are most welcome.

To avoid the need for conversion functions, Types.h and MLIREmitter.h include
mlir-c/Core.h and provide constructors and conversion operators between the
mlir::edsc type and the corresponding C type.

In this first commit, mlir-c/Core.h only contains the types for the C API
to allow EDSCs to work from Python. This includes both a minimal set of core
MLIR
types (mlir_context_t, mlir_type_t, mlir_func_t) as well as the EDSC types
(edsc_mlir_emitter_t, edsc_expr_t, edsc_stmt_t, edsc_indexed_t). This can be
restructured in the future as concrete needs arise.

For now, the API only supports:
1. scalar types;
2. memrefs of scalar types with static or symbolic shapes;
3. functions with input and output of these types.

The C API is not complete wrt ownership semantics. This is in large part due
to the fact that python bindings are written with Pybind11 which allows very
idiomatic C++ bindings. An effort is made to write a large chunk of these
bindings using the C API but some C++isms are used where the design benefits
from this simplication. A fully isolated C API will make more sense once we
also integrate with another language like Swift and have enough use cases to
drive the design.

Lastly, this CL also fixes a bug in mlir::ExecutionEngine were the order of
declaration of llvmContext and the JIT result in an improper order of
destructors (which used to crash before the fix).

PiperOrigin-RevId: 231290250
2019-03-29 15:41:53 -07:00