1//===- TransformOps.td - Transform dialect operations ------*- 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#ifndef MLIR_DIALECT_TRANSFORM_IR_TRANSFORMOPS 10#define MLIR_DIALECT_TRANSFORM_IR_TRANSFORMOPS 11 12include "mlir/Interfaces/CallInterfaces.td" 13include "mlir/Interfaces/CastInterfaces.td" 14include "mlir/Interfaces/ControlFlowInterfaces.td" 15include "mlir/Interfaces/InferTypeOpInterface.td" 16include "mlir/Interfaces/SideEffectInterfaces.td" 17include "mlir/Interfaces/FunctionInterfaces.td" 18include "mlir/IR/OpAsmInterface.td" 19include "mlir/IR/RegionKindInterface.td" 20include "mlir/IR/SymbolInterfaces.td" 21include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" 22include "mlir/Dialect/Transform/IR/TransformAttrs.td" 23include "mlir/Dialect/Transform/IR/TransformDialect.td" 24include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" 25 26def AlternativesOp : TransformDialectOp<"alternatives", 27 [DeclareOpInterfaceMethods<RegionBranchOpInterface, 28 ["getEntrySuccessorOperands", "getSuccessorRegions", 29 "getRegionInvocationBounds"]>, 30 DeclareOpInterfaceMethods<TransformOpInterface>, 31 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 32 IsolatedFromAbove, PossibleTopLevelTransformOpTrait, 33 SingleBlockImplicitTerminator<"::mlir::transform::YieldOp">]> { 34 let summary = "Attempts sequences of transforms until one succeeds"; 35 let description = [{ 36 This op may have an arbitrary number of regions, each of which represents a 37 sequence of transform operations to be applied to the same payload IR. The 38 regions are visited in order of appearance, and transforms in them are 39 applied in their respective order of appearance. If one of these transforms 40 fails to apply, the remaining ops in the same region are skipped an the next 41 region is attempted. If all transformations in a region succeed, the 42 remaining regions are skipped and the entire "alternatives" transformation 43 succeeds. If all regions contained a failing transformation, the entire 44 "alternatives" transformation fails. 45 46 It is up to the nested operations to define which errors are "recoverable" 47 (or "silenceable") and allow another alternatives to be attempted, and which 48 errors should be propagated without attempting the other alternatives. 49 50 The single operand of this operation is the scope in which the alternative 51 transformation sequences are attempted, that is, an operation in the payload 52 IR that contains all the other operations that may be modified by the 53 transformations. The scope operation must be isolated from above. There is 54 no check that the transforms are indeed scoped as their "apply" methods can 55 be arbitrarily complex. Therefore it is the responsibility of the user to 56 ensure that the transforms are scoped correctly, or to produce an 57 irrecoverable error and thus abort the execution without attempting the 58 remaining alternatives. Note that the payload IR outside of the given scope 59 is not necessarily in the valid state, or even accessible to the 60 transformation. 61 62 The changes to the IR within the scope performed by transforms in the failed 63 alternative region are reverted before attempting the next region. 64 Practically, this is achieved by cloning the scope. Therefore it is advised 65 to limit the scope as much as possible and place the most likely 66 alternatives early in the region list. The operation is also isolated from 67 above and requires rediscovering the operations within the given scope to 68 avoid additional handle invalidation. The latter restriction may be lifted 69 in the future. 70 71 Each of the regions may yield transform IR handles. The handles of the first 72 successful alternative region are returned as the results of the 73 "alternatives" op. Therefore, each alternative region must yield the same 74 number of results, which should also match the number and the types of the 75 "alternatives" op results. 76 77 Remark: this op allows one to implement a simple "try" construct as follows: 78 79 ```mlir 80 %result = transform.alternatives %scope { 81 ^bb0(%arg0: !transform.any_op): 82 // Try a fallible transformation. 83 %0 = transform.fallible %arg0 // ... 84 // If succeeded, yield the the result of the transformation. 85 transform.yield %0 : !transform.any_op 86 }, { 87 ^bb0(%arg0: !transform.any_op): 88 // Otherwise, the second alternative is tried and it always succeeds by 89 // returning the original handle. 90 transform.yield %arg0 : !transform.any_op 91 } 92 ``` 93 }]; 94 95 let arguments = (ins Optional<TransformHandleTypeInterface>:$scope); 96 let results = (outs Variadic<TransformHandleTypeInterface>:$results); 97 let regions = (region VariadicRegion<SizedRegion<1>>:$alternatives); 98 99 let assemblyFormat = 100 "($scope^ `:` type($scope))? (`->` type($results)^)? " 101 "attr-dict-with-keyword regions"; 102 let hasVerifier = 1; 103} 104 105def AnnotateOp : TransformDialectOp<"annotate", 106 [DeclareOpInterfaceMethods<TransformOpInterface>, 107 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { 108 let summary = "Annotates the target operation with an attribute by name"; 109 let description = [{ 110 Adds an attribute with the given `name` to the `target` operation. An 111 optional `param` handle can be provided to give the attribute a specific 112 value, else a UnitAttr is added. A single attribute will be broadcasted to 113 all target operations, otherwise the attributes will be mapped 1:1 based on 114 the order within the handles. 115 116 Produces a silenceable failure if the length of the parameter payload does 117 not match the length of the target payload. Does not consume the provided 118 handles. 119 }]; 120 121 let arguments = (ins TransformHandleTypeInterface:$target, 122 StrAttr:$name, 123 Optional<TransformParamTypeInterface>:$param); 124 let results = (outs); 125 126 let assemblyFormat = 127 "$target $name attr-dict (`=` $param^)?" 128 "`:` type($target) (`,` type($param)^)?"; 129} 130 131def ApplyCommonSubexpressionEliminationOp : TransformDialectOp<"apply_cse", 132 [TransformOpInterface, TransformEachOpTrait, 133 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 134 ReportTrackingListenerFailuresOpTrait]> { 135 let summary = "Eliminate common subexpressions in the body of the target op"; 136 let description = [{ 137 This transform applies common subexpression elimination (CSE) to the body 138 of the targeted op. 139 140 This transform reads the target handle and modifies the payload. Existing 141 handles to operations inside of the targeted op are retained and updated if 142 necessary. Note that this can lead to situations where a handle, that was 143 previously mapped to multiple distinct (but equivalent) operations, is now 144 mapped to the same operation multiple times. 145 }]; 146 147 let arguments = (ins TransformHandleTypeInterface:$target); 148 let results = (outs); 149 let assemblyFormat = "`to` $target attr-dict `:` type($target)"; 150 151 let extraClassDeclaration = [{ 152 ::mlir::DiagnosedSilenceableFailure applyToOne( 153 ::mlir::transform::TransformRewriter &rewriter, 154 ::mlir::Operation *target, 155 ::mlir::transform::ApplyToEachResultList &results, 156 ::mlir::transform::TransformState &state); 157 }]; 158} 159 160def ApplyConversionPatternsOp : TransformDialectOp<"apply_conversion_patterns", 161 [DeclareOpInterfaceMethods<TransformOpInterface>, 162 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 163 ReportTrackingListenerFailuresOpTrait] 164 # GraphRegionNoTerminator.traits> { 165 let summary = "Applies conversion patterns to the body of the targeted op"; 166 let description = [{ 167 This transform applies the specified conversion patterns to the targeted op 168 and all nested ops. By default, this transform applies a "full" dialect 169 conversion. If the `partial_conversion` unit attribute is present, this 170 transform applies a partial dialect conversion. 171 172 The patterns that should be applied are specified in the first graph region 173 of this op. They must implement the 174 `ConversionPatternDescriptorOpInterface`. The order in which patterns are 175 applied is unspecified; i.e., the ordering of ops in the region of this op 176 is irrelevant. 177 178 The second, optional graph region contains exactly one op that specifies 179 default type converter that should be used with this dialect conversion. If 180 provided, this op must implement the `TypeConverterBuilderOpInterface`. 181 Type converters are a property of conversion patterns: each conversion 182 pattern stores the type converter that should be used in its C++ class. Each 183 conversion pattern descriptor can optionally specify a type converter in its 184 `getTypeConverter` interface method. If no type converter is specified in 185 this method, the default type converter of the dialect conversion is used. 186 Default type converters are useful if the same type converter should be used 187 for multiple sets of conversion patterns. (Patterns that should not use this 188 default type converter specify their own type converter.) 189 190 The `legal_ops`, `illegal_ops`, `legal_dialects`, `illegal_dialects` 191 attributes specify the conversion target. 192 193 This transform modifies the payload. By default, it consumes the `target` 194 handle. It does not produce any handles. 195 196 If the `preserve_handles` attribute is set, this transform does not consume 197 the `target` handle and instead updates handles based on notifications from 198 a tracking listener that is attached to the dialect conversion, similar to 199 `transform.apply_patterns`. Only replacements via `RewriterBase::replaceOp` 200 or `replaceOpWithNewOp` are considered "payload op replacements". In 201 contrast to `transform.apply_patterns`, we allow replacement ops even if the 202 op name has changed. This is because conversion patterns are expected to 203 lower ops to different ops (from a different dialect). More details can be 204 found at the documentation site of `TrackingListener`. 205 206 This transform produces a silenceable failure if the dialect conversion was 207 unsuccessful or the tracking listener failed to find a replacement op. 208 }]; 209 210 let arguments = (ins TransformHandleTypeInterface:$target, 211 OptionalAttr<StrArrayAttr>:$legal_ops, 212 OptionalAttr<StrArrayAttr>:$illegal_ops, 213 OptionalAttr<StrArrayAttr>:$legal_dialects, 214 OptionalAttr<StrArrayAttr>:$illegal_dialects, 215 UnitAttr:$partial_conversion, 216 UnitAttr:$preserve_handles); 217 let results = (outs); 218 let regions = (region 219 MaxSizedRegion<1>:$patterns, 220 VariadicRegion<MaxSizedRegion<1>>:$default_type_converter_region); 221 222 let assemblyFormat = [{ 223 `to` $target $patterns 224 (`with` `type_converter` $default_type_converter_region^)? 225 attr-dict `:` type($target) 226 }]; 227 let hasVerifier = 1; 228 229 let skipDefaultBuilders = 1; 230 let builders = [ 231 OpBuilder<(ins 232 "Value":$target, 233 CArg<"function_ref<void(OpBuilder &, Location)>", "nullptr">: 234 $patternsBodyBuilder, 235 CArg<"function_ref<void(OpBuilder &, Location)>", "nullptr">: 236 $typeConverterBodyBuilder)>, 237 ]; 238 239 let extraClassDeclaration = [{ 240 ::mlir::transform::TypeConverterBuilderOpInterface getDefaultTypeConverter() { 241 if (getDefaultTypeConverterRegion().size() == 0) 242 return {}; 243 return ::llvm::cast<::mlir::transform::TypeConverterBuilderOpInterface>( 244 &getDefaultTypeConverterRegion()[0].front().front()); 245 } 246 }]; 247} 248 249def ApplyToLLVMConversionPatternsOp : Op<Transform_Dialect, 250 "apply_conversion_patterns.dialect_to_llvm", 251 [DeclareOpInterfaceMethods<ConversionPatternDescriptorOpInterface, 252 ["verifyTypeConverter"]>]> { 253 let description = [{ 254 Collects patterns that convert ops from the specified dialect to LLVM 255 dialect ops. These patterns require an "LLVMTypeConverter". 256 257 Note: Only dialects that implement the `ConvertToLLVMPatternInterface` are 258 supported. Any conversion target modifications by interface implementations 259 are currently ignored. The conversion target is fully specified by the 260 enclosing "apply_conversion_patterns" op. 261 }]; 262 263 let arguments = (ins StrAttr:$dialect_name); 264 let assemblyFormat = "$dialect_name attr-dict"; 265 let hasVerifier = 1; 266} 267 268def ApplyDeadCodeEliminationOp : TransformDialectOp<"apply_dce", 269 [TransformOpInterface, TransformEachOpTrait, 270 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 271 ReportTrackingListenerFailuresOpTrait]> { 272 let summary = "Eliminate dead operations in the body of the target op"; 273 let description = [{ 274 This transform applies dead code elimination (DCE) to the body of the 275 targeted op. 276 277 Note: "transform.apply_patterns" with an empty region can also be used to 278 remove dead ops. However, that op applies additional simplifications such as 279 op folding and region simplification. 280 281 This transform reads the target handle and modifies the payload. Note that 282 this transform may silently remove payload ops from handles. 283 }]; 284 285 let arguments = (ins TransformHandleTypeInterface:$target); 286 let results = (outs); 287 let assemblyFormat = "`to` $target attr-dict `:` type($target)"; 288 289 let extraClassDeclaration = [{ 290 ::mlir::DiagnosedSilenceableFailure applyToOne( 291 ::mlir::transform::TransformRewriter &rewriter, 292 ::mlir::Operation *target, 293 ::mlir::transform::ApplyToEachResultList &results, 294 ::mlir::transform::TransformState &state); 295 }]; 296} 297 298def ApplyPatternsOp : TransformDialectOp<"apply_patterns", 299 [TransformOpInterface, TransformEachOpTrait, 300 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 301 ReportTrackingListenerFailuresOpTrait] 302 # GraphRegionNoTerminator.traits> { 303 let summary = "Greedily applies patterns to the body of the targeted op"; 304 let description = [{ 305 This transform greedily applies the specified patterns to the body of the 306 targeted op until a fixpoint was reached. Patterns are not applied to the 307 targeted op itself. 308 309 The patterns that should be applied are specified in the graph region of 310 this op. They must implement the `PatternDescriptorOpInterface`. The order 311 in which patterns are applied is unspecified; i.e., the ordering of ops in 312 the region of this op is irrelevant. 313 314 If `apple_cse` is set, the greedy pattern rewrite is interleaved with 315 common subexpression elimination (CSE): both are repeated until a fixpoint 316 is reached. 317 318 This transform only reads the target handle and modifies the payload. If a 319 pattern erases or replaces a tracked op, the mapping is updated accordingly. 320 321 Only replacements via `RewriterBase::replaceOp` or `replaceOpWithNewOp` are 322 considered "payload op replacements". Furthermore, only if the replacement 323 values are defined by the same op and that op has the same type as the 324 original op, the mapping is updated. Otherwise, this transform produces a 325 silenceable failure. More details can be found at the documentation site of 326 `TrackingListener`. 327 328 This transform also produces a silenceable failure if the pattern 329 application did not converge within the default number of 330 iterations/rewrites of the greedy pattern rewrite driver. 331 }]; 332 333 let arguments = (ins 334 TransformHandleTypeInterface:$target, 335 UnitAttr:$apply_cse, 336 DefaultValuedAttr<I64Attr, "static_cast<uint64_t>(-1)">:$max_iterations, 337 DefaultValuedAttr<I64Attr, "static_cast<uint64_t>(-1)">:$max_num_rewrites); 338 let results = (outs); 339 let regions = (region MaxSizedRegion<1>:$patterns); 340 341 let assemblyFormat = "`to` $target $patterns attr-dict `:` type($target)"; 342 let hasVerifier = 1; 343 344 let skipDefaultBuilders = 1; 345 let builders = [ 346 OpBuilder<(ins 347 "Value":$target, 348 CArg<"function_ref<void(OpBuilder &, Location)>", "nullptr">: 349 $bodyBuilder)>, 350 ]; 351 352 let extraClassDeclaration = [{ 353 ::mlir::DiagnosedSilenceableFailure applyToOne( 354 ::mlir::transform::TransformRewriter &rewriter, 355 ::mlir::Operation *target, 356 ::mlir::transform::ApplyToEachResultList &results, 357 ::mlir::transform::TransformState &state); 358 }]; 359} 360 361def ApplyCanonicalizationPatternsOp 362 : TransformDialectOp<"apply_patterns.canonicalization", 363 [DeclareOpInterfaceMethods<PatternDescriptorOpInterface>]> { 364 let summary = "Populates canonicalization patterns"; 365 let description = [{ 366 This op populates all canonicalization patterns of all loaded dialects in 367 an `apply_patterns` transform. 368 }]; 369 let assemblyFormat = "attr-dict"; 370} 371 372def ApplyLoopInvariantCodeMotionOp : TransformDialectOp<"apply_licm", 373 [TransformOpInterface, TransformEachOpTrait, 374 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 375 ReportTrackingListenerFailuresOpTrait]> { 376 let summary = "Move loop-invariant code out of a loop-like op"; 377 let description = [{ 378 This transform moves side-effect free, loop invariant code out of the 379 targeted loop-like op. The targeted op must implement the 380 `LoopLikeOpInterface`. 381 382 Note: To move invariant ops from a loop nest, this transform must be applied 383 to each loop of the loop nest, starting with the inner-most loop. 384 385 This transform reads the target handle and modifies the payload. 386 }]; 387 388 let arguments = (ins TransformHandleTypeInterface:$target); 389 let results = (outs); 390 let assemblyFormat = "`to` $target attr-dict `:` type($target)"; 391 392 let extraClassDeclaration = [{ 393 ::mlir::DiagnosedSilenceableFailure applyToOne( 394 ::mlir::transform::TransformRewriter &rewriter, 395 ::mlir::LoopLikeOpInterface target, 396 ::mlir::transform::ApplyToEachResultList &results, 397 ::mlir::transform::TransformState &state); 398 }]; 399} 400 401def ApplyRegisteredPassOp : TransformDialectOp<"apply_registered_pass", 402 [TransformOpInterface, TransformEachOpTrait, 403 FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface]> { 404 let summary = "Applies the specified registered pass or pass pipeline"; 405 let description = [{ 406 This transform applies the specified pass or pass pipeline to the targeted 407 ops. The name of the pass/pipeline is specified as a string attribute, as 408 set during pass/pipeline registration. Optionally, pass options may be 409 specified as a string attribute. The pass options syntax is identical to the 410 one used with "mlir-opt". 411 412 This op first looks for a pass pipeline with the specified name. If no such 413 pipeline exists, it looks for a pass with the specified name. If no such 414 pass exists either, this op fails definitely. 415 416 This transform consumes the target handle and produces a new handle that is 417 mapped to the same op. Passes are not allowed to remove/modify the operation 418 that they operate on, so the target op is guaranteed to still exist. The 419 target handle is invalidated because a pass may arbitrarily modify the body 420 of targeted ops. 421 }]; 422 423 let arguments = (ins TransformHandleTypeInterface:$target, 424 StrAttr:$pass_name, 425 DefaultValuedAttr<StrAttr, "\"\"">:$options); 426 let results = (outs TransformHandleTypeInterface:$result); 427 let assemblyFormat = [{ 428 $pass_name `to` $target attr-dict `:` functional-type(operands, results) 429 }]; 430 431 let extraClassDeclaration = [{ 432 ::mlir::DiagnosedSilenceableFailure applyToOne( 433 ::mlir::transform::TransformRewriter &rewriter, 434 ::mlir::Operation *target, 435 ::mlir::transform::ApplyToEachResultList &results, 436 ::mlir::transform::TransformState &state); 437 }]; 438} 439 440def CastOp : TransformDialectOp<"cast", 441 [TransformOpInterface, TransformEachOpTrait, 442 DeclareOpInterfaceMethods<CastOpInterface>, 443 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { 444 let arguments = (ins TransformHandleTypeInterface:$input); 445 let results = (outs TransformHandleTypeInterface:$output); 446 let assemblyFormat = "$input attr-dict `:` type($input) `to` type($output)"; 447 448 let extraClassDeclaration = [{ 449 ::mlir::DiagnosedSilenceableFailure applyToOne( 450 ::mlir::transform::TransformRewriter &rewriter, 451 ::mlir::Operation *target, 452 ::mlir::transform::ApplyToEachResultList &results, 453 ::mlir::transform::TransformState &state); 454 }]; 455} 456 457def NumAssociationsOp : TransformDialectOp<"num_associations", 458 [MemoryEffectsOpInterface, ParamProducerTransformOpTrait, 459 DeclareOpInterfaceMethods<TransformOpInterface>, 460 MatchOpInterface]> { 461 let summary = 462 "Returns the number of payload objects associated with the argument"; 463 let description = [{ 464 Given an argument, handle or parameter, returns a new parameter associated 465 with a single 64-bit number that corresponds to the number of payload 466 objects (operations or values for a handle, attributes for a parameter) 467 associated with the argument. 468 469 Always succeeds. 470 }]; 471 let arguments = (ins Transform_AnyHandleOrParamType:$handle); 472 let results = (outs TransformParamTypeInterface:$num); 473 let assemblyFormat = [{ 474 $handle attr-dict `:` functional-type(operands, results) 475 }]; 476 let hasVerifier = 1; 477} 478 479def CollectMatchingOp : TransformDialectOp<"collect_matching", [ 480 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 481 DeclareOpInterfaceMethods<SymbolUserOpInterface>, 482 DeclareOpInterfaceMethods<TransformOpInterface>]> { 483 let summary = "Collects all payload ops that match the given named matcher"; 484 let description = [{ 485 Collects operations or other payload IR objects nested under `root` 486 (inclusive) that match the given matcher expressed as a named sequence. The 487 matcher sequence must accept exactly one argument that it is not allowed to 488 modify. It must yield as many values as this op has results. Each of the 489 yielded values must be associated with exactly one payload object. If any 490 operation in the matcher sequence produces a silenceable failure, the 491 matcher advances to the next payload operation in the walk order without 492 finishing the sequence. 493 494 The i-th result of this operation is constructed by concatenating the i-th 495 yielded payload IR objects of all successful matcher sequence applications. 496 All results are guaranteed to be mapped to the same number of payload IR 497 objects. 498 499 The operation succeeds unless the matcher sequence produced a definite 500 failure for any invocation. 501 }]; 502 503 let arguments = (ins TransformHandleTypeInterface:$root, 504 SymbolRefAttr:$matcher); 505 let results = (outs Variadic<Transform_AnyHandleOrParamType>:$results); 506 507 let assemblyFormat = [{ 508 $matcher `in` $root attr-dict `:` functional-type($root, $results) 509 }]; 510} 511 512def ForeachMatchOp : TransformDialectOp<"foreach_match", [ 513 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 514 DeclareOpInterfaceMethods<SymbolUserOpInterface>, 515 DeclareOpInterfaceMethods<TransformOpInterface, 516 ["allowsRepeatedHandleOperands"]>, 517 DeclareOpInterfaceMethods<OpAsmOpInterface, 518 ["getAsmResultNames"]>]> { 519 let summary = "Applies named sequences when a named matcher succeeds"; 520 let description = [{ 521 Given a pair of co-indexed lists of transform dialect symbols (such as 522 `transform.named_sequence`), walks the payload IR associated with the root 523 handle and interprets the symbols as matcher/action pairs by applying the 524 body of the corresponding symbol definition. The symbol from the first list 525 is the matcher part: if it results in a silenceable error, the error is 526 silenced and the next matcher is attempted. Definite failures from any 527 matcher stop the application immediately and are propagated unconditionally. 528 If none of the matchers succeeds, the next payload operation in walk order 529 (post-order at the moment of writing, double check `Operation::walk`) is 530 matched. If a matcher succeeds, the co-indexed action symbol is applied and 531 the following matchers are not applied to the same payload operation. If the 532 action succeeds, the next payload operation in walk order is matched. If it 533 fails, both silenceable and definite errors are propagated as the result of 534 this op; propagation of silenceable errors is postponed until the end of the 535 walk. 536 537 The matcher symbol must take at least one operand of a type that implements 538 the same transform dialect interface as the `root` operand (a check is 539 performed at application time to see if the associated payload satisfies the 540 constraints of the actual type), and may take additional operands with a 541 similar type requirement. It must not consume operands as multiple matchers 542 may be applied. The matcher may produce any number of results. The action 543 symbol paired with the matcher must take the same number of arguments as the 544 matcher has results, and these arguments must implement the same transform 545 dialect interfaces, but not necessarily have the exact same type (again, a 546 check is performed at application time to see if the associated payload 547 satisfies the constraints of actual types on both sides). 548 549 The action symbol may have results that are accumulated from all actions and 550 returned from the `foreach_match` operation on success. Unless the 551 `flatten_results` attribute is present, each action result must be 552 associated with exactly one payload entity. The actions are expected to only 553 modify payload operations nested in the `root` payload operations associated 554 with the operand of this transform operation. Furthermore, the actions may 555 not modify operations outside of the currently matched payload operation, 556 e.g., they may not modify sibling or parent operations. If such behavior is 557 desired, the parent must be matched first and the nested operations obtained 558 by traversing the IR from the parent. This is due to the matching being 559 performed as a post-order IR walk. 560 561 This operation consumes the operand and produces a new handle associated 562 with the same payload. This is necessary to trigger invalidation of handles 563 to any of the payload operations nested in the payload operations associated 564 with the operand, as those are likely to be modified by actions. 565 566 By default, the root payload operation associated with the operand is not 567 matched. This is to support the conservative case where applied actions may 568 invalidate the root payload operation. If the optional `restrict_root` 569 attribute is set, the root operand is guaranteed to not be invalidated by any 570 of the applied actions. In such cases, the root payload operation is also 571 matched. This is useful because matching the root payload operation is a 572 common idiom, when e.g. matching a func.func directly and operations nested 573 under it. 574 575 The operation succeeds if none of the matchers produced a definite failure 576 during application and if all of the applied actions produced success. Note 577 that it also succeeds if all the matchers failed on all payload operations, 578 i.e. failure to apply is not an error. The operation produces a silenceable 579 failure if any applied action produced a silenceable failure. In this case, 580 the resulting handle is associated with an empty payload. The operation 581 produces a definite failure if any of the applied matchers or actions 582 produced a definite failure. 583 }]; 584 585 let arguments = 586 (ins TransformHandleTypeInterface:$root, 587 Variadic<Transform_AnyHandleOrParamType>:$forwarded_inputs, 588 UnitAttr:$restrict_root, 589 UnitAttr:$flatten_results, 590 SymbolRefArrayAttr:$matchers, 591 SymbolRefArrayAttr:$actions); 592 let results = 593 (outs TransformHandleTypeInterface:$updated, 594 Variadic<Transform_AnyHandleOrParamType>:$forwarded_outputs); 595 596 let assemblyFormat = [{ 597 oilist( `restrict_root` $restrict_root 598 | `flatten_results` $flatten_results 599 ) 600 `in` 601 $root (`,` $forwarded_inputs^)? 602 custom<ForeachMatchSymbols>($matchers, $actions) 603 attr-dict 604 `:` functional-type(operands, results) 605 }]; 606 607 let hasVerifier = 1; 608} 609 610def ForeachOp : TransformDialectOp<"foreach", 611 [DeclareOpInterfaceMethods<TransformOpInterface>, 612 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 613 DeclareOpInterfaceMethods<RegionBranchOpInterface, [ 614 "getSuccessorRegions", "getEntrySuccessorOperands"]>, 615 SingleBlockImplicitTerminator<"::mlir::transform::YieldOp"> 616 ]> { 617 let summary = "Executes the body for each element of the payload"; 618 let description = [{ 619 Execute the op's body - its single region block - exactly once per 620 element of the payload associated to a target handle. The body's 621 transformations are applied in order of appearance until reaching the 622 (implicit) YieldOp terminator. 623 624 Each iteration gets executed by co-indexing the payloads of the arguments 625 and mapping the body's arguments to these tuples, as though iterating over 626 the zipped together `targets`. As such, in each iteration, the size of the 627 payload of each of the body's block arguments is exactly one. The attribute 628 `zip_shortest` can be used if the targets vary in their number of payloads; 629 this will limit the iterations to only the number of payloads found in the 630 shortest target. 631 632 This op always reads the target handles. Furthermore, it consumes a handle 633 if there is a transform op in the body that consumes the corresponding 634 block argument. Handles can point to ops, values, or parameters. 635 636 #### Return Modes 637 638 This op produces as many result handles as the body's terminating YieldOp 639 has operands. For each result, the payloads of the corresponding YieldOp 640 operand are merged and mapped to the same resulting handle. 641 642 If the target handles do not associate payloads of the same size, a 643 silencable failure will be generated. 644 645 During application, if any transformation in the sequence fails, the entire 646 sequence fails immediately with the same failure, leaving the payload IR in 647 a potentially invalid state, i.e., this operation offers no transformation 648 rollback capabilities. 649 }]; 650 651 let arguments = (ins Variadic<Transform_AnyHandleOrParamType>:$targets, 652 UnitAttr:$with_zip_shortest); 653 let results = (outs Variadic<Transform_AnyHandleOrParamType>:$results); 654 let regions = (region SizedRegion<1>:$body); 655 let assemblyFormat = 656 "$targets oilist(`with_zip_shortest` $with_zip_shortest) `:` " 657 "type($targets) (`->` type($results)^)? $body attr-dict"; 658 let hasVerifier = 1; 659 660 let extraClassDeclaration = [{ 661 /// Allow the dialect prefix to be omitted. 662 static StringRef getDefaultDialect() { return "transform"; } 663 664 transform::YieldOp getYieldOp(); 665 }]; 666} 667 668def GetConsumersOfResult : TransformDialectOp<"get_consumers_of_result", 669 [DeclareOpInterfaceMethods<TransformOpInterface>, 670 NavigationTransformOpTrait, MemoryEffectsOpInterface]> { 671 let summary = "Get handle to the consumers of this operation's result number"; 672 let description = [{ 673 The handle defined by this Transform op corresponds to all operations that 674 consume the SSA value defined by the `target` and `result_number` 675 arguments. 676 This operation applies to a single payload operation, otherwise it produces 677 a definite failure. 678 The return handle points to the consuming operations operations, which can 679 be empty. 680 }]; 681 682 let arguments = (ins TransformHandleTypeInterface:$target, 683 I64Attr:$result_number); 684 let results = (outs TransformHandleTypeInterface:$consumers); 685 let assemblyFormat = "$target `[` $result_number `]` attr-dict `:` " 686 "functional-type(operands, results)"; 687} 688 689def GetDefiningOp : TransformDialectOp<"get_defining_op", 690 [DeclareOpInterfaceMethods<TransformOpInterface>, 691 MatchOpInterface, 692 NavigationTransformOpTrait, MemoryEffectsOpInterface]> { 693 let summary = "Get handle to the defining op of a value"; 694 let description = [{ 695 The handle defined by this Transform op corresponds to the defining op of 696 the targeted value. 697 698 This transform produces a silenceable failure if the targeted value is a 699 block argument. 700 }]; 701 702 let arguments = (ins TransformValueHandleTypeInterface:$target); 703 let results = (outs TransformHandleTypeInterface:$result); 704 let assemblyFormat = "$target attr-dict `:` " 705 "functional-type(operands, results)"; 706} 707 708def GetParentOp : TransformDialectOp<"get_parent_op", 709 [DeclareOpInterfaceMethods<TransformOpInterface>, 710 MatchOpInterface, 711 NavigationTransformOpTrait, MemoryEffectsOpInterface]> { 712 let summary = "Gets handles to the closest parent ops"; 713 let description = [{ 714 The handle defined by this Transform op corresponds to the parents of the 715 targeted payload ops (in the same order). 716 717 Requirements that parent ops must fulfill can be optionally specified. In 718 that case for each target op, the closest parent op that fulfills all 719 requirements, is returned. 720 - `isolated_from_above`: the parent op must be isolated from above 721 - `allow_empty_results`: get_parent_op is allowed to return an empty list 722 and still succeeds. In such a case, if `get_parent_op` fails for any 723 operation in the list, the entire transform returns an empty handle. 724 - `op_name`: the parent op must have the specified name 725 - `nth_parent`: get the n-th parent of that satisfies the above requirements 726 727 If `deduplicate` is set, the result handle does not contain any duplicate 728 ops. For example, given the list 729 "(childof(A), childof(B), childof(B), childof(A), childof(B))", the 730 resulting list will be just "(A, B)". Note that no other semantic ordering 731 is applied, e.g., "B" may itself be a parent of "A". This may have an impact 732 on the further transformation applied to the handle produced here. 733 734 If any of the given Payload IR ops has no such suitable parent, then: 735 - if `allow_empty_results` is set, the result handle is empty 736 - otherwise, the transformation produces a silenceable failure. 737 }]; 738 739 let arguments = (ins TransformHandleTypeInterface:$target, 740 UnitAttr:$isolated_from_above, 741 UnitAttr:$allow_empty_results, 742 OptionalAttr<StrAttr>:$op_name, 743 UnitAttr:$deduplicate, 744 DefaultValuedAttr<ConfinedAttr<I64Attr, [IntPositive]>, 745 "1">:$nth_parent); 746 let results = (outs TransformHandleTypeInterface:$parent); 747 let assemblyFormat = 748 "$target attr-dict `:` functional-type(operands, results)"; 749} 750 751def GetProducerOfOperand : TransformDialectOp<"get_producer_of_operand", 752 [DeclareOpInterfaceMethods<TransformOpInterface>, 753 NavigationTransformOpTrait, MatchOpInterface, MemoryEffectsOpInterface]> { 754 let summary = "Get handle to the producer of this operation's operand number"; 755 let description = [{ 756 The handle defined by this Transform op corresponds to operation that 757 produces the SSA value defined by the `target` and `operand_number` 758 arguments. If the origin of the SSA value is not an operations (i.e. it is 759 a block argument), the transform produces a silenceable failure. 760 The return handle points to only the subset of successfully produced 761 computational operations, which can be empty. 762 }]; 763 764 let arguments = (ins TransformHandleTypeInterface:$target, 765 I64Attr:$operand_number); 766 let results = (outs TransformHandleTypeInterface:$producer); 767 let assemblyFormat = "$target `[` $operand_number `]` attr-dict `:` " 768 "functional-type(operands, results)"; 769} 770 771def GetOperandOp : TransformDialectOp<"get_operand", 772 [DeclareOpInterfaceMethods<TransformOpInterface>, 773 NavigationTransformOpTrait, MatchOpInterface, MemoryEffectsOpInterface]> { 774 let summary = "Get a handle to the operand(s) of the targeted op"; 775 let description = [{ 776 The handle defined by this Transform op corresponds to the operands of the 777 given `target` operation specified by the given set of positions. There are 778 three possible modes: 779 780 - Position list directly, i.e. `%target[0, 1, 2]`. This will return the 781 operands at the specified positions. 782 - Inverted position list, i.e. `%target[except(0, 1, 2)]`. This will return 783 all operands except those at the given positions. 784 - All, i.e. `%target[all]`. This will return all operands of the operation. 785 786 This transform produces a silenceable failure if any of the operand indices 787 exceeds the number of operands in the target. It reads the target handle and 788 produces the result handle. 789 }]; 790 791 let arguments = (ins TransformHandleTypeInterface:$target, 792 DenseI64ArrayAttr:$raw_position_list, 793 UnitAttr:$is_inverted, 794 UnitAttr:$is_all); 795 let results = (outs TransformValueHandleTypeInterface:$result); 796 let assemblyFormat = 797 "$target `[`" 798 "custom<TransformMatchDims>($raw_position_list, $is_inverted, $is_all)" 799 "`]` attr-dict `:` functional-type(operands, results)"; 800 let hasVerifier = 1; 801} 802 803def GetResultOp : TransformDialectOp<"get_result", 804 [DeclareOpInterfaceMethods<TransformOpInterface>, 805 NavigationTransformOpTrait, MemoryEffectsOpInterface]> { 806 let summary = "Get a handle to the result(s) of the targeted op"; 807 let description = [{ 808 The handle defined by this Transform op correspond to the OpResults of the 809 given `target` operation. Optionally `result_number` can be specified to 810 select a specific result. 811 812 This transform fails silently if the targeted operation does not have enough 813 results. It reads the target handle and produces the result handle. 814 815 The handle defined by this Transform op corresponds to the results of the 816 given `target` operation specified by the given set of positions. There are 817 three possible modes: 818 819 - Position list directly, i.e. `%target[0, 1, 2]`. This will return the 820 results at the specified positions. 821 - Inverted position list, i.e. `%target[except(0, 1, 2)]`. This will return 822 all results except those at the given positions. 823 - All, i.e. `%target[all]`. This will return all results of the operation. 824 825 This transform produces a silenceable failure if any of the result indices 826 exceeds the number of results returned by the target. It reads the target 827 handle and produces the result handle. 828 }]; 829 830 let arguments = (ins TransformHandleTypeInterface:$target, 831 DenseI64ArrayAttr:$raw_position_list, 832 UnitAttr:$is_inverted, 833 UnitAttr:$is_all); 834 let results = (outs TransformValueHandleTypeInterface:$result); 835 let assemblyFormat = 836 "$target `[`" 837 "custom<TransformMatchDims>($raw_position_list, $is_inverted, $is_all)" 838 "`]` attr-dict `:` functional-type(operands, results)"; 839 let hasVerifier = 1; 840} 841 842def GetTypeOp : TransformDialectOp<"get_type", 843 [DeclareOpInterfaceMethods<TransformOpInterface>, 844 MatchOpInterface, 845 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { 846 let summary = "Get a parameter containing the type of the given value"; 847 let description = [{ 848 This operation creates a new Transform parameter containing the 849 type(s) of the value(s) associated with the operand handle. 850 851 This transform never fails. 852 }]; 853 854 let arguments = (ins TransformValueHandleTypeInterface:$value, 855 UnitAttr:$elemental); 856 let results = (outs TransformParamTypeInterface:$type_param); 857 let assemblyFormat = "(`elemental` $elemental^)? $value attr-dict `:`" 858 "functional-type(operands, results)"; 859} 860 861def IncludeOp : TransformDialectOp<"include", 862 [CallOpInterface, 863 MatchOpInterface, 864 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 865 DeclareOpInterfaceMethods<SymbolUserOpInterface>, 866 DeclareOpInterfaceMethods<TransformOpInterface>]> { 867 let summary = "Includes a named transform sequence"; 868 let description = [{ 869 The application of this transform operation is equivalent to applying the 870 operations contained in the named transform sequence with operands being 871 remapped to block arguments. The behavior of the operation when a 872 transformation in the included named sequence produces a silenceable error 873 is controlled by the `failure_propagation_mode` attribute. When set to 874 `propagate`, the failure of any nested transformation in the sequence 875 implies immediate failure of the entire sequence with a silenceable error, 876 and no further transformation is attempted. When set to `suppress`, 877 silenceable errors in nested operations are ignored and further 878 transformations are applied. Beware that even silenceable errors may leave 879 the payload IR in a state unsuitable for further transformations. It is the 880 responsibility of the user to ensure the following transformations are 881 robust enough when errors are suppressed. Definite errors are propagated 882 immediately regardless of the mode. The objects associated with the results 883 of this operation are the same as those associated with the operands of the 884 `transform.yield` in the referenced named sequence. 885 }]; 886 887 let arguments = (ins SymbolRefAttr:$target, 888 FailurePropagationMode:$failure_propagation_mode, 889 Variadic<Transform_AnyHandleOrParamType>:$operands); 890 let results = (outs Variadic<Transform_AnyHandleOrParamType>:$results); 891 892 let assemblyFormat = 893 "$target `failures` `(` $failure_propagation_mode `)`" 894 "`(` $operands `)` attr-dict `:` functional-type($operands, $results)"; 895 896 let extraClassDeclaration = [{ 897 ::mlir::CallInterfaceCallable getCallableForCallee() { 898 return getTarget(); 899 } 900 901 void setCalleeFromCallable(::mlir::CallInterfaceCallable callee) { 902 setTargetAttr(cast<SymbolRefAttr>(callee)); 903 } 904 905 ::mlir::Operation::operand_range getArgOperands() { 906 return getOperands(); 907 } 908 909 ::mlir::MutableOperandRange getArgOperandsMutable() { 910 return getOperandsMutable(); 911 } 912 }]; 913} 914 915def MatchOperationEmptyOp : Op<Transform_Dialect, "match.operation_empty", [ 916 AtMostOneOpMatcher, 917 MatchOpInterface, 918 MemoryEffectsOpInterface]> { 919 let summary = 920 "Matches if the handle is not associated to any op"; 921 let description = [{ 922 Succeeds if the handle is not associated to any op. 923 }]; 924 let arguments = (ins TransformHandleTypeInterface:$operand_handle); 925 let assemblyFormat = 926 "$operand_handle attr-dict `:` type($operand_handle)"; 927 let extraClassDeclaration = AtMostOneOpMatcher.extraDeclaration; 928} 929 930def MatchOperationNameOp : TransformDialectOp<"match.operation_name", 931 [SingleOpMatcher, 932 MatchOpInterface, 933 MemoryEffectsOpInterface]> { 934 let summary = "Matches a single operation of one of the given kinds"; 935 let description = [{ 936 Succeeds if the operation associated with the operand handle has one of the 937 given operation names. Produces a silenceable failure otherwise. 938 939 If more than one payload operation is associated with the operand handle, 940 produces a definite failure. 941 }]; 942 943 let arguments = (ins TransformHandleTypeInterface:$operand_handle, 944 StrArrayAttr:$op_names); 945 let assemblyFormat = 946 "$operand_handle $op_names attr-dict `:` type($operand_handle)"; 947 let extraClassDeclaration = SingleOpMatcher.extraDeclaration; 948} 949 950def MatchParamCmpIOp : Op<Transform_Dialect, "match.param.cmpi", [ 951 DeclareOpInterfaceMethods<TransformOpInterface>, 952 MatchOpInterface, 953 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 954 SameTypeOperands]> { 955 let summary = 956 "Matches if two parameter lists are associated with the same value"; 957 let description = [{ 958 Succeeds if all of the co-indexed values associated with the given 959 parameters relate as specified by the predicate (greater than, less than, 960 equal to, or their combinations). Comparison treats all values as signed. 961 Produces a silenceable failure otherwise. 962 }]; 963 let arguments = (ins TransformParamTypeInterface:$param, 964 TransformParamTypeInterface:$reference, 965 MatchCmpIPredicateAttr:$predicate); 966 let assemblyFormat = 967 "$predicate $param `,` $reference attr-dict `:` type($param)"; 968} 969 970def MergeHandlesOp : TransformDialectOp<"merge_handles", 971 [DeclareOpInterfaceMethods<TransformOpInterface, ["allowsRepeatedHandleOperands"]>, 972 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 973 MatchOpInterface, SameOperandsAndResultType]> { 974 let summary = "Merges handles into one pointing to the union of payload ops"; 975 let description = [{ 976 Creates a new Transform IR handle value that points to the same Payload IR 977 operations/values/parameters as the operand handles. The Payload IR elements 978 are listed in the same order as they are in the operand handles, grouped by 979 operand handle, e.g., all Payload IR associated with the first handle comes 980 first, then all Payload IR associated with the second handle and so on. If 981 `deduplicate` is set, do not add the given Payload IR operation, value, or 982 parameter more than once to the final list regardless of it coming from the 983 same or different handles. Consumes the operands and produces a new handle. 984 }]; 985 986 let arguments = (ins Variadic<Transform_AnyHandleOrParamType>:$handles, 987 UnitAttr:$deduplicate); 988 let results = (outs Transform_AnyHandleOrParamType:$result); 989 let assemblyFormat = "(`deduplicate` $deduplicate^)? $handles attr-dict `:` type($result)"; 990 let hasFolder = 1; 991} 992 993def NamedSequenceOp : TransformDialectOp<"named_sequence", 994 [FunctionOpInterface, 995 IsolatedFromAbove, 996 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 997 DeclareOpInterfaceMethods<TransformOpInterface>]> { 998 let summary = "Named transform sequence that can be included elsewhere"; 999 let description = [{ 1000 Defines a named (callable, function-like) sequence of other Transform 1001 dialect operations that can be included using `transform.include` as part of 1002 another Transform dialect construct. This sequence is not processed 1003 immediately but rather dispatched to when the inclusion is processed. The 1004 arguments and results can be used to communicate a subset of mapping into 1005 the named sequence. The sequence must consist of a single block and end with 1006 a `transform.yield` terminator. The operands of the terminator become the 1007 results of the `transform.include`. 1008 1009 When dispatched to, the operations in the named sequence are executed one by 1010 one, similarly to the regular unnamed sequence. The failure propagation mode 1011 is specified on the `transform.include`. Different inclusions may use 1012 different failure propagation modes. This transform operation always 1013 succeeds by itself, but the inclusion may fail if any of the operations 1014 fail. 1015 1016 Named sequences can only appear at the top-level of the Transform dialect 1017 nesting structure. That is, they cannot be nested in other Transform dialect 1018 operations. Furthermore, one of the ancestors must have the `SymbolTable` 1019 trait and have the `transform.with_named_sequence` attribute attached. 1020 1021 Named sequences may include other named sequences via `transform.include`, 1022 but recursion is *not* allowed. 1023 }]; 1024 1025 let arguments = (ins 1026 SymbolNameAttr:$sym_name, 1027 TypeAttrBase<"::mlir::FunctionType", 1028 "function type attribute">:$function_type, 1029 OptionalAttr<StrAttr>:$sym_visibility, 1030 OptionalAttr<DictArrayAttr>:$arg_attrs, 1031 OptionalAttr<DictArrayAttr>:$res_attrs); 1032 let regions = (region MaxSizedRegion<1>:$body); 1033 1034 let hasCustomAssemblyFormat = 1; 1035 let hasVerifier = 1; 1036 1037 let builders = [ 1038 // Build a named sequence. 1039 OpBuilder<(ins 1040 "StringRef":$symName, 1041 "Type":$rootType, 1042 "TypeRange":$resultType, 1043 "SequenceBodyBuilderFn":$bodyBuilder, 1044 CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs, 1045 CArg<"ArrayRef<DictionaryAttr>", "{}">:$argAttrs)> 1046 ]; 1047 1048 let extraClassDeclaration = [{ 1049 ::llvm::ArrayRef<::mlir::Type> getArgumentTypes() { 1050 return getFunctionType().getInputs(); 1051 } 1052 ::llvm::ArrayRef<::mlir::Type> getResultTypes() { 1053 return getFunctionType().getResults(); 1054 } 1055 ::mlir::Region *getCallableRegion() { 1056 return &getBody(); 1057 } 1058 }]; 1059} 1060 1061def SplitHandleOp : TransformDialectOp<"split_handle", 1062 [FunctionalStyleTransformOpTrait, 1063 DeclareOpInterfaceMethods<TransformOpInterface>, 1064 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { 1065 let summary = "Splits a handle or parameter into multiple values"; 1066 let description = [{ 1067 Splits `handle` into one or multiple handles, as specified by the number 1068 of results of this operation. `handle` should be mapped to as many payload 1069 ops, values or parameteres as there are results. Otherwise, this transform 1070 will fail producing a silenceable failure by default. Each result handle 1071 is mapped to exactly one payload unless specified otherwise by attributes 1072 described below. The order of the payloads is preserved, i.e., the i-th 1073 payload is mapped to the i-th result handle. 1074 1075 This operation is useful for ensuring a statically known number of 1076 payloads are tracked by the source `handle` and to extract them into 1077 individual handles that can be further manipulated in isolation. 1078 1079 If there are more payloads than results, the remaining payloads are mapped to 1080 the result with index `overflow_result`. If no `overflow_result` is 1081 specified, the transform produces a silenceable failure. 1082 1083 If there are fewer payload ops than results, the transform produces a 1084 silenceable failure if `fail_on_payload_too_small` is set to "true". 1085 Otherwise, it succeeds and the remaining result handles are not mapped to 1086 anything. It also succeeds if `handle` is empty and 1087 `pass_through_empty_handle` is set to "true", regardless of 1088 `fail_on_payload_too_small`. 1089 }]; 1090 1091 let arguments = (ins Transform_AnyHandleOrParamType:$handle, 1092 DefaultValuedAttr<BoolAttr, "true">:$pass_through_empty_handle, 1093 DefaultValuedAttr<BoolAttr, "true">:$fail_on_payload_too_small, 1094 OptionalAttr<I64Attr>:$overflow_result); 1095 let results = (outs Variadic<Transform_AnyHandleOrParamType>:$results); 1096 let hasVerifier = 1; 1097 1098 let builders = [ 1099 OpBuilder<(ins "Value":$handle, "int64_t":$numResultHandles)> 1100 ]; 1101 1102 let assemblyFormat = [{ 1103 $handle attr-dict `:` functional-type(operands, results) 1104 }]; 1105} 1106 1107def ParamConstantOp : Op<Transform_Dialect, "param.constant", [ 1108 MatchOpInterface, 1109 DeclareOpInterfaceMethods<TransformOpInterface>, 1110 MemoryEffectsOpInterface, 1111 ParamProducerTransformOpTrait]> { 1112 let summary = "Produces a new transform dialect parameter value associated " 1113 "with the given attribute"; 1114 let description = [{ 1115 Produces a new transform dialect parameter associated with the singleton 1116 list containing the given attribute. The operation itself always succeeds, 1117 but the general association check may fail if the parameter type does not 1118 accept the given kind of attribute as valid. 1119 }]; 1120 let arguments = (ins AnyAttr:$value); 1121 let results = (outs TransformParamTypeInterface:$param); 1122 let assemblyFormat = "$value attr-dict `->` type($param)"; 1123} 1124 1125def PrintOp : TransformDialectOp<"print", 1126 [DeclareOpInterfaceMethods<TransformOpInterface>, 1127 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 1128 MatchOpInterface]> { 1129 let summary = "Dump each payload op"; 1130 let description = [{ 1131 Prints each payload op that is associated with the `target` operand to 1132 `stdout`. It also prints the `name` string attribute. If no target is 1133 specified, the top-level op is dumped. 1134 1135 This op is useful for printf-style debugging. 1136 1137 Supported printing flag attributes: 1138 * `assume_verified` -- skips verification when the unit attribute is 1139 specified. This improves performace but may lead to crashes and 1140 unexpected behavior when the printed payload op is invalid. 1141 * `use_local_scope` -- prints in local scope when the unit attribute is 1142 specified. This improves performance but may not be identical to 1143 printing within the full module. 1144 * `skip_regions` -- does not print regions of operations when the unit 1145 attribute is specified. 1146 }]; 1147 1148 let arguments = (ins Optional<TransformHandleTypeInterface>:$target, 1149 OptionalAttr<StrAttr>:$name, 1150 OptionalAttr<UnitAttr>:$assume_verified, 1151 OptionalAttr<UnitAttr>:$use_local_scope, 1152 OptionalAttr<UnitAttr>:$skip_regions); 1153 let results = (outs); 1154 1155 let builders = [ 1156 OpBuilder<(ins CArg<"StringRef", "StringRef()">:$name)>, 1157 OpBuilder<(ins "Value":$target, CArg<"StringRef", "StringRef()">:$name)> 1158 ]; 1159 1160 let assemblyFormat = "$target attr-dict (`:` type($target)^)?"; 1161} 1162 1163def ReplicateOp : TransformDialectOp<"replicate", 1164 [DeclareOpInterfaceMethods<TransformOpInterface>, 1165 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 1166 AllTypesMatch<["handles", "replicated"]>]> { 1167 let summary = "Lists payload ops multiple times in the new handle"; 1168 let description = [{ 1169 Produces a new handle associated with a list of payload IR ops that is 1170 computed by repeating the list of payload IR ops associated with the 1171 operand handle as many times as the "pattern" handle has associated 1172 operations. For example, if pattern is associated with [op1, op2] and the 1173 operand handle is associated with [op3, op4, op5], the resulting handle 1174 will be associated with [op3, op4, op5, op3, op4, op5]. 1175 1176 This transformation is useful to "align" the sizes of payload IR lists 1177 before a transformation that expects, e.g., identically-sized lists. For 1178 example, a transformation may be parameterized by same notional per-target 1179 size computed at runtime and supplied as another handle, the replication 1180 allows this size to be computed only once and used for every target instead 1181 of replicating the computation itself. 1182 1183 Note that it is undesirable to pass a handle with duplicate operations to 1184 an operation that consumes the handle. Handle consumption often indicates 1185 that the associated payload IR ops are destroyed, so having the same op 1186 listed more than once will lead to double-free. Single-operand 1187 MergeHandlesOp may be used to deduplicate the associated list of payload IR 1188 ops when necessary. Furthermore, a combination of ReplicateOp and 1189 MergeHandlesOp can be used to construct arbitrary lists with repetitions. 1190 }]; 1191 1192 let arguments = (ins TransformHandleTypeInterface:$pattern, 1193 Variadic<Transform_AnyHandleOrParamType>:$handles); 1194 let results = (outs Variadic<Transform_AnyHandleOrParamType>:$replicated); 1195 let assemblyFormat = "`num` `(` $pattern `)` $handles attr-dict `:` " 1196 "type($pattern) `,` type($handles)"; 1197} 1198 1199def SelectOp : TransformDialectOp<"select", 1200 [DeclareOpInterfaceMethods<TransformOpInterface>, 1201 NavigationTransformOpTrait, MemoryEffectsOpInterface]> { 1202 let summary = "Select payload ops by name"; 1203 let description = [{ 1204 The handle defined by this Transform op corresponds to all operations among 1205 `target` that have the specified properties. Currently the following 1206 properties are supported: 1207 1208 - `op_name`: The op must have the specified name. 1209 1210 The result payload ops are in the same relative order as the targeted ops. 1211 This transform op reads the `target` handle and produces the `result` 1212 handle. It reads the payload, but does not modify it. 1213 }]; 1214 1215 let arguments = (ins TransformHandleTypeInterface:$target, 1216 StrAttr:$op_name); 1217 let results = (outs TransformHandleTypeInterface:$result); 1218 let assemblyFormat = [{ 1219 $op_name `in` $target attr-dict `:` functional-type(operands, results) 1220 }]; 1221} 1222 1223def SequenceOp : TransformDialectOp<"sequence", 1224 [DeclareOpInterfaceMethods<RegionBranchOpInterface, 1225 ["getEntrySuccessorOperands", "getSuccessorRegions", 1226 "getRegionInvocationBounds"]>, 1227 MatchOpInterface, 1228 DeclareOpInterfaceMethods<TransformOpInterface>, 1229 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 1230 OpAsmOpInterface, PossibleTopLevelTransformOpTrait, 1231 SingleBlockImplicitTerminator<"::mlir::transform::YieldOp">, 1232 AttrSizedOperandSegments]> { 1233 let summary = "Contains a sequence of other transform ops to apply"; 1234 let description = [{ 1235 The transformations indicated by the sequence are applied in order of their 1236 appearance. Each value produced by a transformation within the sequence 1237 corresponds to a group of operations or values in the payload IR, or to a 1238 group of parameters, depending on the type of the value. The behavior of the 1239 operation when a nested transformation produces a silenceable error is 1240 controlled by the `failure_propagation_mode` attribute. When set to 1241 `propagate`, the failure of any nested transformation in the sequence 1242 implies immediate failure of the entire sequence with a silenceable error, 1243 and no further transformation is attempted. When set to `suppress`, 1244 silenceable errors in nested operations are ignored and further 1245 transformations are applied. Beware that even silenceable errors may leave 1246 the payload IR in a state unsuitable for further transformations. It is the 1247 responsibility of the caller to ensure the following transformations are 1248 robust enough when errors are suppressed. Definite errors reported by nested 1249 transformations abort the sequence regardless of the propagation mode. The 1250 set of modes may be extended in the future, e.g., to collect silenceable 1251 errors and report them after attempting all transformations in the sequence. 1252 1253 The entry block of this operation has a single argument that maps to either 1254 the operand if provided or the top-level container operation of the payload 1255 IR, typically the root operation of the pass interpreting the transform 1256 dialect. Operand omission is only allowed for sequences not contained in 1257 another sequence. 1258 1259 The type of the block argument must match the type of the operand. If the 1260 sequence is a top-level transform (without an operand), it can be used for 1261 matching operations if the specified type within the top-level container 1262 payload IR (including the container op itself). E.g.: 1263 1264 ```mlir 1265 transform.sequence failures(propagate) { 1266 ^bb1(%arg1: !transform.any_op): 1267 // %arg1 is mapped to the top-level container of the payload IR, which is 1268 // typically a module 1269 } 1270 1271 transform.sequence failures(propagate) { 1272 ^bb1(%arg1: !transform.op<"func.func>"): 1273 // %arg1 is mapped to all "func.func" ops within and including the 1274 // top-level container of the payload IR. Nested operations that have the 1275 // specified op type are not included. 1276 } 1277 ``` 1278 1279 The body of the sequence terminates with an implicit or explicit 1280 `transform.yield` op. The operands of the terminator are returned as the 1281 results of the sequence op. 1282 }]; 1283 1284 let arguments = (ins FailurePropagationMode:$failure_propagation_mode, 1285 Optional<TransformHandleTypeInterface>:$root, 1286 Variadic<Transform_AnyHandleOrParamType>:$extra_bindings); 1287 let results = (outs Variadic<TransformHandleTypeInterface>:$results); 1288 let regions = (region SizedRegion<1>:$body); 1289 1290 let assemblyFormat = 1291 "custom<SequenceOpOperands>($root, type($root), $extra_bindings, type($extra_bindings))" 1292 " (`->` type($results)^)? `failures` `(` " 1293 "$failure_propagation_mode `)` attr-dict-with-keyword regions"; 1294 1295 let builders = [ 1296 // Build a sequence with a root. 1297 OpBuilder<(ins 1298 "::mlir::TypeRange":$resultTypes, 1299 "::mlir::transform::FailurePropagationMode":$failure_propagation_mode, 1300 "::mlir::Value":$root, "SequenceBodyBuilderFn":$bodyBuilder)>, 1301 1302 // Build a sequence with a root and additional arguments. 1303 OpBuilder<(ins 1304 "::mlir::TypeRange":$resultTypes, 1305 "::mlir::transform::FailurePropagationMode":$failure_propagation_mode, 1306 "::mlir::Value":$root, "::mlir::ValueRange":$extraBindings, 1307 "SequenceBodyBuilderArgsFn":$bodyBuilder)>, 1308 1309 // Build a top-level sequence (no root). 1310 OpBuilder<(ins 1311 "::mlir::TypeRange":$resultTypes, 1312 "::mlir::transform::FailurePropagationMode":$failure_propagation_mode, 1313 "::mlir::Type":$bbArgType, "SequenceBodyBuilderFn":$bodyBuilder)>, 1314 1315 // Build a top-level sequence (no root) with extra arguments. 1316 OpBuilder<(ins 1317 "::mlir::TypeRange":$resultTypes, 1318 "::mlir::transform::FailurePropagationMode":$failure_propagation_mode, 1319 "::mlir::Type":$bbArgType, "::mlir::TypeRange":$extraBindingTypes, 1320 "SequenceBodyBuilderArgsFn":$bodyBuilder)> 1321 ]; 1322 1323 let extraClassDeclaration = [{ 1324 /// Allow the dialect prefix to be omitted. 1325 static StringRef getDefaultDialect() { return "transform"; } 1326 }]; 1327 1328 let hasVerifier = 1; 1329} 1330 1331def VerifyOp : TransformDialectOp<"verify", 1332 [TransformOpInterface, TransformEachOpTrait, 1333 DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, 1334 ReportTrackingListenerFailuresOpTrait]> { 1335 let summary = "Verifies the targeted ops"; 1336 let description = [{ 1337 This transform verifies the targeted ops. If at least one op fails to 1338 verify, the transform produces a definite failure. 1339 1340 Note: This op was designed for debugging purposes and should be used like an 1341 assertion. It is intentional that this op produces a definite failure and 1342 not a silenceable one. Correctness of the program should not depend on this 1343 op. 1344 1345 This transform reads the target handle. 1346 }]; 1347 1348 let arguments = (ins TransformHandleTypeInterface:$target); 1349 let results = (outs); 1350 let assemblyFormat = "$target attr-dict `:` type($target)"; 1351 1352 let extraClassDeclaration = [{ 1353 ::mlir::DiagnosedSilenceableFailure applyToOne( 1354 ::mlir::transform::TransformRewriter &rewriter, 1355 ::mlir::Operation *target, 1356 ::mlir::transform::ApplyToEachResultList &results, 1357 ::mlir::transform::TransformState &state); 1358 }]; 1359} 1360 1361def YieldOp : TransformDialectOp<"yield", 1362 [Terminator, DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { 1363 let summary = "Yields operation handles from a transform IR region"; 1364 let description = [{ 1365 This terminator operation yields operation handles from regions of the 1366 transform IR ops back to the containing op. It is not itself associated with 1367 any transformation on the payload IR and is used for flow purposes only. 1368 }]; 1369 1370 let arguments = (ins 1371 Arg<Variadic<Transform_AnyHandleOrParamType>, 1372 "Transform values yielded back to the parent" 1373 >:$operands); 1374 let assemblyFormat = "operands attr-dict (`:` type($operands)^)?"; 1375 1376 let builders = [ 1377 OpBuilder<(ins), [{ 1378 return build($_builder, $_state, ::mlir::ValueRange()); 1379 }]> 1380 ]; 1381} 1382 1383#endif // MLIR_DIALECT_TRANSFORM_IR_TRANSFORMOPS 1384