1 //===- SCFOps.h - Structured Control Flow -----------------------*- C++ -*-===//
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 defines structured control flow operations.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_DIALECT_SCF_H_
14 #define MLIR_DIALECT_SCF_H_
15 
16 #include "mlir/IR/Attributes.h"
17 #include "mlir/IR/Builders.h"
18 #include "mlir/IR/Dialect.h"
19 #include "mlir/IR/OpDefinition.h"
20 #include "mlir/Interfaces/ControlFlowInterfaces.h"
21 #include "mlir/Interfaces/LoopLikeInterface.h"
22 #include "mlir/Interfaces/SideEffectInterfaces.h"
23 
24 namespace mlir {
25 namespace scf {
26 void buildTerminatedBody(OpBuilder &builder, Location loc);
27 } // namespace scf
28 } // namespace mlir
29 
30 #include "mlir/Dialect/SCF/SCFOpsDialect.h.inc"
31 
32 #define GET_OP_CLASSES
33 #include "mlir/Dialect/SCF/SCFOps.h.inc"
34 
35 namespace mlir {
36 namespace scf {
37 
38 // Insert `loop.yield` at the end of the only region's only block if it
39 // does not have a terminator already.  If a new `loop.yield` is inserted,
40 // the location is specified by `loc`. If the region is empty, insert a new
41 // block first.
42 void ensureLoopTerminator(Region &region, Builder &builder, Location loc);
43 
44 /// Returns the loop parent of an induction variable. If the provided value is
45 /// not an induction variable, then return nullptr.
46 ForOp getForInductionVarOwner(Value val);
47 
48 /// Returns the parallel loop parent of an induction variable. If the provided
49 /// value is not an induction variable, then return nullptr.
50 ParallelOp getParallelForInductionVarOwner(Value val);
51 
52 /// An owning vector of values, handy to return from functions.
53 using ValueVector = std::vector<Value>;
54 using LoopVector = std::vector<scf::ForOp>;
55 struct LoopNest {
getResultsLoopNest56   ResultRange getResults() { return loops.front().getResults(); }
57   LoopVector loops;
58 };
59 
60 /// Creates a perfect nest of "for" loops, i.e. all loops but the innermost
61 /// contain only another loop and a terminator. The lower, upper bounds and
62 /// steps are provided as `lbs`, `ubs` and `steps`, which are expected to be of
63 /// the same size. `iterArgs` points to the initial values of the loop iteration
64 /// arguments, which will be forwarded through the nest to the innermost loop.
65 /// The body of the loop is populated using `bodyBuilder`, which accepts an
66 /// ordered list of induction variables of all loops, followed by a list of
67 /// iteration arguments of the innermost loop, in the same order as provided to
68 /// `iterArgs`. This function is expected to return as many values as
69 /// `iterArgs`, of the same type and in the same order, that will be treated as
70 /// yielded from the loop body and forwarded back through the loop nest. If the
71 /// function is not provided, the loop nest is not expected to have iteration
72 /// arguments, the body of the innermost loop will be left empty, containing
73 /// only the zero-operand terminator. Returns the LoopNest containing the list
74 /// of perfectly nest scf::ForOp build during the call.
75 /// If bound arrays are empty, the body builder will be called
76 /// once to construct the IR outside of the loop with an empty list of induction
77 /// variables.
78 LoopNest buildLoopNest(
79     OpBuilder &builder, Location loc, ValueRange lbs, ValueRange ubs,
80     ValueRange steps, ValueRange iterArgs,
81     function_ref<ValueVector(OpBuilder &, Location, ValueRange, ValueRange)>
82         bodyBuilder = nullptr);
83 
84 /// A convenience version for building loop nests without iteration arguments
85 /// (like for reductions). Does not take the initial value of reductions or
86 /// expect the body building functions to return their current value.
87 /// The built nested scf::For are captured in `capturedLoops` when non-null.
88 LoopNest buildLoopNest(OpBuilder &builder, Location loc, ValueRange lbs,
89                           ValueRange ubs, ValueRange steps,
90                           function_ref<void(OpBuilder &, Location, ValueRange)>
91                               bodyBuilder = nullptr);
92 
93 } // end namespace scf
94 } // end namespace mlir
95 #endif // MLIR_DIALECT_SCF_H_
96