blob: 64c538367267dc87b3cc064937f7db2f004bc92f [file] [log] [blame]
//===- LinalgOps.td - Linalg dialect ops -------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is the operation definition file for linear algebra operations.
//
//===----------------------------------------------------------------------===//
#ifndef LINALG_OPS
#define LINALG_OPS
include "mlir/Dialect/Linalg/IR/LinalgBase.td"
include "mlir/Dialect/Linalg/IR/LinalgInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
include "mlir/Interfaces/DestinationStyleOpInterface.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/LoopLikeInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/TilingInterface.td"
include "mlir/Interfaces/ViewLikeInterface.td"
// Base class for Linalg dialect ops that do not correspond to library calls.
class Linalg_Op<string mnemonic, list<Trait> traits = []> :
Op<Linalg_Dialect, mnemonic, traits>;
def Linalg_YieldOp : Linalg_Op<"yield", [Pure, ReturnLike, Terminator]>,
Arguments<(ins Variadic<AnyType>:$values)> {
let summary = "Linalg yield operation";
let description = [{
`linalg.yield` is a special terminator operation for blocks inside regions
in `linalg` generic ops. It returns values to the immediately enclosing
`linalg` generic op.
Example:
```mlir
linalg.yield %f0, %f1 : f32, f32
```
}];
let builders = [OpBuilder<(ins), [{ /* nothing to do */ }]>];
let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
def Linalg_IndexOp : Linalg_Op<"index", [Pure]>,
Arguments<(ins ConfinedAttr<I64Attr, [IntMinValue<0>]>:$dim)>,
Results<(outs Index:$result)> {
let summary = "linalg index operation";
let description = [{
The `linalg.index` operation returns the iteration index of the immediately
enclosing linalg structured operation for the iteration dimension `dim`. The
`dim` attribute specifies the position of the accessed dimension in the
indexing map domain.
Example:
```mlir
#map = affine_map<(i, j) -> (i, j)>
linalg.generic {indexing_maps = [#map, #map],
iterator_types = ["parallel", "parallel"]}
outs(%I, %J : memref<?x?xindex>, memref<?x?xindex>) {
^bb0(%arg0 : index, %arg1 : index):
// Access the outer iteration dimension i
%i = linalg.index 0 : index
// Access the inner iteration dimension j
%j = linalg.index 1 : index
linalg.yield %i, %j : index, index
}
```
This may lower to IR resembling:
```mlir
%0 = dim %I, %c0 : memref<?x?xindex>
%1 = dim %I, %c1 : memref<?x?xindex>
scf.for %i = %c0 to %0 step %c1 {
scf.for %j = %c0 to %1 step %c1 {
store %i, %I[%i, %j] : memref<?x?xindex>
store %j, %J[%i, %j] : memref<?x?xindex>
}
}
```
}];
let assemblyFormat = [{ $dim attr-dict `:` type($result) }];
let hasVerifier = 1;
}
def Linalg_SoftmaxOp : Linalg_Op<"softmax",
[DestinationStyleOpInterface,
PredOpTrait<"input and output have same element type", TCopVTEtIsSameAs<0, 1>>,
DeclareOpInterfaceMethods<ReifyRankedShapedTypeOpInterface>,
DeclareOpInterfaceMethods<AggregatedOpInterface, ["decomposeOperation"]>,
DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
DeclareOpInterfaceMethods<TilingInterface,
["getIterationDomain",
"getLoopIteratorTypes",
"getResultTilePosition",
"getTiledImplementation"]>]> {
let summary = "Softmax operator";
let description = [{
linalg.softmax computes a numerically stable version of softmax.
For a given input tensor and a specified dimension `d`, compute:
1. the max `m` along that dimension `d`
2. f(x) = exp(x - m)
3. sum f(x) along dimension d to get l(x).
4. compute the final result f(x) / l(x).
This is an aggregate linalg operation that further reduces to a small DAG of
structured operations.
Warning: Regarding the tiling capabilities, the implementation doesn't
check that the provided dimensions make sense. This is the responsability
of the transformation calling the tiling to ensure that the provided
sizes for each dimension make sense with respect to the semantic of
softmax.
}];
let arguments = (ins AnyShaped:$input,
AnyShaped:$output,
I64Attr:$dimension
);
let results = (outs Variadic<AnyRankedTensor>:$result);
let hasFolder = 1;
let assemblyFormat = [{
attr-dict
`dimension` `(` $dimension `)`
`ins` `(` $input `:` type($input) `)`
`outs` `(` $output `:` type($output) `)`
(`->` type($result)^)?
}];
let extraClassDeclaration = [{
ShapedType getInputOperandType() {
return cast<ShapedType>(getInput().getType());
}
ShapedType getOutputOperandType() {
return cast<ShapedType>(getOutput().getType());
}
int64_t getInputOperandRank() {
return getInputOperandType().getRank();
}
int64_t getOutputOperandRank() {
return getOutputOperandType().getRank();
}
MutableOperandRange getDpsInitsMutable() { return getOutputMutable(); }
}];
let hasVerifier = 1;
}
#endif // LINALG_OPS