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 "PassDetail.h"
17 #include "mlir/IR/Dominance.h"
18 #include "mlir/Interfaces/ControlFlowInterfaces.h"
19 #include "mlir/Interfaces/SideEffectInterfaces.h"
20 #include "mlir/Transforms/ControlFlowSinkUtils.h"
21 #include "mlir/Transforms/Passes.h"
22 #include "mlir/Transforms/SideEffectUtils.h"
23 
24 using namespace mlir;
25 
26 namespace {
27 /// A control-flow sink pass.
28 struct ControlFlowSink : public ControlFlowSinkBase<ControlFlowSink> {
29   void runOnOperation() override;
30 };
31 } // end anonymous namespace
32 
runOnOperation()33 void ControlFlowSink::runOnOperation() {
34   auto &domInfo = getAnalysis<DominanceInfo>();
35   getOperation()->walk([&](RegionBranchOpInterface branch) {
36     SmallVector<Region *> regionsToSink;
37     // Get the regions are that known to be executed at most once.
38     getSinglyExecutedRegionsToSink(branch, regionsToSink);
39     // Sink side-effect free operations.
40     numSunk = controlFlowSink(
41         regionsToSink, domInfo,
42         [](Operation *op, Region *) { return isSideEffectFree(op); },
43         [](Operation *op, Region *region) {
44           // Move the operation to the beginning of the region's entry block.
45           // This guarantees the preservation of SSA dominance of all of the
46           // operation's uses are in the region.
47           op->moveBefore(&region->front(), region->front().begin());
48         });
49   });
50 }
51 
createControlFlowSinkPass()52 std::unique_ptr<Pass> mlir::createControlFlowSinkPass() {
53   return std::make_unique<ControlFlowSink>();
54 }
55