123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- llvm/IR/PassInstrumentation.h ----------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- ///
- /// This file defines the Pass Instrumentation classes that provide
- /// instrumentation points into the pass execution by PassManager.
- ///
- /// There are two main classes:
- /// - PassInstrumentation provides a set of instrumentation points for
- /// pass managers to call on.
- ///
- /// - PassInstrumentationCallbacks registers callbacks and provides access
- /// to them for PassInstrumentation.
- ///
- /// PassInstrumentation object is being used as a result of
- /// PassInstrumentationAnalysis (so it is intended to be easily copyable).
- ///
- /// Intended scheme of use for Pass Instrumentation is as follows:
- /// - register instrumentation callbacks in PassInstrumentationCallbacks
- /// instance. PassBuilder provides helper for that.
- ///
- /// - register PassInstrumentationAnalysis with all the PassManagers.
- /// PassBuilder handles that automatically when registering analyses.
- ///
- /// - Pass Manager requests PassInstrumentationAnalysis from analysis manager
- /// and gets PassInstrumentation as its result.
- ///
- /// - Pass Manager invokes PassInstrumentation entry points appropriately,
- /// passing StringRef identification ("name") of the pass currently being
- /// executed and IRUnit it works on. There can be different schemes of
- /// providing names in future, currently it is just a name() of the pass.
- ///
- /// - PassInstrumentation wraps address of IRUnit into llvm::Any and passes
- /// control to all the registered callbacks. Note that we specifically wrap
- /// 'const IRUnitT*' so as to avoid any accidental changes to IR in
- /// instrumenting callbacks.
- ///
- /// - Some instrumentation points (BeforePass) allow to control execution
- /// of a pass. For those callbacks returning false means pass will not be
- /// executed.
- ///
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_IR_PASSINSTRUMENTATION_H
- #define LLVM_IR_PASSINSTRUMENTATION_H
- #include "llvm/ADT/Any.h"
- #include "llvm/ADT/FunctionExtras.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringMap.h"
- #include <type_traits>
- namespace llvm {
- class PreservedAnalyses;
- class StringRef;
- /// This class manages callbacks registration, as well as provides a way for
- /// PassInstrumentation to pass control to the registered callbacks.
- class PassInstrumentationCallbacks {
- public:
- // Before/After callbacks accept IRUnits whenever appropriate, so they need
- // to take them as constant pointers, wrapped with llvm::Any.
- // For the case when IRUnit has been invalidated there is a different
- // callback to use - AfterPassInvalidated.
- // We call all BeforePassFuncs to determine if a pass should run or not.
- // BeforeNonSkippedPassFuncs are called only if the pass should run.
- // TODO: currently AfterPassInvalidated does not accept IRUnit, since passing
- // already invalidated IRUnit is unsafe. There are ways to handle invalidated
- // IRUnits in a safe way, and we might pursue that as soon as there is a
- // useful instrumentation that needs it.
- using BeforePassFunc = bool(StringRef, Any);
- using BeforeSkippedPassFunc = void(StringRef, Any);
- using BeforeNonSkippedPassFunc = void(StringRef, Any);
- using AfterPassFunc = void(StringRef, Any, const PreservedAnalyses &);
- using AfterPassInvalidatedFunc = void(StringRef, const PreservedAnalyses &);
- using BeforeAnalysisFunc = void(StringRef, Any);
- using AfterAnalysisFunc = void(StringRef, Any);
- public:
- PassInstrumentationCallbacks() {}
- /// Copying PassInstrumentationCallbacks is not intended.
- PassInstrumentationCallbacks(const PassInstrumentationCallbacks &) = delete;
- void operator=(const PassInstrumentationCallbacks &) = delete;
- template <typename CallableT>
- void registerShouldRunOptionalPassCallback(CallableT C) {
- ShouldRunOptionalPassCallbacks.emplace_back(std::move(C));
- }
- template <typename CallableT>
- void registerBeforeSkippedPassCallback(CallableT C) {
- BeforeSkippedPassCallbacks.emplace_back(std::move(C));
- }
- template <typename CallableT>
- void registerBeforeNonSkippedPassCallback(CallableT C) {
- BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
- }
- template <typename CallableT> void registerAfterPassCallback(CallableT C) {
- AfterPassCallbacks.emplace_back(std::move(C));
- }
- template <typename CallableT>
- void registerAfterPassInvalidatedCallback(CallableT C) {
- AfterPassInvalidatedCallbacks.emplace_back(std::move(C));
- }
- template <typename CallableT>
- void registerBeforeAnalysisCallback(CallableT C) {
- BeforeAnalysisCallbacks.emplace_back(std::move(C));
- }
- template <typename CallableT>
- void registerAfterAnalysisCallback(CallableT C) {
- AfterAnalysisCallbacks.emplace_back(std::move(C));
- }
- /// Add a class name to pass name mapping for use by pass instrumentation.
- void addClassToPassName(StringRef ClassName, StringRef PassName);
- /// Get the pass name for a given pass class name.
- StringRef getPassNameForClassName(StringRef ClassName);
- private:
- friend class PassInstrumentation;
- /// These are only run on passes that are not required. They return false when
- /// an optional pass should be skipped.
- SmallVector<llvm::unique_function<BeforePassFunc>, 4>
- ShouldRunOptionalPassCallbacks;
- /// These are run on passes that are skipped.
- SmallVector<llvm::unique_function<BeforeSkippedPassFunc>, 4>
- BeforeSkippedPassCallbacks;
- /// These are run on passes that are about to be run.
- SmallVector<llvm::unique_function<BeforeNonSkippedPassFunc>, 4>
- BeforeNonSkippedPassCallbacks;
- /// These are run on passes that have just run.
- SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks;
- /// These are run passes that have just run on invalidated IR.
- SmallVector<llvm::unique_function<AfterPassInvalidatedFunc>, 4>
- AfterPassInvalidatedCallbacks;
- /// These are run on analyses that are about to be run.
- SmallVector<llvm::unique_function<BeforeAnalysisFunc>, 4>
- BeforeAnalysisCallbacks;
- /// These are run on analyses that have been run.
- SmallVector<llvm::unique_function<AfterAnalysisFunc>, 4>
- AfterAnalysisCallbacks;
- StringMap<std::string> ClassToPassName;
- };
- /// This class provides instrumentation entry points for the Pass Manager,
- /// doing calls to callbacks registered in PassInstrumentationCallbacks.
- class PassInstrumentation {
- PassInstrumentationCallbacks *Callbacks;
- // Template argument PassT of PassInstrumentation::runBeforePass could be two
- // kinds: (1) a regular pass inherited from PassInfoMixin (happen when
- // creating a adaptor pass for a regular pass); (2) a type-erased PassConcept
- // created from (1). Here we want to make case (1) skippable unconditionally
- // since they are regular passes. We call PassConcept::isRequired to decide
- // for case (2).
- template <typename PassT>
- using has_required_t = decltype(std::declval<PassT &>().isRequired());
- template <typename PassT>
- static std::enable_if_t<is_detected<has_required_t, PassT>::value, bool>
- isRequired(const PassT &Pass) {
- return Pass.isRequired();
- }
- template <typename PassT>
- static std::enable_if_t<!is_detected<has_required_t, PassT>::value, bool>
- isRequired(const PassT &Pass) {
- return false;
- }
- public:
- /// Callbacks object is not owned by PassInstrumentation, its life-time
- /// should at least match the life-time of corresponding
- /// PassInstrumentationAnalysis (which usually is till the end of current
- /// compilation).
- PassInstrumentation(PassInstrumentationCallbacks *CB = nullptr)
- : Callbacks(CB) {}
- /// BeforePass instrumentation point - takes \p Pass instance to be executed
- /// and constant reference to IR it operates on. \Returns true if pass is
- /// allowed to be executed. These are only run on optional pass since required
- /// passes must always be run. This allows these callbacks to print info when
- /// they want to skip a pass.
- template <typename IRUnitT, typename PassT>
- bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const {
- if (!Callbacks)
- return true;
- bool ShouldRun = true;
- if (!isRequired(Pass)) {
- for (auto &C : Callbacks->ShouldRunOptionalPassCallbacks)
- ShouldRun &= C(Pass.name(), llvm::Any(&IR));
- }
- if (ShouldRun) {
- for (auto &C : Callbacks->BeforeNonSkippedPassCallbacks)
- C(Pass.name(), llvm::Any(&IR));
- } else {
- for (auto &C : Callbacks->BeforeSkippedPassCallbacks)
- C(Pass.name(), llvm::Any(&IR));
- }
- return ShouldRun;
- }
- /// AfterPass instrumentation point - takes \p Pass instance that has
- /// just been executed and constant reference to \p IR it operates on.
- /// \p IR is guaranteed to be valid at this point.
- template <typename IRUnitT, typename PassT>
- void runAfterPass(const PassT &Pass, const IRUnitT &IR,
- const PreservedAnalyses &PA) const {
- if (Callbacks)
- for (auto &C : Callbacks->AfterPassCallbacks)
- C(Pass.name(), llvm::Any(&IR), PA);
- }
- /// AfterPassInvalidated instrumentation point - takes \p Pass instance
- /// that has just been executed. For use when IR has been invalidated
- /// by \p Pass execution.
- template <typename IRUnitT, typename PassT>
- void runAfterPassInvalidated(const PassT &Pass,
- const PreservedAnalyses &PA) const {
- if (Callbacks)
- for (auto &C : Callbacks->AfterPassInvalidatedCallbacks)
- C(Pass.name(), PA);
- }
- /// BeforeAnalysis instrumentation point - takes \p Analysis instance
- /// to be executed and constant reference to IR it operates on.
- template <typename IRUnitT, typename PassT>
- void runBeforeAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
- if (Callbacks)
- for (auto &C : Callbacks->BeforeAnalysisCallbacks)
- C(Analysis.name(), llvm::Any(&IR));
- }
- /// AfterAnalysis instrumentation point - takes \p Analysis instance
- /// that has just been executed and constant reference to IR it operated on.
- template <typename IRUnitT, typename PassT>
- void runAfterAnalysis(const PassT &Analysis, const IRUnitT &IR) const {
- if (Callbacks)
- for (auto &C : Callbacks->AfterAnalysisCallbacks)
- C(Analysis.name(), llvm::Any(&IR));
- }
- /// Handle invalidation from the pass manager when PassInstrumentation
- /// is used as the result of PassInstrumentationAnalysis.
- ///
- /// On attempt to invalidate just return false. There is nothing to become
- /// invalid here.
- template <typename IRUnitT, typename... ExtraArgsT>
- bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &,
- ExtraArgsT...) {
- return false;
- }
- template <typename CallableT>
- void pushBeforeNonSkippedPassCallback(CallableT C) {
- if (Callbacks)
- Callbacks->BeforeNonSkippedPassCallbacks.emplace_back(std::move(C));
- }
- void popBeforeNonSkippedPassCallback() {
- if (Callbacks)
- Callbacks->BeforeNonSkippedPassCallbacks.pop_back();
- }
- };
- bool isSpecialPass(StringRef PassID, const std::vector<StringRef> &Specials);
- } // namespace llvm
- #endif
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|