MLIR 24.0.0git
LinalgInterfaces.h
Go to the documentation of this file.
1//===- LinalgInterface.h - Linalg operations interfaces -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the operation interfaces for Linalg operations.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_DIALECT_LINALG_IR_LINALGINTERFACES_H_
14#define MLIR_DIALECT_LINALG_IR_LINALGINTERFACES_H_
15
17#include "mlir/IR/AffineMap.h"
19#include "mlir/IR/IRMapping.h"
24
25namespace mlir {
26namespace linalg {
27class IteratorTypeAttr;
28class LinalgOp;
29class GenericOp;
30
31namespace detail {
32/// Implementation of the method that check if given operands
33/// can be dropped, i.e. the remaining operands can compute the loop
34/// bounds of the op.
35bool canOpOperandsBeDroppedImpl(linalg::LinalgOp linalgOp,
36 ArrayRef<OpOperand *> droppedOperands);
37} // namespace detail
38
39/// Positions of a Linalg op loops that correspond to different kinds of a
40/// contraction dimension.
47
48/// Find at least 2 parallel (m and n) and 1 reduction (k) dimension candidates
49/// that form a matmul subcomputation within `linalgOp`.
50/// These dimensions are such that:
51/// 1. The m dimension is involved in an outer-product along LHS
52/// (i.e. it is a permutation on RES and LHS and does not appear in RHS).
53/// 2. The n dimension is involved in an outer-product along RHS
54/// (i.e. it is a permutation on RES and RHS and does not appear in LHS).
55/// 3. The k dimension appears as a permutation on LHS and RHS.
56/// 4. m, n and k appear only once in any given indexing.
57/// 5. Optional batch dimensions that appear in all operands are captured.
58/// This allows e.g. detecting that some contraction is embedded within
59/// `linalgOp` with some orthogonal heuristic.
60/// When multiple dimension occurrences exist that match `batch`, `m`, `n`, or
61/// `k`, indices are returned in sorted order.
62/// Returns a failure if any of `m`, `n` or `k` is empty.
63FailureOr<ContractionDimensions> inferContractionDims(LinalgOp linalgOp);
64FailureOr<ContractionDimensions>
66
67/// Checks whether `linalgOp` conforms to ContractionOpInterface.
68// TODO: embed within `isa<ContractionOpInterface>` if possible / natural.
69bool isaContractionOpInterface(LinalgOp linalgOp);
70
71/// Positions of a Linalg op loops that correspond to different kinds of a
72/// convolution dimension.
83
84/// Find at least 1 parallel (output_image) and reduction (filter_loop)
85/// dimension candidates that form a convolution subcomputation within
86/// `linalgOp`. The LHS is assumed to be the convolution input while the
87/// RHS is assumed as the filter.
88/// These dimensions are such that:
89/// 1. Optional batch dimensions that appear in the input and filter.
90/// 2. The output_image dimension is involved in a cross-correlation along LHS
91/// (i.e. it is a permutation on RES and LHS and has an associated
92/// filter_loop in RHS).
93/// 3. Optional output_channel dimension is involved in an outer-product along
94/// RHS (i.e. it is a permutation on RES and RHS and does not appear in
95/// LHS).
96/// 4. Optional input_channel dimension appears as a permutation on LHS and
97/// RHS.
98/// 5. The filter_loop dimension appears as a permutation on the RHS and
99/// represents the shape of the kernel cross-correlated along a
100/// corresponding output_image dim.
101/// 6. The input_channel dimension appears as a permutation on LHS and RHS.
102/// 7. All dimensions appear only once in any given indexing map.
103/// This allows e.g. detecting that some convolution is embedded within
104/// `linalgOp` with some orthogonal heuristic.
105///
106/// The `outputImage` and `filterLoop` arrays are ordered such that
107/// `outputImage[i]` pairs with `filterLoop[i]` based on the convolution access
108/// pattern in the input indexing map (e.g., `d0 + d2` pairs dimension 0 with
109/// dimension 2). Other dimension sets are returned in sorted order.
110///
111/// Returns a failure if `output_image` (and implicitly `filter_loop`) is empty.
112FailureOr<ConvolutionDimensions> inferConvolutionDims(LinalgOp linalgOp);
113
114/// Maps-based overload of `inferConvolutionDims`. The `indexingMaps` are
115/// expected in operand order: input, filter, output. The iterator types are
116/// inferred from the output map: dimensions that appear in the output are
117/// parallel, all others are reduction. Since there is no operation to carry
118/// native `strides`/`dilations` attributes, the strides and dilations are
119/// derived from the convolution access pattern in the input indexing map.
120/// Returns a failure if there are not exactly 3 maps, the output map is not a
121/// projected permutation, or `output_image` (and implicitly `filter_loop`) is
122/// empty.
123FailureOr<ConvolutionDimensions>
125
126/// Checks whether `linalgOp` conforms to ConvolutionOpInterface.
127/// By default, we require the `linalgOp` to have non-empty convolved dims
128/// (implicitly non-empty `output_image` and `filter_loop`).
129/// Users can loosen the constraint by setting `allowEmptyConvolvedDims` to true
130// TODO: embed within `isa<ConvolutionOpInterface>` if possible / natural.
131bool isaConvolutionOpInterface(LinalgOp linalgOp,
132 bool allowEmptyConvolvedDims = false);
133
134/// Checks whether `linalgOp` is semantically equivalent to a `linalg.copyOp`.
135bool isaCopyOpInterface(LinalgOp linalgOp);
136
137/// Checks whether `linalgOp` is semantically equivalent to a broadcast
138/// operation. Returns broadcast dimensions if true.
139std::optional<SmallVector<int64_t>> isaBroadcastOpInterface(LinalgOp linalgOp);
140
141/// Checks whether `genericOp` is semantically equivalent to a
142/// `linalg.transpose`. Returns permuted dimensions if true.
143std::optional<SmallVector<int64_t>>
144isaTransposeOpInterface(GenericOp genericOp);
145
146/// Checks whether the `genericOp` is semantically equivalent to a
147/// `linalg.reduce`. Returns the reduction dimensions if true.
148std::optional<SmallVector<int64_t>>
149isaReductionOpInterface(GenericOp genericOp);
150
151/// Checks whether a given `genericOp` is semantically equivalent to a single
152/// linalg elementwise unary op, e.g.
153/// `linalg.elementwise <exp>`.
154/// Operations with non-identity indexing maps are included in the check, as
155/// they can be represented by the category op.
156/// A linalg.generic body could be a series of unary elementwise ops e.g.
157/// `exp(neg(x))`, such as formed by linalg op fusion. Here we restrict it to
158/// detecting cases where body is a single computation op.
159bool isaElemwiseSingleUnaryOpInterface(GenericOp genericOp);
160
161/// Checks whether `genericOp` is semantically equivalent to a single linalg
162/// elementwise binary op e.g. linalg.sub.
163/// Operations with non-identity indexing maps are included in the check, as
164/// they can be represented by the category op.
165bool isaElemwiseSingleBinaryOpInterface(GenericOp genericOp);
166
167/// Checks whether `genericOp` is semantically equivalent to a single linalg
168/// elementwise ternary op e.g. linalg.fma.
169/// Operations with non-identity indexing maps are included in the check, as
170/// they can be represented by the category op.
171bool isaElemwiseSingleTernaryOpInterface(GenericOp genericOp);
172
173/// Checks whether `genericOp` is semantically equivalent to a `linalg.fill`.
174/// Supports two patterns:
175/// 1. External: linalg.generic ins(%scalar) outs(%tensor) { yield %scalar }
176/// 2. Inlined: linalg.generic outs(%tensor) { yield %constant }
177/// Returns the scalar fill value if true.
178std::optional<Value> isaFillOpInterface(GenericOp genericOp);
179
180namespace detail {
181
182/// Returns true if the block contains a contraction of the following form:
183///
184/// %0 = <elemwise>(permutation-of(cu(block-argument-0),
185/// cu(block-argument-1)))
186/// %1 = <reduce>(permutation-of(cu(%0), cu(block-argument-2)))
187/// return-like cu(%1)
188///
189/// where <elemwise> and <reduce> are binary operations constituting a
190/// contraction (in the canonical case, <elemwise> is a multiplication and
191/// <reduce> is an addition). The name and other properties of these operations
192/// are checked by `isaPair`. All operands of all operations may be supplied
193/// through a chain of side effect-free unary operations, such as casts, which
194/// is denoted as `cu` above.
195///
196/// When the body does not contain a contraction, a more precise description of
197/// the failed precondition is send to the `errs` stream, if provided.
198bool isContractionBody(Block &block,
199 function_ref<bool(Operation *, Operation *)> isaPair,
200 llvm::raw_ostream &errs = mlir::thread_safe_nulls());
201
202/// Result of matching a Linalg generic against the predicates of it being a
203/// contraction.
204enum class MatchContractionResult;
205
206/// Checks whether `op` conforms to ContractionOpInterface and populates
207/// `dimensions` with indexes of the different kinds of dimensions when
208/// present.
211 ContractionDimensions *dimensions = nullptr);
212
213/// Returns the error message corresponding to the contraction checking return
214/// code.
216
217/// Result of matching a Linalg generic against the predicates of it being a
218/// convolution.
219enum class MatchConvolutionResult;
220
221/// Checks whether `op` conforms to ConvolutionOpInterface and populates
222/// `dimensions` with indexes of the different kinds of dimensions when
223/// present.
224/// If `allowEmptyConvolvedDims` is not set, we further checks whether the `op`
225/// contains convolved dims.
228 ConvolutionDimensions *dimensions = nullptr,
229 bool allowEmptyConvolvedDims = false);
230
231/// Returns the error message corresponding to the convolution checking return
232/// code.
234
235/// Verify that `op` conforms to ContractionOpInterface.
236LogicalResult verifyContractionInterface(Operation *op);
237
238/// Verify that `op` conforms to the ConvolutionOpInterface.
239LogicalResult verifyConvolutionInterface(Operation *op);
240
241/// Verify that `op` conforms to the FillOpInterface.
242LogicalResult verifyFillInterface(Operation *op);
243
244/// Verify that `op` conforms to the invariants of StructuredOpInterface
245LogicalResult verifyStructuredOpInterface(Operation *op);
246
247} // namespace detail
248} // namespace linalg
249} // namespace mlir
250
251#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.h.inc"
252
253/// Include the generated interface declarations.
254#include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h.inc"
255
256/// Include the generated relayout interface declarations.
257#include "mlir/Dialect/Linalg/IR/RelayoutOpInterface.h.inc"
258
259#endif // MLIR_DIALECT_LINALG_IR_LINALGINTERFACES_H_
Block represents an ordered list of Operations.
Definition Block.h:34
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
MatchConvolutionResult isConvolutionInterfaceImpl(Operation *op, ConvolutionDimensions *dimensions=nullptr, bool allowEmptyConvolvedDims=false)
Checks whether op conforms to ConvolutionOpInterface and populates dimensions with indexes of the dif...
bool isContractionBody(Block &block, function_ref< bool(Operation *, Operation *)> isaPair, llvm::raw_ostream &errs=mlir::thread_safe_nulls())
Returns true if the block contains a contraction of the following form:
StringRef getMatchConvolutionMessage(MatchConvolutionResult res)
Returns the error message corresponding to the convolution checking return code.
bool canOpOperandsBeDroppedImpl(linalg::LinalgOp linalgOp, ArrayRef< OpOperand * > droppedOperands)
Implementation of the method that check if given operands can be dropped, i.e.
MatchContractionResult isContractionInterfaceImpl(Operation *op, ContractionDimensions *dimensions=nullptr)
Checks whether op conforms to ContractionOpInterface and populates dimensions with indexes of the dif...
LogicalResult verifyContractionInterface(Operation *op)
Verify that op conforms to ContractionOpInterface.
LogicalResult verifyFillInterface(Operation *op)
Verify that op conforms to the FillOpInterface.
StringRef getMatchContractionMessage(MatchContractionResult res)
Returns the error message corresponding to the contraction checking return code.
LogicalResult verifyStructuredOpInterface(Operation *op)
Verify that op conforms to the invariants of StructuredOpInterface.
LogicalResult verifyConvolutionInterface(Operation *op)
Verify that op conforms to the ConvolutionOpInterface.
std::optional< SmallVector< int64_t > > isaTransposeOpInterface(GenericOp genericOp)
Checks whether genericOp is semantically equivalent to a linalg.transpose.
bool isaElemwiseSingleUnaryOpInterface(GenericOp genericOp)
Checks whether a given genericOp is semantically equivalent to a single linalg elementwise unary op,...
bool isaCopyOpInterface(LinalgOp linalgOp)
Checks whether linalgOp is semantically equivalent to a linalg.copyOp.
std::optional< SmallVector< int64_t > > isaReductionOpInterface(GenericOp genericOp)
Checks whether the genericOp is semantically equivalent to a linalg.reduce.
FailureOr< ConvolutionDimensions > inferConvolutionDims(LinalgOp linalgOp)
Find at least 1 parallel (output_image) and reduction (filter_loop) dimension candidates that form a ...
bool isaConvolutionOpInterface(LinalgOp linalgOp, bool allowEmptyConvolvedDims=false)
Checks whether linalgOp conforms to ConvolutionOpInterface.
bool isaElemwiseSingleTernaryOpInterface(GenericOp genericOp)
Checks whether genericOp is semantically equivalent to a single linalg elementwise ternary op e....
std::optional< SmallVector< int64_t > > isaBroadcastOpInterface(LinalgOp linalgOp)
Checks whether linalgOp is semantically equivalent to a broadcast operation.
FailureOr< ContractionDimensions > inferContractionDims(LinalgOp linalgOp)
Find at least 2 parallel (m and n) and 1 reduction (k) dimension candidates that form a matmul subcom...
bool isaContractionOpInterface(LinalgOp linalgOp)
Checks whether linalgOp conforms to ContractionOpInterface.
std::optional< Value > isaFillOpInterface(GenericOp genericOp)
Checks whether genericOp is semantically equivalent to a linalg.fill.
bool isaElemwiseSingleBinaryOpInterface(GenericOp genericOp)
Checks whether genericOp is semantically equivalent to a single linalg elementwise binary op e....
Include the generated interface declarations.
llvm::raw_ostream & thread_safe_nulls()
Returns a raw output stream that simply discards the output, but in a thread-safe manner.
llvm::function_ref< Fn > function_ref
Definition LLVM.h:155
Positions of a Linalg op loops that correspond to different kinds of a contraction dimension.
SmallVector< unsigned, 2 > batch
Positions of a Linalg op loops that correspond to different kinds of a convolution dimension.
SmallVector< unsigned, 2 > depth
SmallVector< unsigned, 2 > outputImage
SmallVector< unsigned, 2 > outputChannel
SmallVector< int64_t, 2 > dilations
SmallVector< int64_t, 2 > strides
SmallVector< unsigned, 2 > inputChannel
SmallVector< unsigned, 2 > batch
SmallVector< unsigned, 2 > filterLoop