summaryrefslogtreecommitdiffstats
path: root/mlir/include
diff options
context:
space:
mode:
authorNicolas Vasilache <ntv@google.com>2019-12-19 13:16:59 -0800
committerA. Unique TensorFlower <gardener@tensorflow.org>2019-12-19 13:17:35 -0800
commit6685282253c33fa2c5dc7487b04fc92d47082e78 (patch)
tree8a84e44d685f7c6664f8307b96a7fb4b88affdd3 /mlir/include
parent1d798b1d27fb150de47266b009a414db46344f5a (diff)
downloadbcm5719-llvm-6685282253c33fa2c5dc7487b04fc92d47082e78.tar.gz
bcm5719-llvm-6685282253c33fa2c5dc7487b04fc92d47082e78.zip
Restructure and update Linalg ODS and documentation - NFC
This CL allows specifying an additional name for specifying the .td file that is used to generate the doc for a dialect. This is necessary for a dialect like Linalg which has different "types" of ops that are used in different contexts. This CL also restructures the Linalg documentation and renames LinalgLibraryOps -> LinalgStructuredOps but is otherwise NFC. PiperOrigin-RevId: 286450414
Diffstat (limited to 'mlir/include')
-rw-r--r--mlir/include/mlir/Dialect/AffineOps/CMakeLists.txt2
-rw-r--r--mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt2
-rw-r--r--mlir/include/mlir/Dialect/GPU/CMakeLists.txt2
-rw-r--r--mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt4
-rw-r--r--mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt15
-rw-r--r--mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td2
-rw-r--r--mlir/include/mlir/Dialect/Linalg/IR/LinalgDoc.td32
-rw-r--r--mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h4
-rw-r--r--mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td625
-rw-r--r--mlir/include/mlir/Dialect/Linalg/Transforms/LinalgTransformPatterns.td2
-rw-r--r--mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt2
-rw-r--r--mlir/include/mlir/Dialect/QuantOps/CMakeLists.txt2
-rw-r--r--mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt2
-rw-r--r--mlir/include/mlir/Dialect/VectorOps/CMakeLists.txt2
14 files changed, 677 insertions, 21 deletions
diff --git a/mlir/include/mlir/Dialect/AffineOps/CMakeLists.txt b/mlir/include/mlir/Dialect/AffineOps/CMakeLists.txt
index 8f812b39593..7339bcc9dcf 100644
--- a/mlir/include/mlir/Dialect/AffineOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/AffineOps/CMakeLists.txt
@@ -1 +1 @@
-add_mlir_dialect(AffineOps)
+add_mlir_dialect(AffineOps AffineOps)
diff --git a/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt b/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
index a8fb5e08ee5..484230778b3 100644
--- a/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/FxpMathOps/CMakeLists.txt
@@ -1 +1 @@
-add_mlir_dialect(FxpMathOps)
+add_mlir_dialect(FxpMathOps FxpMathOps)
diff --git a/mlir/include/mlir/Dialect/GPU/CMakeLists.txt b/mlir/include/mlir/Dialect/GPU/CMakeLists.txt
index bdb5dec79b9..fd85b5bcfbf 100644
--- a/mlir/include/mlir/Dialect/GPU/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/GPU/CMakeLists.txt
@@ -1 +1 @@
-add_mlir_dialect(GPUOps)
+add_mlir_dialect(GPUOps GPUOps)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 4ecc71aef08..fa68eff91b0 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -5,8 +5,8 @@ mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
add_public_tablegen_target(MLIRLLVMOpsIncGen)
-add_mlir_dialect(NVVMOps)
-add_mlir_dialect(ROCDLOps)
+add_mlir_dialect(NVVMOps NVVMOps)
+add_mlir_dialect(ROCDLOps ROCDLOps)
set(LLVM_TARGET_DEFINITIONS LLVMOps.td)
mlir_tablegen(LLVMConversions.inc -gen-llvmir-conversions)
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
index 2a883a138a5..269729bc644 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
@@ -1,7 +1,8 @@
-add_mlir_dialect(LinalgOps)
-set(LLVM_TARGET_DEFINITIONS LinalgLibraryOps.td)
-mlir_tablegen(LinalgLibraryOps.h.inc -gen-op-decls)
-mlir_tablegen(LinalgLibraryOps.cpp.inc -gen-op-defs)
-mlir_tablegen(LinalgLibraryOpInterfaces.h.inc -gen-op-interface-decls)
-mlir_tablegen(LinalgLibraryOpInterfaces.cpp.inc -gen-op-interface-defs)
-add_public_tablegen_target(MLIRLinalgLibraryOpsIncGen)
+add_mlir_dialect(LinalgOps LinalgDoc)
+set(LLVM_TARGET_DEFINITIONS LinalgStructuredOps.td)
+mlir_tablegen(LinalgStructuredOps.h.inc -gen-op-decls)
+mlir_tablegen(LinalgStructuredOps.cpp.inc -gen-op-defs)
+mlir_tablegen(LinalgStructuredOpsInterfaces.h.inc -gen-op-interface-decls)
+mlir_tablegen(LinalgStructuredOpsInterfaces.cpp.inc -gen-op-interface-defs)
+add_public_tablegen_target(MLIRLinalgStructuredOpsIncGen)
+
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td
index edc81250aae..4e77b0ac0a8 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgBase.td
@@ -117,6 +117,4 @@ def Linalg_Dialect : Dialect {
def LinalgIsRangeTypePred : CPred<"$_self.isa<RangeType>()">;
def Range : Type<LinalgIsRangeTypePred, "range">;
-// TODO(ntv): inject the doc for LinalgLibraryOps.td here.
-
#endif // LINALG_BASE
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgDoc.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgDoc.td
new file mode 100644
index 00000000000..a3163f50476
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgDoc.td
@@ -0,0 +1,32 @@
+//===- LinalgDoc.td - Linalg documentation -----------------*- tablegen -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+//
+// This documentation files exists to circumvent limitations on mixing different
+// .td files in cases one does not want to have all ops belong to the same
+// logical unit. This file should only include other .td files only and be used
+// for the purpose of generating documentation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LINALG_DOC
+#define LINALG_DOC
+
+include "mlir/Dialect/Linalg/IR/LinalgBase.td"
+include "mlir/Dialect/Linalg/IR/LinalgOps.td"
+include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.td"
+
+#endif // LINALG_DOC
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h
index 2226b5ee6e4..c5f1f01d0c7 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.h
@@ -78,13 +78,13 @@ std::string generateLibraryCallName(Operation *op);
/// Only permutation maps are currently supported.
SmallVector<AffineMap, 4> loopToOperandRangesMaps(Operation *op);
-#include "mlir/Dialect/Linalg/IR/LinalgLibraryOpInterfaces.h.inc"
+#include "mlir/Dialect/Linalg/IR/LinalgStructuredOpsInterfaces.h.inc"
#define GET_OP_CLASSES
#include "mlir/Dialect/Linalg/IR/LinalgOps.h.inc"
#define GET_OP_CLASSES
-#include "mlir/Dialect/Linalg/IR/LinalgLibraryOps.h.inc"
+#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.h.inc"
} // namespace linalg
} // namespace mlir
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td
new file mode 100644
index 00000000000..75b63c93cd8
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td
@@ -0,0 +1,625 @@
+//===- LinalgStructuredOps.td - Linalg dialect library ops -*- tablegen -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+//
+// This is the operation definition file for structured operations on buffers
+// that correspond to underlying library calls (e.g. BLAS).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LINALG_STRUCTURED_OPS
+#define LINALG_STRUCTURED_OPS
+
+include "mlir/Dialect/AffineOps/AffineOpsBase.td"
+include "mlir/Dialect/Linalg/IR/LinalgBase.td"
+
+// The Linalg `NInputs` trait provides the API for ops that are known
+// to have a specified number of inputs, all passed as operands.
+// See Linalg/LinalgTraits.h for implementation details an usage.
+class NInputs<int args_in> :
+ NativeOpTrait<"linalg::NInputs<" # !cast<string>(args_in) # ">::Impl"> {}
+
+// The Linalg `NOutputs` trait provides the API for ops that are known
+// to have a specified number of outputs, all passed as operands.
+// See Linalg/LinalgTraits.h for implementation details an usage.
+class NOutputs<int args_out> :
+ NativeOpTrait<"linalg::NOutputs<" # !cast<string>(args_out) # ">::Impl"> {}
+
+def ViewTraits : NativeOpTrait<"linalg::ViewTraits">;
+
+// The linalg 'LinalgStructuredInterface' provides access to the 'LinalgOp'
+// interface.
+def LinalgStructuredInterface : OpInterface<"LinalgOp"> {
+ let methods = [
+ InterfaceMethod<
+ "Query the number of inputs from the current operation.",
+ "unsigned", "getNumInputs"
+ >,
+ InterfaceMethod<
+ "Query the number of outputs from the current operation.",
+ "unsigned", "getNumOutputs"
+ >,
+ InterfaceMethod<
+ "Query the number of inputs and outputs from the current operation.",
+ "unsigned", "getNumInputsAndOutputs"
+ >,
+ InterfaceMethod<
+ "Query the input operands from the current operation.",
+ "Operation::operand_range", "getInputs"
+ >,
+ InterfaceMethod<
+ "Query the output operands from the current operation.",
+ "Operation::operand_range", "getOutputs"
+ >,
+ InterfaceMethod<
+ "Query the input and output operands from the current operation.",
+ "Operation::operand_range", "getInputsAndOutputs"
+ >,
+ InterfaceMethod<
+ "Query the iterator types attribute within the current operation.",
+ "ArrayAttr", "iterator_types"
+ >,
+ InterfaceMethod<
+ "Query the indexing maps attribute within the current operation.",
+ "ArrayAttr", "indexing_maps"
+ >,
+ InterfaceMethod<
+ "Query the number of parallel loops within the current operation.",
+ "unsigned", "getNumParallelLoops"
+ >,
+ InterfaceMethod<
+ "Query the number of reduction loops within the current operation.",
+ "unsigned", "getNumReductionLoops"
+ >,
+ InterfaceMethod<
+ "Query the number of window loops within the current operation.",
+ "unsigned", "getNumWindowLoops"
+ >,
+ InterfaceMethod<
+ "Query the number of loops within the current operation.",
+ "unsigned", "getNumLoops">,
+ InterfaceMethod<"Query the input view at the given index.",
+ "Value *", "getInput", (ins "unsigned":$i)
+ >,
+ InterfaceMethod<"Query the output view at the given index.",
+ "Value *", "getOutput", (ins "unsigned":$i)
+ >,
+ InterfaceMethod<[{
+ Query the index of the given input value, or `None` if the value is not
+ an input.
+ }],
+ "llvm::Optional<unsigned>", "getIndexOfInput", (ins "Value *":$view)
+ >,
+ InterfaceMethod<[{
+ Query the index of the given view value, or `None` if the value is not
+ an view.
+ }],
+ "llvm::Optional<unsigned>", "getIndexOfOutput", (ins "Value *":$view)
+ >,
+ InterfaceMethod<[{
+ Query the type of the input view at the given index.
+ }], "MemRefType", "getInputViewType", (ins "unsigned":$i)>,
+ InterfaceMethod<[{
+ Query the type of the output view at the given index.
+ }], "MemRefType", "getOutputViewType", (ins "unsigned":$i)>,
+
+ StaticInterfaceMethod<[{
+ Create an operation of the current type with the given location,
+ operands, and attributes.
+ }],
+ "Operation *", "create",
+ (ins "OpBuilder &":$builder, "Location":$loc,
+ "ValueRange":$operands,
+ "ArrayRef<NamedAttribute>":$attributes), [{
+ return builder.create<ConcreteOp>(loc, ArrayRef<Type>{}, operands,
+ attributes);
+ }]
+ >,
+
+ /// Clone an operation with the given location and operands. This is used to
+ /// abstract away the optional underlying region creation.
+ InterfaceMethod<[{
+ Clone the current operation with the given location and operands. This
+ is used to abstract away the optional underlying region creation.
+ }],
+ "Operation *", "clone",
+ (ins "OpBuilder &":$b, "Location":$loc, "ValueRange":$operands), [{
+ BlockAndValueMapping map;
+ unsigned numRegions = op.getOperation()->getNumRegions();
+ Operation *res = create(b, loc, operands, op.getAttrs());
+ assert(res->getNumRegions() == numRegions && "inconsistent # regions");
+ for (unsigned ridx = 0; ridx < numRegions; ++ridx)
+ op.getOperation()->getRegion(ridx).cloneInto(
+ &res->getRegion(ridx), map);
+ return res;
+ }]
+ >
+ ];
+}
+
+// Base Tablegen class for Linalg ops.
+// Linalg ops that correspond to library calls operate on linalg::View as their
+// first operands. These may be optionally followed by non-view operands
+// depending on the specific Linalg op.
+class LinalgStructuredBase_Op<string mnemonic, list<OpTrait> props>
+ : Op<Linalg_Dialect, mnemonic,
+ !listconcat(props, [ViewTraits, LinalgStructuredInterface])> {
+ let parser = [{ return parseLinalgStructuredOp(parser, result); }];
+ let printer = [{ printLinalgStructuredOp(p, *this); }];
+}
+
+class LinalgStructured_Op<string mnemonic, list<OpTrait> props>
+ : LinalgStructuredBase_Op<mnemonic, props> {
+ code libraryCallName = [{
+ std::string getLibraryCallName() {
+ return generateLibraryCallName(getOperation());
+ }
+ }];
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Concrete Linalg ops.
+////////////////////////////////////////////////////////////////////////////////
+def CopyOp : LinalgStructured_Op<"copy", [NInputs<1>, NOutputs<1>]> {
+ let description = [{
+ Copies the data in the input view into the output view.
+
+ Usage:
+ ```mlir
+ linalg.copy(%arg0, %arg1) : memref<?xf32, stride_specification>,
+ memref<?xf32, stride_specification>
+ ```
+
+ One possible lowering to loop form is:
+ ```mlir
+ %0 = linalg.dim %arg0, 0 : index
+ loop.for %i0 = %c0 to %0 step %c1 {
+ %1 = linalg.load %arg0[%i0] : memref<?xf32, stride_specification>
+ linalg.store %1, %arg1[%i0] : memref<?xf32, stride_specification>
+ }
+ ```
+
+ Optionally, can take `input_permutation` and `output_permutation` attributes
+ to reorder the dimensions of the input and output views.
+
+ Usage:
+ ```mlir
+ linalg.copy(%arg0, %arg1) {inputPermutation : (i, j, k) -> (i, k, j),
+ outputPermutation : (i, j, k) -> (k, j, i)} :
+ memref<?x?x?xf32, stride_specification>,
+ memref<?x?x?xf32, stride_specification>
+ ```
+
+ One possible lowering to loop form is:
+ ```mlir
+ %0 = linalg.dim %arg0, 0
+ %1 = linalg.dim %arg0, 1
+ %2 = linalg.dim %arg0, 2
+ loop.for %i0 = %c0 to %{{.*}} step %c1 {
+ loop.for %i1 = %c0 to %{{.*}} step %c1 {
+ loop.for %i2 = %c0 to %{{.*}} step %c1 {
+ %3 = linalg.load %arg0[%i0, %i2, %i1] :
+ memref<?x?x?xf32, stride_specification>
+ linalg.store %3, %arg1[%i2, %i1, %i0] :
+ memref<?x?x?xf32, stride_specification>
+ ```
+
+ The views are expected to be compatible for correctness but this is not
+ enforced at the moment.
+ }];
+ let arguments = (ins
+ AnyStridedMemRef:$input,
+ AnyStridedMemRef:$output,
+ OptionalAttr<AffineMapAttr>:$inputPermutation,
+ OptionalAttr<AffineMapAttr>:$outputPermutation);
+ // TODO(ntv) this should go away once the usage of OptionalAttr triggers
+ // emission of builders with default arguments left unspecified.
+ let builders = [OpBuilder<
+ "Builder *builder, OperationState &result, Value *input, Value *output", [{
+ return build(
+ builder, result, input, output, AffineMapAttr(), AffineMapAttr());
+ }]>];
+ let extraClassDeclaration = libraryCallName # [{
+ ArrayAttr indexing_maps();
+
+ ArrayAttr iterator_types() {
+ unsigned nPar = input()->getType().cast<ShapedType>().getRank();
+ MLIRContext *ctx = getContext();
+ SmallVector<Attribute, 8> iters(
+ nPar, StringAttr::get(getParallelIteratorTypeName(), ctx));
+ return ArrayAttr::get(iters, ctx);
+ }
+ }];
+ let verifier = [{ return ::verify(*this); }];
+}
+
+def FillOp : LinalgStructured_Op<"fill", [NInputs<0>, NOutputs<1>]> {
+ let arguments = (ins AnyStridedMemRef:$input,
+ AnyTypeOf<[AnyFloat, AnyInteger, AnyVector]>:$value);
+ let extraClassDeclaration = libraryCallName # [{
+ ArrayAttr indexing_maps();
+
+ ArrayAttr iterator_types() {
+ unsigned nPar = input()->getType().cast<ShapedType>().getRank();
+ MLIRContext *ctx = getContext();
+ SmallVector<Attribute, 8> iters(
+ nPar, StringAttr::get(getParallelIteratorTypeName(), ctx));
+ return ArrayAttr::get(iters, ctx);
+ }
+ }];
+ let verifier = [{ return ::verify(*this); }];
+}
+
+def DotOp : LinalgStructured_Op<"dot", [NInputs<2>, NOutputs<1>]> {
+ let arguments = (ins AnyStridedMemRefOfRank<1>,
+ AnyStridedMemRefOfRank<1>,
+ AnyStridedMemRefOfRank<0>);
+ let extraClassDeclaration = libraryCallName # [{
+ ArrayAttr indexing_maps();
+
+ ArrayAttr iterator_types() {
+ MLIRContext *ctx = getContext();
+ return ArrayAttr::get(
+ StringAttr::get(getReductionIteratorTypeName(), ctx), ctx);
+ }
+ }];
+}
+
+def MatvecOp : LinalgStructured_Op<"matvec", [NInputs<2>, NOutputs<1>]> {
+ let arguments = (ins AnyStridedMemRefOfRank<2>,
+ AnyStridedMemRefOfRank<1>,
+ AnyStridedMemRefOfRank<1>);
+ let extraClassDeclaration = libraryCallName # [{
+ ArrayAttr indexing_maps();
+
+ ArrayAttr iterator_types() {
+ MLIRContext *ctx = getContext();
+ Attribute iters[2]{
+ StringAttr::get(getParallelIteratorTypeName(), ctx),
+ StringAttr::get(getReductionIteratorTypeName(), ctx)};
+ return ArrayAttr::get(iters, ctx);
+ }
+ }];
+}
+
+def MatmulOp : LinalgStructured_Op<"matmul", [NInputs<2>, NOutputs<1>]> {
+ let arguments = (ins AnyStridedMemRefOfRank<2>,
+ AnyStridedMemRefOfRank<2>,
+ AnyStridedMemRefOfRank<2>);
+ let extraClassDeclaration = libraryCallName # [{
+ ArrayAttr indexing_maps();
+
+ ArrayAttr iterator_types() {
+ MLIRContext *ctx = getContext();
+ Attribute iters[3]{
+ StringAttr::get(getParallelIteratorTypeName(), ctx),
+ StringAttr::get(getParallelIteratorTypeName(), ctx),
+ StringAttr::get(getReductionIteratorTypeName(), ctx)};
+ return ArrayAttr::get(iters, ctx);
+ }
+ }];
+}
+
+def ConvOp : LinalgStructured_Op<"conv", [NInputs<2>, NOutputs<1>]> {
+ let description = [{
+ Generic n-D convolution as described in the TF documentation:
+ https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/nn/convolution
+
+ ```
+ output[b, x[0], ..., x[N-1], k] =
+ sum_{z[0], ..., z[N-1], q}
+ filter[z[0], ..., z[N-1], q, k] *
+ padded_input[b,
+ x[0] * strides[0] + dilation_rate[0] * z[0],
+ ...,
+ x[N-1] * strides[N-1] + dilation_rate[N-1] * z[N-1],
+ q]
+ ```
+ }];
+
+ // TODO(ntv) padding.
+ // Following the TF source of truth above, strides and dilations are integer
+ // attributes of the same rank as the number of window dimensions.
+ let arguments = (ins AnyStridedMemRef:$filter, AnyStridedMemRef:$input,
+ AnyStridedMemRef:$output,
+ OptionalAttr<I64ArrayAttr>:$strides,
+ OptionalAttr<I64ArrayAttr>:$dilations);
+ let extraClassDeclaration = libraryCallName # [{
+ // TODO(ntv) extend to support more than 1 dimensions and potentially
+ // grouping too.
+ unsigned getNumBatchDimensions() { return 1; }
+ unsigned getNumInputFeatureDimensions() { return 1; }
+ unsigned getNumOutputFeatureDimensions() { return 1; }
+
+ ArrayAttr indexing_maps();
+
+ ArrayAttr iterator_types() {
+ // Outer parallel loops are always the number of output dimensions; i.e.
+ // [ b, xs, q] in the TF notation above.
+ unsigned nPar = getOutputViewType(0).getRank();
+ unsigned nRed = getNumInputFeatureDimensions();
+ // Window loops are a special kind of reduction that is never tiled or
+ // parallelized across; i.e. [zs] in the TF notation above whose number
+ // match `xs` (i.e. 1 window loop per "image" dimension).
+ // This may evolve in the future.
+ unsigned nWin =
+ nPar - getNumBatchDimensions() - getNumInputFeatureDimensions();
+ MLIRContext *ctx = getContext();
+ SmallVector<Attribute, 8> iters(
+ nPar, StringAttr::get(getParallelIteratorTypeName(), ctx));
+ iters.reserve(nPar + nRed + nWin);
+ iters.append(nRed, StringAttr::get(getReductionIteratorTypeName(), ctx));
+ iters.append(nWin, StringAttr::get(getWindowIteratorTypeName(), ctx));
+ return ArrayAttr::get(iters, ctx);
+ }
+
+ int64_t getStride(unsigned i) {
+ assert(i < getNumWindowLoops());
+ if (!strides().hasValue()) return 1;
+ return strides()->getValue()[i]
+ .cast<IntegerAttr>().getValue().getSExtValue();
+ }
+
+ int64_t getDilation(unsigned i) {
+ assert(i < getNumWindowLoops());
+ if (!dilations().hasValue()) return 1;
+ return dilations()->getValue()[i]
+ .cast<IntegerAttr>().getValue().getSExtValue();
+ }
+ }];
+ let verifier = [{ return ::verify(*this); }];
+}
+
+class GenericOpBase<string mnemonic> : LinalgStructuredBase_Op<mnemonic, []> {
+ let arguments = (ins Variadic<AnyStridedMemRef>:$views,
+ I64Attr:$args_in,
+ I64Attr:$args_out,
+ AffineMapArrayAttr:$indexing_maps,
+ ArrayAttr:$iterator_types,
+ OptionalAttr<StrAttr>:$doc,
+ OptionalAttr<FlatSymbolRefAttr>:$fun,
+ OptionalAttr<StrAttr>:$library_call);
+ let regions = (region AnyRegion:$region);
+ let extraClassDeclaration = [{
+ SmallVector<StringRef, 8> linalgTraitAttrNames() {
+ return SmallVector<StringRef, 8>{
+ getArgsInAttrName(), getArgsOutAttrName(), getDocAttrName(),
+ getFunAttrName(), getIndexingMapsAttrName(), getLibraryCallAttrName(),
+ getIteratorTypesAttrName()
+ };
+ }
+ unsigned getNumInputs() { return args_in().getSExtValue(); }
+ unsigned getNumOutputs() { return args_out().getSExtValue(); }
+ FuncOp getFunction() {
+ auto moduleOp = getParentOfType<ModuleOp>();
+ return fun().hasValue() ?
+ moduleOp.lookupSymbol<FuncOp>(fun().getValue()) : FuncOp();
+ }
+ StringRef getLibraryCallName() {
+ return library_call().hasValue() ? library_call().getValue() : "";
+ }
+ AffineMap getIndexingMap(unsigned i) {
+ assert(i < getNumInputsAndOutputs());
+ return indexing_maps().getValue()[i].cast<AffineMapAttr>().getValue();
+ }
+ AffineMap getInputIndexingMap(unsigned i) {
+ assert(i < getNumInputs());
+ return indexing_maps().getValue()[i].cast<AffineMapAttr>().getValue();
+ }
+ AffineMap getOutputIndexingMap(unsigned i) {
+ assert(i < getNumOutputs());
+ return indexing_maps().getValue()[i + getNumInputs()]
+ .cast<AffineMapAttr>().getValue();
+ }
+ }];
+ let printer = [{ return ::print(p, *this); }];
+ let parser = [{ return ::parseGenericOp(parser, result); }];
+}
+
+def GenericOp : GenericOpBase<"generic"> {
+ let description = [{
+ Generic Linalg op form where the key properties of the computation are
+ specified as attributes. In pretty form, a linalg.generic op is written as:
+
+ ```mlir
+ linalg.generic #trait_attribute %A, %B, %C {other-attributes} :
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>
+ ```
+
+ Where #trait_attributes is an alias of a dictionary attribute containing:
+ - args_in: an I64Attr representing the number of input (readonly) views
+ - args_out: an I64Attr representing the number of output (readwrite) views
+ - doc [optional]: a documentation string
+ - fun: a FlatSymbolRefAttr that must resolve to an existing function
+ symbol. To support inplace updates in a generic fashion, the signature
+ of the function must be:
+ ```
+ fun([input views element types], [output views element types])
+ -> ([output views element types])
+ ```
+ - indexing_maps: a list of AffineMapAttr, one AffineMapAttr per each input
+ and output view. Such AffineMapAttr specifies the mapping between the
+ loops and the indexing within each view.
+ - library_call [optional]: a StringAttr containing the name of an
+ external library function that the linalg.generic operation maps to.
+ The external library is assumed to be dynamically linked and no strong
+ compile-time guarantees are provided. In the absence of such a library
+ call, linalg.generic will always lower to loops.
+ - iterator_types: an ArrayAttr specifying the type of the enclosing loops.
+ Each element of the list represents and iterator of one of the following
+ types:
+ parallel, reduction, window
+
+ Example:
+ Defining a #matmul_trait attribute in MLIR can be done as follows:
+ ```mlir
+ func @fma(%a: f32, %b: f32, %c: f32) -> f32 {
+ %d = mulf %a, %b: f32
+ %e = addf %c, %d: f32
+ return %e: f32
+ }
+ #matmul_accesses = [
+ (m, n, k) -> (m, k),
+ (m, n, k) -> (k, n),
+ (m, n, k) -> (m, n)
+ ]
+ #matmul_trait = {
+ doc = "C(m, n) += A(m, k) * B(k, n)",
+ fun = @fma,
+ indexing_maps = #matmul_accesses,
+ library_call = "linalg_matmul",
+ n_views = [2, 1],
+ iterator_types = ["parallel", "parallel", "reduction"]
+ }
+ ```
+
+ And can be reused in multiple places as:
+ ```mlir
+ linalg.generic #matmul_trait %A, %B, %C [other-attributes] :
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>
+ ```
+
+ This may lower to either:
+ ```mlir
+ call @linalg_matmul(%A, %B, %C) :
+ (memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>)
+ -> ()
+ ```
+
+ or IR resembling:
+ ```mlir
+ loop.for %m = %c0 to %M step %c1 {
+ loop.for %n = %c0 to %N step %c1 {
+ loop.for %k = %c0 to %K step %c1 {
+ %a = linalg.load %A[%m, %k] : memref<?x?xf32, stride_specification>
+ %b = linalg.load %B[%k, %n] : memref<?x?xf32, stride_specification>
+ %c = linalg.load %C[%m, %n] : memref<?x?xf32, stride_specification>
+ %d = call @func_of_elements(%a, %b, %c)
+ : (f32, f32, f32) -> (f32)
+ linalg.store %d, %C[%m, %n] : memref<?x?x?xf32, stride_specification>
+ }
+ }
+ }
+ ```
+ }];
+ let verifier = [{ return ::verify(*this); }];
+}
+
+def IndexedGenericOp : GenericOpBase<"indexed_generic"> {
+ let description = [{
+ Indexed Generic Linalg op form where the key properties of the computation
+ are specified as attributes. In pretty form, a linalg.indexed_generic op is
+ written as:
+
+ ```mlir
+ linalg.indexed_generic #trait_attribute %A, %B, %C {other-attributes} :
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>
+ ```
+
+ Where #trait_attributes is an alias of a dictionary attribute containing:
+ - args_in: an I64Attr representing the number of input (readonly) views
+ - args_out: an I64Attr representing the number of output (readwrite) views
+ - doc [optional]: a documentation string
+ - fun: a FlatSymbolRefAttr that must resolve to an existing function
+ symbol. To support inplace updates in a generic fashion, the signature
+ of the function must be:
+ ```
+ fun([index types of induction variables], [input views element types],
+ [output views element types]) -> ([output views element types])
+ ```
+ - indexing_maps: a list of AffineMapAttr, one AffineMapAttr per each input
+ and output view. Such AffineMapAttr specifies the mapping between the
+ loops and the indexing within each view.
+ - library_call [optional]: a StringAttr containing the name of an
+ external library function that the linalg.indexed_generic operation
+ maps to. The external library is assumed to be dynamically linked and
+ no strong compile-time guarantees are provided. In the absence of such
+ a library call, linalg.indexed_generic will always lower to loops.
+ - iterator_types: an ArrayAttr they type of the enclosing loops; Each
+ element of the list represents and iterator of one of the following
+ types:
+ parallel, reduction, window
+
+ Example:
+ Defining a #matmul_trait attribute in MLIR can be done as follows:
+ ```mlir
+ func @fma(%i: index, %j: index, %k: index, %a: f32, %b: f32, %c: f32)
+ -> f32
+ {
+ %d = mulf %a, %b: f32
+ %e = addf %c, %d: f32
+ return %e: f32
+ }
+ #matmul_accesses = [
+ (m, n, k) -> (m, k),
+ (m, n, k) -> (k, n),
+ (m, n, k) -> (m, n)
+ ]
+ #matmul_trait = {
+ doc = "C(m, n) += A(m, k) * B(k, n)",
+ fun = @fma,
+ indexing_maps = #matmul_accesses,
+ library_call = "linalg_matmul",
+ n_views = [2, 1],
+ iterator_types = ["parallel", "parallel", "reduction"]
+ }
+ ```
+
+ And can be reused in multiple places as:
+ ```mlir
+ linalg.indexed_generic #matmul_trait %A, %B, %C [other-attributes] :
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>
+ ```
+
+ This may lower to either:
+ ```mlir
+ call @linalg_matmul(%A, %B, %C) :
+ (memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>,
+ memref<?x?xf32, stride_specification>)
+ -> ()
+ ```
+
+ or IR resembling:
+ ```mlir
+ loop.for %m = %c0 to %M step %c1 {
+ loop.for %n = %c0 to %N step %c1 {
+ loop.for %k = %c0 to %K step %c1 {
+ %a = linalg.load %A[%m, %k] : memref<?x?xf32, stride_specification>
+ %b = linalg.load %B[%k, %n] : memref<?x?xf32, stride_specification>
+ %c = linalg.load %C[%m, %n] : memref<?x?xf32, stride_specification>
+ %d = call @func_of_elements_and_indices(%m, %n, %k, %a, %b, %c)
+ : (index, index, index, f32, f32, f32) -> (f32)
+ linalg.store %d, %C[%m, %n] : memref<?x?x?xf32, stride_specification>
+ }
+ }
+ }
+ ```
+ }];
+ let verifier = [{ return ::verify(*this); }];
+}
+
+#endif // LINALG_STRUCTURED_OPS
diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/LinalgTransformPatterns.td b/mlir/include/mlir/Dialect/Linalg/Transforms/LinalgTransformPatterns.td
index d92eb77107f..415dd918f74 100644
--- a/mlir/include/mlir/Dialect/Linalg/Transforms/LinalgTransformPatterns.td
+++ b/mlir/include/mlir/Dialect/Linalg/Transforms/LinalgTransformPatterns.td
@@ -23,7 +23,7 @@
#define LINALG_TRANSFORMS
include "mlir/Dialect/Linalg/IR/LinalgOps.td"
-include "mlir/Dialect/Linalg/IR/LinalgLibraryOps.td"
+include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.td"
include "mlir/Dialect/AffineOps/AffineOps.td"
def HasNoLinalgTransformMarker : CPred<[{
diff --git a/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt b/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
index 9f5863f2be9..0fda882d3f5 100644
--- a/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LoopOps/CMakeLists.txt
@@ -1 +1 @@
-add_mlir_dialect(LoopOps)
+add_mlir_dialect(LoopOps LoopOps)
diff --git a/mlir/include/mlir/Dialect/QuantOps/CMakeLists.txt b/mlir/include/mlir/Dialect/QuantOps/CMakeLists.txt
index f95532ecf6e..90a61c4c194 100644
--- a/mlir/include/mlir/Dialect/QuantOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/QuantOps/CMakeLists.txt
@@ -1 +1 @@
-add_mlir_dialect(QuantOps)
+add_mlir_dialect(QuantOps QuantOps)
diff --git a/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt b/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
index b6759a9111b..fc7180de6cb 100644
--- a/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/SPIRV/CMakeLists.txt
@@ -3,7 +3,7 @@ mlir_tablegen(SPIRVLowering.h.inc -gen-struct-attr-decls)
mlir_tablegen(SPIRVLowering.cpp.inc -gen-struct-attr-defs)
add_public_tablegen_target(MLIRSPIRVLoweringStructGen)
-add_mlir_dialect(SPIRVOps)
+add_mlir_dialect(SPIRVOps SPIRVOps)
set(LLVM_TARGET_DEFINITIONS SPIRVBase.td)
mlir_tablegen(SPIRVEnums.h.inc -gen-enum-decls)
diff --git a/mlir/include/mlir/Dialect/VectorOps/CMakeLists.txt b/mlir/include/mlir/Dialect/VectorOps/CMakeLists.txt
index c165c5e676d..5ce3168c558 100644
--- a/mlir/include/mlir/Dialect/VectorOps/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/VectorOps/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_mlir_dialect(VectorOps)
+add_mlir_dialect(VectorOps VectorOps)
set(LLVM_TARGET_DEFINITIONS VectorTransformPatterns.td)
mlir_tablegen(VectorTransformPatterns.h.inc -gen-rewriters)
OpenPOWER on IntegriCloud