1 //===- PassInstrumentation.h ------------------------------------*- 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 #ifndef MLIR_PASS_PASSINSTRUMENTATION_H_
10 #define MLIR_PASS_PASSINSTRUMENTATION_H_
11 
12 #include "mlir/Support/LLVM.h"
13 #include "mlir/Support/TypeID.h"
14 
15 namespace mlir {
16 class OperationName;
17 class Operation;
18 class Pass;
19 
20 namespace detail {
21 struct PassInstrumentorImpl;
22 } // namespace detail
23 
24 /// PassInstrumentation provides several entry points into the pass manager
25 /// infrastructure. Instrumentations should be added directly to a PassManager
26 /// before running a pipeline.
27 class PassInstrumentation {
28 public:
29   /// This struct represents information related to the parent pass of pipeline.
30   /// It includes information that allows for effectively linking pipelines that
31   /// run on different threads.
32   struct PipelineParentInfo {
33     /// The thread of the parent pass that the current pipeline was spawned
34     /// from. Note: This is acquired from llvm::get_threadid().
35     uint64_t parentThreadID;
36 
37     /// The pass that spawned this pipeline.
38     Pass *parentPass;
39   };
40 
41   virtual ~PassInstrumentation() = 0;
42 
43   /// A callback to run before a pass pipeline is executed. This function takes
44   /// the name of the operation type being operated on, or None if the pipeline
45   /// is op-agnostic, and information related to the parent that spawned this
46   /// pipeline.
47   virtual void runBeforePipeline(Optional<OperationName> name,
48                                  const PipelineParentInfo &parentInfo);
49 
50   /// A callback to run after a pass pipeline has executed. This function takes
51   /// the name of the operation type being operated on, or None if the pipeline
52   /// is op-agnostic, and information related to the parent that spawned this
53   /// pipeline.
54   virtual void runAfterPipeline(Optional<OperationName> name,
55                                 const PipelineParentInfo &parentInfo);
56 
57   /// A callback to run before a pass is executed. This function takes a pointer
58   /// to the pass to be executed, as well as the current operation being
59   /// operated on.
runBeforePass(Pass * pass,Operation * op)60   virtual void runBeforePass(Pass *pass, Operation *op) {}
61 
62   /// A callback to run after a pass is successfully executed. This function
63   /// takes a pointer to the pass to be executed, as well as the current
64   /// operation being operated on.
runAfterPass(Pass * pass,Operation * op)65   virtual void runAfterPass(Pass *pass, Operation *op) {}
66 
67   /// A callback to run when a pass execution fails. This function takes a
68   /// pointer to the pass that was being executed, as well as the current
69   /// operation being operated on. Note that the operation may be in an invalid
70   /// state.
runAfterPassFailed(Pass * pass,Operation * op)71   virtual void runAfterPassFailed(Pass *pass, Operation *op) {}
72 
73   /// A callback to run before an analysis is computed. This function takes the
74   /// name of the analysis to be computed, its TypeID, as well as the
75   /// current operation being analyzed.
runBeforeAnalysis(StringRef name,TypeID id,Operation * op)76   virtual void runBeforeAnalysis(StringRef name, TypeID id, Operation *op) {}
77 
78   /// A callback to run before an analysis is computed. This function takes the
79   /// name of the analysis that was computed, its TypeID, as well as the
80   /// current operation being analyzed.
runAfterAnalysis(StringRef name,TypeID id,Operation * op)81   virtual void runAfterAnalysis(StringRef name, TypeID id, Operation *op) {}
82 };
83 
84 /// This class holds a collection of PassInstrumentation objects, and invokes
85 /// their respective call backs.
86 class PassInstrumentor {
87 public:
88   PassInstrumentor();
89   PassInstrumentor(PassInstrumentor &&) = delete;
90   PassInstrumentor(const PassInstrumentor &) = delete;
91   ~PassInstrumentor();
92 
93   /// See PassInstrumentation::runBeforePipeline for details.
94   void
95   runBeforePipeline(Optional<OperationName> name,
96                     const PassInstrumentation::PipelineParentInfo &parentInfo);
97 
98   /// See PassInstrumentation::runAfterPipeline for details.
99   void
100   runAfterPipeline(Optional<OperationName> name,
101                    const PassInstrumentation::PipelineParentInfo &parentInfo);
102 
103   /// See PassInstrumentation::runBeforePass for details.
104   void runBeforePass(Pass *pass, Operation *op);
105 
106   /// See PassInstrumentation::runAfterPass for details.
107   void runAfterPass(Pass *pass, Operation *op);
108 
109   /// See PassInstrumentation::runAfterPassFailed for details.
110   void runAfterPassFailed(Pass *pass, Operation *op);
111 
112   /// See PassInstrumentation::runBeforeAnalysis for details.
113   void runBeforeAnalysis(StringRef name, TypeID id, Operation *op);
114 
115   /// See PassInstrumentation::runAfterAnalysis for details.
116   void runAfterAnalysis(StringRef name, TypeID id, Operation *op);
117 
118   /// Add the given instrumentation to the collection.
119   void addInstrumentation(std::unique_ptr<PassInstrumentation> pi);
120 
121 private:
122   std::unique_ptr<detail::PassInstrumentorImpl> impl;
123 };
124 
125 } // namespace mlir
126 
127 namespace llvm {
128 template <>
129 struct DenseMapInfo<mlir::PassInstrumentation::PipelineParentInfo> {
130   using T = mlir::PassInstrumentation::PipelineParentInfo;
131   using PairInfo = DenseMapInfo<std::pair<uint64_t, void *>>;
132 
133   static T getEmptyKey() {
134     auto pair = PairInfo::getEmptyKey();
135     return {pair.first, reinterpret_cast<mlir::Pass *>(pair.second)};
136   }
137   static T getTombstoneKey() {
138     auto pair = PairInfo::getTombstoneKey();
139     return {pair.first, reinterpret_cast<mlir::Pass *>(pair.second)};
140   }
141   static unsigned getHashValue(T val) {
142     return PairInfo::getHashValue({val.parentThreadID, val.parentPass});
143   }
144   static bool isEqual(T lhs, T rhs) {
145     return lhs.parentThreadID == rhs.parentThreadID &&
146            lhs.parentPass == rhs.parentPass;
147   }
148 };
149 } // namespace llvm
150 
151 #endif // MLIR_PASS_PASSINSTRUMENTATION_H_
152