11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/Support/Threading.h"
26 PassTiming(
TimingScope &timingScope) : rootScope(timingScope) {}
27 PassTiming(std::unique_ptr<TimingManager> tm)
28 : ownedTimingManager(std::move(tm)),
29 ownedTimingScope(ownedTimingManager->getRootScope()),
30 rootScope(ownedTimingScope) {}
43 std::unique_ptr<TimingManager> ownedTimingManager;
56 void runBeforePipeline(std::optional<OperationName> name,
57 const PipelineParentInfo &parentInfo)
override {
58 auto tid = llvm::get_threadid();
59 auto &activeTimers = activeThreadTimers[tid];
64 auto it = parentTimerIndices.find(parentInfo);
65 if (it != parentTimerIndices.end())
66 parentScope = &activeThreadTimers[parentInfo.parentThreadID][it->second];
68 parentScope = &rootScope;
72 const void *timerId = name ? name->getAsOpaquePointer() :
nullptr;
73 activeTimers.push_back(parentScope->
nest(timerId, [name] {
74 return (
"'" + (name ? name->getStringRef() :
"any") +
"' Pipeline").str();
78 void runAfterPipeline(std::optional<OperationName>,
79 const PipelineParentInfo &)
override {
80 auto &activeTimers = activeThreadTimers[llvm::get_threadid()];
81 assert(!activeTimers.empty() &&
"expected active timer");
82 activeTimers.pop_back();
90 auto tid = llvm::get_threadid();
91 auto &activeTimers = activeThreadTimers[tid];
92 auto &parentScope = activeTimers.empty() ? rootScope : activeTimers.back();
94 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass)) {
95 parentTimerIndices[{tid, pass}] = activeTimers.size();
98 [adaptor]() { return adaptor->getAdaptorName(); });
99 if (adaptor->getPassManagers().size() <= 1)
101 activeTimers.push_back(std::move(scope));
103 activeTimers.push_back(
105 [pass]() { return std::string(pass->getName()); }));
110 auto tid = llvm::get_threadid();
111 if (isa<OpToOpPassAdaptor>(pass))
112 parentTimerIndices.erase({tid, pass});
113 auto &activeTimers = activeThreadTimers[tid];
114 assert(!activeTimers.empty() &&
"expected active timer");
115 activeTimers.pop_back();
118 void runAfterPassFailed(
Pass *pass,
Operation *op)
override {
119 runAfterPass(pass, op);
126 void runBeforeAnalysis(StringRef name,
TypeID id,
Operation *)
override {
127 auto tid = llvm::get_threadid();
128 auto &activeTimers = activeThreadTimers[tid];
129 auto &parentScope = activeTimers.empty() ? rootScope : activeTimers.back();
130 activeTimers.push_back(parentScope.
nest(
131 id.getAsOpaquePointer(), [name] { return
"(A) " + name.str(); }));
135 auto &activeTimers = activeThreadTimers[llvm::get_threadid()];
136 assert(!activeTimers.empty() &&
"expected active timer");
137 activeTimers.pop_back();
151 addInstrumentation(std::make_unique<PassTiming>(timingScope));
157 if (!tm->getRootTimer())
159 addInstrumentation(std::make_unique<PassTiming>(std::move(tm)));
165 auto tm = std::make_unique<DefaultTimingManager>();
166 tm->setEnabled(
true);
167 enableTiming(std::move(tm));
Operation is the basic unit of execution within MLIR.
PassInstrumentation provides several entry points into the pass manager infrastructure.
void enableTiming()
Add an instrumentation to time the execution of passes and the computation of analyses.
The abstract base pass class.
const Pass * getThreadingSiblingOrThis() const
Returns the thread sibling of this pass, or the pass itself it has no sibling.
An RAII-style wrapper around a timer that ensures the timer is properly started and stopped.
TimingScope nest(Args... args)
Create a nested timing scope.
void hide()
Hide the timer in timing reports and directly show its children.
This class provides an efficient unique identifier for a specific C++ type.
Include the generated interface declarations.