10b57cec5SDimitry Andric //===- PassManager.h - Pass management infrastructure -----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This header defines various interfaces for pass management in LLVM. There
110b57cec5SDimitry Andric /// is no "pass" interface in LLVM per se. Instead, an instance of any class
120b57cec5SDimitry Andric /// which supports a method to 'run' it over a unit of IR can be used as
130b57cec5SDimitry Andric /// a pass. A pass manager is generally a tool to collect a sequence of passes
140b57cec5SDimitry Andric /// which run over a particular IR construct, and run each of them in sequence
150b57cec5SDimitry Andric /// over each such construct in the containing IR construct. As there is no
160b57cec5SDimitry Andric /// containing IR construct for a Module, a manager for passes over modules
170b57cec5SDimitry Andric /// forms the base case which runs its managed passes in sequence over the
180b57cec5SDimitry Andric /// single module provided.
190b57cec5SDimitry Andric ///
200b57cec5SDimitry Andric /// The core IR library provides managers for running passes over
210b57cec5SDimitry Andric /// modules and functions.
220b57cec5SDimitry Andric ///
230b57cec5SDimitry Andric /// * FunctionPassManager can run over a Module, runs each pass over
240b57cec5SDimitry Andric ///   a Function.
250b57cec5SDimitry Andric /// * ModulePassManager must be directly run, runs each pass over the Module.
260b57cec5SDimitry Andric ///
270b57cec5SDimitry Andric /// Note that the implementations of the pass managers use concept-based
280b57cec5SDimitry Andric /// polymorphism as outlined in the "Value Semantics and Concept-based
290b57cec5SDimitry Andric /// Polymorphism" talk (or its abbreviated sibling "Inheritance Is The Base
300b57cec5SDimitry Andric /// Class of Evil") by Sean Parent:
310b57cec5SDimitry Andric /// * http://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations
320b57cec5SDimitry Andric /// * http://www.youtube.com/watch?v=_BpMYeUFXv8
330b57cec5SDimitry Andric /// * http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil
340b57cec5SDimitry Andric ///
350b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #ifndef LLVM_IR_PASSMANAGER_H
380b57cec5SDimitry Andric #define LLVM_IR_PASSMANAGER_H
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
41e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h"
420b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
430b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
440b57cec5SDimitry Andric #include "llvm/ADT/TinyPtrVector.h"
450b57cec5SDimitry Andric #include "llvm/IR/Function.h"
460b57cec5SDimitry Andric #include "llvm/IR/Module.h"
470b57cec5SDimitry Andric #include "llvm/IR/PassInstrumentation.h"
480b57cec5SDimitry Andric #include "llvm/IR/PassManagerInternal.h"
495f757f3fSDimitry Andric #include "llvm/Support/CommandLine.h"
505ffd83dbSDimitry Andric #include "llvm/Support/TimeProfiler.h"
510b57cec5SDimitry Andric #include "llvm/Support/TypeName.h"
520b57cec5SDimitry Andric #include <cassert>
530b57cec5SDimitry Andric #include <cstring>
540b57cec5SDimitry Andric #include <iterator>
550b57cec5SDimitry Andric #include <list>
560b57cec5SDimitry Andric #include <memory>
570b57cec5SDimitry Andric #include <tuple>
580b57cec5SDimitry Andric #include <type_traits>
590b57cec5SDimitry Andric #include <utility>
600b57cec5SDimitry Andric #include <vector>
610b57cec5SDimitry Andric 
625f757f3fSDimitry Andric extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
635f757f3fSDimitry Andric 
640b57cec5SDimitry Andric namespace llvm {
650b57cec5SDimitry Andric 
665f757f3fSDimitry Andric // RemoveDIs: Provide facilities for converting debug-info from one form to
675f757f3fSDimitry Andric // another, which are no-ops for everything but modules.
shouldConvertDbgInfo(IRUnitT & IR)685f757f3fSDimitry Andric template <class IRUnitT> inline bool shouldConvertDbgInfo(IRUnitT &IR) {
695f757f3fSDimitry Andric   return false;
705f757f3fSDimitry Andric }
shouldConvertDbgInfo(Module & IR)715f757f3fSDimitry Andric template <> inline bool shouldConvertDbgInfo(Module &IR) {
725f757f3fSDimitry Andric   return !IR.IsNewDbgInfoFormat && UseNewDbgInfoFormat;
735f757f3fSDimitry Andric }
doConvertDbgInfoToNew(IRUnitT & IR)745f757f3fSDimitry Andric template <class IRUnitT> inline void doConvertDbgInfoToNew(IRUnitT &IR) {}
doConvertDbgInfoToNew(Module & IR)755f757f3fSDimitry Andric template <> inline void doConvertDbgInfoToNew(Module &IR) {
765f757f3fSDimitry Andric   IR.convertToNewDbgValues();
775f757f3fSDimitry Andric }
doConvertDebugInfoToOld(IRUnitT & IR)785f757f3fSDimitry Andric template <class IRUnitT> inline void doConvertDebugInfoToOld(IRUnitT &IR) {}
doConvertDebugInfoToOld(Module & IR)795f757f3fSDimitry Andric template <> inline void doConvertDebugInfoToOld(Module &IR) {
805f757f3fSDimitry Andric   IR.convertFromNewDbgValues();
815f757f3fSDimitry Andric }
825f757f3fSDimitry Andric 
830b57cec5SDimitry Andric /// A special type used by analysis passes to provide an address that
840b57cec5SDimitry Andric /// identifies that particular analysis pass type.
850b57cec5SDimitry Andric ///
860b57cec5SDimitry Andric /// Analysis passes should have a static data member of this type and derive
870b57cec5SDimitry Andric /// from the \c AnalysisInfoMixin to get a static ID method used to identify
880b57cec5SDimitry Andric /// the analysis in the pass management infrastructure.
890b57cec5SDimitry Andric struct alignas(8) AnalysisKey {};
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric /// A special type used to provide an address that identifies a set of related
920b57cec5SDimitry Andric /// analyses.  These sets are primarily used below to mark sets of analyses as
930b57cec5SDimitry Andric /// preserved.
940b57cec5SDimitry Andric ///
950b57cec5SDimitry Andric /// For example, a transformation can indicate that it preserves the CFG of a
960b57cec5SDimitry Andric /// function by preserving the appropriate AnalysisSetKey.  An analysis that
970b57cec5SDimitry Andric /// depends only on the CFG can then check if that AnalysisSetKey is preserved;
980b57cec5SDimitry Andric /// if it is, the analysis knows that it itself is preserved.
990b57cec5SDimitry Andric struct alignas(8) AnalysisSetKey {};
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric /// This templated class represents "all analyses that operate over \<a
1020b57cec5SDimitry Andric /// particular IR unit\>" (e.g. a Function or a Module) in instances of
1030b57cec5SDimitry Andric /// PreservedAnalysis.
1040b57cec5SDimitry Andric ///
1050b57cec5SDimitry Andric /// This lets a transformation say e.g. "I preserved all function analyses".
1060b57cec5SDimitry Andric ///
1070b57cec5SDimitry Andric /// Note that you must provide an explicit instantiation declaration and
1080b57cec5SDimitry Andric /// definition for this template in order to get the correct behavior on
1090b57cec5SDimitry Andric /// Windows. Otherwise, the address of SetKey will not be stable.
1100b57cec5SDimitry Andric template <typename IRUnitT> class AllAnalysesOn {
1110b57cec5SDimitry Andric public:
ID()1120b57cec5SDimitry Andric   static AnalysisSetKey *ID() { return &SetKey; }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric private:
1150b57cec5SDimitry Andric   static AnalysisSetKey SetKey;
1160b57cec5SDimitry Andric };
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric extern template class AllAnalysesOn<Module>;
1210b57cec5SDimitry Andric extern template class AllAnalysesOn<Function>;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric /// Represents analyses that only rely on functions' control flow.
1240b57cec5SDimitry Andric ///
1250b57cec5SDimitry Andric /// This can be used with \c PreservedAnalyses to mark the CFG as preserved and
1260b57cec5SDimitry Andric /// to query whether it has been preserved.
1270b57cec5SDimitry Andric ///
1280b57cec5SDimitry Andric /// The CFG of a function is defined as the set of basic blocks and the edges
1290b57cec5SDimitry Andric /// between them. Changing the set of basic blocks in a function is enough to
1300b57cec5SDimitry Andric /// mutate the CFG. Mutating the condition of a branch or argument of an
1310b57cec5SDimitry Andric /// invoked function does not mutate the CFG, but changing the successor labels
1320b57cec5SDimitry Andric /// of those instructions does.
1330b57cec5SDimitry Andric class CFGAnalyses {
1340b57cec5SDimitry Andric public:
ID()1350b57cec5SDimitry Andric   static AnalysisSetKey *ID() { return &SetKey; }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric private:
1380b57cec5SDimitry Andric   static AnalysisSetKey SetKey;
1390b57cec5SDimitry Andric };
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric /// A set of analyses that are preserved following a run of a transformation
1420b57cec5SDimitry Andric /// pass.
1430b57cec5SDimitry Andric ///
1440b57cec5SDimitry Andric /// Transformation passes build and return these objects to communicate which
1450b57cec5SDimitry Andric /// analyses are still valid after the transformation. For most passes this is
1460b57cec5SDimitry Andric /// fairly simple: if they don't change anything all analyses are preserved,
1470b57cec5SDimitry Andric /// otherwise only a short list of analyses that have been explicitly updated
1480b57cec5SDimitry Andric /// are preserved.
1490b57cec5SDimitry Andric ///
1500b57cec5SDimitry Andric /// This class also lets transformation passes mark abstract *sets* of analyses
1510b57cec5SDimitry Andric /// as preserved. A transformation that (say) does not alter the CFG can
1520b57cec5SDimitry Andric /// indicate such by marking a particular AnalysisSetKey as preserved, and
1530b57cec5SDimitry Andric /// then analyses can query whether that AnalysisSetKey is preserved.
1540b57cec5SDimitry Andric ///
1550b57cec5SDimitry Andric /// Finally, this class can represent an "abandoned" analysis, which is
1560b57cec5SDimitry Andric /// not preserved even if it would be covered by some abstract set of analyses.
1570b57cec5SDimitry Andric ///
1580b57cec5SDimitry Andric /// Given a `PreservedAnalyses` object, an analysis will typically want to
1590b57cec5SDimitry Andric /// figure out whether it is preserved. In the example below, MyAnalysisType is
1600b57cec5SDimitry Andric /// preserved if it's not abandoned, and (a) it's explicitly marked as
1610b57cec5SDimitry Andric /// preserved, (b), the set AllAnalysesOn<MyIRUnit> is preserved, or (c) both
1620b57cec5SDimitry Andric /// AnalysisSetA and AnalysisSetB are preserved.
1630b57cec5SDimitry Andric ///
1640b57cec5SDimitry Andric /// ```
1650b57cec5SDimitry Andric ///   auto PAC = PA.getChecker<MyAnalysisType>();
1660b57cec5SDimitry Andric ///   if (PAC.preserved() || PAC.preservedSet<AllAnalysesOn<MyIRUnit>>() ||
1670b57cec5SDimitry Andric ///       (PAC.preservedSet<AnalysisSetA>() &&
1680b57cec5SDimitry Andric ///        PAC.preservedSet<AnalysisSetB>())) {
1690b57cec5SDimitry Andric ///     // The analysis has been successfully preserved ...
1700b57cec5SDimitry Andric ///   }
1710b57cec5SDimitry Andric /// ```
1720b57cec5SDimitry Andric class PreservedAnalyses {
1730b57cec5SDimitry Andric public:
1740b57cec5SDimitry Andric   /// Convenience factory function for the empty preserved set.
none()1750b57cec5SDimitry Andric   static PreservedAnalyses none() { return PreservedAnalyses(); }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   /// Construct a special preserved set that preserves all passes.
all()1780b57cec5SDimitry Andric   static PreservedAnalyses all() {
1790b57cec5SDimitry Andric     PreservedAnalyses PA;
1800b57cec5SDimitry Andric     PA.PreservedIDs.insert(&AllAnalysesKey);
1810b57cec5SDimitry Andric     return PA;
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric   /// Construct a preserved analyses object with a single preserved set.
1850b57cec5SDimitry Andric   template <typename AnalysisSetT>
allInSet()1860b57cec5SDimitry Andric   static PreservedAnalyses allInSet() {
1870b57cec5SDimitry Andric     PreservedAnalyses PA;
1880b57cec5SDimitry Andric     PA.preserveSet<AnalysisSetT>();
1890b57cec5SDimitry Andric     return PA;
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   /// Mark an analysis as preserved.
preserve()1930b57cec5SDimitry Andric   template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   /// Given an analysis's ID, mark the analysis as preserved, adding it
1960b57cec5SDimitry Andric   /// to the set.
preserve(AnalysisKey * ID)1970b57cec5SDimitry Andric   void preserve(AnalysisKey *ID) {
1980b57cec5SDimitry Andric     // Clear this ID from the explicit not-preserved set if present.
1990b57cec5SDimitry Andric     NotPreservedAnalysisIDs.erase(ID);
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     // If we're not already preserving all analyses (other than those in
2020b57cec5SDimitry Andric     // NotPreservedAnalysisIDs).
2030b57cec5SDimitry Andric     if (!areAllPreserved())
2040b57cec5SDimitry Andric       PreservedIDs.insert(ID);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   /// Mark an analysis set as preserved.
preserveSet()2080b57cec5SDimitry Andric   template <typename AnalysisSetT> void preserveSet() {
2090b57cec5SDimitry Andric     preserveSet(AnalysisSetT::ID());
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   /// Mark an analysis set as preserved using its ID.
preserveSet(AnalysisSetKey * ID)2130b57cec5SDimitry Andric   void preserveSet(AnalysisSetKey *ID) {
2140b57cec5SDimitry Andric     // If we're not already in the saturated 'all' state, add this set.
2150b57cec5SDimitry Andric     if (!areAllPreserved())
2160b57cec5SDimitry Andric       PreservedIDs.insert(ID);
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   /// Mark an analysis as abandoned.
2200b57cec5SDimitry Andric   ///
2210b57cec5SDimitry Andric   /// An abandoned analysis is not preserved, even if it is nominally covered
2220b57cec5SDimitry Andric   /// by some other set or was previously explicitly marked as preserved.
2230b57cec5SDimitry Andric   ///
2240b57cec5SDimitry Andric   /// Note that you can only abandon a specific analysis, not a *set* of
2250b57cec5SDimitry Andric   /// analyses.
abandon()2260b57cec5SDimitry Andric   template <typename AnalysisT> void abandon() { abandon(AnalysisT::ID()); }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   /// Mark an analysis as abandoned using its ID.
2290b57cec5SDimitry Andric   ///
2300b57cec5SDimitry Andric   /// An abandoned analysis is not preserved, even if it is nominally covered
2310b57cec5SDimitry Andric   /// by some other set or was previously explicitly marked as preserved.
2320b57cec5SDimitry Andric   ///
2330b57cec5SDimitry Andric   /// Note that you can only abandon a specific analysis, not a *set* of
2340b57cec5SDimitry Andric   /// analyses.
abandon(AnalysisKey * ID)2350b57cec5SDimitry Andric   void abandon(AnalysisKey *ID) {
2360b57cec5SDimitry Andric     PreservedIDs.erase(ID);
2370b57cec5SDimitry Andric     NotPreservedAnalysisIDs.insert(ID);
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   /// Intersect this set with another in place.
2410b57cec5SDimitry Andric   ///
2420b57cec5SDimitry Andric   /// This is a mutating operation on this preserved set, removing all
2430b57cec5SDimitry Andric   /// preserved passes which are not also preserved in the argument.
intersect(const PreservedAnalyses & Arg)2440b57cec5SDimitry Andric   void intersect(const PreservedAnalyses &Arg) {
2450b57cec5SDimitry Andric     if (Arg.areAllPreserved())
2460b57cec5SDimitry Andric       return;
2470b57cec5SDimitry Andric     if (areAllPreserved()) {
2480b57cec5SDimitry Andric       *this = Arg;
2490b57cec5SDimitry Andric       return;
2500b57cec5SDimitry Andric     }
2510b57cec5SDimitry Andric     // The intersection requires the *union* of the explicitly not-preserved
2520b57cec5SDimitry Andric     // IDs and the *intersection* of the preserved IDs.
253bdd1243dSDimitry Andric     for (auto *ID : Arg.NotPreservedAnalysisIDs) {
2540b57cec5SDimitry Andric       PreservedIDs.erase(ID);
2550b57cec5SDimitry Andric       NotPreservedAnalysisIDs.insert(ID);
2560b57cec5SDimitry Andric     }
257bdd1243dSDimitry Andric     for (auto *ID : PreservedIDs)
2580b57cec5SDimitry Andric       if (!Arg.PreservedIDs.count(ID))
2590b57cec5SDimitry Andric         PreservedIDs.erase(ID);
2600b57cec5SDimitry Andric   }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   /// Intersect this set with a temporary other set in place.
2630b57cec5SDimitry Andric   ///
2640b57cec5SDimitry Andric   /// This is a mutating operation on this preserved set, removing all
2650b57cec5SDimitry Andric   /// preserved passes which are not also preserved in the argument.
intersect(PreservedAnalyses && Arg)2660b57cec5SDimitry Andric   void intersect(PreservedAnalyses &&Arg) {
2670b57cec5SDimitry Andric     if (Arg.areAllPreserved())
2680b57cec5SDimitry Andric       return;
2690b57cec5SDimitry Andric     if (areAllPreserved()) {
2700b57cec5SDimitry Andric       *this = std::move(Arg);
2710b57cec5SDimitry Andric       return;
2720b57cec5SDimitry Andric     }
2730b57cec5SDimitry Andric     // The intersection requires the *union* of the explicitly not-preserved
2740b57cec5SDimitry Andric     // IDs and the *intersection* of the preserved IDs.
275bdd1243dSDimitry Andric     for (auto *ID : Arg.NotPreservedAnalysisIDs) {
2760b57cec5SDimitry Andric       PreservedIDs.erase(ID);
2770b57cec5SDimitry Andric       NotPreservedAnalysisIDs.insert(ID);
2780b57cec5SDimitry Andric     }
279bdd1243dSDimitry Andric     for (auto *ID : PreservedIDs)
2800b57cec5SDimitry Andric       if (!Arg.PreservedIDs.count(ID))
2810b57cec5SDimitry Andric         PreservedIDs.erase(ID);
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   /// A checker object that makes it easy to query for whether an analysis or
2850b57cec5SDimitry Andric   /// some set covering it is preserved.
2860b57cec5SDimitry Andric   class PreservedAnalysisChecker {
2870b57cec5SDimitry Andric     friend class PreservedAnalyses;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     const PreservedAnalyses &PA;
2900b57cec5SDimitry Andric     AnalysisKey *const ID;
2910b57cec5SDimitry Andric     const bool IsAbandoned;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     /// A PreservedAnalysisChecker is tied to a particular Analysis because
2940b57cec5SDimitry Andric     /// `preserved()` and `preservedSet()` both return false if the Analysis
2950b57cec5SDimitry Andric     /// was abandoned.
PreservedAnalysisChecker(const PreservedAnalyses & PA,AnalysisKey * ID)2960b57cec5SDimitry Andric     PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID)
2970b57cec5SDimitry Andric         : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {}
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   public:
3000b57cec5SDimitry Andric     /// Returns true if the checker's analysis was not abandoned and either
3010b57cec5SDimitry Andric     ///  - the analysis is explicitly preserved or
3020b57cec5SDimitry Andric     ///  - all analyses are preserved.
preserved()3030b57cec5SDimitry Andric     bool preserved() {
3040b57cec5SDimitry Andric       return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) ||
3050b57cec5SDimitry Andric                               PA.PreservedIDs.count(ID));
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric     /// Return true if the checker's analysis was not abandoned, i.e. it was not
3090b57cec5SDimitry Andric     /// explicitly invalidated. Even if the analysis is not explicitly
3100b57cec5SDimitry Andric     /// preserved, if the analysis is known stateless, then it is preserved.
preservedWhenStateless()3110b57cec5SDimitry Andric     bool preservedWhenStateless() {
3120b57cec5SDimitry Andric       return !IsAbandoned;
3130b57cec5SDimitry Andric     }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric     /// Returns true if the checker's analysis was not abandoned and either
3160b57cec5SDimitry Andric     ///  - \p AnalysisSetT is explicitly preserved or
3170b57cec5SDimitry Andric     ///  - all analyses are preserved.
preservedSet()3180b57cec5SDimitry Andric     template <typename AnalysisSetT> bool preservedSet() {
3190b57cec5SDimitry Andric       AnalysisSetKey *SetID = AnalysisSetT::ID();
3200b57cec5SDimitry Andric       return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) ||
3210b57cec5SDimitry Andric                               PA.PreservedIDs.count(SetID));
3220b57cec5SDimitry Andric     }
3230b57cec5SDimitry Andric   };
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   /// Build a checker for this `PreservedAnalyses` and the specified analysis
3260b57cec5SDimitry Andric   /// type.
3270b57cec5SDimitry Andric   ///
3280b57cec5SDimitry Andric   /// You can use the returned object to query whether an analysis was
3290b57cec5SDimitry Andric   /// preserved. See the example in the comment on `PreservedAnalysis`.
getChecker()3300b57cec5SDimitry Andric   template <typename AnalysisT> PreservedAnalysisChecker getChecker() const {
3310b57cec5SDimitry Andric     return PreservedAnalysisChecker(*this, AnalysisT::ID());
3320b57cec5SDimitry Andric   }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   /// Build a checker for this `PreservedAnalyses` and the specified analysis
3350b57cec5SDimitry Andric   /// ID.
3360b57cec5SDimitry Andric   ///
3370b57cec5SDimitry Andric   /// You can use the returned object to query whether an analysis was
3380b57cec5SDimitry Andric   /// preserved. See the example in the comment on `PreservedAnalysis`.
getChecker(AnalysisKey * ID)3390b57cec5SDimitry Andric   PreservedAnalysisChecker getChecker(AnalysisKey *ID) const {
3400b57cec5SDimitry Andric     return PreservedAnalysisChecker(*this, ID);
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   /// Test whether all analyses are preserved (and none are abandoned).
3440b57cec5SDimitry Andric   ///
3450b57cec5SDimitry Andric   /// This is used primarily to optimize for the common case of a transformation
3460b57cec5SDimitry Andric   /// which makes no changes to the IR.
areAllPreserved()3470b57cec5SDimitry Andric   bool areAllPreserved() const {
3480b57cec5SDimitry Andric     return NotPreservedAnalysisIDs.empty() &&
3490b57cec5SDimitry Andric            PreservedIDs.count(&AllAnalysesKey);
3500b57cec5SDimitry Andric   }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   /// Directly test whether a set of analyses is preserved.
3530b57cec5SDimitry Andric   ///
3540b57cec5SDimitry Andric   /// This is only true when no analyses have been explicitly abandoned.
allAnalysesInSetPreserved()3550b57cec5SDimitry Andric   template <typename AnalysisSetT> bool allAnalysesInSetPreserved() const {
3560b57cec5SDimitry Andric     return allAnalysesInSetPreserved(AnalysisSetT::ID());
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   /// Directly test whether a set of analyses is preserved.
3600b57cec5SDimitry Andric   ///
3610b57cec5SDimitry Andric   /// This is only true when no analyses have been explicitly abandoned.
allAnalysesInSetPreserved(AnalysisSetKey * SetID)3620b57cec5SDimitry Andric   bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const {
3630b57cec5SDimitry Andric     return NotPreservedAnalysisIDs.empty() &&
3640b57cec5SDimitry Andric            (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID));
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric private:
3680b57cec5SDimitry Andric   /// A special key used to indicate all analyses.
3690b57cec5SDimitry Andric   static AnalysisSetKey AllAnalysesKey;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   /// The IDs of analyses and analysis sets that are preserved.
3720b57cec5SDimitry Andric   SmallPtrSet<void *, 2> PreservedIDs;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   /// The IDs of explicitly not-preserved analyses.
3750b57cec5SDimitry Andric   ///
3760b57cec5SDimitry Andric   /// If an analysis in this set is covered by a set in `PreservedIDs`, we
3770b57cec5SDimitry Andric   /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always
3780b57cec5SDimitry Andric   /// "wins" over analysis sets in `PreservedIDs`.
3790b57cec5SDimitry Andric   ///
3800b57cec5SDimitry Andric   /// Also, a given ID should never occur both here and in `PreservedIDs`.
3810b57cec5SDimitry Andric   SmallPtrSet<AnalysisKey *, 2> NotPreservedAnalysisIDs;
3820b57cec5SDimitry Andric };
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric // Forward declare the analysis manager template.
3850b57cec5SDimitry Andric template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric /// A CRTP mix-in to automatically provide informational APIs needed for
3880b57cec5SDimitry Andric /// passes.
3890b57cec5SDimitry Andric ///
3900b57cec5SDimitry Andric /// This provides some boilerplate for types that are passes.
3910b57cec5SDimitry Andric template <typename DerivedT> struct PassInfoMixin {
3920b57cec5SDimitry Andric   /// Gets the name of the pass we are mixed into.
namePassInfoMixin3930b57cec5SDimitry Andric   static StringRef name() {
3940b57cec5SDimitry Andric     static_assert(std::is_base_of<PassInfoMixin, DerivedT>::value,
3950b57cec5SDimitry Andric                   "Must pass the derived type as the template argument!");
3960b57cec5SDimitry Andric     StringRef Name = getTypeName<DerivedT>();
397349cc55cSDimitry Andric     Name.consume_front("llvm::");
3980b57cec5SDimitry Andric     return Name;
3990b57cec5SDimitry Andric   }
400349cc55cSDimitry Andric 
printPipelinePassInfoMixin401349cc55cSDimitry Andric   void printPipeline(raw_ostream &OS,
402349cc55cSDimitry Andric                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
403349cc55cSDimitry Andric     StringRef ClassName = DerivedT::name();
404349cc55cSDimitry Andric     auto PassName = MapClassName2PassName(ClassName);
405349cc55cSDimitry Andric     OS << PassName;
406349cc55cSDimitry Andric   }
4070b57cec5SDimitry Andric };
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric /// A CRTP mix-in that provides informational APIs needed for analysis passes.
4100b57cec5SDimitry Andric ///
4110b57cec5SDimitry Andric /// This provides some boilerplate for types that are analysis passes. It
4120b57cec5SDimitry Andric /// automatically mixes in \c PassInfoMixin.
4130b57cec5SDimitry Andric template <typename DerivedT>
4140b57cec5SDimitry Andric struct AnalysisInfoMixin : PassInfoMixin<DerivedT> {
4150b57cec5SDimitry Andric   /// Returns an opaque, unique ID for this analysis type.
4160b57cec5SDimitry Andric   ///
4170b57cec5SDimitry Andric   /// This ID is a pointer type that is guaranteed to be 8-byte aligned and thus
4180b57cec5SDimitry Andric   /// suitable for use in sets, maps, and other data structures that use the low
4190b57cec5SDimitry Andric   /// bits of pointers.
4200b57cec5SDimitry Andric   ///
4210b57cec5SDimitry Andric   /// Note that this requires the derived type provide a static \c AnalysisKey
4220b57cec5SDimitry Andric   /// member called \c Key.
4230b57cec5SDimitry Andric   ///
4240b57cec5SDimitry Andric   /// FIXME: The only reason the mixin type itself can't declare the Key value
4250b57cec5SDimitry Andric   /// is that some compilers cannot correctly unique a templated static variable
4260b57cec5SDimitry Andric   /// so it has the same addresses in each instantiation. The only currently
4270b57cec5SDimitry Andric   /// known platform with this limitation is Windows DLL builds, specifically
4280b57cec5SDimitry Andric   /// building each part of LLVM as a DLL. If we ever remove that build
4290b57cec5SDimitry Andric   /// configuration, this mixin can provide the static key as well.
IDAnalysisInfoMixin4300b57cec5SDimitry Andric   static AnalysisKey *ID() {
4310b57cec5SDimitry Andric     static_assert(std::is_base_of<AnalysisInfoMixin, DerivedT>::value,
4320b57cec5SDimitry Andric                   "Must pass the derived type as the template argument!");
4330b57cec5SDimitry Andric     return &DerivedT::Key;
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric };
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric namespace detail {
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric /// Actual unpacker of extra arguments in getAnalysisResult,
4400b57cec5SDimitry Andric /// passes only those tuple arguments that are mentioned in index_sequence.
4410b57cec5SDimitry Andric template <typename PassT, typename IRUnitT, typename AnalysisManagerT,
4420b57cec5SDimitry Andric           typename... ArgTs, size_t... Ns>
4430b57cec5SDimitry Andric typename PassT::Result
getAnalysisResultUnpackTuple(AnalysisManagerT & AM,IRUnitT & IR,std::tuple<ArgTs...> Args,std::index_sequence<Ns...>)4440b57cec5SDimitry Andric getAnalysisResultUnpackTuple(AnalysisManagerT &AM, IRUnitT &IR,
4450b57cec5SDimitry Andric                              std::tuple<ArgTs...> Args,
4468bcb0991SDimitry Andric                              std::index_sequence<Ns...>) {
4470b57cec5SDimitry Andric   (void)Args;
4480b57cec5SDimitry Andric   return AM.template getResult<PassT>(IR, std::get<Ns>(Args)...);
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric /// Helper for *partial* unpacking of extra arguments in getAnalysisResult.
4520b57cec5SDimitry Andric ///
4530b57cec5SDimitry Andric /// Arguments passed in tuple come from PassManager, so they might have extra
4540b57cec5SDimitry Andric /// arguments after those AnalysisManager's ExtraArgTs ones that we need to
4550b57cec5SDimitry Andric /// pass to getResult.
4560b57cec5SDimitry Andric template <typename PassT, typename IRUnitT, typename... AnalysisArgTs,
4570b57cec5SDimitry Andric           typename... MainArgTs>
4580b57cec5SDimitry Andric typename PassT::Result
getAnalysisResult(AnalysisManager<IRUnitT,AnalysisArgTs...> & AM,IRUnitT & IR,std::tuple<MainArgTs...> Args)4590b57cec5SDimitry Andric getAnalysisResult(AnalysisManager<IRUnitT, AnalysisArgTs...> &AM, IRUnitT &IR,
4600b57cec5SDimitry Andric                   std::tuple<MainArgTs...> Args) {
4610b57cec5SDimitry Andric   return (getAnalysisResultUnpackTuple<
4620b57cec5SDimitry Andric           PassT, IRUnitT>)(AM, IR, Args,
4638bcb0991SDimitry Andric                            std::index_sequence_for<AnalysisArgTs...>{});
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric } // namespace detail
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric // Forward declare the pass instrumentation analysis explicitly queried in
4690b57cec5SDimitry Andric // generic PassManager code.
4700b57cec5SDimitry Andric // FIXME: figure out a way to move PassInstrumentationAnalysis into its own
4710b57cec5SDimitry Andric // header.
4720b57cec5SDimitry Andric class PassInstrumentationAnalysis;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric /// Manages a sequence of passes over a particular unit of IR.
4750b57cec5SDimitry Andric ///
4760b57cec5SDimitry Andric /// A pass manager contains a sequence of passes to run over a particular unit
4770b57cec5SDimitry Andric /// of IR (e.g. Functions, Modules). It is itself a valid pass over that unit of
4780b57cec5SDimitry Andric /// IR, and when run over some given IR will run each of its contained passes in
4790b57cec5SDimitry Andric /// sequence. Pass managers are the primary and most basic building block of a
4800b57cec5SDimitry Andric /// pass pipeline.
4810b57cec5SDimitry Andric ///
4820b57cec5SDimitry Andric /// When you run a pass manager, you provide an \c AnalysisManager<IRUnitT>
4830b57cec5SDimitry Andric /// argument. The pass manager will propagate that analysis manager to each
4840b57cec5SDimitry Andric /// pass it runs, and will call the analysis manager's invalidation routine with
4850b57cec5SDimitry Andric /// the PreservedAnalyses of each pass it runs.
4860b57cec5SDimitry Andric template <typename IRUnitT,
4870b57cec5SDimitry Andric           typename AnalysisManagerT = AnalysisManager<IRUnitT>,
4880b57cec5SDimitry Andric           typename... ExtraArgTs>
4890b57cec5SDimitry Andric class PassManager : public PassInfoMixin<
4900b57cec5SDimitry Andric                         PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
4910b57cec5SDimitry Andric public:
4920b57cec5SDimitry Andric   /// Construct a pass manager.
4931fd87a68SDimitry Andric   explicit PassManager() = default;
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   // FIXME: These are equivalent to the default move constructor/move
4960b57cec5SDimitry Andric   // assignment. However, using = default triggers linker errors due to the
4970b57cec5SDimitry Andric   // explicit instantiations below. Find away to use the default and remove the
4980b57cec5SDimitry Andric   // duplicated code here.
PassManager(PassManager && Arg)499fe6060f1SDimitry Andric   PassManager(PassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   PassManager &operator=(PassManager &&RHS) {
5020b57cec5SDimitry Andric     Passes = std::move(RHS.Passes);
5030b57cec5SDimitry Andric     return *this;
5040b57cec5SDimitry Andric   }
5050b57cec5SDimitry Andric 
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)506349cc55cSDimitry Andric   void printPipeline(raw_ostream &OS,
507349cc55cSDimitry Andric                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
508349cc55cSDimitry Andric     for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
509349cc55cSDimitry Andric       auto *P = Passes[Idx].get();
510349cc55cSDimitry Andric       P->printPipeline(OS, MapClassName2PassName);
511349cc55cSDimitry Andric       if (Idx + 1 < Size)
51206c3fb27SDimitry Andric         OS << ',';
513349cc55cSDimitry Andric     }
514349cc55cSDimitry Andric   }
515349cc55cSDimitry Andric 
5160b57cec5SDimitry Andric   /// Run all of the passes in this manager over the given unit of IR.
5170b57cec5SDimitry Andric   /// ExtraArgs are passed to each pass.
run(IRUnitT & IR,AnalysisManagerT & AM,ExtraArgTs...ExtraArgs)5180b57cec5SDimitry Andric   PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
5190b57cec5SDimitry Andric                         ExtraArgTs... ExtraArgs) {
5200b57cec5SDimitry Andric     PreservedAnalyses PA = PreservedAnalyses::all();
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric     // Request PassInstrumentation from analysis manager, will use it to run
5230b57cec5SDimitry Andric     // instrumenting callbacks for the passes later.
5240b57cec5SDimitry Andric     // Here we use std::tuple wrapper over getResult which helps to extract
5250b57cec5SDimitry Andric     // AnalysisManager's arguments out of the whole ExtraArgs set.
5260b57cec5SDimitry Andric     PassInstrumentation PI =
5270b57cec5SDimitry Andric         detail::getAnalysisResult<PassInstrumentationAnalysis>(
5280b57cec5SDimitry Andric             AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...));
5290b57cec5SDimitry Andric 
5305f757f3fSDimitry Andric     // RemoveDIs: if requested, convert debug-info to DPValue representation
5315f757f3fSDimitry Andric     // for duration of these passes.
5325f757f3fSDimitry Andric     bool ShouldConvertDbgInfo = shouldConvertDbgInfo(IR);
5335f757f3fSDimitry Andric     if (ShouldConvertDbgInfo)
5345f757f3fSDimitry Andric       doConvertDbgInfoToNew(IR);
5355f757f3fSDimitry Andric 
536bdd1243dSDimitry Andric     for (auto &Pass : Passes) {
5370b57cec5SDimitry Andric       // Check the PassInstrumentation's BeforePass callbacks before running the
5380b57cec5SDimitry Andric       // pass, skip its execution completely if asked to (callback returns
5390b57cec5SDimitry Andric       // false).
540bdd1243dSDimitry Andric       if (!PI.runBeforePass<IRUnitT>(*Pass, IR))
5410b57cec5SDimitry Andric         continue;
5420b57cec5SDimitry Andric 
543bdd1243dSDimitry Andric       PreservedAnalyses PassPA = Pass->run(IR, AM, ExtraArgs...);
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric       // Update the analysis manager as each pass runs and potentially
5460b57cec5SDimitry Andric       // invalidates analyses.
5470b57cec5SDimitry Andric       AM.invalidate(IR, PassPA);
5480b57cec5SDimitry Andric 
54906c3fb27SDimitry Andric       // Call onto PassInstrumentation's AfterPass callbacks immediately after
55006c3fb27SDimitry Andric       // running the pass.
55106c3fb27SDimitry Andric       PI.runAfterPass<IRUnitT>(*Pass, IR, PassPA);
55206c3fb27SDimitry Andric 
5530b57cec5SDimitry Andric       // Finally, intersect the preserved analyses to compute the aggregate
5540b57cec5SDimitry Andric       // preserved set for this pass manager.
5550b57cec5SDimitry Andric       PA.intersect(std::move(PassPA));
5560b57cec5SDimitry Andric     }
5570b57cec5SDimitry Andric 
5585f757f3fSDimitry Andric     if (ShouldConvertDbgInfo)
5595f757f3fSDimitry Andric       doConvertDebugInfoToOld(IR);
5605f757f3fSDimitry Andric 
5610b57cec5SDimitry Andric     // Invalidation was handled after each pass in the above loop for the
5620b57cec5SDimitry Andric     // current unit of IR. Therefore, the remaining analysis results in the
5630b57cec5SDimitry Andric     // AnalysisManager are preserved. We mark this with a set so that we don't
5640b57cec5SDimitry Andric     // need to inspect each one individually.
5650b57cec5SDimitry Andric     PA.preserveSet<AllAnalysesOn<IRUnitT>>();
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric     return PA;
5680b57cec5SDimitry Andric   }
5690b57cec5SDimitry Andric 
570e8d8bef9SDimitry Andric   template <typename PassT>
571349cc55cSDimitry Andric   LLVM_ATTRIBUTE_MINSIZE
572e8d8bef9SDimitry Andric       std::enable_if_t<!std::is_same<PassT, PassManager>::value>
addPass(PassT && Pass)573fe6060f1SDimitry Andric       addPass(PassT &&Pass) {
5740b57cec5SDimitry Andric     using PassModelT =
5750b57cec5SDimitry Andric         detail::PassModel<IRUnitT, PassT, PreservedAnalyses, AnalysisManagerT,
5760b57cec5SDimitry Andric                           ExtraArgTs...>;
577349cc55cSDimitry Andric     // Do not use make_unique or emplace_back, they cause too many template
578349cc55cSDimitry Andric     // instantiations, causing terrible compile times.
579349cc55cSDimitry Andric     Passes.push_back(std::unique_ptr<PassConceptT>(
580349cc55cSDimitry Andric         new PassModelT(std::forward<PassT>(Pass))));
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric 
583e8d8bef9SDimitry Andric   /// When adding a pass manager pass that has the same type as this pass
584e8d8bef9SDimitry Andric   /// manager, simply move the passes over. This is because we don't have use
585e8d8bef9SDimitry Andric   /// cases rely on executing nested pass managers. Doing this could reduce
586e8d8bef9SDimitry Andric   /// implementation complexity and avoid potential invalidation issues that may
587e8d8bef9SDimitry Andric   /// happen with nested pass managers of the same type.
588e8d8bef9SDimitry Andric   template <typename PassT>
589349cc55cSDimitry Andric   LLVM_ATTRIBUTE_MINSIZE
590e8d8bef9SDimitry Andric       std::enable_if_t<std::is_same<PassT, PassManager>::value>
addPass(PassT && Pass)591e8d8bef9SDimitry Andric       addPass(PassT &&Pass) {
592e8d8bef9SDimitry Andric     for (auto &P : Pass.Passes)
593349cc55cSDimitry Andric       Passes.push_back(std::move(P));
594e8d8bef9SDimitry Andric   }
595e8d8bef9SDimitry Andric 
596e8d8bef9SDimitry Andric   /// Returns if the pass manager contains any passes.
isEmpty()597e8d8bef9SDimitry Andric   bool isEmpty() const { return Passes.empty(); }
598e8d8bef9SDimitry Andric 
isRequired()599e8d8bef9SDimitry Andric   static bool isRequired() { return true; }
600e8d8bef9SDimitry Andric 
601e8d8bef9SDimitry Andric protected:
6020b57cec5SDimitry Andric   using PassConceptT =
6030b57cec5SDimitry Andric       detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   std::vector<std::unique_ptr<PassConceptT>> Passes;
6060b57cec5SDimitry Andric };
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric extern template class PassManager<Module>;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric /// Convenience typedef for a pass manager over modules.
6110b57cec5SDimitry Andric using ModulePassManager = PassManager<Module>;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric extern template class PassManager<Function>;
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric /// Convenience typedef for a pass manager over functions.
6160b57cec5SDimitry Andric using FunctionPassManager = PassManager<Function>;
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric /// Pseudo-analysis pass that exposes the \c PassInstrumentation to pass
6190b57cec5SDimitry Andric /// managers. Goes before AnalysisManager definition to provide its
6200b57cec5SDimitry Andric /// internals (e.g PassInstrumentationAnalysis::ID) for use there if needed.
6210b57cec5SDimitry Andric /// FIXME: figure out a way to move PassInstrumentationAnalysis into its own
6220b57cec5SDimitry Andric /// header.
6230b57cec5SDimitry Andric class PassInstrumentationAnalysis
6240b57cec5SDimitry Andric     : public AnalysisInfoMixin<PassInstrumentationAnalysis> {
6250b57cec5SDimitry Andric   friend AnalysisInfoMixin<PassInstrumentationAnalysis>;
6260b57cec5SDimitry Andric   static AnalysisKey Key;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   PassInstrumentationCallbacks *Callbacks;
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric public:
6310b57cec5SDimitry Andric   /// PassInstrumentationCallbacks object is shared, owned by something else,
6320b57cec5SDimitry Andric   /// not this analysis.
6330b57cec5SDimitry Andric   PassInstrumentationAnalysis(PassInstrumentationCallbacks *Callbacks = nullptr)
Callbacks(Callbacks)6340b57cec5SDimitry Andric       : Callbacks(Callbacks) {}
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   using Result = PassInstrumentation;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
run(IRUnitT &,AnalysisManagerT &,ExtraArgTs &&...)6390b57cec5SDimitry Andric   Result run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) {
6400b57cec5SDimitry Andric     return PassInstrumentation(Callbacks);
6410b57cec5SDimitry Andric   }
6420b57cec5SDimitry Andric };
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric /// A container for analyses that lazily runs them and caches their
6450b57cec5SDimitry Andric /// results.
6460b57cec5SDimitry Andric ///
6470b57cec5SDimitry Andric /// This class can manage analyses for any IR unit where the address of the IR
6480b57cec5SDimitry Andric /// unit sufficies as its identity.
6490b57cec5SDimitry Andric template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
6500b57cec5SDimitry Andric public:
6510b57cec5SDimitry Andric   class Invalidator;
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric private:
6540b57cec5SDimitry Andric   // Now that we've defined our invalidator, we can define the concept types.
6550b57cec5SDimitry Andric   using ResultConceptT =
6560b57cec5SDimitry Andric       detail::AnalysisResultConcept<IRUnitT, PreservedAnalyses, Invalidator>;
6570b57cec5SDimitry Andric   using PassConceptT =
6580b57cec5SDimitry Andric       detail::AnalysisPassConcept<IRUnitT, PreservedAnalyses, Invalidator,
6590b57cec5SDimitry Andric                                   ExtraArgTs...>;
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   /// List of analysis pass IDs and associated concept pointers.
6620b57cec5SDimitry Andric   ///
6630b57cec5SDimitry Andric   /// Requires iterators to be valid across appending new entries and arbitrary
6640b57cec5SDimitry Andric   /// erases. Provides the analysis ID to enable finding iterators to a given
6650b57cec5SDimitry Andric   /// entry in maps below, and provides the storage for the actual result
6660b57cec5SDimitry Andric   /// concept.
6670b57cec5SDimitry Andric   using AnalysisResultListT =
6680b57cec5SDimitry Andric       std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>>;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   /// Map type from IRUnitT pointer to our custom list type.
6710b57cec5SDimitry Andric   using AnalysisResultListMapT = DenseMap<IRUnitT *, AnalysisResultListT>;
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   /// Map type from a pair of analysis ID and IRUnitT pointer to an
6740b57cec5SDimitry Andric   /// iterator into a particular result list (which is where the actual analysis
6750b57cec5SDimitry Andric   /// result is stored).
6760b57cec5SDimitry Andric   using AnalysisResultMapT =
6770b57cec5SDimitry Andric       DenseMap<std::pair<AnalysisKey *, IRUnitT *>,
6780b57cec5SDimitry Andric                typename AnalysisResultListT::iterator>;
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric public:
6810b57cec5SDimitry Andric   /// API to communicate dependencies between analyses during invalidation.
6820b57cec5SDimitry Andric   ///
6830b57cec5SDimitry Andric   /// When an analysis result embeds handles to other analysis results, it
6840b57cec5SDimitry Andric   /// needs to be invalidated both when its own information isn't preserved and
6850b57cec5SDimitry Andric   /// when any of its embedded analysis results end up invalidated. We pass an
6860b57cec5SDimitry Andric   /// \c Invalidator object as an argument to \c invalidate() in order to let
6870b57cec5SDimitry Andric   /// the analysis results themselves define the dependency graph on the fly.
688e8d8bef9SDimitry Andric   /// This lets us avoid building an explicit representation of the
6890b57cec5SDimitry Andric   /// dependencies between analysis results.
6900b57cec5SDimitry Andric   class Invalidator {
6910b57cec5SDimitry Andric   public:
6920b57cec5SDimitry Andric     /// Trigger the invalidation of some other analysis pass if not already
6930b57cec5SDimitry Andric     /// handled and return whether it was in fact invalidated.
6940b57cec5SDimitry Andric     ///
6950b57cec5SDimitry Andric     /// This is expected to be called from within a given analysis result's \c
6960b57cec5SDimitry Andric     /// invalidate method to trigger a depth-first walk of all inter-analysis
6970b57cec5SDimitry Andric     /// dependencies. The same \p IR unit and \p PA passed to that result's \c
6980b57cec5SDimitry Andric     /// invalidate method should in turn be provided to this routine.
6990b57cec5SDimitry Andric     ///
7000b57cec5SDimitry Andric     /// The first time this is called for a given analysis pass, it will call
7010b57cec5SDimitry Andric     /// the corresponding result's \c invalidate method.  Subsequent calls will
7020b57cec5SDimitry Andric     /// use a cache of the results of that initial call.  It is an error to form
7030b57cec5SDimitry Andric     /// cyclic dependencies between analysis results.
7040b57cec5SDimitry Andric     ///
7050b57cec5SDimitry Andric     /// This returns true if the given analysis's result is invalid. Any
7060b57cec5SDimitry Andric     /// dependecies on it will become invalid as a result.
7070b57cec5SDimitry Andric     template <typename PassT>
invalidate(IRUnitT & IR,const PreservedAnalyses & PA)7080b57cec5SDimitry Andric     bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) {
7090b57cec5SDimitry Andric       using ResultModelT =
7100b57cec5SDimitry Andric           detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
7110b57cec5SDimitry Andric                                       PreservedAnalyses, Invalidator>;
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric       return invalidateImpl<ResultModelT>(PassT::ID(), IR, PA);
7140b57cec5SDimitry Andric     }
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric     /// A type-erased variant of the above invalidate method with the same core
7170b57cec5SDimitry Andric     /// API other than passing an analysis ID rather than an analysis type
7180b57cec5SDimitry Andric     /// parameter.
7190b57cec5SDimitry Andric     ///
7200b57cec5SDimitry Andric     /// This is sadly less efficient than the above routine, which leverages
7210b57cec5SDimitry Andric     /// the type parameter to avoid the type erasure overhead.
invalidate(AnalysisKey * ID,IRUnitT & IR,const PreservedAnalyses & PA)7220b57cec5SDimitry Andric     bool invalidate(AnalysisKey *ID, IRUnitT &IR, const PreservedAnalyses &PA) {
7230b57cec5SDimitry Andric       return invalidateImpl<>(ID, IR, PA);
7240b57cec5SDimitry Andric     }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   private:
7270b57cec5SDimitry Andric     friend class AnalysisManager;
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric     template <typename ResultT = ResultConceptT>
invalidateImpl(AnalysisKey * ID,IRUnitT & IR,const PreservedAnalyses & PA)7300b57cec5SDimitry Andric     bool invalidateImpl(AnalysisKey *ID, IRUnitT &IR,
7310b57cec5SDimitry Andric                         const PreservedAnalyses &PA) {
7320b57cec5SDimitry Andric       // If we've already visited this pass, return true if it was invalidated
7330b57cec5SDimitry Andric       // and false otherwise.
7340b57cec5SDimitry Andric       auto IMapI = IsResultInvalidated.find(ID);
7350b57cec5SDimitry Andric       if (IMapI != IsResultInvalidated.end())
7360b57cec5SDimitry Andric         return IMapI->second;
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric       // Otherwise look up the result object.
7390b57cec5SDimitry Andric       auto RI = Results.find({ID, &IR});
7400b57cec5SDimitry Andric       assert(RI != Results.end() &&
7410b57cec5SDimitry Andric              "Trying to invalidate a dependent result that isn't in the "
7420b57cec5SDimitry Andric              "manager's cache is always an error, likely due to a stale result "
7430b57cec5SDimitry Andric              "handle!");
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric       auto &Result = static_cast<ResultT &>(*RI->second->second);
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric       // Insert into the map whether the result should be invalidated and return
7480b57cec5SDimitry Andric       // that. Note that we cannot reuse IMapI and must do a fresh insert here,
7490b57cec5SDimitry Andric       // as calling invalidate could (recursively) insert things into the map,
7500b57cec5SDimitry Andric       // making any iterator or reference invalid.
7510b57cec5SDimitry Andric       bool Inserted;
7520b57cec5SDimitry Andric       std::tie(IMapI, Inserted) =
7530b57cec5SDimitry Andric           IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, *this)});
7540b57cec5SDimitry Andric       (void)Inserted;
7550b57cec5SDimitry Andric       assert(Inserted && "Should not have already inserted this ID, likely "
7560b57cec5SDimitry Andric                          "indicates a dependency cycle!");
7570b57cec5SDimitry Andric       return IMapI->second;
7580b57cec5SDimitry Andric     }
7590b57cec5SDimitry Andric 
Invalidator(SmallDenseMap<AnalysisKey *,bool,8> & IsResultInvalidated,const AnalysisResultMapT & Results)7600b57cec5SDimitry Andric     Invalidator(SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated,
7610b57cec5SDimitry Andric                 const AnalysisResultMapT &Results)
7620b57cec5SDimitry Andric         : IsResultInvalidated(IsResultInvalidated), Results(Results) {}
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric     SmallDenseMap<AnalysisKey *, bool, 8> &IsResultInvalidated;
7650b57cec5SDimitry Andric     const AnalysisResultMapT &Results;
7660b57cec5SDimitry Andric   };
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   /// Construct an empty analysis manager.
769fe6060f1SDimitry Andric   AnalysisManager();
7705ffd83dbSDimitry Andric   AnalysisManager(AnalysisManager &&);
7715ffd83dbSDimitry Andric   AnalysisManager &operator=(AnalysisManager &&);
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   /// Returns true if the analysis manager has an empty results cache.
empty()7740b57cec5SDimitry Andric   bool empty() const {
7750b57cec5SDimitry Andric     assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
7760b57cec5SDimitry Andric            "The storage and index of analysis results disagree on how many "
7770b57cec5SDimitry Andric            "there are!");
7780b57cec5SDimitry Andric     return AnalysisResults.empty();
7790b57cec5SDimitry Andric   }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric   /// Clear any cached analysis results for a single unit of IR.
7820b57cec5SDimitry Andric   ///
7830b57cec5SDimitry Andric   /// This doesn't invalidate, but instead simply deletes, the relevant results.
7840b57cec5SDimitry Andric   /// It is useful when the IR is being removed and we want to clear out all the
7850b57cec5SDimitry Andric   /// memory pinned for it.
7865ffd83dbSDimitry Andric   void clear(IRUnitT &IR, llvm::StringRef Name);
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   /// Clear all analysis results cached by this AnalysisManager.
7890b57cec5SDimitry Andric   ///
7900b57cec5SDimitry Andric   /// Like \c clear(IRUnitT&), this doesn't invalidate the results; it simply
7910b57cec5SDimitry Andric   /// deletes them.  This lets you clean up the AnalysisManager when the set of
7920b57cec5SDimitry Andric   /// IR units itself has potentially changed, and thus we can't even look up a
7930b57cec5SDimitry Andric   /// a result and invalidate/clear it directly.
clear()7940b57cec5SDimitry Andric   void clear() {
7950b57cec5SDimitry Andric     AnalysisResults.clear();
7960b57cec5SDimitry Andric     AnalysisResultLists.clear();
7970b57cec5SDimitry Andric   }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   /// Get the result of an analysis pass for a given IR unit.
8000b57cec5SDimitry Andric   ///
8010b57cec5SDimitry Andric   /// Runs the analysis if a cached result is not available.
8020b57cec5SDimitry Andric   template <typename PassT>
getResult(IRUnitT & IR,ExtraArgTs...ExtraArgs)8030b57cec5SDimitry Andric   typename PassT::Result &getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs) {
8040b57cec5SDimitry Andric     assert(AnalysisPasses.count(PassT::ID()) &&
8050b57cec5SDimitry Andric            "This analysis pass was not registered prior to being queried");
8060b57cec5SDimitry Andric     ResultConceptT &ResultConcept =
8070b57cec5SDimitry Andric         getResultImpl(PassT::ID(), IR, ExtraArgs...);
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric     using ResultModelT =
8100b57cec5SDimitry Andric         detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
8110b57cec5SDimitry Andric                                     PreservedAnalyses, Invalidator>;
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric     return static_cast<ResultModelT &>(ResultConcept).Result;
8140b57cec5SDimitry Andric   }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric   /// Get the cached result of an analysis pass for a given IR unit.
8170b57cec5SDimitry Andric   ///
8180b57cec5SDimitry Andric   /// This method never runs the analysis.
8190b57cec5SDimitry Andric   ///
8200b57cec5SDimitry Andric   /// \returns null if there is no cached result.
8210b57cec5SDimitry Andric   template <typename PassT>
getCachedResult(IRUnitT & IR)8220b57cec5SDimitry Andric   typename PassT::Result *getCachedResult(IRUnitT &IR) const {
8230b57cec5SDimitry Andric     assert(AnalysisPasses.count(PassT::ID()) &&
8240b57cec5SDimitry Andric            "This analysis pass was not registered prior to being queried");
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric     ResultConceptT *ResultConcept = getCachedResultImpl(PassT::ID(), IR);
8270b57cec5SDimitry Andric     if (!ResultConcept)
8280b57cec5SDimitry Andric       return nullptr;
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric     using ResultModelT =
8310b57cec5SDimitry Andric         detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
8320b57cec5SDimitry Andric                                     PreservedAnalyses, Invalidator>;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric     return &static_cast<ResultModelT *>(ResultConcept)->Result;
8350b57cec5SDimitry Andric   }
8360b57cec5SDimitry Andric 
8375ffd83dbSDimitry Andric   /// Verify that the given Result cannot be invalidated, assert otherwise.
8385ffd83dbSDimitry Andric   template <typename PassT>
verifyNotInvalidated(IRUnitT & IR,typename PassT::Result * Result)8395ffd83dbSDimitry Andric   void verifyNotInvalidated(IRUnitT &IR, typename PassT::Result *Result) const {
8405ffd83dbSDimitry Andric     PreservedAnalyses PA = PreservedAnalyses::none();
8415ffd83dbSDimitry Andric     SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated;
8425ffd83dbSDimitry Andric     Invalidator Inv(IsResultInvalidated, AnalysisResults);
8435ffd83dbSDimitry Andric     assert(!Result->invalidate(IR, PA, Inv) &&
8445ffd83dbSDimitry Andric            "Cached result cannot be invalidated");
8455ffd83dbSDimitry Andric   }
8465ffd83dbSDimitry Andric 
8470b57cec5SDimitry Andric   /// Register an analysis pass with the manager.
8480b57cec5SDimitry Andric   ///
8490b57cec5SDimitry Andric   /// The parameter is a callable whose result is an analysis pass. This allows
8500b57cec5SDimitry Andric   /// passing in a lambda to construct the analysis.
8510b57cec5SDimitry Andric   ///
8520b57cec5SDimitry Andric   /// The analysis type to register is the type returned by calling the \c
8530b57cec5SDimitry Andric   /// PassBuilder argument. If that type has already been registered, then the
8540b57cec5SDimitry Andric   /// argument will not be called and this function will return false.
8550b57cec5SDimitry Andric   /// Otherwise, we register the analysis returned by calling \c PassBuilder(),
8560b57cec5SDimitry Andric   /// and this function returns true.
8570b57cec5SDimitry Andric   ///
8580b57cec5SDimitry Andric   /// (Note: Although the return value of this function indicates whether or not
8590b57cec5SDimitry Andric   /// an analysis was previously registered, there intentionally isn't a way to
8600b57cec5SDimitry Andric   /// query this directly.  Instead, you should just register all the analyses
8610b57cec5SDimitry Andric   /// you might want and let this class run them lazily.  This idiom lets us
8620b57cec5SDimitry Andric   /// minimize the number of times we have to look up analyses in our
8630b57cec5SDimitry Andric   /// hashtable.)
8640b57cec5SDimitry Andric   template <typename PassBuilderT>
registerPass(PassBuilderT && PassBuilder)8650b57cec5SDimitry Andric   bool registerPass(PassBuilderT &&PassBuilder) {
8660b57cec5SDimitry Andric     using PassT = decltype(PassBuilder());
8670b57cec5SDimitry Andric     using PassModelT =
8680b57cec5SDimitry Andric         detail::AnalysisPassModel<IRUnitT, PassT, PreservedAnalyses,
8690b57cec5SDimitry Andric                                   Invalidator, ExtraArgTs...>;
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric     auto &PassPtr = AnalysisPasses[PassT::ID()];
8720b57cec5SDimitry Andric     if (PassPtr)
8730b57cec5SDimitry Andric       // Already registered this pass type!
8740b57cec5SDimitry Andric       return false;
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric     // Construct a new model around the instance returned by the builder.
8770b57cec5SDimitry Andric     PassPtr.reset(new PassModelT(PassBuilder()));
8780b57cec5SDimitry Andric     return true;
8790b57cec5SDimitry Andric   }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric   /// Invalidate cached analyses for an IR unit.
8820b57cec5SDimitry Andric   ///
8830b57cec5SDimitry Andric   /// Walk through all of the analyses pertaining to this unit of IR and
8840b57cec5SDimitry Andric   /// invalidate them, unless they are preserved by the PreservedAnalyses set.
8855ffd83dbSDimitry Andric   void invalidate(IRUnitT &IR, const PreservedAnalyses &PA);
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric private:
8880b57cec5SDimitry Andric   /// Look up a registered analysis pass.
lookUpPass(AnalysisKey * ID)8890b57cec5SDimitry Andric   PassConceptT &lookUpPass(AnalysisKey *ID) {
8900b57cec5SDimitry Andric     typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(ID);
8910b57cec5SDimitry Andric     assert(PI != AnalysisPasses.end() &&
8920b57cec5SDimitry Andric            "Analysis passes must be registered prior to being queried!");
8930b57cec5SDimitry Andric     return *PI->second;
8940b57cec5SDimitry Andric   }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   /// Look up a registered analysis pass.
lookUpPass(AnalysisKey * ID)8970b57cec5SDimitry Andric   const PassConceptT &lookUpPass(AnalysisKey *ID) const {
8980b57cec5SDimitry Andric     typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(ID);
8990b57cec5SDimitry Andric     assert(PI != AnalysisPasses.end() &&
9000b57cec5SDimitry Andric            "Analysis passes must be registered prior to being queried!");
9010b57cec5SDimitry Andric     return *PI->second;
9020b57cec5SDimitry Andric   }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   /// Get an analysis result, running the pass if necessary.
9050b57cec5SDimitry Andric   ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &IR,
9065ffd83dbSDimitry Andric                                 ExtraArgTs... ExtraArgs);
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric   /// Get a cached analysis result or return null.
getCachedResultImpl(AnalysisKey * ID,IRUnitT & IR)9090b57cec5SDimitry Andric   ResultConceptT *getCachedResultImpl(AnalysisKey *ID, IRUnitT &IR) const {
9100b57cec5SDimitry Andric     typename AnalysisResultMapT::const_iterator RI =
9110b57cec5SDimitry Andric         AnalysisResults.find({ID, &IR});
9120b57cec5SDimitry Andric     return RI == AnalysisResults.end() ? nullptr : &*RI->second->second;
9130b57cec5SDimitry Andric   }
9140b57cec5SDimitry Andric 
915e8d8bef9SDimitry Andric   /// Map type from analysis pass ID to pass concept pointer.
9160b57cec5SDimitry Andric   using AnalysisPassMapT =
9170b57cec5SDimitry Andric       DenseMap<AnalysisKey *, std::unique_ptr<PassConceptT>>;
9180b57cec5SDimitry Andric 
919e8d8bef9SDimitry Andric   /// Collection of analysis passes, indexed by ID.
9200b57cec5SDimitry Andric   AnalysisPassMapT AnalysisPasses;
9210b57cec5SDimitry Andric 
922e8d8bef9SDimitry Andric   /// Map from IR unit to a list of analysis results.
9230b57cec5SDimitry Andric   ///
924e8d8bef9SDimitry Andric   /// Provides linear time removal of all analysis results for a IR unit and
9250b57cec5SDimitry Andric   /// the ultimate storage for a particular cached analysis result.
9260b57cec5SDimitry Andric   AnalysisResultListMapT AnalysisResultLists;
9270b57cec5SDimitry Andric 
928e8d8bef9SDimitry Andric   /// Map from an analysis ID and IR unit to a particular cached
9290b57cec5SDimitry Andric   /// analysis result.
9300b57cec5SDimitry Andric   AnalysisResultMapT AnalysisResults;
9310b57cec5SDimitry Andric };
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric extern template class AnalysisManager<Module>;
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric /// Convenience typedef for the Module analysis manager.
9360b57cec5SDimitry Andric using ModuleAnalysisManager = AnalysisManager<Module>;
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric extern template class AnalysisManager<Function>;
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric /// Convenience typedef for the Function analysis manager.
9410b57cec5SDimitry Andric using FunctionAnalysisManager = AnalysisManager<Function>;
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric /// An analysis over an "outer" IR unit that provides access to an
9440b57cec5SDimitry Andric /// analysis manager over an "inner" IR unit.  The inner unit must be contained
9450b57cec5SDimitry Andric /// in the outer unit.
9460b57cec5SDimitry Andric ///
9470b57cec5SDimitry Andric /// For example, InnerAnalysisManagerProxy<FunctionAnalysisManager, Module> is
9480b57cec5SDimitry Andric /// an analysis over Modules (the "outer" unit) that provides access to a
9490b57cec5SDimitry Andric /// Function analysis manager.  The FunctionAnalysisManager is the "inner"
9500b57cec5SDimitry Andric /// manager being proxied, and Functions are the "inner" unit.  The inner/outer
9510b57cec5SDimitry Andric /// relationship is valid because each Function is contained in one Module.
9520b57cec5SDimitry Andric ///
9530b57cec5SDimitry Andric /// If you're (transitively) within a pass manager for an IR unit U that
9540b57cec5SDimitry Andric /// contains IR unit V, you should never use an analysis manager over V, except
9550b57cec5SDimitry Andric /// via one of these proxies.
9560b57cec5SDimitry Andric ///
9570b57cec5SDimitry Andric /// Note that the proxy's result is a move-only RAII object.  The validity of
9580b57cec5SDimitry Andric /// the analyses in the inner analysis manager is tied to its lifetime.
9590b57cec5SDimitry Andric template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
9600b57cec5SDimitry Andric class InnerAnalysisManagerProxy
9610b57cec5SDimitry Andric     : public AnalysisInfoMixin<
9620b57cec5SDimitry Andric           InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>> {
9630b57cec5SDimitry Andric public:
9640b57cec5SDimitry Andric   class Result {
9650b57cec5SDimitry Andric   public:
Result(AnalysisManagerT & InnerAM)9660b57cec5SDimitry Andric     explicit Result(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {}
9670b57cec5SDimitry Andric 
Result(Result && Arg)9680b57cec5SDimitry Andric     Result(Result &&Arg) : InnerAM(std::move(Arg.InnerAM)) {
9690b57cec5SDimitry Andric       // We have to null out the analysis manager in the moved-from state
9700b57cec5SDimitry Andric       // because we are taking ownership of the responsibilty to clear the
9710b57cec5SDimitry Andric       // analysis state.
9720b57cec5SDimitry Andric       Arg.InnerAM = nullptr;
9730b57cec5SDimitry Andric     }
9740b57cec5SDimitry Andric 
~Result()9750b57cec5SDimitry Andric     ~Result() {
9760b57cec5SDimitry Andric       // InnerAM is cleared in a moved from state where there is nothing to do.
9770b57cec5SDimitry Andric       if (!InnerAM)
9780b57cec5SDimitry Andric         return;
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric       // Clear out the analysis manager if we're being destroyed -- it means we
9810b57cec5SDimitry Andric       // didn't even see an invalidate call when we got invalidated.
9820b57cec5SDimitry Andric       InnerAM->clear();
9830b57cec5SDimitry Andric     }
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric     Result &operator=(Result &&RHS) {
9860b57cec5SDimitry Andric       InnerAM = RHS.InnerAM;
9870b57cec5SDimitry Andric       // We have to null out the analysis manager in the moved-from state
9880b57cec5SDimitry Andric       // because we are taking ownership of the responsibilty to clear the
9890b57cec5SDimitry Andric       // analysis state.
9900b57cec5SDimitry Andric       RHS.InnerAM = nullptr;
9910b57cec5SDimitry Andric       return *this;
9920b57cec5SDimitry Andric     }
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric     /// Accessor for the analysis manager.
getManager()9950b57cec5SDimitry Andric     AnalysisManagerT &getManager() { return *InnerAM; }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric     /// Handler for invalidation of the outer IR unit, \c IRUnitT.
9980b57cec5SDimitry Andric     ///
9990b57cec5SDimitry Andric     /// If the proxy analysis itself is not preserved, we assume that the set of
10000b57cec5SDimitry Andric     /// inner IR objects contained in IRUnit may have changed.  In this case,
10010b57cec5SDimitry Andric     /// we have to call \c clear() on the inner analysis manager, as it may now
10020b57cec5SDimitry Andric     /// have stale pointers to its inner IR objects.
10030b57cec5SDimitry Andric     ///
10040b57cec5SDimitry Andric     /// Regardless of whether the proxy analysis is marked as preserved, all of
10050b57cec5SDimitry Andric     /// the analyses in the inner analysis manager are potentially invalidated
10060b57cec5SDimitry Andric     /// based on the set of preserved analyses.
10070b57cec5SDimitry Andric     bool invalidate(
10080b57cec5SDimitry Andric         IRUnitT &IR, const PreservedAnalyses &PA,
10090b57cec5SDimitry Andric         typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &Inv);
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric   private:
10120b57cec5SDimitry Andric     AnalysisManagerT *InnerAM;
10130b57cec5SDimitry Andric   };
10140b57cec5SDimitry Andric 
InnerAnalysisManagerProxy(AnalysisManagerT & InnerAM)10150b57cec5SDimitry Andric   explicit InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM)
10160b57cec5SDimitry Andric       : InnerAM(&InnerAM) {}
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   /// Run the analysis pass and create our proxy result object.
10190b57cec5SDimitry Andric   ///
10200b57cec5SDimitry Andric   /// This doesn't do any interesting work; it is primarily used to insert our
10210b57cec5SDimitry Andric   /// proxy result object into the outer analysis cache so that we can proxy
10220b57cec5SDimitry Andric   /// invalidation to the inner analysis manager.
run(IRUnitT & IR,AnalysisManager<IRUnitT,ExtraArgTs...> & AM,ExtraArgTs...)10230b57cec5SDimitry Andric   Result run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
10240b57cec5SDimitry Andric              ExtraArgTs...) {
10250b57cec5SDimitry Andric     return Result(*InnerAM);
10260b57cec5SDimitry Andric   }
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric private:
10290b57cec5SDimitry Andric   friend AnalysisInfoMixin<
10300b57cec5SDimitry Andric       InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>>;
10310b57cec5SDimitry Andric 
10320b57cec5SDimitry Andric   static AnalysisKey Key;
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   AnalysisManagerT *InnerAM;
10350b57cec5SDimitry Andric };
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
10380b57cec5SDimitry Andric AnalysisKey
10390b57cec5SDimitry Andric     InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::Key;
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric /// Provide the \c FunctionAnalysisManager to \c Module proxy.
10420b57cec5SDimitry Andric using FunctionAnalysisManagerModuleProxy =
10430b57cec5SDimitry Andric     InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric /// Specialization of the invalidate method for the \c
10460b57cec5SDimitry Andric /// FunctionAnalysisManagerModuleProxy's result.
10470b57cec5SDimitry Andric template <>
10480b57cec5SDimitry Andric bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
10490b57cec5SDimitry Andric     Module &M, const PreservedAnalyses &PA,
10500b57cec5SDimitry Andric     ModuleAnalysisManager::Invalidator &Inv);
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric // Ensure the \c FunctionAnalysisManagerModuleProxy is provided as an extern
10530b57cec5SDimitry Andric // template.
10540b57cec5SDimitry Andric extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
10550b57cec5SDimitry Andric                                                 Module>;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric /// An analysis over an "inner" IR unit that provides access to an
10580b57cec5SDimitry Andric /// analysis manager over a "outer" IR unit.  The inner unit must be contained
10590b57cec5SDimitry Andric /// in the outer unit.
10600b57cec5SDimitry Andric ///
10610b57cec5SDimitry Andric /// For example OuterAnalysisManagerProxy<ModuleAnalysisManager, Function> is an
10620b57cec5SDimitry Andric /// analysis over Functions (the "inner" unit) which provides access to a Module
10630b57cec5SDimitry Andric /// analysis manager.  The ModuleAnalysisManager is the "outer" manager being
10640b57cec5SDimitry Andric /// proxied, and Modules are the "outer" IR unit.  The inner/outer relationship
10650b57cec5SDimitry Andric /// is valid because each Function is contained in one Module.
10660b57cec5SDimitry Andric ///
10670b57cec5SDimitry Andric /// This proxy only exposes the const interface of the outer analysis manager,
10680b57cec5SDimitry Andric /// to indicate that you cannot cause an outer analysis to run from within an
1069e8d8bef9SDimitry Andric /// inner pass.  Instead, you must rely on the \c getCachedResult API.  This is
1070e8d8bef9SDimitry Andric /// due to keeping potential future concurrency in mind. To give an example,
1071e8d8bef9SDimitry Andric /// running a module analysis before any function passes may give a different
1072e8d8bef9SDimitry Andric /// result than running it in a function pass. Both may be valid, but it would
1073e8d8bef9SDimitry Andric /// produce non-deterministic results. GlobalsAA is a good analysis example,
1074e8d8bef9SDimitry Andric /// because the cached information has the mod/ref info for all memory for each
1075e8d8bef9SDimitry Andric /// function at the time the analysis was computed. The information is still
1076e8d8bef9SDimitry Andric /// valid after a function transformation, but it may be *different* if
1077e8d8bef9SDimitry Andric /// recomputed after that transform. GlobalsAA is never invalidated.
1078e8d8bef9SDimitry Andric 
10790b57cec5SDimitry Andric ///
10800b57cec5SDimitry Andric /// This proxy doesn't manage invalidation in any way -- that is handled by the
10810b57cec5SDimitry Andric /// recursive return path of each layer of the pass manager.  A consequence of
10820b57cec5SDimitry Andric /// this is the outer analyses may be stale.  We invalidate the outer analyses
10830b57cec5SDimitry Andric /// only when we're done running passes over the inner IR units.
10840b57cec5SDimitry Andric template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
10850b57cec5SDimitry Andric class OuterAnalysisManagerProxy
10860b57cec5SDimitry Andric     : public AnalysisInfoMixin<
10870b57cec5SDimitry Andric           OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> {
10880b57cec5SDimitry Andric public:
10890b57cec5SDimitry Andric   /// Result proxy object for \c OuterAnalysisManagerProxy.
10900b57cec5SDimitry Andric   class Result {
10910b57cec5SDimitry Andric   public:
Result(const AnalysisManagerT & OuterAM)1092480093f4SDimitry Andric     explicit Result(const AnalysisManagerT &OuterAM) : OuterAM(&OuterAM) {}
10930b57cec5SDimitry Andric 
10945ffd83dbSDimitry Andric     /// Get a cached analysis. If the analysis can be invalidated, this will
10955ffd83dbSDimitry Andric     /// assert.
10965ffd83dbSDimitry Andric     template <typename PassT, typename IRUnitTParam>
getCachedResult(IRUnitTParam & IR)10975ffd83dbSDimitry Andric     typename PassT::Result *getCachedResult(IRUnitTParam &IR) const {
10985ffd83dbSDimitry Andric       typename PassT::Result *Res =
10995ffd83dbSDimitry Andric           OuterAM->template getCachedResult<PassT>(IR);
11005ffd83dbSDimitry Andric       if (Res)
11015ffd83dbSDimitry Andric         OuterAM->template verifyNotInvalidated<PassT>(IR, Res);
11025ffd83dbSDimitry Andric       return Res;
11035ffd83dbSDimitry Andric     }
11045ffd83dbSDimitry Andric 
11055ffd83dbSDimitry Andric     /// Method provided for unit testing, not intended for general use.
11065ffd83dbSDimitry Andric     template <typename PassT, typename IRUnitTParam>
cachedResultExists(IRUnitTParam & IR)11075ffd83dbSDimitry Andric     bool cachedResultExists(IRUnitTParam &IR) const {
11085ffd83dbSDimitry Andric       typename PassT::Result *Res =
11095ffd83dbSDimitry Andric           OuterAM->template getCachedResult<PassT>(IR);
11105ffd83dbSDimitry Andric       return Res != nullptr;
11115ffd83dbSDimitry Andric     }
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric     /// When invalidation occurs, remove any registered invalidation events.
invalidate(IRUnitT & IRUnit,const PreservedAnalyses & PA,typename AnalysisManager<IRUnitT,ExtraArgTs...>::Invalidator & Inv)11140b57cec5SDimitry Andric     bool invalidate(
11150b57cec5SDimitry Andric         IRUnitT &IRUnit, const PreservedAnalyses &PA,
11160b57cec5SDimitry Andric         typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &Inv) {
11170b57cec5SDimitry Andric       // Loop over the set of registered outer invalidation mappings and if any
11180b57cec5SDimitry Andric       // of them map to an analysis that is now invalid, clear it out.
11190b57cec5SDimitry Andric       SmallVector<AnalysisKey *, 4> DeadKeys;
11200b57cec5SDimitry Andric       for (auto &KeyValuePair : OuterAnalysisInvalidationMap) {
11210b57cec5SDimitry Andric         AnalysisKey *OuterID = KeyValuePair.first;
11220b57cec5SDimitry Andric         auto &InnerIDs = KeyValuePair.second;
1123e8d8bef9SDimitry Andric         llvm::erase_if(InnerIDs, [&](AnalysisKey *InnerID) {
1124e8d8bef9SDimitry Andric           return Inv.invalidate(InnerID, IRUnit, PA);
1125e8d8bef9SDimitry Andric         });
11260b57cec5SDimitry Andric         if (InnerIDs.empty())
11270b57cec5SDimitry Andric           DeadKeys.push_back(OuterID);
11280b57cec5SDimitry Andric       }
11290b57cec5SDimitry Andric 
1130bdd1243dSDimitry Andric       for (auto *OuterID : DeadKeys)
11310b57cec5SDimitry Andric         OuterAnalysisInvalidationMap.erase(OuterID);
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric       // The proxy itself remains valid regardless of anything else.
11340b57cec5SDimitry Andric       return false;
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric     /// Register a deferred invalidation event for when the outer analysis
11380b57cec5SDimitry Andric     /// manager processes its invalidations.
11390b57cec5SDimitry Andric     template <typename OuterAnalysisT, typename InvalidatedAnalysisT>
registerOuterAnalysisInvalidation()11400b57cec5SDimitry Andric     void registerOuterAnalysisInvalidation() {
11410b57cec5SDimitry Andric       AnalysisKey *OuterID = OuterAnalysisT::ID();
11420b57cec5SDimitry Andric       AnalysisKey *InvalidatedID = InvalidatedAnalysisT::ID();
11430b57cec5SDimitry Andric 
11440b57cec5SDimitry Andric       auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID];
11450b57cec5SDimitry Andric       // Note, this is a linear scan. If we end up with large numbers of
11460b57cec5SDimitry Andric       // analyses that all trigger invalidation on the same outer analysis,
11470b57cec5SDimitry Andric       // this entire system should be changed to some other deterministic
11480b57cec5SDimitry Andric       // data structure such as a `SetVector` of a pair of pointers.
1149e8d8bef9SDimitry Andric       if (!llvm::is_contained(InvalidatedIDList, InvalidatedID))
11500b57cec5SDimitry Andric         InvalidatedIDList.push_back(InvalidatedID);
11510b57cec5SDimitry Andric     }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric     /// Access the map from outer analyses to deferred invalidation requiring
11540b57cec5SDimitry Andric     /// analyses.
11550b57cec5SDimitry Andric     const SmallDenseMap<AnalysisKey *, TinyPtrVector<AnalysisKey *>, 2> &
getOuterInvalidations()11560b57cec5SDimitry Andric     getOuterInvalidations() const {
11570b57cec5SDimitry Andric       return OuterAnalysisInvalidationMap;
11580b57cec5SDimitry Andric     }
11590b57cec5SDimitry Andric 
11600b57cec5SDimitry Andric   private:
1161480093f4SDimitry Andric     const AnalysisManagerT *OuterAM;
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric     /// A map from an outer analysis ID to the set of this IR-unit's analyses
11640b57cec5SDimitry Andric     /// which need to be invalidated.
11650b57cec5SDimitry Andric     SmallDenseMap<AnalysisKey *, TinyPtrVector<AnalysisKey *>, 2>
11660b57cec5SDimitry Andric         OuterAnalysisInvalidationMap;
11670b57cec5SDimitry Andric   };
11680b57cec5SDimitry Andric 
OuterAnalysisManagerProxy(const AnalysisManagerT & OuterAM)1169480093f4SDimitry Andric   OuterAnalysisManagerProxy(const AnalysisManagerT &OuterAM)
1170480093f4SDimitry Andric       : OuterAM(&OuterAM) {}
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric   /// Run the analysis pass and create our proxy result object.
1173480093f4SDimitry Andric   /// Nothing to see here, it just forwards the \c OuterAM reference into the
11740b57cec5SDimitry Andric   /// result.
run(IRUnitT &,AnalysisManager<IRUnitT,ExtraArgTs...> &,ExtraArgTs...)11750b57cec5SDimitry Andric   Result run(IRUnitT &, AnalysisManager<IRUnitT, ExtraArgTs...> &,
11760b57cec5SDimitry Andric              ExtraArgTs...) {
1177480093f4SDimitry Andric     return Result(*OuterAM);
11780b57cec5SDimitry Andric   }
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric private:
11810b57cec5SDimitry Andric   friend AnalysisInfoMixin<
11820b57cec5SDimitry Andric       OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>>;
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric   static AnalysisKey Key;
11850b57cec5SDimitry Andric 
1186480093f4SDimitry Andric   const AnalysisManagerT *OuterAM;
11870b57cec5SDimitry Andric };
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
11900b57cec5SDimitry Andric AnalysisKey
11910b57cec5SDimitry Andric     OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>::Key;
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
11940b57cec5SDimitry Andric                                                 Function>;
11950b57cec5SDimitry Andric /// Provide the \c ModuleAnalysisManager to \c Function proxy.
11960b57cec5SDimitry Andric using ModuleAnalysisManagerFunctionProxy =
11970b57cec5SDimitry Andric     OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>;
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric /// Trivial adaptor that maps from a module to its functions.
12000b57cec5SDimitry Andric ///
12010b57cec5SDimitry Andric /// Designed to allow composition of a FunctionPass(Manager) and
12020b57cec5SDimitry Andric /// a ModulePassManager, by running the FunctionPass(Manager) over every
12030b57cec5SDimitry Andric /// function in the module.
12040b57cec5SDimitry Andric ///
12050b57cec5SDimitry Andric /// Function passes run within this adaptor can rely on having exclusive access
12060b57cec5SDimitry Andric /// to the function they are run over. They should not read or modify any other
12070b57cec5SDimitry Andric /// functions! Other threads or systems may be manipulating other functions in
12080b57cec5SDimitry Andric /// the module, and so their state should never be relied on.
12090b57cec5SDimitry Andric /// FIXME: Make the above true for all of LLVM's actual passes, some still
12100b57cec5SDimitry Andric /// violate this principle.
12110b57cec5SDimitry Andric ///
12120b57cec5SDimitry Andric /// Function passes can also read the module containing the function, but they
12130b57cec5SDimitry Andric /// should not modify that module outside of the use lists of various globals.
12140b57cec5SDimitry Andric /// For example, a function pass is not permitted to add functions to the
12150b57cec5SDimitry Andric /// module.
12160b57cec5SDimitry Andric /// FIXME: Make the above true for all of LLVM's actual passes, some still
12170b57cec5SDimitry Andric /// violate this principle.
12180b57cec5SDimitry Andric ///
12190b57cec5SDimitry Andric /// Note that although function passes can access module analyses, module
12200b57cec5SDimitry Andric /// analyses are not invalidated while the function passes are running, so they
12210b57cec5SDimitry Andric /// may be stale.  Function analyses will not be stale.
12220b57cec5SDimitry Andric class ModuleToFunctionPassAdaptor
1223e8d8bef9SDimitry Andric     : public PassInfoMixin<ModuleToFunctionPassAdaptor> {
12240b57cec5SDimitry Andric public:
1225e8d8bef9SDimitry Andric   using PassConceptT = detail::PassConcept<Function, FunctionAnalysisManager>;
1226e8d8bef9SDimitry Andric 
ModuleToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,bool EagerlyInvalidate)1227349cc55cSDimitry Andric   explicit ModuleToFunctionPassAdaptor(std::unique_ptr<PassConceptT> Pass,
1228349cc55cSDimitry Andric                                        bool EagerlyInvalidate)
1229349cc55cSDimitry Andric       : Pass(std::move(Pass)), EagerlyInvalidate(EagerlyInvalidate) {}
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric   /// Runs the function pass across every function in the module.
1232e8d8bef9SDimitry Andric   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
1233349cc55cSDimitry Andric   void printPipeline(raw_ostream &OS,
1234349cc55cSDimitry Andric                      function_ref<StringRef(StringRef)> MapClassName2PassName);
12350b57cec5SDimitry Andric 
isRequired()1236e8d8bef9SDimitry Andric   static bool isRequired() { return true; }
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric private:
1239e8d8bef9SDimitry Andric   std::unique_ptr<PassConceptT> Pass;
1240349cc55cSDimitry Andric   bool EagerlyInvalidate;
12410b57cec5SDimitry Andric };
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric /// A function to deduce a function pass type and wrap it in the
12440b57cec5SDimitry Andric /// templated adaptor.
12450b57cec5SDimitry Andric template <typename FunctionPassT>
1246e8d8bef9SDimitry Andric ModuleToFunctionPassAdaptor
1247349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(FunctionPassT &&Pass,
1248349cc55cSDimitry Andric                                   bool EagerlyInvalidate = false) {
1249e8d8bef9SDimitry Andric   using PassModelT =
1250e8d8bef9SDimitry Andric       detail::PassModel<Function, FunctionPassT, PreservedAnalyses,
1251e8d8bef9SDimitry Andric                         FunctionAnalysisManager>;
1252349cc55cSDimitry Andric   // Do not use make_unique, it causes too many template instantiations,
1253349cc55cSDimitry Andric   // causing terrible compile times.
1254e8d8bef9SDimitry Andric   return ModuleToFunctionPassAdaptor(
1255349cc55cSDimitry Andric       std::unique_ptr<ModuleToFunctionPassAdaptor::PassConceptT>(
1256349cc55cSDimitry Andric           new PassModelT(std::forward<FunctionPassT>(Pass))),
1257349cc55cSDimitry Andric       EagerlyInvalidate);
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric /// A utility pass template to force an analysis result to be available.
12610b57cec5SDimitry Andric ///
12620b57cec5SDimitry Andric /// If there are extra arguments at the pass's run level there may also be
12630b57cec5SDimitry Andric /// extra arguments to the analysis manager's \c getResult routine. We can't
12640b57cec5SDimitry Andric /// guess how to effectively map the arguments from one to the other, and so
12650b57cec5SDimitry Andric /// this specialization just ignores them.
12660b57cec5SDimitry Andric ///
12670b57cec5SDimitry Andric /// Specific patterns of run-method extra arguments and analysis manager extra
12680b57cec5SDimitry Andric /// arguments will have to be defined as appropriate specializations.
12690b57cec5SDimitry Andric template <typename AnalysisT, typename IRUnitT,
12700b57cec5SDimitry Andric           typename AnalysisManagerT = AnalysisManager<IRUnitT>,
12710b57cec5SDimitry Andric           typename... ExtraArgTs>
12720b57cec5SDimitry Andric struct RequireAnalysisPass
12730b57cec5SDimitry Andric     : PassInfoMixin<RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT,
12740b57cec5SDimitry Andric                                         ExtraArgTs...>> {
12750b57cec5SDimitry Andric   /// Run this pass over some unit of IR.
12760b57cec5SDimitry Andric   ///
12770b57cec5SDimitry Andric   /// This pass can be run over any unit of IR and use any analysis manager
12780b57cec5SDimitry Andric   /// provided they satisfy the basic API requirements. When this pass is
12790b57cec5SDimitry Andric   /// created, these methods can be instantiated to satisfy whatever the
12800b57cec5SDimitry Andric   /// context requires.
runRequireAnalysisPass12810b57cec5SDimitry Andric   PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM,
12820b57cec5SDimitry Andric                         ExtraArgTs &&... Args) {
12830b57cec5SDimitry Andric     (void)AM.template getResult<AnalysisT>(Arg,
12840b57cec5SDimitry Andric                                            std::forward<ExtraArgTs>(Args)...);
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric     return PreservedAnalyses::all();
12870b57cec5SDimitry Andric   }
printPipelineRequireAnalysisPass1288349cc55cSDimitry Andric   void printPipeline(raw_ostream &OS,
1289349cc55cSDimitry Andric                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
1290349cc55cSDimitry Andric     auto ClassName = AnalysisT::name();
1291349cc55cSDimitry Andric     auto PassName = MapClassName2PassName(ClassName);
129206c3fb27SDimitry Andric     OS << "require<" << PassName << '>';
1293349cc55cSDimitry Andric   }
isRequiredRequireAnalysisPass1294e8d8bef9SDimitry Andric   static bool isRequired() { return true; }
12950b57cec5SDimitry Andric };
12960b57cec5SDimitry Andric 
12970b57cec5SDimitry Andric /// A no-op pass template which simply forces a specific analysis result
12980b57cec5SDimitry Andric /// to be invalidated.
12990b57cec5SDimitry Andric template <typename AnalysisT>
13000b57cec5SDimitry Andric struct InvalidateAnalysisPass
13010b57cec5SDimitry Andric     : PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> {
13020b57cec5SDimitry Andric   /// Run this pass over some unit of IR.
13030b57cec5SDimitry Andric   ///
13040b57cec5SDimitry Andric   /// This pass can be run over any unit of IR and use any analysis manager,
13050b57cec5SDimitry Andric   /// provided they satisfy the basic API requirements. When this pass is
13060b57cec5SDimitry Andric   /// created, these methods can be instantiated to satisfy whatever the
13070b57cec5SDimitry Andric   /// context requires.
13080b57cec5SDimitry Andric   template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
runInvalidateAnalysisPass13090b57cec5SDimitry Andric   PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...) {
13100b57cec5SDimitry Andric     auto PA = PreservedAnalyses::all();
13110b57cec5SDimitry Andric     PA.abandon<AnalysisT>();
13120b57cec5SDimitry Andric     return PA;
13130b57cec5SDimitry Andric   }
printPipelineInvalidateAnalysisPass1314349cc55cSDimitry Andric   void printPipeline(raw_ostream &OS,
1315349cc55cSDimitry Andric                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
1316349cc55cSDimitry Andric     auto ClassName = AnalysisT::name();
1317349cc55cSDimitry Andric     auto PassName = MapClassName2PassName(ClassName);
131806c3fb27SDimitry Andric     OS << "invalidate<" << PassName << '>';
1319349cc55cSDimitry Andric   }
13200b57cec5SDimitry Andric };
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric /// A utility pass that does nothing, but preserves no analyses.
13230b57cec5SDimitry Andric ///
13240b57cec5SDimitry Andric /// Because this preserves no analyses, any analysis passes queried after this
13250b57cec5SDimitry Andric /// pass runs will recompute fresh results.
13260b57cec5SDimitry Andric struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> {
13270b57cec5SDimitry Andric   /// Run this pass over some unit of IR.
13280b57cec5SDimitry Andric   template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
runInvalidateAllAnalysesPass13290b57cec5SDimitry Andric   PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) {
13300b57cec5SDimitry Andric     return PreservedAnalyses::none();
13310b57cec5SDimitry Andric   }
13320b57cec5SDimitry Andric };
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric /// A utility pass template that simply runs another pass multiple times.
13350b57cec5SDimitry Andric ///
13360b57cec5SDimitry Andric /// This can be useful when debugging or testing passes. It also serves as an
13370b57cec5SDimitry Andric /// example of how to extend the pass manager in ways beyond composition.
13380b57cec5SDimitry Andric template <typename PassT>
13390b57cec5SDimitry Andric class RepeatedPass : public PassInfoMixin<RepeatedPass<PassT>> {
13400b57cec5SDimitry Andric public:
RepeatedPass(int Count,PassT && P)1341fe6060f1SDimitry Andric   RepeatedPass(int Count, PassT &&P)
1342fe6060f1SDimitry Andric       : Count(Count), P(std::forward<PassT>(P)) {}
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   template <typename IRUnitT, typename AnalysisManagerT, typename... Ts>
run(IRUnitT & IR,AnalysisManagerT & AM,Ts &&...Args)13450b57cec5SDimitry Andric   PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, Ts &&... Args) {
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric     // Request PassInstrumentation from analysis manager, will use it to run
13480b57cec5SDimitry Andric     // instrumenting callbacks for the passes later.
13490b57cec5SDimitry Andric     // Here we use std::tuple wrapper over getResult which helps to extract
13500b57cec5SDimitry Andric     // AnalysisManager's arguments out of the whole Args set.
13510b57cec5SDimitry Andric     PassInstrumentation PI =
13520b57cec5SDimitry Andric         detail::getAnalysisResult<PassInstrumentationAnalysis>(
13530b57cec5SDimitry Andric             AM, IR, std::tuple<Ts...>(Args...));
13540b57cec5SDimitry Andric 
13550b57cec5SDimitry Andric     auto PA = PreservedAnalyses::all();
13560b57cec5SDimitry Andric     for (int i = 0; i < Count; ++i) {
13570b57cec5SDimitry Andric       // Check the PassInstrumentation's BeforePass callbacks before running the
13580b57cec5SDimitry Andric       // pass, skip its execution completely if asked to (callback returns
13590b57cec5SDimitry Andric       // false).
13600b57cec5SDimitry Andric       if (!PI.runBeforePass<IRUnitT>(P, IR))
13610b57cec5SDimitry Andric         continue;
1362e8d8bef9SDimitry Andric       PreservedAnalyses IterPA = P.run(IR, AM, std::forward<Ts>(Args)...);
1363e8d8bef9SDimitry Andric       PA.intersect(IterPA);
1364e8d8bef9SDimitry Andric       PI.runAfterPass(P, IR, IterPA);
13650b57cec5SDimitry Andric     }
13660b57cec5SDimitry Andric     return PA;
13670b57cec5SDimitry Andric   }
13680b57cec5SDimitry Andric 
printPipeline(raw_ostream & OS,function_ref<StringRef (StringRef)> MapClassName2PassName)1369349cc55cSDimitry Andric   void printPipeline(raw_ostream &OS,
1370349cc55cSDimitry Andric                      function_ref<StringRef(StringRef)> MapClassName2PassName) {
1371349cc55cSDimitry Andric     OS << "repeat<" << Count << ">(";
1372349cc55cSDimitry Andric     P.printPipeline(OS, MapClassName2PassName);
137306c3fb27SDimitry Andric     OS << ')';
1374349cc55cSDimitry Andric   }
1375349cc55cSDimitry Andric 
13760b57cec5SDimitry Andric private:
13770b57cec5SDimitry Andric   int Count;
13780b57cec5SDimitry Andric   PassT P;
13790b57cec5SDimitry Andric };
13800b57cec5SDimitry Andric 
13810b57cec5SDimitry Andric template <typename PassT>
createRepeatedPass(int Count,PassT && P)1382fe6060f1SDimitry Andric RepeatedPass<PassT> createRepeatedPass(int Count, PassT &&P) {
1383fe6060f1SDimitry Andric   return RepeatedPass<PassT>(Count, std::forward<PassT>(P));
13840b57cec5SDimitry Andric }
13850b57cec5SDimitry Andric 
13860b57cec5SDimitry Andric } // end namespace llvm
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric #endif // LLVM_IR_PASSMANAGER_H
1389