//===- ControlFlowSinkUtils.h - ControlFlow Sink Utils ----------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef MLIR_TRANSFORMS_CONTROLFLOWSINKUTILS_H #define MLIR_TRANSFORMS_CONTROLFLOWSINKUTILS_H #include "mlir/Support/LLVM.h" namespace mlir { class DominanceInfo; class Operation; class Region; class RegionBranchOpInterface; class RegionRange; /// Given a list of regions, perform control flow sinking on them. For each /// region, control-flow sinking moves operations that dominate the region but /// whose only users are in the region into the regions so that they aren't /// executed on paths where their results are not needed. /// /// TODO: For the moment, this is a *simple* control-flow sink, i.e., no /// duplicating of ops. It should be made to accept a cost model to determine /// whether duplicating a particular op is profitable. /// /// Example: /// /// ```mlir /// %0 = arith.addi %arg0, %arg1 /// scf.if %cond { /// scf.yield %0 /// } else { /// scf.yield %arg2 /// } /// ``` /// /// After control-flow sink: /// /// ```mlir /// scf.if %cond { /// %0 = arith.addi %arg0, %arg1 /// scf.yield %0 /// } else { /// scf.yield %arg2 /// } /// ``` /// /// Users must supply a callback `shouldMoveIntoRegion` that determines whether /// the given operation that only has users in the given operation should be /// moved into that region. If this returns true, `moveIntoRegion` is called on /// the same operation and region. /// /// `moveIntoRegion` must move the operation into the region such that dominance /// of the operation is preserved; for example, by moving the operation to the /// start of the entry block. This ensures the preservation of SSA dominance of /// the operation's results. /// /// Returns the number of operations sunk. size_t controlFlowSink(RegionRange regions, DominanceInfo &domInfo, function_ref<bool(Operation *, Region *)> shouldMoveIntoRegion, function_ref<void(Operation *, Region *)> moveIntoRegion); /// Populates `regions` with regions of the provided region branch op that are /// executed at most once at that are reachable given the current operands of /// the op. These regions can be passed to `controlFlowSink` to perform sinking /// on the regions of the operation. void getSinglyExecutedRegionsToSink(RegionBranchOpInterface branch, SmallVectorImpl<Region *> ®ions); } // namespace mlir #endif // MLIR_TRANSFORMS_CONTROLFLOWSINKUTILS_H