LCOV - code coverage report
Current view: top level - lib/IR - PassTimingInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 68 84 81.0 %
Date: 2018-10-20 13:21:21 Functions: 15 18 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- PassTimingInfo.cpp - LLVM Pass Timing Implementation ---------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file implements the LLVM Pass Timing infrastructure for both
      11             : // new and legacy pass managers.
      12             : //
      13             : // PassTimingInfo Class - This class is used to calculate information about the
      14             : // amount of time each pass takes to execute.  This only happens when
      15             : // -time-passes is enabled on the command line.
      16             : //
      17             : //===----------------------------------------------------------------------===//
      18             : 
      19             : #include "llvm/IR/PassTimingInfo.h"
      20             : #include "llvm/ADT/DenseMap.h"
      21             : #include "llvm/ADT/Statistic.h"
      22             : #include "llvm/ADT/StringRef.h"
      23             : #include "llvm/IR/PassInstrumentation.h"
      24             : #include "llvm/Pass.h"
      25             : #include "llvm/Support/CommandLine.h"
      26             : #include "llvm/Support/Debug.h"
      27             : #include "llvm/Support/FormatVariadic.h"
      28             : #include "llvm/Support/ManagedStatic.h"
      29             : #include "llvm/Support/Mutex.h"
      30             : #include "llvm/Support/Timer.h"
      31             : #include "llvm/Support/raw_ostream.h"
      32             : #include <memory>
      33             : #include <string>
      34             : 
      35             : using namespace llvm;
      36             : 
      37             : #define DEBUG_TYPE "time-passes"
      38             : 
      39             : namespace llvm {
      40             : 
      41             : bool TimePassesIsEnabled = false;
      42             : 
      43             : static cl::opt<bool, true> EnableTiming(
      44             :     "time-passes", cl::location(TimePassesIsEnabled), cl::Hidden,
      45             :     cl::desc("Time each pass, printing elapsed time for each on exit"));
      46             : 
      47             : namespace {
      48             : namespace legacy {
      49             : 
      50             : //===----------------------------------------------------------------------===//
      51             : // Legacy pass manager's PassTimingInfo implementation
      52             : 
      53             : /// Provides an interface for collecting pass timing information.
      54             : ///
      55             : /// It was intended to be generic but now we decided to split
      56             : /// interfaces completely. This is now exclusively for legacy-pass-manager use.
      57             : class PassTimingInfo {
      58             : public:
      59             :   using PassInstanceID = void *;
      60             : 
      61             : private:
      62             :   StringMap<unsigned> PassIDCountMap; ///< Map that counts instances of passes
      63             :   DenseMap<PassInstanceID, std::unique_ptr<Timer>> TimingData; ///< timers for pass instances
      64             :   TimerGroup TG;
      65             : 
      66             : public:
      67             :   /// Default constructor for yet-inactive timeinfo.
      68             :   /// Use \p init() to activate it.
      69             :   PassTimingInfo();
      70             : 
      71             :   /// Print out timing information and release timers.
      72             :   ~PassTimingInfo();
      73             : 
      74             :   /// Initializes the static \p TheTimeInfo member to a non-null value when
      75             :   /// -time-passes is enabled. Leaves it null otherwise.
      76             :   ///
      77             :   /// This method may be called multiple times.
      78             :   static void init();
      79             : 
      80             :   /// Prints out timing information and then resets the timers.
      81             :   void print();
      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          12 : PassTimingInfo::PassTimingInfo()
      95          12 :     : TG("pass", "... Pass execution timing report ...") {}
      96             : 
      97          24 : 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          12 :   TimingData.clear();
     101          12 : }
     102             : 
     103   101534865 : void PassTimingInfo::init() {
     104   101534865 :   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.
     110          12 :   static ManagedStatic<PassTimingInfo> TTI;
     111          12 :   TheTimeInfo = &*TTI;
     112             : }
     113             : 
     114             : /// Prints out timing information and then resets the timers.
     115           0 : void PassTimingInfo::print() { TG.print(*CreateInfoOutputFile()); }
     116             : 
     117        1033 : Timer *PassTimingInfo::newPassTimer(StringRef PassID, StringRef PassDesc) {
     118        1033 :   unsigned &num = PassIDCountMap[PassID];
     119        1033 :   num++;
     120             :   // Appending description with a pass-instance number for all but the first one
     121             :   std::string PassDescNumbered =
     122        1033 :       num <= 1 ? PassDesc.str() : formatv("{0} #{1}", PassDesc, num).str();
     123        2066 :   return new Timer(PassID, PassDescNumbered, TG);
     124             : }
     125             : 
     126        2337 : Timer *PassTimingInfo::getPassTimer(Pass *P, PassInstanceID Pass) {
     127        2337 :   if (P->getAsPMDataManager())
     128             :     return nullptr;
     129             : 
     130        2269 :   init();
     131        2269 :   sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
     132        2269 :   std::unique_ptr<Timer> &T = TimingData[Pass];
     133             : 
     134        2269 :   if (!T) {
     135        1033 :     StringRef PassName = P->getPassName();
     136        1033 :     StringRef PassArgument;
     137        1033 :     if (const PassInfo *PI = Pass::lookupPassInfo(P->getPassID()))
     138        1019 :       PassArgument = PI->getPassArgument();
     139        2052 :     T.reset(newPassTimer(PassArgument.empty() ? PassName : PassArgument, PassName));
     140             :   }
     141             :   return T.get();
     142             : }
     143             : 
     144             : PassTimingInfo *PassTimingInfo::TheTimeInfo;
     145             : } // namespace legacy
     146             : } // namespace
     147             : 
     148   101532587 : Timer *getPassTimer(Pass *P) {
     149   101532587 :   legacy::PassTimingInfo::init();
     150   101532605 :   if (legacy::PassTimingInfo::TheTimeInfo)
     151        2337 :     return legacy::PassTimingInfo::TheTimeInfo->getPassTimer(P, P);
     152             :   return nullptr;
     153             : }
     154             : 
     155             : /// If timing is enabled, report the times collected up to now and then reset
     156             : /// them.
     157          70 : void reportAndResetTimings() {
     158          70 :   if (legacy::PassTimingInfo::TheTimeInfo)
     159           0 :     legacy::PassTimingInfo::TheTimeInfo->print();
     160          70 : }
     161             : 
     162             : //===----------------------------------------------------------------------===//
     163             : // Pass timing handling for the New Pass Manager
     164             : //===----------------------------------------------------------------------===//
     165             : 
     166             : /// Returns the timer for the specified pass invocation of \p PassID.
     167             : /// Each time it creates a new timer.
     168         302 : Timer &TimePassesHandler::getPassTimer(StringRef PassID) {
     169             :   // Bump counts for each request of the timer.
     170         302 :   unsigned Count = nextPassID(PassID);
     171             : 
     172             :   // Unconditionally appending description with a pass-invocation number.
     173         604 :   std::string FullDesc = formatv("{0} #{1}", PassID, Count).str();
     174             : 
     175             :   PassInvocationID UID{PassID, Count};
     176         604 :   Timer *T = new Timer(PassID, FullDesc, TG);
     177         302 :   auto Pair = TimingData.try_emplace(UID, T);
     178             :   assert(Pair.second && "should always create a new timer");
     179         302 :   return *(Pair.first->second.get());
     180             : }
     181             : 
     182         936 : TimePassesHandler::TimePassesHandler(bool Enabled)
     183        1872 :     : TG("pass", "... Pass execution timing report ..."), Enabled(Enabled) {}
     184             : 
     185           0 : void TimePassesHandler::print() { TG.print(*CreateInfoOutputFile()); }
     186             : 
     187           0 : LLVM_DUMP_METHOD void TimePassesHandler::dump() const {
     188           0 :   dbgs() << "Dumping timers for " << getTypeName<TimePassesHandler>()
     189           0 :          << ":\n\tRunning:\n";
     190           0 :   for (auto &I : TimingData) {
     191             :     const Timer *MyTimer = I.second.get();
     192           0 :     if (!MyTimer || MyTimer->isRunning())
     193           0 :       dbgs() << "\tTimer " << MyTimer << " for pass " << I.first.first << "("
     194           0 :              << I.first.second << ")\n";
     195             :   }
     196           0 :   dbgs() << "\tTriggered:\n";
     197           0 :   for (auto &I : TimingData) {
     198             :     const Timer *MyTimer = I.second.get();
     199           0 :     if (!MyTimer || (MyTimer->hasTriggered() && !MyTimer->isRunning()))
     200           0 :       dbgs() << "\tTimer " << MyTimer << " for pass " << I.first.first << "("
     201           0 :              << I.first.second << ")\n";
     202             :   }
     203           0 : }
     204             : 
     205         302 : void TimePassesHandler::startTimer(StringRef PassID) {
     206         302 :   Timer &MyTimer = getPassTimer(PassID);
     207         302 :   TimerStack.push_back(&MyTimer);
     208         302 :   if (!MyTimer.isRunning())
     209         302 :     MyTimer.startTimer();
     210         302 : }
     211             : 
     212         302 : void TimePassesHandler::stopTimer(StringRef PassID) {
     213             :   assert(TimerStack.size() > 0 && "empty stack in popTimer");
     214             :   Timer *MyTimer = TimerStack.pop_back_val();
     215             :   assert(MyTimer && "timer should be present");
     216         302 :   if (MyTimer->isRunning())
     217         302 :     MyTimer->stopTimer();
     218         302 : }
     219             : 
     220         790 : static bool matchPassManager(StringRef PassID) {
     221         586 :   size_t prefix_pos = PassID.find('<');
     222         204 :   if (prefix_pos == StringRef::npos)
     223         586 :     return false;
     224         204 :   StringRef Prefix = PassID.substr(0, prefix_pos);
     225             :   return Prefix.endswith("PassManager") || Prefix.endswith("PassAdaptor") ||
     226             :          Prefix.endswith("AnalysisManagerProxy");
     227             : }
     228             : 
     229         395 : bool TimePassesHandler::runBeforePass(StringRef PassID, Any IR) {
     230         395 :   if (matchPassManager(PassID))
     231             :     return true;
     232             : 
     233         302 :   startTimer(PassID);
     234             : 
     235             :   LLVM_DEBUG(dbgs() << "after runBeforePass(" << PassID << ")\n");
     236             :   LLVM_DEBUG(dump());
     237             : 
     238             :   // we are not going to skip this pass, thus return true.
     239         302 :   return true;
     240             : }
     241             : 
     242         395 : void TimePassesHandler::runAfterPass(StringRef PassID, Any IR) {
     243         395 :   if (matchPassManager(PassID))
     244             :     return;
     245             : 
     246         302 :   stopTimer(PassID);
     247             : 
     248             :   LLVM_DEBUG(dbgs() << "after runAfterPass(" << PassID << ")\n");
     249             :   LLVM_DEBUG(dump());
     250             : }
     251             : 
     252         936 : void TimePassesHandler::registerCallbacks(PassInstrumentationCallbacks &PIC) {
     253         936 :   if (!Enabled)
     254             :     return;
     255             : 
     256           3 :   PIC.registerBeforePassCallback(
     257             :       [this](StringRef P, Any IR) { return this->runBeforePass(P, IR); });
     258           3 :   PIC.registerAfterPassCallback(
     259             :       [this](StringRef P, Any IR) { this->runAfterPass(P, IR); });
     260           3 :   PIC.registerBeforeAnalysisCallback(
     261             :       [this](StringRef P, Any IR) { this->runBeforePass(P, IR); });
     262           3 :   PIC.registerAfterAnalysisCallback(
     263             :       [this](StringRef P, Any IR) { this->runAfterPass(P, IR); });
     264             : }
     265             : 
     266             : } // namespace llvm

Generated by: LCOV version 1.13