1//===- SCFTransformOps.td - SCF (loop) transformation ops --*- 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 SCF_TRANSFORM_OPS 10#define SCF_TRANSFORM_OPS 11 12include "mlir/Dialect/Transform/IR/TransformDialect.td" 13include "mlir/Dialect/Transform/IR/TransformEffects.td" 14include "mlir/Dialect/Transform/IR/TransformInterfaces.td" 15include "mlir/Dialect/PDL/IR/PDLTypes.td" 16include "mlir/Interfaces/SideEffectInterfaces.td" 17include "mlir/IR/OpBase.td" 18 19def GetParentForOp : Op<Transform_Dialect, "loop.get_parent_for", 20 [NavigationTransformOpTrait, MemoryEffectsOpInterface, 21 DeclareOpInterfaceMethods<TransformOpInterface>]> { 22 let summary = "Gets a handle to the parent 'for' loop of the given operation"; 23 let description = [{ 24 Produces a handle to the n-th (default 1) parent `scf.for` loop for each 25 Payload IR operation associated with the operand. Fails if such a loop 26 cannot be found. The list of operations associated with the handle contains 27 parent operations in the same order as the list associated with the operand, 28 except for operations that are parents to more than one input which are only 29 present once. 30 }]; 31 32 let arguments = 33 (ins PDL_Operation:$target, 34 DefaultValuedAttr<Confined<I64Attr, [IntPositive]>, 35 "1">:$num_loops); 36 let results = (outs PDL_Operation:$parent); 37 38 let assemblyFormat = "$target attr-dict"; 39} 40 41def LoopOutlineOp : Op<Transform_Dialect, "loop.outline", 42 [FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface, 43 DeclareOpInterfaceMethods<TransformOpInterface>]> { 44 let summary = "Outlines a loop into a named function"; 45 let description = [{ 46 Moves the loop into a separate function with the specified name and 47 replaces the loop in the Payload IR with a call to that function. Takes 48 care of forwarding values that are used in the loop as function arguments. 49 If the operand is associated with more than one loop, each loop will be 50 outlined into a separate function. The provided name is used as a _base_ 51 for forming actual function names following SymbolTable auto-renaming 52 scheme to avoid duplicate symbols. Expects that all ops in the Payload IR 53 have a SymbolTable ancestor (typically true because of the top-level 54 module). Returns the handle to the list of outlined functions in the same 55 order as the operand handle. 56 }]; 57 58 let arguments = (ins PDL_Operation:$target, 59 StrAttr:$func_name); 60 let results = (outs PDL_Operation:$transformed); 61 62 let assemblyFormat = "$target attr-dict"; 63} 64 65def LoopPeelOp : Op<Transform_Dialect, "loop.peel", 66 [FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface, 67 TransformOpInterface, TransformEachOpTrait]> { 68 let summary = "Peels the last iteration of the loop"; 69 let description = [{ 70 Updates the given loop so that its step evenly divides its range and puts 71 the remaining iteration into a separate loop or a conditional. 72 73 In the absence of sufficient static information, this op may peel a loop, 74 even if the step always divides the range evenly at runtime. 75 76 #### Return modes 77 78 This operation ignores non-scf::ForOp ops and drops them in the return. 79 80 This operation always succeeds and returns the scf::ForOp with the 81 postcondition: "the loop trip count is divisible by the step". 82 This operation may return the same unmodified loop handle when peeling did 83 not modify the IR (i.e. the loop trip count was already divisible). 84 85 Note that even though the Payload IR modification may be performed 86 in-place, this operation consumes the operand handle and produces a new 87 one. 88 89 TODO: Return both the peeled loop and the remainder loop. 90 }]; 91 92 let arguments = 93 (ins PDL_Operation:$target, 94 DefaultValuedAttr<BoolAttr, "false">:$fail_if_already_divisible); 95 // TODO: Return both the peeled loop and the remainder loop. 96 let results = (outs PDL_Operation:$transformed); 97 98 let assemblyFormat = "$target attr-dict"; 99 100 let extraClassDeclaration = [{ 101 ::mlir::DiagnosedSilenceableFailure applyToOne( 102 ::mlir::scf::ForOp target, 103 ::llvm::SmallVector<::mlir::Operation *> &results, 104 ::mlir::transform::TransformState &state); 105 }]; 106} 107 108def LoopPipelineOp : Op<Transform_Dialect, "loop.pipeline", 109 [FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface, 110 TransformOpInterface, TransformEachOpTrait]> { 111 let summary = "Applies software pipelining to the loop"; 112 let description = [{ 113 Transforms the given loops one by one to achieve software pipelining for 114 each of them. That is, performs some amount of reads from memory before the 115 loop rather than inside the loop, the same amount of writes into memory 116 after the loop, and updates each iteration to read the data for a following 117 iteration rather than the current one. 118 119 The amount is specified by the attributes. 120 121 The values read and about to be stored are transferred as loop iteration 122 arguments. Currently supports memref and vector transfer operations as 123 memory reads/writes. 124 125 #### Return modes 126 127 This operation ignores non-scf::For ops and drops them in the return. 128 If all the operations referred to by the `target` PDLOperation pipeline 129 properly, the transform succeeds. Otherwise the transform silently fails. 130 The return handle points to only the subset of successfully produced 131 pipelined loops, which can be empty. 132 }]; 133 134 let arguments = (ins PDL_Operation:$target, 135 DefaultValuedAttr<I64Attr, "1">:$iteration_interval, 136 DefaultValuedAttr<I64Attr, "10">:$read_latency); 137 let results = (outs PDL_Operation:$transformed); 138 139 let assemblyFormat = "$target attr-dict"; 140 141 let extraClassDeclaration = [{ 142 ::mlir::DiagnosedSilenceableFailure applyToOne( 143 ::mlir::scf::ForOp target, 144 ::llvm::SmallVector<::mlir::Operation *> &results, 145 ::mlir::transform::TransformState &state); 146 }]; 147} 148 149def LoopUnrollOp : Op<Transform_Dialect, "loop.unroll", 150 [FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface, 151 TransformOpInterface, TransformEachOpTrait]> { 152 let summary = "Unrolls the given loop with the given unroll factor"; 153 let description = [{ 154 Unrolls each loop associated with the given handle to have up to the given 155 number of loop body copies per iteration. If the unroll factor is larger 156 than the loop trip count, the latter is used as the unroll factor instead. 157 158 #### Return modes 159 160 This operation ignores non-scf::For ops and drops them in the return. 161 If all the operations referred to by the `target` PDLOperation unroll 162 properly, the transform succeeds. Otherwise the transform silently fails. 163 164 Does not return handles as the operation may result in the loop being 165 removed after a full unrolling. 166 }]; 167 168 let arguments = (ins PDL_Operation:$target, 169 Confined<I64Attr, [IntPositive]>:$factor); 170 171 let assemblyFormat = "$target attr-dict"; 172 173 let extraClassDeclaration = [{ 174 ::mlir::DiagnosedSilenceableFailure applyToOne( 175 ::mlir::scf::ForOp target, 176 ::llvm::SmallVector<::mlir::Operation *> &results, 177 ::mlir::transform::TransformState &state); 178 }]; 179} 180 181#endif // SCF_TRANSFORM_OPS 182