10ba00878SRiver Riddle //===- TestInlining.cpp - Pass to inline calls in the test dialect --------===//
20ba00878SRiver Riddle //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60ba00878SRiver Riddle //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
80ba00878SRiver Riddle //
99db53a18SRiver Riddle // TODO: This pass is only necessary because the main inlining pass
10*c7283c26SJaved Absar // has not abstracted away the call+callee relationship. When the inlining
110ba00878SRiver Riddle // interface has this support, this pass should be removed.
120ba00878SRiver Riddle //
130ba00878SRiver Riddle //===----------------------------------------------------------------------===//
140ba00878SRiver Riddle 
150ba00878SRiver Riddle #include "TestDialect.h"
1623aa5a74SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
178472ae17SJacques Pienaar #include "mlir/IR/BlockAndValueMapping.h"
1865fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
190ba00878SRiver Riddle #include "mlir/Pass/Pass.h"
200ba00878SRiver Riddle #include "mlir/Transforms/InliningUtils.h"
210ba00878SRiver Riddle #include "llvm/ADT/StringSet.h"
220ba00878SRiver Riddle 
230ba00878SRiver Riddle using namespace mlir;
247776b19eSStephen Neuendorffer using namespace test;
250ba00878SRiver Riddle 
260ba00878SRiver Riddle namespace {
2758ceae95SRiver Riddle struct Inliner : public PassWrapper<Inliner, OperationPass<func::FuncOp>> {
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon3f50e1be0111::Inliner285e50dd04SRiver Riddle   MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(Inliner)
295e50dd04SRiver Riddle 
30b5e22e6dSMehdi Amini   StringRef getArgument() const final { return "test-inline"; }
getDescription__anon3f50e1be0111::Inliner31b5e22e6dSMehdi Amini   StringRef getDescription() const final {
32b5e22e6dSMehdi Amini     return "Test inlining region calls";
33b5e22e6dSMehdi Amini   }
34b5e22e6dSMehdi Amini 
runOnOperation__anon3f50e1be0111::Inliner3541574554SRiver Riddle   void runOnOperation() override {
3641574554SRiver Riddle     auto function = getOperation();
370ba00878SRiver Riddle 
380ba00878SRiver Riddle     // Collect each of the direct function calls within the module.
3923aa5a74SRiver Riddle     SmallVector<func::CallIndirectOp, 16> callers;
4023aa5a74SRiver Riddle     function.walk(
4123aa5a74SRiver Riddle         [&](func::CallIndirectOp caller) { callers.push_back(caller); });
420ba00878SRiver Riddle 
430ba00878SRiver Riddle     // Build the inliner interface.
440ba00878SRiver Riddle     InlinerInterface interface(&getContext());
450ba00878SRiver Riddle 
460ba00878SRiver Riddle     // Try to inline each of the call operations.
470ba00878SRiver Riddle     for (auto caller : callers) {
480ba00878SRiver Riddle       auto callee = dyn_cast_or_null<FunctionalRegionOp>(
492bdf33ccSRiver Riddle           caller.getCallee().getDefiningOp());
500ba00878SRiver Riddle       if (!callee)
510ba00878SRiver Riddle         continue;
520ba00878SRiver Riddle 
530ba00878SRiver Riddle       // Inline the functional region operation, but only clone the internal
540ba00878SRiver Riddle       // region if there is more than one use.
550ba00878SRiver Riddle       if (failed(inlineRegion(
566a994233SJacques Pienaar               interface, &callee.getBody(), caller, caller.getArgOperands(),
57b87531caSRiver Riddle               caller.getResults(), caller.getLoc(),
582bdf33ccSRiver Riddle               /*shouldCloneInlinedRegion=*/!callee.getResult().hasOneUse())))
590ba00878SRiver Riddle         continue;
600ba00878SRiver Riddle 
610ba00878SRiver Riddle       // If the inlining was successful then erase the call and callee if
620ba00878SRiver Riddle       // possible.
630ba00878SRiver Riddle       caller.erase();
640ba00878SRiver Riddle       if (callee.use_empty())
650ba00878SRiver Riddle         callee.erase();
660ba00878SRiver Riddle     }
670ba00878SRiver Riddle   }
680ba00878SRiver Riddle };
69be0a7e9fSMehdi Amini } // namespace
700ba00878SRiver Riddle 
71c6477050SMehdi Amini namespace mlir {
7272c65b69SAlexander Belyaev namespace test {
registerInliner()73b5e22e6dSMehdi Amini void registerInliner() { PassRegistration<Inliner>(); }
7472c65b69SAlexander Belyaev } // namespace test
75c6477050SMehdi Amini } // namespace mlir
76