1 //===- ControlFlowSink.cpp - Code to perform control-flow sinking ---------===// 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 implements a basic control-flow sink pass. Control-flow sinking 10 // moves operations whose only uses are in conditionally-executed blocks in to 11 // those blocks so that they aren't executed on paths where their results are 12 // not needed. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "mlir/Transforms/Passes.h" 17 18 #include "mlir/IR/Dominance.h" 19 #include "mlir/Interfaces/ControlFlowInterfaces.h" 20 #include "mlir/Interfaces/SideEffectInterfaces.h" 21 #include "mlir/Transforms/ControlFlowSinkUtils.h" 22 23 namespace mlir { 24 #define GEN_PASS_DEF_CONTROLFLOWSINK 25 #include "mlir/Transforms/Passes.h.inc" 26 } // namespace mlir 27 28 using namespace mlir; 29 30 namespace { 31 /// A control-flow sink pass. 32 struct ControlFlowSink : public impl::ControlFlowSinkBase<ControlFlowSink> { 33 void runOnOperation() override; 34 }; 35 } // end anonymous namespace 36 runOnOperation()37void ControlFlowSink::runOnOperation() { 38 auto &domInfo = getAnalysis<DominanceInfo>(); 39 getOperation()->walk([&](RegionBranchOpInterface branch) { 40 SmallVector<Region *> regionsToSink; 41 // Get the regions are that known to be executed at most once. 42 getSinglyExecutedRegionsToSink(branch, regionsToSink); 43 // Sink side-effect free operations. 44 numSunk = controlFlowSink( 45 regionsToSink, domInfo, 46 [](Operation *op, Region *) { return isMemoryEffectFree(op); }, 47 [](Operation *op, Region *region) { 48 // Move the operation to the beginning of the region's entry block. 49 // This guarantees the preservation of SSA dominance of all of the 50 // operation's uses are in the region. 51 op->moveBefore(®ion->front(), region->front().begin()); 52 }); 53 }); 54 } 55 createControlFlowSinkPass()56std::unique_ptr<Pass> mlir::createControlFlowSinkPass() { 57 return std::make_unique<ControlFlowSink>(); 58 } 59