xref: /llvm-project/mlir/include/mlir/Dialect/SCF/Transforms/Passes.td (revision 1549a0c183ee337a6de4c3933e10828808c6a094)
1//===-- Passes.td - SCF pass definition file ---------------*- 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_SCF_PASSES
10#define MLIR_DIALECT_SCF_PASSES
11
12include "mlir/Pass/PassBase.td"
13
14// Note: Making these canonicalization patterns would require a dependency
15// of the SCF dialect on the Affine/Tensor/MemRef dialects or vice versa.
16def SCFForLoopCanonicalization
17    : Pass<"scf-for-loop-canonicalization"> {
18  let summary = "Canonicalize operations within scf.for loop bodies";
19  let constructor = "mlir::createSCFForLoopCanonicalizationPass()";
20  let dependentDialects = ["affine::AffineDialect", "tensor::TensorDialect",
21                           "memref::MemRefDialect"];
22}
23
24def SCFForLoopPeeling : Pass<"scf-for-loop-peeling"> {
25  let summary = "Peel `for` loops at their upper bounds.";
26  let constructor = "mlir::createForLoopPeelingPass()";
27  let options = [
28    Option<"peelFront", "peel-front", "bool",
29           /*default=*/"false",
30           "Peel the first iteration out of the loop.">,
31    Option<"skipPartial", "skip-partial", "bool",
32           /*default=*/"true",
33           "Do not peel loops inside of the last, partial iteration of another "
34           "already peeled loop.">
35  ];
36  let dependentDialects = ["affine::AffineDialect"];
37}
38
39def SCFForLoopSpecialization : Pass<"scf-for-loop-specialization"> {
40  let summary = "Specialize `for` loops for vectorization";
41  let constructor = "mlir::createForLoopSpecializationPass()";
42}
43
44def SCFParallelLoopFusion : Pass<"scf-parallel-loop-fusion"> {
45  let summary = "Fuse adjacent parallel loops";
46  let constructor = "mlir::createParallelLoopFusionPass()";
47}
48
49def TestSCFParallelLoopCollapsing : Pass<"test-scf-parallel-loop-collapsing"> {
50  let summary = "Test parallel loops collapsing transformation";
51  let constructor = "mlir::createTestSCFParallelLoopCollapsingPass()";
52  let dependentDialects = ["affine::AffineDialect"];
53  let description = [{
54      This pass is purely for testing the scf::collapseParallelLoops
55      transformation. The transformation does not have opinions on how a
56      parallel loop should be collapsed, so this pass is structured for the
57      common case on GPUs of collapsing to a 3d parallel loop. 3 lists can be
58      provided to collapsed-indices-{0,1,2} to represent how the loop should be
59      collapsed and must reference evrey iterator in the original parallel loop.
60
61    ```mlir
62    # Before:
63    scf.parallel (%arg0, %arg1)
64                 = (%c0, %c0) to (%c2, %c2) step (%c1, %c1) {
65      "test.sink"(%5, %3) : (index, index) -> ()
66      scf.yield
67    }
68
69    # After:
70    scf.parallel (%arg0) = (%c0) to (%c4) step (%c1) {
71      %0 = arith.remsi %arg0, %c2 : index
72      %1 = arith.divsi %arg0, %c2 : index
73      %2 = arith.muli %0, %c7 : index
74      %3 = arith.addi %2, %c3 : index
75      %4 = arith.muli %1, %c7 : index
76      %5 = arith.addi %4, %c3 : index
77      "test.sink"(%5, %3) : (index, index) -> ()
78    }
79    ```
80  }];
81
82  let options = [
83    ListOption<"clCollapsedIndices0", "collapsed-indices-0", "unsigned",
84               "Which loop indices to combine 0th loop index">,
85    ListOption<"clCollapsedIndices1", "collapsed-indices-1", "unsigned",
86               "Which loop indices to combine into the position 1 loop index">,
87    ListOption<"clCollapsedIndices2", "collapsed-indices-2", "unsigned",
88               "Which loop indices to combine into the position 2 loop index">,
89  ];
90}
91
92def SCFParallelLoopSpecialization
93    : Pass<"scf-parallel-loop-specialization"> {
94  let summary = "Specialize parallel loops for vectorization";
95  let constructor = "mlir::createParallelLoopSpecializationPass()";
96}
97
98def SCFParallelLoopTiling : Pass<"scf-parallel-loop-tiling"> {
99  let summary = "Tile parallel loops";
100  let constructor = "mlir::createParallelLoopTilingPass()";
101  let options = [
102    ListOption<"tileSizes", "parallel-loop-tile-sizes", "int64_t",
103               "Factors to tile parallel loops by">,
104    Option<"noMinMaxBounds", "no-min-max-bounds", "bool",
105           /*default=*/"false",
106           "Perform tiling with fixed upper bound with inbound check "
107           "inside the internal loops">
108  ];
109  let dependentDialects = ["affine::AffineDialect"];
110}
111
112def SCFForLoopRangeFolding : Pass<"scf-for-loop-range-folding"> {
113  let summary = "Fold add/mul ops into loop range";
114  let constructor = "mlir::createForLoopRangeFoldingPass()";
115}
116
117def SCFForallToForLoop : Pass<"scf-forall-to-for"> {
118  let summary = "Convert SCF forall loops to SCF for loops";
119  let constructor = "mlir::createForallToForLoopPass()";
120}
121
122def SCFForallToParallelLoop : Pass<"scf-forall-to-parallel"> {
123  let summary = "Convert SCF forall loops to SCF parallel loops";
124  let constructor = "mlir::createForallToParallelLoopPass()";
125}
126
127def SCFForToWhileLoop : Pass<"scf-for-to-while"> {
128  let summary = "Convert SCF for loops to SCF while loops";
129  let constructor = "mlir::createForToWhileLoopPass()";
130  let description = [{
131    This pass transforms SCF.ForOp operations to SCF.WhileOp. The For loop
132    condition is placed in the 'before' region of the while operation, and the
133    induction variable incrementation and loop body in the 'after' region.
134    The loop carried values of the while op are the induction variable (IV) of
135    the for-loop + any iter_args specified for the for-loop.
136    Any 'yield' ops in the for-loop are rewritten to additionally yield the
137    (incremented) induction variable.
138
139    ```mlir
140    # Before:
141      scf.for %i = %c0 to %arg1 step %c1 {
142        %0 = arith.addi %arg2, %arg2 : i32
143        memref.store %0, %arg0[%i] : memref<?xi32>
144      }
145
146    # After:
147      %0 = scf.while (%i = %c0) : (index) -> index {
148        %1 = arith.cmpi slt, %i, %arg1 : index
149        scf.condition(%1) %i : index
150      } do {
151      ^bb0(%i: index):
152        %1 = arith.addi %i, %c1 : index
153        %2 = arith.addi %arg2, %arg2 : i32
154        memref.store %2, %arg0[%i] : memref<?xi32>
155        scf.yield %1 : index
156      }
157    ```
158  }];
159}
160
161#endif // MLIR_DIALECT_SCF_PASSES
162