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