LLVM  10.0.0svn
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/DenseMap.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Pass.h"
25 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/Mutex.h"
29 #include "llvm/Support/Timer.h"
31 #include <memory>
32 #include <string>
33 
34 using namespace llvm;
35 
36 #define DEBUG_TYPE "time-passes"
37 
38 namespace llvm {
39 
40 bool TimePassesIsEnabled = false;
41 
43  "time-passes", cl::location(TimePassesIsEnabled), cl::Hidden,
44  cl::desc("Time each pass, printing elapsed time for each on exit"));
45 
46 namespace {
47 namespace legacy {
48 
49 //===----------------------------------------------------------------------===//
50 // Legacy pass manager's PassTimingInfo implementation
51 
52 /// Provides an interface for collecting pass timing information.
53 ///
54 /// It was intended to be generic but now we decided to split
55 /// interfaces completely. This is now exclusively for legacy-pass-manager use.
56 class PassTimingInfo {
57 public:
58  using PassInstanceID = void *;
59 
60 private:
61  StringMap<unsigned> PassIDCountMap; ///< Map that counts instances of passes
62  DenseMap<PassInstanceID, std::unique_ptr<Timer>> TimingData; ///< timers for pass instances
63  TimerGroup TG;
64 
65 public:
66  /// Default constructor for yet-inactive timeinfo.
67  /// Use \p init() to activate it.
68  PassTimingInfo();
69 
70  /// Print out timing information and release timers.
71  ~PassTimingInfo();
72 
73  /// Initializes the static \p TheTimeInfo member to a non-null value when
74  /// -time-passes is enabled. Leaves it null otherwise.
75  ///
76  /// This method may be called multiple times.
77  static void init();
78 
79  /// Prints out timing information and then resets the timers.
80  /// By default it uses the stream created by CreateInfoOutputFile().
81  void print(raw_ostream *OutStream = nullptr);
82 
83  /// Returns the timer for the specified pass if it exists.
84  Timer *getPassTimer(Pass *, PassInstanceID);
85 
86  static PassTimingInfo *TheTimeInfo;
87 
88 private:
89  Timer *newPassTimer(StringRef PassID, StringRef PassDesc);
90 };
91 
92 static ManagedStatic<sys::SmartMutex<true>> TimingInfoMutex;
93 
94 PassTimingInfo::PassTimingInfo()
95  : TG("pass", "... Pass execution timing report ...") {}
96 
97 PassTimingInfo::~PassTimingInfo() {
98  // Deleting the timers accumulates their info into the TG member.
99  // Then TG member is (implicitly) deleted, actually printing the report.
100  TimingData.clear();
101 }
102 
103 void PassTimingInfo::init() {
104  if (!TimePassesIsEnabled || TheTimeInfo)
105  return;
106 
107  // Constructed the first time this is called, iff -time-passes is enabled.
108  // This guarantees that the object will be constructed after static globals,
109  // thus it will be destroyed before them.
111  TheTimeInfo = &*TTI;
112 }
113 
114 /// Prints out timing information and then resets the timers.
115 void PassTimingInfo::print(raw_ostream *OutStream) {
116  TG.print(OutStream ? *OutStream : *CreateInfoOutputFile(), true);
117 }
118 
119 Timer *PassTimingInfo::newPassTimer(StringRef PassID, StringRef PassDesc) {
120  unsigned &num = PassIDCountMap[PassID];
121  num++;
122  // Appending description with a pass-instance number for all but the first one
123  std::string PassDescNumbered =
124  num <= 1 ? PassDesc.str() : formatv("{0} #{1}", PassDesc, num).str();
125  return new Timer(PassID, PassDescNumbered, TG);
126 }
127 
128 Timer *PassTimingInfo::getPassTimer(Pass *P, PassInstanceID Pass) {
129  if (P->getAsPMDataManager())
130  return nullptr;
131 
132  init();
133  sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
134  std::unique_ptr<Timer> &T = TimingData[Pass];
135 
136  if (!T) {
137  StringRef PassName = P->getPassName();
138  StringRef PassArgument;
139  if (const PassInfo *PI = Pass::lookupPassInfo(P->getPassID()))
140  PassArgument = PI->getPassArgument();
141  T.reset(newPassTimer(PassArgument.empty() ? PassName : PassArgument, PassName));
142  }
143  return T.get();
144 }
145 
146 PassTimingInfo *PassTimingInfo::TheTimeInfo;
147 } // namespace legacy
148 } // namespace
149 
152  if (legacy::PassTimingInfo::TheTimeInfo)
153  return legacy::PassTimingInfo::TheTimeInfo->getPassTimer(P, P);
154  return nullptr;
155 }
156 
157 /// If timing is enabled, report the times collected up to now and then reset
158 /// them.
160  if (legacy::PassTimingInfo::TheTimeInfo)
161  legacy::PassTimingInfo::TheTimeInfo->print(OutStream);
162 }
163 
164 //===----------------------------------------------------------------------===//
165 // Pass timing handling for the New Pass Manager
166 //===----------------------------------------------------------------------===//
167 
168 /// Returns the timer for the specified pass invocation of \p PassID.
169 /// Each time it creates a new timer.
170 Timer &TimePassesHandler::getPassTimer(StringRef PassID) {
171  // Bump counts for each request of the timer.
172  unsigned Count = nextPassID(PassID);
173 
174  // Unconditionally appending description with a pass-invocation number.
175  std::string FullDesc = formatv("{0} #{1}", PassID, Count).str();
176 
177  PassInvocationID UID{PassID, Count};
178  Timer *T = new Timer(PassID, FullDesc, TG);
179  auto Pair = TimingData.try_emplace(UID, T);
180  assert(Pair.second && "should always create a new timer");
181  return *(Pair.first->second.get());
182 }
183 
185  : TG("pass", "... Pass execution timing report ..."), Enabled(Enabled) {}
186 
188  OutStream = &Out;
189 }
190 
192  if (!Enabled)
193  return;
194  TG.print(OutStream ? *OutStream : *CreateInfoOutputFile(), true);
195 }
196 
197 LLVM_DUMP_METHOD void TimePassesHandler::dump() const {
198  dbgs() << "Dumping timers for " << getTypeName<TimePassesHandler>()
199  << ":\n\tRunning:\n";
200  for (auto &I : TimingData) {
201  const Timer *MyTimer = I.second.get();
202  if (!MyTimer || MyTimer->isRunning())
203  dbgs() << "\tTimer " << MyTimer << " for pass " << I.first.first << "("
204  << I.first.second << ")\n";
205  }
206  dbgs() << "\tTriggered:\n";
207  for (auto &I : TimingData) {
208  const Timer *MyTimer = I.second.get();
209  if (!MyTimer || (MyTimer->hasTriggered() && !MyTimer->isRunning()))
210  dbgs() << "\tTimer " << MyTimer << " for pass " << I.first.first << "("
211  << I.first.second << ")\n";
212  }
213 }
214 
215 void TimePassesHandler::startTimer(StringRef PassID) {
216  Timer &MyTimer = getPassTimer(PassID);
217  TimerStack.push_back(&MyTimer);
218  if (!MyTimer.isRunning())
219  MyTimer.startTimer();
220 }
221 
222 void TimePassesHandler::stopTimer(StringRef PassID) {
223  assert(TimerStack.size() > 0 && "empty stack in popTimer");
224  Timer *MyTimer = TimerStack.pop_back_val();
225  assert(MyTimer && "timer should be present");
226  if (MyTimer->isRunning())
227  MyTimer->stopTimer();
228 }
229 
230 static bool matchPassManager(StringRef PassID) {
231  size_t prefix_pos = PassID.find('<');
232  if (prefix_pos == StringRef::npos)
233  return false;
234  StringRef Prefix = PassID.substr(0, prefix_pos);
235  return Prefix.endswith("PassManager") || Prefix.endswith("PassAdaptor") ||
236  Prefix.endswith("AnalysisManagerProxy");
237 }
238 
239 bool TimePassesHandler::runBeforePass(StringRef PassID) {
240  if (matchPassManager(PassID))
241  return true;
242 
243  startTimer(PassID);
244 
245  LLVM_DEBUG(dbgs() << "after runBeforePass(" << PassID << ")\n");
246  LLVM_DEBUG(dump());
247 
248  // we are not going to skip this pass, thus return true.
249  return true;
250 }
251 
252 void TimePassesHandler::runAfterPass(StringRef PassID) {
253  if (matchPassManager(PassID))
254  return;
255 
256  stopTimer(PassID);
257 
258  LLVM_DEBUG(dbgs() << "after runAfterPass(" << PassID << ")\n");
259  LLVM_DEBUG(dump());
260 }
261 
263  if (!Enabled)
264  return;
265 
267  [this](StringRef P, Any) { return this->runBeforePass(P); });
269  [this](StringRef P, Any) { this->runAfterPass(P); });
271  [this](StringRef P) { this->runAfterPass(P); });
273  [this](StringRef P, Any) { this->runBeforePass(P); });
275  [this](StringRef P, Any) { this->runAfterPass(P); });
276 }
277 
278 } // namespace llvm
Pass interface - Implemented by all &#39;passes&#39;.
Definition: Pass.h:80
Definition: Any.h:26
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:218
void registerCallbacks(PassInstrumentationCallbacks &PIC)
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_NODISCARD bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:267
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
Definition: Compiler.h:473
virtual PMDataManager * getAsPMDataManager()
Definition: Pass.cpp:116
void setOutStream(raw_ostream &OutStream)
Set a custom output stream for subsequent reporting.
void print()
Prints out timing information and then resets the timers.
static sys::Mutex Lock
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
bool isRunning() const
Check if the timer is currently running.
Definition: Timer.h:113
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:79
Timer * getPassTimer(Pass *)
Request the timer for this legacy-pass-manager&#39;s pass instance.
This header defines classes/functions to handle pass execution timing information with interfaces for...
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:578
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:126
TimePassesHandler(bool Enabled=TimePassesIsEnabled)
This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...
Definition: Timer.h:76
void reportAndResetTimings(raw_ostream *OutStream=nullptr)
If -time-passes has been specified, report the timings immediately and then reset the timers to zero...
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
std::unique_ptr< raw_fd_ostream > CreateInfoOutputFile()
Return a file stream to print our output on.
Definition: Timer.cpp:58
static const PassInfo * lookupPassInfo(const void *TI)
Definition: Pass.cpp:224
#define P(N)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
AnalysisID getPassID() const
getPassID - Return the PassID number that corresponds to this pass.
Definition: Pass.h:99
void print(raw_ostream &OS, bool ResetAfterPrint=false)
Print any started timers in this group, optionally resetting timers after printing them...
Definition: Timer.cpp:368
LLVM_NODISCARD size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:285
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
PassInfo class - An instance of this class exists for every pass known by the system, and can be obtained from a live Pass by calling its getPassInfo() method.
Definition: PassInfo.h:30
print lazy value Lazy Value Info Printer Pass
void startTimer()
Start the timer running.
Definition: Timer.cpp:137
static bool Enabled
Definition: Statistic.cpp:50
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition: Mutex.h:71
void registerAfterPassInvalidatedCallback(CallableT C)
static const size_t npos
Definition: StringRef.h:50
#define I(x, y, z)
Definition: MD5.cpp:58
The TimerGroup class is used to group together related timers into a single report that is printed wh...
Definition: Timer.h:170
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
bool TimePassesIsEnabled
If the user specifies the -time-passes argument on an LLVM tool command line then the value of this b...
Definition: Pass.h:356
#define LLVM_DEBUG(X)
Definition: Debug.h:122
static bool matchPassManager(StringRef PassID)
LocationClass< Ty > location(Ty &L)
Definition: CommandLine.h:448
bool hasTriggered() const
Check if startTimer() has ever been called on this timer.
Definition: Timer.h:116