forked from OSchip/llvm-project
Add a linalg.range_intersect op.
This CL adds an operation whose purpose is to encode boundary conditions directly in the view type. In particular, full/partial tile distinction can occur at the level of metadata only. This CL also adopts a Linalg_Op pattern that is similar to Std_Op. -- PiperOrigin-RevId: 248529469
This commit is contained in:
parent
090662c5f3
commit
a4317d1a59
|
@ -19,13 +19,11 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef LINALG_OPS
|
||||
#else
|
||||
|
||||
#ifdef OP_BASE
|
||||
#else
|
||||
include "mlir/IR/OpBase.td"
|
||||
#endif // OP_BASE
|
||||
|
||||
#ifdef LINALG_BASE
|
||||
#else
|
||||
#define LINALG_BASE
|
||||
|
||||
def Linalg_Dialect : Dialect {
|
||||
let name = "linalg";
|
||||
|
@ -35,8 +33,12 @@ def Linalg_Dialect : Dialect {
|
|||
def LinalgIsBufferTypePred : CPred<"$_self.isa<BufferType>()">;
|
||||
def Buffer : Type<LinalgIsBufferTypePred, "buffer">;
|
||||
|
||||
// Whether a type is a RangeType.
|
||||
def LinalgIsRangeTypePred : CPred<"$_self.isa<RangeType>()">;
|
||||
def Range : Type<LinalgIsRangeTypePred, "range">;
|
||||
|
||||
// Whether a type is a ViewType.
|
||||
def LinalgIsViewTypePred : CPred<"$_self.isa<ViewType>()">;
|
||||
def View : Type<LinalgIsViewTypePred, "view">;
|
||||
|
||||
#endif // LINALG_OPS
|
||||
#endif // LINALG_BASE
|
|
@ -20,13 +20,11 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef LINALG_OPS
|
||||
#else
|
||||
|
||||
#ifdef LINALG_BASE
|
||||
#else
|
||||
include "mlir/Linalg/IR/LinalgBase.td"
|
||||
#endif // LINALG_BASE
|
||||
|
||||
#ifdef LINALG_LIBRARY_OPS
|
||||
#else
|
||||
#define LINALG_LIBRARY_OPS
|
||||
|
||||
class LinalgParametricNativeOpTrait<string prop, string parameters> :
|
||||
NativeOpTrait<"linalg::" # prop # parameters>
|
||||
|
@ -68,7 +66,7 @@ LinalgParametricIntNativeOpTrait<"ViewRanks", ranks>
|
|||
{}
|
||||
|
||||
// Base Tablegen class for Linalg ops.
|
||||
class LinalgOp<string mnemonic, list<OpTrait> props> :
|
||||
class LinalgLibrary_Op<string mnemonic, list<OpTrait> props> :
|
||||
Op<Linalg_Dialect, mnemonic, props> {
|
||||
let arguments = (ins Variadic<View>); // default variadic builder
|
||||
let parser = [{ return parseLinalgLibraryOp(parser, result); }];
|
||||
|
@ -78,14 +76,14 @@ Op<Linalg_Dialect, mnemonic, props> {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Concrete Linalg ops.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
def DotOp : LinalgOp<"dot", [NInputsAndOutputs<2, 1>,
|
||||
def DotOp : LinalgLibrary_Op<"dot", [NInputsAndOutputs<2, 1>,
|
||||
NLoopTypes<0, 1, 0>,
|
||||
ViewRanks<[1, 1, 0]>]> {}
|
||||
def MatvecOp : LinalgOp<"matvec", [NInputsAndOutputs<2, 1>,
|
||||
def MatvecOp : LinalgLibrary_Op<"matvec", [NInputsAndOutputs<2, 1>,
|
||||
NLoopTypes<1, 1, 0>,
|
||||
ViewRanks<[2, 1, 1]>]> {}
|
||||
def MatmulOp : LinalgOp<"matmul", [NInputsAndOutputs<2, 1>,
|
||||
def MatmulOp : LinalgLibrary_Op<"matmul", [NInputsAndOutputs<2, 1>,
|
||||
NLoopTypes<2, 1, 0>,
|
||||
ViewRanks<[2, 2, 2]>]> {}
|
||||
|
||||
#endif // LINALG_OPS
|
||||
#endif // LINALG_LIBRARY_OPS
|
|
@ -19,24 +19,42 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
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
|
||||
|
||||
def BufferSizeOp :
|
||||
Op<Linalg_Dialect, "buffer_size", [NoSideEffect]>,
|
||||
Arguments<(ins Buffer)>,
|
||||
Results<(outs Index)>
|
||||
{
|
||||
let parser = [{ return parseBufferSizeOp(parser, result); }];
|
||||
let printer = [{ return printBufferSizeOp(p, *this); }];
|
||||
// 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 DimOp : Op<Linalg_Dialect, "dim", [NoSideEffect]>,
|
||||
def BufferSizeOp :
|
||||
Linalg_Op<"buffer_size", [NoSideEffect]>,
|
||||
Arguments<(ins Buffer)>,
|
||||
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 : Linalg_Op<"dim", [NoSideEffect]>,
|
||||
Arguments<(ins View:$view, APIntAttr:$index)>,
|
||||
Results<(outs Index)> {
|
||||
let summary = "dimension index operation";
|
||||
|
@ -48,12 +66,14 @@ def DimOp : Op<Linalg_Dialect, "dim", [NoSideEffect]>,
|
|||
%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(
|
||||
|
@ -65,7 +85,31 @@ def DimOp : Op<Linalg_Dialect, "dim", [NoSideEffect]>,
|
|||
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
|
|
@ -488,12 +488,12 @@ void mlir::linalg::ViewOp::print(OpAsmPrinter *p) {
|
|||
*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();
|
||||
|
@ -511,7 +511,7 @@ static ParseResult parseBufferSizeOp(OpAsmParser *parser,
|
|||
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"});
|
||||
|
@ -532,24 +532,29 @@ static ParseResult parseDimOp(OpAsmParser *parser, OperationState *result) {
|
|||
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");
|
||||
}
|
||||
|
||||
return success();
|
||||
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();
|
||||
}
|
||||
|
||||
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}
|
||||
|
|
|
@ -234,13 +234,13 @@ static SmallVector<Value *, 4> makeTiledViews(FuncBuilder *b, Location loc,
|
|||
unsigned pos2 = it - nzMap.getResults().begin();
|
||||
using edsc::op::operator+;
|
||||
using range = ValueBuilder<RangeOp>;
|
||||
using range_intersect = ValueBuilder<RangeIntersectOp>;
|
||||
ScopedContext scope(*b, loc);
|
||||
ValueHandle iv(ivs[pos2]), step(tileSizes[pos]);
|
||||
auto min = ValueHandle(extractRangePart(ranges[j], RangePart::Min));
|
||||
// zero case is important enough to fold away by special-casing.
|
||||
auto newMin = isZero(min) ? iv : min + iv;
|
||||
// TODO(ntv): intersect with current range once the operation exists.
|
||||
Value *r = range(newMin, newMin + step, step);
|
||||
Value *r = range_intersect(ranges[j], range(newMin, newMin + step, step));
|
||||
newRanges.push_back(r);
|
||||
}
|
||||
res.push_back(createOrReturnView(b, loc, viewDefiningOp, newRanges));
|
||||
|
|
|
@ -63,3 +63,10 @@ func @dim(%arg0: !linalg.view<?x?xf32>) {
|
|||
// CHECK-NEXT: %1 = linalg.buffer_alloc %0 : !linalg.buffer<f32>
|
||||
// CHECK-NEXT: linalg.buffer_dealloc %1 : !linalg.buffer<f32>
|
||||
|
||||
func @range_intersect(%arg0: !linalg.range, %arg1: !linalg.range) -> !linalg.range {
|
||||
%0 = linalg.range_intersect %arg0, %arg1 : !linalg.range
|
||||
return %0 : !linalg.range
|
||||
}
|
||||
// CHECK-LABEL: func @range_intersect(%arg0: !linalg.range, %arg1: !linalg.range) -> !linalg.range {
|
||||
// CHECK-NEXT: %0 = linalg.range_intersect %arg0, %arg1 : !linalg.range
|
||||
// CHECK-NEXT: return %0 : !linalg.range
|
||||
|
|
|
@ -32,10 +32,12 @@ func @matmul(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -45,10 +47,12 @@ func @matmul(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -58,10 +62,12 @@ func @matmul(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -73,19 +79,25 @@ func @matmul(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -106,10 +118,12 @@ func @matvec(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -119,10 +133,12 @@ func @matvec(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -136,15 +152,19 @@ func @matvec(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: inde
|
|||
// 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>
|
||||
|
||||
|
@ -164,10 +184,12 @@ func @dot(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: index)
|
|||
// 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>
|
||||
|
||||
|
@ -183,9 +205,11 @@ func @dot(%arg0: !linalg.buffer<f32>, %arg1: index, %arg2: index, %arg3: index)
|
|||
// 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>
|
||||
|
|
Loading…
Reference in New Issue