//
//===----------------------------------------------------------------------===//
+include "mlir/Linalg/IR/LinalgBase.td"
+
#ifdef LINALG_OPS
#else
+#define LINALG_OPS
-#ifdef LINALG_BASE
-#else
-include "mlir/Linalg/IR/LinalgBase.td"
-#endif // LINALG_BASE
+// Base class for Linalg dialect ops that do not correspond to library calls.
+class Linalg_Op<string mnemonic, list<OpTrait> traits = []> :
+ Op<Linalg_Dialect, mnemonic, traits> {
+ // For every linalg op, there needs to be a:
+ // * void print(OpAsmPrinter *p, ${C++ class of Op} op)
+ // * LogicalResult verify(${C++ class of Op} op)
+ // * ParseResult parse${C++ class of Op}(OpAsmParser *parser,
+ // OperationState *result)
+ // functions.
+ let printer = [{ return ::print(p, *this); }];
+ let verifier = [{ return ::verify(*this); }];
+ let parser = [{ return ::parse$cppClass(parser, result); }];
+}
def BufferSizeOp :
- Op<Linalg_Dialect, "buffer_size", [NoSideEffect]>,
+ Linalg_Op<"buffer_size", [NoSideEffect]>,
Arguments<(ins Buffer)>,
- Results<(outs Index)>
-{
- let parser = [{ return parseBufferSizeOp(parser, result); }];
- let printer = [{ return printBufferSizeOp(p, *this); }];
+ Results<(outs Index)> {
+ let summary = "buffer size operation";
+ let description = [{
+ The "linalg.buffer_size" operation takes a linalg.buffer and returns an
+ "index". For example:
+
+ %0 = linalg.buffer_size %arg0 : !linalg.buffer<f32>
+ }];
+ // Fully specified by traits.
+ let verifier = ?;
}
-def DimOp : Op<Linalg_Dialect, "dim", [NoSideEffect]>,
+def DimOp : Linalg_Op<"dim", [NoSideEffect]>,
Arguments<(ins View:$view, APIntAttr:$index)>,
Results<(outs Index)> {
let summary = "dimension index operation";
%1 = linalg.dim %0, 2 : view<?x?x?xf32>
}];
- let parser = [{ return parseDimOp(parser, result); }];
- let printer = [{ return printDimOp(p, *this); }];
- let verifier = [{ return ::verify(*this); }];
+ let verifier = [{
+ if (getIndex() >= getViewType().getRank())
+ return emitOpError("index is out of range");
+ return success();
+ }];
let builders = [OpBuilder<
- "Builder *builder, OperationState *result, Value *view," "unsigned index",
+ "Builder *builder, OperationState *result, Value *view, unsigned index",
[{
result->addOperands(view);
result->addAttribute(
unsigned getIndex() {
return getAttrOfType<IntegerAttr>("index").getValue().getZExtValue();
}
+ ViewType getViewType() { return getOperand()->getType().cast<ViewType>(); }
}];
}
+def RangeIntersectOp : Linalg_Op<"range_intersect", [NoSideEffect]>,
+ Arguments<(ins Range, Range)>,
+ Results<(outs Range)> {
+ let summary = "range intersection operation";
+ let description = [{
+ The "linalg.range_intersect" operation takes two linalg.range and returns a
+ linalg.range that represents their intersection. This assumes both steps
+ are one for now. For example:
+
+ %2 = linalg.range_intersect %0, %1 : !linalg.range
+ }];
+
+ // Fully verified by traits.
+ let verifier = ?;
+
+ let builders = [OpBuilder<
+ "Builder *builder, OperationState *result, Value *range1, Value *range2",
+ [{
+ result->addOperands({range1, range2});
+ result->types.push_back(builder->getType<RangeType>());
+ }]>];
+}
+
#endif // LINALG_OPS
\ No newline at end of file
*p << "] : " << getType();
}
-/// Buffer size prints as:
-///
-/// ``` {.mlir}
-/// %0 = linalg.buffer_size %arg0 : !linalg.buffer<f32>
-/// ```
-static void printBufferSizeOp(OpAsmPrinter *p, BufferSizeOp op) {
+///////////////////// Operations defined with Tablegen /////////////////////////
+// For such operations that do not correspond to library calls (i.e. defined in
+// LinalgOps.td), we define an overloaded `print` function and a
+// parse`className` function.
+
+static void print(OpAsmPrinter *p, BufferSizeOp op) {
*p << op.getOperationName() << " " << *op.getOperand();
p->printOptionalAttrDict(op.getAttrs());
*p << " : " << op.getOperand()->getType();
result->types));
}
-static void printDimOp(OpAsmPrinter *p, DimOp op) {
+static void print(OpAsmPrinter *p, linalg::DimOp op) {
*p << op.getOperationName() << " " << *op.getOperand() << ", "
<< op.getIndex();
p->printOptionalAttrDict(op.getAttrs(), /*elidedAttrs=*/{"index"});
parser->addTypeToList(indexType, result->types));
}
-static LogicalResult verify(linalg::DimOp op) {
- // Check that we have an integer index operand.
- auto indexAttr = op.getAttrOfType<IntegerAttr>("index");
- if (!indexAttr)
- return op.emitOpError("requires an integer attribute named 'index'");
-
- uint64_t index = indexAttr.getValue().getZExtValue();
- auto type = op.getOperand()->getType();
- if (auto viewType = type.dyn_cast<ViewType>()) {
- if (index >= viewType.getRank())
- return op.emitOpError("index is out of range");
- } else {
- return op.emitOpError("requires an operand with view type");
- }
+static void print(OpAsmPrinter *p, RangeIntersectOp op) {
+ *p << op.getOperationName() << " " << *op.getOperand(0) << ", "
+ << *op.getOperand(1);
+ p->printOptionalAttrDict(op.getAttrs());
+ *p << " : " << op.getOperand(0)->getType();
+}
- return success();
+static ParseResult parseRangeIntersectOp(OpAsmParser *parser,
+ OperationState *result) {
+ SmallVector<OpAsmParser::OperandType, 2> ops;
+ Type type;
+ return failure(parser->parseOperandList(ops) ||
+ parser->parseOptionalAttributeDict(result->attributes) ||
+ parser->parseColonType(type) ||
+ parser->resolveOperands(ops, type, result->operands) ||
+ parser->addTypeToList(type, result->types));
}
+/////// Operations corresponding to library calls defined with Tablegen ////////
+// For such operations correspond to library calls (i.e. defined in
+// LinalgLibraryOps.td), we define an overloaded `print` function and a
+// parse`className` function.
+
// A LinalgLibraryOp prints as:
//
// ```{.mlir}
// TILE-2-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<?x?xf32>
// TILE-2: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg1) step 2 {
// TILE-2-NEXT: %[[a:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-2-NEXT: %[[ra:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[ra0:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[ra:.*]] = linalg.range_intersect %{{.}}, %[[ra0]] : !linalg.range
// TILE-2-NEXT: %[[sAi:.*]] = linalg.slice %[[A]][%[[ra]], %2] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-2-NEXT: %[[c:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-2-NEXT: %[[rc:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[rc0:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[rc:.*]] = linalg.range_intersect %{{.}}, %[[rc0]] : !linalg.range
// TILE-2-NEXT: %[[sCi:.*]] = linalg.slice %[[C]][%[[rc]], %1] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-2-NEXT: linalg.matmul(%[[sAi]], %[[B]], %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
// TILE-02-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<?x?xf32>
// TILE-02: affine.for %i0 = #[[ID]](%c0_0) to #[[ID]](%arg2) step 2 {
// TILE-02-NEXT: %[[b:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-02-NEXT: %[[rb:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-02-NEXT: %[[rb0:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-02-NEXT: %[[rb:.*]] = linalg.range_intersect %{{.}}, %[[rb0]] : !linalg.range
// TILE-02-NEXT: %[[sBj:.*]] = linalg.slice %[[B]][%{{.*}}, %[[rb]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-02-NEXT: %[[c:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-02-NEXT: %[[rc:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-02-NEXT: %[[rc0:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-02-NEXT: %[[rc:.*]] = linalg.range_intersect %{{.}}, %[[rc0]] : !linalg.range
// TILE-02-NEXT: %[[sCj:.*]] = linalg.slice %[[C]][%{{.*}}, %[[rc]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-02-NEXT: linalg.matmul(%[[A]], %[[sBj]], %[[sCj]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
// TILE-002-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<?x?xf32>
// TILE-002: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg3) step 2 {
// TILE-002-NEXT: %[[a:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-002-NEXT: %[[ra:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-002-NEXT: %[[ra0:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-002-NEXT: %[[ra:.*]] = linalg.range_intersect %{{.}}, %[[ra0]] : !linalg.range
// TILE-002-NEXT: %[[sAj:.*]] = linalg.slice %[[A]][%{{.*}}, %[[ra]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-002-NEXT: %[[b:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-002-NEXT: %[[rb:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-002-NEXT: %[[rb0:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-002-NEXT: %[[rb:.*]] = linalg.range_intersect %{{.}}, %[[rb0]] : !linalg.range
// TILE-002-NEXT: %[[sBj:.*]] = linalg.slice %[[B]][%[[rb]], %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-002-NEXT: linalg.matmul(%[[sAj]], %[[sBj]], %[[C]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
// TILE-234-NEXT: affine.for %i1 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg2) step 3 {
// TILE-234-NEXT: affine.for %i2 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg3) step 4 {
// TILE-234-NEXT: %[[ai:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-234-NEXT: %[[rai:.*]] = linalg.range %i0:%[[ai]]:%c2{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rai0:.*]] = linalg.range %i0:%[[ai]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rai:.*]] = linalg.range_intersect %{{.}}, %[[rai0]] : !linalg.range
// TILE-234-NEXT: %[[ak:.*]] = affine.apply #[[UB2]](%i2)
-// TILE-234-NEXT: %[[rak:.*]] = linalg.range %i2:%[[ak]]:%c4{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rak0:.*]] = linalg.range %i2:%[[ak]]:%c4{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rak:.*]] = linalg.range_intersect %{{.}}, %[[rak0]] : !linalg.range
// TILE-234-NEXT: %[[sAik:.*]] = linalg.slice %[[A]][%[[rai]], %[[rak]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-234-NEXT: %[[bk:.*]] = affine.apply #[[UB2]](%i2)
-// TILE-234-NEXT: %[[rbk:.*]] = linalg.range %i2:%[[bk]]:%c4{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rbk0:.*]] = linalg.range %i2:%[[bk]]:%c4{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rbk:.*]] = linalg.range_intersect %{{.}}, %[[rbk0]] : !linalg.range
// TILE-234-NEXT: %[[bj:.*]] = affine.apply #[[UB1]](%i1)
-// TILE-234-NEXT: %[[rbj:.*]] = linalg.range %i1:%[[bj]]:%c3{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rbj0:.*]] = linalg.range %i1:%[[bj]]:%c3{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rbj:.*]] = linalg.range_intersect %{{.}}, %[[rbj0]] : !linalg.range
// TILE-234-NEXT: %[[sBkj:.*]] = linalg.slice %[[B]][%[[rbk]], %[[rbj]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-234-NEXT: %[[ci:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-234-NEXT: %[[rci:.*]] = linalg.range %i0:%[[ci]]:%c2{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rci0:.*]] = linalg.range %i0:%[[ci]]:%c2{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rci:.*]] = linalg.range_intersect %{{.}}, %[[rci0]] : !linalg.range
// TILE-234-NEXT: %[[cj:.*]] = affine.apply #[[UB1]](%i1)
-// TILE-234-NEXT: %[[rcj:.*]] = linalg.range %i1:%[[cj]]:%c3{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rcj0:.*]] = linalg.range %i1:%[[cj]]:%c3{{.*}} : !linalg.range
+// TILE-234-NEXT: %[[rcj:.*]] = linalg.range_intersect %{{.}}, %[[rcj0]] : !linalg.range
// TILE-234-NEXT: %[[sCij:.*]] = linalg.slice %[[C]][%[[rci]], %[[rcj]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-234-NEXT: linalg.matmul(%[[sAik]], %[[sBkj]], %[[sCij]]) : !linalg.view<?x?xf32>, !linalg.view<?x?xf32>, !linalg.view<?x?xf32>
// TILE-2-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<?xf32>
// TILE-2: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg1) step 2 {
// TILE-2-NEXT: %[[a:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-2-NEXT: %[[ra:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[ra0:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[ra:.*]] = linalg.range_intersect %{{.}}, %[[ra0]] : !linalg.range
// TILE-2-NEXT: %[[sAi:.*]] = linalg.slice %[[A]][%[[ra]], %{{.*}}] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-2-NEXT: %[[c:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-2-NEXT: %[[rc:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[rc0:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[rc:.*]] = linalg.range_intersect %{{.}}, %[[rc0]] : !linalg.range
// TILE-2-NEXT: %[[sCi:.*]] = linalg.slice %[[C]][%[[rc]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-2-NEXT: linalg.matvec(%[[sAi]], %[[B]], %[[sCi]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
// TILE-02-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<?xf32>
// TILE-02: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg2) step 2 {
// TILE-02-NEXT: %[[a:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-02-NEXT: %[[ra:.*]] = linalg.range %i0:%[[a]]:%c2{{.*}} : !linalg.range
+// TILE-02-NEXT: %[[ra0:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-02-NEXT: %[[ra:.*]] = linalg.range_intersect %{{.}}, %[[ra0]] : !linalg.range
// TILE-02-NEXT: %[[sAj:.*]] = linalg.slice %[[A]][%{{.*}}, %[[ra]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-02-NEXT: %[[b:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-02-NEXT: %[[rb:.*]] = linalg.range %i0:%[[b]]:%c2{{.*}} : !linalg.range
+// TILE-02-NEXT: %[[rb0:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-02-NEXT: %[[rb:.*]] = linalg.range_intersect %{{.}}, %[[rb0]] : !linalg.range
// TILE-02-NEXT: %[[sBj:.*]] = linalg.slice %[[B]][%[[rb]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-02-NEXT: linalg.matvec(%[[sAj]], %[[sBj]], %[[C]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
// TILE-234: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg1) step 2 {
// TILE-234-NEXT: affine.for %i1 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg2) step 3 {
// TILE-234-NEXT: %[[ai:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-234-NEXT: %[[rai:.*]] = linalg.range %i0:%[[ai]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rai0:.*]] = linalg.range %i0:%[[ai]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rai:.*]] = linalg.range_intersect %{{.}}, %[[rai0]] : !linalg.range
// TILE-234-NEXT: %[[aj:.*]] = affine.apply #[[UB1]](%i1)
-// TILE-234-NEXT: %[[raj:.*]] = linalg.range %i1:%[[aj]]:%c3 : !linalg.range
+// TILE-234-NEXT: %[[raj0:.*]] = linalg.range %i1:%[[aj]]:%c3 : !linalg.range
+// TILE-234-NEXT: %[[raj:.*]] = linalg.range_intersect %{{.}}, %[[raj0]] : !linalg.range
// TILE-234-NEXT: %[[sAij:.*]] = linalg.slice %[[A]][%[[rai]], %[[raj]]] : !linalg.view<?x?xf32>, !linalg.range, !linalg.range, !linalg.view<?x?xf32>
// TILE-234-NEXT: %[[b:.*]] = affine.apply #[[UB1]](%i1)
-// TILE-234-NEXT: %[[rb:.*]] = linalg.range %i1:%[[b]]:%c3 : !linalg.range
+// TILE-234-NEXT: %[[rb0:.*]] = linalg.range %i1:%[[b]]:%c3 : !linalg.range
+// TILE-234-NEXT: %[[rb:.*]] = linalg.range_intersect %{{.}}, %[[rb0]] : !linalg.range
// TILE-234-NEXT: %[[sB:.*]] = linalg.slice %[[B]][%[[rb]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-234-NEXT: %[[c:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-234-NEXT: %[[rc:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rc0:.*]] = linalg.range %i0:%[[c]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rc:.*]] = linalg.range_intersect %{{.}}, %[[rc0]] : !linalg.range
// TILE-234-NEXT: %[[sC:.*]] = linalg.slice %[[C]][%[[rc]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-234-NEXT: linalg.matvec(%[[sAij]], %[[sB]], %[[sC]]) : !linalg.view<?x?xf32>, !linalg.view<?xf32>, !linalg.view<?xf32>
// TILE-2-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<f32>
// TILE-2: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg1) step 2 {
// TILE-2-NEXT: %[[a:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-2-NEXT: %[[ra:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[ra0:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[ra:.*]] = linalg.range_intersect %{{.}}, %[[ra0]] : !linalg.range
// TILE-2-NEXT: %[[sAi:.*]] = linalg.slice %[[A]][%[[ra]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-2-NEXT: %[[b:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-2-NEXT: %[[rb:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[rb0:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-2-NEXT: %[[rb:.*]] = linalg.range_intersect %{{.}}, %[[rb0]] : !linalg.range
// TILE-2-NEXT: %[[sBi:.*]] = linalg.slice %[[B]][%[[rb]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-2-NEXT: linalg.dot(%[[sAi]], %[[sBi]], %[[C]]) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>
// TILE-234-NEXT: %[[C:.*]] = linalg.view %arg0[{{.*}}] : !linalg.view<f32>
// TILE-234: affine.for %i0 = #[[ID]](%c0{{.*}}) to #[[ID]](%arg1) step 2 {
// TILE-234-NEXT: %[[a:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-234-NEXT: %[[ra:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[ra0:.*]] = linalg.range %i0:%[[a]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[ra:.*]] = linalg.range_intersect %{{.}}, %[[ra0]] : !linalg.range
// TILE-234-NEXT: %[[sA:.*]] = linalg.slice %[[A]][%[[ra]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-234-NEXT: %[[b:.*]] = affine.apply #[[UB0]](%i0)
-// TILE-234-NEXT: %[[rb:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rb0:.*]] = linalg.range %i0:%[[b]]:%c2 : !linalg.range
+// TILE-234-NEXT: %[[rb:.*]] = linalg.range_intersect %{{.}}, %[[rb0]] : !linalg.range
// TILE-234-NEXT: %[[sB:.*]] = linalg.slice %[[B]][%[[rb]]] : !linalg.view<?xf32>, !linalg.range, !linalg.view<?xf32>
// TILE-234-NEXT: linalg.dot(%[[sA]], %[[sB]], %[[C]]) : !linalg.view<?xf32>, !linalg.view<?xf32>, !linalg.view<f32>