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