xref: /llvm-project/mlir/include/mlir/Transforms/Inliner.h (revision db791b278a414fb6df1acc1799adcf11d8fb9169)
1 //===- Inliner.h - Inliner pass utilities -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This header file declares utility structures for the inliner pass.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TRANSFORMS_INLINER_H
14 #define MLIR_TRANSFORMS_INLINER_H
15 
16 #include "mlir/Analysis/CallGraph.h"
17 #include "mlir/Interfaces/CallInterfaces.h"
18 #include "mlir/Pass/AnalysisManager.h"
19 #include "mlir/Pass/PassManager.h"
20 #include "llvm/ADT/StringMap.h"
21 
22 namespace mlir {
23 class OpPassManager;
24 class Operation;
25 
26 class InlinerConfig {
27 public:
28   using DefaultPipelineTy = std::function<void(OpPassManager &)>;
29   using OpPipelinesTy = llvm::StringMap<OpPassManager>;
30 
31   InlinerConfig() = default;
InlinerConfig(DefaultPipelineTy defaultPipeline,unsigned maxInliningIterations)32   InlinerConfig(DefaultPipelineTy defaultPipeline,
33                 unsigned maxInliningIterations)
34       : defaultPipeline(std::move(defaultPipeline)),
35         maxInliningIterations(maxInliningIterations) {}
36 
getDefaultPipeline()37   const DefaultPipelineTy &getDefaultPipeline() const {
38     return defaultPipeline;
39   }
getOpPipelines()40   const OpPipelinesTy &getOpPipelines() const { return opPipelines; }
getMaxInliningIterations()41   unsigned getMaxInliningIterations() const { return maxInliningIterations; }
setDefaultPipeline(DefaultPipelineTy pipeline)42   void setDefaultPipeline(DefaultPipelineTy pipeline) {
43     defaultPipeline = std::move(pipeline);
44   }
setOpPipelines(OpPipelinesTy pipelines)45   void setOpPipelines(OpPipelinesTy pipelines) {
46     opPipelines = std::move(pipelines);
47   }
setMaxInliningIterations(unsigned max)48   void setMaxInliningIterations(unsigned max) { maxInliningIterations = max; }
49 
50 private:
51   /// An optional function that constructs an optimization pipeline for
52   /// a given operation. This optimization pipeline is applied
53   /// only to those callable operations that do not have dedicated
54   /// optimization pipeline in opPipelines (based on the operation name).
55   DefaultPipelineTy defaultPipeline;
56   /// A map of operation names to pass pipelines to use when optimizing
57   /// callable operations of these types. This provides a specialized pipeline
58   /// instead of the one produced by defaultPipeline.
59   OpPipelinesTy opPipelines;
60   /// For SCC-based inlining algorithms, specifies maximum number of iterations
61   /// when inlining within an SCC.
62   unsigned maxInliningIterations{0};
63 };
64 
65 /// This is an implementation of the inliner
66 /// that operates bottom up over the Strongly Connected Components(SCCs)
67 /// of the CallGraph. This enables a more incremental propagation
68 /// of inlining decisions from the leafs to the roots of the callgraph.
69 class Inliner {
70 public:
71   /// This struct represents a resolved call to a given callgraph node. Given
72   /// that the call does not actually contain a direct reference to the
73   /// Region(CallGraphNode) that it is dispatching to, we need to resolve them
74   /// explicitly.
75   struct ResolvedCall {
ResolvedCallResolvedCall76     ResolvedCall(CallOpInterface call, CallGraphNode *sourceNode,
77                  CallGraphNode *targetNode)
78         : call(call), sourceNode(sourceNode), targetNode(targetNode) {}
79     CallOpInterface call;
80     CallGraphNode *sourceNode, *targetNode;
81   };
82 
83   using RunPipelineHelperTy = std::function<LogicalResult(
84       Pass &pass, OpPassManager &pipeline, Operation *op)>;
85 
86   /// Type of the callback answering if it is profitable
87   /// to inline a callable operation at a call site.
88   /// It might be the case that the ResolvedCall does not provide
89   /// enough context to make the profitability decision, so
90   /// this hook's interface might need to be extended in future.
91   using ProfitabilityCallbackTy = std::function<bool(const ResolvedCall &)>;
92 
Inliner(Operation * op,CallGraph & cg,Pass & pass,AnalysisManager am,RunPipelineHelperTy runPipelineHelper,const InlinerConfig & config,ProfitabilityCallbackTy isProfitableToInline)93   Inliner(Operation *op, CallGraph &cg, Pass &pass, AnalysisManager am,
94           RunPipelineHelperTy runPipelineHelper, const InlinerConfig &config,
95           ProfitabilityCallbackTy isProfitableToInline)
96       : op(op), cg(cg), pass(pass), am(am),
97         runPipelineHelper(std::move(runPipelineHelper)), config(config),
98         isProfitableToInline(std::move(isProfitableToInline)) {}
99   Inliner(Inliner &) = delete;
100   void operator=(const Inliner &) = delete;
101 
102   /// Perform inlining on a OpTrait::SymbolTable operation.
103   LogicalResult doInlining();
104 
105 private:
106   /// An OpTrait::SymbolTable operation to run the inlining on.
107   Operation *op;
108   /// A CallGraph analysis for the given operation.
109   CallGraph &cg;
110   /// A reference to the pass using this inliner.
111   Pass &pass;
112   /// Analysis manager for the given operation instance.
113   AnalysisManager am;
114   /// A callback for running a nested pass pipeline on the operation
115   /// contained within the main operation.
116   const RunPipelineHelperTy runPipelineHelper;
117   /// The inliner configuration parameters.
118   const InlinerConfig &config;
119   /// Returns true, if it is profitable to inline the callable operation
120   /// at the call site.
121   ProfitabilityCallbackTy isProfitableToInline;
122 
123   /// Forward declaration of the class providing the actual implementation.
124   class Impl;
125 };
126 } // namespace mlir
127 
128 #endif // MLIR_TRANSFORMS_INLINER_H
129