163 lines
6.6 KiB
C++
163 lines
6.6 KiB
C++
//===- Inliner.h - Inliner pass utilities -----------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This header file declares utility structures for the inliner pass.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_TRANSFORMS_INLINER_H
|
|
#define MLIR_TRANSFORMS_INLINER_H
|
|
|
|
#include "mlir/Analysis/CallGraph.h"
|
|
#include "mlir/Interfaces/CallInterfaces.h"
|
|
#include "mlir/Pass/AnalysisManager.h"
|
|
#include "mlir/Pass/PassManager.h"
|
|
#include "mlir/Transforms/InliningUtils.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
|
|
namespace mlir {
|
|
class OpPassManager;
|
|
class Operation;
|
|
|
|
class InlinerConfig {
|
|
public:
|
|
using DefaultPipelineTy = std::function<void(OpPassManager &)>;
|
|
using OpPipelinesTy = llvm::StringMap<OpPassManager>;
|
|
|
|
InlinerConfig() = default;
|
|
InlinerConfig(DefaultPipelineTy defaultPipeline,
|
|
unsigned maxInliningIterations)
|
|
: defaultPipeline(std::move(defaultPipeline)),
|
|
maxInliningIterations(maxInliningIterations) {}
|
|
|
|
const DefaultPipelineTy &getDefaultPipeline() const {
|
|
return defaultPipeline;
|
|
}
|
|
const OpPipelinesTy &getOpPipelines() const { return opPipelines; }
|
|
unsigned getMaxInliningIterations() const { return maxInliningIterations; }
|
|
const InlinerInterface::CloneCallbackTy &getCloneCallback() const {
|
|
return cloneCallback;
|
|
}
|
|
bool getCanHandleMultipleBlocks() const { return canHandleMultipleBlocks; }
|
|
|
|
void setDefaultPipeline(DefaultPipelineTy pipeline) {
|
|
defaultPipeline = std::move(pipeline);
|
|
}
|
|
void setOpPipelines(OpPipelinesTy pipelines) {
|
|
opPipelines = std::move(pipelines);
|
|
}
|
|
void setMaxInliningIterations(unsigned max) { maxInliningIterations = max; }
|
|
void setCloneCallback(InlinerInterface::CloneCallbackTy callback) {
|
|
cloneCallback = std::move(callback);
|
|
}
|
|
void setCanHandleMultipleBlocks(bool value = true) {
|
|
canHandleMultipleBlocks = value;
|
|
}
|
|
|
|
private:
|
|
/// An optional function that constructs an optimization pipeline for
|
|
/// a given operation. This optimization pipeline is applied
|
|
/// only to those callable operations that do not have dedicated
|
|
/// optimization pipeline in opPipelines (based on the operation name).
|
|
DefaultPipelineTy defaultPipeline;
|
|
/// A map of operation names to pass pipelines to use when optimizing
|
|
/// callable operations of these types. This provides a specialized pipeline
|
|
/// instead of the one produced by defaultPipeline.
|
|
OpPipelinesTy opPipelines;
|
|
/// For SCC-based inlining algorithms, specifies maximum number of iterations
|
|
/// when inlining within an SCC.
|
|
unsigned maxInliningIterations{0};
|
|
/// Callback for cloning operations during inlining
|
|
InlinerInterface::CloneCallbackTy cloneCallback =
|
|
[](OpBuilder &builder, Region *src, Block *inlineBlock,
|
|
Block *postInsertBlock, IRMapping &mapper,
|
|
bool shouldCloneInlinedRegion) {
|
|
// Check to see if the region is being cloned, or moved inline. In
|
|
// either case, move the new blocks after the 'insertBlock' to improve
|
|
// IR readability.
|
|
Region *insertRegion = inlineBlock->getParent();
|
|
if (shouldCloneInlinedRegion)
|
|
src->cloneInto(insertRegion, postInsertBlock->getIterator(), mapper);
|
|
else
|
|
insertRegion->getBlocks().splice(postInsertBlock->getIterator(),
|
|
src->getBlocks(), src->begin(),
|
|
src->end());
|
|
};
|
|
/// Determine if the inliner can inline a function containing multiple
|
|
/// blocks into a region that requires a single block. By default, it is
|
|
/// not allowed. If it is true, cloneCallback should perform the extra
|
|
/// transformation. see the example in
|
|
/// mlir/test/lib/Transforms/TestInliningCallback.cpp
|
|
bool canHandleMultipleBlocks{false};
|
|
};
|
|
|
|
/// This is an implementation of the inliner
|
|
/// that operates bottom up over the Strongly Connected Components(SCCs)
|
|
/// of the CallGraph. This enables a more incremental propagation
|
|
/// of inlining decisions from the leafs to the roots of the callgraph.
|
|
class Inliner {
|
|
public:
|
|
/// This struct represents a resolved call to a given callgraph node. Given
|
|
/// that the call does not actually contain a direct reference to the
|
|
/// Region(CallGraphNode) that it is dispatching to, we need to resolve them
|
|
/// explicitly.
|
|
struct ResolvedCall {
|
|
ResolvedCall(CallOpInterface call, CallGraphNode *sourceNode,
|
|
CallGraphNode *targetNode)
|
|
: call(call), sourceNode(sourceNode), targetNode(targetNode) {}
|
|
CallOpInterface call;
|
|
CallGraphNode *sourceNode, *targetNode;
|
|
};
|
|
|
|
using RunPipelineHelperTy = std::function<LogicalResult(
|
|
Pass &pass, OpPassManager &pipeline, Operation *op)>;
|
|
|
|
/// Type of the callback answering if it is profitable
|
|
/// to inline a callable operation at a call site.
|
|
/// It might be the case that the ResolvedCall does not provide
|
|
/// enough context to make the profitability decision, so
|
|
/// this hook's interface might need to be extended in future.
|
|
using ProfitabilityCallbackTy = std::function<bool(const ResolvedCall &)>;
|
|
|
|
Inliner(Operation *op, CallGraph &cg, Pass &pass, AnalysisManager am,
|
|
RunPipelineHelperTy runPipelineHelper, const InlinerConfig &config,
|
|
ProfitabilityCallbackTy isProfitableToInline)
|
|
: op(op), cg(cg), pass(pass), am(am),
|
|
runPipelineHelper(std::move(runPipelineHelper)), config(config),
|
|
isProfitableToInline(std::move(isProfitableToInline)) {}
|
|
Inliner(Inliner &) = delete;
|
|
void operator=(const Inliner &) = delete;
|
|
|
|
/// Perform inlining on a OpTrait::SymbolTable operation.
|
|
LogicalResult doInlining();
|
|
|
|
private:
|
|
/// An OpTrait::SymbolTable operation to run the inlining on.
|
|
Operation *op;
|
|
/// A CallGraph analysis for the given operation.
|
|
CallGraph &cg;
|
|
/// A reference to the pass using this inliner.
|
|
Pass &pass;
|
|
/// Analysis manager for the given operation instance.
|
|
AnalysisManager am;
|
|
/// A callback for running a nested pass pipeline on the operation
|
|
/// contained within the main operation.
|
|
const RunPipelineHelperTy runPipelineHelper;
|
|
/// The inliner configuration parameters.
|
|
const InlinerConfig &config;
|
|
/// Returns true, if it is profitable to inline the callable operation
|
|
/// at the call site.
|
|
ProfitabilityCallbackTy isProfitableToInline;
|
|
|
|
/// Forward declaration of the class providing the actual implementation.
|
|
class Impl;
|
|
};
|
|
} // namespace mlir
|
|
|
|
#endif // MLIR_TRANSFORMS_INLINER_H
|