Commit Graph

272 Commits

Author SHA1 Message Date
River Riddle 30e68230bd Add support for a standard TupleType. Though this is a standard type, it merely provides a common mechanism for representing tuples in MLIR. It is up to dialect authors to provides operations for manipulating them, e.g. extract_tuple_element.
TupleType has the following form:
   tuple-type ::= `tuple` `<` (type (`,` type)*)? `>`

Example:

// Empty tuple.
tuple<>

// Single element.
tuple<i32>

// Multi element.
tuple<i32, tuple<f32>, i16>

PiperOrigin-RevId: 239226021
2019-03-29 17:25:09 -07:00
River Riddle 087e599a3f Rename allocator to identifierAllocator and add an identifierMutex to make identifier uniquing thread safe. This also adds a general purpose 'contextMutex' to protect access to the rest of the miscellaneous parts of the MLIRContext, e.g. diagnostics, dialect registration, etc. This is step 5/5 of making the MLIRContext thread-safe.
PiperOrigin-RevId: 238516697
2019-03-29 17:19:42 -07:00
River Riddle c769f6b985 Give the Location classes their own SmartRWMutex and make sure that they are using the locationAllocator. This is step 4/N to making MLIRContext thread-safe.
PiperOrigin-RevId: 238516646
2019-03-29 17:19:27 -07:00
River Riddle fd6c94dc8f Give the affine structures, AffineMap/AffineExpr/IntegerSet/etc, their own BumpPtrAllocator and SmartMutex to make them thread-safe. This is step 3/N to making MLIRContext thread-safe.
PiperOrigin-RevId: 238516596
2019-03-29 17:19:11 -07:00
River Riddle 92a8a7115b Give Attributes their own BumpPtrAllocator and SmartRWMutex to make them thread-safe. This is step 2/N to making the MLIRContext thread-safe.
PiperOrigin-RevId: 238516542
2019-03-29 17:18:55 -07:00
River Riddle 7eee76b84c Give the TypeUniquer its own BumpPtrAllocator and a SmartRWMutex to make it thread-safe. This is step 1/N to making the MLIRContext thread-safe.
PiperOrigin-RevId: 238037814
2019-03-29 17:15:11 -07:00
River Riddle 2c78469a93 Introduce a TypeID class to provide unique identifiers for derived type classes. This removes the need for derived types to define a static typeID field.
PiperOrigin-RevId: 237482890
2019-03-29 17:07:06 -07:00
River Riddle f37651c708 NFC. Move all of the remaining operations left in BuiltinOps to StandardOps. The only thing left in BuiltinOps are the core MLIR types. The standard types can't be moved because they are referenced within the IR directory, e.g. in things like Builder.
PiperOrigin-RevId: 236403665
2019-03-29 16:53:35 -07:00
River Riddle 302fb03961 Add a new class NamedAttributeList to deduplicate named attribute handling between Function and Instruction.
PiperOrigin-RevId: 235830304
2019-03-29 16:45:40 -07:00
River Riddle f1f86eac60 Add support for constructing DenseIntElementsAttr with an array of APInt and
DenseFPElementsAttr with an array of APFloat.

PiperOrigin-RevId: 235581794
2019-03-29 16:41:50 -07:00
Tatiana Shpeisman 2e6cd60d3b Add dialect-specific decoding for opaque constants.
Associates opaque constants with a particular dialect. Adds general mechanism to register dialect-specific hooks defined in external components. Adds hooks to decode opaque tensor constant and extract an element of an opaque tensor constant.

This CL does not change the existing mechanism for registering constant folding hook yet. One thing at a time.

PiperOrigin-RevId: 233544757
2019-03-29 16:24:38 -07:00
River Riddle 44e040dd63 Remove remaining references to OperationInst in all directories except for lib/Transforms.
PiperOrigin-RevId: 232322771
2019-03-29 16:10:38 -07:00
Lei Zhang 8b75cc5741 Define NumericAttr as the base class for BoolAttr, IntegerAttr, FloatAttr, and ElementsAttr
These attribute kinds are different from the rest in the sense that their types are defined
in MLIR's type hierarchy and we can build constant op out of them.

By defining this middle-level base class, we have a unified way to test and query the type
of these attributes, which will be useful when constructing constant ops of various dialects.

This CL also added asserts to reject non-NumericAttr in constant op's build() method.

PiperOrigin-RevId: 232188178
2019-03-29 16:08:43 -07:00
Nicolas Vasilache 0e7a8a9027 Drop AffineMap::Null and IntegerSet::Null
Addresses b/122486036

This CL addresses some leftover crumbs in AffineMap and IntegerSet by removing
the Null method and cleaning up the constructors.

As the ::Null uses were tracked down, opportunities appeared to untangle some
of the Parsing logic and make it explicit where AffineMap/IntegerSet have
ambiguous syntax. Previously, ambiguous cases were hidden behind the implicit
pointer values of AffineMap* and IntegerSet* that were passed as function
parameters. Depending the values of those pointers one of 3 behaviors could
occur.

This parsing logic convolution is one of the rare cases where I would advocate
for code duplication. The more proper fix would be to make the syntax
unambiguous or to allow some lookahead.

PiperOrigin-RevId: 231058512
2019-03-29 15:40:08 -07:00
Feng Liu b64998a6b3 Add a method to construct a CallSiteLoc which represents a stack of locations.
PiperOrigin-RevId: 230592860
2019-03-29 15:33:05 -07:00
Lei Zhang 57aade19b3 Add assertions to SplatElementsAttr and ConstantOp builders and fix failures
1) Fix FloatAttr type inconsistency in conversion from tf.FusedBatchNorm to TFLite ops

We used to compose the splat tensor out of the scalar epsilon attribute by using the
type of the variance operand. However, the epsilon attribute may have a different
bitwidth than the one in the variance operand. So it ends up we were creating
inconsistent types within the FloatAttr itself.

2) Fix SplatElementsAttr type inconsistency in AnnotateInputArrays

We need to create the zero-valued attribute according to the type provided as the
command-line arguments.

3) Concretize the result type of tf.Shape constant folding test case

Currently the resultant constant is created by the constant folding harness, using
the result type of the original op as the constant's result type. That can be
a different type than the constant's internal DenseElementsAttr.

PiperOrigin-RevId: 230244665
2019-03-29 15:28:59 -07:00
River Riddle 512d87cefc Add a constant folding hook to ExtractElementOp to fold extracting the element of a constant. This also adds a 'getValue' function to DenseElementsAttr and SparseElementsAttr to get the element at a constant index.
PiperOrigin-RevId: 230098938
2019-03-29 15:28:28 -07:00
River Riddle 174f66bc8a Restructure FloatAttr::get(Type, double) to allow for loss of precision when converting the double value to the target type semantics. A comment is added to discourage the use of this method for non simple constants. The new handling also removes the direct use of the float constructor for APFloat to avoid runtime float cast asan errors.
PiperOrigin-RevId: 230014696
2019-03-29 15:27:44 -07:00
River Riddle b04c9a47ca Fix raw buffer size when creating a DenseElementsAttr from an array of attributes.
PiperOrigin-RevId: 229973134
2019-03-29 15:27:13 -07:00
River Riddle 0e81d7c420 [MLIR] Add functionality for constructing a DenseElementAttr from an array of attributes and rerwite DenseElementsAttr::writeBits/readBits to handle non uniform bitwidths. This fixes asan failures that happen when using non uniform bitwidths.
PiperOrigin-RevId: 229815107
2019-03-29 15:25:45 -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
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 791049fb34 Add a FloatAttr::getChecked, and invoke it during Attribute parsing.
PiperOrigin-RevId: 229167099
2019-03-29 15:13:10 -07:00
Uday Bondhugula b934d75b8f Convert expr - c * (expr floordiv c) to expr mod c in AffineExpr
- Detect 'mod' to replace the combination of floordiv, mul, and subtract when
  possible at construction time; when 'c' is a power of two, this reduces the number of
  operations; also more compact and readable. Update simplifyAdd for this.

  On a side note:
  - with the affine expr flattening we have, a mod expression like d0 mod c
    would be flattened into d0 - c * q,  c * q <= d0 <= c*q + c - 1, with 'q'
    being added as the local variable (q = d0 floordiv c); as a result, a mod
    was turned into a floordiv whenever the expression was reconstructed back,
    i.e., as  d0 - c * (d0 floordiv c); as a result of this change, we recover
    the mod back.

- rename SimplifyAffineExpr -> SimplifyAffineStructures (pass had been renamed but
  the file hadn't been).

PiperOrigin-RevId: 228258120
2019-03-29 15:02:56 -07:00
Uday Bondhugula 94c2d969ce Rename getAffineBinaryExpr -> getAffineBinaryOpExpr, getBinaryAffineOpExpr ->
getAffineBinaryOpExpr for consistency (NFC)

- this is consistent with the name of the class and getAffineDimExpr/ConstantExpr, etc.

PiperOrigin-RevId: 228164959
2019-03-29 14:59:52 -07:00
River Riddle d2cd083f79 Introduce CRTP TypeBase class to simplify type construction and validation.
This impl class currently provides the following:
* auto definition of the 'ImplType = StorageClass'
* get/getChecked wrappers around TypeUniquer
* 'verifyConstructionInvariants' hook
   - This hook verifies that the arguments passed into get/getChecked are valid
     to construct a type instance with.

With this, all non-generic type uniquing has been moved out of MLIRContext.cpp

PiperOrigin-RevId: 227871108
2019-03-29 14:56:22 -07:00
Chris Lattner 7983bbc251 Introduce a simple canonicalization of affine_apply that drops unused dims and
symbols.

Included with this is some other infra:
 - Testcases for other canonicalizations that I will implement next.
 - Some helpers in AffineMap/Expr for doing simple walks without defining whole
   visitor classes.
 - A 'replaceDimsAndSymbols' facility that I'll be using to simplify maps and
   exprs, e.g. to fold one constant into a mapping and to drop/renumber unused dims.
 - Allow index (and everything else) to work in memref's, as we previously
   discussed, to make the testcase easier to write.
 - A "getAffineBinaryExpr" helper to produce a binop when you know the kind as
   an enum.

This line of work will eventually subsume the ComposeAffineApply pass, but it is no where close to that yet :-)

PiperOrigin-RevId: 227852951
2019-03-29 14:56:07 -07:00
River Riddle 54948a4380 Split the standard types from builtin types and move them into separate source files(StandardTypes.cpp/h). After this cl only FunctionType and IndexType are builtin types, but IndexType will likely become a standard type when the ml/cfgfunc merger is done. Mechanical NFC.
PiperOrigin-RevId: 227750918
2019-03-29 14:54:07 -07:00
River Riddle 8abc06f3d5 Implement initial support for dialect specific types.
Dialect specific types are registered similarly to operations, i.e. registerType<...> within the dialect. Unlike operations, there is no notion of a "verbose" type, that is *all* types must be registered to a dialect. Casting support(isa/dyn_cast/etc.) is implemented by reserving a range of type kinds in the top level Type class as opposed to string comparison like operations.

To support derived types a few hooks need to be implemented:

In the concrete type class:
    - static char typeID;
      * A unique identifier for the type used during registration.

In the Dialect:
    - typeParseHook and typePrintHook must be implemented to provide parser support.

The syntax for dialect extended types is as follows:
 dialect-type:  '!' dialect-namespace '<' '"' type-specific-data '"' '>'

The 'type-specific-data' is information used to identify different types within the dialect, e.g:
 - !tf<"variant"> // Tensor Flow Variant Type
 - !tf<"string">  // Tensor Flow String Type

TensorFlow/TensorFlowControl types are now implemented as dialect specific types as a proof
 of concept.

PiperOrigin-RevId: 227580052
2019-03-29 14:53:07 -07:00
River Riddle ae3f8a79ae Rename OperationPrefix to Namespace in Dialect. This is important as dialects will soon be able to define more than just operations.
Moving forward dialect namespaces cannot contain '.' characters.

This cl also standardizes that operation names must begin with the dialect namespace followed by a '.'.

PiperOrigin-RevId: 227532193
2019-03-29 14:51:22 -07:00
Chris Lattner 5187cfcf03 Merge Operation into OperationInst and standardize nomenclature around
OperationInst.  This is a big mechanical patch.

This is step 16/n towards merging instructions and statements, NFC.

PiperOrigin-RevId: 227093712
2019-03-29 14:42:23 -07:00
Feng Liu 63068da4d9 Support NameLoc and CallSiteLoc for mlir::Location
The NameLoc can be used to represent a variable, node or method. The
CallSiteLoc has two fields, one represents the concrete location and another
one represents the caller's location. Multiple CallSiteLocs can be chained as
a call stack.

For example, the following call stack
```
AAA
at file1:1
at file2:135
at file3:34
```

can be formed by call0:

```
auto name = NameLoc::get("AAA");
auto file1 = FileLineColLoc::get("file1", 1);
auto file2 = FileLineColLoc::get("file2", 135);
auto file3 = FileLineColLoc::get("file3", 34);
auto call2 = CallSiteLoc::get(file2, file3);
auto call1 = CallSiteLoc::get(file1, call2);
auto call0 = CallSiteLoc::get(name, call1);
```

PiperOrigin-RevId: 226941797
2019-03-29 14:37:34 -07:00
River Riddle 1e0ebabf66 Unify type uniquing and construction.
This allows for us to decouple type uniquing/construction from MLIRContext and pave the way for dialect specific types.

To accomplish this we two new classes, TypeUniquer and TypeStorageAllocator.

* TypeUniquer is now responsible for all construction and uniquing of types.
* TypeStorageAllocator is a utility used by derived type storage objects to allocate memory within an MLIRContext.

This cl also standardizes what a derived type storage class needs to provide:
    - Define a type alias, KeyTy, to a type that uniquely identifies the
      instance of the type within its kind.
      * The key type must be constructible from the values passed into the
        detail::TypeUniquer::get call after the type kind.
      * The key type must have a llvm::DenseMapInfo specialization for
        hashing.

    - Provide a method, 'KeyTy getKey() const', to construct the key type
      from an existing storage instance.

    - Provide a construction method:
        'DerivedStorage *construct(TypeStorageAllocator &, ...)'
      that builds a unique instance of the derived storage. The arguments
      after the TypeStorageAllocator must correspond with the values passed
      into the detail::TypeUniquer::get call after the type kind.

PiperOrigin-RevId: 226507184
2019-03-29 14:34:46 -07:00
Alex Zinenko 49c81ebcb0 Densify storage for f16, f32 and support f16 semantics in FloatAttrs
Existing implementation always uses 64 bits to store floating point values in
DenseElementsAttr.  This was due to FloatAttrs always a `double` for storage
independently of the actual type.  Recent commits added support for FloatAttrs
with the proper f32 type and floating semantics and changed the bitwidth
reporting on FloatType.

Use the existing infrastructure for densely storing 16 and 32-bit values in
DenseElementsAttr storage to store f16 and f32 values.  Move floating semantics
definition to the FloatType level.  Properly support f16 / IEEEhalf semantics
at the FloatAttr level and in the builder.

Note that bf16 is still stored as a 64-bit value with IEEEdouble semantics
because APFloat does not have first-class support for bf16 types.

PiperOrigin-RevId: 225981289
2019-03-29 14:32:14 -07:00
Alex Zinenko df9bd857b1 Type system: replace Type::getBitWidth with getIntOrFloatBitWidth
As MLIR moves towards dialect-specific types, a generic Type::getBitWidth does
not make sense for all of them.  Even with the current type system, the bit
width is not defined (and causes the method in question to abort) for all
TensorFlow types.

This commit restricts the bit width definition to primitive standard types that
have a number of bits appearing verbatim in their type, i.e., integers and
floats.  As a side effect, it delegates the decision on the bit width of the
`index` to the backends.  Existing backends currently hardcode it to 64 bits.

The Type::getBitWidth method is replaced by Type::getIntOrFloatBitWidth that
only applies to integers and floats.  The call sites are updated to use the new
method, where applicable, or rewritten so as not rely on it.  Incidentally,
this fixes a utility method that did not account for memrefs being allowed to
have vectors as element types in the size computation.

As an observation, several places in the code use Type in places where a more
specific type could be used instead.  Some of those are fixed by this commit.

PiperOrigin-RevId: 225844792
2019-03-29 14:30:43 -07:00
Jacques Pienaar 49c4d2a630 Fix builder getFloatAttr of double to use F64 type and use fltSemantics in FloatAttr.
Store FloatAttr using more appropriate fltSemantics (mostly fixing up F32/F64 storage, F16/BF16 pending). Previously F32 type was used incorrectly for double (the storage was double). Also add query method that returns fltSemantics for IEEE fp types and use that to verify that the APfloat given matches the type:
* FloatAttr created using APFloat is verified that the semantics of the type and APFloat matches;
* FloatAttr created using double has the APFloat created to match the semantics of the type;

Change parsing of tensor negative splat element to pass in the element type expected. Misc other changes to account for the storage type matching the attribute.

PiperOrigin-RevId: 225821834
2019-03-29 14:29:58 -07:00
Alex Zinenko 63261aa9a8 Disallow index types as elements of vector, memref and tensor types
An extensive discussion demonstrated that it is difficult to support `index`
types as elements of compound (vector, memref, tensor) types.  In particular,
their size is unknown until the target-specific lowering takes place.  MLIR may
need to store constants of the fixed-shape compound types (e.g.,
vector<4 x index>) internally and must know the size of the element type and
data layout constraints.  The same information is necessary for target-specific
lowering and translation to reliably support compound types with `index`
elements, but MLIR does not have a dedicated target description mechanism yet.

The uses cases for compound types with `index` elements, should they appear,
can be handled via an `index_cast` operation that converts between `index` and
fixed-size integer types at the SSA value level instead of the type level.

PiperOrigin-RevId: 225064373
2019-03-29 14:25:22 -07:00
Smit Hinsu adca59e4f7 Return bool from all emitError methods similar to Operation::emitOpError
This simplifies call-sites returning true after emitting an error. After the
conversion, dropped braces around single statement blocks as that seems more
common.

Also, switched to emitError method instead of emitting Error kind using the
emitDiagnostic method.

TESTED with existing unit tests

PiperOrigin-RevId: 224527868
2019-03-29 14:22:06 -07:00
Jacques Pienaar bb3ffc1c22 Fix two more getHashValues.
These were still returning the hash of the pointers resulting in the two getHashValues being different.

PiperOrigin-RevId: 223862743
2019-03-29 14:15:11 -07:00
Jacques Pienaar 3277f94bf4 Update getHashValue for ptr values stored in a DenseMap/Set to use getHasValue of KeyTy.
Ensures both hash values returned are the same. Tested by triggering resize of map/set and verifying failure before change.

PiperOrigin-RevId: 223651443
2019-03-29 14:13:58 -07:00
Jacques Pienaar 45e3139bc8 RankedTensorType: Use getHashValue(KeyTy) when calling getHashValue(RankedTensorTypeStorage*).
PiperOrigin-RevId: 223649958
2019-03-29 14:13:44 -07:00
Feng Liu a9d3e5ee38 Adds ConstantFoldHook registry in MLIRContext
This reverts the previous method which needs to create a new dialect with the
constant fold hook from TensorFlow. This new method uses a function object in
dialect to store the constant fold hook. Once a hook is registered to the
dialect, this function object will be assigned when the dialect is added to the
MLIRContext.

For the operations which are not registered, a new method getRegisteredDialects
is added to the MLIRContext to query the dialects which matches their op name
prefixes.

PiperOrigin-RevId: 222310149
2019-03-29 14:04:34 -07:00
Jacques Pienaar 711047c0cd Add Type to int/float attributes.
* Optionally attach the type of integer and floating point attributes to the attributes, this allows restricting a int/float to specific width.
  - Currently this allows suffixing int/float constant with type [this might be revised in future].
  - Default to i64 and f32 if not specified.
* For index types the APInt width used is 64.
* Change callers to request a specific attribute type.
* Store iN type with APInt of width N.
* This change does not handle the folding of constants of different types (e.g., doing int type promotions to support constant folding i3 and i32), and instead restricts the constant folding to only operate on the same types.

PiperOrigin-RevId: 221722699
2019-03-29 13:59:23 -07:00
Alex Zinenko be6ea23aee Optionally emit errors from IntegerType factory functions.
Similarly to other types, introduce "get" and "getChecked" static member
functions for IntegerType.  The latter emits errors to the error handler
registered with the MLIR context and returns a null type for the caller to
handle errors gracefully.  This deduplicates type consistency checks between
the parser and the builder.  Update the parser to call IntegerType::getChecked
for error reporting instead of the builder that would simply assert.

This CL completes the type system error emission refactoring: the parser now
only emits syntax-related errors for types while type factory systems may emit
type consistency errors.

PiperOrigin-RevId: 221165207
2019-03-29 13:55:50 -07:00
Jacques Pienaar 25e6b541cd Switch IntegerAttr to use APInt.
Change the storage type to APInt from int64_t for IntegerAttr (following the change to APFloat storage in FloatAttr). Effectively a direct change from int64_t to 64-bit APInt throughout (the bitwidth hardcoded). This change also adds a getInt convenience method to IntegerAttr and replaces previous getValue calls with getInt calls.

While this changes updates the storage type, it does not update all constant folding calls.

PiperOrigin-RevId: 221082788
2019-03-29 13:55:08 -07:00
River Riddle ce5ba22cd9 - Add support for fused locations.
These are locations that form a collection of other source locations with an optional metadata attribute.

- Add initial support for print/dump for locations.
Location Printing Examples:
* Unknown        : [unknown-location]
* FileLineColLoc : third_party/llvm/llvm/projects/google-mlir/test/TensorFlowLite/legalize.mlir:6:8
* FusedLoc       : <"tfl-legalize">[third_party/llvm/llvm/projects/google-mlir/test/TensorFlowLite/legalize.mlir:6:8, third_party/llvm/llvm/projects/google-mlir/test/TensorFlowLite/legalize.mlir:7:8]

- Add diagnostic support for fused locs.
* Prints the first location as the main location and the remaining as "fused from here" notes:
e.g.
third_party/llvm/llvm/projects/google-mlir/test/TensorFlowLite/legalize.mlir:6:8: error: This is an error.
  %1 = "tf.add"(%arg0, %0) : (i32, i32) -> i32
       ^
third_party/llvm/llvm/projects/google-mlir/test/TensorFlowLite/legalize.mlir:7:8: error: Fused from here.
  %2 = "tf.relu"(%1) : (i32) -> i32
       ^

PiperOrigin-RevId: 220835552
2019-03-29 13:53:42 -07:00
Alex Zinenko dafa6929d3 Clean up TensorType construction.
This CL introduces the following related changes:
- move tensor element type validity checking to a static member function
  TensorType::isValidElementType
- introduce get/getChecked similarly to MemRefType, where the checked function
  emits errors and returns nullptrs;
- remove duplicate element type validity checking from the parser and rely on
  the type constructor to emit errors instead.

PiperOrigin-RevId: 220694831
2019-03-29 13:52:59 -07:00
Alex Zinenko 8e711246e4 Clean up VectorType construction.
This CL introduces the following related changes:
- factor out element type validity checking to a static member function
  VectorType::isValidElementType;
- introduce get/getChecked similarly to MemRefType, where the checked function
  emits errors and returns nullptrs;
- remove duplicate element type validity checking from the parser and rely on
  the type constructor to emit errors instead.

PiperOrigin-RevId: 220693828
2019-03-29 13:52:46 -07:00
River Riddle 2fa4bc9fc8 Implement value type abstraction for locations.
Value type abstraction for locations differ from others in that a Location can NOT be null. NOTE: dyn_cast returns an Optional<T>.

PiperOrigin-RevId: 220682078
2019-03-29 13:52:31 -07:00
Alex Zinenko 846e48d16f Allow vector types to have index elements.
It is unclear why vector types were not allowed to have "index" as element
type.  Index values are integers, although of unknown bit width, and should
behave as such.  Vectors of integers are allowed and so are tensors of indices
(for indirection purposes), it is more consistent to also have vectors of
indices.

PiperOrigin-RevId: 220630123
2019-03-29 13:51:33 -07:00
Alex Zinenko ac2a655e87 Enable arithmetics for index types.
Arithmetic and comparison instructions are necessary to implement, e.g.,
control flow when lowering MLFunctions to CFGFunctions.  (While it is possible
to replace some of the arithmetics by affine_apply instructions for loop
bounds, it is still necessary for loop bounds checking, steps, if-conditions,
non-trivial memref subscripts, etc.)  Furthermore, working with indirect
accesses in, e.g., lookup tables for large embeddings, may require operating on
tensors of indexes.  For example, the equivalents to C code "LUT[Index[i]]" or
"ResultIndex[i] = i + j" where i, j are loop induction variables require the
arithmetics on indices as well as the possibility to operate on tensors
thereof.  Allow arithmetic and comparison operations to apply to index types by
declaring them integer-like.  Allow tensors whose element type is index for
indirection purposes.

The absence of vectors with "index" element type is explicitly tested, but the
only justification for this restriction in the CL introducing the test is
"because we don't need them".  Do NOT enable vectors of index types, although
it makes vector and tensor types inconsistent with respect to allowed element
types.

PiperOrigin-RevId: 220614055
2019-03-29 13:51:19 -07:00
Alex Zinenko cc82a94aff Materialize IndexType in the API.
Previously, index (aka affint) type was hidden under OtherType in the type API.
We will need to identify and operate on values of index types in the upcoming
MLFunc->CFGFunc(->LLVM) lowering passes.  Materialize index type into a
separate class and make it visible to LLVM RTTI hierarchy directly.
Practically, index is an integer type of unknown bit width and is accetable in
most places where regular integer types are.  This is purely an API change that
does not affect the IR.

After IndexType is separated out from OtherType, the remaining "other types"
are, in fact, TF-specific types only.  Further renaming may be of interest.

PiperOrigin-RevId: 220614026
2019-03-29 13:51:04 -07:00
Alex Zinenko 4aeb0a872c Uniformize MemRefType well-formedness checks.
Introduce a new public static member function, MemRefType::getChecked, intended
for the users that want detailed error messages to be emitted during MemRefType
construction and can gracefully handle these errors.  This function takes a
Location of the "MemRef" token if known.  The parser is one user of getChecked
that has location information, it outputs errors as compiler diagnostics.
Other users may pass in an instance of UnknownLoc and still have error messages
emitted.  Compiler-internal users not expecting the MemRefType construction to
fail should call MemRefType::get, which now aborts on failure with a generic
message.

Both "getChecked" and "get" call to a static free function that does actual
construction with well-formedness checks, optionally emits errors and returns
nullptr on failure.

The location information passed to getChecked has voluntarily coarse precision.
The error messages are intended for compiler engineers and do not justify
heavier API than a single location.  The text of the messages can be written so
that it pinpoints the actual location of the error within a MemRef declaration.

PiperOrigin-RevId: 219765902
2019-03-29 13:47:49 -07:00
River Riddle 4c465a181d Implement value type abstraction for types.
This is done by changing Type to be a POD interface around an underlying pointer storage and adding in-class support for isa/dyn_cast/cast.

PiperOrigin-RevId: 219372163
2019-03-29 13:45:54 -07:00
Nicolas Vasilache af7f56fdf8 [MLIR] Implement 1-D vectorization for fastest varying load/stores
This CL is a first in a series that implements early vectorization of
increasingly complex patterns. In particular, early vectorization will support
arbitrary loop nesting patterns (both perfectly and imperfectly nested), at
arbitrary depths in the loop tree.

This first CL builds the minimal support for applying 1-D patterns.
It relies on an unaligned load/store op abstraction that can be inplemented
differently on different HW.
Future CLs will support higher dimensional patterns, but 1-D patterns already
exhibit interesting properties.
In particular, we want to separate pattern matching (i.e. legality both
structural and dependency analysis based), from profitability analysis, from
application of the transformation.
As a consequence patterns may intersect and we need to verify that a pattern
can still apply by the time we get to applying it.

A non-greedy analysis on profitability that takes into account pattern
intersection is left for future work.

Additionally the CL makes the following cleanups:
1. the matches method now returns a value, not a reference;
2. added comments about the MLFunctionMatcher and MLFunctionMatches usage by
value;
3. added size and empty methods to matches;
4. added a negative vectorization test with a conditional, this exhibited a
but in the iterators. Iterators now return nullptr if the underlying storage
is nullpt.

PiperOrigin-RevId: 219299489
2019-03-29 13:44:26 -07:00
Alex Zinenko 19f14b72bb Drop unbounded identity map from MemRef affine map composition.
Unbounded identity maps do not affect the accesses through MemRefs in any way.
A previous CL dropped such maps only if they were alone in the composition.  Go
further and drop such maps everywhere they appear in the composition.

Update the parser test to check for unique'd hoisted map to be present but
without assuming any particular order.  Because some of the hoisted identity
maps still apear due to the nested "for" statements, we need to check for them.
However, they no longer appear above the non-identity maps because they are no
longer necessary for the extfunc memref declarations that are textually first
in the test file.  This order may change further as map simplification is
improved, there is no reason to assume a particular order.

PiperOrigin-RevId: 219287280
2019-03-29 13:44:13 -07:00
Alex Zinenko d45e193680 [trivial] fix MLIRContext::registerDiagnosticHandler documentation
The documentation for MLIRContext::registerDiagnosticHandler describing the
arguments of the diagnostic handler is inconsistent with the code.  It also
mentions LLVM context rather than MLIR context, likely a typo.  Fix both
issues.

PiperOrigin-RevId: 219120954
2019-03-29 13:43:16 -07:00
Alex Zinenko aae372ecb8 Drop trivial identity affine mappings in MemRef construction.
As per MLIR spec, the absence of affine maps in MemRef type is interpreted as
an implicit identity affine map.  Therefore, MemRef types declared with
explicit or implicit identity map should be considered equal at the MemRefType
level.  During MemRefType construction, drop trivial identity affine map
compositions.  A trivial identity composition consists of a single unbounded
identity map.  It is unclear whether affine maps should be composed in-place to
a single map during MemRef type construction, so non-trivial compositions that
could have been simplified to an identity are NOT removed.  We chose to drop
the trivial identity map rather than inject it in places that assume its
present implicitly because it makes the code simpler by reducing boilerplate;
identity mappings are obvious defaults.

Update tests that were checking for the presence of trivial identity map
compositions in the outputs.

PiperOrigin-RevId: 218862454
2019-03-29 13:41:47 -07:00
Uday Bondhugula ea65c695b9 Introduce integer set attribute
- add IntegerSetAttr to Attributes; add parsing and other support for it
  (builder, etc.).

PiperOrigin-RevId: 218804579
2019-03-29 13:40:50 -07:00
Chris Lattner 7de0da9594 Refactor all of the canonicalization patterns out of the Canonicalize pass, and
make operations provide a list of canonicalizations that can be applied to
them.  This allows canonicalization to be general to any IR definition.

As part of this, sink PatternMatch.h/cpp down to the IR library to fix a
layering problem.

PiperOrigin-RevId: 218773981
2019-03-29 13:39:49 -07:00
River Riddle 792d1c25e4 Implement value type abstraction for attributes.
This is done by changing Attribute to be a POD interface around an underlying pointer storage and adding in-class support for isa/dyn_cast/cast.

PiperOrigin-RevId: 218764173
2019-03-29 13:39:19 -07:00
Uday Bondhugula 80610c2f49 Introduce Fourier-Motzkin variable elimination + other cleanup/support
- Introduce Fourier-Motzkin variable elimination to eliminate a dimension from
  a system of linear equalities/inequalities. Update isEmpty to use this.
  Since FM is only exact on rational/real spaces, an emptiness check based on
  this is guaranteed to be exact whenever it says the underlying set is empty;
  if it says, it's not empty, there may still be no integer points in it.
  Also, supports a version that computes "dark shadows".

- Test this by checking for "always false" conditionals in if statements.

- Unique IntegerSet's that are small (few constraints, few variables). This
  basically means the canonical empty set and other small sets that are
  likely commonly used get uniqued; allows checking for the canonical empty set
  by pointer. IntegerSet::kUniquingThreshold gives the threshold constraint size
  for uniqui'ing.

- rename simplify-affine-expr -> simplify-affine-structures

Other cleanup

- IntegerSet::numConstraints, AffineMap::numResults are no longer needed;
  remove them.
- add copy assignment operators for AffineMap, IntegerSet.
- rename Invalid() -> Null() on AffineExpr, AffineMap, IntegerSet
- Misc cleanup for FlatAffineConstraints API

PiperOrigin-RevId: 218690456
2019-03-29 13:38:24 -07:00
Feng Liu 3d7ab2d265 Add support to opaque elements attributes
For some of the constant vector / tesor, if the compiler doesn't need to
interpret their elements content, they can be stored in this class to save the
serialize / deserialize cost.

syntax:

`opaque<` tensor-type `,` opaque-string `>`

opaque-string ::= `0x` [0-9a-fA-F]*
PiperOrigin-RevId: 218399426
2019-03-29 13:36:45 -07:00
Chris Lattner 9eedf6adb1 Replace the "OperationSet" abstraction with a new Dialect abstraction. This is
a step forward because now every AbstractOperation knows which Dialect it is
associated with, enabling things in the future like "constant folding
hooks" which will be important for layering.  This is also a bit nicer on
the registration side of things.

PiperOrigin-RevId: 218104230
2019-03-29 13:34:37 -07:00
Feng Liu c5a3a5e4ca Use APFloat for FloatAttribute
We should be able to represent arbitrary precision Float-point values inside
the IR, so compiler optimizations, such as constant folding can be done
independently on the compiling platform.

This CL also added a new field, AttrValueGetter, to the Attr class definition
for TableGen. This field is used to customize which mlir::Attr getter method to
get the defined PrimitiveType.

PiperOrigin-RevId: 218034983
2019-03-29 13:34:09 -07:00
MLIR Team 8c7478d10c Touch an unused variable.
PiperOrigin-RevId: 217861580
2019-03-29 13:33:26 -07:00
Feng Liu 03b48999b6 Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.

The syntax is:

`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`

Example: a sparse tensor

sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor

[[1, 0, 0, 0]
 [0, 0, 2, 0]
 [0, 0, 0, 0]]

PiperOrigin-RevId: 217764319
2019-03-29 13:32:55 -07:00
Feng Liu b5b90e5465 Add support to constant dense vector/tensor attribute.
The syntax of dense vecor/tensor attribute value is

`dense<` (tensor-type | vector-type)`,` attribute-list`>`

and

attribute-list ::= `[` attribute-list (`, ` attribute-list)* `]`.

The construction of the dense vector/tensor attribute takes a vector/tensor
type and a character array as arguments. The size of the input array should be
larger than the size specified by the type argument. It also assumes the
elements of the vector or tensor have been trunked to the data type sizes in
the input character array, so it extends the trunked data to 64 bits when it is
retrieved.

PiperOrigin-RevId: 217762811
2019-03-29 13:32:41 -07:00
Jacques Pienaar 764fd035b0 Split BuiltinOps out of StandardOps.
* Move Return, Constant and AffineApply out into BuiltinOps;
* BuiltinOps are always registered, while StandardOps follow the same dynamic registration;
* Kept isValidX in MLValue as we don't have a verify on AffineMap so need to keep it callable from Parser (I wanted to move it to be called in verify instead);

PiperOrigin-RevId: 216592527
2019-03-29 13:28:12 -07:00
Jacques Pienaar 487cc50613 Simplify simplify functions as follow up on previous CL.
Addressing comment from post submit + simplifying the logic.

PiperOrigin-RevId: 216560688
2019-03-29 13:27:46 -07:00
Jacques Pienaar fb176d40fc Only simplify floor div, ceil div or mod if the rhs constant >= 1.
Else we hit asserts in MathExtras.

PiperOrigin-RevId: 216553595
2019-03-29 13:27:32 -07:00
Nicolas Vasilache b04f881dcb [MLIR] IntegerSet value type
This CL applies the same pattern as AffineMap to IntegerSet: a simple struct
that acts as the storage is allocated in the bump pointer. The IntegerSet is
immutable and accessed everywhere by value.

Note that unlike AffineMap, it is not possible to remove the MLIRContext
parameter when constructing an IntegerSet for now. One possible way to achieve
this would be to add an enum to distinguish between the mathematically empty
set, the universe set and other sets.

This is left for future discussion.

PiperOrigin-RevId: 216545361
2019-03-29 13:27:19 -07:00
Feng Liu 5e3cca906a Add support to constant splat vector/tensor attribute.
This attribute represents a reference to a splat vector or tensor, where all
the elements have the same value. The syntax of the attribute is:

`splat<` (tensor-type | vector-type)`,` attribute-value `>`

PiperOrigin-RevId: 216537997
2019-03-29 13:27:05 -07:00
Chris Lattner fd06c6bc4e Change the representation of an operation name to be either an
AbstractOperation* or an Identifier.  This makes it possible to get to stuff in
AbstractOperation faster than going through a hash table lookup.  This makes
constant folding a bit faster now, but will become more important with
subsequent changes.

PiperOrigin-RevId: 216476772
2019-03-29 13:26:51 -07:00
Feng Liu 84a0c40261 Support `getShape`, `hasStaticShape` and `getDimSize` methods for all the Vector and Tensor Types.
PiperOrigin-RevId: 216447553
2019-03-29 13:26:38 -07:00
Nicolas Vasilache 1d3e7e2616 [MLIR] AffineMap value type
This CL applies the same pattern as AffineExpr to AffineMap: a simple struct
that acts as the storage is allocated in the bump pointer. The AffineMap is
immutable and accessed everywhere by value.

PiperOrigin-RevId: 216445930
2019-03-29 13:26:24 -07:00
Nicolas Vasilache 8ebb6ff171 [MLIR] Sketch AffineExpr value type
This CL sketches what it takes for AffineExpr to fully have by-value semantics
and not be a not-so-smart pointer anymore.

This essentially makes the underyling class a simple storage struct and
implements the operations on the value type directly. Since there is no
forwarding of operations anymore, we can full isolate the storage class and
make a hard visibility barrier by moving detail::AffineExpr into
AffineExprDetail.h.

AffineExprDetail.h is only included where storage-related information is
needed.

PiperOrigin-RevId: 216385459
2019-03-29 13:25:42 -07:00
Nicolas Vasilache 6707c7bea1 [MLIR] AffineExpr final cleanups
This CL:
1. performs the global codemod AffineXExpr->AffineXExprClass and
AffineXExprRef -> AffineXExpr;
2. simplifies function calls by removing the redundant MLIRContext parameter;
3. adds missing binary operator versions of scalar op AffineExpr where it
makes sense.

PiperOrigin-RevId: 216242674
2019-03-29 13:25:14 -07:00
Nicolas Vasilache ce2edea135 [MLIR] Cleanup AffineExpr
This CL introduces a series of cleanups for AffineExpr value types:
1. to make it clear that the value types should be used, the pointer
AffineExpr types are put in the detail namespace. Unfortunately, since the
value type operator-> only forwards to the underlying pointer type, we
still
need to expose this in the include file for now;
2. AffineExprKind is ok to use, it thus comes out of detail and thus of
AffineExpr
3. getAffineDimExpr, getAffineSymbolExpr, getAffineConstantExpr are
similarly
extracted as free functions and their naming is mande consistent across
Builder, MLContext and AffineExpr
4. AffineBinaryOpEx::simplify functions are made into static free
functions.
In particular it is moved away from AffineMap.cpp where it does not belong
5. operator AffineExprType is made explicit
6. uses the binary operators everywhere possible
7. drops the pointer usage everywhere outside of AffineExpr.cpp,
MLIRContext.cpp and AsmPrinter.cpp

PiperOrigin-RevId: 216207212
2019-03-29 13:24:45 -07:00
Nicolas Vasilache b55b407601 [RFC][MLIR] Use AffineExprRef in place of AffineExpr* in IR
This CL starts by replacing AffineExpr* with value-type AffineExprRef in a few
places in the IR. By a domino effect that is pretty telling of the
inconsistencies in the codebase, const is removed where it makes sense.

The rationale is that the decision was concisously made that unique'd types
have pointer semantics without const specifier. This is fine but we should be
consistent. In the end, the only logical invariant is that there should never
be such a thing as a const AffineExpr*, const AffineMap* or const IntegerSet*
in our codebase.

This CL takes a number of shortcuts to killing const with fire, in particular
forcing const AffineExprRef to return the underlying non-const
AffineExpr*. This will be removed once AffineExpr* has disappeared in
containers but for now such shortcuts allow a bit of sanity in this long quest
for cleanups.

The **only** places where const AffineExpr*, const AffineMap* or const
IntegerSet* may still appear is by transitive needs from containers,
comparison operators etc.

There is still one major thing remaining here: figure out why cast/dyn_cast
return me a const AffineXXX*, which in turn requires a bunch of ugly
const_casts. I suspect this is due to the classof
taking const AffineXXXExpr*. I wonder whether this is a side effect of 1., if
it is coming from llvm itself (I'd doubt it) or something else (clattner@?)

In light of this, the whole discussion about const makes total sense to me now
and I would systematically apply the rule that in the end, we should never
have any const XXX in our codebase for unique'd types (assuming we can remove
them all in containers and no additional constness constraint is added on us
from the outside world).

PiperOrigin-RevId: 215811554
2019-03-29 13:23:05 -07:00
Nicolas Vasilache 5b8017db18 [MLIR] Templated AffineExprBaseRef
This CL implements AffineExprBaseRef as a templated type to allow LLVM-style
casts to work properly. This also allows making AffineExprBaseRef::expr
private.

To achieve this, it is necessary to use llvm::simplify_type and make
AffineConstExpr derive from both AffineExpr and llvm::simplify<AffineExprRef>.
Note that llvm::simplify_type is just an interface to enable the proper
template resolution of isa/cast/dyn_cast but it otherwise holds no value.

Lastly note that certain dyn_cast operations wanted the const AffineExpr* form
of AffineExprBaseRef so I made the implicit constructor take that by default
and documented the immutable behavior. I think this is consistent with the
decision to make unique'd type immutable by convention and never use const on
them.

PiperOrigin-RevId: 215642247
2019-03-29 13:22:49 -07:00
Nicolas Vasilache 544f5e7a9b [MLIR] Remove uses of AffineExpr* outside of IR
This CL uniformizes the uses of AffineExprWrap outside of IR.
The public API of AffineExpr builder is modified to only use AffineExprWrap.
A few places access AffineExprWrap.expr, this is only while the API is in
transition to easily keep track (i.e. make expr private and let the compiler
track the errors).

Parser.cpp exhibits patterns that are dependent on nullptr values so
converting it is left for another CL.

PiperOrigin-RevId: 215642005
2019-03-29 13:22:35 -07:00
Nicolas Vasilache 9ef87c4b6b [MLIR] AffineExpr lightweight value type for operators
This CL proposes adding MLIRContext* to AffineExpr as discussed previously.
This allows the value class to not require the context in its constructor and
makes it a POD that it makes sense to pass by value everywhere.
A list of other RFC CLs will build on this. The RFC CLs are small incremental
pushes of the API which would be a pretty big change otherwise.

Pushing the thinking a little bit more it seems reasonable to use implicit
cast/constructor to/from AffineExpr*.
As this thing evolves, it looks to me like IR (and
probably Parser, for not so good reasons) want to operate on AffineExpr* and
the rest of the code wants to operate on the value type.

For this reason I think AffineExprImpl*/AffineExpr may also make sense but I
do not have a particular naming preference.
The jury is still out for naming decision between the above and
AffineExprBase*/AffineExpr or AffineExpr*/AffineExprRef.

PiperOrigin-RevId: 215641596
2019-03-29 13:22:21 -07:00
Jacques Pienaar e5354c2404 Add op registry for registering MLIR ops.
Instead of linking in different initializeMLIRContext functions, add a registry mechanism and function to initialize all registered ops in a given MLIRContext. Initialize all registered ops along with the StandardOps when constructing a MLIRContext.

PiperOrigin-RevId: 214073842
2019-03-29 13:17:49 -07:00
Chris Lattner c2f987b664 rework the custom op verifier hooks to use the diagnostic emission
infrastructure, instead of returning a const char*.  This allows custom
formatting and more interesting diagnostics.

This patch regresses the error message quality from the control flow
lowering pass, I'll address this in a subsequent patch.

PiperOrigin-RevId: 212210681
2019-03-29 13:12:18 -07:00
Chris Lattner 6dc2a34dcf Continue revising diagnostic handling to simplify and generalize it, and improve related infra.
- Add a new -verify mode to the mlir-opt tool that allows writing test cases
   for optimization and other passes that produce diagnostics.
 - Refactor existing the -check-parser-errors flag to mlir-opt into a new
   -split-input-file option which is orthogonal to -verify.
 - Eliminate the special error hook the parser maintained and use the standard
   MLIRContext's one instead.
 - Enhance the default MLIRContext error reporter to print file/line/col of
   errors when it is available.
 - Add new createChecked() methods to the builder that create ops and invoke
   the verify hook on them, use this to detected unhandled code in the
   RaiseControlFlow pass.
 - Teach mlir-opt about expected-error @+, it previously only worked with @-

PiperOrigin-RevId: 211305770
2019-03-29 13:08:51 -07:00
Chris Lattner adf48e1bd2 Introduce a new Location abstraction to represent location data in a structured
(and more useful) way rather than hacking up a pile of attributes for it.  In
the future this will grow to represent inlined locations, fusion cases etc, but
for now we start with simple Unknown and File/Line/Col locations.  NFC.

PiperOrigin-RevId: 210485775
2019-03-29 13:06:49 -07:00
Chris Lattner 9de71b2aea Introduce a new extract_element operation that does what it says. Introduce a
new VectorOrTensorType class that provides a common interface between vector
and tensor since a number of operations will be uniform across them (including
extract_element).  Improve the LoadOp verifier.

I also updated the MLIR spec doc as well.

PiperOrigin-RevId: 209953189
2019-03-29 13:04:19 -07:00
Chris Lattner 84259c7def Implement call and call_indirect ops.
This also fixes an infinite recursion in VariadicOperands that this turned up.

PiperOrigin-RevId: 209692932
2019-03-29 13:03:51 -07:00
Chris Lattner d9290db5fe Finish support for function attributes, and improve lots of things:
- Have the parser rewrite forward references to their resolved values at the
   end of parsing.
 - Implement verifier support for detecting malformed function attrs.
 - Add efficient query for (in general, recursive) attributes to tell if they
   contain a function.

As part of this, improve other general infrastructure:
 - Implement support for verifying OperationStmt's in ml functions, refactoring
   and generalizing support for operations in the verifier.
 - Refactor location handling code in mlir-opt to have the non-error expecting
   form of mlir-opt invocations to report error locations precisely.
 - Fix parser to detect verifier failures and report them through errorReporter
   instead of printing the error and crashing.

This regresses the location info for verifier errors in the parser that were
previously ascribed to the function.  This will get resolved in future patches
by adding support for function attributes, which we can use to manage location
information.

PiperOrigin-RevId: 209600980
2019-03-29 13:03:11 -07:00
Chris Lattner 9265197c4e Implement initial support for function attributes, including parser, printer,
resolver support.

Still TODO are verifier support (to make sure you don't use an attribute for a
function in another module) and the TODO in ModuleParser::finalizeModule that I
will handle in the next patch.

PiperOrigin-RevId: 209361648
2019-03-29 13:02:44 -07:00
Uday Bondhugula 8a663870e8 Support for affine integer sets
- introduce affine integer sets into the IR
- parse and print affine integer sets (both inline or outlined) similar to
  affine maps
- use integer set for IfStmt's conditional, and implement parsing of IfStmt's
  conditional

- fixed an affine expr paren omission bug while one this.

TODO: parse/represent/print MLValue operands to affine integer set references.
PiperOrigin-RevId: 207779408
2019-03-29 12:56:58 -07:00
Chris Lattner ed9fa46413 Continue wiring up diagnostic reporting infrastructure, still WIP.
- Implement a diagnostic hook in one of the paths in mlir-opt which
   captures and reports the diagnostics nicely.
 - Have the parser capture simple location information from the parser
   indicating where each op came from in the source .mlir file.
 - Add a verifyDominance() method to MLFuncVerifier to demo this, resolving b/112086163
 - Add some PrettyStackTrace handlers to make crashes in the testsuite easier
   to track down.

PiperOrigin-RevId: 207488548
2019-03-29 12:55:34 -07:00
James Molloy 72645b31b8 [mlir] Add a TypeAttr class, allow type attributes
PiperOrigin-RevId: 207235956
2019-03-29 12:54:11 -07:00
James Molloy 1e793eb8dc [mlir] Add a string type
PiperOrigin-RevId: 206977161
2019-03-29 12:52:35 -07:00
Chris Lattner 48dbfb48d5 Enhance MLIRContext and operations with the ability to register diagnostic
handlers and to feed them with errors and warnings produced by the compiler.
Enhance Operation to be able to get its own MLIRContext on demand, simplifying
some clients.  Change the verifier to emit certain errors with the diagnostic
handler.

This is steps towards reworking the verifier and diagnostic propagation but is
itself not particularly useful.  More to come.

PiperOrigin-RevId: 206948643
2019-03-29 12:51:52 -07:00
Chris Lattner c77f39f55c Eliminate "primitive" types from being a thing, splitting them into FloatType
and OtherType.  Other type is now the thing that holds AffineInt, Control,
eventually Resource, Variant, String, etc.  FloatType holds the floating point
types, and allows convenient query of isa<FloatType>().

This fixes issues where we allowed control to be the element type of tensor,
memref, vector.  At the same time, ban AffineInt from being an element of a
vector/memref/tensor as well since we don't need it.

I updated the spec to match this as well.

PiperOrigin-RevId: 206361942
2019-03-29 12:46:57 -07:00
Uday Bondhugula 50b2ce51ff Fix/clean up convoluted AffineBinaryOpExpr::get.
The code for this has been convoluted. We shouldn't be doing a "*result =
simplified" below at 703 since the simplified expression would have already
been inserted by a simplify* method,  whether it was a binary op expr or
something else.

PiperOrigin-RevId: 206114115
2019-03-29 12:44:43 -07:00
Uday Bondhugula e866f57730 Unique AffineDimExpr, AffineSymbolExpr, AffineConstantExpr, and allocate these
from the bump pointer allocator.

- delete AffineExpr destructors.

PiperOrigin-RevId: 205943807
2019-03-29 12:43:15 -07:00
James Molloy 4db2ee5f1b [mlir] Fix a use-after-free iterator error found by asan
While fixing this the parser-affine-map.mlir test started failing due to ordering of the printed affine maps. Even the existing CHECK-DAGs weren't enough to disambiguate; a partial match on one line precluded a total match on a following line.

The fix for this was easy - print the affine maps in reference order rather than in DenseMap iteration order.

PiperOrigin-RevId: 205843770
2019-03-29 12:40:47 -07:00
Jacques Pienaar 0b6b99667b Vector types elementtype can be either PrimitiveType or IntegerType.
Change the type of elementType and remove the cast to PrimitiveType.

PiperOrigin-RevId: 205698221
2019-03-29 12:39:38 -07:00
James Molloy 0b2ec56d8f [mlir] clang-format
Mostly whitespace changes, but this makes these files clang-format clean.

PiperOrigin-RevId: 205697599
2019-03-29 12:39:25 -07:00
Uday Bondhugula 6d242fcf4b Simplify affine binary op expression class hierarchy
- Drop sub-classing of affine binary op expressions.
- Drop affine expr op kind sub. Represent it as multiply by -1 and add. This
  will also be in line with the math form when we'll need to represent a system of
  linear equalities/inequalities: the negative number goes into the coefficient
  of an affine form. (For eg. x_1 + (-1)*x_2 + 3*x_3 + (-2) >= 0). The folding
  simplification will transparently deal with multiplying the -1 with any other
  constants. This also means we won't need to simplify a multiply expression
  like in x_1 + (-2)*x_2 to a subtract expression (x_1 - 2*x_2) for
  canonicalization/uniquing.
- When we print the IR, we will still pretty print to a subtract when possible.

PiperOrigin-RevId: 205298958
2019-03-29 12:36:46 -07:00
MLIR Team f1e039617b Support for AffineMapAttr.
PiperOrigin-RevId: 205157390
2019-03-29 12:35:40 -07:00
MLIR Team 8e8114a96d Adds MemRef type and adds support for parsing memref affine map composition.
PiperOrigin-RevId: 204756982
2019-03-29 12:34:20 -07:00
Uday Bondhugula 686fb64e2f Comment fixes for affine map range size parsing.
PiperOrigin-RevId: 204399402
2019-03-29 12:33:13 -07:00
Uday Bondhugula 8fbaf79afb Parse affine map range sizes.
PiperOrigin-RevId: 204240947
2019-03-29 12:32:59 -07:00
Uday Bondhugula b488a035aa Implement some simple affine expr canonicalization/simplification.
- fold constants when possible.
- for a mul expression, canonicalize to always keep the LHS as the
  constant/symbolic term, and similarly, the RHS for an add expression to keep
  it closer to the mathematical form. (Eg: f(x) = 3*x + 5)); other similar simplifications;
- verify binary op expressions at creation time.

TODO: we can completely drop AffineSubExpr, and instead use add and mul by -1.
This way something like x - 4 and -4 + x get canonicalized to x + -1 * 4
instead of being x - 4 and x + -4. (The other alternative if wanted to retain
AffineSubExpr would be to simplify x + -1*y to x - y and x + <neg number> to x
- <pos number>).
PiperOrigin-RevId: 204240258
2019-03-29 12:32:45 -07:00
Uday Bondhugula fc46bcf51d Complete affine expr parsing support
- check for non-affine expressions
- handle negative numbers and negation of id's, expressions
- functions to check if a map is pure affine or semi-affine
- simplify/clean up affine map parsing code
- report more errors messages, more accurate error messages

PiperOrigin-RevId: 203773633
2019-03-29 12:31:03 -07:00
Chris Lattner 67c03193de Implement a simple IR verifier, including support for custom ops adding their
own requirements.

PiperOrigin-RevId: 203497491
2019-03-29 12:29:55 -07:00
Chris Lattner 9e0e01b47a Implement Uday's suggestion to unique attribute lists across instructions,
reducing the memory impact on Operation to one word instead of 3 from an
std::vector.

Implement Jacques' suggestion to merge OpImpl::Storage into OpImpl::Base.

PiperOrigin-RevId: 203426518
2019-03-29 12:29:42 -07:00
Chris Lattner 1928e20a56 Add the ability to have "Ops" defined as small C++ classes, with some nice
properties:
 - They allow type checked dynamic casting from their base Operation.
 - They allow nice accessors for C++ clients, e.g. a "getIndex()" method on
   'dim' that returns an unsigned.
 - They work with both OperationInst/OperationStmt (once OperationStmt is
   implemented).
 - They get custom printing logic.  They will eventually get custom parsing,
   verifier, and builder logic as well.
 - Out of tree clients can register their own operation set without having to
   change MLIR core, e.g. for TensorFlow or custom target instructions.

This registers addf and dim as examples.

PiperOrigin-RevId: 203382993
2019-03-29 12:29:29 -07:00
Chris Lattner ccd8caee9e Implement IR support for attributes.
PiperOrigin-RevId: 203293376
2019-03-29 12:29:00 -07:00
Chris Lattner ad4ea23278 Clean up the implementation of Type, making it structurally more similar to
Instruction and AffineExpr.  NFC.

PiperOrigin-RevId: 203287117
2019-03-29 12:28:47 -07:00
Uday Bondhugula bd7c1f9566 Clean up an MLIRContext comment
PiperOrigin-RevId: 203227287
2019-03-29 12:28:35 -07:00
Uday Bondhugula 3dc4fb6f0f Parsing support for affine maps and affine expressions
A recursive descent parser for affine maps/expressions with operator precedence and
associativity. (While on this, sketch out uniqui'ing functionality for affine maps
and affine binary op expressions (partly).)

PiperOrigin-RevId: 203222063
2019-03-29 12:28:22 -07:00
Chris Lattner 6af866c58d Enhance the type system to support arbitrary precision integers, which are
important for low-bitwidth inference cases and hardware synthesis targets.

Rename 'int' to 'affineint' to avoid confusion between "the integers" and "the int
type".

PiperOrigin-RevId: 202751508
2019-03-29 12:27:32 -07:00
Uday Bondhugula fdf7bc4e25 [WIP] Sketching IR and parsing support for affine maps, affine expressions
Run test case:

$ mlir-opt test/IR/parser-affine-map.mlir
test/IR/parser-affine-map.mlir:3:30: error: expect '(' at start of map range
#hello_world2 (i, j) [s0] -> i+s0, j)
                             ^

PiperOrigin-RevId: 202736856
2019-03-29 12:27:20 -07:00
Chris Lattner 1734d78f88 Sketch out parser/IR support for OperationInst, and a new Instruction base
class.

Introduce an Identifier class to MLIRContext to represent uniqued identifiers,
introduce string literal support to the lexer, introducing parser and printer
support etc.

PiperOrigin-RevId: 202592007
2019-03-29 12:26:53 -07:00
MLIR Team 81f5332e45 Remove unused UnrankedTensorTypeKeyInfo.
PiperOrigin-RevId: 201830967
2019-03-29 12:25:11 -07:00
MLIR Team 642f3e8847 Add tensor type.
PiperOrigin-RevId: 201830793
2019-03-29 12:24:58 -07:00
Chris Lattner 49795d166f Introduce IR support for MLIRContext, primitive types, function types, and
vector types.

tensors and memref types are still TODO, and would be a good starter project
for someone.

PiperOrigin-RevId: 201782748
2019-03-29 12:24:32 -07:00