xref: /llvm-project/mlir/include/mlir/Dialect/Shape/IR/ShapeBase.td (revision 863c346209e27d22157fad21d0fd730e710a3441)
1//===- ShapeBase.td ----------------------------------------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Base definitions for the `shape` dialect.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SHAPE_BASE_TD
14#define SHAPE_BASE_TD
15
16include "mlir/IR/AttrTypeBase.td"
17include "mlir/IR/OpBase.td"
18
19//===----------------------------------------------------------------------===//
20// Shape Inference dialect definitions
21//===----------------------------------------------------------------------===//
22
23def ShapeDialect : Dialect {
24  let name = "shape";
25
26  let summary = "Types and operations for shape dialect";
27  let description = [{
28    This dialect contains operations for shape inference.
29
30    Note: Unless explicitly stated, all functions that return a shape and take
31    shapes as input, return the invalid shape if one of its operands is an
32    invalid shape. This avoids flagging multiple errors for one verification
33    failure. The dialect itself does not specify how errors should be combined
34    (there are multiple different options, from always choosing first operand,
35    concatting etc. on how to combine them).
36  }];
37
38  let cppNamespace = "::mlir::shape";
39  let dependentDialects = ["arith::ArithDialect", "tensor::TensorDialect"];
40
41  let useDefaultTypePrinterParser = 1;
42  let hasConstantMaterializer = 1;
43  let hasOperationAttrVerify = 1;
44}
45
46class Shape_Type<string name, string typeMnemonic> : TypeDef<ShapeDialect, name> {
47  let mnemonic = typeMnemonic;
48}
49
50def Shape_ShapeType : Shape_Type<"Shape", "shape"> {
51  let description = [{
52    `shape.shape` represents either an unranked shape, a ranked shape with
53    possibly unknown dimensions or an invalid shape. The rank is of type
54    `shape.size` and, if rank is known, the extent is a 1D tensor of type
55    `shape.size`.
56
57    Shape is printed:
58    * `[*]` if it is an unranked shape
59    * `[?, 2]` if a rank 2 tensor with one unknown dimension
60    * `[3, 4]` is a rank 2 static tensor
61    * `[]` is a scalar
62    * `[1]` is a rank 1 tensor with 1 element
63    * `[invalid]` for an invalid shape
64  }];
65}
66
67def Shape_SizeType : Shape_Type<"Size", "size"> {
68  let description = [{
69    `shape.size` represents a non-negative integer with support for being
70    unknown and invalid.
71
72    Operations on `shape.size` types are specialized to handle unknown/dynamic
73    value. So, for example, `<unknown> + x == <unknown>` for all non-error `x :
74    !shape.size` (e.g., an unknown value does not become known due to addition).
75  }];
76}
77
78def Shape_ValueShapeType : Shape_Type<"ValueShape", "value_shape"> {
79  let description = [{
80    `shape.value_shape` represents the value produced by an operation (this
81    corresponds to `Value` in the compiler) and a shape. Conceptually this is a
82    tuple of a value (potentially unknown) and `shape.shape`. The value and
83    shape can either or both be unknown. If both the `value` and `shape` are
84    known, then the shape of `value` is conformant with `shape`. That is, the
85    shape of the value conforms to the shape of the ValueShape, so that if we
86    have ValueShape `(value, shape)` then `join(shape_of(value), shape)` would
87    be error free and in particular it means that if both are statically known,
88    then they are equal.
89  }];
90}
91
92def Shape_ExtentTensorType :
93    1DTensorOf<[Index]>,
94    BuildableType<"::mlir::RankedTensorType::get({ShapedType::kDynamic}, "
95                  "$_builder.getType<::mlir::IndexType>())"> {
96  let description = [{
97    The extent tensor is a tensor of rank one with arbitrarily many index
98    elements (tensor<?xindex>). Like `!shape.shape`, it is used to represent
99    shapes with the difference that it is guaranteed to be error-free.
100  }];
101}
102
103def Shape_ShapeOrSizeType : AnyTypeOf<[Shape_SizeType, Shape_ShapeType],
104  "shape or size">;
105
106def Shape_ShapeOrExtentTensorType : AnyTypeOf<[Shape_ShapeType,
107                                               Shape_ExtentTensorType],
108                                              "shape or extent tensor">;
109
110def Shape_SizeOrIndexType : AnyTypeOf<[Shape_SizeType, Index], "size or index">;
111
112// Any type representing a shape or size/dim.
113def Shape_AnyShapeOrSizeType : AnyTypeOf<
114    [Shape_SizeOrIndexType, Shape_ShapeOrExtentTensorType],
115  "any shape or size">;
116
117def Shape_WitnessType : Shape_Type<"Witness", "witness"> {
118  let description = [{
119    A witness is a structural device in the compiler to maintain ordering of
120    code relying on information obtained from passing assertions. Witnesses do
121    not represent any physical data.
122
123    "cstr_" operations will return witnesses and be lowered into assertion logic
124    when not resolvable at compile time.
125
126    "assuming_" operations will take witnesses as input and represent only
127    information to the compiler, so they do not exist in executing code. Code
128    that is dependent on "assuming_" operations can assume all cstr operations
129    transitively before are honored as true.
130
131    These abstractions are intended to allow the compiler more freedom with
132    assertions by merely showing the assertion through dataflow at this time
133    rather than a side effecting operation that acts as a barrier. This can be
134    viewed similarly to a compiler representation of promises from asynchronous,
135    possibly crashing assertions. Reliant code will not be reordered to before
136    the code and non-reliant code can be reordered freely, and there are no
137    guarantees on the final ordering of the assertions or their related code.
138  }];
139}
140
141#endif // SHAPE_BASE_TD
142