[Mlir-commits] [mlir] 0d01dfb - [mlir][IR][NFC] Move the remaining builtin types to ODS

River Riddle llvmlistbot at llvm.org
Mon Mar 8 14:32:55 PST 2021


Author: River Riddle
Date: 2021-03-08T14:32:40-08:00
New Revision: 0d01dfbc377a259e6d2cf318dd2bdb82da44ad1a

URL: https://github.com/llvm/llvm-project/commit/0d01dfbc377a259e6d2cf318dd2bdb82da44ad1a
DIFF: https://github.com/llvm/llvm-project/commit/0d01dfbc377a259e6d2cf318dd2bdb82da44ad1a.diff

LOG: [mlir][IR][NFC] Move the remaining builtin types to ODS

This will allow for removing the duplicated type documentation from LangRef and instead link to the builtin dialect documentation.

Differential Revision: https://reviews.llvm.org/D98093

Added: 
    

Modified: 
    mlir/include/mlir/IR/BuiltinTypes.h
    mlir/include/mlir/IR/BuiltinTypes.td
    mlir/include/mlir/IR/OpBase.td
    mlir/lib/IR/BuiltinTypes.cpp
    mlir/lib/IR/TypeDetail.h

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/IR/BuiltinTypes.h b/mlir/include/mlir/IR/BuiltinTypes.h
index 61836b11fee8e..039ef47bc4cbb 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.h
+++ b/mlir/include/mlir/IR/BuiltinTypes.h
@@ -22,22 +22,8 @@ class FloatType;
 class Identifier;
 class IndexType;
 class IntegerType;
-class Location;
-class MLIRContext;
 class TypeRange;
 
-namespace detail {
-
-struct BaseMemRefTypeStorage;
-struct MemRefTypeStorage;
-struct RankedTensorTypeStorage;
-struct ShapedTypeStorage;
-struct UnrankedMemRefTypeStorage;
-struct UnrankedTensorTypeStorage;
-struct VectorTypeStorage;
-
-} // namespace detail
-
 //===----------------------------------------------------------------------===//
 // FloatType
 //===----------------------------------------------------------------------===//
@@ -78,7 +64,6 @@ class FloatType : public Type {
 /// from ShapedType.
 class ShapedType : public Type {
 public:
-  using ImplType = detail::ShapedTypeStorage;
   using Type::Type;
 
   // TODO: merge these two special values in a single one used everywhere.
@@ -157,46 +142,6 @@ class ShapedType : public Type {
   }
 };
 
-//===----------------------------------------------------------------------===//
-// VectorType
-//===----------------------------------------------------------------------===//
-
-/// Vector types represent multi-dimensional SIMD vectors, and have a fixed
-/// known constant shape with one or more dimension.
-class VectorType
-    : public Type::TypeBase<VectorType, ShapedType, detail::VectorTypeStorage> {
-public:
-  using Base::Base;
-  using Base::getChecked;
-
-  /// Get or create a new VectorType of the provided shape and element type.
-  /// Assumes the arguments define a well-formed VectorType.
-  static VectorType get(ArrayRef<int64_t> shape, Type elementType);
-
-  /// Get or create a new VectorType of the provided shape and element type. If
-  /// the VectorType defined by the arguments would be ill-formed, an error is
-  /// emitted to `emitError` and a null type is returned.
-  static VectorType getChecked(function_ref<InFlightDiagnostic()> emitError,
-                               ArrayRef<int64_t> shape, Type elementType);
-
-  /// Verify the construction of a vector type.
-  static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
-                              ArrayRef<int64_t> shape, Type elementType);
-
-  /// Returns true of the given type can be used as an element of a vector type.
-  /// In particular, vectors can consist of integer or float primitives.
-  static bool isValidElementType(Type t) {
-    return t.isa<IntegerType, FloatType>();
-  }
-
-  ArrayRef<int64_t> getShape() const;
-
-  /// Get or create a new VectorType with the same shape as `this` and an
-  /// element type of bitwidth scaled by `scale`.
-  /// Return null if the scaled element type cannot be represented.
-  VectorType scaleElementBitwidth(unsigned scale);
-};
-
 //===----------------------------------------------------------------------===//
 // TensorType
 //===----------------------------------------------------------------------===//
@@ -214,68 +159,6 @@ class TensorType : public ShapedType {
   static bool classof(Type type);
 };
 
-//===----------------------------------------------------------------------===//
-// RankedTensorType
-
-/// Ranked tensor types represent multi-dimensional arrays that have a shape
-/// with a fixed number of dimensions. Each shape element can be a non-negative
-/// integer or unknown (represented by -1).
-class RankedTensorType
-    : public Type::TypeBase<RankedTensorType, TensorType,
-                            detail::RankedTensorTypeStorage> {
-public:
-  using Base::Base;
-  using Base::getChecked;
-
-  /// Get or create a new RankedTensorType of the provided shape and element
-  /// type. Assumes the arguments define a well-formed type.
-  static RankedTensorType get(ArrayRef<int64_t> shape, Type elementType);
-
-  /// Get or create a new RankedTensorType of the provided shape and element
-  /// type. If the RankedTensorType defined by the arguments would be
-  /// ill-formed, an error is emitted to `emitError` and a null type is
-  /// returned.
-  static RankedTensorType
-  getChecked(function_ref<InFlightDiagnostic()> emitError,
-             ArrayRef<int64_t> shape, Type elementType);
-
-  /// Verify the construction of a ranked tensor type.
-  static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
-                              ArrayRef<int64_t> shape, Type elementType);
-
-  ArrayRef<int64_t> getShape() const;
-};
-
-//===----------------------------------------------------------------------===//
-// UnrankedTensorType
-
-/// Unranked tensor types represent multi-dimensional arrays that have an
-/// unknown shape.
-class UnrankedTensorType
-    : public Type::TypeBase<UnrankedTensorType, TensorType,
-                            detail::UnrankedTensorTypeStorage> {
-public:
-  using Base::Base;
-  using Base::getChecked;
-
-  /// Get or create a new UnrankedTensorType of the provided shape and element
-  /// type. Assumes the arguments define a well-formed type.
-  static UnrankedTensorType get(Type elementType);
-
-  /// Get or create a new UnrankedTensorType of the provided shape and element
-  /// type. If the RankedTensorType defined by the arguments would be
-  /// ill-formed, an error is emitted to `emitError` and a null type is
-  /// returned.
-  static UnrankedTensorType
-  getChecked(function_ref<InFlightDiagnostic()> emitError, Type elementType);
-
-  /// Verify the construction of a unranked tensor type.
-  static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
-                              Type elementType);
-
-  ArrayRef<int64_t> getShape() const { return llvm::None; }
-};
-
 //===----------------------------------------------------------------------===//
 // BaseMemRefType
 //===----------------------------------------------------------------------===//
@@ -283,7 +166,6 @@ class UnrankedTensorType
 /// Base MemRef for Ranked and Unranked variants
 class BaseMemRefType : public ShapedType {
 public:
-  using ImplType = detail::BaseMemRefTypeStorage;
   using ShapedType::ShapedType;
 
   /// Return true if the specified element type is ok in a memref.
@@ -296,149 +178,69 @@ class BaseMemRefType : public ShapedType {
   unsigned getMemorySpaceAsInt() const;
 };
 
+} // end namespace mlir
+
+//===----------------------------------------------------------------------===//
+// Tablegen Type Declarations
+//===----------------------------------------------------------------------===//
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/IR/BuiltinTypes.h.inc"
+
+namespace mlir {
 //===----------------------------------------------------------------------===//
 // MemRefType
+//===----------------------------------------------------------------------===//
 
-/// MemRef types represent a region of memory that have a shape with a fixed
-/// number of dimensions. Each shape element can be a non-negative integer or
-/// unknown (represented by -1). MemRef types also have an affine map
-/// composition, represented as an array AffineMap pointers.
-class MemRefType : public Type::TypeBase<MemRefType, BaseMemRefType,
-                                         detail::MemRefTypeStorage> {
+/// This is a builder type that keeps local references to arguments. Arguments
+/// that are passed into the builder must out-live the builder.
+class MemRefType::Builder {
 public:
-  /// This is a builder type that keeps local references to arguments. Arguments
-  /// that are passed into the builder must out-live the builder.
-  class Builder {
-  public:
-    // Build from another MemRefType.
-    explicit Builder(MemRefType other)
-        : shape(other.getShape()), elementType(other.getElementType()),
-          affineMaps(other.getAffineMaps()),
-          memorySpace(other.getMemorySpaceAsInt()) {}
-
-    // Build from scratch.
-    Builder(ArrayRef<int64_t> shape, Type elementType)
-        : shape(shape), elementType(elementType), affineMaps(), memorySpace(0) {
-    }
-
-    Builder &setShape(ArrayRef<int64_t> newShape) {
-      shape = newShape;
-      return *this;
-    }
-
-    Builder &setElementType(Type newElementType) {
-      elementType = newElementType;
-      return *this;
-    }
-
-    Builder &setAffineMaps(ArrayRef<AffineMap> newAffineMaps) {
-      affineMaps = newAffineMaps;
-      return *this;
-    }
-
-    Builder &setMemorySpace(unsigned newMemorySpace) {
-      memorySpace = newMemorySpace;
-      return *this;
-    }
-
-    operator MemRefType() {
-      return MemRefType::get(shape, elementType, affineMaps, memorySpace);
-    }
-
-  private:
-    ArrayRef<int64_t> shape;
-    Type elementType;
-    ArrayRef<AffineMap> affineMaps;
-    unsigned memorySpace;
-  };
-
-  using Base::Base;
-  using Base::getChecked;
-
-  /// Get or create a new MemRefType based on shape, element type, affine
-  /// map composition, and memory space.  Assumes the arguments define a
-  /// well-formed MemRef type.  Use getChecked to gracefully handle MemRefType
-  /// construction failures.
-  static MemRefType get(ArrayRef<int64_t> shape, Type elementType,
-                        ArrayRef<AffineMap> affineMapComposition = {},
-                        unsigned memorySpace = 0);
-
-  /// Get or create a new MemRefType based on shape, element type, affine
-  /// map composition, and memory space. If the MemRefType defined by the
-  /// arguments would be ill-formed, an error is emitted to `emitError` and a
-  /// null type is returned.
-  static MemRefType getChecked(function_ref<InFlightDiagnostic()> emitError,
-                               ArrayRef<int64_t> shape, Type elementType,
-                               ArrayRef<AffineMap> affineMapComposition,
-                               unsigned memorySpace);
-
-  ArrayRef<int64_t> getShape() const;
+  // Build from another MemRefType.
+  explicit Builder(MemRefType other)
+      : shape(other.getShape()), elementType(other.getElementType()),
+        affineMaps(other.getAffineMaps()),
+        memorySpace(other.getMemorySpaceAsInt()) {}
+
+  // Build from scratch.
+  Builder(ArrayRef<int64_t> shape, Type elementType)
+      : shape(shape), elementType(elementType), affineMaps(), memorySpace(0) {}
+
+  Builder &setShape(ArrayRef<int64_t> newShape) {
+    shape = newShape;
+    return *this;
+  }
 
-  /// Returns an array of affine map pointers representing the memref affine
-  /// map composition.
-  ArrayRef<AffineMap> getAffineMaps() const;
+  Builder &setElementType(Type newElementType) {
+    elementType = newElementType;
+    return *this;
+  }
 
-  // TODO: merge these two special values in a single one used everywhere.
-  // Unfortunately, uses of `-1` have crept deep into the codebase now and are
-  // hard to track.
-  static int64_t getDynamicStrideOrOffset() {
-    return ShapedType::kDynamicStrideOrOffset;
+  Builder &setAffineMaps(ArrayRef<AffineMap> newAffineMaps) {
+    affineMaps = newAffineMaps;
+    return *this;
   }
 
-private:
-  /// Get or create a new MemRefType defined by the arguments.  If the resulting
-  /// type would be ill-formed, return nullptr.
-  static MemRefType getImpl(ArrayRef<int64_t> shape, Type elementType,
-                            ArrayRef<AffineMap> affineMapComposition,
-                            unsigned memorySpace,
-                            function_ref<InFlightDiagnostic()> emitError);
-  using Base::getImpl;
-};
+  Builder &setMemorySpace(unsigned newMemorySpace) {
+    memorySpace = newMemorySpace;
+    return *this;
+  }
 
-//===----------------------------------------------------------------------===//
-// UnrankedMemRefType
+  operator MemRefType() {
+    return MemRefType::get(shape, elementType, affineMaps, memorySpace);
+  }
 
-/// Unranked MemRef type represent multi-dimensional MemRefs that
-/// have an unknown rank.
-class UnrankedMemRefType
-    : public Type::TypeBase<UnrankedMemRefType, BaseMemRefType,
-                            detail::UnrankedMemRefTypeStorage> {
-public:
-  using Base::Base;
-  using Base::getChecked;
-
-  /// Get or create a new UnrankedMemRefType of the provided element
-  /// type and memory space
-  static UnrankedMemRefType get(Type elementType, unsigned memorySpace);
-
-  /// Get or create a new UnrankedMemRefType of the provided element
-  /// type and memory space. If the UnrankedMemRefType defined by the arguments
-  /// would be ill-formed, an error is emitted to `emitError` and a null type is
-  /// returned.
-  static UnrankedMemRefType
-  getChecked(function_ref<InFlightDiagnostic()> emitError, Type elementType,
-             unsigned memorySpace);
-
-  /// Verify the construction of a unranked memref type.
-  static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
-                              Type elementType, unsigned memorySpace);
-
-  ArrayRef<int64_t> getShape() const { return llvm::None; }
+private:
+  ArrayRef<int64_t> shape;
+  Type elementType;
+  ArrayRef<AffineMap> affineMaps;
+  unsigned memorySpace;
 };
-} // end namespace mlir
-
-//===----------------------------------------------------------------------===//
-// Tablegen Type Declarations
-//===----------------------------------------------------------------------===//
-
-#define GET_TYPEDEF_CLASSES
-#include "mlir/IR/BuiltinTypes.h.inc"
 
 //===----------------------------------------------------------------------===//
 // Deferred Method Definitions
 //===----------------------------------------------------------------------===//
 
-namespace mlir {
 inline bool BaseMemRefType::classof(Type type) {
   return type.isa<MemRefType, UnrankedMemRefType>();
 }

diff  --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index 7f1bf618d17e7..9953eafae2914 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -21,7 +21,8 @@ include "mlir/IR/BuiltinDialect.td"
 // remove the definitions in OpBase.td, and repoint users to this file instead.
 
 // Base class for Builtin dialect types.
-class Builtin_Type<string name> : TypeDef<Builtin_Dialect, name> {
+class Builtin_Type<string name, string baseCppClass = "::mlir::Type">
+    : TypeDef<Builtin_Dialect, name, baseCppClass> {
   let mnemonic = ?;
 }
 
@@ -250,6 +251,316 @@ def Builtin_Integer : Builtin_Type<"Integer"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// MemRefType
+//===----------------------------------------------------------------------===//
+
+def Builtin_MemRef : Builtin_Type<"MemRef", "BaseMemRefType"> {
+  let summary = "Shaped reference to a region of memory";
+  let description = [{
+    Syntax:
+
+    ```
+    memref-type ::= `memref` `<` dimension-list-ranked type
+                    (`,` layout-specification)? (`,` memory-space)? `>`
+
+    stride-list ::= `[` (dimension (`,` dimension)*)? `]`
+    strided-layout ::= `offset:` dimension `,` `strides: ` stride-list
+    semi-affine-map-composition ::= (semi-affine-map `,` )* semi-affine-map
+    layout-specification ::= semi-affine-map-composition | strided-layout
+    memory-space ::= integer-literal /* | TODO: address-space-id */
+    ```
+
+    A `memref` type is a reference to a region of memory (similar to a buffer
+    pointer, but more powerful). The buffer pointed to by a memref can be
+    allocated, aliased and deallocated. A memref can be used to read and write
+    data from/to the memory region which it references. Memref types use the
+    same shape specifier as tensor types. Note that `memref<f32>`,
+    `memref<0 x f32>`, `memref<1 x 0 x f32>`, and `memref<0 x 1 x f32>` are all
+    
diff erent types.
+
+    A `memref` is allowed to have an unknown rank (e.g. `memref<*xf32>`). The
+    purpose of unranked memrefs is to allow external library functions to
+    receive memref arguments of any rank without versioning the functions based
+    on the rank. Other uses of this type are disallowed or will have undefined
+    behavior.
+
+    ##### Codegen of Unranked Memref
+
+    Using unranked memref in codegen besides the case mentioned above is highly
+    discouraged. Codegen is concerned with generating loop nests and specialized
+    instructions for high-performance, unranked memref is concerned with hiding
+    the rank and thus, the number of enclosing loops required to iterate over
+    the data. However, if there is a need to code-gen unranked memref, one
+    possible path is to cast into a static ranked type based on the dynamic
+    rank. Another possible path is to emit a single while loop conditioned on a
+    linear index and perform delinearization of the linear index to a dynamic
+    array containing the (unranked) indices. While this is possible, it is
+    expected to not be a good idea to perform this during codegen as the cost
+    of the translations is expected to be prohibitive and optimizations at this
+    level are not expected to be worthwhile. If expressiveness is the main
+    concern, irrespective of performance, passing unranked memrefs to an
+    external C++ library and implementing rank-agnostic logic there is expected
+    to be significantly simpler.
+
+    Unranked memrefs may provide expressiveness gains in the future and help
+    bridge the gap with unranked tensors. Unranked memrefs will not be expected
+    to be exposed to codegen but one may query the rank of an unranked memref
+    (a special op will be needed for this purpose) and perform a switch and cast
+    to a ranked memref as a prerequisite to codegen.
+
+    Example:
+
+    ```mlir
+    // With static ranks, we need a function for each possible argument type
+    %A = alloc() : memref<16x32xf32>
+    %B = alloc() : memref<16x32x64xf32>
+    call @helper_2D(%A) : (memref<16x32xf32>)->()
+    call @helper_3D(%B) : (memref<16x32x64xf32>)->()
+
+    // With unknown rank, the functions can be unified under one unranked type
+    %A = alloc() : memref<16x32xf32>
+    %B = alloc() : memref<16x32x64xf32>
+    // Remove rank info
+    %A_u = memref_cast %A : memref<16x32xf32> -> memref<*xf32>
+    %B_u = memref_cast %B : memref<16x32x64xf32> -> memref<*xf32>
+    // call same function with dynamic ranks
+    call @helper(%A_u) : (memref<*xf32>)->()
+    call @helper(%B_u) : (memref<*xf32>)->()
+    ```
+
+    The core syntax and representation of a layout specification is a
+    [semi-affine map](Dialects/Affine.md#semi-affine-maps). Additionally,
+    syntactic sugar is supported to make certain layout specifications more
+    intuitive to read. For the moment, a `memref` supports parsing a strided
+    form which is converted to a semi-affine map automatically.
+
+    The memory space of a memref is specified by a target-specific integer
+    index. If no memory space is specified, then the default memory space (0)
+    is used. The default space is target specific but always at index 0.
+
+    TODO: MLIR will eventually have target-dialects which allow symbolic use of
+    memory hierarchy names (e.g. L3, L2, L1, ...) but we have not spec'd the
+    details of that mechanism yet. Until then, this document pretends that it
+    is valid to refer to these memories by `bare-id`.
+
+    The notionally dynamic value of a memref value includes the address of the
+    buffer allocated, as well as the symbols referred to by the shape, layout
+    map, and index maps.
+
+    Examples of memref static type
+
+    ```mlir
+    // Identity index/layout map
+    #identity = affine_map<(d0, d1) -> (d0, d1)>
+
+    // Column major layout.
+    #col_major = affine_map<(d0, d1, d2) -> (d2, d1, d0)>
+
+    // A 2-d tiled layout with tiles of size 128 x 256.
+    #tiled_2d_128x256 = affine_map<(d0, d1) -> (d0 div 128, d1 div 256, d0 mod 128, d1 mod 256)>
+
+    // A tiled data layout with non-constant tile sizes.
+    #tiled_dynamic = affine_map<(d0, d1)[s0, s1] -> (d0 floordiv s0, d1 floordiv s1,
+                                 d0 mod s0, d1 mod s1)>
+
+    // A layout that yields a padding on two at either end of the minor dimension.
+    #padded = affine_map<(d0, d1) -> (d0, (d1 + 2) floordiv 2, (d1 + 2) mod 2)>
+
+
+    // The dimension list "16x32" defines the following 2D index space:
+    //
+    //   { (i, j) : 0 <= i < 16, 0 <= j < 32 }
+    //
+    memref<16x32xf32, #identity>
+
+    // The dimension list "16x4x?" defines the following 3D index space:
+    //
+    //   { (i, j, k) : 0 <= i < 16, 0 <= j < 4, 0 <= k < N }
+    //
+    // where N is a symbol which represents the runtime value of the size of
+    // the third dimension.
+    //
+    // %N here binds to the size of the third dimension.
+    %A = alloc(%N) : memref<16x4x?xf32, #col_major>
+
+    // A 2-d dynamic shaped memref that also has a dynamically sized tiled
+    // layout. The memref index space is of size %M x %N, while %B1 and %B2
+    // bind to the symbols s0, s1 respectively of the layout map #tiled_dynamic.
+    // Data tiles of size %B1 x %B2 in the logical space will be stored
+    // contiguously in memory. The allocation size will be
+    // (%M ceildiv %B1) * %B1 * (%N ceildiv %B2) * %B2 f32 elements.
+    %T = alloc(%M, %N) [%B1, %B2] : memref<?x?xf32, #tiled_dynamic>
+
+    // A memref that has a two-element padding at either end. The allocation
+    // size will fit 16 * 64 float elements of data.
+    %P = alloc() : memref<16x64xf32, #padded>
+
+    // Affine map with symbol 's0' used as offset for the first dimension.
+    #imapS = affine_map<(d0, d1) [s0] -> (d0 + s0, d1)>
+    // Allocate memref and bind the following symbols:
+    // '%n' is bound to the dynamic second dimension of the memref type.
+    // '%o' is bound to the symbol 's0' in the affine map of the memref type.
+    %n = ...
+    %o = ...
+    %A = alloc (%n)[%o] : <16x?xf32, #imapS>
+    ```
+
+    ##### Index Space
+
+    A memref dimension list defines an index space within which the memref can
+    be indexed to access data.
+
+    ##### Index
+
+    Data is accessed through a memref type using a multidimensional index into
+    the multidimensional index space defined by the memref's dimension list.
+
+    Examples
+
+    ```mlir
+    // Allocates a memref with 2D index space:
+    //   { (i, j) : 0 <= i < 16, 0 <= j < 32 }
+    %A = alloc() : memref<16x32xf32, #imapA>
+
+    // Loads data from memref '%A' using a 2D index: (%i, %j)
+    %v = load %A[%i, %j] : memref<16x32xf32, #imapA>
+    ```
+
+    ##### Index Map
+
+    An index map is a one-to-one
+    [semi-affine map](Dialects/Affine.md#semi-affine-maps) that transforms a
+    multidimensional index from one index space to another. For example, the
+    following figure shows an index map which maps a 2-dimensional index from a
+    2x2 index space to a 3x3 index space, using symbols `S0` and `S1` as
+    offsets.
+
+    ![Index Map Example](/includes/img/index-map.svg)
+
+    The number of domain dimensions and range dimensions of an index map can be
+    
diff erent, but must match the number of dimensions of the input and output
+    index spaces on which the map operates. The index space is always
+    non-negative and integral. In addition, an index map must specify the size
+    of each of its range dimensions onto which it maps. Index map symbols must
+    be listed in order with symbols for dynamic dimension sizes first, followed
+    by other required symbols.
+
+    ##### Layout Map
+
+    A layout map is a [semi-affine map](Dialects/Affine.md#semi-affine-maps)
+    which encodes logical to physical index space mapping, by mapping input
+    dimensions to their ordering from most-major (slowest varying) to most-minor
+    (fastest varying). Therefore, an identity layout map corresponds to a
+    row-major layout. Identity layout maps do not contribute to the MemRef type
+    identification and are discarded on construction. That is, a type with an
+    explicit identity map is `memref<?x?xf32, (i,j)->(i,j)>` is strictly the
+    same as the one without layout maps, `memref<?x?xf32>`.
+
+    Layout map examples:
+
+    ```mlir
+    // MxN matrix stored in row major layout in memory:
+    #layout_map_row_major = (i, j) -> (i, j)
+
+    // MxN matrix stored in column major layout in memory:
+    #layout_map_col_major = (i, j) -> (j, i)
+
+    // MxN matrix stored in a 2-d blocked/tiled layout with 64x64 tiles.
+    #layout_tiled = (i, j) -> (i floordiv 64, j floordiv 64, i mod 64, j mod 64)
+    ```
+
+    ##### Affine Map Composition
+
+    A memref specifies a semi-affine map composition as part of its type. A
+    semi-affine map composition is a composition of semi-affine maps beginning
+    with zero or more index maps, and ending with a layout map. The composition
+    must be conformant: the number of dimensions of the range of one map, must
+    match the number of dimensions of the domain of the next map in the
+    composition.
+
+    The semi-affine map composition specified in the memref type, maps from
+    accesses used to index the memref in load/store operations to other index
+    spaces (i.e. logical to physical index mapping). Each of the
+    [semi-affine maps](Affine.md) and thus its composition is required
+    to be one-to-one.
+
+    The semi-affine map composition can be used in dependence analysis, memory
+    access pattern analysis, and for performance optimizations like
+    vectorization, copy elision and in-place updates. If an affine map
+    composition is not specified for the memref, the identity affine map is
+    assumed.
+
+    ##### Strided MemRef
+
+    A memref may specify strides as part of its type. A stride specification is
+    a list of integer values that are either static or `?` (dynamic case).
+    Strides encode the distance, in number of elements, in (linear) memory
+    between successive entries along a particular dimension. A stride
+    specification is syntactic sugar for an equivalent strided memref
+    representation using semi-affine maps. For example,
+    `memref<42x16xf32, offset: 33, strides: [1, 64]>` specifies a non-contiguous
+    memory region of `42` by `16` `f32` elements such that:
+
+    1.  the minimal size of the enclosing memory region must be
+        `33 + 42 * 1 + 16 * 64 = 1066` elements;
+    2.  the address calculation for accessing element `(i, j)` computes
+        `33 + i + 64 * j`
+    3.  the distance between two consecutive elements along the inner dimension
+        is `1` element and the distance between two consecutive elements along
+        the outer dimension is `64` elements.
+
+    This corresponds to a column major view of the memory region and is
+    internally represented as the type
+    `memref<42x16xf32, (i, j) -> (33 + i + 64 * j)>`.
+
+    The specification of strides must not alias: given an n-D strided memref,
+    indices `(i1, ..., in)` and `(j1, ..., jn)` may not refer to the same memory
+    address unless `i1 == j1, ..., in == jn`.
+
+    Strided memrefs represent a view abstraction over preallocated data. They
+    are constructed with special ops, yet to be introduced. Strided memrefs are
+    a special subclass of memrefs with generic semi-affine map and correspond to
+    a normalized memref descriptor when lowering to LLVM.
+  }];
+  let parameters = (ins
+    ArrayRefParameter<"int64_t">:$shape,
+    "Type":$elementType,
+    ArrayRefParameter<"AffineMap">:$affineMaps,
+    "unsigned":$memorySpaceAsInt
+  );
+
+  let builders = [
+    TypeBuilderWithInferredContext<(ins
+      "ArrayRef<int64_t>":$shape, "Type":$elementType,
+      CArg<"ArrayRef<AffineMap>", "{}">:$affineMaps,
+      CArg<"unsigned", "0">:$memorySpace
+    ), [{
+      // Drop identity maps from the composition. This may lead to the
+      // composition becoming empty, which is interpreted as an implicit
+      // identity.
+      auto nonIdentityMaps = llvm::make_filter_range(affineMaps,
+        [](AffineMap map) { return !map.isIdentity(); });
+      return $_get(elementType.getContext(), shape, elementType,
+                   llvm::to_vector<4>(nonIdentityMaps), memorySpace);
+    }]>
+  ];
+  let extraClassDeclaration = [{
+    /// This is a builder type that keeps local references to arguments.
+    /// Arguments that are passed into the builder must out-live the builder.
+    class Builder;
+
+    // TODO: merge these two special values in a single one used everywhere.
+    // Unfortunately, uses of `-1` have crept deep into the codebase now and are
+    // hard to track.
+    static int64_t getDynamicStrideOrOffset() {
+      return ShapedType::kDynamicStrideOrOffset;
+    }
+  }];
+  let skipDefaultBuilders = 1;
+  let genVerifyDecl = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // NoneType
 //===----------------------------------------------------------------------===//
@@ -305,6 +616,79 @@ def Builtin_Opaque : Builtin_Type<"Opaque"> {
   let genVerifyDecl = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// RankedTensorType
+//===----------------------------------------------------------------------===//
+
+def Builtin_RankedTensor : Builtin_Type<"RankedTensor", "TensorType"> {
+  let summary = "Multi-dimensional array with a fixed number of dimensions";
+  let description = [{
+    Syntax:
+
+    ```
+    tensor-type ::= `tensor` `<` dimension-list type `>`
+    dimension-list ::= (dimension `x`)*
+    dimension ::= `?` | decimal-literal
+    ```
+
+    Values with tensor type represents aggregate N-dimensional data values, and
+    have a known element type and a fixed rank with a list of dimensions. Each
+    dimension may be a static non-negative decimal constant or be dynamically
+    determined (indicated by `?`).
+
+    The runtime representation of the MLIR tensor type is intentionally
+    abstracted - you cannot control layout or get a pointer to the data. For
+    low level buffer access, MLIR has a [`memref` type](#memref-type). This
+    abstracted runtime representation holds both the tensor data values as well
+    as information about the (potentially dynamic) shape of the tensor. The
+    [`dim` operation](Dialects/Standard.md#dim-operation) returns the size of a
+    dimension from a value of tensor type.
+
+    Note: hexadecimal integer literals are not allowed in tensor type
+    declarations to avoid confusion between `0xf32` and `0 x f32`. Zero sizes
+    are allowed in tensors and treated as other sizes, e.g.,
+    `tensor<0 x 1 x i32>` and `tensor<1 x 0 x i32>` are 
diff erent types. Since
+    zero sizes are not allowed in some other types, such tensors should be
+    optimized away before lowering tensors to vectors.
+
+    Examples:
+
+    ```mlir
+    // Known rank but unknown dimensions.
+    tensor<? x ? x ? x ? x f32>
+
+    // Partially known dimensions.
+    tensor<? x ? x 13 x ? x f32>
+
+    // Full static shape.
+    tensor<17 x 4 x 13 x 4 x f32>
+
+    // Tensor with rank zero. Represents a scalar.
+    tensor<f32>
+
+    // Zero-element dimensions are allowed.
+    tensor<0 x 42 x f32>
+
+    // Zero-element tensor of f32 type (hexadecimal literals not allowed here).
+    tensor<0xf32>
+    ```
+  }];
+  let parameters = (ins
+    ArrayRefParameter<"int64_t">:$shape,
+    "Type":$elementType
+  );
+
+  let builders = [
+    TypeBuilderWithInferredContext<(ins
+      "ArrayRef<int64_t>":$shape, "Type":$elementType
+    ), [{
+      return $_get(elementType.getContext(), shape, elementType);
+    }]>
+  ];
+  let skipDefaultBuilders = 1;
+  let genVerifyDecl = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // TupleType
 //===----------------------------------------------------------------------===//
@@ -372,4 +756,149 @@ def Builtin_Tuple : Builtin_Type<"Tuple"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// UnrankedMemRefType
+//===----------------------------------------------------------------------===//
+
+def Builtin_UnrankedMemRef : Builtin_Type<"UnrankedMemRef", "BaseMemRefType"> {
+  let summary = "Shaped reference, with unknown rank, to a region of memory";
+  let description = [{
+    Syntax:
+
+    ```
+    unranked-memref-type ::= `memref` `<*x` type (`,` memory-space)? `>`
+    memory-space ::= integer-literal /* | TODO: address-space-id */
+    ```
+
+    A `memref` type with an unknown rank (e.g. `memref<*xf32>`). The purpose of
+    unranked memrefs is to allow external library functions to receive memref
+    arguments of any rank without versioning the functions based on the rank.
+    Other uses of this type are disallowed or will have undefined behavior.
+
+    See [MemRefType](#builtin_memref-memreftype) for more information on
+    memref types.
+
+    Examples:
+
+    ```mlir
+    memref<*f32>
+
+    // An unranked memref with a memory space of 10.
+    memref<*f32, 10>
+    ```
+  }];
+  let parameters = (ins "Type":$elementType, "unsigned":$memorySpaceAsInt);
+
+  let builders = [
+    TypeBuilderWithInferredContext<(ins "Type":$elementType,
+                                        "unsigned":$memorySpace), [{
+      return $_get(elementType.getContext(), elementType, memorySpace);
+    }]>
+  ];
+  let extraClassDeclaration = [{
+    ArrayRef<int64_t> getShape() const { return llvm::None; }
+  }];
+  let skipDefaultBuilders = 1;
+  let genVerifyDecl = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// UnrankedTensorType
+//===----------------------------------------------------------------------===//
+
+def Builtin_UnrankedTensor : Builtin_Type<"UnrankedTensor", "TensorType"> {
+  let summary = "Multi-dimensional array with unknown dimensions";
+  let description = [{
+    Syntax:
+
+    ```
+    tensor-type ::= `tensor` `<` `*` `x` type `>`
+    ```
+
+    An unranked tensor is a type of tensor in which the set of dimensions have
+    unknown rank. See [RankedTensorType](#builtin_rankedtensor-rankedtensortype)
+    for more information on tensor types.
+
+    Examples:
+
+    ```mlir
+    tensor<*f32>
+    ```
+  }];
+  let parameters = (ins "Type":$elementType);
+
+  let builders = [
+    TypeBuilderWithInferredContext<(ins "Type":$elementType), [{
+      return $_get(elementType.getContext(), elementType);
+    }]>
+  ];
+  let extraClassDeclaration = [{
+    ArrayRef<int64_t> getShape() const { return llvm::None; }
+  }];
+  let skipDefaultBuilders = 1;
+  let genVerifyDecl = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// VectorType
+//===----------------------------------------------------------------------===//
+
+def Builtin_Vector : Builtin_Type<"Vector", "ShapedType"> {
+  let summary = "Multi-dimensional SIMD vector type";
+  let description = [{
+    Syntax:
+
+    ```
+    vector-type ::= `vector` `<` static-dimension-list vector-element-type `>`
+    vector-element-type ::= float-type | integer-type
+
+    static-dimension-list ::= (decimal-literal `x`)+
+    ```
+
+    The vector type represents a SIMD style vector, used by target-specific
+    operation sets like AVX. While the most common use is for 1D vectors (e.g.
+    vector<16 x f32>) we also support multidimensional registers on targets that
+    support them (like TPUs).
+
+    Vector shapes must be positive decimal integers.
+
+    Note: hexadecimal integer literals are not allowed in vector type
+    declarations, `vector<0x42xi32>` is invalid because it is interpreted as a
+    2D vector with shape `(0, 42)` and zero shapes are not allowed.
+
+
+    Examples:
+
+    ```mlir
+    vector<3x42xi32>
+    ```
+  }];
+  let parameters = (ins
+    ArrayRefParameter<"int64_t">:$shape,
+    "Type":$elementType
+  );
+
+  let builders = [
+    TypeBuilderWithInferredContext<(ins
+      "ArrayRef<int64_t>":$shape, "Type":$elementType
+    ), [{
+      return $_get(elementType.getContext(), shape, elementType);
+    }]>
+  ];
+  let extraClassDeclaration = [{
+    /// Returns true of the given type can be used as an element of a vector
+    /// type. In particular, vectors can consist of integer or float primitives.
+    static bool isValidElementType(Type t) {
+      return t.isa<IntegerType, FloatType>();
+    }
+
+    /// Get or create a new VectorType with the same shape as `this` and an
+    /// element type of bitwidth scaled by `scale`.
+    /// Return null if the scaled element type cannot be represented.
+    VectorType scaleElementBitwidth(unsigned scale);
+  }];
+  let skipDefaultBuilders = 1;
+  let genVerifyDecl = 1;
+}
+
 #endif // BUILTIN_TYPES

diff  --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
index c18034c47d4f7..7e68896531306 100644
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -2684,13 +2684,13 @@ class AttrParameter<string type, string desc> : AttrOrTypeParameter<type, desc>;
 class TypeParameter<string type, string desc> : AttrOrTypeParameter<type, desc>;
 
 // For StringRefs, which require allocation.
-class StringRefParameter<string desc> :
+class StringRefParameter<string desc = ""> :
     AttrOrTypeParameter<"::llvm::StringRef", desc> {
   let allocator = [{$_dst = $_allocator.copyInto($_self);}];
 }
 
 // For standard ArrayRefs, which require allocation.
-class ArrayRefParameter<string arrayOf, string desc> :
+class ArrayRefParameter<string arrayOf, string desc = ""> :
     AttrOrTypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
   let allocator = [{$_dst = $_allocator.copyInto($_self);}];
 }

diff  --git a/mlir/lib/IR/BuiltinTypes.cpp b/mlir/lib/IR/BuiltinTypes.cpp
index c84569a535319..48afa791f43b1 100644
--- a/mlir/lib/IR/BuiltinTypes.cpp
+++ b/mlir/lib/IR/BuiltinTypes.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/ADT/TypeSwitch.h"
 
 using namespace mlir;
 using namespace mlir::detail;
@@ -266,7 +267,9 @@ ShapedType ShapedType::clone(Type elementType) {
 }
 
 Type ShapedType::getElementType() const {
-  return static_cast<ImplType *>(impl)->elementType;
+  return TypeSwitch<Type, Type>(*this)
+      .Case<VectorType, RankedTensorType, UnrankedTensorType, MemRefType,
+            UnrankedMemRefType>([](auto ty) { return ty.getElementType(); });
 }
 
 unsigned ShapedType::getElementTypeBitWidth() const {
@@ -357,16 +360,6 @@ bool ShapedType::hasStaticShape(ArrayRef<int64_t> shape) const {
 // VectorType
 //===----------------------------------------------------------------------===//
 
-VectorType VectorType::get(ArrayRef<int64_t> shape, Type elementType) {
-  return Base::get(elementType.getContext(), shape, elementType);
-}
-
-VectorType VectorType::getChecked(function_ref<InFlightDiagnostic()> emitError,
-                                  ArrayRef<int64_t> shape, Type elementType) {
-  return Base::getChecked(emitError, elementType.getContext(), shape,
-                          elementType);
-}
-
 LogicalResult VectorType::verify(function_ref<InFlightDiagnostic()> emitError,
                                  ArrayRef<int64_t> shape, Type elementType) {
   if (shape.empty())
@@ -381,8 +374,6 @@ LogicalResult VectorType::verify(function_ref<InFlightDiagnostic()> emitError,
   return success();
 }
 
-ArrayRef<int64_t> VectorType::getShape() const { return getImpl()->getShape(); }
-
 VectorType VectorType::scaleElementBitwidth(unsigned scale) {
   if (!scale)
     return VectorType();
@@ -422,46 +413,19 @@ bool TensorType::isValidElementType(Type type) {
 // RankedTensorType
 //===----------------------------------------------------------------------===//
 
-RankedTensorType RankedTensorType::get(ArrayRef<int64_t> shape,
-                                       Type elementType) {
-  return Base::get(elementType.getContext(), shape, elementType);
-}
-
-RankedTensorType
-RankedTensorType::getChecked(function_ref<InFlightDiagnostic()> emitError,
-                             ArrayRef<int64_t> shape, Type elementType) {
-  return Base::getChecked(emitError, elementType.getContext(), shape,
-                          elementType);
-}
-
 LogicalResult
 RankedTensorType::verify(function_ref<InFlightDiagnostic()> emitError,
                          ArrayRef<int64_t> shape, Type elementType) {
-  for (int64_t s : shape) {
+  for (int64_t s : shape)
     if (s < -1)
       return emitError() << "invalid tensor dimension size";
-  }
   return checkTensorElementType(emitError, elementType);
 }
 
-ArrayRef<int64_t> RankedTensorType::getShape() const {
-  return getImpl()->getShape();
-}
-
 //===----------------------------------------------------------------------===//
 // UnrankedTensorType
 //===----------------------------------------------------------------------===//
 
-UnrankedTensorType UnrankedTensorType::get(Type elementType) {
-  return Base::get(elementType.getContext(), elementType);
-}
-
-UnrankedTensorType
-UnrankedTensorType::getChecked(function_ref<InFlightDiagnostic()> emitError,
-                               Type elementType) {
-  return Base::getChecked(emitError, elementType.getContext(), elementType);
-}
-
 LogicalResult
 UnrankedTensorType::verify(function_ref<InFlightDiagnostic()> emitError,
                            Type elementType) {
@@ -473,115 +437,50 @@ UnrankedTensorType::verify(function_ref<InFlightDiagnostic()> emitError,
 //===----------------------------------------------------------------------===//
 
 unsigned BaseMemRefType::getMemorySpaceAsInt() const {
-  return static_cast<ImplType *>(impl)->memorySpace;
+  if (auto rankedMemRefTy = dyn_cast<MemRefType>())
+    return rankedMemRefTy.getMemorySpaceAsInt();
+  return cast<UnrankedMemRefType>().getMemorySpaceAsInt();
 }
 
 //===----------------------------------------------------------------------===//
 // MemRefType
 //===----------------------------------------------------------------------===//
 
-/// Get or create a new MemRefType based on shape, element type, affine
-/// map composition, and memory space.  Assumes the arguments define a
-/// well-formed MemRef type.  Use getChecked to gracefully handle MemRefType
-/// construction failures.
-MemRefType MemRefType::get(ArrayRef<int64_t> shape, Type elementType,
-                           ArrayRef<AffineMap> affineMapComposition,
-                           unsigned memorySpace) {
-  auto result =
-      getImpl(shape, elementType, affineMapComposition, memorySpace, [=] {
-        return emitError(UnknownLoc::get(elementType.getContext()));
-      });
-  assert(result && "Failed to construct instance of MemRefType.");
-  return result;
-}
-
-/// Get or create a new MemRefType based on shape, element type, affine
-/// map composition, and memory space declared at the given location.
-/// If the location is unknown, the last argument should be an instance of
-/// UnknownLoc.  If the MemRefType defined by the arguments would be
-/// ill-formed, emits errors (to the handler registered with the context or to
-/// the error stream) and returns nullptr.
-MemRefType MemRefType::getChecked(function_ref<InFlightDiagnostic()> emitError,
-                                  ArrayRef<int64_t> shape, Type elementType,
-                                  ArrayRef<AffineMap> affineMapComposition,
-                                  unsigned memorySpace) {
-  return getImpl(shape, elementType, affineMapComposition, memorySpace,
-                 emitError);
-}
-
-/// Get or create a new MemRefType defined by the arguments.  If the resulting
-/// type would be ill-formed, return nullptr.  If the location is provided,
-/// emit detailed error messages.  To emit errors when the location is unknown,
-/// pass in an instance of UnknownLoc.
-MemRefType MemRefType::getImpl(ArrayRef<int64_t> shape, Type elementType,
-                               ArrayRef<AffineMap> affineMapComposition,
-                               unsigned memorySpace,
-                               function_ref<InFlightDiagnostic()> emitError) {
-  auto *context = elementType.getContext();
-
+LogicalResult MemRefType::verify(function_ref<InFlightDiagnostic()> emitError,
+                                 ArrayRef<int64_t> shape, Type elementType,
+                                 ArrayRef<AffineMap> affineMapComposition,
+                                 unsigned memorySpace) {
   if (!BaseMemRefType::isValidElementType(elementType))
-    return (emitError() << "invalid memref element type", MemRefType());
+    return emitError() << "invalid memref element type";
 
-  for (int64_t s : shape) {
     // Negative sizes are not allowed except for `-1` that means dynamic size.
+  for (int64_t s : shape)
     if (s < -1)
-      return (emitError() << "invalid memref size", MemRefType());
-  }
+      return emitError() << "invalid memref size";
 
   // Check that the structure of the composition is valid, i.e. that each
   // subsequent affine map has as many inputs as the previous map has results.
   // Take the dimensionality of the MemRef for the first map.
-  auto dim = shape.size();
-  unsigned i = 0;
-  for (const auto &affineMap : affineMapComposition) {
-    if (affineMap.getNumDims() != dim) {
-      emitError() << "memref affine map dimension mismatch between "
-                  << (i == 0 ? Twine("memref rank") : "affine map " + Twine(i))
-                  << " and affine map" << i + 1 << ": " << dim
-                  << " != " << affineMap.getNumDims();
-      return nullptr;
-    }
-
-    dim = affineMap.getNumResults();
-    ++i;
-  }
-
-  // Drop identity maps from the composition.
-  // This may lead to the composition becoming empty, which is interpreted as an
-  // implicit identity.
-  SmallVector<AffineMap, 2> cleanedAffineMapComposition;
-  for (const auto &map : affineMapComposition) {
-    if (map.isIdentity())
+  size_t dim = shape.size();
+  for (auto it : llvm::enumerate(affineMapComposition)) {
+    AffineMap map = it.value();
+    if (map.getNumDims() == dim) {
+      dim = map.getNumResults();
       continue;
-    cleanedAffineMapComposition.push_back(map);
+    }
+    return emitError() << "memref affine map dimension mismatch between "
+                       << (it.index() == 0 ? Twine("memref rank")
+                                           : "affine map " + Twine(it.index()))
+                       << " and affine map" << it.index() + 1 << ": " << dim
+                       << " != " << map.getNumDims();
   }
-
-  return Base::get(context, shape, elementType, cleanedAffineMapComposition,
-                   memorySpace);
-}
-
-ArrayRef<int64_t> MemRefType::getShape() const { return getImpl()->getShape(); }
-
-ArrayRef<AffineMap> MemRefType::getAffineMaps() const {
-  return getImpl()->getAffineMaps();
+  return success();
 }
 
 //===----------------------------------------------------------------------===//
 // UnrankedMemRefType
 //===----------------------------------------------------------------------===//
 
-UnrankedMemRefType UnrankedMemRefType::get(Type elementType,
-                                           unsigned memorySpace) {
-  return Base::get(elementType.getContext(), elementType, memorySpace);
-}
-
-UnrankedMemRefType
-UnrankedMemRefType::getChecked(function_ref<InFlightDiagnostic()> emitError,
-                               Type elementType, unsigned memorySpace) {
-  return Base::getChecked(emitError, elementType.getContext(), elementType,
-                          memorySpace);
-}
-
 LogicalResult
 UnrankedMemRefType::verify(function_ref<InFlightDiagnostic()> emitError,
                            Type elementType, unsigned memorySpace) {

diff  --git a/mlir/lib/IR/TypeDetail.h b/mlir/lib/IR/TypeDetail.h
index 1973fdd60f008..694b161caba5a 100644
--- a/mlir/lib/IR/TypeDetail.h
+++ b/mlir/lib/IR/TypeDetail.h
@@ -23,8 +23,6 @@
 
 namespace mlir {
 
-class MLIRContext;
-
 namespace detail {
 
 /// Integer Type Storage and Uniquing.
@@ -96,175 +94,6 @@ struct FunctionTypeStorage : public TypeStorage {
   Type const *inputsAndResults;
 };
 
-/// Shaped Type Storage.
-struct ShapedTypeStorage : public TypeStorage {
-  ShapedTypeStorage(Type elementTy) : elementType(elementTy) {}
-
-  /// The hash key used for uniquing.
-  using KeyTy = Type;
-  bool operator==(const KeyTy &key) const { return key == elementType; }
-
-  Type elementType;
-};
-
-/// Vector Type Storage and Uniquing.
-struct VectorTypeStorage : public ShapedTypeStorage {
-  VectorTypeStorage(unsigned shapeSize, Type elementTy,
-                    const int64_t *shapeElements)
-      : ShapedTypeStorage(elementTy), shapeElements(shapeElements),
-        shapeSize(shapeSize) {}
-
-  /// The hash key used for uniquing.
-  using KeyTy = std::pair<ArrayRef<int64_t>, Type>;
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(getShape(), elementType);
-  }
-
-  /// Construction.
-  static VectorTypeStorage *construct(TypeStorageAllocator &allocator,
-                                      const KeyTy &key) {
-    // Copy the shape into the bump pointer.
-    ArrayRef<int64_t> shape = allocator.copyInto(key.first);
-
-    // Initialize the memory using placement new.
-    return new (allocator.allocate<VectorTypeStorage>())
-        VectorTypeStorage(shape.size(), key.second, shape.data());
-  }
-
-  ArrayRef<int64_t> getShape() const {
-    return ArrayRef<int64_t>(shapeElements, shapeSize);
-  }
-
-  const int64_t *shapeElements;
-  unsigned shapeSize;
-};
-
-struct RankedTensorTypeStorage : public ShapedTypeStorage {
-  RankedTensorTypeStorage(unsigned shapeSize, Type elementTy,
-                          const int64_t *shapeElements)
-      : ShapedTypeStorage(elementTy), shapeElements(shapeElements),
-        shapeSize(shapeSize) {}
-
-  /// The hash key used for uniquing.
-  using KeyTy = std::pair<ArrayRef<int64_t>, Type>;
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(getShape(), elementType);
-  }
-
-  /// Construction.
-  static RankedTensorTypeStorage *construct(TypeStorageAllocator &allocator,
-                                            const KeyTy &key) {
-    // Copy the shape into the bump pointer.
-    ArrayRef<int64_t> shape = allocator.copyInto(key.first);
-
-    // Initialize the memory using placement new.
-    return new (allocator.allocate<RankedTensorTypeStorage>())
-        RankedTensorTypeStorage(shape.size(), key.second, shape.data());
-  }
-
-  ArrayRef<int64_t> getShape() const {
-    return ArrayRef<int64_t>(shapeElements, shapeSize);
-  }
-
-  const int64_t *shapeElements;
-  unsigned shapeSize;
-};
-
-struct UnrankedTensorTypeStorage : public ShapedTypeStorage {
-  using ShapedTypeStorage::KeyTy;
-  using ShapedTypeStorage::ShapedTypeStorage;
-
-  /// Construction.
-  static UnrankedTensorTypeStorage *construct(TypeStorageAllocator &allocator,
-                                              Type elementTy) {
-    return new (allocator.allocate<UnrankedTensorTypeStorage>())
-        UnrankedTensorTypeStorage(elementTy);
-  }
-};
-
-struct BaseMemRefTypeStorage : public ShapedTypeStorage {
-  BaseMemRefTypeStorage(Type elementType, unsigned memorySpace)
-      : ShapedTypeStorage(elementType), memorySpace(memorySpace) {}
-
-  /// Memory space in which data referenced by memref resides.
-  const unsigned memorySpace;
-};
-
-struct MemRefTypeStorage : public BaseMemRefTypeStorage {
-  MemRefTypeStorage(unsigned shapeSize, Type elementType,
-                    const int64_t *shapeElements, const unsigned numAffineMaps,
-                    AffineMap const *affineMapList, const unsigned memorySpace)
-      : BaseMemRefTypeStorage(elementType, memorySpace),
-        shapeElements(shapeElements), shapeSize(shapeSize),
-        numAffineMaps(numAffineMaps), affineMapList(affineMapList) {}
-
-  /// The hash key used for uniquing.
-  // MemRefs are uniqued based on their shape, element type, affine map
-  // composition, and memory space.
-  using KeyTy =
-      std::tuple<ArrayRef<int64_t>, Type, ArrayRef<AffineMap>, unsigned>;
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(getShape(), elementType, getAffineMaps(), memorySpace);
-  }
-
-  /// Construction.
-  static MemRefTypeStorage *construct(TypeStorageAllocator &allocator,
-                                      const KeyTy &key) {
-    // Copy the shape into the bump pointer.
-    ArrayRef<int64_t> shape = allocator.copyInto(std::get<0>(key));
-
-    // Copy the affine map composition into the bump pointer.
-    ArrayRef<AffineMap> affineMapComposition =
-        allocator.copyInto(std::get<2>(key));
-
-    // Initialize the memory using placement new.
-    return new (allocator.allocate<MemRefTypeStorage>())
-        MemRefTypeStorage(shape.size(), std::get<1>(key), shape.data(),
-                          affineMapComposition.size(),
-                          affineMapComposition.data(), std::get<3>(key));
-  }
-
-  ArrayRef<int64_t> getShape() const {
-    return ArrayRef<int64_t>(shapeElements, shapeSize);
-  }
-
-  ArrayRef<AffineMap> getAffineMaps() const {
-    return ArrayRef<AffineMap>(affineMapList, numAffineMaps);
-  }
-
-  /// An array of integers which stores the shape dimension sizes.
-  const int64_t *shapeElements;
-  /// The number of shape elements.
-  unsigned shapeSize;
-  /// The number of affine maps in the 'affineMapList' array.
-  const unsigned numAffineMaps;
-  /// List of affine maps in the memref's layout/index map composition.
-  AffineMap const *affineMapList;
-};
-
-/// Unranked MemRef is a MemRef with unknown rank.
-/// Only element type and memory space are known
-struct UnrankedMemRefTypeStorage : public BaseMemRefTypeStorage {
-
-  UnrankedMemRefTypeStorage(Type elementTy, const unsigned memorySpace)
-      : BaseMemRefTypeStorage(elementTy, memorySpace) {}
-
-  /// The hash key used for uniquing.
-  using KeyTy = std::tuple<Type, unsigned>;
-  bool operator==(const KeyTy &key) const {
-    return key == KeyTy(elementType, memorySpace);
-  }
-
-  /// Construction.
-  static UnrankedMemRefTypeStorage *construct(TypeStorageAllocator &allocator,
-                                              const KeyTy &key) {
-
-    // Initialize the memory using placement new.
-    return new (allocator.allocate<UnrankedMemRefTypeStorage>())
-        UnrankedMemRefTypeStorage(std::get<0>(key), std::get<1>(key));
-  }
-};
-
 /// A type representing a collection of other types.
 struct TupleTypeStorage final
     : public TypeStorage,


        


More information about the Mlir-commits mailing list