11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/Support/Threading.h"
25 PassTiming(
TimingScope &timingScope) : rootScope(timingScope) {}
26 PassTiming(std::unique_ptr<TimingManager> tm)
27 : ownedTimingManager(std::move(tm)),
28 ownedTimingScope(ownedTimingManager->getRootScope()),
29 rootScope(ownedTimingScope) {}
42 std::unique_ptr<TimingManager> ownedTimingManager;
55 void runBeforePipeline(std::optional<OperationName> name,
56 const PipelineParentInfo &parentInfo)
override {
57 auto tid = llvm::get_threadid();
58 auto &activeTimers = activeThreadTimers[tid];
63 auto it = parentTimerIndices.find(parentInfo);
64 if (it != parentTimerIndices.end())
65 parentScope = &activeThreadTimers[parentInfo.parentThreadID][it->second];
67 parentScope = &rootScope;
71 const void *timerId = name ? name->getAsOpaquePointer() :
nullptr;
72 activeTimers.push_back(parentScope->
nest(timerId, [name] {
73 return (
"'" + (name ? name->getStringRef() :
"any") +
"' Pipeline").str();
77 void runAfterPipeline(std::optional<OperationName>,
78 const PipelineParentInfo &)
override {
79 auto &activeTimers = activeThreadTimers[llvm::get_threadid()];
80 assert(!activeTimers.empty() &&
"expected active timer");
81 activeTimers.pop_back();
89 auto tid = llvm::get_threadid();
90 auto &activeTimers = activeThreadTimers[tid];
91 auto &parentScope = activeTimers.empty() ? rootScope : activeTimers.back();
93 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass)) {
94 parentTimerIndices[{tid, pass}] = activeTimers.size();
97 [adaptor]() { return adaptor->getAdaptorName(); });
98 if (adaptor->getPassManagers().size() <= 1)
100 activeTimers.push_back(std::move(scope));
102 activeTimers.push_back(
104 [pass]() { return std::string(pass->getName()); }));
109 auto tid = llvm::get_threadid();
110 if (isa<OpToOpPassAdaptor>(pass))
111 parentTimerIndices.erase({tid, pass});
112 auto &activeTimers = activeThreadTimers[tid];
113 assert(!activeTimers.empty() &&
"expected active timer");
114 activeTimers.pop_back();
117 void runAfterPassFailed(
Pass *pass,
Operation *op)
override {
118 runAfterPass(pass, op);
125 void runBeforeAnalysis(StringRef name,
TypeID id,
Operation *)
override {
126 auto tid = llvm::get_threadid();
127 auto &activeTimers = activeThreadTimers[tid];
128 auto &parentScope = activeTimers.empty() ? rootScope : activeTimers.back();
129 activeTimers.push_back(parentScope.
nest(
130 id.getAsOpaquePointer(), [name] { return
"(A) " + name.str(); }));
134 auto &activeTimers = activeThreadTimers[llvm::get_threadid()];
135 assert(!activeTimers.empty() &&
"expected active timer");
136 activeTimers.pop_back();
150 addInstrumentation(std::make_unique<PassTiming>(timingScope));
156 if (!tm->getRootTimer())
158 addInstrumentation(std::make_unique<PassTiming>(std::move(tm)));
164 auto tm = std::make_unique<DefaultTimingManager>();
165 tm->setEnabled(
true);
166 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.