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