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 100ba00878SRiver Riddle // has no 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" 1669d757c0SRob Suderman #include "mlir/Dialect/StandardOps/IR/Ops.h" 178472ae17SJacques Pienaar #include "mlir/IR/BlockAndValueMapping.h" 18*65fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h" 190ba00878SRiver Riddle #include "mlir/Pass/Pass.h" 200ba00878SRiver Riddle #include "mlir/Transforms/InliningUtils.h" 210ba00878SRiver Riddle #include "mlir/Transforms/Passes.h" 220ba00878SRiver Riddle #include "llvm/ADT/StringSet.h" 230ba00878SRiver Riddle 240ba00878SRiver Riddle using namespace mlir; 2572c65b69SAlexander Belyaev using namespace mlir::test; 260ba00878SRiver Riddle 270ba00878SRiver Riddle namespace { 2880aca1eaSRiver Riddle struct Inliner : public PassWrapper<Inliner, FunctionPass> { 290ba00878SRiver Riddle void runOnFunction() override { 300ba00878SRiver Riddle auto function = getFunction(); 310ba00878SRiver Riddle 320ba00878SRiver Riddle // Collect each of the direct function calls within the module. 330ba00878SRiver Riddle SmallVector<CallIndirectOp, 16> callers; 340ba00878SRiver Riddle function.walk([&](CallIndirectOp caller) { callers.push_back(caller); }); 350ba00878SRiver Riddle 360ba00878SRiver Riddle // Build the inliner interface. 370ba00878SRiver Riddle InlinerInterface interface(&getContext()); 380ba00878SRiver Riddle 390ba00878SRiver Riddle // Try to inline each of the call operations. 400ba00878SRiver Riddle for (auto caller : callers) { 410ba00878SRiver Riddle auto callee = dyn_cast_or_null<FunctionalRegionOp>( 422bdf33ccSRiver Riddle caller.getCallee().getDefiningOp()); 430ba00878SRiver Riddle if (!callee) 440ba00878SRiver Riddle continue; 450ba00878SRiver Riddle 460ba00878SRiver Riddle // Inline the functional region operation, but only clone the internal 470ba00878SRiver Riddle // region if there is more than one use. 480ba00878SRiver Riddle if (failed(inlineRegion( 4922219cfcSSean Silva interface, &callee.body(), caller, caller.getArgOperands(), 50b87531caSRiver Riddle caller.getResults(), caller.getLoc(), 512bdf33ccSRiver Riddle /*shouldCloneInlinedRegion=*/!callee.getResult().hasOneUse()))) 520ba00878SRiver Riddle continue; 530ba00878SRiver Riddle 540ba00878SRiver Riddle // If the inlining was successful then erase the call and callee if 550ba00878SRiver Riddle // possible. 560ba00878SRiver Riddle caller.erase(); 570ba00878SRiver Riddle if (callee.use_empty()) 580ba00878SRiver Riddle callee.erase(); 590ba00878SRiver Riddle } 600ba00878SRiver Riddle } 610ba00878SRiver Riddle }; 620ba00878SRiver Riddle } // end anonymous namespace 630ba00878SRiver Riddle 64c6477050SMehdi Amini namespace mlir { 6572c65b69SAlexander Belyaev namespace test { 66c6477050SMehdi Amini void registerInliner() { 67c6477050SMehdi Amini PassRegistration<Inliner>("test-inline", "Test inlining region calls"); 68c6477050SMehdi Amini } 6972c65b69SAlexander Belyaev } // namespace test 70c6477050SMehdi Amini } // namespace mlir 71