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/IR/Identifier.h"
13 #include "mlir/Support/LLVM.h"
14 #include "mlir/Support/TypeID.h"
15 
16 namespace mlir {
17 class Operation;
18 class Pass;
19 
20 namespace detail {
21 struct PassInstrumentorImpl;
22 } // end 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, and information related
45   /// to the parent that spawned this pipeline.
runBeforePipeline(Identifier name,const PipelineParentInfo & parentInfo)46   virtual void runBeforePipeline(Identifier name,
47                                  const PipelineParentInfo &parentInfo) {}
48 
49   /// A callback to run after a pass pipeline has executed. This function takes
50   /// the name of the operation type being operated on, and information related
51   /// to the parent that spawned this pipeline.
runAfterPipeline(Identifier name,const PipelineParentInfo & parentInfo)52   virtual void runAfterPipeline(Identifier name,
53                                 const PipelineParentInfo &parentInfo) {}
54 
55   /// A callback to run before a pass is executed. This function takes a pointer
56   /// to the pass to be executed, as well as the current operation being
57   /// operated on.
runBeforePass(Pass * pass,Operation * op)58   virtual void runBeforePass(Pass *pass, Operation *op) {}
59 
60   /// A callback to run after a pass is successfully executed. This function
61   /// takes a pointer to the pass to be executed, as well as the current
62   /// operation being operated on.
runAfterPass(Pass * pass,Operation * op)63   virtual void runAfterPass(Pass *pass, Operation *op) {}
64 
65   /// A callback to run when a pass execution fails. This function takes a
66   /// pointer to the pass that was being executed, as well as the current
67   /// operation being operated on. Note that the operation may be in an invalid
68   /// state.
runAfterPassFailed(Pass * pass,Operation * op)69   virtual void runAfterPassFailed(Pass *pass, Operation *op) {}
70 
71   /// A callback to run before an analysis is computed. This function takes the
72   /// name of the analysis to be computed, its TypeID, as well as the
73   /// current operation being analyzed.
runBeforeAnalysis(StringRef name,TypeID id,Operation * op)74   virtual void runBeforeAnalysis(StringRef name, TypeID id, Operation *op) {}
75 
76   /// A callback to run before an analysis is computed. This function takes the
77   /// name of the analysis that was computed, its TypeID, as well as the
78   /// current operation being analyzed.
runAfterAnalysis(StringRef name,TypeID id,Operation * op)79   virtual void runAfterAnalysis(StringRef name, TypeID id, Operation *op) {}
80 };
81 
82 /// This class holds a collection of PassInstrumentation objects, and invokes
83 /// their respective call backs.
84 class PassInstrumentor {
85 public:
86   PassInstrumentor();
87   PassInstrumentor(PassInstrumentor &&) = delete;
88   PassInstrumentor(const PassInstrumentor &) = delete;
89   ~PassInstrumentor();
90 
91   /// See PassInstrumentation::runBeforePipeline for details.
92   void
93   runBeforePipeline(Identifier name,
94                     const PassInstrumentation::PipelineParentInfo &parentInfo);
95 
96   /// See PassInstrumentation::runAfterPipeline for details.
97   void
98   runAfterPipeline(Identifier name,
99                    const PassInstrumentation::PipelineParentInfo &parentInfo);
100 
101   /// See PassInstrumentation::runBeforePass for details.
102   void runBeforePass(Pass *pass, Operation *op);
103 
104   /// See PassInstrumentation::runAfterPass for details.
105   void runAfterPass(Pass *pass, Operation *op);
106 
107   /// See PassInstrumentation::runAfterPassFailed for details.
108   void runAfterPassFailed(Pass *pass, Operation *op);
109 
110   /// See PassInstrumentation::runBeforeAnalysis for details.
111   void runBeforeAnalysis(StringRef name, TypeID id, Operation *op);
112 
113   /// See PassInstrumentation::runAfterAnalysis for details.
114   void runAfterAnalysis(StringRef name, TypeID id, Operation *op);
115 
116   /// Add the given instrumentation to the collection.
117   void addInstrumentation(std::unique_ptr<PassInstrumentation> pi);
118 
119 private:
120   std::unique_ptr<detail::PassInstrumentorImpl> impl;
121 };
122 
123 } // end namespace mlir
124 
125 namespace llvm {
126 template <> struct DenseMapInfo<mlir::PassInstrumentation::PipelineParentInfo> {
127   using T = mlir::PassInstrumentation::PipelineParentInfo;
128   using PairInfo = DenseMapInfo<std::pair<uint64_t, void *>>;
129 
130   static T getEmptyKey() {
131     auto pair = PairInfo::getEmptyKey();
132     return {pair.first, reinterpret_cast<mlir::Pass *>(pair.second)};
133   }
134   static T getTombstoneKey() {
135     auto pair = PairInfo::getTombstoneKey();
136     return {pair.first, reinterpret_cast<mlir::Pass *>(pair.second)};
137   }
138   static unsigned getHashValue(T val) {
139     return PairInfo::getHashValue({val.parentThreadID, val.parentPass});
140   }
141   static bool isEqual(T lhs, T rhs) {
142     return lhs.parentThreadID == rhs.parentThreadID &&
143            lhs.parentPass == rhs.parentPass;
144   }
145 };
146 } // end namespace llvm
147 
148 #endif // MLIR_PASS_PASSINSTRUMENTATION_H_
149