[Mlir-commits] [mlir] f4ac9f0 - [mlir][Linalg] Drop SliceOp

Nicolas Vasilache llvmlistbot at llvm.org
Thu Feb 4 03:25:17 PST 2021


Author: Nicolas Vasilache
Date: 2021-02-04T11:22:01Z
New Revision: f4ac9f03340676a86ff73b5904dafc7ea8fa3379

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

LOG: [mlir][Linalg] Drop SliceOp

This op is subsumed by rank-reducing SubViewOp and has become useless.

Differential revision: https://reviews.llvm.org/D95317

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Linalg/EDSC/Intrinsics.h
    mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
    mlir/include/mlir/Interfaces/ViewLikeInterface.td
    mlir/lib/Conversion/LinalgToLLVM/LinalgToLLVM.cpp
    mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
    mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
    mlir/lib/IR/BuiltinTypes.cpp
    mlir/test/Dialect/Linalg/canonicalize.mlir
    mlir/test/Dialect/Linalg/invalid.mlir
    mlir/test/Dialect/Linalg/llvm.mlir
    mlir/test/Dialect/Linalg/roundtrip.mlir
    mlir/test/IR/core-ops.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Linalg/EDSC/Intrinsics.h b/mlir/include/mlir/Dialect/Linalg/EDSC/Intrinsics.h
index 0b53fc7573a5..4ebbb93cca5d 100644
--- a/mlir/include/mlir/Dialect/Linalg/EDSC/Intrinsics.h
+++ b/mlir/include/mlir/Dialect/Linalg/EDSC/Intrinsics.h
@@ -24,7 +24,6 @@ using linalg_matvec = OperationBuilder<linalg::MatvecOp>;
 using linalg_vecmat = OperationBuilder<linalg::VecmatOp>;
 using linalg_range = ValueBuilder<linalg::RangeOp>;
 using linalg_reshape = ValueBuilder<linalg::ReshapeOp>;
-using linalg_slice = ValueBuilder<linalg::SliceOp>;
 using linalg_yield = OperationBuilder<linalg::YieldOp>;
 
 } // namespace intrinsics

diff  --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
index 3185502b1879..f558f656e558 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
@@ -433,78 +433,6 @@ def Linalg_TensorReshapeOp : Linalg_ReshapeLikeOp<"tensor_reshape">,
   let hasCanonicalizer = 1;
 }
 
-def Linalg_SliceOp : Linalg_Op<"slice", [
-      DeclareOpInterfaceMethods<ViewLikeOpInterface>, NoSideEffect]>,
-    Arguments<(ins AnyStridedMemRef:$view,
-                   Variadic<AnyTypeOf<[Range, Index]>>:$indexings)>,
-    Results<(outs AnyStridedMemRef)> {
-  let summary = "Produce a rank-reduced `subview` of a base `view`.";
-  let description = [{
-    The `linalg.slice` op allows defining a subregion of a smaller rank than the
-    operand `view` within the underlying buffer.
-
-    A `linalg.slice` op takes a view and a variadic number of indexings and
-    produces a `view` of the same elemental type. An indexing is either:
-      1. a `linalg.range`, in which case it does not reduce the rank of the
-         parent `view` along the corresponding dimension.
-      2. an `index`, in which case it reduces the rank of the parent view by
-         one.
-
-    If an indexing extends past the size of the `view`, this is undefined
-    behavior. Ideally the `linalg.slice` operation would automatically truncate
-    it to be within bounds but there are tradeoffs involved now that `std.view`
-    is a standard op.
-
-    Examples:
-
-      1. rank-preserving `slice`:
-
-      ```mlir
-      %4 = linalg.slice %0[%1, %2] : memref<?x?xf32, stride_spec>,
-        !linalg.range, !linalg.range, memref<?x?xf32, stride_spec>
-      ```
-
-      2. rank-reducing `slice` (from 2-D to 1-D):
-
-      ```mlir
-      %4 = linalg.slice %0[%1, %2] : memref<?x?xf32, stride_spec>,
-        index, !linalg.range, memref<?x?xf32, stride_spec>
-      ```
-
-      3. rank-reducing `slice` (from 2-D to 0-D):
-
-      ```mlir
-      %4 = linalg.slice %0[%1, %2] : memref<?x?xf32, stride_spec>,
-        index, index, memref<?x?xf32, stride_spec>
-      ```
-  }];
-
-  let builders = [OpBuilderDAG<(ins "Value":$base, "ValueRange":$indexings)>];
-
-  let extraClassDeclaration = [{
-    enum { FirstIndexingOperand = 1 };
-    unsigned getRank() { return getShapedType().getRank(); }
-    Type getElementType() { return getShapedType().getElementType(); }
-    ShapedType getShapedType() { return getType().cast<ShapedType>(); }
-    unsigned getBaseViewRank() { return getBaseViewType().getRank(); }
-    ShapedType getBaseViewType() { return view().getType().cast<ShapedType>();}
-
-    // Get the underlying indexing at a given rank.
-    Value indexing(unsigned rank) { return *(indexings().begin() + rank); }
-
-    // Get the subset of indexings that are of RangeType.
-    SmallVector<Value, 8> getRanges() {
-      SmallVector<Value, 8> res;
-      for (auto operand : indexings())
-        if (!operand.getType().isa<IndexType>())
-          res.push_back(operand);
-      return res;
-    }
-  }];
-
-  let hasFolder = 1;
-}
-
 def Linalg_YieldOp : Linalg_Op<"yield", [NoSideEffect, ReturnLike, Terminator]>,
     Arguments<(ins Variadic<AnyType>:$values)> {
   let summary = "Linalg yield operation";

diff  --git a/mlir/include/mlir/Interfaces/ViewLikeInterface.td b/mlir/include/mlir/Interfaces/ViewLikeInterface.td
index bb24404670c8..f515c5816096 100644
--- a/mlir/include/mlir/Interfaces/ViewLikeInterface.td
+++ b/mlir/include/mlir/Interfaces/ViewLikeInterface.td
@@ -45,9 +45,9 @@ def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface
 
     The invariants of this interface are:
       1. `static_offsets`, `static_sizes` and `static_strides` have length
-          at most `getArrayAttrMaxRanks()`[0] (resp. [1], [2]).
+          exactly `getArrayAttrMaxRanks()`[0] (resp. [1], [2]).
       2. `offsets`, `sizes` and `strides` have each length at most
-         length `static_offsets` (resp. `static_sizes`, `static_strides`).
+         `getArrayAttrMaxRanks()`[0] (resp. [1], [2]).
       3. if an entry of `static_offsets` (resp. `static_sizes`,
          `static_strides`) is equal to a special sentinel value, namely
          `ShapedType::kDynamicStrideOrOffset` (resp. `ShapedType::kDynamicSize`,

diff  --git a/mlir/lib/Conversion/LinalgToLLVM/LinalgToLLVM.cpp b/mlir/lib/Conversion/LinalgToLLVM/LinalgToLLVM.cpp
index 95e7c34a1710..f3f978a7dc5f 100644
--- a/mlir/lib/Conversion/LinalgToLLVM/LinalgToLLVM.cpp
+++ b/mlir/lib/Conversion/LinalgToLLVM/LinalgToLLVM.cpp
@@ -185,93 +185,6 @@ class ReshapeOpConversion : public ConvertOpToLLVMPattern<ReshapeOp> {
   }
 };
 
-/// Conversion pattern that transforms a linalg.slice op into:
-///   1. An "undef" value for the ViewDescriptor.
-///   2. Updates to the ViewDescriptor to introduce the data ptr, offset, size
-///      and stride corresponding to the region of memory within the bounds of
-///      the parent view.
-/// The linalg.slice op is replaced by the alloca'ed pointer.
-class SliceOpConversion : public ConvertOpToLLVMPattern<SliceOp> {
-public:
-  using ConvertOpToLLVMPattern<SliceOp>::ConvertOpToLLVMPattern;
-
-  LogicalResult
-  matchAndRewrite(SliceOp sliceOp, ArrayRef<Value> operands,
-                  ConversionPatternRewriter &rewriter) const override {
-    edsc::ScopedContext context(rewriter, sliceOp->getLoc());
-    SliceOpAdaptor adaptor(operands);
-    BaseViewConversionHelper baseDesc(adaptor.view());
-
-    auto memRefType = sliceOp.getBaseViewType();
-    auto int64Ty = typeConverter->convertType(rewriter.getIntegerType(64));
-
-    BaseViewConversionHelper desc(
-        typeConverter->convertType(sliceOp.getShapedType()));
-
-    // TODO: extract sizes and emit asserts.
-    SmallVector<Value, 4> strides(memRefType.getRank());
-    for (int i = 0, e = memRefType.getRank(); i < e; ++i)
-      strides[i] = baseDesc.stride(i);
-
-    auto pos = [&rewriter](ArrayRef<int64_t> values) {
-      return rewriter.getI64ArrayAttr(values);
-    };
-
-    // Compute base offset.
-    Value baseOffset = baseDesc.offset();
-    for (int i = 0, e = memRefType.getRank(); i < e; ++i) {
-      Value indexing = adaptor.indexings()[i];
-      Value min = indexing;
-      if (sliceOp.indexing(i).getType().isa<RangeType>())
-        min = llvm_extractvalue(int64Ty, indexing, pos(0));
-      baseOffset = llvm_add(baseOffset, llvm_mul(min, strides[i]));
-    }
-
-    // Insert the base and aligned pointers.
-    desc.setAllocatedPtr(baseDesc.allocatedPtr());
-    desc.setAlignedPtr(baseDesc.alignedPtr());
-
-    // Insert base offset.
-    desc.setOffset(baseOffset);
-
-    // Corner case, no sizes or strides: early return the descriptor.
-    if (sliceOp.getShapedType().getRank() == 0)
-      return rewriter.replaceOp(sliceOp, {desc}), success();
-
-    Value zero = llvm_constant(
-        int64Ty, rewriter.getIntegerAttr(rewriter.getIndexType(), 0));
-    // Compute and insert view sizes (max - min along the range) and strides.
-    // Skip the non-range operands as they will be projected away from the view.
-    int numNewDims = 0;
-    for (auto en : llvm::enumerate(sliceOp.indexings())) {
-      Value indexing = en.value();
-      if (indexing.getType().isa<RangeType>()) {
-        int rank = en.index();
-        Value rangeDescriptor = adaptor.indexings()[rank];
-        Value min = llvm_extractvalue(int64Ty, rangeDescriptor, pos(0));
-        Value max = llvm_extractvalue(int64Ty, rangeDescriptor, pos(1));
-        Value step = llvm_extractvalue(int64Ty, rangeDescriptor, pos(2));
-        Value baseSize = baseDesc.size(rank);
-
-        // Bound upper by base view upper bound.
-        max = llvm_select(llvm_icmp(ICmpPredicate::slt, max, baseSize), max,
-                          baseSize);
-        Value size = llvm_sub(max, min);
-        // Bound lower by zero.
-        size =
-            llvm_select(llvm_icmp(ICmpPredicate::slt, size, zero), zero, size);
-        Value stride = llvm_mul(strides[rank], step);
-        desc.setSize(numNewDims, size);
-        desc.setStride(numNewDims, stride);
-        ++numNewDims;
-      }
-    }
-
-    rewriter.replaceOp(sliceOp, {desc});
-    return success();
-  }
-};
-
 // YieldOp produces and LLVM::ReturnOp.
 class YieldOpConversion : public ConvertOpToLLVMPattern<linalg::YieldOp> {
 public:
@@ -289,8 +202,8 @@ class YieldOpConversion : public ConvertOpToLLVMPattern<linalg::YieldOp> {
 /// Populate the given list with patterns that convert from Linalg to LLVM.
 void mlir::populateLinalgToLLVMConversionPatterns(
     LLVMTypeConverter &converter, OwningRewritePatternList &patterns) {
-  patterns.insert<RangeOpConversion, ReshapeOpConversion, SliceOpConversion,
-                  YieldOpConversion>(converter);
+  patterns.insert<RangeOpConversion, ReshapeOpConversion, YieldOpConversion>(
+      converter);
 
   // Populate the type conversions for the linalg types.
   converter.addConversion(

diff  --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
index 7a720d3e68bc..2d1e64a04230 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
@@ -1318,83 +1318,6 @@ void TensorReshapeOp::getCanonicalizationPatterns(
       context);
 }
 
-//===----------------------------------------------------------------------===//
-// SliceOp
-//===----------------------------------------------------------------------===//
-void mlir::linalg::SliceOp::build(OpBuilder &b, OperationState &result,
-                                  Value base, ValueRange indexings) {
-  result.addOperands(base);
-  result.addOperands(indexings);
-
-  auto memRefType = base.getType().cast<MemRefType>();
-  int64_t offset;
-  SmallVector<int64_t, 4> strides;
-  auto res = getStridesAndOffset(memRefType, strides, offset);
-  assert(succeeded(res) && strides.size() == indexings.size());
-  (void)res;
-
-  unsigned rank = memRefType.getRank();
-  // TODO: propagate static size and stride information when available.
-  SmallVector<int64_t, 4> sizes(rank, -1); // -1 encodes dynamic size.
-  result.addTypes({MemRefType::Builder(memRefType)
-                       .setShape(sizes)
-                       .setAffineMaps(makeStridedLinearLayoutMap(
-                           strides, offset, b.getContext()))});
-}
-
-static void print(OpAsmPrinter &p, SliceOp op) {
-  auto indexings = op.indexings();
-  p << SliceOp::getOperationName() << " " << op.view() << "[" << indexings
-    << "] ";
-  p.printOptionalAttrDict(op.getAttrs());
-  p << " : " << op.getBaseViewType();
-  if (!indexings.empty())
-    p << ", " << op.indexings().getTypes();
-  p << ", " << op.getType();
-}
-
-static ParseResult parseSliceOp(OpAsmParser &parser, OperationState &result) {
-  OpAsmParser::OperandType baseInfo;
-  SmallVector<OpAsmParser::OperandType, 8> operands;
-  SmallVector<Type, 8> types;
-  if (parser.parseOperand(baseInfo) ||
-      parser.parseOperandList(operands, OpAsmParser::Delimiter::Square) ||
-      parser.parseOptionalAttrDict(result.attributes) ||
-      parser.parseColonTypeList(types))
-    return failure();
-
-  if (types.size() < 2)
-    return parser.emitError(parser.getCurrentLocation(),
-                            "expected at least input and result view types");
-
-  ArrayRef<Type> indexingTypes = ArrayRef<Type>(types).drop_front().drop_back();
-  return failure(
-      parser.resolveOperand(baseInfo, types.front(), result.operands) ||
-      (!operands.empty() &&
-       parser.resolveOperands(operands, indexingTypes,
-                              operands.front().location, result.operands)) ||
-      parser.addTypeToList(types.back(), result.types));
-}
-
-static LogicalResult verify(SliceOp op) {
-  unsigned rank = op.getBaseViewRank();
-  if (rank != llvm::size(op.indexings()))
-    return op.emitOpError("expected ")
-           << rank << " indexings, got " << llvm::size(op.indexings());
-  unsigned index = 0;
-  for (auto indexing : op.indexings()) {
-    if (indexing.getType().isa<IndexType>())
-      --rank;
-    ++index;
-  }
-  if (op.getRank() != rank)
-    return op.emitOpError() << "expected rank of the view(" << op.getRank()
-                            << ") to be the number of ranges(" << rank << ")";
-  return success();
-}
-
-Value SliceOp::getViewSource() { return view(); }
-
 //===----------------------------------------------------------------------===//
 // YieldOp
 //===----------------------------------------------------------------------===//
@@ -1746,11 +1669,6 @@ OpFoldResult ReshapeOp::fold(ArrayRef<Attribute> operands) {
     return getResult();
   return foldReshapeOp(*this, operands);
 }
-OpFoldResult SliceOp::fold(ArrayRef<Attribute>) {
-  if (succeeded(foldMemRefCast(*this)))
-    return getResult();
-  return {};
-}
 OpFoldResult TensorReshapeOp::fold(ArrayRef<Attribute> operands) {
   return foldReshapeOp(*this, operands);
 }

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp b/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
index 7441a54cdc05..f6289b9541ce 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Fusion.cpp
@@ -426,9 +426,8 @@ mlir::linalg::fuseProducerOfBuffer(OpBuilder &b, OpOperand &consumerOpOperand,
   // Must be a subview or a slice to guarantee there are loops we can fuse
   // into.
   auto subView = consumerOpOperand.get().getDefiningOp<SubViewOp>();
-  auto slice = consumerOpOperand.get().getDefiningOp<SliceOp>();
-  if (!subView && !slice) {
-    LLVM_DEBUG(llvm::dbgs() << "\nNot fusable (not a subview or slice)");
+  if (!subView) {
+    LLVM_DEBUG(llvm::dbgs() << "\nNot fusable (not a subview)");
     return llvm::None;
   }
 

diff  --git a/mlir/lib/IR/BuiltinTypes.cpp b/mlir/lib/IR/BuiltinTypes.cpp
index 14144077ef4c..e7e912aa8318 100644
--- a/mlir/lib/IR/BuiltinTypes.cpp
+++ b/mlir/lib/IR/BuiltinTypes.cpp
@@ -754,6 +754,12 @@ MemRefType mlir::canonicalizeStridedLayout(MemRefType t) {
     return t;
   }
 
+  // 0-D corner case for empty shape that still have an affine map. Example:
+  // `memref<f32, affine_map<()[s0] -> (s0)>>`. This is a 1 element memref whose
+  // offset needs to remain, just return t.
+  if (t.getShape().empty())
+    return t;
+
   // If the canonical strided layout for the sizes of `t` is equal to the
   // simplified layout of `t` we can just return an empty layout. Otherwise,
   // just simplify the existing layout.
@@ -770,6 +776,9 @@ MemRefType mlir::canonicalizeStridedLayout(MemRefType t) {
 AffineExpr mlir::makeCanonicalStridedLayoutExpr(ArrayRef<int64_t> sizes,
                                                 ArrayRef<AffineExpr> exprs,
                                                 MLIRContext *context) {
+  assert(!sizes.empty() && !exprs.empty() &&
+         "expected non-empty sizes and exprs");
+
   // Size 0 corner case is useful for canonicalizations.
   if (llvm::is_contained(sizes, 0))
     return getAffineConstantExpr(0, context);

diff  --git a/mlir/test/Dialect/Linalg/canonicalize.mlir b/mlir/test/Dialect/Linalg/canonicalize.mlir
index 418d9d2195b9..f35b41c47da3 100644
--- a/mlir/test/Dialect/Linalg/canonicalize.mlir
+++ b/mlir/test/Dialect/Linalg/canonicalize.mlir
@@ -9,15 +9,11 @@ func @memref_cast(%a: index, %b: index) -> memref<?x?xf32> {
   %1 = alloc (%b) : memref<?xi8>
   %2 = view %1[%c0][] : memref<?xi8> to memref<16x16xf32>
   %3 = memref_cast %2 : memref<16x16xf32> to memref<?x?xf32>
-  %r0 = linalg.range %c0:%c8:%c1 : !linalg.range
-
-  // CHECK:  linalg.slice {{.*}} : memref<16x16xf32>, !linalg.range, !linalg.range, memref<?x?xf32>
-  %4 = linalg.slice %3[%r0, %r0] : memref<?x?xf32>, !linalg.range, !linalg.range, memref<?x?xf32>
 
   // CHECK:  linalg.matmul ins({{.*}}memref<16x16xf32>, memref<16x16xf32>) outs({{.*}}memref<16x16xf32>)
   linalg.matmul ins(%3, %3: memref<?x?xf32>, memref<?x?xf32>)
                outs(%3: memref<?x?xf32>)
-  return %4: memref<?x?xf32>
+  return %3: memref<?x?xf32>
 }
 
 // -----

diff  --git a/mlir/test/Dialect/Linalg/invalid.mlir b/mlir/test/Dialect/Linalg/invalid.mlir
index 44e51d615006..e27e7fc25825 100644
--- a/mlir/test/Dialect/Linalg/invalid.mlir
+++ b/mlir/test/Dialect/Linalg/invalid.mlir
@@ -8,22 +8,6 @@ func @load_number_of_indices(%v : memref<f32>) {
 
 // -----
 
-func @slice_number_of_indexings(%arg0: memref<?x?xf32, affine_map<(i, j)[off, M]->(off + M * i + j)>>) {
-  // expected-error @+2 {{expected 2 indexings, got 1}}
-  %c0 = constant 0: index
-  %0 = linalg.slice %arg0[%c0] : memref<?x?xf32, affine_map<(i, j)[off, M]->(off + M * i + j)>>, index, memref<?x?xf32, affine_map<(i, j)[off, M]->(off + M * i + j)>>
-}
-
-// -----
-
-func @slice_rank_vs_range_indices(%arg0: memref<?x?xf32, affine_map<(i, j)[off, M]->(off + M * i + j)>>) {
-  // expected-error @+2 {{op expected rank of the view(1) to be the number of ranges(0)}}
-  %c0 = constant 0: index
-  %0 = linalg.slice %arg0[%c0, %c0] : memref<?x?xf32, affine_map<(i, j)[off, M]->(off + M * i + j)>>, index, index, memref<?xf32, affine_map<(i)[off]->(off + i)>>
-}
-
-// -----
-
 func @store_number_of_indices(%v : memref<f32>) {
   // expected-error @+3 {{store index operand count not equal to memref rank}}
   %c0 = constant 0 : index

diff  --git a/mlir/test/Dialect/Linalg/llvm.mlir b/mlir/test/Dialect/Linalg/llvm.mlir
index 8b023c388937..d90fa991fdb9 100644
--- a/mlir/test/Dialect/Linalg/llvm.mlir
+++ b/mlir/test/Dialect/Linalg/llvm.mlir
@@ -14,61 +14,6 @@ func @range(%arg0: index) {
 //  CHECK-NEXT:   llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm.struct<(i64, i64, i64)>
 //  CHECK-NEXT:   llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm.struct<(i64, i64, i64)>
 
-func @slice(%arg0: memref<?xf32, offset: ?, strides: [1]>, %arg1: !linalg.range) {
-  %1 = linalg.slice %arg0[%arg1] : memref<?xf32, offset: ?, strides: [1]>, !linalg.range, memref<?xf32, offset: ?, strides: [1]>
-  return
-}
-// CHECK-LABEL: func @slice
-//   insert data ptr for slice op
-//       CHECK:   llvm.extractvalue %{{.*}}[4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-//  CHECK-NEXT:   llvm.extractvalue %{{.*}}[2] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-//  CHECK-NEXT:   llvm.extractvalue %{{.*}}[0] : !llvm.struct<(i64, i64, i64)>
-//  CHECK-NEXT:   llvm.mul %{{.*}}, %{{.*}} : i64
-//  CHECK-NEXT:   llvm.add %{{.*}}, %{{.*}} : i64
-//    insert offset
-//       CHECK:   llvm.insertvalue %{{.*}}, %{{.*}}[1] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-//  CHECK-NEXT:   llvm.insertvalue %{{.*}}, %{{.*}}[2] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-//  CHECK-NEXT:   llvm.mlir.constant(0 : index)
-//  CHECK-NEXT:   llvm.extractvalue %{{.*}}[0] : !llvm.struct<(i64, i64, i64)>
-//  CHECK-NEXT:   llvm.extractvalue %{{.*}}[1] : !llvm.struct<(i64, i64, i64)>
-//  CHECK-NEXT:   llvm.extractvalue %{{.*}}[2] : !llvm.struct<(i64, i64, i64)>
-//    get size[0] from parent view
-//  CHECK-NEXT:   llvm.extractvalue %{{.*}}[3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-//  CHECK-NEXT:   llvm.icmp "slt" %{{.*}}, %{{.*}} : i64
-//  CHECK-NEXT:   llvm.select %{{.*}}, %{{.*}}, %{{.*}} : i1, i64
-//    compute size[0] bounded by parent view's size[0]
-//  CHECK-NEXT:   llvm.sub %{{.*}}, %{{.*}} : i64
-//    bound below by 0
-//  CHECK-NEXT:   llvm.icmp "slt" %{{.*}}, %{{.*}} : i64
-//  CHECK-NEXT:   llvm.select %{{.*}}, %{{.*}}, %{{.*}} : i1, i64
-//    compute stride[0] using bounded size
-//  CHECK-NEXT:   llvm.mul %{{.*}}, %{{.*}} : i64
-//    insert size and stride
-//  CHECK-NEXT:   llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-//  CHECK-NEXT:   llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)>
-
-func @slice_with_range_and_index(%arg0: memref<?x?xf64, offset: ?, strides: [?, 1]>) {
-  %c0 = constant 0 : index
-  %c1 = constant 1 : index
-  %R = linalg.range %c0:%c1:%c1 : !linalg.range
-  scf.for %i0 = %c0 to %c1 step %c1 {
-    %1 = linalg.slice %arg0[%i0, %R] : memref<?x?xf64, offset: ?, strides: [?, 1]>, index, !linalg.range, memref<?xf64, offset: ?, strides: [1]>
-  }
-  return
-}
-// CHECK-LABEL: func @slice_with_range_and_index
-// loop-body.
-//       CHECK:   llvm.mlir.undef : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<1 x i64>, array<1 x i64>)>
-//       CHECK:   llvm.extractvalue %{{.*}}[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
-//       CHECK:   llvm.extractvalue %{{.*}}[4, 1] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
-//       CHECK:   llvm.extractvalue %{{.*}}[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<2 x i64>, array<2 x i64>)>
-//       CHECK:   llvm.insertvalue %{{.*}}, %{{.*}}[0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<1 x i64>, array<1 x i64>)>
-//       CHECK:   llvm.insertvalue %{{.*}}[2] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<1 x i64>, array<1 x i64>)>
-//       CHECK:   llvm.extractvalue %{{.*}}[0] : !llvm.struct<(i64, i64, i64)>
-//       CHECK:   llvm.extractvalue %{{.*}}[1] : !llvm.struct<(i64, i64, i64)>
-//       CHECK:   llvm.insertvalue %{{.*}}[3, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<1 x i64>, array<1 x i64>)>
-//       CHECK:   llvm.insertvalue %{{.*}}[4, 0] : !llvm.struct<(ptr<f64>, ptr<f64>, i64, array<1 x i64>, array<1 x i64>)>
-
 func @reshape_static_expand(%arg0: memref<3x4x5xf32>) -> memref<1x3x4x1x5xf32> {
   // Reshapes that expand a contiguous tensor with some 1's.
   %0 = linalg.reshape %arg0 [affine_map<(i, j, k, l, m) -> (i, j)>,

diff  --git a/mlir/test/Dialect/Linalg/roundtrip.mlir b/mlir/test/Dialect/Linalg/roundtrip.mlir
index 0b3cc28d79d0..32ea93bc3c2c 100644
--- a/mlir/test/Dialect/Linalg/roundtrip.mlir
+++ b/mlir/test/Dialect/Linalg/roundtrip.mlir
@@ -85,32 +85,13 @@ func @range(%arg0: index, %arg1: index, %arg2: index) {
 
 // -----
 
-// CHECK-DAG: #[[$strided1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
-
 func @views(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) {
   %c0 = constant 0 : index
   %0 = muli %arg0, %arg0 : index
   %1 = alloc (%0) : memref<?xi8>
   %2 = linalg.range %arg0:%arg1:%arg2 : !linalg.range
   %3 = view %1[%c0][%arg0, %arg0] : memref<?xi8> to memref<?x?xf32>
-  %4 = linalg.slice %3[%2, %2] :
-    memref<?x?xf32>,
-    !linalg.range,
-    !linalg.range,
-    memref<?x?xf32>
-  %5 = linalg.slice %3[%2, %arg2] : memref<?x?xf32>,
-                                    !linalg.range,
-                                    index,
-                                    memref<?xf32, offset: ?, strides: [1]>
-  %6 = linalg.slice %3[%arg2, %2] : memref<?x?xf32>,
-                                    index,
-                                    !linalg.range,
-                                    memref<?xf32, offset: ?, strides: [1]>
-  %7 = linalg.slice %3[%arg2, %arg3] : memref<?x?xf32>,
-                                       index,
-                                       index,
-                                       memref<f32>
-  %8 = view %1[%c0][%arg0, %arg0] : memref<?xi8> to memref<?x?xvector<4x4xf32>>
+  %4 = view %1[%c0][%arg0, %arg0] : memref<?xi8> to memref<?x?xvector<4x4xf32>>
   dealloc %1 : memref<?xi8>
   return
 }
@@ -120,26 +101,6 @@ func @views(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index
 //  CHECK-NEXT:  range
 //  CHECK-NEXT:  std.view %{{.*}}[%{{.*}}][%{{.*}}] :
 //  CHECK-SAME:     memref<?xi8> to memref<?x?xf32>
-//  CHECK-NEXT:  linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
-//  CHECK-SAME:     memref<?x?xf32>,
-//  CHECK-SAME:     !linalg.range,
-//  CHECK-SAME:     !linalg.range,
-//  CHECK-SAME:     memref<?x?xf32>
-//  CHECK-NEXT:  linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
-//  CHECK-SAME:     memref<?x?xf32>,
-//  CHECK-SAME:     !linalg.range,
-//  CHECK-SAME:     index,
-//  CHECK-SAME:     memref<?xf32, #[[$strided1D]]>
-//  CHECK-NEXT:  linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
-//  CHECK-SAME:     memref<?x?xf32>,
-//  CHECK-SAME:     index,
-//  CHECK-SAME:     !linalg.range,
-//  CHECK-SAME:     memref<?xf32, #[[$strided1D]]>
-//  CHECK-NEXT:  linalg.slice %{{.*}}[%{{.*}}, %{{.*}}] :
-//  CHECK-SAME:     memref<?x?xf32>,
-//  CHECK-SAME:     index,
-//  CHECK-SAME:     index,
-//  CHECK-SAME:     memref<f32>
 //  CHECK-NEXT:  view %{{.*}}[%{{.*}}][%{{.*}}] :
 //  CHECK-SAME:     memref<?xi8> to memref<?x?xvector<4x4xf32>>
 //  CHECK-NEXT:  dealloc %{{.*}} : memref<?xi8>

diff  --git a/mlir/test/IR/core-ops.mlir b/mlir/test/IR/core-ops.mlir
index 0285cbb36e9e..ef645030bacf 100644
--- a/mlir/test/IR/core-ops.mlir
+++ b/mlir/test/IR/core-ops.mlir
@@ -24,6 +24,8 @@
 // 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)>
 
 // CHECK-LABEL: func @func_with_ops
 // CHECK-SAME: %[[ARG:.*]]: f32
@@ -803,6 +805,13 @@ func @memref_subview(%arg0 : index, %arg1 : index, %arg2 : index) {
   // CHECK: subview %{{.*}}[1] [1] [1] : memref<5x3xf32> to memref<3xf32, #[[$SUBVIEW_MAP10]]>
   %26 = subview %24[1][1][1]: memref<5x3xf32> to memref<3xf32, offset: 3, strides: [1]>
 
+  // Corner-case of 0-D rank-reducing subview with an offset.
+  // CHECK: subview %{{.*}}[1, 1] [1, 1] [1, 1] : memref<5x3xf32> to memref<f32, #[[$SUBVIEW_MAP11]]>
+  %27 = subview %24[1, 1] [1, 1] [1, 1] : memref<5x3xf32> to memref<f32, affine_map<() -> (4)>>
+
+  // CHECK: subview %{{.*}}[%{{.*}}, 1] [1, 1] [1, 1] : memref<5x3xf32> to memref<f32, #[[$SUBVIEW_MAP12]]>
+  %28 = subview %24[%arg0, 1] [1, 1] [1, 1] : memref<5x3xf32> to memref<f32, affine_map<()[s0] -> (s0)>>
+
   return
 }
 
@@ -903,9 +912,9 @@ func @subtensor(%t: tensor<8x16x4xf32>, %idx : index) {
 
 // CHECK-LABEL: func @subtensor_insert({{.*}}) {
 func @subtensor_insert(
-    %t: tensor<8x16x4xf32>, 
-    %t2: tensor<16x32x8xf32>, 
-    %t3: tensor<4x4xf32>, 
+    %t: tensor<8x16x4xf32>,
+    %t2: tensor<16x32x8xf32>,
+    %t3: tensor<4x4xf32>,
     %idx : index) {
   %c0 = constant 0 : index
   %c1 = constant 1 : index


        


More information about the Mlir-commits mailing list