| //===- 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 |