[Mlir-commits] [mlir] 519847f - [mlir] materialize strided memref layout as attribute

Alex Zinenko llvmlistbot at llvm.org
Tue Aug 30 08:20:11 PDT 2022


Author: Alex Zinenko
Date: 2022-08-30T17:19:58+02:00
New Revision: 519847fefc6da1f82cffb44d31cb923f512557fe

URL: https://github.com/llvm/llvm-project/commit/519847fefc6da1f82cffb44d31cb923f512557fe
DIFF: https://github.com/llvm/llvm-project/commit/519847fefc6da1f82cffb44d31cb923f512557fe.diff

LOG: [mlir] materialize strided memref layout as attribute

Introduce a new attribute to represent the strided memref layout. Strided
layouts are omnipresent in code generation flows and are the only kind of
layouts produced and supported by a half of operation in the memref dialect
(view-related, shape-related). However, they are internally represented as
affine maps that require a somewhat fragile extraction of the strides from the
linear form that also comes with an overhead. Furthermore, textual
representation of strided layouts as affine maps is difficult to read: compare
`affine_map<(d0, d1, d2)[s0, s1] -> (d0*32 + d1*s0 + s1 + d2)>` with
`strides: [32, ?, 1], offset: ?`. While a rudimentary support for parsing a
syntactically sugared version of the strided layout has existed in the codebase
for a long time, it does not go as far as this commit to make the strided
layout a first-class attribute in the IR.

This introduces the attribute and updates the tests that using the pre-existing
sugared form to use the new attribute instead. Most memref created
programmatically, e.g., in passes, still use the affine form with further
extraction of strides and will be updated separately.

Update and clean-up the memref type documentation that has gotten stale and has
been referring to the details of affine map composition that are long gone.

See https://discourse.llvm.org/t/rfc-materialize-strided-memref-layout-as-an-attribute/64211.

Reviewed By: nicolasvasilache

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

Added: 
    mlir/test/Dialect/Builtin/types.mlir

Modified: 
    mlir/docs/Dialects/Linalg/_index.md
    mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
    mlir/include/mlir/IR/BuiltinAttributes.h
    mlir/include/mlir/IR/BuiltinAttributes.td
    mlir/include/mlir/IR/BuiltinTypes.h
    mlir/include/mlir/IR/BuiltinTypes.td
    mlir/lib/AsmParser/AttributeParser.cpp
    mlir/lib/AsmParser/Parser.h
    mlir/lib/AsmParser/TokenKinds.def
    mlir/lib/AsmParser/TypeParser.cpp
    mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
    mlir/lib/IR/AsmPrinter.cpp
    mlir/lib/IR/BuiltinAttributes.cpp
    mlir/lib/IR/BuiltinTypes.cpp
    mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir
    mlir/test/Conversion/FuncToSPIRV/types-to-spirv.mlir
    mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir
    mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
    mlir/test/Dialect/Affine/memref-stride-calculation.mlir
    mlir/test/Dialect/Affine/ops.mlir
    mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
    mlir/test/Dialect/Bufferization/canonicalize.mlir
    mlir/test/Dialect/Linalg/fusion-2-level.mlir
    mlir/test/Dialect/Linalg/fusion.mlir
    mlir/test/Dialect/Linalg/loops.mlir
    mlir/test/Dialect/Linalg/promote.mlir
    mlir/test/Dialect/Linalg/roundtrip.mlir
    mlir/test/Dialect/Linalg/standard.mlir
    mlir/test/Dialect/Linalg/tile-parallel.mlir
    mlir/test/Dialect/Linalg/tile.mlir
    mlir/test/Dialect/Linalg/transform-patterns.mlir
    mlir/test/Dialect/Linalg/transform-promotion.mlir
    mlir/test/Dialect/MemRef/canonicalize.mlir
    mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir
    mlir/test/Dialect/MemRef/invalid.mlir
    mlir/test/Dialect/MemRef/ops.mlir
    mlir/test/Dialect/MemRef/subview.mlir
    mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
    mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir
    mlir/test/Dialect/Vector/vector-transfer-flatten.mlir
    mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir
    mlir/test/IR/core-ops.mlir
    mlir/test/IR/invalid-builtin-types.mlir
    mlir/test/Integration/Dialect/Linalg/CPU/matmul-vs-matvec.mlir
    mlir/test/Integration/Dialect/Linalg/CPU/rank-reducing-subview.mlir
    mlir/test/Integration/Dialect/Standard/CPU/test_subview.mlir
    mlir/test/Integration/Dialect/Vector/CPU/test-transfer-read-1d.mlir
    mlir/test/Transforms/canonicalize.mlir
    mlir/test/mlir-cpu-runner/copy.mlir
    mlir/test/mlir-cpu-runner/memref-reinterpret-cast.mlir
    mlir/test/python/dialects/memref.py

Removed: 
    


################################################################################
diff  --git a/mlir/docs/Dialects/Linalg/_index.md b/mlir/docs/Dialects/Linalg/_index.md
index ab53aa8770098..246436a0a6f68 100644
--- a/mlir/docs/Dialects/Linalg/_index.md
+++ b/mlir/docs/Dialects/Linalg/_index.md
@@ -103,10 +103,10 @@ layout, and the second one is a `memref` of 4-element vectors with a 2-strided,
 #identity = affine_map<(d0) -> (d0)>
 
 func.func @example(%A: memref<?xf32, #identity>,
-              %B: memref<?xvector<4xf32>, offset: 1, strides: [2]>) {
+              %B: memref<?xvector<4xf32>, strided<[2], offset: 1>>) {
   linalg.generic #attrs
   ins(%A: memref<?xf32, #identity>)
-  outs(%B: memref<?xvector<4xf32>, offset: 1, strides: [2]>) {
+  outs(%B: memref<?xvector<4xf32>, strided<[2], offset: 1>>) {
   ^bb0(%a: f32, %b: vector<4xf32>):
     %c = "some_compute"(%a, %b): (f32, vector<4xf32>) -> (vector<4xf32>)
     linalg.yield %c: vector<4xf32>
@@ -186,10 +186,10 @@ uses an identity layout.
   iterator_types = ["parallel", "parallel"]
 }
 
-func.func @example(%A: memref<8x?xf32, offset: 0, strides: [2, 2]>,
+func.func @example(%A: memref<8x?xf32, strided<[2, 2], offset: 0>>,
               %B: memref<?xvector<4xf32>>) {
   linalg.generic #attrs
-  ins(%A: memref<8x?xf32, offset: 0, strides: [2, 2]>)
+  ins(%A: memref<8x?xf32, strided<[2, 2], offset: 0>>)
   outs(%B: memref<?xvector<4xf32>>) {
   ^bb0(%a: f32, %b: vector<4xf32>):
     %c = "some_compute"(%a, %b): (f32, vector<4xf32>) -> (vector<4xf32>)

diff  --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
index a9b9d54f0e127..2a3b1ee924f49 100644
--- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
+++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td
@@ -343,12 +343,12 @@ def MemRef_CastOp : MemRef_Op<"cast", [
     // The same holds true for offsets and strides.
 
     // Assert that the input dynamic shape matches the destination static stride.
-    %4 = memref.cast %1 : memref<12x4xf32, offset:?, strides: [?, ?]> to
-                          memref<12x4xf32, offset:5, strides: [4, 1]>
+    %4 = memref.cast %1 : memref<12x4xf32, strided<[?, ?], offset: ?>> to
+                          memref<12x4xf32, strided<[4, 1], offset: 5>>
     // Erase static offset and stride information, replacing it with
     // dynamic information.
-    %5 = memref.cast %1 : memref<12x4xf32, offset:5, strides: [4, 1]> to
-                          memref<12x4xf32, offset:?, strides: [?, ?]>
+    %5 = memref.cast %1 : memref<12x4xf32, strided<[4, 1], offset: 5>> to
+                          memref<12x4xf32, strided<[?, ?], offset: ?>>
     ```
 
     b. Either or both memref types are unranked with the same element type, and
@@ -1067,13 +1067,13 @@ def MemRef_ReinterpretCastOp
       offset: [0],
       sizes: [%size0, 10],
       strides: [1, %stride1]
-    : memref<?x?xf32> to memref<?x10xf32, offset: 0, strides: [1, ?]>
+    : memref<?x?xf32> to memref<?x10xf32, strided<[1, ?], offset: 0>>
 
     memref.reinterpret_cast %unranked to
       offset: [%offset],
       sizes: [%size0, %size1],
       strides: [%stride0, %stride1]
-    : memref<*xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+    : memref<*xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
     ```
   }];
 
@@ -1639,7 +1639,7 @@ def SubViewOp : MemRef_OpWithOffsetSizesAndStrides<"subview", [
     // After rank reducing:
     // (d0, d1) -> (4 * d0 + d1 + 210)
     %3 = memref.subview %2[3, 4, 2][1, 6, 3][1, 1, 1] :
-      memref<8x16x4xf32> to memref<6x3xf32, offset: 210, strides: [4, 1]>
+      memref<8x16x4xf32> to memref<6x3xf32, strided<[4, 1], offset: 210>>
     ```
   }];
 

diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h
index 70574b9fe9eb4..4f2b41540a148 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.h
+++ b/mlir/include/mlir/IR/BuiltinAttributes.h
@@ -1074,6 +1074,30 @@ inline bool operator!=(StringRef lhs, StringAttr rhs) { return !(lhs == rhs); }
 // Attribute Utilities
 //===----------------------------------------------------------------------===//
 
+namespace mlir {
+
+/// Given a list of strides (in which MemRefType::getDynamicStrideOrOffset()
+/// represents a dynamic value), return the single result AffineMap which
+/// represents the linearized strided layout map. Dimensions correspond to the
+/// offset followed by the strides in order. Symbols are inserted for each
+/// dynamic dimension in order. A stride is always positive.
+///
+/// Examples:
+/// =========
+///
+///   1. For offset: 0 strides: ?, ?, 1 return
+///         (i, j, k)[M, N]->(M * i + N * j + k)
+///
+///   2. For offset: 3 strides: 32, ?, 16 return
+///         (i, j, k)[M]->(3 + 32 * i + M * j + 16 * k)
+///
+///   3. For offset: ? strides: ?, ?, ? return
+///         (i, j, k)[off, M, N, P]->(off + M * i + N * j + P * k)
+AffineMap makeStridedLinearLayoutMap(ArrayRef<int64_t> strides, int64_t offset,
+                                     MLIRContext *context);
+
+} // namespace mlir
+
 namespace llvm {
 
 template <>

diff  --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index cee4f0ef20673..96ab4f2b92ece 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -966,6 +966,60 @@ def Builtin_SparseElementsAttr : Builtin_Attr<
   let skipDefaultBuilders = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// StridedLayoutAttr
+//===----------------------------------------------------------------------===//
+
+def StridedLayoutAttr : Builtin_Attr<"StridedLayout",
+    [DeclareAttrInterfaceMethods<MemRefLayoutAttrInterface,
+                                 ["verifyLayout"]>]> {
+  let summary = "An Attribute representing a strided layout of a shaped type";
+  let description = [{
+    Syntax:
+
+    ```
+    strided-layout-attribute ::= `strided` `<` `[` stride-list `]`
+                                 (`,` `offset` `:` dimension)? `>`
+    stride-list ::= /*empty*/
+                  | dimension (`,` dimension)*
+    dimension ::= decimal-literal | `?`
+    ```
+
+    A strided layout attribute captures layout information of the memref type in
+    the canonical form. Specifically, it contains a list of _strides_, one for
+    each dimension. A stride is the number of elements in the linear storage
+    one must step over to reflect an increment in the given dimension. For
+    example, a `MxN` row-major contiguous shaped type would have the strides
+    `[N, 1]`. The layout attribute also contains the _offset_ from the base
+    pointer of the shaped type to the first effectively accessed element,
+    expressed in terms of the number of contiguously stored elements.
+
+    Strides must be positive and the offset must be non-negative. Both the
+    strides and the offset may be _dynamic_, i.e. their value may not be known
+    at compile time. This is expressed as a `?` in the assembly syntax and as
+    `ShapedType::kDynamicStrideOrOffset` in the code. Stride and offset values
+    must satisfy the constraints above at runtime, the behavior is undefined
+    otherwise.
+
+    See [Dialects/Builtin.md#memreftype](MemRef type) for more information.
+  }];
+
+  let parameters = (ins
+    "int64_t":$offset,
+    ArrayRefParameter<
+      "int64_t",
+      "array of strides (64-bit integer)"
+    >:$strides
+  );
+  let genVerifyDecl = 1;
+
+  let extraClassDeclaration = [{
+    /// Print the attribute to the given output stream.
+    void print(raw_ostream &os) const;
+  }];
+}
+
+
 //===----------------------------------------------------------------------===//
 // StringAttr
 //===----------------------------------------------------------------------===//

diff  --git a/mlir/include/mlir/IR/BuiltinTypes.h b/mlir/include/mlir/IR/BuiltinTypes.h
index 171203e9b26ff..96c7804d96495 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.h
+++ b/mlir/include/mlir/IR/BuiltinTypes.h
@@ -436,26 +436,6 @@ LogicalResult getStridesAndOffset(MemRefType t,
                                   SmallVectorImpl<AffineExpr> &strides,
                                   AffineExpr &offset);
 
-/// Given a list of strides (in which MemRefType::getDynamicStrideOrOffset()
-/// represents a dynamic value), return the single result AffineMap which
-/// represents the linearized strided layout map. Dimensions correspond to the
-/// offset followed by the strides in order. Symbols are inserted for each
-/// dynamic dimension in order. A stride cannot take value `0`.
-///
-/// Examples:
-/// =========
-///
-///   1. For offset: 0 strides: ?, ?, 1 return
-///         (i, j, k)[M, N]->(M * i + N * j + k)
-///
-///   2. For offset: 3 strides: 32, ?, 16 return
-///         (i, j, k)[M]->(3 + 32 * i + M * j + 16 * k)
-///
-///   3. For offset: ? strides: ?, ?, ? return
-///         (i, j, k)[off, M, N, P]->(off + M * i + N * j + P * k)
-AffineMap makeStridedLinearLayoutMap(ArrayRef<int64_t> strides, int64_t offset,
-                                     MLIRContext *context);
-
 /// Return a version of `t` with identity layout if it can be determined
 /// statically that the layout is the canonical contiguous strided layout.
 /// Otherwise pass `t`'s layout into `simplifyAffineMap` and return a copy of

diff  --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td
index 41336b1ea02c9..55dc24134b451 100644
--- a/mlir/include/mlir/IR/BuiltinTypes.td
+++ b/mlir/include/mlir/IR/BuiltinTypes.td
@@ -280,10 +280,7 @@ def Builtin_MemRef : Builtin_Type<"MemRef", [
     ```
     memref-type ::= `memref` `<` dimension-list-ranked type
                     (`,` layout-specification)? (`,` memory-space)? `>`
-
-    stride-list ::= `[` (dimension (`,` dimension)*)? `]`
-    strided-layout ::= `offset:` dimension `,` `strides: ` stride-list
-    layout-specification ::= semi-affine-map | strided-layout | attribute-value
+    layout-specification ::= attribute-value
     memory-space ::= attribute-value
     ```
 
@@ -310,6 +307,84 @@ def Builtin_MemRef : Builtin_Type<"MemRef", [
     - another memref type;
     - any other type implementing `MemRefElementTypeInterface`.
 
+    ##### Layout
+
+    A memref may optionally have a layout that indicates how indices are
+    transformed from the multi-dimensional form into a linear address. The
+    layout must avoid internal aliasing, i.e., two distinct tuples of
+    _in-bounds_ indices must be pointing to 
diff erent elements in memory. The
+    layout is an attribute that implements `MemRefLayoutAttrInterface`. The
+    bulitin dialect offers two kinds of layouts: strided and affine map, each
+    of which is available as an attribute. Other attributes may be used to
+    represent the layout as long as they can be converted to a
+    [semi-affine map](Affine.md/#semi-affine-maps) and implement the required
+    interface. Users of memref are expected to fallback to the affine
+    representation when handling unknown memref layouts. Multi-dimensional
+    affine forms are interpreted in _row-major_ fashion.
+
+    In absence of an explicit layout, a memref is considered to have a
+    multi-dimensional identity affine map 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 a
+    layout, `memref<?x?xf32>`.
+
+    ##### Affine Map Layout
+
+    The layout may be represented directly as an affine map from the index space
+    to the storage space. 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)
+
+    Semi-affine maps are sufficiently flexible to represent a wide variety of
+    dense storage layouts, including row- and column-major and tiled:
+
+    ```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)
+    ```
+
+    ##### Strided Layout
+
+    Memref layout can be expressed using strides to encode the distance, in
+    number of elements, in (linear) memory between successive entries along a
+    particular dimension. For example, a row-major strided layout for
+    `memref<2x3x4xf32>` is `strided<[12, 4, 1]>`, where the last dimension is
+    contiguous as indicated by the unit stride and the remaining strides are
+    products of the sizes of faster-variying dimensions. Strided layout can also
+    express non-contiguity, e.g., `memref<2x3, strided<[6, 2]>>` only accesses
+    even elements of the dense consecutive storage along the innermost
+    dimension.
+
+    The strided layout supports an optional _offset_ that indicates the
+    distance, in the number of elements, between the beginning of the memref
+    and the first accessed element. When omitted, the offset is considered to
+    be zero. That is, `memref<2, strided<[2], offset: 0>>` and
+    `memref<2, strided<[2]>>` are strictly the same type.
+
+    Both offsets and strides may be _dynamic_, that is, unknown at compile time.
+    This is represented by using a question mark (`?`) instead of the value in
+    the textual form of the IR.
+
+    The strided layout converts into the following canonical one-dimensional
+    affine form through explicit linearization:
+
+    ```mlir
+    affine_map<(d0, ... dN)[offset, stride0, ... strideN] -> 
+                (offset + d0 * stride0 + ... dN * strideN)>
+    ```
+
+    Therefore, it is never subject to the implicit row-major layout
+    interpretation.
+
     ##### Codegen of Unranked Memref
 
     Using unranked memref in codegen besides the case mentioned above is highly
@@ -425,104 +500,6 @@ def Builtin_MemRef : Builtin_Type<"MemRef", [
     %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](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](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)
-    ```
-
-    ##### Strided MemRef
-
-    A memref may specify a strided layout 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 with a *single* semi-affine map.
-
-    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,

diff  --git a/mlir/lib/AsmParser/AttributeParser.cpp b/mlir/lib/AsmParser/AttributeParser.cpp
index 8e7a83a7d2732..8fadc2933e94d 100644
--- a/mlir/lib/AsmParser/AttributeParser.cpp
+++ b/mlir/lib/AsmParser/AttributeParser.cpp
@@ -15,6 +15,7 @@
 #include "AsmParserImpl.h"
 #include "mlir/AsmParser/AsmParserState.h"
 #include "mlir/IR/AffineMap.h"
+#include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinDialect.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/DialectImplementation.h"
@@ -42,6 +43,8 @@ using namespace mlir::detail;
 ///                      (tensor-type | vector-type)
 ///                    | `sparse` `<` attribute-value `,` attribute-value `>`
 ///                      `:` (tensor-type | vector-type)
+///                    | `strided` `<` `[` comma-separated-int-or-question `]`
+///                      (`,` `offset` `:` integer-literal)? `>`
 ///                    | extended-attribute
 ///
 Attribute Parser::parseAttribute(Type type) {
@@ -147,6 +150,10 @@ Attribute Parser::parseAttribute(Type type) {
   case Token::kw_sparse:
     return parseSparseElementsAttr(type);
 
+  // Parse a strided layout attribute.
+  case Token::kw_strided:
+    return parseStridedLayoutAttr();
+
   // Parse a string attribute.
   case Token::string: {
     auto val = getToken().getStringValue();
@@ -1072,3 +1079,74 @@ Attribute Parser::parseSparseElementsAttr(Type attrType) {
   // Build the sparse elements attribute by the indices and values.
   return getChecked<SparseElementsAttr>(loc, type, indices, values);
 }
+
+Attribute Parser::parseStridedLayoutAttr() {
+  // Callback for error emissing at the keyword token location.
+  llvm::SMLoc loc = getToken().getLoc();
+  auto errorEmitter = [&] { return emitError(loc); };
+
+  consumeToken(Token::kw_strided);
+  if (failed(parseToken(Token::less, "expected '<' after 'strided'")) ||
+      failed(parseToken(Token::l_square, "expected '['")))
+    return nullptr;
+
+  // Parses either an integer token or a question mark token. Reports an error
+  // and returns None if the current token is neither. The integer token must
+  // fit into int64_t limits.
+  auto parseStrideOrOffset = [&]() -> Optional<int64_t> {
+    if (consumeIf(Token::question))
+      return ShapedType::kDynamicStrideOrOffset;
+
+    SMLoc loc = getToken().getLoc();
+    auto emitWrongTokenError = [&] {
+      emitError(loc, "expected a non-negative 64-bit signed integer or '?'");
+      return llvm::None;
+    };
+
+    if (getToken().is(Token::integer)) {
+      Optional<uint64_t> value = getToken().getUInt64IntegerValue();
+      if (!value || *value > std::numeric_limits<int64_t>::max())
+        return emitWrongTokenError();
+      consumeToken();
+      return static_cast<int64_t>(*value);
+    }
+
+    return emitWrongTokenError();
+  };
+
+  // Parse strides.
+  SmallVector<int64_t> strides;
+  if (!getToken().is(Token::r_square)) {
+    do {
+      Optional<int64_t> stride = parseStrideOrOffset();
+      if (!stride)
+        return nullptr;
+      strides.push_back(*stride);
+    } while (consumeIf(Token::comma));
+  }
+
+  if (failed(parseToken(Token::r_square, "expected ']'")))
+    return nullptr;
+
+  // Fast path in absence of offset.
+  if (consumeIf(Token::greater)) {
+    if (failed(StridedLayoutAttr::verify(errorEmitter,
+                                         /*offset=*/0, strides)))
+      return nullptr;
+    return StridedLayoutAttr::get(getContext(), /*offset=*/0, strides);
+  }
+
+  if (failed(parseToken(Token::comma, "expected ','")) ||
+      failed(parseToken(Token::kw_offset, "expected 'offset' after comma")) ||
+      failed(parseToken(Token::colon, "expected ':' after 'offset'")))
+    return nullptr;
+
+  Optional<int64_t> offset = parseStrideOrOffset();
+  if (!offset || failed(parseToken(Token::greater, "expected '>'")))
+    return nullptr;
+
+  if (failed(StridedLayoutAttr::verify(errorEmitter, *offset, strides)))
+    return nullptr;
+  return StridedLayoutAttr::get(getContext(), *offset, strides);
+  // return getChecked<StridedLayoutAttr>(loc,getContext(), *offset, strides);
+}

diff  --git a/mlir/lib/AsmParser/Parser.h b/mlir/lib/AsmParser/Parser.h
index fd87ff9960661..d52b05d72b7e4 100644
--- a/mlir/lib/AsmParser/Parser.h
+++ b/mlir/lib/AsmParser/Parser.h
@@ -217,14 +217,6 @@ class Parser {
   ParseResult parseIntegerInDimensionList(int64_t &value);
   ParseResult parseXInDimensionList();
 
-  /// Parse strided layout specification.
-  ParseResult parseStridedLayout(int64_t &offset,
-                                 SmallVectorImpl<int64_t> &strides);
-
-  // Parse a brace-delimiter list of comma-separated integers with `?` as an
-  // unknown marker.
-  ParseResult parseStrideList(SmallVectorImpl<int64_t> &dimensions);
-
   //===--------------------------------------------------------------------===//
   // Attribute Parsing
   //===--------------------------------------------------------------------===//
@@ -279,6 +271,9 @@ class Parser {
   /// Parse a sparse elements attribute.
   Attribute parseSparseElementsAttr(Type attrType);
 
+  /// Parse a strided layout attribute.
+  Attribute parseStridedLayoutAttr();
+
   //===--------------------------------------------------------------------===//
   // Location Parsing
   //===--------------------------------------------------------------------===//

diff  --git a/mlir/lib/AsmParser/TokenKinds.def b/mlir/lib/AsmParser/TokenKinds.def
index 2d746d902335d..94d2fd3687fc3 100644
--- a/mlir/lib/AsmParser/TokenKinds.def
+++ b/mlir/lib/AsmParser/TokenKinds.def
@@ -109,7 +109,7 @@ TOK_KEYWORD(offset)
 TOK_KEYWORD(size)
 TOK_KEYWORD(sparse)
 TOK_KEYWORD(step)
-TOK_KEYWORD(strides)
+TOK_KEYWORD(strided)
 TOK_KEYWORD(symbol)
 TOK_KEYWORD(tensor)
 TOK_KEYWORD(to)

diff  --git a/mlir/lib/AsmParser/TypeParser.cpp b/mlir/lib/AsmParser/TypeParser.cpp
index 85f4519f77c84..16da006809d29 100644
--- a/mlir/lib/AsmParser/TypeParser.cpp
+++ b/mlir/lib/AsmParser/TypeParser.cpp
@@ -146,35 +146,6 @@ Type Parser::parseFunctionType() {
   return builder.getFunctionType(arguments, results);
 }
 
-/// Parse the offset and strides from a strided layout specification.
-///
-///   strided-layout ::= `offset:` dimension `,` `strides: ` stride-list
-///
-ParseResult Parser::parseStridedLayout(int64_t &offset,
-                                       SmallVectorImpl<int64_t> &strides) {
-  // Parse offset.
-  consumeToken(Token::kw_offset);
-  if (parseToken(Token::colon, "expected colon after `offset` keyword"))
-    return failure();
-
-  auto maybeOffset = getToken().getUnsignedIntegerValue();
-  bool question = getToken().is(Token::question);
-  if (!maybeOffset && !question)
-    return emitWrongTokenError("invalid offset");
-  offset = maybeOffset ? static_cast<int64_t>(*maybeOffset)
-                       : MemRefType::getDynamicStrideOrOffset();
-  consumeToken();
-
-  // Parse stride list.
-  if (parseToken(Token::comma, "expected comma after offset value") ||
-      parseToken(Token::kw_strides,
-                 "expected `strides` keyword after offset specification") ||
-      parseToken(Token::colon, "expected colon after `strides` keyword") ||
-      parseStrideList(strides))
-    return failure();
-  return success();
-}
-
 /// Parse a memref type.
 ///
 ///   memref-type ::= ranked-memref-type | unranked-memref-type
@@ -225,29 +196,18 @@ Type Parser::parseMemRefType() {
   Attribute memorySpace;
 
   auto parseElt = [&]() -> ParseResult {
-    // Check for AffineMap as offset/strides.
-    if (getToken().is(Token::kw_offset)) {
-      int64_t offset;
-      SmallVector<int64_t, 4> strides;
-      if (failed(parseStridedLayout(offset, strides)))
-        return failure();
-      // Construct strided affine map.
-      AffineMap map = makeStridedLinearLayoutMap(strides, offset, getContext());
-      layout = AffineMapAttr::get(map);
-    } else {
-      // Either it is MemRefLayoutAttrInterface or memory space attribute.
-      Attribute attr = parseAttribute();
-      if (!attr)
-        return failure();
+    // Either it is MemRefLayoutAttrInterface or memory space attribute.
+    Attribute attr = parseAttribute();
+    if (!attr)
+      return failure();
 
-      if (attr.isa<MemRefLayoutAttrInterface>()) {
-        layout = attr.cast<MemRefLayoutAttrInterface>();
-      } else if (memorySpace) {
-        return emitError("multiple memory spaces specified in memref type");
-      } else {
-        memorySpace = attr;
-        return success();
-      }
+    if (attr.isa<MemRefLayoutAttrInterface>()) {
+      layout = attr.cast<MemRefLayoutAttrInterface>();
+    } else if (memorySpace) {
+      return emitError("multiple memory spaces specified in memref type");
+    } else {
+      memorySpace = attr;
+      return success();
     }
 
     if (isUnranked)
@@ -617,34 +577,3 @@ ParseResult Parser::parseXInDimensionList() {
 
   return success();
 }
-
-// Parse a comma-separated list of dimensions, possibly empty:
-//   stride-list ::= `[` (dimension (`,` dimension)*)? `]`
-ParseResult Parser::parseStrideList(SmallVectorImpl<int64_t> &dimensions) {
-  return parseCommaSeparatedList(
-      Delimiter::Square,
-      [&]() -> ParseResult {
-        if (consumeIf(Token::question)) {
-          dimensions.push_back(MemRefType::getDynamicStrideOrOffset());
-        } else {
-          // This must be an integer value.
-          int64_t val;
-          if (getToken().getSpelling().getAsInteger(10, val))
-            return emitError("invalid integer value: ")
-                   << getToken().getSpelling();
-          // Make sure it is not the one value for `?`.
-          if (ShapedType::isDynamic(val))
-            return emitError("invalid integer value: ")
-                   << getToken().getSpelling()
-                   << ", use `?` to specify a dynamic dimension";
-
-          if (val == 0)
-            return emitError("invalid memref stride");
-
-          dimensions.push_back(val);
-          consumeToken(Token::integer);
-        }
-        return success();
-      },
-      " in stride list");
-}

diff  --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
index a2c49db4b51b8..90275c1458b4b 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
@@ -2577,13 +2577,13 @@ namespace {
 /// ```
 ///   %0 = memref.cast %V : memref<16x16xf32> to memref<?x?xf32>
 ///   %1 = memref.subview %0[0, 0][3, 4][1, 1] :
-///     memref<?x?xf32> to memref<3x4xf32, offset:?, strides:[?, 1]>
+///     memref<?x?xf32> to memref<3x4xf32, strided<[?, 1], offset: ?>>
 /// ```
 /// is rewritten into:
 /// ```
 ///   %0 = memref.subview %V: memref<16x16xf32> to memref<3x4xf32, #[[map0]]>
-///   %1 = memref.cast %0: memref<3x4xf32, offset:0, strides:[16, 1]> to
-///     memref<3x4xf32, offset:?, strides:[?, 1]>
+///   %1 = memref.cast %0: memref<3x4xf32, strided<[16, 1], offset: 0>> to
+///     memref<3x4xf32, strided<[?, 1], offset: ?>>
 /// ```
 class SubViewOpMemRefCastFolder final : public OpRewritePattern<SubViewOp> {
 public:

diff  --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index dcd4ef60294b3..3bb67fcbc39a8 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -1858,6 +1858,8 @@ void AsmPrinter::Impl::printAttribute(Attribute attr,
       }
       os << '>';
     }
+  } else if (auto stridedLayoutAttr = attr.dyn_cast<StridedLayoutAttr>()) {
+    stridedLayoutAttr.print(os);
   } else if (auto denseArrayAttr = attr.dyn_cast<DenseArrayBaseAttr>()) {
     typeElision = AttrTypeElision::Must;
     os << "array<" << denseArrayAttr.getType().getElementType();

diff  --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index a7eedb25a524e..dab80f1f942a8 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -236,6 +236,60 @@ DictionaryAttr::replaceImmediateSubElements(ArrayRef<Attribute> replAttrs,
   return getWithSorted(getContext(), vec);
 }
 
+//===----------------------------------------------------------------------===//
+// StridedLayoutAttr
+//===----------------------------------------------------------------------===//
+
+/// Prints a strided layout attribute.
+void StridedLayoutAttr::print(llvm::raw_ostream &os) const {
+  auto printIntOrQuestion = [&](int64_t value) {
+    if (value == ShapedType::kDynamicStrideOrOffset)
+      os << "?";
+    else
+      os << value;
+  };
+
+  os << "strided<[";
+  llvm::interleaveComma(getStrides(), os, printIntOrQuestion);
+  os << "]";
+
+  if (getOffset() != 0) {
+    os << ", offset: ";
+    printIntOrQuestion(getOffset());
+  }
+  os << ">";
+}
+
+/// Returns the strided layout as an affine map.
+AffineMap StridedLayoutAttr::getAffineMap() const {
+  return makeStridedLinearLayoutMap(getStrides(), getOffset(), getContext());
+}
+
+/// Checks that the type-agnostic strided layout invariants are satisfied.
+LogicalResult
+StridedLayoutAttr::verify(function_ref<InFlightDiagnostic()> emitError,
+                          int64_t offset, ArrayRef<int64_t> strides) {
+  if (offset < 0 && offset != ShapedType::kDynamicStrideOrOffset)
+    return emitError() << "offset must be non-negative or dynamic";
+
+  if (llvm::any_of(strides, [&](int64_t stride) {
+        return stride <= 0 && stride != ShapedType::kDynamicStrideOrOffset;
+      })) {
+    return emitError() << "strides must be positive or dynamic";
+  }
+  return success();
+}
+
+/// Checks that the type-specific strided layout invariants are satisfied.
+LogicalResult StridedLayoutAttr::verifyLayout(
+    ArrayRef<int64_t> shape,
+    function_ref<InFlightDiagnostic()> emitError) const {
+  if (shape.size() != getStrides().size())
+    return emitError() << "expected the number of strides to match the rank";
+
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // StringAttr
 //===----------------------------------------------------------------------===//
@@ -1783,3 +1837,43 @@ TypeAttr::replaceImmediateSubElements(ArrayRef<Attribute> replAttrs,
                                       ArrayRef<Type> replTypes) const {
   return get(replTypes[0]);
 }
+
+//===----------------------------------------------------------------------===//
+// Attribute Utilities
+//===----------------------------------------------------------------------===//
+
+AffineMap mlir::makeStridedLinearLayoutMap(ArrayRef<int64_t> strides,
+                                           int64_t offset,
+                                           MLIRContext *context) {
+  AffineExpr expr;
+  unsigned nSymbols = 0;
+
+  // AffineExpr for offset.
+  // Static case.
+  if (offset != MemRefType::getDynamicStrideOrOffset()) {
+    auto cst = getAffineConstantExpr(offset, context);
+    expr = cst;
+  } else {
+    // Dynamic case, new symbol for the offset.
+    auto sym = getAffineSymbolExpr(nSymbols++, context);
+    expr = sym;
+  }
+
+  // AffineExpr for strides.
+  for (const auto &en : llvm::enumerate(strides)) {
+    auto dim = en.index();
+    auto stride = en.value();
+    assert(stride != 0 && "Invalid stride specification");
+    auto d = getAffineDimExpr(dim, context);
+    AffineExpr mult;
+    // Static case.
+    if (stride != MemRefType::getDynamicStrideOrOffset())
+      mult = getAffineConstantExpr(stride, context);
+    else
+      // Dynamic case, new symbol for each new stride.
+      mult = getAffineSymbolExpr(nSymbols++, context);
+    expr = expr + d * mult;
+  }
+
+  return AffineMap::get(strides.size(), nSymbols, expr);
+}

diff  --git a/mlir/lib/IR/BuiltinTypes.cpp b/mlir/lib/IR/BuiltinTypes.cpp
index f361b4359a7c8..f53a94146efcb 100644
--- a/mlir/lib/IR/BuiltinTypes.cpp
+++ b/mlir/lib/IR/BuiltinTypes.cpp
@@ -895,42 +895,6 @@ Type TupleType::replaceImmediateSubElements(ArrayRef<Attribute> replAttrs,
 // Type Utilities
 //===----------------------------------------------------------------------===//
 
-AffineMap mlir::makeStridedLinearLayoutMap(ArrayRef<int64_t> strides,
-                                           int64_t offset,
-                                           MLIRContext *context) {
-  AffineExpr expr;
-  unsigned nSymbols = 0;
-
-  // AffineExpr for offset.
-  // Static case.
-  if (offset != MemRefType::getDynamicStrideOrOffset()) {
-    auto cst = getAffineConstantExpr(offset, context);
-    expr = cst;
-  } else {
-    // Dynamic case, new symbol for the offset.
-    auto sym = getAffineSymbolExpr(nSymbols++, context);
-    expr = sym;
-  }
-
-  // AffineExpr for strides.
-  for (const auto &en : llvm::enumerate(strides)) {
-    auto dim = en.index();
-    auto stride = en.value();
-    assert(stride != 0 && "Invalid stride specification");
-    auto d = getAffineDimExpr(dim, context);
-    AffineExpr mult;
-    // Static case.
-    if (stride != MemRefType::getDynamicStrideOrOffset())
-      mult = getAffineConstantExpr(stride, context);
-    else
-      // Dynamic case, new symbol for each new stride.
-      mult = getAffineSymbolExpr(nSymbols++, context);
-    expr = expr + d * mult;
-  }
-
-  return AffineMap::get(strides.size(), nSymbols, expr);
-}
-
 /// Return a version of `t` with identity layout if it can be determined
 /// statically that the layout is the canonical contiguous strided layout.
 /// Otherwise pass `t`'s layout into `simplifyAffineMap` and return a copy of

diff  --git a/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir b/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir
index abccf9f5117e5..de6d565bcb123 100644
--- a/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir
+++ b/mlir/test/Conversion/FuncToLLVM/func-memref-return.mlir
@@ -40,7 +40,7 @@ func.func @check_static_return(%static : memref<32x18xf32>) -> memref<32x18xf32>
 // CHECK-SAME: -> !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
 // BAREPTR-LABEL: func @check_static_return_with_offset
 // BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr<f32>) -> !llvm.ptr<f32> {
-func.func @check_static_return_with_offset(%static : memref<32x18xf32, offset:7, strides:[22,1]>) -> memref<32x18xf32, offset:7, strides:[22,1]> {
+func.func @check_static_return_with_offset(%static : memref<32x18xf32, strided<[22,1], offset: 7>>) -> memref<32x18xf32, strided<[22,1], offset: 7>> {
 // CHECK:  llvm.return %{{.*}} : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
 
 // BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
@@ -58,7 +58,7 @@ func.func @check_static_return_with_offset(%static : memref<32x18xf32, offset:7,
 // BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
 // BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
 // BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr<f32>
-  return %static : memref<32x18xf32, offset:7, strides:[22,1]>
+  return %static : memref<32x18xf32, strided<[22,1], offset: 7>>
 }
 
 // -----

diff  --git a/mlir/test/Conversion/FuncToSPIRV/types-to-spirv.mlir b/mlir/test/Conversion/FuncToSPIRV/types-to-spirv.mlir
index 719af7f0a21de..4ff67ce001fbc 100644
--- a/mlir/test/Conversion/FuncToSPIRV/types-to-spirv.mlir
+++ b/mlir/test/Conversion/FuncToSPIRV/types-to-spirv.mlir
@@ -597,22 +597,22 @@ func.func @memref_offset_strides(
 // CHECK-SAME: !spv.array<256 x f32, stride=4> [0])>, StorageBuffer>
 // CHECK-SAME: !spv.array<64 x f32, stride=4> [0])>, StorageBuffer>
 // CHECK-SAME: !spv.array<88 x f32, stride=4> [0])>, StorageBuffer>
-  %arg0: memref<16x4xf32, offset: 0, strides: [4, 1], #spv.storage_class<StorageBuffer>>,  // tightly packed; row major
-  %arg1: memref<16x4xf32, offset: 8, strides: [4, 1], #spv.storage_class<StorageBuffer>>,  // offset 8
-  %arg2: memref<16x4xf32, offset: 0, strides: [16, 1], #spv.storage_class<StorageBuffer>>, // pad 12 after each row
-  %arg3: memref<16x4xf32, offset: 0, strides: [1, 16], #spv.storage_class<StorageBuffer>>, // tightly packed; col major
-  %arg4: memref<16x4xf32, offset: 0, strides: [1, 22], #spv.storage_class<StorageBuffer>>, // pad 4 after each col
+  %arg0: memref<16x4xf32, strided<[4, 1], offset: 0>, #spv.storage_class<StorageBuffer>>,  // tightly packed; row major
+  %arg1: memref<16x4xf32, strided<[4, 1], offset: 8>, #spv.storage_class<StorageBuffer>>,  // offset 8
+  %arg2: memref<16x4xf32, strided<[16, 1], offset: 0>, #spv.storage_class<StorageBuffer>>, // pad 12 after each row
+  %arg3: memref<16x4xf32, strided<[1, 16], offset: 0>, #spv.storage_class<StorageBuffer>>, // tightly packed; col major
+  %arg4: memref<16x4xf32, strided<[1, 22], offset: 0>, #spv.storage_class<StorageBuffer>>, // pad 4 after each col
 
 // CHECK-SAME: !spv.array<64 x f16, stride=2> [0])>, StorageBuffer>
 // CHECK-SAME: !spv.array<72 x f16, stride=2> [0])>, StorageBuffer>
 // CHECK-SAME: !spv.array<256 x f16, stride=2> [0])>, StorageBuffer>
 // CHECK-SAME: !spv.array<64 x f16, stride=2> [0])>, StorageBuffer>
 // CHECK-SAME: !spv.array<88 x f16, stride=2> [0])>, StorageBuffer>
-  %arg5: memref<16x4xf16, offset: 0, strides: [4, 1], #spv.storage_class<StorageBuffer>>,
-  %arg6: memref<16x4xf16, offset: 8, strides: [4, 1], #spv.storage_class<StorageBuffer>>,
-  %arg7: memref<16x4xf16, offset: 0, strides: [16, 1], #spv.storage_class<StorageBuffer>>,
-  %arg8: memref<16x4xf16, offset: 0, strides: [1, 16], #spv.storage_class<StorageBuffer>>,
-  %arg9: memref<16x4xf16, offset: 0, strides: [1, 22], #spv.storage_class<StorageBuffer>>
+  %arg5: memref<16x4xf16, strided<[4, 1], offset: 0>, #spv.storage_class<StorageBuffer>>,
+  %arg6: memref<16x4xf16, strided<[4, 1], offset: 8>, #spv.storage_class<StorageBuffer>>,
+  %arg7: memref<16x4xf16, strided<[16, 1], offset: 0>, #spv.storage_class<StorageBuffer>>,
+  %arg8: memref<16x4xf16, strided<[1, 16], offset: 0>, #spv.storage_class<StorageBuffer>>,
+  %arg9: memref<16x4xf16, strided<[1, 22], offset: 0>, #spv.storage_class<StorageBuffer>>
 ) { return }
 
 } // end module

diff  --git a/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir b/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir
index 74749e7221a96..22bec31f9d91e 100644
--- a/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir
+++ b/mlir/test/Conversion/MemRefToLLVM/convert-dynamic-memref-ops.mlir
@@ -436,7 +436,7 @@ func.func @memref_reinterpret_cast_unranked_to_dynamic_shape(%offset: index,
   %output = memref.reinterpret_cast %input to
            offset: [%offset], sizes: [%size_0, %size_1],
            strides: [%stride_0, %stride_1]
-           : memref<*xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+           : memref<*xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
   return
 }
 // CHECK-SAME: ([[OFFSETarg:%[a-z,0-9]+]]: index,

diff  --git a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
index f6e496c713f03..021e92cf50fc8 100644
--- a/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
+++ b/mlir/test/Conversion/MemRefToLLVM/memref-to-llvm.mlir
@@ -122,7 +122,7 @@ func.func @view_empty_memref(%offset: index, %mem: memref<0xi8>) {
 // CHECK32:         %[[ARG0f:[a-zA-Z0-9]*]]: index,
 // CHECK32:         %[[ARG1f:[a-zA-Z0-9]*]]: index,
 // CHECK32:         %[[ARG2f:.*]]: index)
-func.func @subview(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) {
+func.func @subview(%0 : memref<64x4xf32, strided<[4, 1], offset: 0>>, %arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK-DAG: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast %[[MEM]]
   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[ARG0f]]
   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[ARG1f]]
@@ -170,8 +170,8 @@ func.func @subview(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : in
   // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
 
   %1 = memref.subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] :
-    memref<64x4xf32, offset: 0, strides: [4, 1]>
-  to memref<?x?xf32, offset: ?, strides: [?, ?]>
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+  to memref<?x?xf32, strided<[?, ?], offset: ?>>
   return
 }
 
@@ -187,7 +187,7 @@ func.func @subview(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : in
 // CHECK32:         %[[ARG0f:[a-zA-Z0-9]*]]: index,
 // CHECK32:         %[[ARG1f:[a-zA-Z0-9]*]]: index,
 // CHECK32:         %[[ARG2f:.*]]: index)
-func.func @subview_non_zero_addrspace(%0 : memref<64x4xf32, offset: 0, strides: [4, 1], 3>, %arg0 : index, %arg1 : index, %arg2 : index) {
+func.func @subview_non_zero_addrspace(%0 : memref<64x4xf32, strided<[4, 1], offset: 0>, 3>, %arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK-DAG: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast %[[MEM]]
   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[ARG0f]]
   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[ARG1f]]
@@ -234,8 +234,8 @@ func.func @subview_non_zero_addrspace(%0 : memref<64x4xf32, offset: 0, strides:
   // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr<f32, 3>, ptr<f32, 3>, i32, array<2 x i32>, array<2 x i32>)>
 
   %1 = memref.subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] :
-    memref<64x4xf32, offset: 0, strides: [4, 1], 3>
-    to memref<?x?xf32, offset: ?, strides: [?, ?], 3>
+    memref<64x4xf32, strided<[4, 1], offset: 0>, 3>
+    to memref<?x?xf32, strided<[?, ?], offset: ?>, 3>
   return
 }
 
@@ -251,7 +251,7 @@ func.func @subview_non_zero_addrspace(%0 : memref<64x4xf32, offset: 0, strides:
 // CHECK32-SAME:         %[[ARG0f:[a-zA-Z0-9]*]]: index
 // CHECK32-SAME:         %[[ARG1f:[a-zA-Z0-9]*]]: index
 // CHECK32-SAME:         %[[ARG2f:[a-zA-Z0-9]*]]: index
-func.func @subview_const_size(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) {
+func.func @subview_const_size(%0 : memref<64x4xf32, strided<[4, 1], offset: 0>>, %arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK-DAG: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast %[[MEM]]
   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[ARG0f]]
   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[ARG1f]]
@@ -302,8 +302,8 @@ func.func @subview_const_size(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>,
   // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[CST4]], %[[DESC4]][3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   // CHECK32: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   %1 = memref.subview %0[%arg0, %arg1][4, 2][%arg0, %arg1] :
-    memref<64x4xf32, offset: 0, strides: [4, 1]>
-    to memref<4x2xf32, offset: ?, strides: [?, ?]>
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+    to memref<4x2xf32, strided<[?, ?], offset: ?>>
   return
 }
 
@@ -319,7 +319,7 @@ func.func @subview_const_size(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>,
 // CHECK32-SAME:         %[[ARG0f:[a-zA-Z0-9]*]]: index
 // CHECK32-SAME:         %[[ARG1f:[a-zA-Z0-9]*]]: index
 // CHECK32-SAME:         %[[ARG2f:[a-zA-Z0-9]*]]: index
-func.func @subview_const_stride(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) {
+func.func @subview_const_stride(%0 : memref<64x4xf32, strided<[4, 1], offset: 0>>, %arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK-DAG: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast %[[MEM]]
   // CHECK-DAG: %[[ARG0:.*]] = builtin.unrealized_conversion_cast %[[ARG0f]]
   // CHECK-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[ARG1f]]
@@ -366,8 +366,8 @@ func.func @subview_const_stride(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]
   // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   // CHECK32: llvm.insertvalue %[[CST4]], %[[DESC5]][4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   %1 = memref.subview %0[%arg0, %arg1][%arg0, %arg1][1, 2] :
-    memref<64x4xf32, offset: 0, strides: [4, 1]>
-    to memref<?x?xf32, offset: ?, strides: [4, 2]>
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+    to memref<?x?xf32, strided<[4, 2], offset: ?>>
   return
 }
 
@@ -375,7 +375,7 @@ func.func @subview_const_stride(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]
 
 // CHECK-LABEL: func @subview_const_stride_and_offset(
 // CHECK32-LABEL: func @subview_const_stride_and_offset(
-func.func @subview_const_stride_and_offset(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>) {
+func.func @subview_const_stride_and_offset(%0 : memref<64x4xf32, strided<[4, 1], offset: 0>>) {
   // The last "insertvalue" that populates the memref descriptor from the function arguments.
   // CHECK: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast
   // CHECK32: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast
@@ -398,8 +398,8 @@ func.func @subview_const_stride_and_offset(%0 : memref<64x4xf32, offset: 0, stri
   // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[CST62]], %[[DESC4]][3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   // CHECK32: llvm.insertvalue %[[CST4]], %[[DESC5]][4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   %1 = memref.subview %0[0, 8][62, 3][1, 1] :
-    memref<64x4xf32, offset: 0, strides: [4, 1]>
-    to memref<62x3xf32, offset: 8, strides: [4, 1]>
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+    to memref<62x3xf32, strided<[4, 1], offset: 8>>
   return
 }
 
@@ -415,7 +415,7 @@ func.func @subview_const_stride_and_offset(%0 : memref<64x4xf32, offset: 0, stri
 // CHECK32:         %[[ARG0f:[a-zA-Z0-9]*]]: index,
 // CHECK32:         %[[ARG1f:[a-zA-Z0-9]*]]: index,
 // CHECK32:         %[[ARG2f:.*]]: index)
-func.func @subview_mixed_static_dynamic(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) {
+func.func @subview_mixed_static_dynamic(%0 : memref<64x4xf32, strided<[4, 1], offset: 0>>, %arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK32-DAG: %[[MEMREF:.*]] = builtin.unrealized_conversion_cast %[[MEM]]
   // CHECK32-DAG: %[[ARG1:.*]] = builtin.unrealized_conversion_cast %[[ARG1f]]
   // CHECK32-DAG: %[[ARG2:.*]] = builtin.unrealized_conversion_cast %[[ARG2f]]
@@ -444,8 +444,8 @@ func.func @subview_mixed_static_dynamic(%0 : memref<64x4xf32, offset: 0, strides
   // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[CST62]], %[[DESC4]][3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   // CHECK32: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i32, array<2 x i32>, array<2 x i32>)>
   %1 = memref.subview %0[%arg1, 8][62, %arg2][%arg0, 1] :
-    memref<64x4xf32, offset: 0, strides: [4, 1]>
-    to memref<62x?xf32, offset: ?, strides: [?, 1]>
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+    to memref<62x?xf32, strided<[?, 1], offset: ?>>
   return
 }
 
@@ -471,7 +471,7 @@ func.func @subview_leading_operands(%0 : memref<5x3xf32>, %1: memref<5x?xf32>) {
   // CHECK: %[[C3_3:.*]] = llvm.mlir.constant(3 : i64) : i64
   // CHECK: llvm.insertvalue %[[C3_2]], %{{.*}}[3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
   // CHECK: llvm.insertvalue %[[C3_3]], %{{.*}}[4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
-  %2 = memref.subview %0[2, 0][3, 3][1, 1]: memref<5x3xf32> to memref<3x3xf32, offset: 6, strides: [3, 1]>
+  %2 = memref.subview %0[2, 0][3, 3][1, 1]: memref<5x3xf32> to memref<3x3xf32, strided<[3, 1], offset: 6>>
 
   return
 }
@@ -509,7 +509,7 @@ func.func @subview_leading_operands_dynamic(%0 : memref<5x?xf32>) {
   // CHECK: llvm.insertvalue %[[MUL]], %{{.*}}[4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<2 x i64>, array<2 x i64>)>
   %c0 = arith.constant 1 : index
   %d0 = memref.dim %0, %c0 : memref<5x?xf32>
-  %1 = memref.subview %0[2, 0][3, %d0][1, 1]: memref<5x?xf32> to memref<3x?xf32, offset: ?, strides: [?, 1]>
+  %1 = memref.subview %0[2, 0][3, %d0][1, 1]: memref<5x?xf32> to memref<3x?xf32, strided<[?, 1], offset: ?>>
   return
 }
 
@@ -533,7 +533,7 @@ func.func @subview_rank_reducing_leading_operands(%0 : memref<5x3xf32>) {
   // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
   // CHECK: llvm.insertvalue %[[C3]], %{{.*}}[3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
   // CHECK: llvm.insertvalue %[[C1]], %{{.*}}[4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-  %1 = memref.subview %0[1, 0][1, 3][1, 1]: memref<5x3xf32> to memref<3xf32, offset: 3, strides: [1]>
+  %1 = memref.subview %0[1, 0][1, 3][1, 1]: memref<5x3xf32> to memref<3xf32, strided<[1], offset: 3>>
 
   return
 }
@@ -608,8 +608,8 @@ func.func @address_space(%arg0 : memref<32xf32, affine_map<(d0) -> (d0)>, 7>) {
 //       CHECK:    llvm.insertvalue {{.*}}[3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<3 x i64>, array<3 x i64>)>
 //       CHECK:   llvm.extractvalue {{.*}}[3, 2] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<3 x i64>, array<3 x i64>)>
 //       CHECK:    llvm.insertvalue {{.*}}[3, 1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<3 x i64>, array<3 x i64>)>
-func.func @transpose(%arg0: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
-  %0 = memref.transpose %arg0 (i, j, k) -> (k, i, j) : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]> to memref<?x?x?xf32, affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d0 * s2 + d1)>>
+func.func @transpose(%arg0: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
+  %0 = memref.transpose %arg0 (i, j, k) -> (k, i, j) : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>> to memref<?x?x?xf32, affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d0 * s2 + d1)>>
   return
 }
 

diff  --git a/mlir/test/Dialect/Affine/memref-stride-calculation.mlir b/mlir/test/Dialect/Affine/memref-stride-calculation.mlir
index 8a0fc4e251869..50cb32076e61e 100644
--- a/mlir/test/Dialect/Affine/memref-stride-calculation.mlir
+++ b/mlir/test/Dialect/Affine/memref-stride-calculation.mlir
@@ -17,7 +17,7 @@ func.func @f(%0: index) {
 
   %11 = memref.alloc() : memref<3x4x5xf32, affine_map<(i, j, k)->(i, j, k)>>
 // CHECK: MemRefType offset: 0 strides: 20, 5, 1
-  %b11 = memref.alloc() : memref<3x4x5xf32, offset: 0, strides: [20, 5, 1]>
+  %b11 = memref.alloc() : memref<3x4x5xf32, strided<[20, 5, 1], offset: 0>>
 // CHECK: MemRefType offset: 0 strides: 20, 5, 1
   %12 = memref.alloc(%0) : memref<3x4x?xf32, affine_map<(i, j, k)->(i, j, k)>>
 // CHECK: MemRefType offset: 0 strides: ?, ?, 1
@@ -34,19 +34,19 @@ func.func @f(%0: index) {
 // CHECK: MemRefType offset: 1 strides: 32, 16, ?
   %22 = memref.alloc()[%0] : memref<3x4x5xf32, affine_map<(i, j, k)[M]->(32 * i + M * j + 16 * k + 3)>>
 // CHECK: MemRefType offset: 3 strides: 32, ?, 16
-  %b22 = memref.alloc(%0)[%0, %0] : memref<3x4x?xf32, offset: 0, strides: [?, ?, 1]>
+  %b22 = memref.alloc(%0)[%0, %0] : memref<3x4x?xf32, strided<[?, ?, 1], offset: 0>>
 // CHECK: MemRefType offset: 0 strides: ?, ?, 1
   %23 = memref.alloc(%0)[%0] : memref<3x?x5xf32, affine_map<(i, j, k)[M]->(M * i + 32 * j + 16 * k + 7)>>
 // CHECK: MemRefType offset: 7 strides: ?, 32, 16
-  %b23 = memref.alloc(%0)[%0] : memref<3x?x5xf32, offset: 0, strides: [?, 5, 1]>
+  %b23 = memref.alloc(%0)[%0] : memref<3x?x5xf32, strided<[?, 5, 1], offset: 0>>
 // CHECK: MemRefType offset: 0 strides: ?, 5, 1
   %24 = memref.alloc(%0)[%0] : memref<3x?x5xf32, affine_map<(i, j, k)[M]->(M * i + 32 * j + 16 * k + M)>>
 // CHECK: MemRefType offset: ? strides: ?, 32, 16
-  %b24 = memref.alloc(%0)[%0, %0] : memref<3x?x5xf32, offset: ?, strides: [?, 32, 16]>
+  %b24 = memref.alloc(%0)[%0, %0] : memref<3x?x5xf32, strided<[?, 32, 16], offset: ?>>
 // CHECK: MemRefType offset: ? strides: ?, 32, 16
   %25 = memref.alloc(%0, %0)[%0, %0] : memref<?x?x16xf32, affine_map<(i, j, k)[M, N]->(M * i + N * j + k + 1)>>
 // CHECK: MemRefType offset: 1 strides: ?, ?, 1
-  %b25 = memref.alloc(%0, %0)[%0, %0] : memref<?x?x16xf32, offset: 1, strides: [?, ?, 1]>
+  %b25 = memref.alloc(%0, %0)[%0, %0] : memref<?x?x16xf32, strided<[?, ?, 1], offset: 1>>
 // CHECK: MemRefType offset: 1 strides: ?, ?, 1
   %26 = memref.alloc(%0)[] : memref<?xf32, affine_map<(i)[M]->(i)>>
 // CHECK: MemRefType offset: 0 strides: 1

diff  --git a/mlir/test/Dialect/Affine/ops.mlir b/mlir/test/Dialect/Affine/ops.mlir
index df10163d59822..49b100ccdb5c0 100644
--- a/mlir/test/Dialect/Affine/ops.mlir
+++ b/mlir/test/Dialect/Affine/ops.mlir
@@ -103,8 +103,8 @@ func.func @valid_symbols(%arg0: index, %arg1: index, %arg2: index) {
     affine.for %arg4 = 0 to %13 step 264 {
       %18 = memref.dim %0, %c0 : memref<?x?xf32>
       %20 = memref.subview %0[%c0, %c0][%18,%arg4][%c1,%c1] : memref<?x?xf32>
-                          to memref<?x?xf32, offset : ?, strides : [?, ?]>
-      %24 = memref.dim %20, %c0 : memref<?x?xf32, offset : ?, strides : [?, ?]>
+                          to memref<?x?xf32, strided<[?, ?], offset: ?>>
+      %24 = memref.dim %20, %c0 : memref<?x?xf32, strided<[?, ?], offset: ?>>
       affine.for %arg5 = 0 to %24 step 768 {
         "foo"() : () -> ()
       }

diff  --git a/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir b/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
index 61493d964093c..1b3be68dd5bdc 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation.mlir
@@ -706,12 +706,12 @@ func.func @inner_region_control_flow(%arg0 : index) -> memref<?x?xf32> {
 
 // CHECK-LABEL: func @subview
 func.func @subview(%arg0 : index, %arg1 : index, %arg2 : memref<?x?xf32>) {
-  %0 = memref.alloc() : memref<64x4xf32, offset: 0, strides: [4, 1]>
+  %0 = memref.alloc() : memref<64x4xf32, strided<[4, 1], offset: 0>>
   %1 = memref.subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] :
-    memref<64x4xf32, offset: 0, strides: [4, 1]>
-  to memref<?x?xf32, offset: ?, strides: [?, ?]>
+    memref<64x4xf32, strided<[4, 1], offset: 0>>
+  to memref<?x?xf32, strided<[?, ?], offset: ?>>
   test.copy(%1, %arg2) :
-    (memref<?x?xf32, offset: ?, strides: [?, ?]>, memref<?x?xf32>)
+    (memref<?x?xf32, strided<[?, ?], offset: ?>>, memref<?x?xf32>)
   return
 }
 

diff  --git a/mlir/test/Dialect/Bufferization/canonicalize.mlir b/mlir/test/Dialect/Bufferization/canonicalize.mlir
index fa18b1502f40d..df3403941886e 100644
--- a/mlir/test/Dialect/Bufferization/canonicalize.mlir
+++ b/mlir/test/Dialect/Bufferization/canonicalize.mlir
@@ -46,52 +46,46 @@ func.func @no_fold_buffer_cast_of_tensor_load(%arg0: memref<?xf32, 2>)
 
 // -----
 
-// CHECK-DAG: #[[$OFF_3:[a-z0-9]+]] = affine_map<(d0) -> (d0 + 3)>
-// CHECK-DAG: #[[$OFF_UNK:[a-z0-9]+]] = affine_map<(d0)[s0] -> (d0 + s0)>
-
 // If the memrefs are definitely cast-compatible, canonicalize to
 //            cast.
 // CHECK-LABEL: func @canonicalize_buffer_cast_of_tensor_load(
-//  CHECK-SAME:   %[[M:.*]]: memref<?xf32, #[[$OFF_3]]>)
-//  CHECK-SAME:     -> memref<?xf32, #[[$OFF_UNK]]> {
+//  CHECK-SAME:   %[[M:.*]]: memref<?xf32, strided<[1], offset: 3>>)
+//  CHECK-SAME:     -> memref<?xf32, strided<[1], offset: ?>> {
 //   CHECK-NOT: bufferization.to_tensor
 //   CHECK-NOT: bufferization.to_memref
 //       CHECK: %[[R:.*]] = memref.cast %[[M]]
-//  CHECK-SAME:   memref<?xf32, #[[$OFF_3]]> to memref<?xf32, #[[$OFF_UNK]]>
+//  CHECK-SAME:   memref<?xf32, strided<[1], offset: 3>> to memref<?xf32, strided<[1], offset: ?>>
 //       CHECK: return %[[R]]
 func.func @canonicalize_buffer_cast_of_tensor_load(
-  %arg0: memref<?xf32, offset: 3, strides: [1]>)
-  -> memref<?xf32, offset: ?, strides: [1]>
+  %arg0: memref<?xf32, strided<[1], offset: 3>>)
+  -> memref<?xf32, strided<[1], offset: ?>>
 {
-  %0 = bufferization.to_tensor %arg0 : memref<?xf32, offset: 3, strides: [1]>
-  %1 = bufferization.to_memref %0 : memref<?xf32, offset: ?, strides: [1]>
-  return %1 : memref<?xf32, offset: ?, strides: [1]>
+  %0 = bufferization.to_tensor %arg0 : memref<?xf32, strided<[1], offset: 3>>
+  %1 = bufferization.to_memref %0 : memref<?xf32, strided<[1], offset: ?>>
+  return %1 : memref<?xf32, strided<[1], offset: ?>>
 }
 
 // -----
 
-// CHECK-DAG: #[[$OFF_UNK:[a-z0-9]+]] = affine_map<(d0)[s0] -> (d0 + s0)>
-// CHECK-DAG: #[[$OFF_3:[a-z0-9]+]] = affine_map<(d0) -> (d0 + 3)>
-
 // If the memrefs are potentially cast-compatible, canonicalize to
 //            copy.
 // CHECK-LABEL: func @canonicalize_buffer_cast_of_tensor_load_to_copy(
 func.func @canonicalize_buffer_cast_of_tensor_load_to_copy(
-  %arg0: memref<?xf32, offset: ?, strides: [1]>)
-  -> memref<?xf32, offset: 3, strides: [1]> {
-  %0 = bufferization.to_tensor %arg0 : memref<?xf32, offset: ?, strides: [1]>
-  %1 = bufferization.to_memref %0 : memref<?xf32, offset: 3, strides: [1]>
-  return %1 : memref<?xf32, offset: 3, strides: [1]>
+  %arg0: memref<?xf32, strided<[1], offset: ?>>)
+  -> memref<?xf32, strided<[1], offset: 3>> {
+  %0 = bufferization.to_tensor %arg0 : memref<?xf32, strided<[1], offset: ?>>
+  %1 = bufferization.to_memref %0 : memref<?xf32, strided<[1], offset: 3>>
+  return %1 : memref<?xf32, strided<[1], offset: 3>>
 }
-// CHECK-SAME:   %[[M:.*]]: memref<?xf32, #[[$OFF_UNK]]>)
-// CHECK-SAME:     -> memref<?xf32, #[[$OFF_3]]> {
+// CHECK-SAME:   %[[M:.*]]: memref<?xf32, strided<[1], offset: ?>>)
+// CHECK-SAME:     -> memref<?xf32, strided<[1], offset: 3>> {
 //  CHECK-NOT: bufferization.to_tensor
 //  CHECK-NOT: bufferization.to_memref
 //      CHECK: %[[C0:.*]] = arith.constant 0 : index
-//      CHECK: %[[DIM:.*]] = memref.dim %[[M]], %[[C0]] : memref<?xf32, #[[$OFF_UNK]]>
-//      CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM]]) : memref<?xf32, #[[$OFF_3]]>
+//      CHECK: %[[DIM:.*]] = memref.dim %[[M]], %[[C0]] : memref<?xf32, strided<[1], offset: ?>>
+//      CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM]]) : memref<?xf32, strided<[1], offset: 3>>
 //      CHECK: memref.copy %[[M]], %[[ALLOC]]
-// CHECK-SAME:   memref<?xf32, #[[$OFF_UNK]]> to memref<?xf32, #[[$OFF_3]]>
+// CHECK-SAME:   memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, strided<[1], offset: 3>>
 //      CHECK: return %[[ALLOC]]
 
 // -----

diff  --git a/mlir/test/Dialect/Builtin/types.mlir b/mlir/test/Dialect/Builtin/types.mlir
new file mode 100644
index 0000000000000..d01b819dc7fbb
--- /dev/null
+++ b/mlir/test/Dialect/Builtin/types.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt %s | mlir-opt | FileCheck %s
+
+// CHECK: memref<?x?xf32, strided<[?, ?], offset: ?>>
+func.func private @f1() -> memref<?x?xf32, strided<[?, ?], offset: ?>>
+// CHECK: memref<?x?xf32, strided<[42, 1], offset: 10>>
+func.func private @f2() -> memref<?x?xf32, strided<[42, 1], offset: 10>>
+// CHECK: memref<?x?xf32, strided<[?, 1], offset: 10>>
+func.func private @f3() -> memref<?x?xf32, strided<[?, 1], offset: 10>>
+// CHECK: memref<?x?xf32, strided<[?, 1], offset: ?>>
+func.func private @f4() -> memref<?x?xf32, strided<[?, 1], offset: ?>>
+// CHECK: memref<?x?xf32, strided<[42, 1]>>
+func.func private @f5() -> memref<?x?xf32, strided<[42, 1]>>
+// CHECK: memref<?x?xf32, strided<[42, 1]>>
+func.func private @f6() -> memref<?x?xf32, strided<[42, 1], offset: 0>>
+// CHECK: memref<f32, strided<[]>>
+func.func private @f7() -> memref<f32, strided<[]>>
+// CHECK: memref<f32, strided<[], offset: ?>>
+func.func private @f8() -> memref<f32, strided<[], offset: ?>>

diff  --git a/mlir/test/Dialect/Linalg/fusion-2-level.mlir b/mlir/test/Dialect/Linalg/fusion-2-level.mlir
index 83eba26982d97..0cafe4d3f3fe9 100644
--- a/mlir/test/Dialect/Linalg/fusion-2-level.mlir
+++ b/mlir/test/Dialect/Linalg/fusion-2-level.mlir
@@ -1,6 +1,6 @@
 // RUN: mlir-opt %s -test-linalg-greedy-fusion | FileCheck %s
 
-func.func @f1(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>, %C: memref<?x?xf32, offset: ?, strides: [?, 1]>, %D: memref<?x?xf32, offset: ?, strides: [?, 1]>, %E: memref<?x?xf32, offset: ?, strides: [?, 1]>) -> memref<?x?xf32, offset: ?, strides: [?, 1]> {
+func.func @f1(%A: memref<?x?xf32, strided<[?, 1], offset: ?>>, %B: memref<?x?xf32, strided<[?, 1], offset: ?>>, %C: memref<?x?xf32, strided<[?, 1], offset: ?>>, %D: memref<?x?xf32, strided<[?, 1], offset: ?>>, %E: memref<?x?xf32, strided<[?, 1], offset: ?>>) -> memref<?x?xf32, strided<[?, 1], offset: ?>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
@@ -9,35 +9,35 @@ func.func @f1(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>, %B: memref<?x?xf3
   %c40 = arith.constant 40 : index
   %c30 = arith.constant 30 : index
   %c20 = arith.constant 20 : index
-  %0 = memref.dim %C, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %1 = memref.dim %C, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %2 = memref.dim %D, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  linalg.matmul ins(%A, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>)
-               outs(%C: memref<?x?xf32, offset: ?, strides: [?, 1]>)
+  %0 = memref.dim %C, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %1 = memref.dim %C, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %2 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  linalg.matmul ins(%A, %B: memref<?x?xf32, strided<[?, 1], offset: ?>>, memref<?x?xf32, strided<[?, 1], offset: ?>>)
+               outs(%C: memref<?x?xf32, strided<[?, 1], offset: ?>>)
   scf.for %arg5 = %c0 to %0 step %c20 {
     scf.for %arg6 = %c0 to %2 step %c30 {
       scf.for %arg7 = %c0 to %1 step %c40 {
-        %5 = memref.subview %C[%arg5, %arg7][%c20, %c40][%c1, %c1] : memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-        %7 = memref.subview %D[%arg7, %arg6][%c40, %c30][%c1, %c1]: memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-        %8 = memref.subview %E[%arg5, %arg6][%c20, %c40][%c1, %c1] : memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-        %9 = memref.dim %5, %c0 : memref<?x?xf32, offset: ?, strides: [?, ?]>
-        %10 = memref.dim %5, %c1 : memref<?x?xf32, offset: ?, strides: [?, ?]>
-        %11 = memref.dim %7, %c1 : memref<?x?xf32, offset: ?, strides: [?, ?]>
+        %5 = memref.subview %C[%arg5, %arg7][%c20, %c40][%c1, %c1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+        %7 = memref.subview %D[%arg7, %arg6][%c40, %c30][%c1, %c1]: memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+        %8 = memref.subview %E[%arg5, %arg6][%c20, %c40][%c1, %c1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+        %9 = memref.dim %5, %c0 : memref<?x?xf32, strided<[?, ?], offset: ?>>
+        %10 = memref.dim %5, %c1 : memref<?x?xf32, strided<[?, ?], offset: ?>>
+        %11 = memref.dim %7, %c1 : memref<?x?xf32, strided<[?, ?], offset: ?>>
         scf.for %arg8 = %c0 to %9 step %c2 {
           scf.for %arg9 = %c0 to %11 step %c3 {
             scf.for %arg10 = %c0 to %10 step %c4 {
-              %14 = memref.subview %5[%arg8, %arg10][%c2, %c4][%c1, %c1] : memref<?x?xf32, offset: ?, strides: [?, ?]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-              %16 = memref.subview %7[%arg10, %arg9][%c4, %c3][%c1, %c1]: memref<?x?xf32, offset: ?, strides: [?, ?]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-              %17 = memref.subview %8[%arg8, %arg9][%c2, %c3][%c1, %c1] : memref<?x?xf32, offset: ?, strides: [?, ?]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-              linalg.matmul ins(%14, %16: memref<?x?xf32, offset: ?, strides: [?, ?]>, memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                           outs(%17: memref<?x?xf32, offset: ?, strides: [?, ?]>)
+              %14 = memref.subview %5[%arg8, %arg10][%c2, %c4][%c1, %c1] : memref<?x?xf32, strided<[?, ?], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+              %16 = memref.subview %7[%arg10, %arg9][%c4, %c3][%c1, %c1]: memref<?x?xf32, strided<[?, ?], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+              %17 = memref.subview %8[%arg8, %arg9][%c2, %c3][%c1, %c1] : memref<?x?xf32, strided<[?, ?], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+              linalg.matmul ins(%14, %16: memref<?x?xf32, strided<[?, ?], offset: ?>>, memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                           outs(%17: memref<?x?xf32, strided<[?, ?], offset: ?>>)
             }
           }
         }
       }
     }
   }
-  return %E : memref<?x?xf32, offset: ?, strides: [?, 1]>
+  return %E : memref<?x?xf32, strided<[?, 1], offset: ?>>
 }
 // CHECK-LABEL: func @f1
 //       CHECK:   (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})

diff  --git a/mlir/test/Dialect/Linalg/fusion.mlir b/mlir/test/Dialect/Linalg/fusion.mlir
index 3218fa4df4159..225718ee059fd 100644
--- a/mlir/test/Dialect/Linalg/fusion.mlir
+++ b/mlir/test/Dialect/Linalg/fusion.mlir
@@ -1,41 +1,41 @@
 // RUN: mlir-opt %s -test-linalg-greedy-fusion -split-input-file | FileCheck %s
 
-func.func @f1(%A: memref<?x?xf32, offset: 0, strides: [?, 1]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, 1]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, 1]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, 1]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, 1]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, 1]> {
+func.func @f1(%A: memref<?x?xf32, strided<[?, 1], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, 1], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, 1], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, 1], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, 1], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, 1], offset: 0>> {
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
   %c1 = arith.constant 1 : index
-  %0 = memref.dim %A, %c0 : memref<?x?xf32, offset: 0, strides: [?, 1]>
-  %1 = memref.dim %A, %c1 : memref<?x?xf32, offset: 0, strides: [?, 1]>
-  %2 = memref.dim %B, %c1 : memref<?x?xf32, offset: 0, strides: [?, 1]>
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, 1]>,
-                             memref<?x?xf32, offset: 0, strides: [?, 1]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, 1]>)
+  %0 = memref.dim %A, %c0 : memref<?x?xf32, strided<[?, 1], offset: 0>>
+  %1 = memref.dim %A, %c1 : memref<?x?xf32, strided<[?, 1], offset: 0>>
+  %2 = memref.dim %B, %c1 : memref<?x?xf32, strided<[?, 1], offset: 0>>
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, 1], offset: 0>>,
+                             memref<?x?xf32, strided<[?, 1], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, 1], offset: 0>>)
   scf.for %arg5 = %c0 to %0 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %1 step %c4 {
         %5 = memref.subview %A[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, 1]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, 1], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %7 = memref.subview %B[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, 1]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, 1], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %C[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, 1]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8: memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, 1], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8: memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, 1]>
+  return %E : memref<?x?xf32, strided<[?, 1], offset: 0>>
 }
 // CHECK-LABEL: func @f1
 // CHECK:   (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
@@ -47,49 +47,48 @@ func.func @f1(%A: memref<?x?xf32, offset: 0, strides: [?, 1]>,
 
 // -----
 
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 * s1)>
-func.func @f2(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f2(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C: memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  %0 = memref.dim %C, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %C, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %2 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C: memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  %0 = memref.dim %C, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %C, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %2 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
   scf.for %arg5 = %c0 to %0 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %1 step %c4 {
         %5 = memref.subview %C[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %7 = memref.subview %D[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 // CHECK-LABEL: func @f2
 // CHECK:  (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
-// CHECK-DAG:  %[[C_0:.*]] = memref.dim %[[C]], %c0{{[_0-9]*}} : memref<?x?xf32, #[[$strided2D]]>
-// CHECK-DAG:  %[[C_1:.*]] = memref.dim %[[C]], %c1{{[_0-9]*}} : memref<?x?xf32, #[[$strided2D]]>
-// CHECK-DAG:  %[[D_1:.*]] = memref.dim %[[D]], %c1{{[_0-9]*}} : memref<?x?xf32, #[[$strided2D]]>
+// CHECK-DAG:  %[[C_0:.*]] = memref.dim %[[C]], %c0{{[_0-9]*}} : memref<?x?xf32, strided<[?, ?]>>
+// CHECK-DAG:  %[[C_1:.*]] = memref.dim %[[C]], %c1{{[_0-9]*}} : memref<?x?xf32, strided<[?, ?]>>
+// CHECK-DAG:  %[[D_1:.*]] = memref.dim %[[D]], %c1{{[_0-9]*}} : memref<?x?xf32, strided<[?, ?]>>
 // CHECK:  scf.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
 // CHECK:    scf.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
 // CHECK:      scf.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
@@ -98,52 +97,50 @@ func.func @f2(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 
 // -----
 
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 * s1)>
-
-func.func @f3(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f3(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  %0 = memref.dim %D, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %2 = memref.dim %C, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  %0 = memref.dim %D, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %2 = memref.dim %C, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
   scf.for %arg5 = %c0 to %0 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %1 step %c4 {
         %5 = memref.subview %D[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %7 = memref.subview %C[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 // CHECK-LABEL: func @f3
 // CHECK:  (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
 // CHECK-DAG:  %[[C0:.*]] = arith.constant 0 : index
 // CHECK-DAG:  %[[C1:.*]] = arith.constant 1 : index
-// CHECK:  %[[D_0:.*]] = memref.dim %[[D]], %[[C0]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[C_1:.*]] = memref.dim %[[C]], %[[C1]] : memref<?x?xf32, #[[$strided2D]]>
+// CHECK:  %[[D_0:.*]] = memref.dim %[[D]], %[[C0]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[C_1:.*]] = memref.dim %[[C]], %[[C1]] : memref<?x?xf32, strided<[?, ?]>>
 // CHECK:  scf.for %{{.*}} = %{{.*}} to %[[D_0]] step %{{.*}} {
 // CHECK:    scf.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
 // CHECK:      scf.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
@@ -152,55 +149,53 @@ func.func @f3(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 
 // -----
 
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 * s1)>
-
-func.func @f4(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f4(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%D : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  %0 = memref.dim %C, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %C, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %2 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%D : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  %0 = memref.dim %C, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %C, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %2 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
   scf.for %arg5 = %c0 to %0 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %1 step %c4 {
         %5 = memref.subview %C[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %7 = memref.subview %D[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 // CHECK-LABEL: func @f4
 // CHECK:  (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
 // CHECK-DAG:  %[[C0:.*]] = arith.constant 0 : index
 // CHECK-DAG:  %[[C1:.*]] = arith.constant 1 : index
-// CHECK:  %[[C_0:.*]] = memref.dim %[[C]], %[[C0:.*]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[C_1:.*]] = memref.dim %[[C]], %[[C1:.*]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1:.*]] : memref<?x?xf32, #[[$strided2D]]>
+// CHECK:  %[[C_0:.*]] = memref.dim %[[C]], %[[C0:.*]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[C_1:.*]] = memref.dim %[[C]], %[[C1:.*]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1:.*]] : memref<?x?xf32, strided<[?, ?]>>
 // CHECK:  scf.for %{{.*}} = %{{.*}} to %[[C_0]] step %{{.*}} {
 // CHECK:    scf.for %{{.*}} = %{{.*}} to %[[D_1]] step %{{.*}} {
 // CHECK:      scf.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
@@ -211,46 +206,45 @@ func.func @f4(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 
 // -----
 
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s0 + d1 * s1)>
-func.func @f5(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f5(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  %0 = memref.dim %B, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %D, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %2 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  linalg.matmul ins(%C, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%D : memref<?x?xf32, offset: 0, strides: [?, ?]>)
+  %0 = memref.dim %B, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %D, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %2 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  linalg.matmul ins(%C, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%D : memref<?x?xf32, strided<[?, ?], offset: 0>>)
   scf.for %arg5 = %c0 to %1 step %c2 {
     scf.for %arg6 = %c0 to %0 step %c3 {
       scf.for %arg7 = %c0 to %2 step %c4 {
         %5 = memref.subview %D[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %7 = memref.subview %B[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 
 // CHECK-DAG: #[[BOUND_2_MAP:.+]] = affine_map<(d0)[s0] -> (-d0 + s0, 2)>
@@ -260,11 +254,11 @@ func.func @f5(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 // CHECK-SAME:  (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
 // CHECK-DAG:  %[[C0:.*]] = arith.constant 0 : index
 // CHECK-DAG:  %[[C1:.*]] = arith.constant 1 : index
-// CHECK-DAG:  %[[A_0:.*]] = memref.dim %[[A]], %[[C0]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK-DAG:  %[[B_1:.*]] = memref.dim %[[B]], %[[C1]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK-DAG:  %[[C_0:.*]] = memref.dim %[[C]], %[[C0]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK-DAG:  %[[D_0:.*]] = memref.dim %[[D]], %[[C0]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK-DAG:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1]] : memref<?x?xf32, #[[$strided2D]]>
+// CHECK-DAG:  %[[A_0:.*]] = memref.dim %[[A]], %[[C0]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK-DAG:  %[[B_1:.*]] = memref.dim %[[B]], %[[C1]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK-DAG:  %[[C_0:.*]] = memref.dim %[[C]], %[[C0]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK-DAG:  %[[D_0:.*]] = memref.dim %[[D]], %[[C0]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK-DAG:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1]] : memref<?x?xf32, strided<[?, ?]>>
 // CHECK-DAG:  %[[B_00:.*]] = memref.subview %[[B]][0, 0]{{.*}}
 //     CHECK:  scf.for %[[I:.*]] = %{{.*}} to %[[D_0]] step %{{.*}} {
 //     CHECK:    %[[BOUND_2_C0:.+]] = affine.min #[[BOUND_2_MAP]](%[[I]])[%[[C_0]]]
@@ -290,48 +284,48 @@ func.func @f5(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 #map1 = affine_map<(d0) -> (d0 + 4)>
 #map2 = affine_map<(d0) -> (d0 + 3)>
 
-func.func @f6(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f6(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  %0 = memref.dim %C, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  linalg.matmul ins(%A, %C : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%E : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  %1 = memref.dim %C, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %2 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  %0 = memref.dim %C, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  linalg.matmul ins(%A, %C : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%E : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  %1 = memref.dim %C, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %2 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
   scf.for %arg5 = %c0 to %1 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %0 step %c4 {
         %3 = affine.apply #map0(%arg5)
         %4 = affine.apply #map1(%arg7)
         %5 = memref.subview %C[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %6 = affine.apply #map2(%arg6)
         %7 = memref.subview %D[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 // CHECK-LABEL: func @f6
 // CHECK:  (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
@@ -345,43 +339,43 @@ func.func @f6(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 
 // -----
 
-func.func @f7(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f7(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  %0 = memref.dim %A, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %A, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %2 = memref.dim %C, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %3 = memref.dim %C, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %4 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  linalg.matmul ins(%A, %C : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%E : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
+  %0 = memref.dim %A, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %A, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %2 = memref.dim %C, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %3 = memref.dim %C, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %4 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  linalg.matmul ins(%A, %C : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%E : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
   scf.for %arg5 = %c0 to %0 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %1 step %c4 {
         %7 = memref.subview %A[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %9 = memref.subview %C[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %10 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%7, %9 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%10 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%7, %9 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%10 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
@@ -389,31 +383,31 @@ func.func @f7(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
     scf.for %arg6 = %c0 to %4 step %c3 {
       scf.for %arg7 = %c0 to %2 step %c4 {
         %7 = memref.subview %C[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %9 = memref.subview %D[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %10 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%7, %9 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%10 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%7, %9 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%10 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 // CHECK-LABEL: func @f7
 // CHECK:  (%[[A:.*]]:{{.*}}, %[[B:.*]]:{{.*}}, %[[C:.*]]:{{.*}}, %[[D:.*]]:{{.*}}, %[[E:.*]]:{{.*}})
 // CHECK-DAG:  %[[C0:.*]] = arith.constant 0 : index
 // CHECK-DAG:  %[[C1:.*]] = arith.constant 1 : index
-// CHECK:  %[[A_0:.*]] = memref.dim %[[A]], %[[C0:.*]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[A_1:.*]] = memref.dim %[[A]], %[[C1:.*]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[C_1:.*]] = memref.dim %[[C]], %[[C1:.*]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[C_0:.*]] = memref.dim %[[C]], %[[C0:.*]] : memref<?x?xf32, #[[$strided2D]]>
-// CHECK:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1:.*]] : memref<?x?xf32, #[[$strided2D]]>
+// CHECK:  %[[A_0:.*]] = memref.dim %[[A]], %[[C0:.*]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[A_1:.*]] = memref.dim %[[A]], %[[C1:.*]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[C_1:.*]] = memref.dim %[[C]], %[[C1:.*]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[C_0:.*]] = memref.dim %[[C]], %[[C0:.*]] : memref<?x?xf32, strided<[?, ?]>>
+// CHECK:  %[[D_1:.*]] = memref.dim %[[D]], %[[C1:.*]] : memref<?x?xf32, strided<[?, ?]>>
 // CHECK:  linalg.matmul ins(%[[A]], %[[C]]{{.*}} outs(%[[E]]
 // CHECK:  scf.for %{{.*}} = %{{.*}} to %[[A_0]] step %{{.*}} {
 // CHECK:    scf.for %{{.*}} = %{{.*}} to %[[C_1]] step %{{.*}} {
@@ -432,48 +426,48 @@ func.func @f7(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
 #map1 = affine_map<(d0) -> (d0 + 4)>
 #map2 = affine_map<(d0) -> (d0 + 3)>
 
-func.func @f8(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %D: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-         %E: memref<?x?xf32, offset: 0, strides: [?, ?]>
-        ) -> memref<?x?xf32, offset: 0, strides: [?, ?]> {
+func.func @f8(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %D: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+         %E: memref<?x?xf32, strided<[?, ?], offset: 0>>
+        ) -> memref<?x?xf32, strided<[?, ?], offset: 0>> {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c4 = arith.constant 4 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
-  %0 = memref.dim %A, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %A, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  linalg.matmul ins(%A, %C : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%D : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
-  %2 = memref.dim %D, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  %0 = memref.dim %A, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %A, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  linalg.matmul ins(%A, %C : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%D : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
+  %2 = memref.dim %D, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
   scf.for %arg5 = %c0 to %0 step %c2 {
     scf.for %arg6 = %c0 to %2 step %c3 {
       scf.for %arg7 = %c0 to %1 step %c4 {
         %3 = affine.apply #map0(%arg5)
         %4 = affine.apply #map1(%arg7)
         %5 = memref.subview %A[%arg5, %arg7][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %6 = affine.apply #map2(%arg6)
         %7 = memref.subview %D[%arg7, %arg6][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %8 = memref.subview %E[%arg5, %arg6][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%5, %7 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%8 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%5, %7 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%8 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
-  return %E : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  return %E : memref<?x?xf32, strided<[?, ?], offset: 0>>
 }
 // CHECK-LABEL: func @f8
 // CHECK:  (%[[A:.*]]: memref{{.*}}, %[[B:.*]]: memref{{.*}}, %[[C:.*]]: memref{{.*}}, %[[D:.*]]: memref{{.*}}, %[[E:.*]]: memref{{.*}})
@@ -492,39 +486,39 @@ func.func @f8(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
   indexing_maps = [#id_2d, #id_2d, #id_2d],
   iterator_types = ["parallel", "parallel"]
 }
-func.func @pointwise(%A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                %B: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                %C: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                %D: memref<?x?xf32, offset: 0, strides: [?, ?]>) {
+func.func @pointwise(%A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                %B: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                %C: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                %D: memref<?x?xf32, strided<[?, ?], offset: 0>>) {
   %c1 = arith.constant 1 : index
   %c0 = arith.constant 0 : index
   %c3 = arith.constant 3 : index
   %c2 = arith.constant 2 : index
   linalg.generic #pointwise_2d_trait
-      ins(%A, %A: memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                  memref<?x?xf32, offset: 0, strides: [?, ?]>)
-     outs(%B : memref<?x?xf32, offset: 0, strides: [?, ?]>) {
+      ins(%A, %A: memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                  memref<?x?xf32, strided<[?, ?], offset: 0>>)
+     outs(%B : memref<?x?xf32, strided<[?, ?], offset: 0>>) {
   ^bb0(%E: f32, %arg5: f32, %arg6: f32):
     %2 = arith.addf %E, %arg5 : f32
     linalg.yield %2 : f32
   }
-  %0 = memref.dim %B, %c0 : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %1 = memref.dim %B, %c1 : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  %0 = memref.dim %B, %c0 : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %1 = memref.dim %B, %c1 : memref<?x?xf32, strided<[?, ?], offset: 0>>
   scf.for %arg4 = %c0 to %0 step %c2 {
     scf.for %arg5 = %c0 to %1 step %c3 {
       %4 = memref.subview %B[%arg4, %arg5][%c2, %c3][%c1, %c1] :
-        memref<?x?xf32, offset: 0, strides: [?, ?]> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+        memref<?x?xf32, strided<[?, ?], offset: 0>> to
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
       %5 = memref.subview %C[%arg4, %arg5][%c2, %c3][%c1, %c1] :
-        memref<?x?xf32, offset: 0, strides: [?, ?]> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+        memref<?x?xf32, strided<[?, ?], offset: 0>> to
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
       %6 = memref.subview %D[%arg4, %arg5][%c2, %c3][%c1, %c1] :
-        memref<?x?xf32, offset: 0, strides: [?, ?]> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+        memref<?x?xf32, strided<[?, ?], offset: 0>> to
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
       linalg.generic #pointwise_2d_trait
-        ins(%4, %5: memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                    memref<?x?xf32, offset: ?, strides: [?, ?]>)
-       outs(%6 : memref<?x?xf32, offset: ?, strides: [?, ?]>) {
+        ins(%4, %5: memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                    memref<?x?xf32, strided<[?, ?], offset: ?>>)
+       outs(%6 : memref<?x?xf32, strided<[?, ?], offset: ?>>) {
       ^bb0(%arg6: f32, %arg7: f32, %arg8: f32):
         %7 = arith.mulf %arg6, %arg7 : f32
         linalg.yield %7 : f32
@@ -572,17 +566,17 @@ func.func @pointwise_no_view(%M: index, %N: index) {
     scf.for %arg5 = %c0 to %1 step %c3 {
       %4 = memref.subview %B[%arg4, %arg5][%c2, %c3][%c1, %c1] :
         memref<?x?xf32> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
       %5 = memref.subview %C[%arg4, %arg5][%c2, %c3][%c1, %c1] :
         memref<?x?xf32> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
       %6 = memref.subview %D[%arg4, %arg5][%c2, %c3][%c1, %c1] :
         memref<?x?xf32> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
       linalg.generic #pointwise_2d_trait
-        ins(%4, %5: memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                    memref<?x?xf32, offset: ?, strides: [?, ?]>)
-       outs(%6 : memref<?x?xf32, offset: ?, strides: [?, ?]>) {
+        ins(%4, %5: memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                    memref<?x?xf32, strided<[?, ?], offset: ?>>)
+       outs(%6 : memref<?x?xf32, strided<[?, ?], offset: ?>>) {
       ^bb0(%arg6: f32, %arg7: f32, %arg8: f32):
         %7 = arith.mulf %arg6, %arg7 : f32
         linalg.yield %7 : f32
@@ -719,29 +713,29 @@ func.func @accept_
diff erent_alloc_ops(%dim: index, %s0 : index, %s1: index) {
   %c3 = arith.constant 3 : index
   %c4 = arith.constant 4 : index
 
-  %A = memref.alloca(%dim, %dim)[%s0, %s1] : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %B = memref.alloca(%dim, %dim)[%s0, %s1] : memref<?x?xf32, offset: 0, strides: [?, ?]>
-  %C = memref.alloc(%dim, %dim)[%s0, %s1]  : memref<?x?xf32, offset: 0, strides: [?, ?]>
+  %A = memref.alloca(%dim, %dim)[%s0, %s1] : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %B = memref.alloca(%dim, %dim)[%s0, %s1] : memref<?x?xf32, strided<[?, ?], offset: 0>>
+  %C = memref.alloc(%dim, %dim)[%s0, %s1]  : memref<?x?xf32, strided<[?, ?], offset: 0>>
 
-  linalg.matmul ins(%A, %B : memref<?x?xf32, offset: 0, strides: [?, ?]>,
-                             memref<?x?xf32, offset: 0, strides: [?, ?]>)
-               outs(%C : memref<?x?xf32, offset: 0, strides: [?, ?]>)
+  linalg.matmul ins(%A, %B : memref<?x?xf32, strided<[?, ?], offset: 0>>,
+                             memref<?x?xf32, strided<[?, ?], offset: 0>>)
+               outs(%C : memref<?x?xf32, strided<[?, ?], offset: 0>>)
 
   scf.for %i = %c0 to %dim step %c2 {
     scf.for %j = %c0 to %dim step %c3 {
       scf.for %k = %c0 to %dim step %c4 {
         %0 = memref.subview %A[%i, %k][%c2, %c4][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %1 = memref.subview %B[%k, %j][%c4, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
         %2 = memref.subview %C[%i, %j][%c2, %c3][%c1, %c1] :
-          memref<?x?xf32, offset: 0, strides: [?, ?]> to
-          memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%0, %1 : memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%2 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          memref<?x?xf32, strided<[?, ?], offset: 0>> to
+          memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%0, %1 : memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%2 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }

diff  --git a/mlir/test/Dialect/Linalg/loops.mlir b/mlir/test/Dialect/Linalg/loops.mlir
index 208664aa03bc6..d1be939c6b297 100644
--- a/mlir/test/Dialect/Linalg/loops.mlir
+++ b/mlir/test/Dialect/Linalg/loops.mlir
@@ -4,15 +4,9 @@
 // Test that we can lower all the way to LLVM without crashing, don't check results here.
 // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -o=/dev/null 2>&1
 
-// CHECK-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
-// CHECK-DAG: #[[$strided3D:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2 + d2)>
-// CHECK-DAG: #[[$stride1Dilation1:.*]] = affine_map<(d0, d1) -> (d0  + d1)>
+// CHECK: #[[$stride1Dilation1:.*]] = affine_map<(d0, d1) -> (d0 + d1)>
 
-// CHECKPARALLEL-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
-// CHECKPARALLEL-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
-// CHECKPARALLEL-DAG: #[[$strided3D:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2 + d2)>
-// CHECKPARALLEL-DAG: #[[$stride1Dilation1:.*]] = affine_map<(d0, d1) -> (d0  + d1)>
+// CHECKPARALLEL: #[[$stride1Dilation1:.*]] = affine_map<(d0, d1) -> (d0 + d1)>
 
 func.func @matmul(%arg0: memref<?xi8>, %M: index, %N: index, %K: index) {
   %c0 = arith.constant 0 : index
@@ -163,47 +157,47 @@ func.func @dot_bool(%arg0: memref<?xi1>, %arg1: memref<?xi1>,
 //  CHECK-NEXT:   store %[[res]], {{.*}} : memref<i1>
 
 
-func.func @dot_view(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: memref<?xf32, offset: ?, strides: [1]>, %arg2: memref<f32>) {
-  linalg.dot ins(%arg0, %arg1 : memref<?xf32, offset: ?, strides: [1]>,
-                                memref<?xf32, offset: ?, strides: [1]>)
+func.func @dot_view(%arg0: memref<?xf32, strided<[1], offset: ?>>, %arg1: memref<?xf32, strided<[1], offset: ?>>, %arg2: memref<f32>) {
+  linalg.dot ins(%arg0, %arg1 : memref<?xf32, strided<[1], offset: ?>>,
+                                memref<?xf32, strided<[1], offset: ?>>)
             outs(%arg2:  memref<f32>)
   return
 }
 // CHECK-LABEL: func @dot_view(
-//       CHECK:   %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: memref<f32>) {
-//       CHECK: %[[K:.*]] = memref.dim %arg0, %c0 : memref<?xf32, #[[$strided1D]]>
+//       CHECK:   %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: memref<f32>) {
+//       CHECK: %[[K:.*]] = memref.dim %arg0, %c0 : memref<?xf32, strided<[1], offset: ?>>
 //       CHECK: scf.for {{.*}} to %[[K]]
-//   CHECK-DAG:   %[[a:.*]] = memref.load %arg0[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
-//   CHECK-DAG:   %[[b:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
+//   CHECK-DAG:   %[[a:.*]] = memref.load %arg0[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
+//   CHECK-DAG:   %[[b:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
 //   CHECK-DAG:   %[[inc:.*]] = arith.mulf %[[a]], %[[b]] : f32
 //   CHECK-DAG:   %[[c:.*]] = memref.load %{{.*}}[] : memref<f32>
 //   CHECK-DAG:   %[[res:.*]] = arith.addf %[[c]], %[[inc]] : f32
 //       CHECK:   store %[[res]], %{{.*}}[] : memref<f32>
 
 // CHECKPARALLEL-LABEL: func @dot_view(
-//       CHECKPARALLEL:   %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: memref<f32>) {
-//       CHECKPARALLEL: %[[K:.*]] = memref.dim %arg0, %c0 : memref<?xf32, #[[$strided1D]]>
+//       CHECKPARALLEL:   %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: memref<f32>) {
+//       CHECKPARALLEL: %[[K:.*]] = memref.dim %arg0, %c0 : memref<?xf32, strided<[1], offset: ?>>
 //       CHECKPARALLEL: scf.for {{.*}} to %[[K]]
-//   CHECKPARALLEL-DAG:   %[[a:.*]] = memref.load %arg0[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
-//   CHECKPARALLEL-DAG:   %[[b:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
+//   CHECKPARALLEL-DAG:   %[[a:.*]] = memref.load %arg0[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
+//   CHECKPARALLEL-DAG:   %[[b:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
 //   CHECKPARALLEL-DAG:   %[[inc:.*]] = arith.mulf %[[a]], %[[b]] : f32
 //   CHECKPARALLEL-DAG:   %[[c:.*]] = memref.load %{{.*}}[] : memref<f32>
 //   CHECKPARALLEL-DAG:   %[[res:.*]] = arith.addf %[[c]], %[[inc]] : f32
 //       CHECKPARALLEL:   store %[[res]], %{{.*}}[] : memref<f32>
 
-func.func @fill_view(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: f32) {
-  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?xf32, offset: ?, strides: [1]>)
+func.func @fill_view(%arg0: memref<?xf32, strided<[1], offset: ?>>, %arg1: f32) {
+  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?xf32, strided<[1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @fill_view(
-//       CHECK: %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: f32) {
+//       CHECK: %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: f32) {
 //       CHECK:   scf.for {{.*}} to %{{.*}}
-//       CHECK:     store %{{.*}}, %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
+//       CHECK:     store %{{.*}}, %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
 
 // CHECKPARALLEL-LABEL: func @fill_view(
-//       CHECKPARALLEL: %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: f32) {
+//       CHECKPARALLEL: %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: f32) {
 //       CHECKPARALLEL:   scf.parallel (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) {
-//       CHECKPARALLEL:     store %{{.*}}, %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
+//       CHECKPARALLEL:     store %{{.*}}, %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
 
 func.func @fill_view0(%arg0: memref<f32>, %arg1: f32) {
   linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<f32>)
@@ -215,44 +209,44 @@ func.func @fill_view0(%arg0: memref<f32>, %arg1: f32) {
 // CHECKPARALLEL-LABEL: func @fill_view0(%{{.*}}: memref<f32>, %{{.*}}: f32) {
 //       CHECKPARALLEL:   store %{{.*}}, %{{.*}}[] : memref<f32>
 
-func.func @fill_view3(%arg0: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, %arg1: f32) {
-  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>)
+func.func @fill_view3(%arg0: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>, %arg1: f32) {
+  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @fill_view3(
-//       CHECK: %{{.*}}: memref<?x?x?xf32, #[[$strided3D]]>, %{{.*}}: f32) {
+//       CHECK: %{{.*}}: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>, %{{.*}}: f32) {
 //       CHECK:   scf.for {{.*}} to %{{.*}}
 //       CHECK:     scf.for {{.*}} to %{{.*}}
 //       CHECK:       scf.for {{.*}} to %{{.*}}
-//       CHECK:         store %{{.*}}, {{.*}} : memref<?x?x?xf32, #[[$strided3D]]>
+//       CHECK:         store %{{.*}}, {{.*}} : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
 
 // CHECKPARALLEL-LABEL: func @fill_view3(
-//       CHECKPARALLEL: %{{.*}}: memref<?x?x?xf32, #[[$strided3D]]>, %{{.*}}: f32) {
+//       CHECKPARALLEL: %{{.*}}: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>, %{{.*}}: f32) {
 //       CHECKPARALLEL:   scf.parallel (%{{.*}}, %{{.*}}, %{{.*}}) = (%{{.*}}, %{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}}, %{{.*}}) {
-//       CHECKPARALLEL:     store %{{.*}}, {{.*}} : memref<?x?x?xf32, #[[$strided3D]]>
+//       CHECKPARALLEL:     store %{{.*}}, {{.*}} : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
 
-func.func @copy_view(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: memref<?xf32, offset: ?, strides: [1]>) {
+func.func @copy_view(%arg0: memref<?xf32, strided<[1], offset: ?>>, %arg1: memref<?xf32, strided<[1], offset: ?>>) {
   linalg.generic {
     iterator_types = ["parallel"],
     indexing_maps = [ affine_map<(i) -> (i)>, affine_map<(i) -> (i)>] }
-    ins(%arg0: memref<?xf32, offset: ?, strides: [1]>)
-   outs(%arg1: memref<?xf32, offset: ?, strides : [1]>) {
+    ins(%arg0: memref<?xf32, strided<[1], offset: ?>>)
+   outs(%arg1: memref<?xf32, strided<[1], offset: ?>>) {
     ^bb0(%a: f32, %b: f32):
       linalg.yield %a : f32
   }
   return
 }
 // CHECK-LABEL: func @copy_view(
-//       CHECK: %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: memref<?xf32, #[[$strided1D]]>) {
+//       CHECK: %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: memref<?xf32, strided<[1], offset: ?>>) {
 //       CHECK:   scf.for {{.*}} to %{{.*}}
-//       CHECK:     %[[L:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
-//       CHECK:     store %[[L]], %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
+//       CHECK:     %[[L:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
+//       CHECK:     store %[[L]], %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
 
 // CHECKPARALLEL-LABEL: func @copy_view(
-//       CHECKPARALLEL: %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: memref<?xf32, #[[$strided1D]]>) {
+//       CHECKPARALLEL: %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: memref<?xf32, strided<[1], offset: ?>>) {
 //       CHECKPARALLEL:   scf.parallel (%{{.*}}) = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) {
-//       CHECKPARALLEL:     %[[L:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
-//       CHECKPARALLEL:     store %[[L]], %{{.*}}[%{{.*}}] : memref<?xf32, #[[$strided1D]]>
+//       CHECKPARALLEL:     %[[L:.*]] = memref.load %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
+//       CHECKPARALLEL:     store %[[L]], %{{.*}}[%{{.*}}] : memref<?xf32, strided<[1], offset: ?>>
 
 #accesses = [
   affine_map<(i, j, k) -> (i, j)>,
@@ -267,11 +261,11 @@ func.func @copy_view(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: memre
   library_call = "some_external_function_name_2",
   doc = "B(i,j,k), C(i,k,j) = foo(A(i, j), B(i,j,k), C(i,k,j))"
 }
-func.func @generic_region(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, %arg2: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+func.func @generic_region(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>, %arg1: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>, %arg2: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
   linalg.generic #trait2
-    ins(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>)
-   outs(%arg1, %arg2 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>,
-                       memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+    ins(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>)
+   outs(%arg1, %arg2 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>,
+                       memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
     ^bb0(%a: f32, %b: f32, %c: f32):
       %d = arith.mulf %a, %b : f32
       %e = arith.addf %c, %d : f32
@@ -283,23 +277,23 @@ func.func @generic_region(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %a
 //       CHECK: scf.for %[[i:.*]] = {{.*}}
 //       CHECK:   scf.for %[[j:.*]] = {{.*}}
 //       CHECK:     scf.for %[[k:.*]] = {{.*}}
-//       CHECK:       %[[a:.*]] = memref.load %{{.*}}[%[[i]], %[[j]]] : memref<?x?xf32, #[[$strided2D]]>
-//       CHECK:       %[[b:.*]] = memref.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, #[[$strided3D]]>
-//       CHECK:       %[[c:.*]] = memref.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, #[[$strided3D]]>
+//       CHECK:       %[[a:.*]] = memref.load %{{.*}}[%[[i]], %[[j]]] : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       CHECK:       %[[b:.*]] = memref.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
+//       CHECK:       %[[c:.*]] = memref.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
 //       CHECK:       %[[d:.*]] = arith.mulf %[[a]], %[[b]] : f32
 //       CHECK:       %[[e:.*]] = arith.addf %[[c]], %[[d]] : f32
-//       CHECK:       store %[[d]], %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, #[[$strided3D]]>
-//       CHECK:       store %[[e]], %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, #[[$strided3D]]>
+//       CHECK:       store %[[d]], %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
+//       CHECK:       store %[[e]], %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
 
 // CHECKPARALLEL-LABEL: @generic_region
 //       CHECKPARALLEL: scf.parallel (%[[i:[a-zA-Z0-9_]*]], %[[j:[a-zA-Z0-9_]*]], %[[k:[a-zA-Z0-9_]*]])
-//       CHECKPARALLEL:   %[[a:.*]] = memref.load %{{.*}}[%[[i]], %[[j]]] : memref<?x?xf32, #[[$strided2D]]>
-//       CHECKPARALLEL:   %[[b:.*]] = memref.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, #[[$strided3D]]>
-//       CHECKPARALLEL:   %[[c:.*]] = memref.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, #[[$strided3D]]>
+//       CHECKPARALLEL:   %[[a:.*]] = memref.load %{{.*}}[%[[i]], %[[j]]] : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       CHECKPARALLEL:   %[[b:.*]] = memref.load %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
+//       CHECKPARALLEL:   %[[c:.*]] = memref.load %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
 //       CHECKPARALLEL:   %[[d:.*]] = arith.mulf %[[a]], %[[b]] : f32
 //       CHECKPARALLEL:   %[[e:.*]] = arith.addf %[[c]], %[[d]] : f32
-//       CHECKPARALLEL:   store %[[d]], %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, #[[$strided3D]]>
-//       CHECKPARALLEL:   store %[[e]], %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, #[[$strided3D]]>
+//       CHECKPARALLEL:   store %[[d]], %{{.*}}[%[[i]], %[[j]], %[[k]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
+//       CHECKPARALLEL:   store %[[e]], %{{.*}}[%[[i]], %[[k]], %[[j]]] : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>
 
 #trait4 = {
   args_in = 1,
@@ -310,13 +304,13 @@ func.func @generic_region(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %a
   doc = "B(i,j,k), C(i,k,j) = foo(A(i, j) * B(i,j,k), i * j * k + C(i,k,j))"
 }
 func.func @generic_index_region(
-        %arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-        %arg1: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>,
-        %arg2: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+        %arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+        %arg1: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>,
+        %arg2: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
   linalg.generic #trait4
-      ins(%arg0 : memref<?x?xf32, offset: ?, strides: [?, 1]>)
-     outs(%arg1, %arg2 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>,
-                         memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+      ins(%arg0 : memref<?x?xf32, strided<[?, 1], offset: ?>>)
+     outs(%arg1, %arg2 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>,
+                         memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
     ^bb0(%a: f32, %b: f32, %c: f32):
       %i = linalg.index 0 : index
       %j = linalg.index 1 : index
@@ -855,14 +849,14 @@ func.func @lower_to_loops_with_rank_reducing_subviews(
     %arg0 : memref<?xi32>, %arg1 : memref<?x?xi32>, %arg2 : index,
     %arg3 : index, %arg4 : index) {
   %0 = memref.subview %arg0[%arg2] [%arg3] [1]
-      : memref<?xi32> to memref<?xi32, offset: ?, strides: [1]>
+      : memref<?xi32> to memref<?xi32, strided<[1], offset: ?>>
   %1 = memref.subview %arg1[0, %arg4] [1, %arg3] [1, 1]
-      : memref<?x?xi32> to memref<?xi32, offset: ?, strides : [1]>
+      : memref<?x?xi32> to memref<?xi32, strided<[1], offset: ?>>
   linalg.generic {
     iterator_types = ["parallel"],
     indexing_maps = [affine_map<(i) -> (i)>, affine_map<(i) -> (i)>]}
-    ins(%0: memref<?xi32, offset: ?, strides: [1]>)
-   outs(%1: memref<?xi32, offset: ?, strides : [1]>) {
+    ins(%0: memref<?xi32, strided<[1], offset: ?>>)
+   outs(%1: memref<?xi32, strided<[1], offset: ?>>) {
     ^bb0(%a: i32, %b: i32):
       linalg.yield %a : i32
   }

diff  --git a/mlir/test/Dialect/Linalg/promote.mlir b/mlir/test/Dialect/Linalg/promote.mlir
index beae28850875f..6ef8a1d71406c 100644
--- a/mlir/test/Dialect/Linalg/promote.mlir
+++ b/mlir/test/Dialect/Linalg/promote.mlir
@@ -21,13 +21,13 @@ func.func @matmul_f32(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
   scf.for %arg4 = %c0 to %6 step %c2 {
     scf.for %arg5 = %c0 to %8 step %c3 {
       scf.for %arg6 = %c0 to %7 step %c4 {
-        %11 = memref.subview %3[%arg4, %arg6][%c2, %c4][1, 1] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
-        %14 = memref.subview %4[%arg6, %arg5][%c4, %c3][1, 1] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
-        %17 = memref.subview %5[%arg4, %arg5][%c2, %c3][1, 1] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
+        %11 = memref.subview %3[%arg4, %arg6][%c2, %c4][1, 1] : memref<?x?xf32> to memref<?x?xf32, strided<[?, 1], offset: ?>>
+        %14 = memref.subview %4[%arg6, %arg5][%c4, %c3][1, 1] : memref<?x?xf32> to memref<?x?xf32, strided<[?, 1], offset: ?>>
+        %17 = memref.subview %5[%arg4, %arg5][%c2, %c3][1, 1] : memref<?x?xf32> to memref<?x?xf32, strided<[?, 1], offset: ?>>
         linalg.matmul
-          ins(%11, %14: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                        memref<?x?xf32, offset: ?, strides: [?, 1]>)
-         outs(%17: memref<?x?xf32, offset: ?, strides: [?, 1]>)
+          ins(%11, %14: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                        memref<?x?xf32, strided<[?, 1], offset: ?>>)
+         outs(%17: memref<?x?xf32, strided<[?, 1], offset: ?>>)
       }
     }
   }
@@ -54,15 +54,15 @@ func.func @matmul_f32(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
 //       CHECK:         %[[fullC:.*]] = memref.view %[[tmpC]][{{.*}}][{{.*}}] : memref<24xi8> to memref<?x?xf32>
 //       CHECK:         %[[partialC:.*]] = memref.subview %[[fullC]]{{.*}} : memref<?x?xf32> to memref<?x?xf32, #[[$strided2D]]>
 
-//       CHECK:         memref.copy %[[vA]], %[[partialA]] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       CHECK:         memref.copy %[[vB]], %[[partialB]] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       CHECK:         memref.copy %[[vC]], %[[partialC]] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
+//       CHECK:         memref.copy %[[vA]], %[[partialA]] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       CHECK:         memref.copy %[[vB]], %[[partialB]] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       CHECK:         memref.copy %[[vC]], %[[partialC]] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
 //
 //       CHECK:         linalg.matmul ins(%[[partialA]], %[[partialB]]{{.*}} outs(%[[partialC]]
 //
 //       CHECK:         memref.copy %[[partialC]], %[[vC]] :
 //       CHECK:           memref<?x?xf32, #[[$strided2D]]> to
-//       CHECK:           memref<?x?xf32, #[[$strided2D]]>
+//       CHECK:           memref<?x?xf32, strided<[?, 1], offset: ?>>
 //
 //   CHECK-NOT:         memref.dealloc %[[tmpA]] : memref<32xi8>
 //   CHECK-NOT:         memref.dealloc %[[tmpB]] : memref<48xi8>
@@ -94,13 +94,13 @@ func.func @matmul_f64(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
   scf.for %arg4 = %c0 to %6 step %c2 {
     scf.for %arg5 = %c0 to %8 step %c3 {
       scf.for %arg6 = %c0 to %7 step %c4 {
-        %11 = memref.subview %3[%arg4, %arg6][%c2, %c4][1, 1] : memref<?x?xf64> to memref<?x?xf64, offset: ?, strides: [?, 1]>
-        %14 = memref.subview %4[%arg6, %arg5][%c4, %c3][1, 1] : memref<?x?xf64> to memref<?x?xf64, offset: ?, strides: [?, 1]>
-        %17 = memref.subview %5[%arg4, %arg5][%c2, %c3][1, 1] : memref<?x?xf64> to memref<?x?xf64, offset: ?, strides: [?, 1]>
+        %11 = memref.subview %3[%arg4, %arg6][%c2, %c4][1, 1] : memref<?x?xf64> to memref<?x?xf64, strided<[?, 1], offset: ?>>
+        %14 = memref.subview %4[%arg6, %arg5][%c4, %c3][1, 1] : memref<?x?xf64> to memref<?x?xf64, strided<[?, 1], offset: ?>>
+        %17 = memref.subview %5[%arg4, %arg5][%c2, %c3][1, 1] : memref<?x?xf64> to memref<?x?xf64, strided<[?, 1], offset: ?>>
         linalg.matmul
-          ins(%11, %14: memref<?x?xf64, offset: ?, strides: [?, 1]>,
-                        memref<?x?xf64, offset: ?, strides: [?, 1]>)
-         outs(%17: memref<?x?xf64, offset: ?, strides: [?, 1]>)
+          ins(%11, %14: memref<?x?xf64, strided<[?, 1], offset: ?>>,
+                        memref<?x?xf64, strided<[?, 1], offset: ?>>)
+         outs(%17: memref<?x?xf64, strided<[?, 1], offset: ?>>)
       }
     }
   }
@@ -127,15 +127,15 @@ func.func @matmul_f64(%A: memref<?xi8>, %M: index, %N: index, %K: index) {
 //       CHECK:         %[[fullC_f64:.*]] = memref.view %[[tmpC_f64]][{{.*}}][{{.*}}] : memref<48xi8> to memref<?x?xf64>
 //       CHECK:         %[[partialC_f64:.*]] = memref.subview %[[fullC_f64]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf64> to memref<?x?xf64, #[[$strided2D]]>
 
-//       CHECK:         memref.copy %[[vA_f64]], %[[partialA_f64]] : memref<?x?xf64, #[[$strided2D]]> to memref<?x?xf64, #[[$strided2D]]>
-//       CHECK:         memref.copy %[[vB_f64]], %[[partialB_f64]] : memref<?x?xf64, #[[$strided2D]]> to memref<?x?xf64, #[[$strided2D]]>
-//       CHECK:         memref.copy %[[vC_f64]], %[[partialC_f64]] : memref<?x?xf64, #[[$strided2D]]> to memref<?x?xf64, #[[$strided2D]]>
+//       CHECK:         memref.copy %[[vA_f64]], %[[partialA_f64]] : memref<?x?xf64, strided<[?, 1], offset: ?>> to memref<?x?xf64, #[[$strided2D]]>
+//       CHECK:         memref.copy %[[vB_f64]], %[[partialB_f64]] : memref<?x?xf64, strided<[?, 1], offset: ?>> to memref<?x?xf64, #[[$strided2D]]>
+//       CHECK:         memref.copy %[[vC_f64]], %[[partialC_f64]] : memref<?x?xf64, strided<[?, 1], offset: ?>> to memref<?x?xf64, #[[$strided2D]]>
 //
 //       CHECK:         linalg.matmul ins(%[[partialA_f64]], %[[partialB_f64]]{{.*}} outs(%[[partialC_f64]]
 //
 //       CHECK:         memref.copy %[[partialC_f64]], %[[vC_f64]] :
 //       CHECK:           memref<?x?xf64, #[[$strided2D]]> to
-//       CHECK:           memref<?x?xf64, #[[$strided2D]]>
+//       CHECK:           memref<?x?xf64, strided<[?, 1], offset: ?>>
 //
 //       CHECK:         memref.dealloc %[[tmpA_f64]] : memref<64xi8>
 //       CHECK:         memref.dealloc %[[tmpB_f64]] : memref<96xi8>

diff  --git a/mlir/test/Dialect/Linalg/roundtrip.mlir b/mlir/test/Dialect/Linalg/roundtrip.mlir
index 70857b7e8e4a7..651c669633729 100644
--- a/mlir/test/Dialect/Linalg/roundtrip.mlir
+++ b/mlir/test/Dialect/Linalg/roundtrip.mlir
@@ -6,10 +6,7 @@
 // Test that we can lower all the way to LLVM without crashing, don't check results here.
 // DISABLED: mlir-opt %s --convert-linalg-to-llvm -o=/dev/null 2>&1
 
-// CHECK-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
-// CHECK-DAG: #[[$strided3D:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2 + d2)>
-// CHECK-DAG: #[[$strided3DT:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d1 * s2 + d0)>
+// CHECK: #[[$strided3DT:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d1 * s2 + d0)>
 
 func.func @views(%arg0: index) {
   %c0 = arith.constant 0 : index
@@ -31,65 +28,65 @@ func.func @views(%arg0: index) {
 
 // -----
 
-func.func @ops(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-          %arg1: memref<?xf32, offset: ?, strides: [1]>,
-          %arg2: memref<?xf32, offset: ?, strides: [1]>,
+func.func @ops(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+          %arg1: memref<?xf32, strided<[1], offset: ?>>,
+          %arg2: memref<?xf32, strided<[1], offset: ?>>,
           %arg3: memref<f32>) {
-  linalg.matmul ins(%arg0, %arg0 : memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                                   memref<?x?xf32, offset: ?, strides: [?, 1]>)
-               outs(%arg0 : memref<?x?xf32, offset: ?, strides: [?, 1]>)
-  linalg.matvec ins(%arg0, %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                                  memref<?xf32, offset: ?, strides: [1]>)
-               outs(%arg2: memref<?xf32, offset: ?, strides: [1]>)
-  linalg.dot ins(%arg1, %arg2: memref<?xf32, offset: ?, strides: [1]>,
-                               memref<?xf32, offset: ?, strides: [1]>)
+  linalg.matmul ins(%arg0, %arg0 : memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                                   memref<?x?xf32, strided<[?, 1], offset: ?>>)
+               outs(%arg0 : memref<?x?xf32, strided<[?, 1], offset: ?>>)
+  linalg.matvec ins(%arg0, %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                                  memref<?xf32, strided<[1], offset: ?>>)
+               outs(%arg2: memref<?xf32, strided<[1], offset: ?>>)
+  linalg.dot ins(%arg1, %arg2: memref<?xf32, strided<[1], offset: ?>>,
+                               memref<?xf32, strided<[1], offset: ?>>)
             outs(%arg3: memref<f32>)
   return
 }
 // CHECK-LABEL: func @ops(%
 // CHECK: linalg.matmul
-// CHECK-SAME:   ins(%{{.*}}, %{{.*}} : memref<?x?xf32, #[[$strided2D]]>,
-// CHECK-SAME:                          memref<?x?xf32, #[[$strided2D]]>)
-// CHECK-SAME:  outs(%{{.*}} : memref<?x?xf32, #[[$strided2D]]>)
+// CHECK-SAME:   ins(%{{.*}}, %{{.*}} : memref<?x?xf32, strided<[?, 1], offset: ?>>,
+// CHECK-SAME:                          memref<?x?xf32, strided<[?, 1], offset: ?>>)
+// CHECK-SAME:  outs(%{{.*}} : memref<?x?xf32, strided<[?, 1], offset: ?>>)
 // CHECK: linalg.matvec
-// CHECK-SAME:   ins(%{{.*}}, %{{.*}}: memref<?x?xf32, #[[$strided2D]]>,
-// CHECK-SAME:                         memref<?xf32, #[[$strided1D]]>)
-// CHECK-SAME:  outs(%{{.*}}: memref<?xf32, #[[$strided1D]]>)
+// CHECK-SAME:   ins(%{{.*}}, %{{.*}}: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+// CHECK-SAME:                         memref<?xf32, strided<[1], offset: ?>>)
+// CHECK-SAME:  outs(%{{.*}}: memref<?xf32, strided<[1], offset: ?>>)
 // CHECK: linalg.dot
-// CHECK-SAME:   ins(%{{.*}}, %{{.*}}: memref<?xf32, #[[$strided1D]]>,
-// CHECK-SAME:                         memref<?xf32, #[[$strided1D]]>)
+// CHECK-SAME:   ins(%{{.*}}, %{{.*}}: memref<?xf32, strided<[1], offset: ?>>,
+// CHECK-SAME:                         memref<?xf32, strided<[1], offset: ?>>)
 // CHECK-SAME:  outs(%{{.*}}: memref<f32>)
 
 // -----
 
-func.func @fill_view(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: f32) {
-  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?xf32, offset: ?, strides: [1]>)
+func.func @fill_view(%arg0: memref<?xf32, strided<[1], offset: ?>>, %arg1: f32) {
+  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?xf32, strided<[1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @fill_view(
-//       CHECK:  %{{.*}}: memref<?xf32, #[[$strided1D]]>, %{{.*}}: f32) {
-//       CHECK:   linalg.fill ins(%{{.*}} : f32) outs(%{{.*}} : memref<?xf32, #[[$strided1D]]>)
+//       CHECK:  %{{.*}}: memref<?xf32, strided<[1], offset: ?>>, %{{.*}}: f32) {
+//       CHECK:   linalg.fill ins(%{{.*}} : f32) outs(%{{.*}} : memref<?xf32, strided<[1], offset: ?>>)
 
 // -----
 
-func.func @transpose(%arg0: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
-  %0 = memref.transpose %arg0 (i, j, k) -> (k, j, i) : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]> to memref<?x?x?xf32, affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d1 * s2 + d0)>>
+func.func @transpose(%arg0: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
+  %0 = memref.transpose %arg0 (i, j, k) -> (k, j, i) : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>> to memref<?x?x?xf32, affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d1 * s2 + d0)>>
   return
 }
 // CHECK-LABEL: func @transpose
 //       CHECK:   memref.transpose %{{.*}} ([[i:.*]], [[j:.*]], [[k:.*]]) -> ([[k]], [[j]], [[i]]) :
-//  CHECK-SAME:      memref<?x?x?xf32, #[[$strided3D]]> to memref<?x?x?xf32, #[[$strided3DT]]>
+//  CHECK-SAME:      memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>> to memref<?x?x?xf32, #[[$strided3DT]]>
 
 // -----
 
 
-func.func @fill_view3(%arg0: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, %arg1: f32) {
-  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>)
+func.func @fill_view3(%arg0: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>, %arg1: f32) {
+  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @fill_view3(
-//       CHECK:  %{{.*}}: memref<?x?x?xf32, #[[$strided3D]]>, %{{.*}}: f32) {
-//       CHECK:   linalg.fill ins(%{{.*}} : f32) outs(%{{.*}} : memref<?x?x?xf32, #[[$strided3D]]>)
+//       CHECK:  %{{.*}}: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>, %{{.*}}: f32) {
+//       CHECK:   linalg.fill ins(%{{.*}} : f32) outs(%{{.*}} : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
 
 // -----
 
@@ -105,12 +102,12 @@ func.func @fill_view3(%arg0: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>, %
   library_call = "some_external_function_name_1"
 }
 
-func.func @generic(%arg0: memref<?x?xvector<3x4xi4>, offset: ?, strides: [?, 1]>,
-              %arg1: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+func.func @generic(%arg0: memref<?x?xvector<3x4xi4>, strided<[?, 1], offset: ?>>,
+              %arg1: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
   %cst = arith.constant 0.0 : f32
   linalg.generic #trait_0
-       ins(%arg0, %cst : memref<?x?xvector<3x4xi4>, offset: ?, strides: [?, 1]>, f32)
-      outs(%arg1 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>)
+       ins(%arg0, %cst : memref<?x?xvector<3x4xi4>, strided<[?, 1], offset: ?>>, f32)
+      outs(%arg1 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
       attrs = {foo = 1} {
     ^bb(%0: vector<3x4xi4>, %1: f32, %2: f32) :
       linalg.yield %1 : f32
@@ -122,16 +119,16 @@ func.func @generic(%arg0: memref<?x?xvector<3x4xi4>, offset: ?, strides: [?, 1]>
 //  CHECK-SAME:     indexing_maps = [#{{[0-9a-z]*}}, #{{[0-9a-z]*}}, #{{[0-9a-z]*}}],
 //  CHECK-SAME:     iterator_types = ["parallel", "parallel", "parallel"],
 //  CHECK-SAME:     library_call = "some_external_function_name_1"}
-//  CHECK-SAME:      ins({{.*}}, {{.*}} : memref<?x?xvector<3x4xi4>, #[[$strided2D]]>, f32)
-//  CHECK-SAME:     outs({{.*}} : memref<?x?x?xf32, #[[$strided3D]]>)
+//  CHECK-SAME:      ins({{.*}}, {{.*}} : memref<?x?xvector<3x4xi4>, strided<[?, 1], offset: ?>>, f32)
+//  CHECK-SAME:     outs({{.*}} : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
 //  CHECK-SAME:     {foo = 1 : i64}
 
 func.func @generic_with_tensor_input(%arg0: tensor<?x?xvector<3x4xi4>>,
-                                %arg1: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+                                %arg1: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
   %cst = arith.constant 0.0 : f32
   linalg.generic #trait_0
        ins(%arg0, %cst : tensor<?x?xvector<3x4xi4>>, f32)
-      outs(%arg1 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>)
+      outs(%arg1 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
       attrs = {foo = 1} {
     ^bb(%0: vector<3x4xi4>, %1: f32, %2: f32) :
       linalg.yield %1 : f32
@@ -143,7 +140,7 @@ func.func @generic_with_tensor_input(%arg0: tensor<?x?xvector<3x4xi4>>,
 //  CHECK-SAME:     indexing_maps = [#{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel"],
 //  CHECK-SAME:     library_call = "some_external_function_name_1"}
 //  CHECK-SAME:     ins({{.*}}, {{.*}} : tensor<?x?xvector<3x4xi4>>, f32)
-//  CHECK-SAME:     outs({{.*}} : memref<?x?x?xf32, #[[$strided3D]]>)
+//  CHECK-SAME:     outs({{.*}} : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
 //  CHECK-SAME:     {foo = 1 : i64}
 
 // -----
@@ -272,11 +269,11 @@ func.func @generic_op_zero_rank(%arg0: tensor<f32>, %arg1 : tensor<3x4xf32>) ->
   library_call = "some_external_function_name_2"
 }
 
-func.func @generic_region(%arg0: memref<?x?xvector<3x4xi4>, offset: ?, strides: [?, 1]>,
-                     %arg1: memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>) {
+func.func @generic_region(%arg0: memref<?x?xvector<3x4xi4>, strided<[?, 1], offset: ?>>,
+                     %arg1: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>) {
   linalg.generic #trait_3
-       ins(%arg0 : memref<?x?xvector<3x4xi4>, offset: ?, strides: [?, 1]>)
-      outs(%arg1 : memref<?x?x?xf32, offset: ?, strides: [?, ?, 1]>)
+       ins(%arg0 : memref<?x?xvector<3x4xi4>, strided<[?, 1], offset: ?>>)
+      outs(%arg1 : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
       attrs = {foo = 1} {
     ^bb(%a: vector<3x4xi4>, %b: f32) :
       %0 = linalg.index 0 : index
@@ -291,8 +288,8 @@ func.func @generic_region(%arg0: memref<?x?xvector<3x4xi4>, offset: ?, strides:
 //  CHECK-SAME:     indexing_maps = [#{{[0-9a-z]*}}, #{{[0-9a-z]*}}],
 //  CHECK-SAME:     iterator_types = ["parallel", "parallel", "parallel"],
 //  CHECK-SAME:     library_call = "some_external_function_name_2"
-//  CHECK-SAME:      ins({{.*}} : memref<?x?xvector<3x4xi4>, #[[$strided2D]]>)
-//  CHECK-SAME:     outs({{.*}} : memref<?x?x?xf32, #[[$strided3D]]>)
+//  CHECK-SAME:      ins({{.*}} : memref<?x?xvector<3x4xi4>, strided<[?, 1], offset: ?>>)
+//  CHECK-SAME:     outs({{.*}} : memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>)
 //  CHECK-SAME:     attrs = {foo = 1 : i64} {
 //       CHECK:  ^{{.*}}(%{{.*}}: vector<3x4xi4>, %{{.*}}: f32):
 //       CHECK:    %{{.*}} = linalg.index 0 : index

diff  --git a/mlir/test/Dialect/Linalg/standard.mlir b/mlir/test/Dialect/Linalg/standard.mlir
index e51529d667d62..20c75c76c2e88 100644
--- a/mlir/test/Dialect/Linalg/standard.mlir
+++ b/mlir/test/Dialect/Linalg/standard.mlir
@@ -1,25 +1,24 @@
 // RUN: mlir-opt %s -convert-linalg-to-std | FileCheck %s
 
-// CHECK-DAG: #[[$map0:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
 // CHECK-DAG: #[[$map6:.*]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
 // CHECK-DAG: #[[$map7:.*]] = affine_map<()[s0] -> (s0)>
 
-func.func @dot(%arg0: memref<?xf32, offset: ?, strides: [1]>,
-          %arg1: memref<?xf32, offset: ?, strides: [1]>,
+func.func @dot(%arg0: memref<?xf32, strided<[1], offset: ?>>,
+          %arg1: memref<?xf32, strided<[1], offset: ?>>,
           %arg2: memref<f32>) {
-  linalg.dot ins(%arg0, %arg1: memref<?xf32, offset: ?, strides: [1]>,
-                               memref<?xf32, offset: ?, strides: [1]>)
+  linalg.dot ins(%arg0, %arg1: memref<?xf32, strided<[1], offset: ?>>,
+                               memref<?xf32, strided<[1], offset: ?>>)
              outs(%arg2: memref<f32>)
   return
 }
 // CHECK-LABEL: func @dot(
-//  CHECK-SAME: %[[arg0:[a-zA-z0-9]*]]: memref<?xf32, #[[$map0]]>,
-//  CHECK-SAME: %[[arg1:[a-zA-z0-9]*]]: memref<?xf32, #[[$map0]]>,
+//  CHECK-SAME: %[[arg0:[a-zA-z0-9]*]]: memref<?xf32, strided<[1], offset: ?>>,
+//  CHECK-SAME: %[[arg1:[a-zA-z0-9]*]]: memref<?xf32, strided<[1], offset: ?>>,
 //  CHECK-SAME: %[[arg2:[a-zA-z0-9]*]]: memref<f32>) {
 //       CHECK:   %[[o0:.*]] = memref.cast %[[arg0]] :
-//  CHECK-SAME:     memref<?xf32, #[[$map0]]> to memref<?xf32, #[[$map6]]>
+//  CHECK-SAME:     memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$map6]]>
 //       CHECK:   %[[o1:.*]] = memref.cast %[[arg1]] :
-//  CHECK-SAME:     memref<?xf32, #[[$map0]]> to memref<?xf32, #[[$map6]]>
+//  CHECK-SAME:     memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$map6]]>
 //       CHECK:   %[[o2:.*]] = memref.cast %[[arg2]] :
 //  CHECK-SAME:     memref<f32> to memref<f32, #[[$map7]]>
 //       CHECK:   call @linalg_dot_viewsxf32_viewsxf32_viewf32(

diff  --git a/mlir/test/Dialect/Linalg/tile-parallel.mlir b/mlir/test/Dialect/Linalg/tile-parallel.mlir
index 1e479b9423d2b..cf346f938be32 100644
--- a/mlir/test/Dialect/Linalg/tile-parallel.mlir
+++ b/mlir/test/Dialect/Linalg/tile-parallel.mlir
@@ -11,13 +11,13 @@
   iterator_types = ["parallel", "parallel"]
 }
 
-func.func @sum(%lhs: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-          %rhs: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-          %sum: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @sum(%lhs: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+          %rhs: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+          %sum: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   linalg.generic #pointwise_2d_trait
-     ins(%lhs, %rhs: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                     memref<?x?xf32, offset: ?, strides: [?, 1]>)
-    outs(%sum : memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+     ins(%lhs, %rhs: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                     memref<?x?xf32, strided<[?, 1], offset: ?>>)
+    outs(%sum : memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   ^bb0(%lhs_in: f32, %rhs_in: f32, %sum_out: f32):
     %result = arith.addf %lhs_in, %rhs_in : f32
     linalg.yield %result : f32
@@ -25,7 +25,7 @@ func.func @sum(%lhs: memref<?x?xf32, offset: ?, strides: [?, 1]>,
   return
 }
 // TILE-2-LABEL: func @sum(
-// TILE-2-SAME:    [[LHS:%.*]]: {{.*}}, [[RHS:%.*]]: {{.*}}, [[SUM:%.*]]: {{.*}}) {
+// TILE-2-SAME:    [[LHS:%.*]]: memref{{.*}}, [[RHS:%.*]]: memref{{.*}}, [[SUM:%.*]]: memref{{.*}}) {
 // TILE-2-DAG: [[C0:%.*]] = arith.constant 0 : index
 // TILE-2-DAG: [[C2:%.*]] = arith.constant 2 : index
 // TILE-2: [[LHS_ROWS:%.*]] = memref.dim [[LHS]], %c0
@@ -37,7 +37,7 @@ func.func @sum(%lhs: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 // TILE-2:   linalg.generic {{.*}} ins([[LHS_SUBVIEW]], [[RHS_SUBVIEW]]{{.*}} outs([[SUM_SUBVIEW]]
 
 // TILE-02-LABEL: func @sum(
-// TILE-02-SAME:    [[LHS:%.*]]: {{.*}}, [[RHS:%.*]]: {{.*}}, [[SUM:%.*]]: {{.*}}) {
+// TILE-02-SAME:    [[LHS:%.*]]: memref{{.*}}, [[RHS:%.*]]: memref{{.*}}, [[SUM:%.*]]: memref{{.*}}) {
 // TILE-02-DAG: [[C0:%.*]] = arith.constant 0 : index
 // TILE-02-DAG: [[C2:%.*]] = arith.constant 2 : index
 // TILE-02: [[LHS_COLS:%.*]] = memref.dim [[LHS]], %c1
@@ -49,12 +49,12 @@ func.func @sum(%lhs: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 // TILE-02:    linalg.generic {{.*}} ins([[LHS_SUBVIEW]], [[RHS_SUBVIEW]]{{.*}} outs([[SUM_SUBVIEW]]
 
 // TILE-002-LABEL: func @sum(
-// TILE-002-SAME:    [[LHS:%.*]]: {{.*}}, [[RHS:%.*]]: {{.*}}, [[SUM:%.*]]: {{.*}}) {
+// TILE-002-SAME:    [[LHS:%.*]]: memref{{.*}}, [[RHS:%.*]]: memref{{.*}}, [[SUM:%.*]]: memref{{.*}}) {
 // TILE-002-NO: scf.parallel
 // TILE-002:   linalg.generic {{.*}} ins([[LHS]], [[RHS]]{{.*}} outs([[SUM]]
 
 // TILE-234-LABEL: func @sum(
-// TILE-234-SAME:    [[LHS:%.*]]: {{.*}}, [[RHS:%.*]]: {{.*}}, [[SUM:%.*]]: {{.*}}) {
+// TILE-234-SAME:    [[LHS:%.*]]: memref{{.*}}, [[RHS:%.*]]: memref{{.*}}, [[SUM:%.*]]: memref{{.*}}) {
 // TILE-234-DAG: [[C0:%.*]] = arith.constant 0 : index
 // TILE-234-DAG: [[C2:%.*]] = arith.constant 2 : index
 // TILE-234-DAG: [[C3:%.*]] = arith.constant 3 : index

diff  --git a/mlir/test/Dialect/Linalg/tile.mlir b/mlir/test/Dialect/Linalg/tile.mlir
index 86936a9f58438..329e9841d314e 100644
--- a/mlir/test/Dialect/Linalg/tile.mlir
+++ b/mlir/test/Dialect/Linalg/tile.mlir
@@ -5,7 +5,6 @@
 
 //   TILE-2-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
 //  TILE-02-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
-// TILE-002-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
 // TILE-234-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
 
 //   TILE-2-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
@@ -24,52 +23,52 @@
 //  TILE-02-DAG: #[[$stride_99_1_layout_map:.*]] = affine_map<(d0, d1)[s0] -> (d0 * 99 + s0 + d1)>
 // TILE-234-DAG: #[[$stride_99_1_layout_map:.*]] = affine_map<(d0, d1)[s0] -> (d0 * 99 + s0 + d1)>
 
-func.func @matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @matmul(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %arg2: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   linalg.matmul
-    ins(%arg0, %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                      memref<?x?xf32, offset: ?, strides: [?, 1]>)
-   outs(%arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>)
+    ins(%arg0, %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                      memref<?x?xf32, strided<[?, 1], offset: ?>>)
+   outs(%arg2: memref<?x?xf32, strided<[?, 1], offset: ?>>)
   return
 }
 // TILE-2-LABEL: func @matmul(
 //       TILE-2-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-2-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-2: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-2: scf.for %[[I:.*]] = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
 //       TILE-2:   %[[szM:.*]] = affine.min #[[$bound_map]](%[[I]])[%[[M]]]
-//       TILE-2:   %[[K:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2:   %[[K:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-2:   %[[szK:.*]] = affine.min #[[$bound_map]](%[[I]])[%[[M]]]
-//       TILE-2:   %[[N:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
-//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [%[[szM]], %[[K]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-2:   %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [%[[szK]], %[[N]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2:   %[[N:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [%[[szM]], %[[K]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2:   %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [%[[szK]], %[[N]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
 //       TILE-2:   linalg.matmul ins(%[[sAi]]{{.*}} outs(%[[sCi]]
 
 // TILE-02-LABEL: func @matmul(
 //       TILE-02-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-02-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-02: %[[N:.*]] = memref.dim %arg1, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02: %[[N:.*]] = memref.dim %arg1, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-02: scf.for %[[J:.*]] = %{{.*}} to %[[N]] step %{{.*}} {
-//       TILE-02:   %[[K:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02:   %[[K:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-02:   %[[szN:.*]] = affine.min #[[$bound_map]](%[[J]])[%[[N]]]
-//       TILE-02:   %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02:   %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-02:   %[[szK:.*]] = affine.min #[[$bound_map]](%[[J]])[%[[N]]]
-//       TILE-02:   %[[sBj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [%[[K]], %[[szN]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-02:   %[[sCj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [%[[M]], %[[szK]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02:   %[[sBj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [%[[K]], %[[szN]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02:   %[[sCj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [%[[M]], %[[szK]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
 //       TILE-02:   linalg.matmul ins(%{{.*}}, %[[sBj]]{{.*}} outs(%[[sCj]]
 
 // TILE-002-LABEL: func @matmul(
 //       TILE-002-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-002-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-002: %[[ubK:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-002: %[[ubK:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-002: scf.for %[[K:.*]] = %{{.*}}{{.*}} to %[[ubK]] step %{{.*}} {
-//       TILE-002:   %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-002:   %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-002:   %[[szK:.*]] = affine.min #[[$bound_map]](%[[K]])[%[[ubK]]]
 //       TILE-002:   %[[szK_1:.*]] = affine.min #[[$bound_map]](%[[K]])[%[[ubK]]]
-//       TILE-002:   %[[N:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
-//       TILE-002:   %[[sAj:.*]] = memref.subview %{{.*}}[0, %[[K]]] [%[[M]], %[[szK]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-002:   %[[sBj:.*]] = memref.subview %{{.*}}[%[[K]], 0] [%[[szK_1]], %[[N]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-002:   %[[N:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       TILE-002:   %[[sAj:.*]] = memref.subview %{{.*}}[0, %[[K]]] [%[[M]], %[[szK]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-002:   %[[sBj:.*]] = memref.subview %{{.*}}[%[[K]], 0] [%[[szK_1]], %[[N]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
 //       TILE-002:   linalg.matmul ins(%[[sAj]], %[[sBj]]{{.*}} outs(%{{.*}}
 
 // TILE-234-LABEL: func @matmul(
@@ -77,9 +76,9 @@ func.func @matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 //       TILE-234-DAG: %[[C2:.*]] = arith.constant 2 : index
 //       TILE-234-DAG: %[[C3:.*]] = arith.constant 3 : index
 //       TILE-234-DAG: %[[C4:.*]] = arith.constant 4 : index
-//       TILE-234: %[[ubM:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
-//       TILE-234: %[[ubK:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
-//       TILE-234: %[[ubN:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-234: %[[ubM:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       TILE-234: %[[ubK:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       TILE-234: %[[ubN:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-234:  scf.for %[[I:.*]] = %{{.*}}{{.*}} to %[[ubM]] step %{{.*}} {
 //       TILE-234:    scf.for %[[J:.*]] = %{{.*}}{{.*}} to %[[ubN]] step %{{.*}} {
 //       TILE-234:      scf.for %[[K:.*]] = %{{.*}}{{.*}} to %[[ubK]] step %{{.*}} {
@@ -89,9 +88,9 @@ func.func @matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 //       TILE-234:        %[[szN:.*]] = affine.min #[[$bound_map_3]](%[[J]])[%[[ubN]]]
 //       TILE-234:        %[[szM_1:.*]] = affine.min #[[$bound_map_2]](%[[I]])[%[[ubM]]]
 //       TILE-234:        %[[szN_1:.*]] = affine.min #[[$bound_map_3]](%[[J]])[%[[ubN]]]
-//       TILE-234:        %[[sAik:.*]] = memref.subview %{{.*}}[%[[I]], %[[K]]] [%[[szM]], %[[szK]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-234:        %[[sBkj:.*]] = memref.subview %{{.*}}[%[[K]], %[[J]]] [%[[szK_1]], %[[szN]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-234:        %[[sCij:.*]] = memref.subview %{{.*}}[%[[I]], %[[J]]] [%[[szM_1]], %[[szN_1]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-234:        %[[sAik:.*]] = memref.subview %{{.*}}[%[[I]], %[[K]]] [%[[szM]], %[[szK]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-234:        %[[sBkj:.*]] = memref.subview %{{.*}}[%[[K]], %[[J]]] [%[[szK_1]], %[[szN]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-234:        %[[sCij:.*]] = memref.subview %{{.*}}[%[[I]], %[[J]]] [%[[szM_1]], %[[szN_1]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
 //
 //       TILE-234:        linalg.matmul ins(%[[sAik]], %[[sBkj]]{{.*}} outs(%[[sCij]]
 
@@ -99,13 +98,13 @@ func.func @matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 // the "min" in subview size computation. This test uses buffer sizes divisible
 // by respective tile sizes (M=10 divisble by 2, N=12 divisible by 2 and 3,
 // K=16 divisble by 2 and 4).
-func.func @matmul_static(%arg0: memref<10x16xf32, offset: ?, strides: [?, 1]>,
-                    %arg1: memref<16x12xf32, offset: ?, strides: [?, 1]>,
-                    %arg2: memref<10x12xf32, offset: ?, strides: [?, 1]>) {
+func.func @matmul_static(%arg0: memref<10x16xf32, strided<[?, 1], offset: ?>>,
+                    %arg1: memref<16x12xf32, strided<[?, 1], offset: ?>>,
+                    %arg2: memref<10x12xf32, strided<[?, 1], offset: ?>>) {
   linalg.matmul
-    ins(%arg0, %arg1: memref<10x16xf32, offset: ?, strides: [?, 1]>,
-                      memref<16x12xf32, offset: ?, strides: [?, 1]>)
-   outs(%arg2: memref<10x12xf32, offset: ?, strides: [?, 1]>)
+    ins(%arg0, %arg1: memref<10x16xf32, strided<[?, 1], offset: ?>>,
+                      memref<16x12xf32, strided<[?, 1], offset: ?>>)
+   outs(%arg2: memref<10x12xf32, strided<[?, 1], offset: ?>>)
   return
 }
 // TILE-2-LABEL: func @matmul_static(
@@ -116,8 +115,8 @@ func.func @matmul_static(%arg0: memref<10x16xf32, offset: ?, strides: [?, 1]>,
 //       TILE-2-DAG: %[[C2:.*]] = arith.constant 2 : index
 //       TILE-2-DAG: %[[M:.*]] = arith.constant 10 : index
 //       TILE-2: scf.for %[[I:.*]] = %{{.*}} to %[[M]] step %{{.*}} {
-//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [2, 16] [1, 1] : memref<10x16xf32, #[[$strided2D]]> to memref<2x16xf32, #[[$strided2D]]>
-//       TILE-2:   %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [2, 12] [1, 1] : memref<10x12xf32, #[[$strided2D]]> to memref<2x12xf32, #[[$strided2D]]>
+//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [2, 16] [1, 1] : memref<10x16xf32, strided<[?, 1], offset: ?>> to memref<2x16xf32, #[[$strided2D]]>
+//       TILE-2:   %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [2, 12] [1, 1] : memref<10x12xf32, strided<[?, 1], offset: ?>> to memref<2x12xf32, #[[$strided2D]]>
 //       TILE-2:   linalg.matmul ins(%[[sAi]], %{{.*}}{{.*}} outs(%[[sCi]]
 
 // TILE-02-LABEL: func @matmul_static(
@@ -125,8 +124,8 @@ func.func @matmul_static(%arg0: memref<10x16xf32, offset: ?, strides: [?, 1]>,
 //       TILE-02-DAG: %[[C2:.*]] = arith.constant 2 : index
 //       TILE-02-DAG: %[[N:.*]] = arith.constant 12 : index
 //       TILE-02: scf.for %[[J:.*]] = %{{.*}} to %[[N]] step %{{.*}} {
-//       TILE-02:   %[[sBj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [16, 2] [1, 1] : memref<16x12xf32, #[[$strided2D]]> to memref<16x2xf32, #[[$strided2D]]>
-//       TILE-02:   %[[sCj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [10, 2] [1, 1] : memref<10x12xf32, #[[$strided2D]]> to memref<10x2xf32, #[[$strided2D]]>
+//       TILE-02:   %[[sBj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [16, 2] [1, 1] : memref<16x12xf32, strided<[?, 1], offset: ?>> to memref<16x2xf32, #[[$strided2D]]>
+//       TILE-02:   %[[sCj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [10, 2] [1, 1] : memref<10x12xf32, strided<[?, 1], offset: ?>> to memref<10x2xf32, #[[$strided2D]]>
 //       TILE-02:   linalg.matmul ins(%{{.*}}, %[[sBj]]{{.*}} outs(%[[sCj]]
 
 // TILE-002-LABEL: func @matmul_static(
@@ -134,8 +133,8 @@ func.func @matmul_static(%arg0: memref<10x16xf32, offset: ?, strides: [?, 1]>,
 //       TILE-002-DAG: %[[C2:.*]] = arith.constant 2 : index
 //       TILE-002-DAG: %[[C16:.*]] = arith.constant 16 : index
 //       TILE-002: scf.for %[[K:.*]] = %{{.*}}{{.*}} to %[[C16]] step %{{.*}} {
-//       TILE-002:   %[[sAj:.*]] = memref.subview %{{.*}}[0, %[[K]]] [10, 2] [1, 1] : memref<10x16xf32, #[[$strided2D]]> to memref<10x2xf32, #[[$strided2D]]>
-//       TILE-002:   %[[sBj:.*]] = memref.subview %{{.*}}[%[[K]], 0] [2, 12] [1, 1] : memref<16x12xf32, #[[$strided2D]]> to memref<2x12xf32, #[[$strided2D]]>
+//       TILE-002:   %[[sAj:.*]] = memref.subview %{{.*}}[0, %[[K]]] [10, 2] [1, 1] : memref<10x16xf32, strided<[?, 1], offset: ?>> to memref<10x2xf32, #[[$strided2D]]>
+//       TILE-002:   %[[sBj:.*]] = memref.subview %{{.*}}[%[[K]], 0] [2, 12] [1, 1] : memref<16x12xf32, strided<[?, 1], offset: ?>> to memref<2x12xf32, #[[$strided2D]]>
 //       TILE-002:   linalg.matmul ins(%[[sAj]], %[[sBj]]{{.*}} outs(%{{.*}}
 
 // TILE-234-LABEL: func @matmul_static(
@@ -149,17 +148,17 @@ func.func @matmul_static(%arg0: memref<10x16xf32, offset: ?, strides: [?, 1]>,
 //       TILE-234:  scf.for %[[I:.*]] = %{{.*}}{{.*}} to %[[C10]] step %{{.*}} {
 //       TILE-234:    scf.for %[[J:.*]] = %{{.*}}{{.*}} to %[[C12]] step %{{.*}} {
 //       TILE-234:      scf.for %[[K:.*]] = %{{.*}}{{.*}} to %[[C16]] step %{{.*}} {
-//       TILE-234:        %[[sAik:.*]] = memref.subview %{{.*}}[%[[I]], %[[K]]] [2, 4] [1, 1] : memref<10x16xf32, #[[$strided2D]]> to memref<2x4xf32, #[[$strided2D]]>
-//       TILE-234:        %[[sBkj:.*]] = memref.subview %{{.*}}[%[[K]], %[[J]]] [4, 3] [1, 1] : memref<16x12xf32, #[[$strided2D]]> to memref<4x3xf32, #[[$strided2D]]>
-//       TILE-234:        %[[sCij:.*]] = memref.subview %{{.*}}[%[[I]], %[[J]]] [2, 3] [1, 1] : memref<10x12xf32, #[[$strided2D]]> to memref<2x3xf32, #[[$strided2D]]>
+//       TILE-234:        %[[sAik:.*]] = memref.subview %{{.*}}[%[[I]], %[[K]]] [2, 4] [1, 1] : memref<10x16xf32, strided<[?, 1], offset: ?>> to memref<2x4xf32, #[[$strided2D]]>
+//       TILE-234:        %[[sBkj:.*]] = memref.subview %{{.*}}[%[[K]], %[[J]]] [4, 3] [1, 1] : memref<16x12xf32, strided<[?, 1], offset: ?>> to memref<4x3xf32, #[[$strided2D]]>
+//       TILE-234:        %[[sCij:.*]] = memref.subview %{{.*}}[%[[I]], %[[J]]] [2, 3] [1, 1] : memref<10x12xf32, strided<[?, 1], offset: ?>> to memref<2x3xf32, #[[$strided2D]]>
 //
 //       TILE-234:        linalg.matmul ins(%[[sAik]], %[[sBkj]]{{.*}} outs(%[[sCij]]
 
-func.func @matvec(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: memref<?xf32, offset: ?, strides: [1]>, %arg2: memref<?xf32, offset: ?, strides: [1]>) {
+func.func @matvec(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>, %arg1: memref<?xf32, strided<[1], offset: ?>>, %arg2: memref<?xf32, strided<[1], offset: ?>>) {
   linalg.matvec
-    ins(%arg0, %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                      memref<?xf32, offset: ?, strides: [1]>)
-   outs(%arg2: memref<?xf32, offset: ?, strides: [1]>)
+    ins(%arg0, %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                      memref<?xf32, strided<[1], offset: ?>>)
+   outs(%arg2: memref<?xf32, strided<[1], offset: ?>>)
   return
 }
 // TILE-2-LABEL: func @matvec(
@@ -168,13 +167,13 @@ func.func @matvec(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: mem
 //  TILE-2-SAME: %[[ARG2:[0-9a-zA-Z]*]]: memref
 //       TILE-2-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-2-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-2: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-2: scf.for %[[I:.*]] = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
 //       TILE-2:   %[[szM:.*]] = affine.min #[[$bound_map]](%[[I]])[%[[M]]]
-//       TILE-2:   %[[N:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2:   %[[N:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-2:   %[[szN:.*]] = affine.min #[[$bound_map]](%[[I]])[%[[M]]]
-//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [%[[szM]], %[[N]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-2:   %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szN]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
+//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]], 0] [%[[szM]], %[[N]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-2:   %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szN]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
 //       TILE-2:   linalg.matvec ins(%[[sAi]], %{{.*}} outs(%[[sCi]]
 
 // TILE-02-LABEL: func @matvec(
@@ -183,13 +182,13 @@ func.func @matvec(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: mem
 // TILE-02-SAME: %[[ARG2:[0-9a-zA-Z]*]]: memref
 //       TILE-02-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-02-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-02: %[[K:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02: %[[K:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-02: scf.for %[[J:.*]] = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
-//       TILE-02:   %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02:   %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-02:   %[[szN:.*]] = affine.min #[[$bound_map]](%[[J]])[%[[K]]]
 //       TILE-02:   %[[szN_1:.*]] = affine.min #[[$bound_map]](%[[J]])[%[[K]]]
-//       TILE-02:   %[[sAj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [%[[M]], %[[szN]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-02:   %[[sBj:.*]] = memref.subview %{{.*}}[%[[J]]] [%[[szN_1]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
+//       TILE-02:   %[[sAj:.*]] = memref.subview %{{.*}}[0, %[[J]]] [%[[M]], %[[szN]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-02:   %[[sBj:.*]] = memref.subview %{{.*}}[%[[J]]] [%[[szN_1]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
 //       TILE-02:   linalg.matvec ins(%[[sAj]], %[[sBj]]{{.*}} outs(%{{.*}}
 
 // TILE-002-LABEL: func @matvec(
@@ -205,35 +204,35 @@ func.func @matvec(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: mem
 //       TILE-234-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-234-DAG: %[[C2:.*]] = arith.constant 2 : index
 //       TILE-234-DAG: %[[C3:.*]] = arith.constant 3 : index
-//       TILE-234: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, #[[$strided2D]]>
-//       TILE-234: %[[K:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, #[[$strided2D]]>
+//       TILE-234: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+//       TILE-234: %[[K:.*]] = memref.dim %{{.*}}, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
 //       TILE-234:  scf.for %[[I:.*]] = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
 //       TILE-234:    scf.for %[[J:.*]] = %{{.*}}{{.*}} to %[[K]] step %{{.*}} {
 //       TILE-234:      %[[szM:.*]] = affine.min #[[$bound_map_2]](%[[I]])[%[[M]]]
 //       TILE-234:      %[[szN:.*]] = affine.min #[[$bound_map_3]](%[[J]])[%[[K]]]
 //       TILE-234:      %[[szN_1:.*]] = affine.min #[[$bound_map_3]](%[[J]])[%[[K]]]
 //       TILE-234:      %[[szM_1:.*]] = affine.min #[[$bound_map_2]](%[[I]])[%[[M]]]
-//       TILE-234:      %[[sAij:.*]] = memref.subview %{{.*}}[%[[I]], %[[J]]] [%[[szM]], %[[szN]]] [1, 1] : memref<?x?xf32, #[[$strided2D]]> to memref<?x?xf32, #[[$strided2D]]>
-//       TILE-234:      %[[sBj:.*]] = memref.subview %{{.*}}[%[[J]]] [%[[szN_1]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
-//       TILE-234:      %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM_1]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
+//       TILE-234:      %[[sAij:.*]] = memref.subview %{{.*}}[%[[I]], %[[J]]] [%[[szM]], %[[szN]]] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$strided2D]]>
+//       TILE-234:      %[[sBj:.*]] = memref.subview %{{.*}}[%[[J]]] [%[[szN_1]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
+//       TILE-234:      %[[sCi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM_1]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
 //
 //       TILE-234:      linalg.matvec ins(%[[sAij]], %[[sBj]]{{.*}} outs(%[[sCi]]
 
-func.func @dot(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: memref<?xf32, offset: ?, strides: [1]>, %arg2: memref<f32>) {
+func.func @dot(%arg0: memref<?xf32, strided<[1], offset: ?>>, %arg1: memref<?xf32, strided<[1], offset: ?>>, %arg2: memref<f32>) {
   linalg.dot
-    ins(%arg0, %arg1: memref<?xf32, offset: ?, strides: [1]>, memref<?xf32, offset: ?, strides: [1]>)
+    ins(%arg0, %arg1: memref<?xf32, strided<[1], offset: ?>>, memref<?xf32, strided<[1], offset: ?>>)
    outs(%arg2: memref<f32>)
   return
 }
 // TILE-2-LABEL: func @dot(
 //       TILE-2-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-2-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-2: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?xf32, #[[$strided1D]]>
+//       TILE-2: %[[M:.*]] = memref.dim %{{.*}}, %c0 : memref<?xf32, strided<[1], offset: ?>>
 //       TILE-2: scf.for %[[I:.*]] = %{{.*}}{{.*}} to %[[M]] step %{{.*}} {
 //       TILE-2:   %[[szM:.*]] = affine.min #[[$bound_map]](%[[I]])[%[[M]]]
 //       TILE-2:   %[[szM_1:.*]] = affine.min #[[$bound_map]](%[[I]])[%[[M]]]
-//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
-//       TILE-2:   %[[sBi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM_1]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
+//       TILE-2:   %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
+//       TILE-2:   %[[sBi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM_1]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
 //       TILE-2:   linalg.dot ins(%[[sAi]], %[[sBi]]{{.*}} outs(
 
 // TILE-02-LABEL: func @dot(
@@ -245,12 +244,12 @@ func.func @dot(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: memref<?xf3
 // TILE-234-LABEL: func @dot(
 //       TILE-234-DAG: %[[C0:.*]] = arith.constant 0 : index
 //       TILE-234-DAG: %[[C2:.*]] = arith.constant 2 : index
-//       TILE-234:  %[[ubK:.*]] = memref.dim %{{.*}}, %c0 : memref<?xf32, #[[$strided1D]]>
+//       TILE-234:  %[[ubK:.*]] = memref.dim %{{.*}}, %c0 : memref<?xf32, strided<[1], offset: ?>>
 //       TILE-234:  scf.for %[[I:.*]] = %{{.*}} to %[[ubK]] step %{{.*}} {
 //       TILE-234:    %[[szM:.*]] = affine.min #[[$bound_map_2]](%[[I]])[%[[ubK]]]
 //       TILE-234:    %[[szM_1:.*]] = affine.min #[[$bound_map_2]](%[[I]])[%[[ubK]]]
-//       TILE-234:    %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
-//       TILE-234:    %[[sBi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM_1]]] [1] : memref<?xf32, #[[$strided1D]]> to memref<?xf32, #[[$strided1D]]>
+//       TILE-234:    %[[sAi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
+//       TILE-234:    %[[sBi:.*]] = memref.subview %{{.*}}[%[[I]]] [%[[szM_1]]] [1] : memref<?xf32, strided<[1], offset: ?>> to memref<?xf32, #[[$strided1D]]>
 //       TILE-234:    linalg.dot ins(%[[sAi]], %[[sBi]]{{.*}} outs(
 
 func.func @fill_static(%arg0: memref<127x99xf32>, %arg1: f32) {
@@ -281,8 +280,8 @@ func.func @fill_static(%arg0: memref<127x99xf32>, %arg1: f32) {
 //       TILE-234:       linalg.fill{{.*}} : memref<?x3xf32, #[[$stride_99_1_layout_map]]>
 
 
-func.func @fill(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: f32) {
-  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?x?xf32, offset: ?, strides: [?, 1]>)
+func.func @fill(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>, %arg1: f32) {
+  linalg.fill ins(%arg1 : f32) outs(%arg0 : memref<?x?xf32, strided<[?, 1], offset: ?>>)
   return
 }
 // TILE-2-LABEL: func @fill
@@ -313,11 +312,11 @@ func.func @fill(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: f32)
   iterator_types = ["parallel", "parallel"]
 }
 
-func.func @pointwise(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>, %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @pointwise(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>, %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                %arg2: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   linalg.generic #pointwise_2d_trait
-    ins(%arg0, %arg1 : memref<?x?xf32, offset: ?, strides: [?, 1]>, memref<?x?xf32, offset: ?, strides: [?, 1]>)
-    outs(%arg2 : memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+    ins(%arg0, %arg1 : memref<?x?xf32, strided<[?, 1], offset: ?>>, memref<?x?xf32, strided<[?, 1], offset: ?>>)
+    outs(%arg2 : memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   ^bb0(%arg4: f32, %arg5: f32, %arg6: f32):
     %4 = arith.addf %arg4, %arg5 : f32
     linalg.yield %4 : f32

diff  --git a/mlir/test/Dialect/Linalg/transform-patterns.mlir b/mlir/test/Dialect/Linalg/transform-patterns.mlir
index e7053c3a3383f..0bbfb2582e777 100644
--- a/mlir/test/Dialect/Linalg/transform-patterns.mlir
+++ b/mlir/test/Dialect/Linalg/transform-patterns.mlir
@@ -7,12 +7,12 @@
 // CHECK-DAG: #[[$nm:.*]] = affine_map<(d0, d1, d2) -> (d1, d0)>
 // CHECK-DAG: #[[$km:.*]] = affine_map<(d0, d1, d2) -> (d2, d0)>
 
-func.func @dot(%x: memref<?xf32, offset: ?, strides: [1]>,
-          %y: memref<?xf32, offset: ?, strides: [1]>,
+func.func @dot(%x: memref<?xf32, strided<[1], offset: ?>>,
+          %y: memref<?xf32, strided<[1], offset: ?>>,
           %v: memref<f32>) {
   linalg.dot { __internal_linalg_transform__ = "MEM" }
-    ins(%x, %y: memref<?xf32, offset: ?, strides: [1]>,
-                memref<?xf32, offset: ?, strides: [1]>)
+    ins(%x, %y: memref<?xf32, strided<[1], offset: ?>>,
+                memref<?xf32, strided<[1], offset: ?>>)
     outs(%v: memref<f32>)
 
   return
@@ -30,13 +30,13 @@ func.func @dot(%x: memref<?xf32, offset: ?, strides: [1]>,
 // CHECK:               arith.addf
 // CHECK:               store
 
-func.func @matvec(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %x: memref<?xf32, offset: ?, strides: [1]>,
-             %y: memref<?xf32, offset: ?, strides: [1]>) {
+func.func @matvec(%A: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %x: memref<?xf32, strided<[1], offset: ?>>,
+             %y: memref<?xf32, strided<[1], offset: ?>>) {
   linalg.matvec
-    ins(%A, %x: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                memref<?xf32, offset: ?, strides: [1]>)
-    outs(%y: memref<?xf32, offset: ?, strides: [1]>)
+    ins(%A, %x: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                memref<?xf32, strided<[1], offset: ?>>)
+    outs(%y: memref<?xf32, strided<[1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @matvec
@@ -49,13 +49,13 @@ func.func @matvec(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 // CHECK:               ins({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?xf32, #[[$STRIDED_1D]]>)
 // CHECK:              outs({{.*}}: memref<?xf32, #[[$STRIDED_1D]]>)
 
-func.func @matmul(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @matmul(%A: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %B: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %C: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   linalg.matmul { __internal_linalg_transform__ = "MEM" }
-    ins(%A, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                memref<?x?xf32, offset: ?, strides: [?, 1]>)
-    outs(%C: memref<?x?xf32, offset: ?, strides: [?, 1]>)
+    ins(%A, %B: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                memref<?x?xf32, strided<[?, 1], offset: ?>>)
+    outs(%C: memref<?x?xf32, strided<[?, 1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @matmul
@@ -100,13 +100,13 @@ func.func @matmul(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
   library_call = "linalg_matmul",
   iterator_types = ["parallel", "parallel", "reduction"]
 }
-func.func @permute_generic(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-           %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-           %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @permute_generic(%A: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+           %B: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+           %C: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   linalg.generic #generic_matmul_trait
-    ins(%A, %B : memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                 memref<?x?xf32, offset: ?, strides: [?, 1]>)
-   outs(%C : memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+    ins(%A, %B : memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                 memref<?x?xf32, strided<[?, 1], offset: ?>>)
+   outs(%C : memref<?x?xf32, strided<[?, 1], offset: ?>>) {
     ^bb(%a: f32, %b: f32, %c: f32):
       %d = arith.mulf %a, %b: f32
       %e = arith.addf %c, %d: f32
@@ -127,17 +127,17 @@ transform.with_pdl_patterns {
 // CHECK-SAME:   indexing_maps = [#[[$kn]], #[[$nm]], #[[$km]]],
 // CHECK-SAME:   iterator_types = ["parallel", "reduction", "parallel"],
 // CHECK-SAME:   library_call = "linalg_matmul"}
-// CHECK:          memref<?x?xf32, #[[$STRIDED_2D_u_1]]>,
-// CHECK-SAME:     memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
-// CHECK-SAME:     memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
+// CHECK:          memref<?x?xf32, strided<[?, 1], offset: ?>>,
+// CHECK-SAME:     memref<?x?xf32, strided<[?, 1], offset: ?>>
+// CHECK-SAME:     memref<?x?xf32, strided<[?, 1], offset: ?>>
 
-func.func @matvec_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %x: memref<?xf32, offset: ?, strides: [1]>,
-             %y: memref<?xf32, offset: ?, strides: [1]>) {
+func.func @matvec_perm(%A: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %x: memref<?xf32, strided<[1], offset: ?>>,
+             %y: memref<?xf32, strided<[1], offset: ?>>) {
   linalg.matvec {__internal_linalg_transform__ = "__with_perm__"}
-    ins(%A, %x: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                memref<?xf32, offset: ?, strides: [1]>)
-   outs(%y: memref<?xf32, offset: ?, strides: [1]>)
+    ins(%A, %x: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                memref<?xf32, strided<[1], offset: ?>>)
+   outs(%y: memref<?xf32, strided<[1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @matvec_perm
@@ -150,13 +150,13 @@ func.func @matvec_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
 // CHECK:               ins({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?xf32, #[[$STRIDED_1D]]>)
 // CHECK:              outs({{.*}}: memref<?xf32, #[[$STRIDED_1D]]>)
 
-func.func @matmul_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-             %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @matmul_perm(%A: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %B: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+             %C: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   linalg.matmul {__internal_linalg_transform__ = "__with_perm__"}
-    ins(%A, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                memref<?x?xf32, offset: ?, strides: [?, 1]>)
-   outs(%C : memref<?x?xf32, offset: ?, strides: [?, 1]>)
+    ins(%A, %B: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                memref<?x?xf32, strided<[?, 1], offset: ?>>)
+   outs(%C : memref<?x?xf32, strided<[?, 1], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @matmul_perm

diff  --git a/mlir/test/Dialect/Linalg/transform-promotion.mlir b/mlir/test/Dialect/Linalg/transform-promotion.mlir
index e2980d30005c4..ad8b21e8d0a74 100644
--- a/mlir/test/Dialect/Linalg/transform-promotion.mlir
+++ b/mlir/test/Dialect/Linalg/transform-promotion.mlir
@@ -2,31 +2,29 @@
 
 // Map corresponding to a 2D memory access where the stride along the last dim is known to be 1.
 // CHECK-DAG: #[[$STRIDED_2D_u_1:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
-// Map corresponding to a 2D memory access where the stride along all dims are unknown.
-// CHECK-DAG: #[[$STRIDED_2D:.*]] = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>
-func.func @promote_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @promote_subview_matmul(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                             %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                             %arg2: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   %c2000 = arith.constant 2000 : index
   %c3000 = arith.constant 3000 : index
   %c4000 = arith.constant 4000 : index
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
-  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
+  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
   scf.for %arg3 = %c0 to %0 step %c2000 {
     scf.for %arg4 = %c0 to %2 step %c3000 {
       scf.for %arg5 = %c0 to %1 step %c4000 {
         %3 = memref.subview %arg0[%arg3, %arg5][%c2000, %c4000][%c1, %c1] :
-             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+             memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
         %4 = memref.subview %arg1[%arg5, %arg4][%c4000, %c3000][%c1, %c1] :
-             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+             memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
         %5 = memref.subview %arg2[%arg3, %arg4][%c2000, %c3000][%c1, %c1] :
-             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-        linalg.matmul ins(%3, %4: memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                                  memref<?x?xf32, offset: ?, strides: [?, ?]>)
-                     outs(%5: memref<?x?xf32, offset: ?, strides: [?, ?]>)
+             memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+        linalg.matmul ins(%3, %4: memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                                  memref<?x?xf32, strided<[?, ?], offset: ?>>)
+                     outs(%5: memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
@@ -40,9 +38,9 @@ func.func @promote_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?,
 // CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
 // CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
 // CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
-// CHECK:               %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
-// CHECK:               %[[s1:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
-// CHECK:               %[[s2:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:               %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
+// CHECK:               %[[s1:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
+// CHECK:               %[[s2:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
 // CHECK:               %[[a0:.*]] = memref.alloc() : memref<32000000xi8>
 // CHECK:               %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<32000000xi8> to memref<?x?xf32>
 // CHECK:               %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
@@ -55,9 +53,9 @@ func.func @promote_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?,
 // CHECK:               %[[v2:.*]] = memref.view %[[a2]]{{.*}} : memref<24000000xi8> to memref<?x?xf32>
 // CHECK:               %[[l2:.*]] = memref.subview %[[v2]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
 // CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
-// CHECK:               memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
-// CHECK:               memref.copy %[[s1]], %[[l1]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
-// CHECK:               memref.copy %[[s2]], %[[l2]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:               memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:               memref.copy %[[s1]], %[[l1]] : memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:               memref.copy %[[s2]], %[[l2]] : memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, #map{{.*}}>
 // CHECK:               linalg.matmul
 // CHECK-SAME:                 ins(%[[v0]], %[[v1]] : memref<?x?xf32>, memref<?x?xf32>)
 // CHECK-SAME:                outs(%[[v2]] : memref<?x?xf32>)
@@ -73,30 +71,30 @@ transform.with_pdl_patterns {
 
 // -----
 
-func.func @promote_first_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
-                             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @promote_first_subview_matmul(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                             %arg1: memref<?x?xf32, strided<[?, 1], offset: ?>>,
+                             %arg2: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   %c2000 = arith.constant 2000 : index
   %c3000 = arith.constant 3000 : index
   %c4000 = arith.constant 4000 : index
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
-  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
+  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, strided<[?, 1], offset: ?>>
   scf.for %arg3 = %c0 to %0 step %c2000 {
     scf.for %arg4 = %c0 to %2 step %c3000 {
       scf.for %arg5 = %c0 to %1 step %c4000 {
         %3 = memref.subview %arg0[%arg3, %arg5][%c2000, %c4000][%c1, %c1] :
-             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+             memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
         %4 = memref.subview %arg1[%arg5, %arg4][%c4000, %c3000][%c1, %c1] :
-             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+             memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
         %5 = memref.subview %arg2[%arg3, %arg4][%c2000, %c3000][%c1, %c1] :
-             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+             memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
         linalg.matmul {__internal_linalg_transform__ = "_promote_first_view_"}
-          ins(%3, %4: memref<?x?xf32, offset: ?, strides: [?, ?]>,
-                      memref<?x?xf32, offset: ?, strides: [?, ?]>)
-         outs(%5: memref<?x?xf32, offset: ?, strides: [?, ?]>)
+          ins(%3, %4: memref<?x?xf32, strided<[?, ?], offset: ?>>,
+                      memref<?x?xf32, strided<[?, ?], offset: ?>>)
+         outs(%5: memref<?x?xf32, strided<[?, ?], offset: ?>>)
       }
     }
   }
@@ -110,20 +108,20 @@ func.func @promote_first_subview_matmul(%arg0: memref<?x?xf32, offset: ?, stride
 // CHECK:   scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
 // CHECK:     scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
 // CHECK:       scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
-// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
-// CHECK:         %[[s1:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
-// CHECK:         %[[s2:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
+// CHECK:         %[[s1:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
+// CHECK:         %[[s2:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
 // CHECK:         %[[a0:.*]] = memref.alloc() : memref<32000000xi8>
 // CHECK:         %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<32000000xi8> to memref<?x?xf32>
 // CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
 // CHECK-NOT:     memref.alloc
 // CHECK-NOT:     memref.view
 // CHECK-NOT:     memref.subview
-// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, #map{{.*}}>
 // CHECK-NOT:     memref.copy
 // CHECK:         linalg.matmul
-// CHECK-SAME:           ins(%[[v0]], %[[s1]] : memref<?x?xf32>, memref<?x?xf32, #[[$STRIDED_2D]]>)
-// CHECK-SAME:          outs(%[[s2]] : memref<?x?xf32, #[[$STRIDED_2D]]>)
+// CHECK-SAME:           ins(%[[v0]], %[[s1]] : memref<?x?xf32>, memref<?x?xf32, strided<[?, ?], offset: ?>>)
+// CHECK-SAME:          outs(%[[s2]] : memref<?x?xf32, strided<[?, ?], offset: ?>>)
 
 transform.with_pdl_patterns {
 ^bb0(%arg0: !pdl.operation):
@@ -136,26 +134,26 @@ transform.with_pdl_patterns {
 
 // -----
 
-func.func @aligned_promote_fill(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
+func.func @aligned_promote_fill(%arg0: memref<?x?xf32, strided<[?, 1], offset: ?>>) {
   %c2000 = arith.constant 2000 : index
   %c4000 = arith.constant 4000 : index
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
   %cf = arith.constant 1.0 : f32
   %3 = memref.subview %arg0[%c0, %c0][%c2000, %c4000][%c1, %c1] :
- 	 memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+ 	 memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
   linalg.fill
-   ins(%cf : f32) outs(%3 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
+   ins(%cf : f32) outs(%3 : memref<?x?xf32, strided<[?, ?], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @aligned_promote_fill
 // CHECK:	  %[[cf:.*]] = arith.constant 1.{{.*}} : f32
-// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, strided{{.*}}>
 // CHECK:         %[[a0:.*]] = memref.alloc() {alignment = 32 : i64} : memref<32000000xi8>
 // CHECK:         %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<32000000xi8> to memref<?x?xf32>
 // CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
 // CHECK:         linalg.fill ins({{.*}} : f32) outs(%[[v0]] : memref<?x?xf32>)
-// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
+// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, strided{{.*}}> to memref<?x?xf32, #map{{.*}}>
 // CHECK:         linalg.fill ins(%[[cf]] : f32) outs(%[[v0]] : memref<?x?xf32>)
 
 transform.with_pdl_patterns {
@@ -169,7 +167,7 @@ transform.with_pdl_patterns {
 
 // -----
 
-func.func @aligned_promote_fill_complex(%arg0: memref<?x?xcomplex<f32>, offset: ?, strides: [?, 1]>) {
+func.func @aligned_promote_fill_complex(%arg0: memref<?x?xcomplex<f32>, strided<[?, 1], offset: ?>>) {
   %c2000 = arith.constant 2000 : index
   %c4000 = arith.constant 4000 : index
   %c0 = arith.constant 0 : index
@@ -177,19 +175,19 @@ func.func @aligned_promote_fill_complex(%arg0: memref<?x?xcomplex<f32>, offset:
   %cf = arith.constant 1.0 : f32
   %cc = complex.create %cf, %cf : complex<f32>
   %3 = memref.subview %arg0[%c0, %c0][%c2000, %c4000][%c1, %c1] :
- 	 memref<?x?xcomplex<f32>, offset: ?, strides: [?, 1]> to memref<?x?xcomplex<f32>, offset: ?, strides: [?, ?]>
+ 	 memref<?x?xcomplex<f32>, strided<[?, 1], offset: ?>> to memref<?x?xcomplex<f32>, strided<[?, ?], offset: ?>>
   linalg.fill ins(%cc : complex<f32>) 
-             outs(%3 : memref<?x?xcomplex<f32>, offset: ?, strides: [?, ?]>)
+             outs(%3 : memref<?x?xcomplex<f32>, strided<[?, ?], offset: ?>>)
   return
 }
 // CHECK-LABEL: func @aligned_promote_fill_complex
 // CHECK:	  %[[cc:.*]] = complex.create {{.*}} : complex<f32>
-// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xcomplex<f32>, #map{{.*}}> to memref<?x?xcomplex<f32>, #map{{.*}}>
+// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xcomplex<f32>, strided{{.*}}> to memref<?x?xcomplex<f32>, strided{{.*}}>
 // CHECK:         %[[a0:.*]] = memref.alloc() {alignment = 32 : i64} : memref<64000000xi8>
 // CHECK:         %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<64000000xi8> to memref<?x?xcomplex<f32>>
 // CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xcomplex<f32>> to memref<?x?xcomplex<f32>, #[[$STRIDED_2D_u_1]]>
 // CHECK:         linalg.fill ins({{.*}} : complex<f32>) outs(%[[v0]] : memref<?x?xcomplex<f32>>)
-// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xcomplex<f32>, #map{{.*}}> to memref<?x?xcomplex<f32>, #map{{.*}}>
+// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xcomplex<f32>, strided{{.*}}> to memref<?x?xcomplex<f32>, #map{{.*}}>
 // CHECK:         linalg.fill ins(%[[cc]] : complex<f32>) outs(%[[v0]] : memref<?x?xcomplex<f32>>)
 
 transform.with_pdl_patterns {

diff  --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir
index 454277599dc71..1241d925e7f82 100644
--- a/mlir/test/Dialect/MemRef/canonicalize.mlir
+++ b/mlir/test/Dialect/MemRef/canonicalize.mlir
@@ -88,59 +88,61 @@ func.func @rank_reducing_subview_canonicalize(%arg0 : memref<?x?x?xf32>, %arg1 :
 
 // -----
 
+// CHECK-DAG: #[[MAP0:.*]] = affine_map<(d0, d1)[s0] -> (d0 * 384 + s0 + d1)>
+// CHECK-DAG: #[[MAP1:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
+
 func.func @multiple_reducing_dims(%arg0 : memref<1x384x384xf32>,
-    %arg1 : index, %arg2 : index, %arg3 : index) -> memref<?xf32, offset: ?, strides: [1]>
+    %arg1 : index, %arg2 : index, %arg3 : index) -> memref<?xf32, strided<[1], offset: ?>>
 {
   %c1 = arith.constant 1 : index
-  %0 = memref.subview %arg0[0, %arg1, %arg2] [1, %c1, %arg3] [1, 1, 1] : memref<1x384x384xf32> to memref<?x?xf32, offset: ?, strides: [384, 1]>
-  %1 = memref.subview %0[0, 0] [1, %arg3] [1, 1] : memref<?x?xf32, offset: ?, strides: [384, 1]> to memref<?xf32, offset: ?, strides: [1]>
-  return %1 : memref<?xf32, offset: ?, strides: [1]>
+  %0 = memref.subview %arg0[0, %arg1, %arg2] [1, %c1, %arg3] [1, 1, 1] : memref<1x384x384xf32> to memref<?x?xf32, strided<[384, 1], offset: ?>>
+  %1 = memref.subview %0[0, 0] [1, %arg3] [1, 1] : memref<?x?xf32, strided<[384, 1], offset: ?>> to memref<?xf32, strided<[1], offset: ?>>
+  return %1 : memref<?xf32, strided<[1], offset: ?>>
 }
-//   CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0)[s0] -> (d0 + s0)>
-//   CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1)[s0] -> (d0 * 384 + s0 + d1)>
 //       CHECK: func @multiple_reducing_dims
 //       CHECK:   %[[REDUCED1:.+]] = memref.subview %{{.+}}[0, %{{.+}}, %{{.+}}] [1, 1, %{{.+}}] [1, 1, 1]
-//  CHECK-SAME:       : memref<1x384x384xf32> to memref<1x?xf32, #[[MAP1]]>
+//  CHECK-SAME:       : memref<1x384x384xf32> to memref<1x?xf32, #[[MAP0]]>
 //       CHECK:   %[[REDUCED2:.+]] = memref.subview %[[REDUCED1]][0, 0] [1, %{{.+}}] [1, 1]
-//  CHECK-SAME:       : memref<1x?xf32, #[[MAP1]]> to memref<?xf32, #[[MAP0]]>
+//  CHECK-SAME:       : memref<1x?xf32, #[[MAP0]]> to memref<?xf32, #[[MAP1]]>
 
 // -----
 
+// CHECK-DAG: #[[MAP0]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
+// CHECK-DAG: #[[MAP1]] = affine_map<(d0)[s0] -> (d0 + s0)>
+
 func.func @multiple_reducing_dims_dynamic(%arg0 : memref<?x?x?xf32>,
-    %arg1 : index, %arg2 : index, %arg3 : index) -> memref<?xf32, offset: ?, strides: [1]>
+    %arg1 : index, %arg2 : index, %arg3 : index) -> memref<?xf32, strided<[1], offset: ?>>
 {
   %c1 = arith.constant 1 : index
-  %0 = memref.subview %arg0[0, %arg1, %arg2] [1, %c1, %arg3] [1, 1, 1] : memref<?x?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, 1]>
-  %1 = memref.subview %0[0, 0] [1, %arg3] [1, 1] : memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?xf32, offset: ?, strides: [1]>
-  return %1 : memref<?xf32, offset: ?, strides: [1]>
+  %0 = memref.subview %arg0[0, %arg1, %arg2] [1, %c1, %arg3] [1, 1, 1] : memref<?x?x?xf32> to memref<?x?xf32, strided<[?, 1], offset: ?>>
+  %1 = memref.subview %0[0, 0] [1, %arg3] [1, 1] : memref<?x?xf32, strided<[?, 1], offset: ?>> to memref<?xf32, strided<[1], offset: ?>>
+  return %1 : memref<?xf32, strided<[1], offset: ?>>
 }
-//   CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0)[s0] -> (d0 + s0)>
-//   CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
 //       CHECK: func @multiple_reducing_dims_dynamic
 //       CHECK:   %[[REDUCED1:.+]] = memref.subview %{{.+}}[0, %{{.+}}, %{{.+}}] [1, 1, %{{.+}}] [1, 1, 1]
-//  CHECK-SAME:       : memref<?x?x?xf32> to memref<1x?xf32, #[[MAP1]]>
+//  CHECK-SAME:       : memref<?x?x?xf32> to memref<1x?xf32, #[[MAP0]]>
 //       CHECK:   %[[REDUCED2:.+]] = memref.subview %[[REDUCED1]][0, 0] [1, %{{.+}}] [1, 1]
-//  CHECK-SAME:       : memref<1x?xf32, #[[MAP1]]> to memref<?xf32, #[[MAP0]]>
+//  CHECK-SAME:       : memref<1x?xf32, #[[MAP0]]> to memref<?xf32, #[[MAP1]]>
 
 // -----
 
-func.func @multiple_reducing_dims_all_dynamic(%arg0 : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>,
-    %arg1 : index, %arg2 : index, %arg3 : index) -> memref<?xf32, offset: ?, strides: [?]>
+// CHECK-DAG: #[[MAP0]] = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>
+// CHECK-DAG: #[[MAP1]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
+
+func.func @multiple_reducing_dims_all_dynamic(%arg0 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>,
+    %arg1 : index, %arg2 : index, %arg3 : index) -> memref<?xf32, strided<[?], offset: ?>>
 {
   %c1 = arith.constant 1 : index
   %0 = memref.subview %arg0[0, %arg1, %arg2] [1, %c1, %arg3] [1, 1, 1]
-      : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-  %1 = memref.subview %0[0, 0] [1, %arg3] [1, 1] : memref<?x?xf32, offset: ?, strides: [?, ?]> to memref<?xf32, offset: ?, strides: [?]>
-  return %1 : memref<?xf32, offset: ?, strides: [?]>
+      : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+  %1 = memref.subview %0[0, 0] [1, %arg3] [1, 1] : memref<?x?xf32, strided<[?, ?], offset: ?>> to memref<?xf32, strided<[?], offset: ?>>
+  return %1 : memref<?xf32, strided<[?], offset: ?>>
 }
-//   CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
-//   CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>
-//   CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
 //       CHECK: func @multiple_reducing_dims_all_dynamic
 //       CHECK:   %[[REDUCED1:.+]] = memref.subview %{{.+}}[0, %{{.+}}, %{{.+}}] [1, 1, %{{.+}}] [1, 1, 1]
-//  CHECK-SAME:       : memref<?x?x?xf32, #[[MAP2]]> to memref<1x?xf32, #[[MAP1]]>
+//  CHECK-SAME:       : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>> to memref<1x?xf32, #[[MAP0]]>
 //       CHECK:   %[[REDUCED2:.+]] = memref.subview %[[REDUCED1]][0, 0] [1, %{{.+}}] [1, 1]
-//  CHECK-SAME:       : memref<1x?xf32, #[[MAP1]]> to memref<?xf32, #[[MAP0]]>
+//  CHECK-SAME:       : memref<1x?xf32, #[[MAP0]]> to memref<?xf32, #[[MAP1]]>
 
 
 // -----
@@ -330,15 +332,15 @@ func.func @compose_collapse_of_collapse(%arg0 : memref<?x?x?x?x?xf32>)
 // -----
 
 func.func @do_not_compose_collapse_of_expand_non_identity_layout(
-    %arg0: memref<?x?xf32, offset : 0, strides : [?, 1]>)
-    -> memref<?xf32, offset : 0, strides : [?]> {
+    %arg0: memref<?x?xf32, strided<[?, 1], offset: 0>>)
+    -> memref<?xf32, strided<[?], offset: 0>> {
   %1 = memref.expand_shape %arg0 [[0, 1], [2]] :
-    memref<?x?xf32, offset : 0, strides : [?, 1]> into
-    memref<?x4x?xf32, offset : 0, strides : [?, ?, 1]>
+    memref<?x?xf32, strided<[?, 1], offset: 0>> into
+    memref<?x4x?xf32, strided<[?, ?, 1], offset: 0>>
   %2 = memref.collapse_shape %1 [[0, 1, 2]] :
-    memref<?x4x?xf32, offset : 0, strides : [?, ?, 1]> into
-    memref<?xf32, offset : 0, strides : [?]>
-  return %2 : memref<?xf32, offset : 0, strides : [?]>
+    memref<?x4x?xf32, strided<[?, ?, 1], offset: 0>> into
+    memref<?xf32, strided<[?], offset: 0>>
+  return %2 : memref<?xf32, strided<[?], offset: 0>>
 }
 // CHECK-LABEL: func @do_not_compose_collapse_of_expand_non_identity_layout
 // CHECK: expand
@@ -747,10 +749,10 @@ func.func @reinterpret_of_subview(%arg : memref<?xi8>, %size1: index, %size2: in
 //  CHECK-SAME: (%[[ARG:.*]]: memref<8x2xf32>)
 //       CHECK: %[[CAST:.*]] = memref.cast %[[ARG]] : memref<8x2xf32> to memref<?x?xf32,
 //       CHECK: return %[[CAST]]
-func.func @reinterpret_of_extract_strided_metadata_w_type_mistach(%arg0 : memref<8x2xf32>) -> memref<?x?xf32, offset : ?, strides : [?, ?]> {
+func.func @reinterpret_of_extract_strided_metadata_w_type_mistach(%arg0 : memref<8x2xf32>) -> memref<?x?xf32, strided<[?, ?], offset: ?>> {
   %base, %offset, %sizes:2, %strides:2 = memref.extract_strided_metadata %arg0 : memref<8x2xf32> -> memref<f32>, index, index, index, index, index
-  %m2 = memref.reinterpret_cast %base to offset: [%offset], sizes: [%sizes#0, %sizes#1], strides: [%strides#0, %strides#1] : memref<f32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-  return %m2 : memref<?x?xf32, offset: ?, strides: [?, ?]>
+  %m2 = memref.reinterpret_cast %base to offset: [%offset], sizes: [%sizes#0, %sizes#1], strides: [%strides#0, %strides#1] : memref<f32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+  return %m2 : memref<?x?xf32, strided<[?, ?], offset: ?>>
 }
 
 // -----
@@ -775,10 +777,10 @@ func.func @reinterpret_of_extract_strided_metadata_same_type(%arg0 : memref<8x2x
 //       CHECK: %[[BASE:.*]], %[[OFFSET:.*]], %[[SIZES:.*]]:2, %[[STRIDES:.*]]:2 = memref.extract_strided_metadata %[[ARG]]
 //       CHECK: %[[RES:.*]] = memref.reinterpret_cast %[[BASE]] to offset: [%[[OFFSET]]], sizes: [4, 2, 2], strides: [1, 1, %[[STRIDES]]#1]
 //       CHECK: return %[[RES]]
-func.func @reinterpret_of_extract_strided_metadata_w_
diff erent_stride(%arg0 : memref<8x2xf32>) -> memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]> {
+func.func @reinterpret_of_extract_strided_metadata_w_
diff erent_stride(%arg0 : memref<8x2xf32>) -> memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>> {
   %base, %offset, %sizes:2, %strides:2 = memref.extract_strided_metadata %arg0 : memref<8x2xf32> -> memref<f32>, index, index, index, index, index
-  %m2 = memref.reinterpret_cast %base to offset: [%offset], sizes: [4, 2, 2], strides: [1, 1, %strides#1] : memref<f32> to memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
-  return %m2 : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+  %m2 = memref.reinterpret_cast %base to offset: [%offset], sizes: [4, 2, 2], strides: [1, 1, %strides#1] : memref<f32> to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  return %m2 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 }
 // -----
 
@@ -789,20 +791,20 @@ func.func @reinterpret_of_extract_strided_metadata_w_
diff erent_stride(%arg0 : me
 //       CHECK: %[[BASE:.*]], %[[OFFSET:.*]], %[[SIZES:.*]]:2, %[[STRIDES:.*]]:2 = memref.extract_strided_metadata %[[ARG]]
 //       CHECK: %[[RES:.*]] = memref.reinterpret_cast %[[BASE]] to offset: [1], sizes: [%[[SIZES]]#0, %[[SIZES]]#1], strides: [%[[STRIDES]]#0, %[[STRIDES]]#1]
 //       CHECK: return %[[RES]]
-func.func @reinterpret_of_extract_strided_metadata_w_
diff erent_offset(%arg0 : memref<8x2xf32>) -> memref<?x?xf32, offset : ?, strides : [?, ?]> {
+func.func @reinterpret_of_extract_strided_metadata_w_
diff erent_offset(%arg0 : memref<8x2xf32>) -> memref<?x?xf32, strided<[?, ?], offset: ?>> {
   %base, %offset, %sizes:2, %strides:2 = memref.extract_strided_metadata %arg0 : memref<8x2xf32> -> memref<f32>, index, index, index, index, index
-  %m2 = memref.reinterpret_cast %base to offset: [1], sizes: [%sizes#0, %sizes#1], strides: [%strides#0, %strides#1] : memref<f32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
-  return %m2 : memref<?x?xf32, offset: ?, strides: [?, ?]>
+  %m2 = memref.reinterpret_cast %base to offset: [1], sizes: [%sizes#0, %sizes#1], strides: [%strides#0, %strides#1] : memref<f32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+  return %m2 : memref<?x?xf32, strided<[?, ?], offset: ?>>
 }
 
 // -----
 
 func.func @canonicalize_rank_reduced_subview(%arg0 : memref<8x?xf32>,
-    %arg1 : index) -> memref<?xf32, offset : ?, strides : [?]> {
+    %arg1 : index) -> memref<?xf32, strided<[?], offset: ?>> {
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
-  %0 = memref.subview %arg0[%c0, %c0] [1, %arg1] [%c1, %c1] : memref<8x?xf32> to memref<?xf32, offset : ?, strides : [?]>
-  return %0 :  memref<?xf32, offset : ?, strides : [?]>
+  %0 = memref.subview %arg0[%c0, %c0] [1, %arg1] [%c1, %c1] : memref<8x?xf32> to memref<?xf32, strided<[?], offset: ?>>
+  return %0 :  memref<?xf32, strided<[?], offset: ?>>
 }
 //  CHECK-DAG: #[[MAP:.+]] = affine_map<(d0)[s0] -> (d0 + s0)>
 //      CHECK: func @canonicalize_rank_reduced_subview

diff  --git a/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir b/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir
index 18c2b3f403e98..9ee6893f8b1f7 100644
--- a/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir
+++ b/mlir/test/Dialect/MemRef/fold-memref-alias-ops.mlir
@@ -1,8 +1,8 @@
 // RUN: mlir-opt -fold-memref-alias-ops -split-input-file %s -o - | FileCheck %s
 
 func.func @fold_static_stride_subview_with_load(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index) -> f32 {
-  %0 = memref.subview %arg0[%arg1, %arg2][4, 4][2, 3] : memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [64, 3]>
-  %1 = memref.load %0[%arg3, %arg4] : memref<4x4xf32, offset:?, strides: [64, 3]>
+  %0 = memref.subview %arg0[%arg1, %arg2][4, 4][2, 3] : memref<12x32xf32> to memref<4x4xf32, strided<[64, 3], offset: ?>>
+  %1 = memref.load %0[%arg3, %arg4] : memref<4x4xf32, strided<[64, 3], offset: ?>>
   return %1 : f32
 }
 //  CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0)[s0] -> (d0 * 2 + s0)>
@@ -21,8 +21,8 @@ func.func @fold_static_stride_subview_with_load(%arg0 : memref<12x32xf32>, %arg1
 
 func.func @fold_dynamic_stride_subview_with_load(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index, %arg5 : index, %arg6 : index) -> f32 {
   %0 = memref.subview %arg0[%arg1, %arg2][4, 4][%arg5, %arg6] :
-    memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [?, ?]>
-  %1 = memref.load %0[%arg3, %arg4] : memref<4x4xf32, offset:?, strides: [?, ?]>
+    memref<12x32xf32> to memref<4x4xf32, strided<[?, ?], offset: ?>>
+  %1 = memref.load %0[%arg3, %arg4] : memref<4x4xf32, strided<[?, ?], offset: ?>>
   return %1 : f32
 }
 //  CHECK-DAG: #[[MAP:.+]] = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>
@@ -42,8 +42,8 @@ func.func @fold_dynamic_stride_subview_with_load(%arg0 : memref<12x32xf32>, %arg
 
 func.func @fold_static_stride_subview_with_store(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index, %arg5 : f32) {
   %0 = memref.subview %arg0[%arg1, %arg2][4, 4][2, 3] :
-    memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [64, 3]>
-  memref.store %arg5, %0[%arg3, %arg4] : memref<4x4xf32, offset:?, strides: [64, 3]>
+    memref<12x32xf32> to memref<4x4xf32, strided<[64, 3], offset: ?>>
+  memref.store %arg5, %0[%arg3, %arg4] : memref<4x4xf32, strided<[64, 3], offset: ?>>
   return
 }
 //  CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0)[s0] -> (d0 * 2 + s0)>
@@ -62,8 +62,8 @@ func.func @fold_static_stride_subview_with_store(%arg0 : memref<12x32xf32>, %arg
 
 func.func @fold_dynamic_stride_subview_with_store(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index, %arg5 : index, %arg6 : index, %arg7 : f32) {
   %0 = memref.subview %arg0[%arg1, %arg2][4, 4][%arg5, %arg6] :
-    memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [?, ?]>
-  memref.store %arg7, %0[%arg3, %arg4] : memref<4x4xf32, offset:?, strides: [?, ?]>
+    memref<12x32xf32> to memref<4x4xf32, strided<[?, ?], offset: ?>>
+  memref.store %arg7, %0[%arg3, %arg4] : memref<4x4xf32, strided<[?, ?], offset: ?>>
   return
 }
 //  CHECK-DAG: #[[MAP:.+]] = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>
@@ -83,8 +83,8 @@ func.func @fold_dynamic_stride_subview_with_store(%arg0 : memref<12x32xf32>, %ar
 
 func.func @fold_subview_with_transfer_read(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index, %arg5 : index, %arg6 : index) -> vector<4xf32> {
   %f1 = arith.constant 1.0 : f32
-  %0 = memref.subview %arg0[%arg1, %arg2][4, 4][%arg5, %arg6] : memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [?, ?]>
-  %1 = vector.transfer_read %0[%arg3, %arg4], %f1 {in_bounds = [true]} : memref<4x4xf32, offset:?, strides: [?, ?]>, vector<4xf32>
+  %0 = memref.subview %arg0[%arg1, %arg2][4, 4][%arg5, %arg6] : memref<12x32xf32> to memref<4x4xf32, strided<[?, ?], offset: ?>>
+  %1 = vector.transfer_read %0[%arg3, %arg4], %f1 {in_bounds = [true]} : memref<4x4xf32, strided<[?, ?], offset: ?>>, vector<4xf32>
   return %1 : vector<4xf32>
 }
 //  CHECK-DAG: #[[MAP:.+]] = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>
@@ -104,8 +104,8 @@ func.func @fold_subview_with_transfer_read(%arg0 : memref<12x32xf32>, %arg1 : in
 
 func.func @fold_static_stride_subview_with_transfer_write(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index, %arg5: index, %arg6 : index, %arg7 : vector<4xf32>) {
   %0 = memref.subview %arg0[%arg1, %arg2][4, 4][%arg5, %arg6] :
-    memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [?, ?]>
-  vector.transfer_write %arg7, %0[%arg3, %arg4] {in_bounds = [true]} : vector<4xf32>, memref<4x4xf32, offset:?, strides: [?, ?]>
+    memref<12x32xf32> to memref<4x4xf32, strided<[?, ?], offset: ?>>
+  vector.transfer_write %arg7, %0[%arg3, %arg4] {in_bounds = [true]} : vector<4xf32>, memref<4x4xf32, strided<[?, ?], offset: ?>>
   return
 }
 //  CHECK-DAG: #[[MAP:.+]] = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>
@@ -129,8 +129,8 @@ func.func @fold_rank_reducing_subview_with_load
      %arg7 : index, %arg8 : index, %arg9 : index, %arg10: index,
      %arg11 : index, %arg12 : index, %arg13 : index, %arg14: index,
      %arg15 : index, %arg16 : index) -> f32 {
-  %0 = memref.subview %arg0[%arg1, %arg2, %arg3, %arg4, %arg5, %arg6][4, 1, 1, 4, 1, 1][%arg7, %arg8, %arg9, %arg10, %arg11, %arg12] : memref<?x?x?x?x?x?xf32> to memref<4x1x4x1xf32, offset:?, strides: [?, ?, ?, ?]>
-  %1 = memref.load %0[%arg13, %arg14, %arg15, %arg16] : memref<4x1x4x1xf32, offset:?, strides: [?, ?, ?, ?]>
+  %0 = memref.subview %arg0[%arg1, %arg2, %arg3, %arg4, %arg5, %arg6][4, 1, 1, 4, 1, 1][%arg7, %arg8, %arg9, %arg10, %arg11, %arg12] : memref<?x?x?x?x?x?xf32> to memref<4x1x4x1xf32, strided<[?, ?, ?, ?], offset: ?>>
+  %1 = memref.load %0[%arg13, %arg14, %arg15, %arg16] : memref<4x1x4x1xf32, strided<[?, ?, ?, ?], offset: ?>>
   return %1 : f32
 }
 //  CHECK-DAG: #[[MAP:.+]] = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>
@@ -164,21 +164,20 @@ func.func @fold_rank_reducing_subview_with_load
 // -----
 
 func.func @fold_vector_transfer_read_with_rank_reduced_subview(
-    %arg0 : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>,
+    %arg0 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>,
     %arg1: index, %arg2 : index, %arg3 : index, %arg4: index, %arg5 : index,
     %arg6 : index) -> vector<4xf32> {
   %cst = arith.constant 0.0 : f32
   %0 = memref.subview %arg0[0, %arg1, %arg2] [1, %arg3, %arg4] [1, 1, 1]
-      : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+      : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>> to
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
   %1 = vector.transfer_read %0[%arg5, %arg6], %cst {in_bounds = [true]}
-      : memref<?x?xf32, offset: ?, strides: [?, ?]>, vector<4xf32>
+      : memref<?x?xf32, strided<[?, ?], offset: ?>>, vector<4xf32>
   return %1 : vector<4xf32>
 }
-//   CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
 //   CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0)[s0] -> (d0 + s0)>
 //       CHECK: func @fold_vector_transfer_read_with_rank_reduced_subview
-//  CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?xf32, #[[MAP0]]>
+//  CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 //  CHECK-SAME:    %[[ARG1:[a-zA-Z0-9]+]]: index
 //  CHECK-SAME:    %[[ARG2:[a-zA-Z0-9]+]]: index
 //  CHECK-SAME:    %[[ARG3:[a-zA-Z0-9]+]]: index
@@ -193,21 +192,20 @@ func.func @fold_vector_transfer_read_with_rank_reduced_subview(
 // -----
 
 func.func @fold_vector_transfer_write_with_rank_reduced_subview(
-    %arg0 : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>,
+    %arg0 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>,
     %arg1 : vector<4xf32>, %arg2: index, %arg3 : index, %arg4 : index,
     %arg5: index, %arg6 : index, %arg7 : index) {
   %cst = arith.constant 0.0 : f32
   %0 = memref.subview %arg0[0, %arg2, %arg3] [1, %arg4, %arg5] [1, 1, 1]
-      : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+      : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>> to
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
   vector.transfer_write %arg1, %0[%arg6, %arg7] {in_bounds = [true]}
-      : vector<4xf32>, memref<?x?xf32, offset: ?, strides: [?, ?]>
+      : vector<4xf32>, memref<?x?xf32, strided<[?, ?], offset: ?>>
   return
 }
-//   CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
 //   CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0)[s0] -> (d0 + s0)>
 //       CHECK: func @fold_vector_transfer_write_with_rank_reduced_subview
-//  CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?xf32, #[[MAP0]]>
+//  CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 //  CHECK-SAME:    %[[ARG1:[a-zA-Z0-9]+]]: vector<4xf32>
 //  CHECK-SAME:    %[[ARG2:[a-zA-Z0-9]+]]: index
 //  CHECK-SAME:    %[[ARG3:[a-zA-Z0-9]+]]: index
@@ -223,22 +221,21 @@ func.func @fold_vector_transfer_write_with_rank_reduced_subview(
 // -----
 
 func.func @fold_vector_transfer_write_with_inner_rank_reduced_subview(
-    %arg0 : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>,
+    %arg0 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>,
     %arg1 : vector<4xf32>, %arg2: index, %arg3 : index, %arg4 : index,
     %arg5: index, %arg6 : index, %arg7 : index) {
   %cst = arith.constant 0.0 : f32
   %0 = memref.subview %arg0[%arg2, %arg3, 0] [%arg4, %arg5, 1] [1, 1, 1]
-      : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]> to
-        memref<?x?xf32, offset: ?, strides: [?, ?]>
+      : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>> to
+        memref<?x?xf32, strided<[?, ?], offset: ?>>
   vector.transfer_write %arg1, %0[%arg6, %arg7] {in_bounds = [true]}
-      : vector<4xf32>, memref<?x?xf32, offset: ?, strides: [?, ?]>
+      : vector<4xf32>, memref<?x?xf32, strided<[?, ?], offset: ?>>
   return
 }
-//   CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
 //   CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0)[s0] -> (d0 + s0)>
 //   CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1, d2) -> (d1)>
 //       CHECK: func @fold_vector_transfer_write_with_inner_rank_reduced_subview
-//  CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?xf32, #[[MAP0]]>
+//  CHECK-SAME:    %[[ARG0:[a-zA-Z0-9]+]]: memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 //  CHECK-SAME:    %[[ARG1:[a-zA-Z0-9]+]]: vector<4xf32>
 //  CHECK-SAME:    %[[ARG2:[a-zA-Z0-9]+]]: index
 //  CHECK-SAME:    %[[ARG3:[a-zA-Z0-9]+]]: index
@@ -260,12 +257,12 @@ func.func @fold_vector_transfer_write_with_inner_rank_reduced_subview(
 
 // CHECK-LABEL: func @fold_static_stride_subview_with_affine_load_store
 func.func @fold_static_stride_subview_with_affine_load_store(%arg0 : memref<12x32xf32>, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index) -> f32 {
-  %0 = memref.subview %arg0[%arg1, %arg2][4, 4][2, 3] : memref<12x32xf32> to memref<4x4xf32, offset:?, strides: [64, 3]>
-  %1 = affine.load %0[%arg3, %arg4] : memref<4x4xf32, offset:?, strides: [64, 3]>
+  %0 = memref.subview %arg0[%arg1, %arg2][4, 4][2, 3] : memref<12x32xf32> to memref<4x4xf32, strided<[64, 3], offset: ?>>
+  %1 = affine.load %0[%arg3, %arg4] : memref<4x4xf32, strided<[64, 3], offset: ?>>
   // CHECK-NEXT: affine.apply
   // CHECK-NEXT: affine.apply
   // CHECK-NEXT: affine.load
-  affine.store %1, %0[%arg3, %arg4] : memref<4x4xf32, offset:?, strides: [64, 3]>
+  affine.store %1, %0[%arg3, %arg4] : memref<4x4xf32, strided<[64, 3], offset: ?>>
   // CHECK-NEXT: affine.apply
   // CHECK-NEXT: affine.apply
   // CHECK-NEXT: affine.store

diff  --git a/mlir/test/Dialect/MemRef/invalid.mlir b/mlir/test/Dialect/MemRef/invalid.mlir
index bf6d32357751a..77dc58044e48c 100644
--- a/mlir/test/Dialect/MemRef/invalid.mlir
+++ b/mlir/test/Dialect/MemRef/invalid.mlir
@@ -152,7 +152,7 @@ func.func @memref_reinterpret_cast_too_many_offsets(%in: memref<?xf32>) {
   // expected-error @+1 {{expected 1 offset values}}
   %out = memref.reinterpret_cast %in to
            offset: [0, 0], sizes: [10, 10], strides: [10, 1]
-           : memref<?xf32> to memref<10x10xf32, offset: 0, strides: [10, 1]>
+           : memref<?xf32> to memref<10x10xf32, strided<[10, 1], offset: 0>>
   return
 }
 
@@ -162,7 +162,7 @@ func.func @memref_reinterpret_cast_incompatible_element_types(%in: memref<*xf32>
   // expected-error @+1 {{
diff erent element types specified}}
   %out = memref.reinterpret_cast %in to
            offset: [0], sizes: [10], strides: [1]
-         : memref<*xf32> to memref<10xi32, offset: 0, strides: [1]>
+         : memref<*xf32> to memref<10xi32, strided<[1], offset: 0>>
   return
 }
 
@@ -172,7 +172,7 @@ func.func @memref_reinterpret_cast_incompatible_memory_space(%in: memref<*xf32>)
   // expected-error @+1 {{
diff erent memory spaces specified}}
   %out = memref.reinterpret_cast %in to
            offset: [0], sizes: [10], strides: [1]
-         : memref<*xf32> to memref<10xi32, offset: 0, strides: [1], 2>
+         : memref<*xf32> to memref<10xi32, strided<[1], offset: 0>, 2>
   return
 }
 
@@ -182,7 +182,7 @@ func.func @memref_reinterpret_cast_offset_mismatch(%in: memref<?xf32>) {
   // expected-error @+1 {{expected result type with offset = 2 instead of 1}}
   %out = memref.reinterpret_cast %in to
            offset: [1], sizes: [10], strides: [1]
-         : memref<?xf32> to memref<10xf32, offset: 2, strides: [1]>
+         : memref<?xf32> to memref<10xf32, strided<[1], offset: 2>>
   return
 }
 
@@ -192,7 +192,7 @@ func.func @memref_reinterpret_cast_size_mismatch(%in: memref<*xf32>) {
   // expected-error @+1 {{expected result type with size = 10 instead of 1 in dim = 0}}
   %out = memref.reinterpret_cast %in to
            offset: [0], sizes: [10], strides: [1]
-         : memref<*xf32> to memref<1xf32, offset: 0, strides: [1]>
+         : memref<*xf32> to memref<1xf32, strided<[1], offset: 0>>
   return
 }
 
@@ -202,7 +202,7 @@ func.func @memref_reinterpret_cast_offset_mismatch(%in: memref<?xf32>) {
   // expected-error @+1 {{expected result type with stride = 2 instead of 1 in dim = 0}}
   %out = memref.reinterpret_cast %in to
            offset: [2], sizes: [10], strides: [2]
-         : memref<?xf32> to memref<10xf32, offset: 2, strides: [1]>
+         : memref<?xf32> to memref<10xf32, strided<[1], offset: 2>>
   return
 }
 
@@ -272,11 +272,11 @@ func.func @memref_reshape_dst_shape_rank_mismatch(
 // -----
 
 func.func @memref_reshape_src_affine_map_is_not_identity(
-        %buf: memref<4x4xf32, offset: 0, strides: [3, 2]>,
+        %buf: memref<4x4xf32, strided<[3, 2], offset: 0>>,
         %shape: memref<1xi32>) {
   // expected-error @+1 {{source memref type should have identity affine map}}
   memref.reshape %buf(%shape)
-    : (memref<4x4xf32, offset: 0, strides: [3, 2]>, memref<1xi32>)
+    : (memref<4x4xf32, strided<[3, 2], offset: 0>>, memref<1xi32>)
     -> memref<8xf32>
 }
 
@@ -286,7 +286,7 @@ func.func @memref_reshape_result_affine_map_is_not_identity(
         %buf: memref<4x4xf32>, %shape: memref<1xi32>) {
   // expected-error @+1 {{result memref type should have identity affine map}}
   memref.reshape %buf(%shape)
-    : (memref<4x4xf32>, memref<1xi32>) -> memref<8xf32, offset: 0, strides: [2]>
+    : (memref<4x4xf32>, memref<1xi32>) -> memref<8xf32, strided<[2], offset: 0>>
 }
 
 // -----
@@ -423,11 +423,11 @@ func.func @expand_shape_to_smaller_rank(%arg0: memref<1xf32>) {
 // -----
 
 func.func @expand_shape_invalid_result_layout(
-    %arg0: memref<30x20xf32, offset : 100, strides : [4000, 2]>) {
+    %arg0: memref<30x20xf32, strided<[4000, 2], offset: 100>>) {
   // expected-error @+1 {{expected expanded type to be 'memref<2x15x20xf32, affine_map<(d0, d1, d2) -> (d0 * 60000 + d1 * 4000 + d2 * 2 + 100)>>' but found 'memref<2x15x20xf32, affine_map<(d0, d1, d2) -> (d0 * 5000 + d1 * 4000 + d2 * 2 + 100)>>'}}
   %0 = memref.expand_shape %arg0 [[0, 1], [2]] :
-      memref<30x20xf32, offset : 100, strides : [4000, 2]>
-      into memref<2x15x20xf32, offset : 100, strides : [5000, 4000, 2]>
+      memref<30x20xf32, strided<[4000, 2], offset: 100>>
+      into memref<2x15x20xf32, strided<[5000, 4000, 2], offset: 100>>
 }
 
 // -----
@@ -435,7 +435,7 @@ func.func @expand_shape_invalid_result_layout(
 func.func @collapse_shape_mismatch_indices_num(%arg0: memref<?x?x?xf32>) {
   // expected-error @+1 {{invalid number of reassociation groups: found 1, expected 2}}
   %0 = memref.collapse_shape %arg0 [[0, 1]] :
-    memref<?x?x?xf32> into memref<?x?xf32, offset: 0, strides: [?, 1]>
+    memref<?x?x?xf32> into memref<?x?xf32, strided<[?, 1], offset: 0>>
 }
 
 // -----
@@ -443,17 +443,17 @@ func.func @collapse_shape_mismatch_indices_num(%arg0: memref<?x?x?xf32>) {
 func.func @collapse_shape_invalid_reassociation(%arg0: memref<?x?x?xf32>) {
   // expected-error @+1 {{reassociation indices must be contiguous}}
   %0 = memref.collapse_shape %arg0 [[0, 1], [1, 2]] :
-    memref<?x?x?xf32> into memref<?x?xf32, offset: 0, strides: [?, 1]>
+    memref<?x?x?xf32> into memref<?x?xf32, strided<[?, 1], offset: 0>>
 }
 
 // -----
 
 func.func @collapse_shape_reshaping_non_contiguous(
-    %arg0: memref<3x4x5xf32, offset: 0, strides: [270, 50, 10]>) {
+    %arg0: memref<3x4x5xf32, strided<[270, 50, 10], offset: 0>>) {
   // expected-error @+1 {{invalid source layout map or collapsing non-contiguous dims}}
   %0 = memref.collapse_shape %arg0 [[0, 1], [2]] :
-      memref<3x4x5xf32, offset: 0, strides: [270, 50, 10]>
-      into memref<12x5xf32, offset: 0, strides: [50, 1]>
+      memref<3x4x5xf32, strided<[270, 50, 10], offset: 0>>
+      into memref<12x5xf32, strided<[50, 1], offset: 0>>
   return
 }
 
@@ -628,10 +628,10 @@ func.func @invalid_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
 // -----
 
 func.func @invalid_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
-  %0 = memref.alloc() : memref<8x16x4xf32, offset: 0, strides: [64, 4, 1], 2>
+  %0 = memref.alloc() : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>, 2>
   // expected-error at +1 {{
diff erent memory spaces}}
   %1 = memref.subview %0[0, 0, 0][%arg2, %arg2, %arg2][1, 1, 1]
-    : memref<8x16x4xf32, offset: 0, strides: [64, 4, 1], 2> to
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>, 2> to
       memref<8x?x4xf32, affine_map<(d0, d1, d2)[s0] -> (d0 * s0 + d1 * 4 + d2)>>
   return
 }
@@ -643,7 +643,7 @@ func.func @invalid_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
   // expected-error at +1 {{is not strided}}
   %1 = memref.subview %0[0, 0, 0][%arg2, %arg2, %arg2][1, 1, 1]
     : memref<8x16x4xf32, affine_map<(d0, d1, d2) -> (d0 + d1, d1 + d2, d2)>> to
-      memref<8x?x4xf32, offset: 0, strides: [?, 4, 1]>
+      memref<8x?x4xf32, strided<[?, 4, 1], offset: 0>>
   return
 }
 
@@ -654,7 +654,7 @@ func.func @invalid_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
   // expected-error at +1 {{expected 3 offset values}}
   %1 = memref.subview %0[%arg0, %arg1, 0, 0][%arg2, 0, 0, 0][1, 1, 1, 1]
     : memref<8x16x4xf32> to
-      memref<8x?x4xf32, offset: 0, strides:[?, ?, 4]>
+      memref<8x?x4xf32, strided<[?, ?, 4], offset: 0>>
   return
 }
 
@@ -746,17 +746,17 @@ func.func @subview_bad_offset_3(%arg0: memref<16x16xf32>) {
 
 // -----
 
-func.func @invalid_memref_cast(%arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]>) {
-  // expected-error at +1{{operand type 'memref<12x4x16xf32, affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 16 + d2)>>' and result type 'memref<12x4x16xf32, affine_map<(d0, d1, d2) -> (d0 * 128 + d1 * 32 + d2 * 2)>>' are cast incompatible}}
-  %0 = memref.cast %arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]> to memref<12x4x16xf32, offset:0, strides:[128, 32, 2]>
+func.func @invalid_memref_cast(%arg0 : memref<12x4x16xf32, strided<[64, 16, 1], offset: 0>>) {
+  // expected-error at +1{{operand type 'memref<12x4x16xf32, strided<[64, 16, 1]>>' and result type 'memref<12x4x16xf32, strided<[128, 32, 2]>>' are cast incompatible}}
+  %0 = memref.cast %arg0 : memref<12x4x16xf32, strided<[64, 16, 1], offset: 0>> to memref<12x4x16xf32, strided<[128, 32, 2], offset: 0>>
   return
 }
 
 // -----
 
-func.func @invalid_memref_cast(%arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]>) {
-  // expected-error at +1{{operand type 'memref<12x4x16xf32, affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 16 + d2)>>' and result type 'memref<12x4x16xf32, affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 16 + d2 + 16)>>' are cast incompatible}}
-  %0 = memref.cast %arg0 : memref<12x4x16xf32, offset:0, strides:[64, 16, 1]> to memref<12x4x16xf32, offset:16, strides:[64, 16, 1]>
+func.func @invalid_memref_cast(%arg0 : memref<12x4x16xf32, strided<[64, 16, 1], offset: 0>>) {
+  // expected-error at +1{{operand type 'memref<12x4x16xf32, strided<[64, 16, 1]>>' and result type 'memref<12x4x16xf32, strided<[64, 16, 1], offset: 16>>' are cast incompatible}}
+  %0 = memref.cast %arg0 : memref<12x4x16xf32, strided<[64, 16, 1], offset: 0>> to memref<12x4x16xf32, strided<[64, 16, 1], offset: 16>>
   return
 }
 

diff  --git a/mlir/test/Dialect/MemRef/ops.mlir b/mlir/test/Dialect/MemRef/ops.mlir
index eda7c4cb3bf5e..69c7e178778f0 100644
--- a/mlir/test/Dialect/MemRef/ops.mlir
+++ b/mlir/test/Dialect/MemRef/ops.mlir
@@ -1,39 +1,33 @@
 // RUN: mlir-opt %s | mlir-opt | FileCheck %s
 // RUN: mlir-opt %s --mlir-print-op-generic | mlir-opt | FileCheck %s
 
-// CHECK-DAG: #[[$strided2D:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
-// CHECK-DAG: #[[$strided3D:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2 + d2)>
-// CHECK-DAG: #[[$strided2DOFF0:.*]] = affine_map<(d0, d1)[s0] -> (d0 * s0 + d1)>
-// CHECK-DAG: #[[$strided3DOFF0:.*]] = affine_map<(d0, d1, d2)[s0, s1] -> (d0 * s0 + d1 * s1 + d2)>
-// CHECK-DAG: #[[$strided2D42:.*]] = affine_map<(d0, d1) -> (d0 * 42 + d1)>
-
 // CHECK-LABEL: func @memref_reinterpret_cast
 func.func @memref_reinterpret_cast(%in: memref<?xf32>)
-    -> memref<10x?xf32, offset: ?, strides: [?, 1]> {
+    -> memref<10x?xf32, strided<[?, 1], offset: ?>> {
   %c0 = arith.constant 0 : index
   %c10 = arith.constant 10 : index
   %out = memref.reinterpret_cast %in to
            offset: [%c0], sizes: [10, %c10], strides: [%c10, 1]
-           : memref<?xf32> to memref<10x?xf32, offset: ?, strides: [?, 1]>
-  return %out : memref<10x?xf32, offset: ?, strides: [?, 1]>
+           : memref<?xf32> to memref<10x?xf32, strided<[?, 1], offset: ?>>
+  return %out : memref<10x?xf32, strided<[?, 1], offset: ?>>
 }
 
 // CHECK-LABEL: func @memref_reinterpret_cast_static_to_dynamic_sizes
 func.func @memref_reinterpret_cast_static_to_dynamic_sizes(%in: memref<?xf32>)
-    -> memref<10x?xf32, offset: ?, strides: [?, 1]> {
+    -> memref<10x?xf32, strided<[?, 1], offset: ?>> {
   %out = memref.reinterpret_cast %in to
            offset: [1], sizes: [10, 10], strides: [1, 1]
-           : memref<?xf32> to memref<10x?xf32, offset: ?, strides: [?, 1]>
-  return %out : memref<10x?xf32, offset: ?, strides: [?, 1]>
+           : memref<?xf32> to memref<10x?xf32, strided<[?, 1], offset: ?>>
+  return %out : memref<10x?xf32, strided<[?, 1], offset: ?>>
 }
 
 // CHECK-LABEL: func @memref_reinterpret_cast_dynamic_offset
 func.func @memref_reinterpret_cast_dynamic_offset(%in: memref<?xf32>, %offset: index)
-    -> memref<10x?xf32, offset: ?, strides: [?, 1]> {
+    -> memref<10x?xf32, strided<[?, 1], offset: ?>> {
   %out = memref.reinterpret_cast %in to
            offset: [%offset], sizes: [10, 10], strides: [1, 1]
-           : memref<?xf32> to memref<10x?xf32, offset: ?, strides: [?, 1]>
-  return %out : memref<10x?xf32, offset: ?, strides: [?, 1]>
+           : memref<?xf32> to memref<10x?xf32, strided<[?, 1], offset: ?>>
+  return %out : memref<10x?xf32, strided<[?, 1], offset: ?>>
 }
 
 // CHECK-LABEL: func @memref_reshape(
@@ -109,10 +103,10 @@ func.func @expand_collapse_shape_static(
     %arg0: memref<3x4x5xf32>,
     %arg1: tensor<3x4x5xf32>,
     %arg2: tensor<3x?x5xf32>,
-    %arg3: memref<30x20xf32, offset : 100, strides : [4000, 2]>,
+    %arg3: memref<30x20xf32, strided<[4000, 2], offset: 100>>,
     %arg4: memref<1x5xf32, affine_map<(d0, d1)[s0] -> (d0 * 5 + s0 + d1)>>,
     %arg5: memref<f32>,
-    %arg6: memref<3x4x5xf32, offset: 0, strides: [240, 60, 10]>,
+    %arg6: memref<3x4x5xf32, strided<[240, 60, 10], offset: 0>>,
     %arg7: memref<1x2049xi64, affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>>) {
   // Reshapes that collapse and expand back a contiguous buffer.
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]]
@@ -153,13 +147,13 @@ func.func @expand_collapse_shape_static(
 // Reshapes with a custom layout map.
 //       CHECK:   memref.expand_shape {{.*}} {{\[}}[0], [1, 2]]
   %l0 = memref.expand_shape %arg3 [[0], [1, 2]] :
-      memref<30x20xf32, offset : 100, strides : [4000, 2]>
-      into memref<30x4x5xf32, offset : 100, strides : [4000, 10, 2]>
+      memref<30x20xf32, strided<[4000, 2], offset: 100>>
+      into memref<30x4x5xf32, strided<[4000, 10, 2], offset: 100>>
 
 //       CHECK:   memref.expand_shape {{.*}} {{\[}}[0, 1], [2]]
   %l1 = memref.expand_shape %arg3 [[0, 1], [2]] :
-      memref<30x20xf32, offset : 100, strides : [4000, 2]>
-      into memref<2x15x20xf32, offset : 100, strides : [60000, 4000, 2]>
+      memref<30x20xf32, strided<[4000, 2], offset: 100>>
+      into memref<2x15x20xf32, strided<[60000, 4000, 2], offset: 100>>
 
 //       CHECK:   memref.expand_shape {{.*}} {{\[}}[0], [1, 2]]
   %r4 = memref.expand_shape %arg4 [[0], [1, 2]] :
@@ -169,8 +163,8 @@ func.func @expand_collapse_shape_static(
   // Note: Only the collapsed two shapes are contiguous in the follow test case.
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]]
   %r6 = memref.collapse_shape %arg6 [[0, 1], [2]] :
-      memref<3x4x5xf32, offset: 0, strides: [240, 60, 10]> into
-      memref<12x5xf32, offset: 0, strides: [60, 10]>
+      memref<3x4x5xf32, strided<[240, 60, 10], offset: 0>> into
+      memref<12x5xf32, strided<[60, 10], offset: 0>>
 
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1]]
   %r7 = memref.collapse_shape %arg7 [[0, 1]] :
@@ -209,9 +203,9 @@ func.func @expand_collapse_shape_static(
 
 // CHECK-LABEL: func @expand_collapse_shape_dynamic
 func.func @expand_collapse_shape_dynamic(%arg0: memref<?x?x?xf32>,
-         %arg1: memref<?x?x?xf32, offset : 0, strides : [?, ?, 1]>,
-         %arg2: memref<?x?x?xf32, offset : ?, strides : [?, ?, 1]>,
-         %arg3: memref<?x42xf32, offset : 0, strides : [42, 1]>) {
+         %arg1: memref<?x?x?xf32, strided<[?, ?, 1], offset: 0>>,
+         %arg2: memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>>,
+         %arg3: memref<?x42xf32, strided<[42, 1], offset: 0>>) {
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]]
 //  CHECK-SAME:     memref<?x?x?xf32> into memref<?x?xf32>
   %0 = memref.collapse_shape %arg0 [[0, 1], [2]] :
@@ -223,39 +217,39 @@ func.func @expand_collapse_shape_dynamic(%arg0: memref<?x?x?xf32>,
     memref<?x?xf32> into memref<?x4x?xf32>
 
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]]
-//  CHECK-SAME:     memref<?x?x?xf32, #[[$strided3DOFF0]]> into memref<?x?xf32, #[[$strided2DOFF0]]>
+//  CHECK-SAME:     memref<?x?x?xf32, strided<[?, ?, 1]>> into memref<?x?xf32, strided<[?, 1]>>
   %1 = memref.collapse_shape %arg1 [[0, 1], [2]] :
-    memref<?x?x?xf32, offset : 0, strides : [?, ?, 1]> into
-    memref<?x?xf32, offset : 0, strides : [?, 1]>
+    memref<?x?x?xf32, strided<[?, ?, 1], offset: 0>> into
+    memref<?x?xf32, strided<[?, 1], offset: 0>>
 
 //       CHECK:   memref.expand_shape {{.*}} {{\[}}[0, 1], [2]]
-//  CHECK-SAME:     memref<?x?xf32, #[[$strided2DOFF0]]> into memref<?x4x?xf32, #[[$strided3DOFF0]]>
+//  CHECK-SAME:     memref<?x?xf32, strided<[?, 1]>> into memref<?x4x?xf32, strided<[?, ?, 1]>>
   %r1 = memref.expand_shape %1 [[0, 1], [2]] :
-    memref<?x?xf32, offset : 0, strides : [?, 1]> into
-    memref<?x4x?xf32, offset : 0, strides : [?, ?, 1]>
+    memref<?x?xf32, strided<[?, 1], offset: 0>> into
+    memref<?x4x?xf32, strided<[?, ?, 1], offset: 0>>
 
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1], [2]]
-//  CHECK-SAME:     memref<?x?x?xf32, #[[$strided3D]]> into memref<?x?xf32, #[[$strided2D]]>
+//  CHECK-SAME:     memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>> into memref<?x?xf32, strided<[?, 1], offset: ?>>
   %2 = memref.collapse_shape %arg2 [[0, 1], [2]] :
-    memref<?x?x?xf32, offset : ?, strides : [?, ?, 1]> into
-    memref<?x?xf32, offset : ?, strides : [?, 1]>
+    memref<?x?x?xf32, strided<[?, ?, 1], offset: ?>> into
+    memref<?x?xf32, strided<[?, 1], offset: ?>>
 
 //       CHECK:   memref.expand_shape {{.*}} {{\[}}[0, 1], [2]]
-//  CHECK-SAME:     memref<?x?xf32, #[[$strided2D]]> into memref<?x4x?xf32, #[[$strided3D]]>
+//  CHECK-SAME:     memref<?x?xf32, strided<[?, 1], offset: ?>> into memref<?x4x?xf32, strided<[?, ?, 1], offset: ?>>
   %r2 = memref.expand_shape %2 [[0, 1], [2]] :
-    memref<?x?xf32, offset : ?, strides : [?, 1]> into
-    memref<?x4x?xf32, offset : ?, strides : [?, ?, 1]>
+    memref<?x?xf32, strided<[?, 1], offset: ?>> into
+    memref<?x4x?xf32, strided<[?, ?, 1], offset: ?>>
 
 //       CHECK:   memref.collapse_shape {{.*}} {{\[}}[0, 1]]
-//  CHECK-SAME:     memref<?x42xf32, #[[$strided2D42]]> into memref<?xf32>
+//  CHECK-SAME:     memref<?x42xf32, strided<[42, 1]>> into memref<?xf32>
   %3 = memref.collapse_shape %arg3 [[0, 1]] :
-    memref<?x42xf32, offset : 0, strides : [42, 1]> into
-    memref<?xf32, offset : 0, strides : [1]>
+    memref<?x42xf32, strided<[42, 1], offset: 0>> into
+    memref<?xf32>
 
 //       CHECK:   memref.expand_shape {{.*}} {{\[}}[0, 1]]
 //  CHECK-SAME:     memref<?xf32> into memref<?x42xf32>
   %r3 = memref.expand_shape %3 [[0, 1]] :
-    memref<?xf32, offset : 0, strides : [1]> into memref<?x42xf32>
+    memref<?xf32> into memref<?x42xf32>
   return
 }
 
@@ -283,22 +277,22 @@ func.func @collapse_shape_to_dynamic
 
 // CHECK-LABEL: func @expand_collapse_shape_transposed_layout
 func.func @expand_collapse_shape_transposed_layout(
-    %m0: memref<?x?xf32, offset : 0, strides : [1, 10]>,
-    %m1: memref<4x5x6xf32, offset : 0, strides : [1, ?, 1000]>) {
+    %m0: memref<?x?xf32, strided<[1, 10], offset: 0>>,
+    %m1: memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>>) {
 
   %r0 = memref.expand_shape %m0 [[0], [1, 2]] :
-    memref<?x?xf32, offset : 0, strides : [1, 10]> into
-    memref<?x?x5xf32, offset : 0, strides : [1, 50, 10]>
+    memref<?x?xf32, strided<[1, 10], offset: 0>> into
+    memref<?x?x5xf32, strided<[1, 50, 10], offset: 0>>
   %rr0 = memref.collapse_shape %r0 [[0], [1, 2]] :
-    memref<?x?x5xf32, offset : 0, strides : [1, 50, 10]> into
-    memref<?x?xf32, offset : 0, strides : [1, 10]>
+    memref<?x?x5xf32, strided<[1, 50, 10], offset: 0>> into
+    memref<?x?xf32, strided<[1, 10], offset: 0>>
 
   %r1 = memref.expand_shape %m1 [[0, 1], [2], [3, 4]] :
-    memref<4x5x6xf32, offset : 0, strides : [1, ?, 1000]> into 
-    memref<2x2x5x2x3xf32, offset : 0, strides : [2, 1, ?, 3000, 1000]>
+    memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>> into 
+    memref<2x2x5x2x3xf32, strided<[2, 1, ?, 3000, 1000], offset: 0>>
   %rr1 = memref.collapse_shape %r1 [[0, 1], [2], [3, 4]] :
-    memref<2x2x5x2x3xf32, offset : 0, strides : [2, 1, ?, 3000, 1000]> into
-    memref<4x5x6xf32, offset : 0, strides : [1, ?, 1000]>
+    memref<2x2x5x2x3xf32, strided<[2, 1, ?, 3000, 1000], offset: 0>> into
+    memref<4x5x6xf32, strided<[1, ?, 1000], offset: 0>>
   return
 }
 
@@ -340,7 +334,7 @@ func.func @generic_atomic_rmw(%I: memref<1x2xf32>, %i : index, %j : index) {
 // -----
 
 func.func @extract_strided_metadata(%memref : memref<10x?xf32>) 
-    -> memref<?x?xf32, offset: ?, strides: [?, ?]> {
+  -> memref<?x?xf32, strided<[?, ?], offset: ?>> {
 
   %base, %offset, %sizes:2, %strides:2 = memref.extract_strided_metadata %memref
     : memref<10x?xf32> -> memref<f32>, index, index, index, index, index
@@ -349,7 +343,7 @@ func.func @extract_strided_metadata(%memref : memref<10x?xf32>)
       offset: [%offset],
       sizes: [%sizes#0, %sizes#1],
       strides: [%strides#0, %strides#1]
-    : memref<f32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+    : memref<f32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
 
-  return %m2: memref<?x?xf32, offset: ?, strides: [?, ?]>
+  return %m2: memref<?x?xf32, strided<[?, ?], offset: ?>>
 }

diff  --git a/mlir/test/Dialect/MemRef/subview.mlir b/mlir/test/Dialect/MemRef/subview.mlir
index cb34de760f6e6..3e3367e4bff9c 100644
--- a/mlir/test/Dialect/MemRef/subview.mlir
+++ b/mlir/test/Dialect/MemRef/subview.mlir
@@ -1,22 +1,8 @@
 // RUN: mlir-opt %s | mlir-opt | FileCheck %s
 // RUN: mlir-opt %s --mlir-print-op-generic | mlir-opt | FileCheck %s
 
-// CHECK-DAG: #[[$BASE_MAP0:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)>
-// CHECK-DAG: #[[$BASE_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
-
 // CHECK-DAG: #[[$BASE_MAP1:map[0-9]+]] = affine_map<(d0)[s0] -> (d0 + s0)>
 // CHECK-DAG: #[[$SUBVIEW_MAP1:map[0-9]+]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
-
-// CHECK-DAG: #[[$BASE_MAP2:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 22 + d1)>
-// CHECK-DAG: #[[$SUBVIEW_MAP2:map[0-9]+]] = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>
-// CHECK-DAG: #[[$SUBVIEW_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2 + 8)>
-// CHECK-DAG: #[[$SUBVIEW_MAP4:map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
-// CHECK-DAG: #[[$SUBVIEW_MAP5:map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0 * 8 + s0 + d1 * 2)>
-// CHECK-DAG: #[[$SUBVIEW_MAP6:map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4) -> (d0 * 36 + d1 * 36 + d2 * 4 + d3 * 4 + d4)>
-// CHECK-DAG: #[[$SUBVIEW_MAP7:map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4, d5)[s0, s1, s2, s3, s4, s5, s6] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3 * s4 + d4 * s5 + d5 * s6)>
-// CHECK-DAG: #[[$SUBVIEW_MAP8:map[0-9]+]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3, s4] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3 * s4)>
-// CHECK-DAG: #[[$SUBVIEW_MAP9:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 3 + d1 + 6)>
-// CHECK-DAG: #[[$SUBVIEW_MAP10:map[0-9]+]] = affine_map<(d0) -> (d0 + 3)>
 // CHECK-DAG: #[[$SUBVIEW_MAP11:map[0-9]+]] = affine_map<() -> (4)>
 // CHECK-DAG: #[[$SUBVIEW_MAP12:map[0-9]+]] = affine_map<()[s0] -> (s0)>
 
@@ -25,13 +11,13 @@ func.func @memref_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
 
-  %0 = memref.alloc() : memref<8x16x4xf32, affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)>>
+  %0 = memref.alloc() : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>>
   // CHECK: subview %0[%c0, %c0, %c0] [%arg0, %arg1, %arg2] [%c1, %c1, %c1] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]>
-  // CHECK-SAME: to memref<?x?x?xf32, #[[$BASE_MAP3]]>
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>>
+  // CHECK-SAME: to memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
   %1 = memref.subview %0[%c0, %c0, %c0][%arg0, %arg1, %arg2][%c1, %c1, %c1]
-    : memref<8x16x4xf32, offset:0, strides: [64, 4, 1]> to
-      memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   %2 = memref.alloc()[%arg2] : memref<64xf32, affine_map<(d0)[s0] -> (d0 + s0)>>
   // CHECK: memref.subview %2[%c1] [%arg0] [%c1] :
@@ -41,58 +27,58 @@ func.func @memref_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
     : memref<64xf32, affine_map<(d0)[s0] -> (d0 + s0)>> to
       memref<?xf32, affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>>
 
-  %4 = memref.alloc() : memref<64x22xf32, affine_map<(d0, d1) -> (d0 * 22 + d1)>>
+  %4 = memref.alloc() : memref<64x22xf32, strided<[22, 1]>>
   // CHECK: memref.subview %4[%c0, %c1] [%arg0, %arg1] [%c1, %c0] :
-  // CHECK-SAME: memref<64x22xf32, #[[$BASE_MAP2]]>
-  // CHECK-SAME: to memref<?x?xf32, #[[$SUBVIEW_MAP2]]>
+  // CHECK-SAME: memref<64x22xf32, strided<[22, 1]>>
+  // CHECK-SAME: to memref<?x?xf32, strided<[?, ?], offset: ?>>
   %5 = memref.subview %4[%c0, %c1][%arg0, %arg1][%c1, %c0]
-    : memref<64x22xf32, offset:0, strides: [22, 1]> to
-      memref<?x?xf32, offset:?, strides: [?, ?]>
+    : memref<64x22xf32, strided<[22, 1], offset: 0>> to
+      memref<?x?xf32, strided<[?, ?], offset: ?>>
 
   // CHECK: memref.subview %0[0, 2, 0] [4, 4, 4] [1, 1, 1] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]>
-  // CHECK-SAME: to memref<4x4x4xf32, #[[$SUBVIEW_MAP3]]>
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>>
+  // CHECK-SAME: to memref<4x4x4xf32, strided<[64, 4, 1], offset: 8>>
   %6 = memref.subview %0[0, 2, 0][4, 4, 4][1, 1, 1]
-    : memref<8x16x4xf32, offset:0, strides: [64, 4, 1]> to
-      memref<4x4x4xf32, offset:8, strides: [64, 4, 1]>
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<4x4x4xf32, strided<[64, 4, 1], offset: 8>>
 
   %7 = memref.alloc(%arg1, %arg2) : memref<?x?xf32>
   // CHECK: memref.subview {{%.*}}[0, 0] [4, 4] [1, 1] :
   // CHECK-SAME: memref<?x?xf32>
-  // CHECK-SAME: to memref<4x4xf32, #[[$SUBVIEW_MAP4]]>
+  // CHECK-SAME: to memref<4x4xf32, strided<[?, 1], offset: ?>>
   %8 = memref.subview %7[0, 0][4, 4][1, 1]
-    : memref<?x?xf32> to memref<4x4xf32, offset: ?, strides:[?, 1]>
+    : memref<?x?xf32> to memref<4x4xf32, strided<[?, 1], offset: ?>>
 
   %9 = memref.alloc() : memref<16x4xf32>
   // CHECK: memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [4, 4] [{{%.*}}, {{%.*}}] :
   // CHECK-SAME: memref<16x4xf32>
-  // CHECK-SAME: to memref<4x4xf32, #[[$SUBVIEW_MAP2]]
+  // CHECK-SAME: to memref<4x4xf32, strided<[?, ?], offset: ?>>
   %10 = memref.subview %9[%arg1, %arg1][4, 4][%arg2, %arg2]
-    : memref<16x4xf32> to memref<4x4xf32, offset: ?, strides:[?, ?]>
+    : memref<16x4xf32> to memref<4x4xf32, strided<[?, ?], offset: ?>>
 
   // CHECK: memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [4, 4] [2, 2] :
   // CHECK-SAME: memref<16x4xf32>
-  // CHECK-SAME: to memref<4x4xf32, #[[$SUBVIEW_MAP5]]
+  // CHECK-SAME: to memref<4x4xf32, strided<[8, 2], offset: ?>>
   %11 = memref.subview %9[%arg1, %arg2][4, 4][2, 2]
-    : memref<16x4xf32> to memref<4x4xf32, offset: ?, strides:[8, 2]>
+    : memref<16x4xf32> to memref<4x4xf32, strided<[8, 2], offset: ?>>
 
-  %12 = memref.alloc() : memref<1x9x1x4x1xf32, affine_map<(d0, d1, d2, d3, d4) -> (36 * d0 + 36 * d1 + 4 * d2 + 4 * d3 + d4)>>
+  %12 = memref.alloc() : memref<1x9x1x4x1xf32, strided<[36, 36, 4, 4, 1]>>
   // CHECK: memref.subview %12[%arg1, %arg1, %arg1, %arg1, %arg1]
   // CHECK-SAME: [1, 9, 1, 4, 1] [%arg2, %arg2, %arg2, %arg2, %arg2] :
-  // CHECK-SAME: memref<1x9x1x4x1xf32, #[[$SUBVIEW_MAP6]]> to memref<9x4xf32, #[[$SUBVIEW_MAP2]]>
-  %13 = memref.subview %12[%arg1, %arg1, %arg1, %arg1, %arg1][1, 9, 1, 4, 1][%arg2, %arg2, %arg2, %arg2, %arg2] : memref<1x9x1x4x1xf32, offset: 0, strides: [36, 36, 4, 4, 1]> to memref<9x4xf32, offset: ?, strides: [?, ?]>
+  // CHECK-SAME: memref<1x9x1x4x1xf32, strided<[36, 36, 4, 4, 1]>> to memref<9x4xf32, strided<[?, ?], offset: ?>>
+  %13 = memref.subview %12[%arg1, %arg1, %arg1, %arg1, %arg1][1, 9, 1, 4, 1][%arg2, %arg2, %arg2, %arg2, %arg2] : memref<1x9x1x4x1xf32, strided<[36, 36, 4, 4, 1], offset: 0>> to memref<9x4xf32, strided<[?, ?], offset: ?>>
   // CHECK: memref.subview %12[%arg1, %arg1, %arg1, %arg1, %arg1]
   // CHECK-SAME: [1, 9, 1, 4, 1] [%arg2, %arg2, %arg2, %arg2, %arg2] :
-  // CHECK-SAME: memref<1x9x1x4x1xf32, #[[$SUBVIEW_MAP6]]> to memref<1x9x4xf32, #[[$BASE_MAP3]]>
-  %14 = memref.subview %12[%arg1, %arg1, %arg1, %arg1, %arg1][1, 9, 1, 4, 1][%arg2, %arg2, %arg2, %arg2, %arg2] : memref<1x9x1x4x1xf32, offset: 0, strides: [36, 36, 4, 4, 1]> to memref<1x9x4xf32, offset: ?, strides: [?, ?, ?]>
+  // CHECK-SAME: memref<1x9x1x4x1xf32, strided<[36, 36, 4, 4, 1]>> to memref<1x9x4xf32, strided<[?, ?, ?], offset: ?>>
+  %14 = memref.subview %12[%arg1, %arg1, %arg1, %arg1, %arg1][1, 9, 1, 4, 1][%arg2, %arg2, %arg2, %arg2, %arg2] : memref<1x9x1x4x1xf32, strided<[36, 36, 4, 4, 1], offset: 0>> to memref<1x9x4xf32, strided<[?, ?, ?], offset: ?>>
 
-  %15 = memref.alloc(%arg1, %arg2)[%c0, %c1, %arg1, %arg0, %arg0, %arg2, %arg2] : memref<1x?x5x1x?x1xf32, affine_map<(d0, d1, d2, d3, d4, d5)[s0, s1, s2, s3, s4, s5, s6] -> (s0 + s1 * d0 + s2 * d1 + s3 * d2 + s4 * d3 + s5 * d4 + s6 * d5)>>
+  %15 = memref.alloc(%arg1, %arg2)[%c0, %c1, %arg1, %arg0, %arg0, %arg2, %arg2] : memref<1x?x5x1x?x1xf32, strided<[?, ?, ?, ?, ?, ?], offset: ?>>
   // CHECK: memref.subview %15[0, 0, 0, 0, 0, 0] [1, %arg1, 5, 1, %arg2, 1] [1, 1, 1, 1, 1, 1]  :
-  // CHECK-SAME: memref<1x?x5x1x?x1xf32,  #[[$SUBVIEW_MAP7]]> to memref<?x5x?xf32, #[[$BASE_MAP3]]>
-  %16 = memref.subview %15[0, 0, 0, 0, 0, 0][1, %arg1, 5, 1, %arg2, 1][1, 1, 1, 1, 1, 1] : memref<1x?x5x1x?x1xf32, offset: ?, strides: [?, ?, ?, ?, ?, ?]> to memref<?x5x?xf32, offset: ?, strides: [?, ?, ?]>
+  // CHECK-SAME: memref<1x?x5x1x?x1xf32, strided<[?, ?, ?, ?, ?, ?], offset: ?>> to memref<?x5x?xf32, strided<[?, ?, ?], offset: ?>>
+  %16 = memref.subview %15[0, 0, 0, 0, 0, 0][1, %arg1, 5, 1, %arg2, 1][1, 1, 1, 1, 1, 1] : memref<1x?x5x1x?x1xf32, strided<[?, ?, ?, ?, ?, ?], offset: ?>> to memref<?x5x?xf32, strided<[?, ?, ?], offset: ?>>
   // CHECK: memref.subview %15[%arg1, %arg1, %arg1, %arg1, %arg1, %arg1] [1, %arg1, 5, 1, %arg2, 1] [1, 1, 1, 1, 1, 1]  :
-  // CHECK-SAME: memref<1x?x5x1x?x1xf32, #[[$SUBVIEW_MAP7]]> to memref<?x5x?x1xf32, #[[$SUBVIEW_MAP8]]>
-  %17 = memref.subview %15[%arg1, %arg1, %arg1, %arg1, %arg1, %arg1][1, %arg1, 5, 1, %arg2, 1][1, 1, 1, 1, 1, 1] :  memref<1x?x5x1x?x1xf32, offset: ?, strides: [?, ?, ?, ?, ?, ?]> to memref<?x5x?x1xf32, offset: ?, strides: [?, ?, ?, ?]>
+  // CHECK-SAME: memref<1x?x5x1x?x1xf32, strided<[?, ?, ?, ?, ?, ?], offset: ?>> to memref<?x5x?x1xf32, strided<[?, ?, ?, ?], offset: ?>>
+  %17 = memref.subview %15[%arg1, %arg1, %arg1, %arg1, %arg1, %arg1][1, %arg1, 5, 1, %arg2, 1][1, 1, 1, 1, 1, 1] :  memref<1x?x5x1x?x1xf32, strided<[?, ?, ?, ?, ?, ?], offset: ?>> to memref<?x5x?x1xf32, strided<[?, ?, ?, ?], offset: ?>>
 
   %18 = memref.alloc() : memref<1x8xf32>
   // CHECK: memref.subview %18[0, 0] [1, 8] [1, 1]  : memref<1x8xf32> to memref<8xf32>
@@ -102,19 +88,19 @@ func.func @memref_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK: memref.subview %20[0, 0, 0] [1, 16, 4] [1, 1, 1]  : memref<8x16x4xf32> to memref<16x4xf32>
   %21 = memref.subview %20[0, 0, 0][1, 16, 4][1, 1, 1] : memref<8x16x4xf32> to memref<16x4xf32>
 
-  %22 = memref.subview %20[3, 4, 2][1, 6, 3][1, 1, 1] : memref<8x16x4xf32> to memref<6x3xf32, offset: 210, strides: [4, 1]>
+  %22 = memref.subview %20[3, 4, 2][1, 6, 3][1, 1, 1] : memref<8x16x4xf32> to memref<6x3xf32, strided<[4, 1], offset: 210>>
 
   %23 = memref.alloc() : memref<f32>
   %78 = memref.subview %23[] [] []  : memref<f32> to memref<f32>
 
   /// Subview with only leading operands.
   %24 = memref.alloc() : memref<5x3xf32>
-  // CHECK: memref.subview %{{.*}}[2, 0] [3, 3] [1, 1] : memref<5x3xf32> to memref<3x3xf32, #[[$SUBVIEW_MAP9]]>
-  %25 = memref.subview %24[2, 0][3, 3][1, 1]: memref<5x3xf32> to memref<3x3xf32, offset: 6, strides: [3, 1]>
+  // CHECK: memref.subview %{{.*}}[2, 0] [3, 3] [1, 1] : memref<5x3xf32> to memref<3x3xf32, strided<[3, 1], offset: 6>>
+  %25 = memref.subview %24[2, 0][3, 3][1, 1]: memref<5x3xf32> to memref<3x3xf32, strided<[3, 1], offset: 6>>
 
   /// Rank-reducing subview with only leading operands.
-  // CHECK: memref.subview %{{.*}}[1, 0] [1, 3] [1, 1] : memref<5x3xf32> to memref<3xf32, #[[$SUBVIEW_MAP10]]>
-  %26 = memref.subview %24[1, 0][1, 3][1, 1]: memref<5x3xf32> to memref<3xf32, offset: 3, strides: [1]>
+  // CHECK: memref.subview %{{.*}}[1, 0] [1, 3] [1, 1] : memref<5x3xf32> to memref<3xf32, strided<[1], offset: 3>>
+  %26 = memref.subview %24[1, 0][1, 3][1, 1]: memref<5x3xf32> to memref<3xf32, strided<[1], offset: 3>>
 
   // Corner-case of 0-D rank-reducing subview with an offset.
   // CHECK: memref.subview %{{.*}}[1, 1] [1, 1] [1, 1] : memref<5x3xf32> to memref<f32, #[[$SUBVIEW_MAP11]]>

diff  --git a/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir b/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
index eb6ad8a809fdf..96befd7d57b99 100644
--- a/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
+++ b/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
@@ -298,8 +298,8 @@ func.func @do_not_fuse_loops_with_memref_defined_in_loop_bodies() {
   }
   scf.parallel (%i, %j) = (%c0, %c0) to (%c2, %c2) step (%c1, %c1) {
     %A = memref.subview %buffer[%c0, %c0][%c2, %c2][%c1, %c1]
-      : memref<2x2xf32> to memref<?x?xf32, offset: ?, strides:[?, ?]>
-    %A_elem = memref.load %A[%i, %j] : memref<?x?xf32, offset: ?, strides:[?, ?]>
+      : memref<2x2xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+    %A_elem = memref.load %A[%i, %j] : memref<?x?xf32, strided<[?, ?], offset: ?>>
     scf.yield
   }
   return

diff  --git a/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir b/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir
index 3f2025581ac4b..1c42923abc382 100644
--- a/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir
+++ b/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir
@@ -1,11 +1,11 @@
 // RUN: mlir-opt %s -test-vector-transfer-drop-unit-dims-patterns -split-input-file | FileCheck %s
 
 func.func @transfer_read_rank_reducing(
-      %arg : memref<1x1x3x2xi8, offset:?, strides:[6, 6, 2, 1]>) -> vector<3x2xi8> {
+      %arg : memref<1x1x3x2xi8, strided<[6, 6, 2, 1], offset: ?>>) -> vector<3x2xi8> {
     %c0 = arith.constant 0 : index
     %cst = arith.constant 0 : i8
     %v = vector.transfer_read %arg[%c0, %c0, %c0, %c0], %cst : 
-      memref<1x1x3x2xi8, offset:?, strides:[6, 6, 2, 1]>, vector<3x2xi8>
+      memref<1x1x3x2xi8, strided<[6, 6, 2, 1], offset: ?>>, vector<3x2xi8>
     return %v : vector<3x2xi8>
 }
 
@@ -17,10 +17,10 @@ func.func @transfer_read_rank_reducing(
 
 // -----
 
-func.func @transfer_write_rank_reducing(%arg : memref<1x1x3x2xi8, offset:?, strides:[6, 6, 2, 1]>, %vec : vector<3x2xi8>) {
+func.func @transfer_write_rank_reducing(%arg : memref<1x1x3x2xi8, strided<[6, 6, 2, 1], offset: ?>>, %vec : vector<3x2xi8>) {
     %c0 = arith.constant 0 : index
     vector.transfer_write %vec, %arg [%c0, %c0, %c0, %c0] : 
-      vector<3x2xi8>, memref<1x1x3x2xi8, offset:?, strides:[6, 6, 2, 1]>
+      vector<3x2xi8>, memref<1x1x3x2xi8, strided<[6, 6, 2, 1], offset: ?>>
     return
 }
 

diff  --git a/mlir/test/Dialect/Vector/vector-transfer-flatten.mlir b/mlir/test/Dialect/Vector/vector-transfer-flatten.mlir
index cd55222dddcd9..41e61887a6311 100644
--- a/mlir/test/Dialect/Vector/vector-transfer-flatten.mlir
+++ b/mlir/test/Dialect/Vector/vector-transfer-flatten.mlir
@@ -1,11 +1,11 @@
 // RUN: mlir-opt %s -test-vector-transfer-flatten-patterns -split-input-file | FileCheck %s
 
 func.func @transfer_read_flattenable_with_offset(
-      %arg : memref<5x4x3x2xi8, offset:?, strides:[24, 6, 2, 1]>) -> vector<5x4x3x2xi8> {
+      %arg : memref<5x4x3x2xi8, strided<[24, 6, 2, 1], offset: ?>>) -> vector<5x4x3x2xi8> {
     %c0 = arith.constant 0 : index
     %cst = arith.constant 0 : i8
     %v = vector.transfer_read %arg[%c0, %c0, %c0, %c0], %cst : 
-      memref<5x4x3x2xi8, offset:?, strides:[24, 6, 2, 1]>, vector<5x4x3x2xi8>
+      memref<5x4x3x2xi8, strided<[24, 6, 2, 1], offset: ?>>, vector<5x4x3x2xi8>
     return %v : vector<5x4x3x2xi8>
 }
 
@@ -19,10 +19,10 @@ func.func @transfer_read_flattenable_with_offset(
 // -----
 
 func.func @transfer_write_flattenable_with_offset(
-      %arg : memref<5x4x3x2xi8, offset:?, strides:[24, 6, 2, 1]>, %vec : vector<5x4x3x2xi8>) {
+      %arg : memref<5x4x3x2xi8, strided<[24, 6, 2, 1], offset: ?>>, %vec : vector<5x4x3x2xi8>) {
     %c0 = arith.constant 0 : index
     vector.transfer_write %vec, %arg [%c0, %c0, %c0, %c0] : 
-      vector<5x4x3x2xi8>, memref<5x4x3x2xi8, offset:?, strides:[24, 6, 2, 1]>
+      vector<5x4x3x2xi8>, memref<5x4x3x2xi8, strided<[24, 6, 2, 1], offset: ?>>
     return
 }
 

diff  --git a/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir b/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir
index 34f7f7095d4d8..7891d71ef91f0 100644
--- a/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir
+++ b/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir
@@ -106,7 +106,7 @@ func.func @split_vector_transfer_read_2d(%A: memref<?x8xf32>, %i: index, %j: ind
 //  LINALG-SAME: %[[i:[a-zA-Z0-9]*]]: index
 //  LINALG-SAME: %[[j:[a-zA-Z0-9]*]]: index
 func.func @split_vector_transfer_read_strided_2d(
-    %A: memref<7x8xf32, offset:?, strides:[?, 1]>,
+    %A: memref<7x8xf32, strided<[?, 1], offset: ?>>,
     %i: index, %j: index) -> vector<4x8xf32> {
   %c0 = arith.constant 0 : index
   %f0 = arith.constant 0.0 : f32
@@ -127,13 +127,13 @@ func.func @split_vector_transfer_read_strided_2d(
   //      CHECK: %[[ifres:.*]]:3 = scf.if %[[cond]] -> (memref<?x8xf32, #[[$map_2d_stride_1]]>, index, index) {
   //               inBounds but not cast-compatible: yield a memref_casted form of %A
   //      CHECK:   %[[casted:.*]] = memref.cast %arg0 :
-  // CHECK-SAME:     memref<7x8xf32, #[[$map_2d_stride_1]]> to memref<?x8xf32, #[[$map_2d_stride_1]]>
+  // CHECK-SAME:     memref<7x8xf32, strided<[?, 1], offset: ?>> to memref<?x8xf32, #[[$map_2d_stride_1]]>
   //      CHECK:   scf.yield %[[casted]], %[[i]], %[[j]] :
   // CHECK-SAME:     memref<?x8xf32, #[[$map_2d_stride_1]]>, index, index
   //      CHECK: } else {
   //               slow path, fill tmp alloc and yield a memref_casted version of it
   //      CHECK:   %[[slow:.*]] = vector.transfer_read %[[A]][%[[i]], %[[j]]], %cst :
-  // CHECK-SAME:     memref<7x8xf32, #[[$map_2d_stride_1]]>, vector<4x8xf32>
+  // CHECK-SAME:     memref<7x8xf32, strided<[?, 1], offset: ?>>, vector<4x8xf32>
   //      CHECK:   %[[cast_alloc:.*]] = vector.type_cast %[[alloc]] :
   // CHECK-SAME:     memref<4x8xf32> to memref<vector<4x8xf32>>
   //      CHECK:   store %[[slow]], %[[cast_alloc]][] :
@@ -163,7 +163,7 @@ func.func @split_vector_transfer_read_strided_2d(
   //      LINALG: %[[ifres:.*]]:3 = scf.if %[[cond]] -> (memref<?x8xf32, #[[$map_2d_stride_1]]>, index, index) {
   //               inBounds but not cast-compatible: yield a memref_casted form of %A
   //      LINALG:   %[[casted:.*]] = memref.cast %arg0 :
-  // LINALG-SAME:     memref<7x8xf32, #[[$map_2d_stride_1]]> to memref<?x8xf32, #[[$map_2d_stride_1]]>
+  // LINALG-SAME:     memref<7x8xf32, strided<[?, 1], offset: ?>> to memref<?x8xf32, #[[$map_2d_stride_1]]>
   //      LINALG:   scf.yield %[[casted]], %[[i]], %[[j]] :
   // LINALG-SAME:     memref<?x8xf32, #[[$map_2d_stride_1]]>, index, index
   //      LINALG: } else {
@@ -172,7 +172,7 @@ func.func @split_vector_transfer_read_strided_2d(
   //      LINALG:   %[[sv0:.*]] = affine.min #[[$bounds_map_4]](%[[c7]], %[[i]], %[[c4]])
   //      LINALG:   %[[sv1:.*]] = affine.min #[[$bounds_map_8]](%[[c8]], %[[j]], %[[c8]])
   //      LINALG:   %[[sv:.*]] = memref.subview %[[A]][%[[i]], %[[j]]] [%[[sv0]], %[[sv1]]] [1, 1]
-  // LINALG-SAME:     memref<7x8xf32, #[[$map_2d_stride_1]]> to memref<?x?xf32, #[[$map_2d_stride_1]]>
+  // LINALG-SAME:     memref<7x8xf32, strided<[?, 1], offset: ?>> to memref<?x?xf32, #[[$map_2d_stride_1]]>
   //      LINALG:   %[[alloc_view:.*]] = memref.subview %[[alloc]][0, 0] [%[[sv0]], %[[sv1]]] [1, 1]
   //      LINALG:   memref.copy %[[sv]], %[[alloc_view]] : memref<?x?xf32, #[[$map_2d_stride_1]]> to memref<?x?xf32, #{{.*}}>
   //      LINALG:   %[[yielded:.*]] = memref.cast %[[alloc]] :
@@ -183,7 +183,7 @@ func.func @split_vector_transfer_read_strided_2d(
   //      LINALG: %[[res:.*]] = vector.transfer_read {{.*}} {in_bounds = [true, true]} :
   // LINALG-SAME:   memref<?x8xf32, #[[$map_2d_stride_1]]>, vector<4x8xf32>
   %1 = vector.transfer_read %A[%i, %j], %f0 :
-    memref<7x8xf32, offset:?, strides:[?, 1]>, vector<4x8xf32>
+    memref<7x8xf32, strided<[?, 1], offset: ?>>, vector<4x8xf32>
 
   // CHECK: return %[[res]] : vector<4x8xf32>
   return %1 : vector<4x8xf32>
@@ -288,10 +288,10 @@ func.func @split_vector_transfer_write_2d(%V: vector<4x8xf32>, %A: memref<?x8xf3
 // -----
 
 func.func @split_vector_transfer_write_strided_2d(
-    %V: vector<4x8xf32>, %A: memref<7x8xf32, offset:?, strides:[?, 1]>,
+    %V: vector<4x8xf32>, %A: memref<7x8xf32, strided<[?, 1], offset: ?>>,
     %i: index, %j: index) {
   vector.transfer_write %V, %A[%i, %j] :
-    vector<4x8xf32>, memref<7x8xf32, offset:?, strides:[?, 1]>
+    vector<4x8xf32>, memref<7x8xf32, strided<[?, 1], offset: ?>>
   return
 }
 
@@ -300,7 +300,7 @@ func.func @split_vector_transfer_write_strided_2d(
 // CHECK-DAG: #[[MAP2:.*]] = affine_map<()[s0] -> (s0 + 8)>
 // CHECK:   func @split_vector_transfer_write_strided_2d(
 // CHECK-SAME:                                                 %[[VEC:.*]]: vector<4x8xf32>,
-// CHECK-SAME:                                                 %[[DEST:.*]]: memref<7x8xf32, #[[MAP0]]>,
+// CHECK-SAME:                                                 %[[DEST:.*]]: memref<7x8xf32, strided<[?, 1], offset: ?>>,
 // CHECK-SAME:                                                 %[[I:.*]]: index,
 // CHECK-SAME:                                                 %[[J:.*]]: index) {
 // CHECK-DAG:       %[[C7:.*]] = arith.constant 7 : index
@@ -316,7 +316,7 @@ func.func @split_vector_transfer_write_strided_2d(
 // CHECK:           %[[IN_BOUND_DEST:.*]]:3 = scf.if %[[IN_BOUNDS]]
 // CHECK-SAME:          -> (memref<?x8xf32, #[[MAP0]]>, index, index) {
 // CHECK:             %[[VAL_15:.*]] = memref.cast %[[DEST]]
-// CHECK-SAME:            : memref<7x8xf32, #[[MAP0]]> to memref<?x8xf32, #[[MAP0]]>
+// CHECK-SAME:            : memref<7x8xf32, strided<[?, 1], offset: ?>> to memref<?x8xf32, #[[MAP0]]>
 // CHECK:             scf.yield %[[VAL_15]], %[[I]], %[[J]]
 // CHECK-SAME:            : memref<?x8xf32, #[[MAP0]]>, index, index
 // CHECK:           } else {
@@ -336,7 +336,7 @@ func.func @split_vector_transfer_write_strided_2d(
 // CHECK:             %[[VAL_20:.*]] = memref.load %[[VAL_19]][]
 // CHECK-SAME:            : memref<vector<4x8xf32>>
 // CHECK:             vector.transfer_write %[[VAL_20]], %[[DEST]][%[[I]], %[[J]]]
-// CHECK-SAME:            : vector<4x8xf32>, memref<7x8xf32, #[[MAP0]]>
+// CHECK-SAME:            : vector<4x8xf32>, memref<7x8xf32, strided<[?, 1], offset: ?>>
 // CHECK:           }
 // CHECK:           return
 // CHECK:         }
@@ -349,7 +349,7 @@ func.func @split_vector_transfer_write_strided_2d(
 // LINALG-DAG: #[[MAP5:.*]] = affine_map<(d0, d1)[s0] -> (d0 * 8 + s0 + d1)>
 // LINALG:   func @split_vector_transfer_write_strided_2d(
 // LINALG-SAME:                                                 %[[VEC:.*]]: vector<4x8xf32>,
-// LINALG-SAME:                                                 %[[DEST:.*]]: memref<7x8xf32, #[[MAP0]]>,
+// LINALG-SAME:                                                 %[[DEST:.*]]: memref<7x8xf32, strided<[?, 1], offset: ?>>,
 // LINALG-SAME:                                                 %[[I:.*]]: index,
 // LINALG-SAME:                                                 %[[J:.*]]: index) {
 // LINALG-DAG:       %[[C0:.*]] = arith.constant 0 : index
@@ -366,7 +366,7 @@ func.func @split_vector_transfer_write_strided_2d(
 // LINALG:           %[[IN_BOUND_DEST:.*]]:3 = scf.if %[[IN_BOUNDS]]
 // LINALG-SAME:          -> (memref<?x8xf32, #[[MAP0]]>, index, index) {
 // LINALG:             %[[VAL_16:.*]] = memref.cast %[[DEST]]
-// LINALG-SAME:            : memref<7x8xf32, #[[MAP0]]> to memref<?x8xf32, #[[MAP0]]>
+// LINALG-SAME:            : memref<7x8xf32, strided<[?, 1], offset: ?>> to memref<?x8xf32, #[[MAP0]]>
 // LINALG:             scf.yield %[[VAL_16]], %[[I]], %[[J]]
 // LINALG-SAME:            : memref<?x8xf32, #[[MAP0]]>, index, index
 // LINALG:           } else {

diff  --git a/mlir/test/IR/core-ops.mlir b/mlir/test/IR/core-ops.mlir
index 6ede116bfc2e0..210612bec7a3f 100644
--- a/mlir/test/IR/core-ops.mlir
+++ b/mlir/test/IR/core-ops.mlir
@@ -8,9 +8,6 @@
 
 // CHECK: #map1 = affine_map<()[s0] -> (s0 + 1)>
 
-// CHECK-DAG: #[[$BASE_MAP0:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)>
-// CHECK-DAG: #[[$BASE_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
-
 // CHECK-LABEL: func @func_with_ops
 // CHECK-SAME: %[[ARG:.*]]: f32
 func.func @func_with_ops(f32) {
@@ -236,18 +233,18 @@ func.func @calls(%arg0: i32) {
 }
 
 // CHECK-LABEL: func @memref_cast(%arg0
-func.func @memref_cast(%arg0: memref<4xf32>, %arg1 : memref<?xf32>, %arg2 : memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]>) {
+func.func @memref_cast(%arg0: memref<4xf32>, %arg1 : memref<?xf32>, %arg2 : memref<64x16x4xf32, strided<[64, 4, 1], offset: 0>>) {
   // CHECK: %0 = memref.cast %arg0 : memref<4xf32> to memref<?xf32>
   %0 = memref.cast %arg0 : memref<4xf32> to memref<?xf32>
 
   // CHECK: %1 = memref.cast %arg1 : memref<?xf32> to memref<4xf32>
   %1 = memref.cast %arg1 : memref<?xf32> to memref<4xf32>
 
-  // CHECK: {{%.*}} = memref.cast %arg2 : memref<64x16x4xf32, #[[$BASE_MAP0]]> to memref<64x16x4xf32, #[[$BASE_MAP3]]>
-  %2 = memref.cast %arg2 : memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]> to memref<64x16x4xf32, offset: ?, strides: [?, ?, ?]>
+  // CHECK: {{%.*}} = memref.cast %arg2 : memref<64x16x4xf32, strided<[64, 4, 1]>> to memref<64x16x4xf32, strided<[?, ?, ?], offset: ?>>
+  %2 = memref.cast %arg2 : memref<64x16x4xf32, strided<[64, 4, 1], offset: 0>> to memref<64x16x4xf32, strided<[?, ?, ?], offset: ?>>
 
-  // CHECK: {{%.*}} = memref.cast {{%.*}} : memref<64x16x4xf32, #[[$BASE_MAP3]]> to memref<64x16x4xf32, #[[$BASE_MAP0]]>
-  %3 = memref.cast %2 : memref<64x16x4xf32, offset: ?, strides: [?, ?, ?]> to memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]>
+  // CHECK: {{%.*}} = memref.cast {{%.*}} : memref<64x16x4xf32, strided<[?, ?, ?], offset: ?>> to memref<64x16x4xf32, strided<[64, 4, 1]>>
+  %3 = memref.cast %2 : memref<64x16x4xf32, strided<[?, ?, ?], offset: ?>> to memref<64x16x4xf32, strided<[64, 4, 1], offset: 0>>
 
   // CHECK: memref.cast %{{.*}} : memref<4xf32> to memref<*xf32>
   %4 = memref.cast %1 : memref<4xf32> to memref<*xf32>

diff  --git a/mlir/test/IR/invalid-builtin-types.mlir b/mlir/test/IR/invalid-builtin-types.mlir
index cf1421c4b6613..4f168954785db 100644
--- a/mlir/test/IR/invalid-builtin-types.mlir
+++ b/mlir/test/IR/invalid-builtin-types.mlir
@@ -64,36 +64,58 @@ func.func @memrefs(memref<42xi8, #map0>) // expected-error {{memref layout misma
 
 // -----
 
-func.func @memref_space_after_strides(memref<42x42xi8, 0, offset: ?, strides: [?, ?]>) // expected-error {{expected memory space to be last in memref type}}
+// expected-error @below {{expected '<' after 'strided'}}
+func.func private @memref_unfinished_strided() -> memref<?x?xf32, strided>
 
 // -----
 
-func.func @memref_stride_missing_colon(memref<42x42xi8, offset ?, strides: [?, ?]>) // expected-error {{expected colon after `offset` keyword}}
+// expected-error @below {{expected '['}}
+func.func private @memref_unfinished_strided() -> memref<?x?xf32, strided<>>
 
 // -----
 
-func.func @memref_stride_invalid_offset(memref<42x42xi8, offset: [], strides: [?, ?]>) // expected-error {{invalid offset}}
+// expected-error @below {{expected a non-negative 64-bit signed integer or '?'}}
+func.func private @memref_unfinished_stride_list() -> memref<?x?xf32, strided<[>>
 
 // -----
 
-func.func @memref_stride_missing_strides(memref<42x42xi8, offset: 0 [?, ?]>) // expected-error {{expected comma after offset value}}
+// expected-error @below {{expected 'offset' after comma}}
+func.func private @memref_missing_offset() -> memref<?x?xf32, strided<[], >>
 
 // -----
 
-func.func @memref_stride_missing_strides(memref<42x42xi8, offset: 0, [?, ?]>) // expected-error {{expected `strides` keyword after offset specification}}
+// expected-error @below {{expected ':' after 'offset'}}
+func.func private @memref_missing_offset_colon() -> memref<?x?xf32, strided<[], offset>>
 
 // -----
 
-func.func @memref_stride_missing_colon_2(memref<42x42xi8, offset: 0, strides [?, ?]>) // expected-error {{expected colon after `strides` keyword}}
+// expected-error @below {{expected a non-negative 64-bit signed integer or '?'}}
+func.func private @memref_missing_offset_value() -> memref<?x?xf32, strided<[], offset: >>
 
 // -----
 
-// expected-error @+1 {{expected '['}}
-func.func @memref_stride_invalid_strides(memref<42x42xi8, offset: 0, strides: ()>)
+// expected-error @below {{expected '>'}}
+func.func private @memref_incorrect_strided_ending() -> memref<?x?xf32, strided<[], offset: 32)>
 
 // -----
 
-func.func @memref_zero_stride(memref<42x42xi8, offset: ?, strides: [0, ?]>) // expected-error {{invalid memref stride}}
+// expected-error @below {{strides must be positive or dynamic}}
+func.func private @memref_zero_stride() -> memref<?x?xf32, strided<[0, 0]>>
+
+// -----
+
+// expected-error @below {{expected a non-negative 64-bit signed integer or '?'}}
+func.func private @memref_negative_stride() -> memref<?x?xf32, strided<[-2, -2]>>
+
+// -----
+
+// expected-error @below {{expected a non-negative 64-bit signed integer or '?'}}
+func.func private @memref_negative_offset() -> memref<?x?xf32, strided<[2, 1], offset: -2>>
+
+// -----
+
+// expected-error @below {{expected the number of strides to match the rank}}
+func.func private @memref_strided_rank_mismatch() -> memref<?x?xf32, strided<[1]>>
 
 // -----
 

diff  --git a/mlir/test/Integration/Dialect/Linalg/CPU/matmul-vs-matvec.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/matmul-vs-matvec.mlir
index 6f409a8e411ef..2e1041f6aeb6e 100644
--- a/mlir/test/Integration/Dialect/Linalg/CPU/matmul-vs-matvec.mlir
+++ b/mlir/test/Integration/Dialect/Linalg/CPU/matmul-vs-matvec.mlir
@@ -28,10 +28,10 @@ func.func @matvec(%A: memref<?x?xf32>, %B: memref<?x?xf32>) -> (memref<?x?xf32>)
   %C = memref.alloc(%m, %n) : memref<?x?xf32>
   linalg.fill ins(%f0 : f32) outs(%C : memref<?x?xf32>)
   scf.for %i = %c0 to %n step %c1 {
-    %b = memref.subview %B[0, %i][%x, 1][1, 1] : memref<?x?xf32> to memref<?xf32, offset: ?, strides: [?]>
-    %c = memref.subview %C[0, %i][%m, 1][1, 1] : memref<?x?xf32> to memref<?xf32, offset: ?, strides: [?]>
-    linalg.matvec ins(%A, %b: memref<?x?xf32>, memref<?xf32, offset: ?, strides: [?]>)
-                  outs(%c: memref<?xf32, offset: ?, strides: [?]>)
+    %b = memref.subview %B[0, %i][%x, 1][1, 1] : memref<?x?xf32> to memref<?xf32, strided<[?], offset: ?>>
+    %c = memref.subview %C[0, %i][%m, 1][1, 1] : memref<?x?xf32> to memref<?xf32, strided<[?], offset: ?>>
+    linalg.matvec ins(%A, %b: memref<?x?xf32>, memref<?xf32, strided<[?], offset: ?>>)
+                  outs(%c: memref<?xf32, strided<[?], offset: ?>>)
   }
   return %C : memref<?x?xf32>
 }

diff  --git a/mlir/test/Integration/Dialect/Linalg/CPU/rank-reducing-subview.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/rank-reducing-subview.mlir
index 578703bc13317..5af39d5f00b18 100644
--- a/mlir/test/Integration/Dialect/Linalg/CPU/rank-reducing-subview.mlir
+++ b/mlir/test/Integration/Dialect/Linalg/CPU/rank-reducing-subview.mlir
@@ -18,13 +18,13 @@ func.func @main() {
   memref.store %f1, %A[%c0, %c1] : memref<?x?xf32>
   memref.store %f2, %A[%c1, %c0] : memref<?x?xf32>
   memref.store %f3, %A[%c1, %c1] : memref<?x?xf32>
-  %B = memref.subview %A[%c1, 0][1, %c2][1, 1] : memref<?x?xf32> to memref<?xf32, offset: ?, strides: [1]>
-  %C = memref.subview %A[0, %c1][%c2, 1][1, 1] : memref<?x?xf32> to memref<?xf32, offset: ?, strides: [?]>
+  %B = memref.subview %A[%c1, 0][1, %c2][1, 1] : memref<?x?xf32> to memref<?xf32, strided<[1], offset: ?>>
+  %C = memref.subview %A[0, %c1][%c2, 1][1, 1] : memref<?x?xf32> to memref<?xf32, strided<[?], offset: ?>>
   %A_ = memref.cast %A : memref<?x?xf32> to memref<*xf32>
   call @printMemrefF32(%A_) : (memref<*xf32>) -> ()
-  %B_ = memref.cast %B : memref<?xf32, offset: ?, strides: [1]> to memref<*xf32>
+  %B_ = memref.cast %B : memref<?xf32, strided<[1], offset: ?>> to memref<*xf32>
   call @printMemrefF32(%B_) : (memref<*xf32>) -> ()
-  %C_ = memref.cast %C : memref<?xf32, offset: ?, strides: [?]> to memref<*xf32>
+  %C_ = memref.cast %C : memref<?xf32, strided<[?], offset: ?>> to memref<*xf32>
   call @printMemrefF32(%C_) : (memref<*xf32>) -> ()
   memref.dealloc %A : memref<?x?xf32>
   return

diff  --git a/mlir/test/Integration/Dialect/Standard/CPU/test_subview.mlir b/mlir/test/Integration/Dialect/Standard/CPU/test_subview.mlir
index ee4dd47420ed4..2d13ead9618d5 100644
--- a/mlir/test/Integration/Dialect/Standard/CPU/test_subview.mlir
+++ b/mlir/test/Integration/Dialect/Standard/CPU/test_subview.mlir
@@ -13,8 +13,8 @@ func.func @main() {
   %0 = memref.get_global @__constant_5x3xf32 : memref<5x3xf32>
 
   /// Subview with only leading operands.
-  %1 = memref.subview %0[2, 0][3, 3][1, 1]: memref<5x3xf32> to memref<3x3xf32, offset: 6, strides: [3, 1]>
-  %unranked = memref.cast %1 : memref<3x3xf32, offset: 6, strides: [3, 1]> to memref<*xf32>
+  %1 = memref.subview %0[2, 0][3, 3][1, 1]: memref<5x3xf32> to memref<3x3xf32, strided<[3, 1], offset: 6>>
+  %unranked = memref.cast %1 : memref<3x3xf32, strided<[3, 1], offset: 6>> to memref<*xf32>
   call @printMemrefF32(%unranked) : (memref<*xf32>) -> ()
 
   //      CHECK: Unranked Memref base@ = {{0x[-9a-f]*}}
@@ -26,8 +26,8 @@ func.func @main() {
   // CHECK-SAME: ]
 
   /// Regular subview.
-  %2 = memref.subview %0[0, 2][5, 1][1, 1]: memref<5x3xf32> to memref<5x1xf32, offset: 2, strides: [3, 1]>
-  %unranked2 = memref.cast %2 : memref<5x1xf32, offset: 2, strides: [3, 1]> to memref<*xf32>
+  %2 = memref.subview %0[0, 2][5, 1][1, 1]: memref<5x3xf32> to memref<5x1xf32, strided<[3, 1], offset: 2>>
+  %unranked2 = memref.cast %2 : memref<5x1xf32, strided<[3, 1], offset: 2>> to memref<*xf32>
   call @printMemrefF32(%unranked2) : (memref<*xf32>) -> ()
 
   //      CHECK: Unranked Memref base@ = {{0x[-9a-f]*}}
@@ -41,8 +41,8 @@ func.func @main() {
   // CHECK-SAME: ]
 
   /// Rank-reducing subview.
-  %3 = memref.subview %0[0, 2][5, 1][1, 1]: memref<5x3xf32> to memref<5xf32, offset: 2, strides: [3]>
-  %unranked3 = memref.cast %3 : memref<5xf32, offset: 2, strides: [3]> to memref<*xf32>
+  %3 = memref.subview %0[0, 2][5, 1][1, 1]: memref<5x3xf32> to memref<5xf32, strided<[3], offset: 2>>
+  %unranked3 = memref.cast %3 : memref<5xf32, strided<[3], offset: 2>> to memref<*xf32>
   call @printMemrefF32(%unranked3) : (memref<*xf32>) -> ()
 
   //      CHECK: Unranked Memref base@ = {{0x[-9a-f]*}}
@@ -50,8 +50,8 @@ func.func @main() {
   // CHECK-NEXT: [2,  5,  8,  11,  14]
 
   /// Rank-reducing subview with only leading operands.
-  %4 = memref.subview %0[1, 0][1, 3][1, 1]: memref<5x3xf32> to memref<3xf32, offset: 3, strides: [1]>
-  %unranked4 = memref.cast %4 : memref<3xf32, offset: 3, strides: [1]> to memref<*xf32>
+  %4 = memref.subview %0[1, 0][1, 3][1, 1]: memref<5x3xf32> to memref<3xf32, strided<[1], offset: 3>>
+  %unranked4 = memref.cast %4 : memref<3xf32, strided<[1], offset: 3>> to memref<*xf32>
   call @printMemrefF32(%unranked4) : (memref<*xf32>) -> ()
   //      CHECK: Unranked Memref base@ = {{0x[-9a-f]*}}
   // CHECK-SAME: rank = 1 offset = 3 sizes = [3] strides = [1] data =

diff  --git a/mlir/test/Integration/Dialect/Vector/CPU/test-transfer-read-1d.mlir b/mlir/test/Integration/Dialect/Vector/CPU/test-transfer-read-1d.mlir
index 0caf3e0027631..45bf4f0de2718 100644
--- a/mlir/test/Integration/Dialect/Vector/CPU/test-transfer-read-1d.mlir
+++ b/mlir/test/Integration/Dialect/Vector/CPU/test-transfer-read-1d.mlir
@@ -70,9 +70,9 @@ func.func @transfer_read_1d_non_static_unit_stride(%A : memref<?x?xf32>) {
   %c6 = arith.constant 6 : index
   %fm42 = arith.constant -42.0: f32
   %1 = memref.reinterpret_cast %A to offset: [%c6], sizes: [%c1, %c2],  strides: [%c6, %c1]
-      : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+      : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
   %2 = vector.transfer_read %1[%c2, %c1], %fm42 {in_bounds=[true]}
-      : memref<?x?xf32, offset: ?, strides: [?, ?]>, vector<4xf32>
+      : memref<?x?xf32, strided<[?, ?], offset: ?>>, vector<4xf32>
   vector.print %2 : vector<4xf32>
   return
 }

diff  --git a/mlir/test/Transforms/canonicalize.mlir b/mlir/test/Transforms/canonicalize.mlir
index 51c5ecab8d548..a7b3b343c9dcd 100644
--- a/mlir/test/Transforms/canonicalize.mlir
+++ b/mlir/test/Transforms/canonicalize.mlir
@@ -764,86 +764,86 @@ func.func @subview(%arg0 : index, %arg1 : index) -> (index, index) {
   %c15 = arith.constant 15 : index
 
   // CHECK: %[[ALLOC0:.*]] = memref.alloc()
-  %0 = memref.alloc() : memref<8x16x4xf32, offset : 0, strides : [64, 4, 1]>
+  %0 = memref.alloc() : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>>
 
   // Test: subview with constant base memref and constant operands is folded.
   // Note that the subview uses the base memrefs layout map because it used
   // zero offset and unit stride arguments.
   // CHECK: memref.subview %[[ALLOC0]][0, 0, 0] [7, 11, 2] [1, 1, 1] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]>
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>>
   // CHECK-SAME: to memref<7x11x2xf32, #[[$BASE_MAP0]]>
   %1 = memref.subview %0[%c0, %c0, %c0] [%c7, %c11, %c2] [%c1, %c1, %c1]
-    : memref<8x16x4xf32, offset : 0, strides : [64, 4, 1]> to
-      memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
-  %v0 = memref.load %1[%c0, %c0, %c0] : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  %v0 = memref.load %1[%c0, %c0, %c0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // Test: subview with one dynamic operand can also be folded.
   // CHECK: memref.subview %[[ALLOC0]][0, %[[ARG0]], 0] [7, 11, 15] [1, 1, 1] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]>
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>>
   // CHECK-SAME: to memref<7x11x15xf32, #[[$SUBVIEW_MAP0]]>
   %2 = memref.subview %0[%c0, %arg0, %c0] [%c7, %c11, %c15] [%c1, %c1, %c1]
-    : memref<8x16x4xf32, offset : 0, strides : [64, 4, 1]> to
-      memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
-  memref.store %v0, %2[%c0, %c0, %c0] : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %2[%c0, %c0, %c0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // CHECK: %[[ALLOC1:.*]] = memref.alloc(%[[ARG0]])
-  %3 = memref.alloc(%arg0) : memref<?x16x4xf32, offset : 0, strides : [64, 4, 1]>
+  %3 = memref.alloc(%arg0) : memref<?x16x4xf32, strided<[64, 4, 1], offset: 0>>
   // Test: subview with constant operands but dynamic base memref is folded as long as the strides and offset of the base memref are static.
   // CHECK: memref.subview %[[ALLOC1]][0, 0, 0] [7, 11, 15] [1, 1, 1] :
-  // CHECK-SAME: memref<?x16x4xf32, #[[$BASE_MAP0]]>
+  // CHECK-SAME: memref<?x16x4xf32, strided<[64, 4, 1]>>
   // CHECK-SAME: to memref<7x11x15xf32, #[[$BASE_MAP0]]>
   %4 = memref.subview %3[%c0, %c0, %c0] [%c7, %c11, %c15] [%c1, %c1, %c1]
-    : memref<?x16x4xf32, offset : 0, strides : [64, 4, 1]> to
-      memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
-  memref.store %v0, %4[%c0, %c0, %c0] : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
+    : memref<?x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %4[%c0, %c0, %c0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // Test: subview offset operands are folded correctly w.r.t. base strides.
   // CHECK: memref.subview %[[ALLOC0]][1, 2, 7] [7, 11, 2] [1, 1, 1] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]> to
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>> to
   // CHECK-SAME: memref<7x11x2xf32, #[[$SUBVIEW_MAP1]]>
   %5 = memref.subview %0[%c1, %c2, %c7] [%c7, %c11, %c2] [%c1, %c1, %c1]
-    : memref<8x16x4xf32, offset : 0, strides : [64, 4, 1]> to
-      memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
-  memref.store %v0, %5[%c0, %c0, %c0] : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %5[%c0, %c0, %c0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // Test: subview stride operands are folded correctly w.r.t. base strides.
   // CHECK: memref.subview %[[ALLOC0]][0, 0, 0] [7, 11, 2] [2, 7, 11] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]>
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>>
   // CHECK-SAME: to memref<7x11x2xf32, #[[$SUBVIEW_MAP2]]>
   %6 = memref.subview %0[%c0, %c0, %c0] [%c7, %c11, %c2] [%c2, %c7, %c11]
-    : memref<8x16x4xf32, offset : 0, strides : [64, 4, 1]> to
-      memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
-  memref.store %v0, %6[%c0, %c0, %c0] : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
+    : memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+      memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %6[%c0, %c0, %c0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // Test: subview shape are folded, but offsets and strides are not even if base memref is static
   // CHECK: memref.subview %[[ALLOC0]][%[[ARG0]], %[[ARG0]], %[[ARG0]]] [7, 11, 2] [%[[ARG1]], %[[ARG1]], %[[ARG1]]] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]> to
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>> to
   // CHECK-SAME: memref<7x11x2xf32, #[[$SUBVIEW_MAP3]]>
   %10 = memref.subview %0[%arg0, %arg0, %arg0] [%c7, %c11, %c2] [%arg1, %arg1, %arg1] :
-    memref<8x16x4xf32, offset:0, strides:[64, 4, 1]> to
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
   memref.store %v0, %10[%arg1, %arg1, %arg1] :
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // Test: subview strides are folded, but offsets and shape are not even if base memref is static
   // CHECK: memref.subview %[[ALLOC0]][%[[ARG0]], %[[ARG0]], %[[ARG0]]] [%[[ARG1]], %[[ARG1]], %[[ARG1]]] [2, 7, 11] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]> to
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>> to
   // CHECK-SAME: memref<?x?x?xf32, #[[$SUBVIEW_MAP4]]
   %11 = memref.subview %0[%arg0, %arg0, %arg0] [%arg1, %arg1, %arg1] [%c2, %c7, %c11] :
-    memref<8x16x4xf32, offset:0, strides:[64, 4, 1]> to
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
   memref.store %v0, %11[%arg0, %arg0, %arg0] :
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // Test: subview offsets are folded, but strides and shape are not even if base memref is static
   // CHECK: memref.subview %[[ALLOC0]][1, 2, 7] [%[[ARG1]], %[[ARG1]], %[[ARG1]]] [%[[ARG0]], %[[ARG0]], %[[ARG0]]] :
-  // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]> to
+  // CHECK-SAME: memref<8x16x4xf32, strided<[64, 4, 1]>> to
   // CHECK-SAME: memref<?x?x?xf32, #[[$SUBVIEW_MAP5]]
   %13 = memref.subview %0[%c1, %c2, %c7] [%arg1, %arg1, %arg1] [%arg0, %arg0, %arg0] :
-    memref<8x16x4xf32, offset:0, strides:[64, 4, 1]> to
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<8x16x4xf32, strided<[64, 4, 1], offset: 0>> to
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
   memref.store %v0, %13[%arg1, %arg1, %arg1] :
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // CHECK: %[[ALLOC2:.*]] = memref.alloc(%[[ARG0]], %[[ARG0]], %[[ARG1]])
   %14 = memref.alloc(%arg0, %arg0, %arg1) : memref<?x?x?xf32>
@@ -853,8 +853,8 @@ func.func @subview(%arg0 : index, %arg1 : index) -> (index, index) {
   // CHECK-SAME: memref<7x11x2xf32, #[[$SUBVIEW_MAP3]]>
   %15 = memref.subview %14[%arg0, %arg0, %arg0] [%c7, %c11, %c2] [%arg1, %arg1, %arg1] :
     memref<?x?x?xf32> to
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
-  memref.store %v0, %15[%arg1, %arg1, %arg1] : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %15[%arg1, %arg1, %arg1] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // TEST: subview strides are folded, in the type only the most minor stride is folded.
   // CHECK: memref.subview %[[ALLOC2]][%[[ARG0]], %[[ARG0]], %[[ARG0]]] [%[[ARG1]], %[[ARG1]], %[[ARG1]]] [2, 2, 2] :
@@ -862,8 +862,8 @@ func.func @subview(%arg0 : index, %arg1 : index) -> (index, index) {
   // CHECK-SAME: memref<?x?x?xf32, #[[$SUBVIEW_MAP6]]
   %16 = memref.subview %14[%arg0, %arg0, %arg0] [%arg1, %arg1, %arg1] [%c2, %c2, %c2] :
     memref<?x?x?xf32> to
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
-  memref.store %v0, %16[%arg0, %arg0, %arg0] : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %16[%arg0, %arg0, %arg0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // TEST: subview offsets are folded but the type offset remains dynamic, when the base memref is not static
   // CHECK: memref.subview %[[ALLOC2]][1, 1, 1] [%[[ARG0]], %[[ARG0]], %[[ARG0]]] [%[[ARG1]], %[[ARG1]], %[[ARG1]]] :
@@ -871,8 +871,8 @@ func.func @subview(%arg0 : index, %arg1 : index) -> (index, index) {
   // CHECK-SAME: memref<?x?x?xf32, #[[$SUBVIEW_MAP3]]
   %17 = memref.subview %14[%c1, %c1, %c1] [%arg0, %arg0, %arg0] [%arg1, %arg1, %arg1] :
     memref<?x?x?xf32> to
-    memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
-  memref.store %v0, %17[%arg0, %arg0, %arg0] : memref<?x?x?xf32, offset: ?, strides: [?, ?, ?]>
+    memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  memref.store %v0, %17[%arg0, %arg0, %arg0] : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // CHECK: %[[ALLOC3:.*]] = memref.alloc() : memref<12x4xf32>
   %18 = memref.alloc() : memref<12x4xf32>
@@ -884,8 +884,8 @@ func.func @subview(%arg0 : index, %arg1 : index) -> (index, index) {
   // CHECK-SAME: memref<2x4xf32, #[[$SUBVIEW_MAP7]]>
   %19 = memref.subview %18[%arg1, %arg1] [%c2, %c4] [1, 1] :
     memref<12x4xf32> to
-    memref<?x?xf32, offset: ?, strides:[4, 1]>
-  memref.store %v0, %19[%arg1, %arg1] : memref<?x?xf32, offset: ?, strides:[4, 1]>
+    memref<?x?xf32, strided<[4, 1], offset: ?>>
+  memref.store %v0, %19[%arg1, %arg1] : memref<?x?xf32, strided<[4, 1], offset: ?>>
 
   // TEST: subview strides and sizes are maintained when offsets are folded
   // CHECK: memref.subview %[[ALLOC3]][2, 4] [12, 4] [1, 1] :
@@ -893,12 +893,12 @@ func.func @subview(%arg0 : index, %arg1 : index) -> (index, index) {
   // CHECK-SAME: memref<12x4xf32, #[[$SUBVIEW_MAP8]]>
   %20 = memref.subview %18[%c2, %c4] [12, 4] [1, 1] :
     memref<12x4xf32> to
-    memref<12x4xf32, offset: ?, strides:[4, 1]>
-  memref.store %v0, %20[%arg1, %arg1] : memref<12x4xf32, offset: ?, strides:[4, 1]>
+    memref<12x4xf32, strided<[4, 1], offset: ?>>
+  memref.store %v0, %20[%arg1, %arg1] : memref<12x4xf32, strided<[4, 1], offset: ?>>
 
   // Test: dim on subview is rewritten to size operand.
-  %7 = memref.dim %4, %c0 : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
-  %8 = memref.dim %4, %c1 : memref<?x?x?xf32, offset : ?, strides : [?, ?, ?]>
+  %7 = memref.dim %4, %c0 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
+  %8 = memref.dim %4, %c1 : memref<?x?x?xf32, strided<[?, ?, ?], offset: ?>>
 
   // CHECK: return %[[C7]], %[[C11]]
   return %7, %8 : index, index
@@ -1049,28 +1049,28 @@ func.func @tensor_arith.ceildivui_by_one(%arg0: tensor<4x5xi32>) -> tensor<4x5xi
 // -----
 
 // CHECK-LABEL: func @memref_cast_folding_subview
-func.func @memref_cast_folding_subview(%arg0: memref<4x5xf32>, %i: index) -> (memref<?x?xf32, offset:? , strides: [?, ?]>) {
+func.func @memref_cast_folding_subview(%arg0: memref<4x5xf32>, %i: index) -> (memref<?x?xf32, strided<[?, ?], offset: ?>>) {
   %0 = memref.cast %arg0 : memref<4x5xf32> to memref<?x?xf32>
   // CHECK-NEXT: memref.subview %{{.*}}: memref<4x5xf32>
-  %1 = memref.subview %0[%i, %i][%i, %i][%i, %i]: memref<?x?xf32> to memref<?x?xf32, offset:? , strides: [?, ?]>
+  %1 = memref.subview %0[%i, %i][%i, %i][%i, %i]: memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
+  // CHECK-NEXT: memref.cast
   // CHECK-NEXT: return %{{.*}}
-  return %1: memref<?x?xf32, offset:? , strides: [?, ?]>
+  return %1: memref<?x?xf32, strided<[?, ?], offset: ?>>
 }
 
 // -----
 
 // CHECK-DAG: #[[$map0:.*]] = affine_map<(d0, d1) -> (d0 * 16 + d1)>
-// CHECK-DAG: #[[$map1:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
 
 // CHECK-LABEL: func @memref_cast_folding_subview_static(
 func.func @memref_cast_folding_subview_static(%V: memref<16x16xf32>, %a: index, %b: index)
-  -> memref<3x4xf32, offset:?, strides:[?, 1]>
+  -> memref<3x4xf32, strided<[?, 1], offset: ?>>
 {
   %0 = memref.cast %V : memref<16x16xf32> to memref<?x?xf32>
-  %1 = memref.subview %0[0, 0][3, 4][1, 1] : memref<?x?xf32> to memref<3x4xf32, offset:?, strides:[?, 1]>
+  %1 = memref.subview %0[0, 0][3, 4][1, 1] : memref<?x?xf32> to memref<3x4xf32, strided<[?, 1], offset: ?>>
 
   // CHECK:  memref.subview{{.*}}: memref<16x16xf32> to memref<3x4xf32, #[[$map0]]>
-  return %1: memref<3x4xf32, offset:?, strides:[?, 1]>
+  return %1: memref<3x4xf32, strided<[?, 1], offset: ?>>
 }
 
 // -----

diff  --git a/mlir/test/mlir-cpu-runner/copy.mlir b/mlir/test/mlir-cpu-runner/copy.mlir
index d3cfdbc1c1305..a16d199c4077f 100644
--- a/mlir/test/mlir-cpu-runner/copy.mlir
+++ b/mlir/test/mlir-cpu-runner/copy.mlir
@@ -37,8 +37,8 @@ func.func @main() -> () {
 
   %copy_two = memref.alloc() : memref<3x2xf32>
   %copy_two_casted = memref.reinterpret_cast %copy_two to offset: [0], sizes: [2, 3], strides: [1, 2]
-    : memref<3x2xf32> to memref<2x3xf32, offset: 0, strides: [1, 2]>
-  memref.copy %input, %copy_two_casted : memref<2x3xf32> to memref<2x3xf32, offset: 0, strides: [1, 2]>
+    : memref<3x2xf32> to memref<2x3xf32, strided<[1, 2], offset: 0>>
+  memref.copy %input, %copy_two_casted : memref<2x3xf32> to memref<2x3xf32, strided<[1, 2], offset: 0>>
   %unranked_copy_two = memref.cast %copy_two : memref<3x2xf32> to memref<*xf32>
   call @printMemrefF32(%unranked_copy_two) : (memref<*xf32>) -> ()
   // CHECK: rank = 2 offset = 0 sizes = [3, 2] strides = [2, 1]
@@ -52,10 +52,10 @@ func.func @main() -> () {
   memref.copy %input_empty, %copy_empty : memref<3x0x1xf32> to memref<3x0x1xf32>
 
   %input_empty_casted = memref.reinterpret_cast %input_empty to offset: [0], sizes: [0, 3, 1], strides: [3, 1, 1]
-    : memref<3x0x1xf32> to memref<0x3x1xf32, offset: 0, strides: [3, 1, 1]>
+    : memref<3x0x1xf32> to memref<0x3x1xf32, strided<[3, 1, 1], offset: 0>>
   %copy_empty_casted = memref.alloc() : memref<0x3x1xf32>
   // Copying a casted empty shape should do nothing (and should not crash).
-  memref.copy %input_empty_casted, %copy_empty_casted : memref<0x3x1xf32, offset: 0, strides: [3, 1, 1]> to memref<0x3x1xf32>
+  memref.copy %input_empty_casted, %copy_empty_casted : memref<0x3x1xf32, strided<[3, 1, 1], offset: 0>> to memref<0x3x1xf32>
 
   %scalar = memref.alloc() : memref<f32>
   memref.store %c42, %scalar[] : memref<f32>

diff  --git a/mlir/test/mlir-cpu-runner/memref-reinterpret-cast.mlir b/mlir/test/mlir-cpu-runner/memref-reinterpret-cast.mlir
index a6c1ee31a41c0..645f1a0c26f2c 100644
--- a/mlir/test/mlir-cpu-runner/memref-reinterpret-cast.mlir
+++ b/mlir/test/mlir-cpu-runner/memref-reinterpret-cast.mlir
@@ -59,10 +59,10 @@ func.func @cast_ranked_memref_to_dynamic_shape(%input : memref<2x3xf32>) {
   %c6 = arith.constant 6 : index
   %output = memref.reinterpret_cast %input to
            offset: [%c0], sizes: [%c1, %c6], strides: [%c6, %c1]
-           : memref<2x3xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+           : memref<2x3xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
 
   %unranked_output = memref.cast %output
-      : memref<?x?xf32, offset: ?, strides: [?, ?]> to memref<*xf32>
+      : memref<?x?xf32, strided<[?, ?], offset: ?>> to memref<*xf32>
   call @printMemrefF32(%unranked_output) : (memref<*xf32>) -> ()
   // CHECK: rank = 2 offset = 0 sizes = [1, 6] strides = [6, 1] data =
   // CHECK-NEXT: [0,   1,   2,   3,   4,   5]
@@ -95,10 +95,10 @@ func.func @cast_unranked_memref_to_dynamic_shape(%input : memref<2x3xf32>) {
   %c6 = arith.constant 6 : index
   %output = memref.reinterpret_cast %unranked_input to
            offset: [%c0], sizes: [%c1, %c6], strides: [%c6, %c1]
-           : memref<*xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+           : memref<*xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
 
   %unranked_output = memref.cast %output
-      : memref<?x?xf32, offset: ?, strides: [?, ?]> to memref<*xf32>
+      : memref<?x?xf32, strided<[?, ?], offset: ?>> to memref<*xf32>
   call @printMemrefF32(%unranked_output) : (memref<*xf32>) -> ()
   // CHECK: rank = 2 offset = 0 sizes = [1, 6] strides = [6, 1] data =
   // CHECK-NEXT: [0,   1,   2,   3,   4,   5]

diff  --git a/mlir/test/python/dialects/memref.py b/mlir/test/python/dialects/memref.py
index d3501d403b52a..59092feffba23 100644
--- a/mlir/test/python/dialects/memref.py
+++ b/mlir/test/python/dialects/memref.py
@@ -24,7 +24,7 @@ def testSubViewAccessors():
       %3 = arith.constant 3 : index
       %4 = arith.constant 4 : index
       %5 = arith.constant 5 : index
-      memref.subview %arg0[%0, %1][%2, %3][%4, %5] : memref<?x?xf32> to memref<?x?xf32, offset: ?, strides: [?, ?]>
+      memref.subview %arg0[%0, %1][%2, %3][%4, %5] : memref<?x?xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
       return
     }
   """, ctx)


        


More information about the Mlir-commits mailing list