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