1 //===- TestInlining.cpp - Pass to inline calls in the test dialect --------===//
2 //
3 // Copyright 2019 The MLIR Authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // =============================================================================
17 //
18 // TODO(riverriddle) This pass is only necessary because the main inlining pass
19 // has no abstracted away the call+callee relationship. When the inlining
20 // interface has this support, this pass should be removed.
21 //
22 //===----------------------------------------------------------------------===//
23 
24 #include "TestDialect.h"
25 #include "mlir/Dialect/StandardOps/Ops.h"
26 #include "mlir/IR/Function.h"
27 #include "mlir/Pass/Pass.h"
28 #include "mlir/Transforms/InliningUtils.h"
29 #include "mlir/Transforms/Passes.h"
30 #include "llvm/ADT/StringSet.h"
31 
32 using namespace mlir;
33 
34 namespace {
35 struct Inliner : public FunctionPass<Inliner> {
36   void runOnFunction() override {
37     auto function = getFunction();
38 
39     // Collect each of the direct function calls within the module.
40     SmallVector<CallIndirectOp, 16> callers;
41     function.walk([&](CallIndirectOp caller) { callers.push_back(caller); });
42 
43     // Build the inliner interface.
44     InlinerInterface interface(&getContext());
45 
46     // Try to inline each of the call operations.
47     for (auto caller : callers) {
48       auto callee = dyn_cast_or_null<FunctionalRegionOp>(
49           caller.getCallee()->getDefiningOp());
50       if (!callee)
51         continue;
52 
53       // Inline the functional region operation, but only clone the internal
54       // region if there is more than one use.
55       if (failed(inlineRegion(
56               interface, &callee.body(), caller,
57               llvm::to_vector<8>(caller.getArgOperands()),
58               llvm::to_vector<8>(caller.getResults()), caller.getLoc(),
59               /*shouldCloneInlinedRegion=*/!callee.getResult()->hasOneUse())))
60         continue;
61 
62       // If the inlining was successful then erase the call and callee if
63       // possible.
64       caller.erase();
65       if (callee.use_empty())
66         callee.erase();
67     }
68   }
69 };
70 } // end anonymous namespace
71 
72 static PassRegistration<Inliner> pass("test-inline",
73                                       "Test inlining region calls");
74