xref: /llvm-project/mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.td (revision db791b278a414fb6df1acc1799adcf11d8fb9169)
1//===- TransformInterfaces.td - Transform Op interfaces ----*- tablegen -*-===//
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 declares the interfaces for transformation-related-ops.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_DIALECT_TRANSFORM_IR_TRANSFORM_INTERFACES_TD
14#define MLIR_DIALECT_TRANSFORM_IR_TRANSFORM_INTERFACES_TD
15
16include "mlir/IR/OpBase.td"
17
18def TransformOpInterface : OpInterface<"TransformOpInterface"> {
19  let description = [{
20    This interface is to be implemented by operations that identify
21    transformations to be performed on other operations. The former are referred
22    to as transform IR operations. The latter are referred to as payload IR
23    operations. Such transform IR operations provide a fine-grain control
24    mechanism over how transformations are applied by using and defining
25    transform IR values, referred to as handles, that correspond to sets of
26    operations in the payload IR. Transformations are applied starting from the
27    operations identified by handles, but may affect other operations as well.
28    Further restrictions may be imposed by flows that rely on transform IR
29    operations to control transformations.
30  }];
31
32  let cppNamespace = "::mlir::transform";
33
34  let methods = [
35    InterfaceMethod<
36      /*desc=*/[{
37        Applies the transformation represented by the current operation. This
38        accepts as arguments the object that must be populated with results of
39        the current transformation and a transformation state object that can be
40        used for queries, e.g., to obtain the list of operations on which the
41        transformation represented by the current op is targeted. Returns a
42        special status object indicating whether the transformation succeeded
43        or failed, and, if it failed, whether the failure is recoverable or not.
44
45        IR must be created, modified and deleted with the provided rewriter.
46        implementations are responsible for setting the insertion point of the
47        rewriter to the desired location.
48      }],
49      /*returnType=*/"::mlir::DiagnosedSilenceableFailure",
50      /*name=*/"apply",
51      /*arguments=*/(ins
52          "::mlir::transform::TransformRewriter &":$rewriter,
53          "::mlir::transform::TransformResults &":$transformResults,
54          "::mlir::transform::TransformState &":$state
55    )>,
56    InterfaceMethod<
57      /*desc=*/[{
58        Indicates whether the op instance allows its handle operands to be
59        associated with the same payload operations.
60      }],
61      /*returnType=*/"bool",
62      /*name=*/"allowsRepeatedHandleOperands",
63      /*arguments=*/(ins),
64      /*methodBody=*/"",
65      /*defaultImplementation=*/[{
66        return false;
67      }]
68    >,
69  ];
70
71  let extraSharedClassDeclaration = [{
72    /// Creates the silenceable failure object with a diagnostic located at the
73    /// current operation. Silenceable failure must be suppressed or reported
74    /// explicitly at some later time.
75    DiagnosedSilenceableFailure
76    emitSilenceableError(const ::llvm::Twine &message = {}) {
77      return ::mlir::emitSilenceableFailure($_op, message);
78    }
79
80    /// Creates the definite failure object with a diagnostic located at the
81    /// current operation. Definite failure will be reported when the object
82    /// is destroyed or converted.
83    DiagnosedDefiniteFailure
84    emitDefiniteFailure(const ::llvm::Twine &message = {}) {
85      return ::mlir::emitDefiniteFailure($_op, message);
86    }
87
88    /// Emits a generic definite failure for the current transform operation
89    /// targeting the given Payload IR operation and returns failure. Should
90    /// be only used as a last resort when the transformation itself provides
91    /// no further indication as to the reason of the failure.
92    DiagnosedDefiniteFailure emitDefaultDefiniteFailure(
93        ::mlir::Operation *target) {
94      auto diag = ::mlir::emitDefiniteFailure($_op, "failed to apply");
95      diag.attachNote(target->getLoc()) << "attempted to apply to this op";
96      return diag;
97    }
98
99    /// Creates the default silenceable failure for a transform op that failed
100    /// to properly apply to a target.
101    DiagnosedSilenceableFailure emitDefaultSilenceableFailure(
102        Operation *target) {
103      DiagnosedSilenceableFailure diag = emitSilenceableFailure($_op->getLoc());
104      diag << $_op->getName() << " failed to apply";
105      diag.attachNote(target->getLoc()) << "when applied to this op";
106      return diag;
107    }
108
109    /// Returns all operands that are handles and being consumed by this op.
110    ::llvm::SmallVector<OpOperand *> getConsumedHandleOpOperands() {
111      return ::mlir::transform::detail::getConsumedHandleOpOperands($_op);
112    }
113  }];
114
115  let verify = [{
116    return ::mlir::transform::detail::verifyTransformOpInterface($_op);
117  }];
118}
119
120class TransformTypeInterfaceBase<string cppClass, string cppObjectType>
121    : TypeInterface<cppClass> {
122  let cppNamespace = "::mlir::transform";
123
124  let methods = [
125    InterfaceMethod<
126      /*desc=*/[{
127        Checks if the given associated objects (Payload IR operations or attributes)
128        satisfy the conditions defined by this type. If not, produces a silenceable
129        error at the specified location.
130      }],
131      /*returnType=*/"::mlir::DiagnosedSilenceableFailure",
132      /*name=*/"checkPayload",
133      /*arguments=*/(ins "::mlir::Location":$loc,
134                         "::mlir::ArrayRef<" # cppObjectType # ">":$payload)
135    >
136  ];
137
138  let extraSharedClassDeclaration = [{
139    DiagnosedSilenceableFailure emitSilenceableError(Location loc) const {
140      Diagnostic diag(loc, DiagnosticSeverity::Error);
141      return DiagnosedSilenceableFailure::silenceableFailure(std::move(diag));
142    }
143  }];
144}
145
146def TransformHandleTypeInterface
147    : TransformTypeInterfaceBase<"TransformHandleTypeInterface",
148                                 "::mlir::Operation *"> {
149  let description = [{
150    Types that can be used for the Transform dialect operation handle values.
151    Such types define the properties of Payload IR operations associated with
152    the handle. A user of such a handle can assume that these properties have
153    been verified for any Payload IR operation associated with it.
154  }];
155}
156
157def TransformParamTypeInterface
158    : TransformTypeInterfaceBase<"TransformParamTypeInterface",
159                                 "::mlir::Attribute"> {
160  let description = [{
161    Types that can be used for the Transform dialect parameter values. Such types
162    define the structure of the parameters associated with the value, e.g., their
163    underlying type. A user of the value can assume that the parameter has been
164    verified.
165  }];
166}
167
168def TransformValueHandleTypeInterface
169    : TransformTypeInterfaceBase<"TransformValueHandleTypeInterface",
170                                 "::mlir::Value"> {
171  let description = [{
172    Types that can be used for the Transform dialect handle values pointing to
173    Payload IR values. Such types define the properties of Payload IR values
174    associated with the handle. Users of such a handle can assume that these
175    properties have been verified for any Payload IR value associated with it.
176  }];
177}
178
179def Transform_AnyHandleOrParamType
180  : Type<Or<[TransformParamTypeInterface.predicate,
181             TransformHandleTypeInterface.predicate,
182             TransformValueHandleTypeInterface.predicate]>,
183         "any transform handle or parameter">;
184
185def Transform_AnyHandleType
186  : Type<Or<[TransformHandleTypeInterface.predicate,
187             TransformValueHandleTypeInterface.predicate]>,
188         "any transform handle">;
189
190def FunctionalStyleTransformOpTrait
191    : NativeOpTrait<"FunctionalStyleTransformOpTrait"> {
192  let cppNamespace = "::mlir::transform";
193}
194
195def TransformEachOpTrait : NativeOpTrait<"TransformEachOpTrait"> {
196  let cppNamespace = "::mlir::transform";
197}
198
199def NavigationTransformOpTrait : NativeOpTrait<"NavigationTransformOpTrait"> {
200  let cppNamespace = "::mlir::transform";
201}
202
203def ParamProducerTransformOpTrait : NativeOpTrait<"ParamProducerTransformOpTrait"> {
204  let cppNamespace = "::mlir::transform";
205}
206
207def ReportTrackingListenerFailuresOpTrait : NativeOpTrait<"ReportTrackingListenerFailuresOpTrait"> {
208  let cppNamespace = "::mlir::transform";
209}
210
211def FindPayloadReplacementOpInterface
212    : OpInterface<"FindPayloadReplacementOpInterface"> {
213  let description = [{
214    This interface is queried by the `TrackingListener` and can be implemented
215    by payload ops to indicate that the lookup should be continue with its
216    operands when looking for payload op replacements.
217
218    Example: Consider the case where a tracked "test.foo" payload op is replaced
219    with a new "test.foo" op, but wrapped in a "tensor.reshape" op. In that
220    case, the mapping of the original "test.foo" op should be updated with the
221    new "test.foo" op. A "tensor.reshape" is a metadata-only op that should be
222    skipped when inspecting the replacement values of the original "test.foo"
223    op. More details can be found at `TrackingListener` documentation.
224
225    Note: Ops that implement `CastOpInterface` do not need to implement this
226    interface. Such ops are skipped by default. This interface should be
227    implemented by cast-like/metadata-only ops that cannot implement
228    `CastOpInterface`.
229  }];
230
231  let cppNamespace = "::mlir::transform";
232
233  let methods = [
234    InterfaceMethod<
235      /*desc=*/[{
236        Return the operands at which the lookup for replacement payload ops
237        should continue.
238      }],
239      /*returnType=*/"::llvm::SmallVector<::mlir::Value>",
240      /*name=*/"getNextOperands",
241      /*arguments=*/(ins)
242    >,
243  ];
244
245  let extraSharedClassDeclaration = [{
246    /// Name of the attribute attachable to an operation, indicating that
247    /// TrackingListener failures should be silenced.
248    constexpr const static ::llvm::StringLiteral
249        kSilenceTrackingFailuresAttrName =
250            "transform.silence_tracking_failures";
251  }];
252}
253
254def PatternDescriptorOpInterface : OpInterface<"PatternDescriptorOpInterface"> {
255  let description = [{
256    This interface should be implemented by ops that select rewrite patterns of
257    a `transform.apply_patterns` op. It provides a method to populate a rewrite
258    pattern set with patterns.
259
260    Note: Conversion patterns are rewrite patterns in MLIR, but they should not
261    be populated with `PatternDescriptorOpInterface` because they cannot be
262    used in a greedy pattern rewrite.
263  }];
264
265  let cppNamespace = "::mlir::transform";
266
267  let methods = [
268    InterfaceMethod<
269      /*desc=*/[{
270        Populate rewrite patterns into the given pattern set.
271      }],
272      /*returnType=*/"void",
273      /*name=*/"populatePatterns",
274      /*arguments=*/(ins "::mlir::RewritePatternSet &":$patterns)
275    >,
276    InterfaceMethod<
277      /*desc=*/[{
278        Populate rewrite patterns into the given pattern set taking into account
279        the transform state.
280      }],
281      /*returnType=*/"void",
282      /*name=*/"populatePatternsWithState",
283      /*arguments=*/(ins "::mlir::RewritePatternSet &":$patterns,
284                         "::mlir::transform::TransformState &":$state),
285      /*methodBody=*/"",
286      /*defaultImplementation=*/[{ $_op.populatePatterns(patterns); }]
287    >
288  ];
289}
290
291def TypeConverterBuilderOpInterface
292    : OpInterface<"TypeConverterBuilderOpInterface"> {
293  let description = [{
294    This interface should be implemented by ops that specify a type converter
295    for a dialect conversion, or to populate a type converter with
296    conversions.
297
298    When such ops are intended to be used with "apply_conversion_patterns" or
299    other operations that expect a type converter, a non-default implementation
300    of `getTypeConverter` should be implemented. For use with "cast_and_call"
301    like ops that construct a type converter iteratively, non-default
302    `populateTypeMaterializations` should be implemented.
303  }];
304
305  let cppNamespace = "::mlir::transform";
306
307  let methods = [
308    InterfaceMethod<
309      /*desc=*/[{
310        Return the type converter to be used with a dialect conversion.
311      }],
312      /*returnType=*/"std::unique_ptr<::mlir::TypeConverter>",
313      /*name=*/"getTypeConverter",
314      /*arguments=*/(ins),
315      /*methodBody=*/"",
316      /*defaultImplementation=*/[{
317        return std::make_unique<::mlir::TypeConverter>();
318      }]
319    >,
320    StaticInterfaceMethod<
321      /*desc=*/[{
322        Return the type of type converter that this `getTypeConverter` returns.
323        This function is used for op verification.
324      }],
325      /*returnType=*/"StringRef",
326      /*name=*/"getTypeConverterType",
327      /*arguments=*/(ins),
328      /*methodBody=*/"",
329      /*defaultImplementation=*/[{ return "TypeConverter"; }]
330    >,
331    InterfaceMethod<
332      /*desc=*/[{
333        Populate the given type converter with source/target materialization
334        functions.
335      }],
336      /*returnType=*/"void",
337      /*name=*/"populateTypeMaterializations",
338      /*arguments=*/(ins "::mlir::TypeConverter &":$converter),
339      /*methodBody=*/"",
340      /*defaultImplementation=*/[{ return; }]
341    >,
342  ];
343}
344
345def ConversionPatternDescriptorOpInterface
346    : OpInterface<"ConversionPatternDescriptorOpInterface"> {
347  let description = [{
348    This interface should be implemented by ops that select conversion patterns
349    of a `transform.apply_patterns` op. It provides a method to populate a
350    rewrite pattern set with conversion patterns.
351
352    Note: Non-conversion rewrite patterns should not be populated with
353    `ConversionPatternDescriptorOpInterface` because it is not generally safe
354    to use non-conversion rewrite patterns as part of a dialect conversion.
355  }];
356
357  let cppNamespace = "::mlir::transform";
358
359  let methods = [
360    InterfaceMethod<
361      /*desc=*/[{
362        Populate conversion patterns into the given pattern set with the
363        given type converter.
364      }],
365      /*returnType=*/"void",
366      /*name=*/"populatePatterns",
367      /*arguments=*/(ins "::mlir::TypeConverter &":$typeConverter,
368                         "::mlir::RewritePatternSet &":$patterns)
369    >,
370    InterfaceMethod<
371      /*desc=*/[{
372        Populate the ConversionTarget using the final TypeConverter. The default
373        implementation is to do nothing. Overriding this method can be useful
374        in order to setup the ConversionTarget for structural type conversions.
375        In such a situation, an op's legality depends on using the TypeConverter
376        to determine whether the op's operand and result types are legal
377        (defined as converting to themselves).
378
379      }],
380      /*returnType=*/"void",
381      /*name=*/"populateConversionTargetRules",
382      /*arguments=*/(ins "const ::mlir::TypeConverter &":$typeConverter,
383                         "::mlir::ConversionTarget &":$conversionTarget),
384      /*methodBody=*/"",
385      /*defaultImplementation=*/"return;"
386    >,
387    InterfaceMethod<
388      /*desc=*/[{
389        Return the type converter to be used with this pattern set. If no
390        type converter is specified, the default type converter of the enclosing
391        "apply_conversion_patterns" op is used.
392      }],
393      /*returnType=*/"std::unique_ptr<::mlir::TypeConverter>",
394      /*name=*/"getTypeConverter",
395      /*arguments=*/(ins),
396      /*methodBody=*/"",
397      /*defaultImplementation=*/"return nullptr;"
398    >,
399    InterfaceMethod<
400      /*desc=*/[{
401        Verify the default type converter that is provided by the enclosing
402        "apply_conversion_patterns" op.
403      }],
404      /*returnType=*/"::llvm::LogicalResult",
405      /*name=*/"verifyTypeConverter",
406      /*arguments=*/(ins "TypeConverterBuilderOpInterface":$builder),
407      /*methodBody=*/"",
408      /*defaultImplementation=*/"return success();"
409    >,
410  ];
411}
412
413#endif // MLIR_DIALECT_TRANSFORM_IR_TRANSFORM_INTERFACES_TD
414