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