Files
llvm/mlir/test/lib/Transforms/TestInlining.cpp
River Riddle 0ba0087887 Add the initial inlining infrastructure.
This defines a set of initial utilities for inlining a region(or a FuncOp), and defines a simple inliner pass for testing purposes.
A new dialect interface is defined, DialectInlinerInterface, that allows for dialects to override hooks controlling inlining legality. The interface currently provides the following hooks, but these are just premilinary and should be changed/added to/modified as necessary:

* isLegalToInline
  - Determine if a region can be inlined into one of this dialect, *or* if an operation of this dialect can be inlined into a given region.

* shouldAnalyzeRecursively
  - Determine if an operation with regions should be analyzed recursively for legality. This allows for child operations to be closed off from the legality checks for operations like lambdas.

* handleTerminator
  - Process a terminator that has been inlined.

This cl adds support for inlining StandardOps, but other dialects will be added in followups as necessary.

PiperOrigin-RevId: 267426759
2019-09-05 12:24:13 -07:00

74 lines
2.7 KiB
C++

//===- TestInlining.cpp - Pass to inline calls in the test dialect --------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// TODO(riverriddle) This pass is only necessary because the main inlining pass
// has no abstracted away the call+callee relationship. When the inlining
// interface has this support, this pass should be removed.
//
//===----------------------------------------------------------------------===//
#include "TestDialect.h"
#include "mlir/Dialect/StandardOps/Ops.h"
#include "mlir/IR/Function.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/InliningUtils.h"
#include "mlir/Transforms/Passes.h"
#include "llvm/ADT/StringSet.h"
using namespace mlir;
namespace {
struct Inliner : public FunctionPass<Inliner> {
void runOnFunction() override {
auto function = getFunction();
// Collect each of the direct function calls within the module.
SmallVector<CallIndirectOp, 16> callers;
function.walk([&](CallIndirectOp caller) { callers.push_back(caller); });
// Build the inliner interface.
InlinerInterface interface(&getContext());
// Try to inline each of the call operations.
for (auto caller : callers) {
auto callee = dyn_cast_or_null<FunctionalRegionOp>(
caller.getCallee()->getDefiningOp());
if (!callee)
continue;
// Inline the functional region operation, but only clone the internal
// region if there is more than one use.
if (failed(inlineRegion(
interface, &callee.body(), caller,
llvm::to_vector<8>(caller.getArgOperands()),
llvm::to_vector<8>(caller.getResults()), caller.getLoc(),
/*shouldCloneInlinedRegion=*/!callee.getResult()->hasOneUse())))
continue;
// If the inlining was successful then erase the call and callee if
// possible.
caller.erase();
if (callee.use_empty())
callee.erase();
}
}
};
} // end anonymous namespace
static PassRegistration<Inliner> pass("test-inline",
"Test inlining region calls");