Commit Graph

741 Commits

Author SHA1 Message Date
Chris Lattner adc2ab172d Some tweaks to the really great op definition doc.
PiperOrigin-RevId: 229622071
2019-03-29 15:23:58 -07:00
Uday Bondhugula c1ca23ef6e Some loop fusion code cleanup/simplification post cl/229575126
- enforce the assumptions better / in a simpler way

PiperOrigin-RevId: 229612424
2019-03-29 15:23:43 -07:00
Lei Zhang 3766332533 Change impl::printBinaryOp() to consider operand and result type
The operand and result types of binary ops are not necessarily the
same. For those binary ops, we cannot print in the short-form assembly.

Enhance impl:::printBinaryOp to consider operand and result types
to select which assembly form to use.

PiperOrigin-RevId: 229608142
2019-03-29 15:23:28 -07:00
River Riddle 5843e5a7c0 Add a canonicalization pattern to remove Dealloc operations if the memref is an AllocOp that is only used by Dealloc operations.
PiperOrigin-RevId: 229606558
2019-03-29 15:23:13 -07:00
Alex Zinenko 05b02bb98e TableGen: implement predicate tree and basic simplification
A recent change in TableGen definitions allowed arbitrary AND/OR predicate
compositions at the cost of removing known-true predicate simplification.
Introduce a more advanced simplification mechanism instead.

In particular, instead of folding predicate C++ expressions directly in
TableGen, keep them as is and build a predicate tree in TableGen C++ library.
The predicate expression-substitution mechanism, necessary to implement complex
predicates for nested classes such as `ContainerType`, is replaced by a
dedicated predicate.  This predicate appears in the predicate tree and can be
used for tree matching and separation.  More specifically, subtrees defined
below such predicate may be subject to different transformations than those
that appear above.  For example, a subtree known to be true above the
substitution predicate is not necessarily true below it.

Use the predicate tree structure to eliminate known-true and known-false
predicates before code emission, as well as to collapse AND and OR predicates
if their value can be deduced based on the value of one child.

PiperOrigin-RevId: 229605997
2019-03-29 15:22:58 -07:00
Jacques Pienaar 4b2b5f5267 Enable specifying the op for which the reference implementation should be printed.
Allows emitting reference implementation of multiple ops inside the test lowering pass.

PiperOrigin-RevId: 229603494
2019-03-29 15:22:43 -07:00
River Riddle ada685f352 Add canonicalization to remove AllocOps if there are no uses. AllocOp has side effects on the heap, but can still be deleted if it has zero uses.
PiperOrigin-RevId: 229596556
2019-03-29 15:22:28 -07:00
Jacques Pienaar a5827fc91d Add attribute matching and transform to pattern rewrites.
Start simple with single predicate match & transform rules for attributes.
* Its unclear whether modelling Attr predicates will be needed so start with allowing matching attributes with a single predicate.
*  The input and output attr type often differs and so add ability to specify a transform between the input and output format.

PiperOrigin-RevId: 229580879
2019-03-29 15:22:14 -07:00
MLIR Team 27d067e164 LoopFusion improvements:
*) Adds support for fusing into consumer loop nests with multiple loads from the same memref.
*) Adds support for reducing slice loop trip count by projecting out destination loop IVs greater than destination loop depth.
*) Removes dependence on src loop depth and simplifies cost model computation.

PiperOrigin-RevId: 229575126
2019-03-29 15:21:59 -07:00
Jacques Pienaar 9d4bb57189 Start a testing pass for EDSC lowering.
This is mostly plumbing to start allowing testing EDSC lowering. Prototype specifying reference implementation using verbose format without any generation/binding support. Add test pass that dumps the constructed EDSC (of which there can only be one). The idea is to enable iterating from multiple sides, this is wrong on many dimensions at the moment.

PiperOrigin-RevId: 229570535
2019-03-29 15:21:44 -07:00
Alex Zinenko bd161ae5bc TableGen: untie Attr from Type
In TableGen definitions, the "Type" class has been used for types of things
that can be stored in Attributes, but not necessarily present in the MLIR type
system.  As a consequence, records like "String" or "DerviedAttrBody" were of
class "Type", which can be confusing.  Furthermore, the "builderCall" field of
the "Type" class serves only for attribute construction.  Some TableGen "Type"
subclasses that correspond to MLIR kinds of types do not have a canonical way
of construction only from the data available in TableGen, e.g. MemRefType would
require the list of affine maps.  This leads to a conclusion that the entities
that describe types of objects appearing in Attributes should be independent of
"Type": they have some properties "Type"s don't and vice versa.

Do not parameterize Tablegen "Attr" class by an instance of "Type".  Instead,
provide a "constBuilderCall" field that can be used to build an attribute from
a constant value stored in TableGen instead of indirectly going through
Attribute.Type.builderCall.  Some attributes still don't have a
"constBuilderCall" because they used to depend on types without a
"builderCall".

Drop definitions of class "Type" that don't correspond to MLIR Types.  Provide
infrastructure to define type-dependent attributes and string-backed attributes
for convenience.

PiperOrigin-RevId: 229570087
2019-03-29 15:21:28 -07:00
Lei Zhang 590012772d Promote broadcast logic from TensorFlowLite to Dialect/ directory
We also need the broadcast logic in the TensorFlow dialect. Move it to a
Dialect/ directory for a broader scope. This Dialect/ directory is intended
for code not in core IR, but can potentially be shared by multiple dialects.

Apart from fixing TensorFlow op TableGen to use this trait, this CL only
contains mechanical code shuffling.

PiperOrigin-RevId: 229563911
2019-03-29 15:21:14 -07:00
Uday Bondhugula f99a44a7cd Address documentation/readability related comments from cl/227252907 on memref
store forwarding - NFC.

PiperOrigin-RevId: 229561933
2019-03-29 15:20:59 -07:00
Lei Zhang 254821d1db Rename hasCanonicalizationPatterns to hasCanonicalizer
The latter is shorter but still conveys the idea clearly. It is also more
consistent with hasConstantFolder.

PiperOrigin-RevId: 229561774
2019-03-29 15:20:44 -07:00
Jacques Pienaar b5b7e61f7a Update to new sugared form in doc
PiperOrigin-RevId: 229544256
2019-03-29 15:20:29 -07:00
Jacques Pienaar 57fb7bcda6 Use op_base in mlir-tblgen test instead of extracted class.
Avoid having to update the extracted classes and use the real op_base.td as
input.

PiperOrigin-RevId: 229474573
2019-03-29 15:20:12 -07:00
River Riddle 18fe1ffcd7 Move the storage of uniqued TypeStorage objects into TypeUniquer and give each context a unique TypeUniquer instance.
PiperOrigin-RevId: 229460053
2019-03-29 15:19:56 -07:00
Uday Bondhugula 03e15e1b9f Minor code cleanup - NFC.
- readability changes

PiperOrigin-RevId: 229443430
2019-03-29 15:19:41 -07:00
Lei Zhang b7dbfd04eb Const fold splat tensors for TFLite AddOp, SubOp, MulOp
The constant folding rules assumes value attributes of operands are already
verified to be in good standing.

For each op in the above, the constant folding rules support both integer and
floating point cases. Broadcast behavior is also supported as per the semantics
of TFLite ops.

This CL does not handle overflow/underflow cases yet.

PiperOrigin-RevId: 229441221
2019-03-29 15:19:26 -07:00
River Riddle f9d2eb1c8c Change derived type storage objects to define an 'operator==(const KeyTy &)' instead of converting to the KeyTy. This allows for handling cases where the KeyTy does not provide an equality operator on itself.
PiperOrigin-RevId: 229423249
2019-03-29 15:19:11 -07:00
River Riddle f8341cfe06 Verify that the parsed predicate attribute of a cmpi operation is a string.
PiperOrigin-RevId: 229419703
2019-03-29 15:18:53 -07:00
Alex Zinenko 0e58de70e7 Initial version of the LLVM IR dialect
LLVM IR types are defined using MLIR's extendable type system.  The dialect
provides the only type kind, LLVMType, that wraps an llvm::Type*.  Since LLVM
IR types are pointer-unique, MLIR type systems relies on those pointers to
perform its own type unique'ing.  Type parsing and printing is delegated to
LLVM libraries.

Define MLIR operations for the LLVM IR instructions currently used by the
translation to the LLVM IR Target to simplify eventual transition.  Operations
classes are defined using TableGen.  LLVM IR instruction operands that are only
allowed to take constant values are accepted as attributes instead.  All
operations are using verbose form for printing and parsing.

PiperOrigin-RevId: 229400375
2019-03-29 15:18:37 -07:00
Alex Zinenko 44e9869f1a TableGen: extract TypeConstraints from Type
MLIR has support for type-polymorphic instructions, i.e. instructions that may
take arguments of different types.  For example, standard arithmetic operands
take scalars, vectors or tensors.  In order to express such instructions in
TableGen, we need to be able to verify that a type object satisfies certain
constraints, but we don't need to construct an instance of this type.  The
existing TableGen definition of Type requires both.  Extract out a
TypeConstraint TableGen class to define restrictions on types.  Define the Type
TableGen class as a subclass of TypeConstraint for consistency.  Accept records
of the TypeConstraint class instead of the Type class as values in the
Arguments class when defining operators.

Replace the predicate logic TableGen class based on conjunctive normal form
with the predicate logic classes allowing for abitrary combinations of
predicates using Boolean operators (AND/OR/NOT).  The combination is
implemented using simple string rewriting of C++ expressions and, therefore,
respects the short-circuit evaluation order.  No logic simplification is
performed at the TableGen level so all expressions must be valid C++.
Maintaining CNF using TableGen only would have been complicated when one needed
to introduce top-level disjunction.  It is also unclear if it could lead to a
significantly simpler emitted C++ code.  In the future, we may replace inplace
predicate string combination with a tree structure that can be simplified in
TableGen's C++ driver.

Combined, these changes allow one to express traits like ArgumentsAreFloatLike
directly in TableGen instead of relying on C++ trait classes.

PiperOrigin-RevId: 229398247
2019-03-29 15:18:23 -07:00
Uday Bondhugula 4598dafa30 Parsing DmaStartOp: check if source, destination, and tag are of memref type.
- fix along the lines of cl/229390720 by @riverriddle

PiperOrigin-RevId: 229395218
2019-03-29 15:18:07 -07:00
River Riddle d50dc4fd6d When parsing DmaWait, check that the tag is a MemRef type.
PiperOrigin-RevId: 229390720
2019-03-29 15:17:52 -07:00
Nicolas Vasilache 515ce1e68e Add edsc::Indexed helper struct to act as syntactic sugar
This CL adds edsc::Indexed.

This helper class exists purely for sugaring purposes and allows writing
expressions such as:

```mlir
   Indexed A(...), B(...), C(...);
   ForNest(ivs, zeros, shapeA, ones, {
     C[ivs] = A[ivs] + B[ivs]
   });
```

PiperOrigin-RevId: 229388644
2019-03-29 15:17:37 -07:00
River Riddle 25d5b895fd When parsing Select/Cmpi standard operations, emit an error if the type does not have a valid i1 shape instead of crashing.
PiperOrigin-RevId: 229384794
2019-03-29 15:17:22 -07:00
Jacques Pienaar ce64d3dbf0 Add OpDefinitions document.
Moving MLIR operation description doc to MarkDown doc.

PiperOrigin-RevId: 229376100
2019-03-29 15:17:08 -07:00
Nicolas Vasilache 424041ad58 Add EDSC sugar
This allows load, store and ForNest to be used with both Expr and Bindable.
This simplifies writing generic pieces of MLIR snippet.

For instance, a generic pointwise add can now be written:

```cpp
// Different Bindable ivs, one per loop in the loop nest.
auto ivs = makeBindables(shapeA.size());
Bindable zero, one;
// Same bindable, all equal to `zero`.
SmallVector<Bindable, 8> zeros(ivs.size(), zero);
// Same bindable, all equal to `one`.
SmallVector<Bindable, 8> ones(ivs.size(), one);
// clang-format off
Bindable A, B, C;
Stmt scalarA, scalarB, tmp;
Stmt block = edsc::Block({
  ForNest(ivs, zeros, shapeA, ones, {
    scalarA = load(A, ivs),
    scalarB = load(B, ivs),
    tmp = scalarA + scalarB,
    store(tmp, C, ivs)
  }),
});
// clang-format on
```

This CL also adds some extra support for pretty printing that will be used in
a future CL when we introduce standalone testing of EDSCs. At the momen twe
are lacking the basic infrastructure to write such tests.

PiperOrigin-RevId: 229375850
2019-03-29 15:16:53 -07:00
Jacques Pienaar 02ba8fd6d9 Move tests and add missing BUILD file.
Updated the extracted base classes here. The test wasn't updated post the move.

PiperOrigin-RevId: 229353434
2019-03-29 15:16:38 -07:00
Uday Bondhugula 11ab300ad5 Update LangRef - integer sets should have at least one constraint
- this change is already consistent with the current code
- having no constraints made the integer set spec look odd - as nothing appears
  between ':' and the closing parenthesis
- there is no loss in representational power - an unconstrained set can always
  be represented by a trivially true constraint

PiperOrigin-RevId: 229307353
2019-03-29 15:16:22 -07:00
Uday Bondhugula 6e4f3e40c7 Fix outdated comments
PiperOrigin-RevId: 229300301
2019-03-29 15:16:08 -07:00
River Riddle 3bb35ad0dc Don't allocate a buffer for an empty ArrayRef in TypeStorageAllocator.
PiperOrigin-RevId: 229290802
2019-03-29 15:15:52 -07:00
River Riddle b9c791b96d Change derived type storage objects to be constructed with an instance of the
KeyTy. This will simplify the cases where a type can be constructed, and need to be verified, in multiple ways.

PiperOrigin-RevId: 229279000
2019-03-29 15:15:37 -07:00
River Riddle 8b0ad6f579 If an instruction contains blocks, IfInst/ForInst, make sure to drop references held by those blocks when dropping references for the instruction.
PiperOrigin-RevId: 229278667
2019-03-29 15:15:23 -07:00
River Riddle 6c1631b3f8 Check that at least one constraint is parsed when parsing an IntegerSet.
PiperOrigin-RevId: 229248638
2019-03-29 15:15:08 -07:00
Lei Zhang 61ec6c0992 Swap the type and attribute parameter in ConstantOp::build()
This is to keep consistent with other TableGen generated builders
so that we can also use this builder in TableGen rules.

PiperOrigin-RevId: 229244630
2019-03-29 15:14:52 -07:00
River Riddle ed26dd0421 Add a canonicalization pattern for conditional branch to fold constant branch conditions.
PiperOrigin-RevId: 229242007
2019-03-29 15:14:37 -07:00
River Riddle 06b0bd9651 Emit unsupported error when parsing a DenseElementAttr with an integer type of greater than 64 bits.
DenseElementAttr currently does not support value bitwidths of > 64. This can result in asan failures and crashes when trying to invoke DenseElementsAttr::writeBits/DenseElementsAttr::readBits.

PiperOrigin-RevId: 229241125
2019-03-29 15:14:23 -07:00
River Riddle e0594ce732 Add missing return post parse failure for the indices of a sparse attribute.
PiperOrigin-RevId: 229231462
2019-03-29 15:14:07 -07:00
MLIR Team 38c2fe3158 LoopFusion: automate selection of source loop nest slice depth and destination loop nest insertion depth based on a simple cost model (cost model can be extended/replaced at a later time).
*) LoopFusion: Adds fusion cost function which compares the cost of the fused loop nest, with the cost of the two unfused loop nests to determine if it is profitable to fuse the candidate loop nests. The fusion cost function is run for various combinations for src/dst loop depths attempting find the minimum cost setting for src/dst loop depths which does not increase the computational cost when the loop nests are fused. Combinations of src/dst loop depth are evaluated attempting to maximize loop depth (i.e. take a bigger computation slice from the source loop nest, and insert it deeper in the destination loop nest for better locality).
*) LoopFusion: Adds utility to compute op instance count for loop nests, sliced loop nests, and to compute the cost of a loop nest fused with another sliced loop nest.
*) LoopFusion: canonicalizes slice bound AffineMaps (and updates related tests).
*) Analysis::Utils: Splits getBackwardComputationSlice into two functions: one which calculates and returns the slice loop bounds for analysis by LoopFusion, and the other for insertion of the computation slice (ones fusion has calculated the min-cost src/dst loop depths).
*) Test: Adds multiple unit tests to test the new functionality.

PiperOrigin-RevId: 229219757
2019-03-29 15:13:53 -07:00
River Riddle d6b71b0d57 Add a Block::dropAllReferences to drop all references from held instructions and call it when clearing the block. This fixes a bug where ForInst/IfInst instructions may still have references to values while being destroyed.
PiperOrigin-RevId: 229207798
2019-03-29 15:13:39 -07:00
River Riddle a674ae8bbd Return an empty IntegerSet if the '(' is not parsed.
PiperOrigin-RevId: 229198934
2019-03-29 15:13:25 -07:00
River Riddle 791049fb34 Add a FloatAttr::getChecked, and invoke it during Attribute parsing.
PiperOrigin-RevId: 229167099
2019-03-29 15:13:10 -07:00
Nicolas Vasilache 1b171e9357 Add EDSC support for operator*
PiperOrigin-RevId: 229097351
2019-03-29 15:12:55 -07:00
Nicolas Vasilache 0ab81776aa Fix typo in lower_vector_transfers.mlir
PiperOrigin-RevId: 229010160
2019-03-29 15:12:40 -07:00
Nicolas Vasilache d734c50c5f [MLIR] Clip all access dimensions during LowerVectorTransfers
This CL adds a short term remedy to an issue that was found during execution
tests.

Lowering of vector transfer ops uses the permutation map to determine which
ForInst have been super-vectorized. During materialization to HW vector sizes
however, some of those dimensions may be fully unrolled and do not appear in
the permutation map.
Such dimensions were then not clipped and may have accessed out of bounds.

This CL conservatively clips all dimensions to ensure no out of bounds access.
The longer term solution is still up for debate but will probably require
either passing more information between Materialization and lowering, or just
merging the 2 passes.

PiperOrigin-RevId: 228980787
2019-03-29 15:12:26 -07:00
Nicolas Vasilache b941dc8238 [MLIR] Make MLIREmitter emit composed single-result AffineMap by construction
Arguably the dependence of EDSCs on Analysis is not great but on the other
hand this is a strict improvement in the emitted IR and since EDSCs are an
alternative to builders it makes sense that they have as much access to
Analysis as Transforms.

PiperOrigin-RevId: 228967624
2019-03-29 15:12:11 -07:00
Nicolas Vasilache 362557e11c Simplify compositions of AffineApply
This CL is the 6th and last on the path to simplifying AffineMap composition.
This removes `AffineValueMap::forwardSubstitutions` and replaces it by simple
calls to `fullyComposeAffineMapAndOperands`.

PiperOrigin-RevId: 228962580
2019-03-29 15:11:56 -07:00
River Riddle ba9a544615 Simplify Attribute constructor definitions.
PiperOrigin-RevId: 228926113
2019-03-29 15:11:41 -07:00