LLVM  16.0.0git
PassTimingInfo.cpp
Go to the documentation of this file.
1 //===- PassTimingInfo.cpp - LLVM Pass Timing Implementation ---------------===//
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 file implements the LLVM Pass Timing infrastructure for both
10 // new and legacy pass managers.
11 //
12 // PassTimingInfo Class - This class is used to calculate information about the
13 // amount of time each pass takes to execute. This only happens when
14 // -time-passes is enabled on the command line.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "llvm/IR/PassTimingInfo.h"
19 #include "llvm/ADT/Statistic.h"
21 #include "llvm/Pass.h"
23 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/Mutex.h"
27 #include "llvm/Support/TypeName.h"
29 #include <string>
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "time-passes"
34 
35 namespace llvm {
36 
37 bool TimePassesIsEnabled = false;
38 bool TimePassesPerRun = false;
39 
42  cl::desc("Time each pass, printing elapsed time for each on exit"));
43 
45  "time-passes-per-run", cl::location(TimePassesPerRun), cl::Hidden,
46  cl::desc("Time each pass run, printing elapsed time for each run on exit"),
47  cl::callback([](const bool &) { TimePassesIsEnabled = true; }));
48 
49 namespace {
50 namespace legacy {
51 
52 //===----------------------------------------------------------------------===//
53 // Legacy pass manager's PassTimingInfo implementation
54 
55 /// Provides an interface for collecting pass timing information.
56 ///
57 /// It was intended to be generic but now we decided to split
58 /// interfaces completely. This is now exclusively for legacy-pass-manager use.
59 class PassTimingInfo {
60 public:
61  using PassInstanceID = void *;
62 
63 private:
64  StringMap<unsigned> PassIDCountMap; ///< Map that counts instances of passes
65  DenseMap<PassInstanceID, std::unique_ptr<Timer>> TimingData; ///< timers for pass instances
66  TimerGroup TG;
67 
68 public:
69  /// Default constructor for yet-inactive timeinfo.
70  /// Use \p init() to activate it.
71  PassTimingInfo();
72 
73  /// Print out timing information and release timers.
74  ~PassTimingInfo();
75 
76  /// Initializes the static \p TheTimeInfo member to a non-null value when
77  /// -time-passes is enabled. Leaves it null otherwise.
78  ///
79  /// This method may be called multiple times.
80  static void init();
81 
82  /// Prints out timing information and then resets the timers.
83  /// By default it uses the stream created by CreateInfoOutputFile().
84  void print(raw_ostream *OutStream = nullptr);
85 
86  /// Returns the timer for the specified pass if it exists.
87  Timer *getPassTimer(Pass *, PassInstanceID);
88 
89  static PassTimingInfo *TheTimeInfo;
90 
91 private:
92  Timer *newPassTimer(StringRef PassID, StringRef PassDesc);
93 };
94 
95 static ManagedStatic<sys::SmartMutex<true>> TimingInfoMutex;
96 
97 PassTimingInfo::PassTimingInfo() : TG("pass", "Pass execution timing report") {}
98 
99 PassTimingInfo::~PassTimingInfo() {
100  // Deleting the timers accumulates their info into the TG member.
101  // Then TG member is (implicitly) deleted, actually printing the report.
102  TimingData.clear();
103 }
104 
105 void PassTimingInfo::init() {
106  if (!TimePassesIsEnabled || TheTimeInfo)
107  return;
108 
109  // Constructed the first time this is called, iff -time-passes is enabled.
110  // This guarantees that the object will be constructed after static globals,
111  // thus it will be destroyed before them.
113  TheTimeInfo = &*TTI;
114 }
115 
116 /// Prints out timing information and then resets the timers.
117 void PassTimingInfo::print(raw_ostream *OutStream) {
118  TG.print(OutStream ? *OutStream : *CreateInfoOutputFile(), true);
119 }
120 
121 Timer *PassTimingInfo::newPassTimer(StringRef PassID, StringRef PassDesc) {
122  unsigned &num = PassIDCountMap[PassID];
123  num++;
124  // Appending description with a pass-instance number for all but the first one
125  std::string PassDescNumbered =
126  num <= 1 ? PassDesc.str() : formatv("{0} #{1}", PassDesc, num).str();
127  return new Timer(PassID, PassDescNumbered, TG);
128 }
129 
130 Timer *PassTimingInfo::getPassTimer(Pass *P, PassInstanceID Pass) {
131  if (P->getAsPMDataManager())
132  return nullptr;
133 
134  init();
135  sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
136  std::unique_ptr<Timer> &T = TimingData[Pass];
137 
138  if (!T) {
139  StringRef PassName = P->getPassName();
140  StringRef PassArgument;
141  if (const PassInfo *PI = Pass::lookupPassInfo(P->getPassID()))
142  PassArgument = PI->getPassArgument();
143  T.reset(newPassTimer(PassArgument.empty() ? PassName : PassArgument, PassName));
144  }
145  return T.get();
146 }
147 
148 PassTimingInfo *PassTimingInfo::TheTimeInfo;
149 } // namespace legacy
150 } // namespace
151 
154  if (legacy::PassTimingInfo::TheTimeInfo)
155  return legacy::PassTimingInfo::TheTimeInfo->getPassTimer(P, P);
156  return nullptr;
157 }
158 
159 /// If timing is enabled, report the times collected up to now and then reset
160 /// them.
162  if (legacy::PassTimingInfo::TheTimeInfo)
163  legacy::PassTimingInfo::TheTimeInfo->print(OutStream);
164 }
165 
166 //===----------------------------------------------------------------------===//
167 // Pass timing handling for the New Pass Manager
168 //===----------------------------------------------------------------------===//
169 
170 /// Returns the timer for the specified pass invocation of \p PassID.
171 /// Each time it creates a new timer.
172 Timer &TimePassesHandler::getPassTimer(StringRef PassID, bool IsPass) {
173  TimerGroup &TG = IsPass ? PassTG : AnalysisTG;
174  if (!PerRun) {
175  TimerVector &Timers = TimingData[PassID];
176  if (Timers.size() == 0)
177  Timers.emplace_back(new Timer(PassID, PassID, TG));
178  return *Timers.front();
179  }
180 
181  // Take a vector of Timers created for this \p PassID and append
182  // one more timer to it.
183  TimerVector &Timers = TimingData[PassID];
184  unsigned Count = Timers.size() + 1;
185 
186  std::string FullDesc = formatv("{0} #{1}", PassID, Count).str();
187 
188  Timer *T = new Timer(PassID, FullDesc, TG);
189  Timers.emplace_back(T);
190  assert(Count == Timers.size() && "Timers vector not adjusted correctly.");
191 
192  return *T;
193 }
194 
196  : PassTG("pass", "Pass execution timing report"),
197  AnalysisTG("analysis", "Analysis execution timing report"),
198  Enabled(Enabled), PerRun(PerRun) {}
199 
202 
204  OutStream = &Out;
205 }
206 
208  if (!Enabled)
209  return;
210  std::unique_ptr<raw_ostream> MaybeCreated;
211  raw_ostream *OS = OutStream;
212  if (OutStream) {
213  OS = OutStream;
214  } else {
215  MaybeCreated = CreateInfoOutputFile();
216  OS = &*MaybeCreated;
217  }
218  PassTG.print(*OS, true);
219  AnalysisTG.print(*OS, true);
220 }
221 
222 LLVM_DUMP_METHOD void TimePassesHandler::dump() const {
223  dbgs() << "Dumping timers for " << getTypeName<TimePassesHandler>()
224  << ":\n\tRunning:\n";
225  for (auto &I : TimingData) {
226  StringRef PassID = I.getKey();
227  const TimerVector& MyTimers = I.getValue();
228  for (unsigned idx = 0; idx < MyTimers.size(); idx++) {
229  const Timer* MyTimer = MyTimers[idx].get();
230  if (MyTimer && MyTimer->isRunning())
231  dbgs() << "\tTimer " << MyTimer << " for pass " << PassID << "(" << idx << ")\n";
232  }
233  }
234  dbgs() << "\tTriggered:\n";
235  for (auto &I : TimingData) {
236  StringRef PassID = I.getKey();
237  const TimerVector& MyTimers = I.getValue();
238  for (unsigned idx = 0; idx < MyTimers.size(); idx++) {
239  const Timer* MyTimer = MyTimers[idx].get();
240  if (MyTimer && MyTimer->hasTriggered() && !MyTimer->isRunning())
241  dbgs() << "\tTimer " << MyTimer << " for pass " << PassID << "(" << idx << ")\n";
242  }
243  }
244 }
245 
246 static bool shouldIgnorePass(StringRef PassID) {
247  return isSpecialPass(PassID,
248  {"PassManager", "PassAdaptor", "AnalysisManagerProxy",
249  "ModuleInlinerWrapperPass", "DevirtSCCRepeatedPass"});
250 }
251 
252 void TimePassesHandler::startPassTimer(StringRef PassID) {
253  if (shouldIgnorePass(PassID))
254  return;
255  assert(!ActivePassTimer && "should only have one pass timer at a time");
256  Timer &MyTimer = getPassTimer(PassID, /*IsPass*/ true);
257  ActivePassTimer = &MyTimer;
258  assert(!MyTimer.isRunning());
259  MyTimer.startTimer();
260 }
261 
262 void TimePassesHandler::stopPassTimer(StringRef PassID) {
263  if (shouldIgnorePass(PassID))
264  return;
265  assert(ActivePassTimer);
266  assert(ActivePassTimer->isRunning());
267  ActivePassTimer->stopTimer();
268  ActivePassTimer = nullptr;
269 }
270 
271 void TimePassesHandler::startAnalysisTimer(StringRef PassID) {
272  // Stop the previous analysis timer to prevent double counting when an
273  // analysis requests another analysis.
274  if (!AnalysisActiveTimerStack.empty()) {
275  assert(AnalysisActiveTimerStack.back()->isRunning());
276  AnalysisActiveTimerStack.back()->stopTimer();
277  }
278 
279  Timer &MyTimer = getPassTimer(PassID, /*IsPass*/ false);
280  AnalysisActiveTimerStack.push_back(&MyTimer);
281  if (!MyTimer.isRunning())
282  MyTimer.startTimer();
283 }
284 
285 void TimePassesHandler::stopAnalysisTimer(StringRef PassID) {
286  assert(!AnalysisActiveTimerStack.empty() && "empty stack in popTimer");
287  Timer *MyTimer = AnalysisActiveTimerStack.pop_back_val();
288  assert(MyTimer && "timer should be present");
289  if (MyTimer->isRunning())
290  MyTimer->stopTimer();
291 
292  // Restart the previously stopped timer.
293  if (!AnalysisActiveTimerStack.empty()) {
294  assert(!AnalysisActiveTimerStack.back()->isRunning());
295  AnalysisActiveTimerStack.back()->startTimer();
296  }
297 }
298 
300  if (!Enabled)
301  return;
302 
304  [this](StringRef P, Any) { this->startPassTimer(P); });
306  [this](StringRef P, Any, const PreservedAnalyses &) {
307  this->stopPassTimer(P);
308  });
310  [this](StringRef P, const PreservedAnalyses &) {
311  this->stopPassTimer(P);
312  });
314  [this](StringRef P, Any) { this->startAnalysisTimer(P); });
316  [this](StringRef P, Any) { this->stopAnalysisTimer(P); });
317 }
318 
319 } // namespace llvm
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:152
llvm::PassInstrumentationCallbacks::registerAfterPassInvalidatedCallback
void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront=false)
Definition: PassInstrumentation.h:119
LLVM_DUMP_METHOD
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:492
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::reportAndResetTimings
void reportAndResetTimings(raw_ostream *OutStream=nullptr)
If -time-passes has been specified, report the timings immediately and then reset the timers to zero.
Definition: PassTimingInfo.cpp:161
Pass
print lazy value Lazy Value Info Printer Pass
Definition: LazyValueInfo.cpp:1999
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:189
llvm::Timer::hasTriggered
bool hasTriggered() const
Check if startTimer() has ever been called on this timer.
Definition: Timer.h:121
T
llvm::cl::location
LocationClass< Ty > location(Ty &L)
Definition: CommandLine.h:466
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
Pass.h
llvm::PassInstrumentationCallbacks::registerBeforeNonSkippedPassCallback
void registerBeforeNonSkippedPassCallback(CallableT C)
Definition: PassInstrumentation.h:106
llvm::TimerGroup::print
void print(raw_ostream &OS, bool ResetAfterPrint=false)
Print any started timers in this group, optionally resetting timers after printing them.
Definition: Timer.cpp:426
Statistic.h
ManagedStatic.h
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:139
llvm::Timer
This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...
Definition: Timer.h:81
llvm::TimePassesIsEnabled
bool TimePassesIsEnabled
If the user specifies the -time-passes argument on an LLVM tool command line then the value of this b...
Definition: PassTimingInfo.cpp:37
PIC
PassInstrumentationCallbacks PIC
Definition: PassBuilderBindings.cpp:55
llvm::PassInfo
PassInfo class - An instance of this class exists for every pass known by the system,...
Definition: PassInfo.h:30
llvm::TimePassesHandler::TimePassesHandler
TimePassesHandler()
Definition: PassTimingInfo.cpp:200
llvm::Timer::startTimer
void startTimer()
Start the timer running.
Definition: Timer.cpp:190
llvm::CreateInfoOutputFile
std::unique_ptr< raw_fd_ostream > CreateInfoOutputFile()
Return a file stream to print our output on.
Definition: Timer.cpp:96
llvm::TimePassesHandler::print
void print()
Prints out timing information and then resets the timers.
Definition: PassTimingInfo.cpp:207
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::Timer::isRunning
bool isRunning() const
Check if the timer is currently running.
Definition: Timer.h:118
PassTimingInfo.h
CommandLine.h
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:251
llvm::EnableTimingPerRun
static cl::opt< bool, true > EnableTimingPerRun("time-passes-per-run", cl::location(TimePassesPerRun), cl::Hidden, cl::desc("Time each pass run, printing elapsed time for each run on exit"), cl::callback([](const bool &) { TimePassesIsEnabled=true;}))
PassInstrumentation.h
llvm::ManagedStatic
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
llvm::isSpecialPass
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
Definition: PassInstrumentation.cpp:33
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::shouldIgnorePass
static bool shouldIgnorePass(StringRef PassID)
Definition: PassTimingInfo.cpp:246
FormatVariadic.h
llvm::StringMap< unsigned >
llvm::PassInstrumentationCallbacks::registerBeforeAnalysisCallback
void registerBeforeAnalysisCallback(CallableT C)
Definition: PassInstrumentation.h:128
llvm::TimePassesHandler::setOutStream
void setOutStream(raw_ostream &OutStream)
Set a custom output stream for subsequent reporting.
Definition: PassTimingInfo.cpp:203
llvm::StringRef::empty
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
llvm::cl::opt
Definition: CommandLine.h:1411
llvm::DenseMap
Definition: DenseMap.h:714
llvm::getPassTimer
Timer * getPassTimer(Pass *)
Request the timer for this legacy-pass-manager's pass instance.
Definition: PassTimingInfo.cpp:152
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::sys::SmartScopedLock
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition: Mutex.h:69
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:446
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::TTI
TargetTransformInfo TTI
Definition: TargetTransformInfo.h:168
llvm::Timer::stopTimer
void stopTimer()
Stop the timer.
Definition: Timer.cpp:197
llvm::print
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
Definition: GCNRegPressure.cpp:138
TypeName.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::TimePassesHandler::registerCallbacks
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Definition: PassTimingInfo.cpp:299
Mutex.h
llvm::TimePassesPerRun
bool TimePassesPerRun
If TimePassesPerRun is true, there would be one line of report for each pass invocation.
Definition: PassTimingInfo.cpp:38
llvm::PassInstrumentationCallbacks::registerAfterPassCallback
void registerAfterPassCallback(CallableT C, bool ToFront=false)
Definition: PassInstrumentation.h:111
llvm::Any
Definition: Any.h:28
llvm::TimerGroup
The TimerGroup class is used to group together related timers into a single report that is printed wh...
Definition: Timer.h:175
Enabled
static bool Enabled
Definition: Statistic.cpp:46
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
llvm::PassInstrumentationCallbacks
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
Definition: PassInstrumentation.h:66
llvm::TimePassesHandler
This class implements -time-passes functionality for new pass manager.
Definition: PassTimingInfo.h:44
llvm::StringRef::str
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:221
llvm::EnableTiming
static cl::opt< bool, true > EnableTiming("time-passes", cl::location(TimePassesIsEnabled), cl::Hidden, cl::desc("Time each pass, printing elapsed time for each on exit"))
llvm::cl::callback
cb< typename detail::callback_traits< F >::result_type, typename detail::callback_traits< F >::arg_type > callback(F CB)
Definition: CommandLine.h:518
llvm::PassInstrumentationCallbacks::registerAfterAnalysisCallback
void registerAfterAnalysisCallback(CallableT C, bool ToFront=false)
Definition: PassInstrumentation.h:133
llvm::cl::desc
Definition: CommandLine.h:412
raw_ostream.h
Debug.h
PassName
static const char PassName[]
Definition: X86LowerAMXIntrinsics.cpp:671