1 //===- ControlFlowSinkUtils.h - ControlFlow Sink Utils ----------*- 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 #ifndef MLIR_TRANSFORMS_CONTROLFLOWSINKUTILS_H 10 #define MLIR_TRANSFORMS_CONTROLFLOWSINKUTILS_H 11 12 #include "mlir/Support/LLVM.h" 13 14 namespace mlir { 15 16 class DominanceInfo; 17 class Operation; 18 class Region; 19 class RegionBranchOpInterface; 20 class RegionRange; 21 22 /// Given a list of regions, perform control flow sinking on them. For each 23 /// region, control-flow sinking moves operations that dominate the region but 24 /// whose only users are in the region into the regions so that they aren't 25 /// executed on paths where their results are not needed. 26 /// 27 /// TODO: For the moment, this is a *simple* control-flow sink, i.e., no 28 /// duplicating of ops. It should be made to accept a cost model to determine 29 /// whether duplicating a particular op is profitable. 30 /// 31 /// Example: 32 /// 33 /// ```mlir 34 /// %0 = arith.addi %arg0, %arg1 35 /// scf.if %cond { 36 /// scf.yield %0 37 /// } else { 38 /// scf.yield %arg2 39 /// } 40 /// ``` 41 /// 42 /// After control-flow sink: 43 /// 44 /// ```mlir 45 /// scf.if %cond { 46 /// %0 = arith.addi %arg0, %arg1 47 /// scf.yield %0 48 /// } else { 49 /// scf.yield %arg2 50 /// } 51 /// ``` 52 /// 53 /// Users must supply a callback `shouldMoveIntoRegion` that determines whether 54 /// the given operation that only has users in the given operation should be 55 /// moved into that region. If this returns true, `moveIntoRegion` is called on 56 /// the same operation and region. 57 /// 58 /// `moveIntoRegion` must move the operation into the region such that dominance 59 /// of the operation is preserved; for example, by moving the operation to the 60 /// start of the entry block. This ensures the preservation of SSA dominance of 61 /// the operation's results. 62 /// 63 /// Returns the number of operations sunk. 64 size_t 65 controlFlowSink(RegionRange regions, DominanceInfo &domInfo, 66 function_ref<bool(Operation *, Region *)> shouldMoveIntoRegion, 67 function_ref<void(Operation *, Region *)> moveIntoRegion); 68 69 /// Populates `regions` with regions of the provided region branch op that are 70 /// executed at most once at that are reachable given the current operands of 71 /// the op. These regions can be passed to `controlFlowSink` to perform sinking 72 /// on the regions of the operation. 73 void getSinglyExecutedRegionsToSink(RegionBranchOpInterface branch, 74 SmallVectorImpl<Region *> ®ions); 75 76 } // namespace mlir 77 78 #endif // MLIR_TRANSFORMS_CONTROLFLOWSINKUTILS_H 79