brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · dab56f0 Raw
168 lines · cpp
1//===- PassTiming.cpp -----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "PassDetail.h"10#include "mlir/Pass/PassManager.h"11#include "llvm/ADT/SmallVector.h"12#include "llvm/Support/Threading.h"13 14#include <optional>15 16using namespace mlir;17using namespace mlir::detail;18 19//===----------------------------------------------------------------------===//20// PassTiming21//===----------------------------------------------------------------------===//22 23namespace {24struct PassTiming : public PassInstrumentation {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) {}30 31  /// If a pass can spawn additional work on other threads, it records the32  /// index to its currently active timer here. Passes that run on a33  /// newly-forked thread will check this list to find the active timer of the34  /// parent thread into which the new thread should be nested.35  DenseMap<PipelineParentInfo, unsigned> parentTimerIndices;36 37  /// The timing manager owned by this instrumentation (in case timing was38  /// enabled by the user on the pass manager without providing an external39  /// timing manager). This *must* appear before the `ownedTimingScope` to40  /// ensure the timing manager is destroyed *after* the scope, since the latter41  /// may hold a timer that points into the former.42  std::unique_ptr<TimingManager> ownedTimingManager;43  TimingScope ownedTimingScope;44 45  /// A stack of the currently active timing scopes per thread.46  DenseMap<uint64_t, SmallVector<TimingScope, 4>> activeThreadTimers;47 48  /// The root timing scope into which timing is reported.49  TimingScope &rootScope;50 51  //===--------------------------------------------------------------------===//52  // Pipeline53  //===--------------------------------------------------------------------===//54 55  void runBeforePipeline(std::optional<OperationName> name,56                         const PipelineParentInfo &parentInfo) override {57    auto tid = llvm::get_threadid();58    auto &activeTimers = activeThreadTimers[tid];59 60    // Find the parent scope, either using the parent info or the root scope61    // (e.g. in the case of the top-level pipeline).62    TimingScope *parentScope;63    auto it = parentTimerIndices.find(parentInfo);64    if (it != parentTimerIndices.end())65      parentScope = &activeThreadTimers[parentInfo.parentThreadID][it->second];66    else67      parentScope = &rootScope;68 69    // Use nullptr to anchor op-agnostic pipelines, otherwise use the name of70    // the operation.71    const void *timerId = name ? name->getAsOpaquePointer() : nullptr;72    activeTimers.push_back(parentScope->nest(timerId, [name] {73      return ("'" + (name ? name->getStringRef() : "any") + "' Pipeline").str();74    }));75  }76 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();82  }83 84  //===--------------------------------------------------------------------===//85  // Pass86  //===--------------------------------------------------------------------===//87 88  void runBeforePass(Pass *pass, Operation *) override {89    auto tid = llvm::get_threadid();90    auto &activeTimers = activeThreadTimers[tid];91    auto &parentScope = activeTimers.empty() ? rootScope : activeTimers.back();92 93    if (auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass)) {94      parentTimerIndices[{tid, pass}] = activeTimers.size();95      auto scope =96          parentScope.nest(pass->getThreadingSiblingOrThis(),97                           [adaptor]() { return adaptor->getAdaptorName(); });98      if (adaptor->getPassManagers().size() <= 1)99        scope.hide();100      activeTimers.push_back(std::move(scope));101    } else {102      activeTimers.push_back(103          parentScope.nest(pass->getThreadingSiblingOrThis(),104                           [pass]() { return std::string(pass->getName()); }));105    }106  }107 108  void runAfterPass(Pass *pass, Operation *) override {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();115  }116 117  void runAfterPassFailed(Pass *pass, Operation *op) override {118    runAfterPass(pass, op);119  }120 121  //===--------------------------------------------------------------------===//122  // Analysis123  //===--------------------------------------------------------------------===//124 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(); }));131  }132 133  void runAfterAnalysis(StringRef, TypeID, Operation *) override {134    auto &activeTimers = activeThreadTimers[llvm::get_threadid()];135    assert(!activeTimers.empty() && "expected active timer");136    activeTimers.pop_back();137  }138};139} // namespace140 141//===----------------------------------------------------------------------===//142// PassManager143//===----------------------------------------------------------------------===//144 145/// Add an instrumentation to time the execution of passes and the computation146/// of analyses.147void PassManager::enableTiming(TimingScope &timingScope) {148  if (!timingScope)149    return;150  addInstrumentation(std::make_unique<PassTiming>(timingScope));151}152 153/// Add an instrumentation to time the execution of passes and the computation154/// of analyses.155void PassManager::enableTiming(std::unique_ptr<TimingManager> tm) {156  if (!tm->getRootTimer())157    return; // no need to keep the timing manager around if it's disabled158  addInstrumentation(std::make_unique<PassTiming>(std::move(tm)));159}160 161/// Add an instrumentation to time the execution of passes and the computation162/// of analyses.163void PassManager::enableTiming() {164  auto tm = std::make_unique<DefaultTimingManager>();165  tm->setEnabled(true);166  enableTiming(std::move(tm));167}168