1572fa964SMogball //===- ControlFlowSink.cpp - Code to perform control-flow sinking ---------===//
2572fa964SMogball //
3572fa964SMogball // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4572fa964SMogball // See https://llvm.org/LICENSE.txt for license information.
5572fa964SMogball // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6572fa964SMogball //
7572fa964SMogball //===----------------------------------------------------------------------===//
8572fa964SMogball //
9572fa964SMogball // This file implements a basic control-flow sink pass. Control-flow sinking
10572fa964SMogball // moves operations whose only uses are in conditionally-executed blocks in to
11572fa964SMogball // those blocks so that they aren't executed on paths where their results are
12572fa964SMogball // not needed.
13572fa964SMogball //
14572fa964SMogball //===----------------------------------------------------------------------===//
15572fa964SMogball 
16572fa964SMogball #include "PassDetail.h"
17572fa964SMogball #include "mlir/IR/Dominance.h"
18572fa964SMogball #include "mlir/Interfaces/ControlFlowInterfaces.h"
1936d3efeaSRiver Riddle #include "mlir/Interfaces/SideEffectInterfaces.h"
20a70aa7bbSRiver Riddle #include "mlir/Transforms/ControlFlowSinkUtils.h"
21572fa964SMogball #include "mlir/Transforms/Passes.h"
22*fa26c7ffSMogball #include "mlir/Transforms/SideEffectUtils.h"
23572fa964SMogball 
24572fa964SMogball using namespace mlir;
25572fa964SMogball 
26572fa964SMogball namespace {
273628febcSMogball /// A control-flow sink pass.
28572fa964SMogball struct ControlFlowSink : public ControlFlowSinkBase<ControlFlowSink> {
29572fa964SMogball   void runOnOperation() override;
30572fa964SMogball };
31572fa964SMogball } // end anonymous namespace
32572fa964SMogball 
runOnOperation()33572fa964SMogball void ControlFlowSink::runOnOperation() {
34572fa964SMogball   auto &domInfo = getAnalysis<DominanceInfo>();
35572fa964SMogball   getOperation()->walk([&](RegionBranchOpInterface branch) {
36572fa964SMogball     SmallVector<Region *> regionsToSink;
373628febcSMogball     // Get the regions are that known to be executed at most once.
38572fa964SMogball     getSinglyExecutedRegionsToSink(branch, regionsToSink);
393628febcSMogball     // Sink side-effect free operations.
40b73f1d2cSMogball     numSunk = controlFlowSink(
41b73f1d2cSMogball         regionsToSink, domInfo,
42b73f1d2cSMogball         [](Operation *op, Region *) { return isSideEffectFree(op); },
43b73f1d2cSMogball         [](Operation *op, Region *region) {
44b73f1d2cSMogball           // Move the operation to the beginning of the region's entry block.
45b73f1d2cSMogball           // This guarantees the preservation of SSA dominance of all of the
46b73f1d2cSMogball           // operation's uses are in the region.
47b73f1d2cSMogball           op->moveBefore(&region->front(), region->front().begin());
483628febcSMogball         });
49572fa964SMogball   });
50572fa964SMogball }
51572fa964SMogball 
createControlFlowSinkPass()52572fa964SMogball std::unique_ptr<Pass> mlir::createControlFlowSinkPass() {
53572fa964SMogball   return std::make_unique<ControlFlowSink>();
54572fa964SMogball }
55