[llvm] [NFC][PassManager] Remove PreservedAnalysesT template parameter (PR #80324)

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 1 20:07:17 PST 2024


https://github.com/aeubanks updated https://github.com/llvm/llvm-project/pull/80324

>From 7a93384d31d2712ec48a36ff0da66c36d43bb027 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Thu, 1 Feb 2024 18:54:42 +0000
Subject: [PATCH 1/2] [NFC][PassManager] Remove PreservedAnalysesT template
 parameter

This is always PreservedAnalyses. Perhaps in the past there was the idea
to make some types of passes return more invalidation information, but
that hasn't happened.

Requires splitting out some analysis classes into a header so
PassManagerInternal.h can see the definition of PreservedAnalyses.
---
 llvm/include/llvm/Analysis/CGSCCPassManager.h |  15 +-
 .../include/llvm/CodeGen/MachinePassManager.h |  15 +-
 llvm/include/llvm/IR/Analysis.h               | 319 +++++++++++++++++
 llvm/include/llvm/IR/PassManager.h            | 323 +-----------------
 llvm/include/llvm/IR/PassManagerInternal.h    |  53 ++-
 .../llvm/Transforms/Scalar/LoopPassManager.h  |  29 +-
 6 files changed, 377 insertions(+), 377 deletions(-)
 create mode 100644 llvm/include/llvm/IR/Analysis.h

diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h
index 0264b36a1d12f..5654ad46d6eab 100644
--- a/llvm/include/llvm/Analysis/CGSCCPassManager.h
+++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h
@@ -371,9 +371,9 @@ class ModuleToPostOrderCGSCCPassAdaptor
 template <typename CGSCCPassT>
 ModuleToPostOrderCGSCCPassAdaptor
 createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT &&Pass) {
-  using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
-                                       PreservedAnalyses, CGSCCAnalysisManager,
-                                       LazyCallGraph &, CGSCCUpdateResult &>;
+  using PassModelT =
+      detail::PassModel<LazyCallGraph::SCC, CGSCCPassT, CGSCCAnalysisManager,
+                        LazyCallGraph &, CGSCCUpdateResult &>;
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.
   return ModuleToPostOrderCGSCCPassAdaptor(
@@ -518,8 +518,7 @@ createCGSCCToFunctionPassAdaptor(FunctionPassT &&Pass,
                                  bool EagerlyInvalidate = false,
                                  bool NoRerun = false) {
   using PassModelT =
-      detail::PassModel<Function, FunctionPassT, PreservedAnalyses,
-                        FunctionAnalysisManager>;
+      detail::PassModel<Function, FunctionPassT, FunctionAnalysisManager>;
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.
   return CGSCCToFunctionPassAdaptor(
@@ -588,9 +587,9 @@ class DevirtSCCRepeatedPass : public PassInfoMixin<DevirtSCCRepeatedPass> {
 template <typename CGSCCPassT>
 DevirtSCCRepeatedPass createDevirtSCCRepeatedPass(CGSCCPassT &&Pass,
                                                   int MaxIterations) {
-  using PassModelT = detail::PassModel<LazyCallGraph::SCC, CGSCCPassT,
-                                       PreservedAnalyses, CGSCCAnalysisManager,
-                                       LazyCallGraph &, CGSCCUpdateResult &>;
+  using PassModelT =
+      detail::PassModel<LazyCallGraph::SCC, CGSCCPassT, CGSCCAnalysisManager,
+                        LazyCallGraph &, CGSCCUpdateResult &>;
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.
   return DevirtSCCRepeatedPass(
diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index 662b7e8689717..a0ad7d7a95a28 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -183,9 +183,8 @@ class MachineFunctionPassManager
   template <typename PassT>
   std::enable_if_t<is_detected<has_init_t, PassT>::value>
   addDoInitialization(PassConceptT *Pass) {
-    using PassModelT =
-        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
-                          MachineFunctionAnalysisManager>;
+    using PassModelT = detail::PassModel<MachineFunction, PassT,
+                                         MachineFunctionAnalysisManager>;
     auto *P = static_cast<PassModelT *>(Pass);
     InitializationFuncs.emplace_back(
         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
@@ -205,9 +204,8 @@ class MachineFunctionPassManager
   template <typename PassT>
   std::enable_if_t<is_detected<has_fini_t, PassT>::value>
   addDoFinalization(PassConceptT *Pass) {
-    using PassModelT =
-        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
-                          MachineFunctionAnalysisManager>;
+    using PassModelT = detail::PassModel<MachineFunction, PassT,
+                                         MachineFunctionAnalysisManager>;
     auto *P = static_cast<PassModelT *>(Pass);
     FinalizationFuncs.emplace_back(
         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
@@ -236,9 +234,8 @@ class MachineFunctionPassManager
                   "machine module pass needs to define machine function pass "
                   "api. sorry.");
 
-    using PassModelT =
-        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
-                          MachineFunctionAnalysisManager>;
+    using PassModelT = detail::PassModel<MachineFunction, PassT,
+                                         MachineFunctionAnalysisManager>;
     auto *P = static_cast<PassModelT *>(Pass);
     MachineModulePasses.emplace(
         Passes.size() - 1,
diff --git a/llvm/include/llvm/IR/Analysis.h b/llvm/include/llvm/IR/Analysis.h
new file mode 100644
index 0000000000000..a7005285dd9bf
--- /dev/null
+++ b/llvm/include/llvm/IR/Analysis.h
@@ -0,0 +1,319 @@
+//===- Analysis.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Pass manager infrastructure for declaring and invalidating analyses.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_ANALYSIS_H
+#define LLVM_IR_ANALYSIS_H
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+
+namespace llvm {
+/// A special type used by analysis passes to provide an address that
+/// identifies that particular analysis pass type.
+///
+/// Analysis passes should have a static data member of this type and derive
+/// from the \c AnalysisInfoMixin to get a static ID method used to identify
+/// the analysis in the pass management infrastructure.
+struct alignas(8) AnalysisKey {};
+
+/// A special type used to provide an address that identifies a set of related
+/// analyses.  These sets are primarily used below to mark sets of analyses as
+/// preserved.
+///
+/// For example, a transformation can indicate that it preserves the CFG of a
+/// function by preserving the appropriate AnalysisSetKey.  An analysis that
+/// depends only on the CFG can then check if that AnalysisSetKey is preserved;
+/// if it is, the analysis knows that it itself is preserved.
+struct alignas(8) AnalysisSetKey {};
+
+/// This templated class represents "all analyses that operate over \<a
+/// particular IR unit\>" (e.g. a Function or a Module) in instances of
+/// PreservedAnalysis.
+///
+/// This lets a transformation say e.g. "I preserved all function analyses".
+///
+/// Note that you must provide an explicit instantiation declaration and
+/// definition for this template in order to get the correct behavior on
+/// Windows. Otherwise, the address of SetKey will not be stable.
+template <typename IRUnitT> class AllAnalysesOn {
+public:
+  static AnalysisSetKey *ID() { return &SetKey; }
+
+private:
+  static AnalysisSetKey SetKey;
+};
+
+template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
+
+extern template class AllAnalysesOn<Module>;
+extern template class AllAnalysesOn<Function>;
+
+/// Represents analyses that only rely on functions' control flow.
+///
+/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and
+/// to query whether it has been preserved.
+///
+/// The CFG of a function is defined as the set of basic blocks and the edges
+/// between them. Changing the set of basic blocks in a function is enough to
+/// mutate the CFG. Mutating the condition of a branch or argument of an
+/// invoked function does not mutate the CFG, but changing the successor labels
+/// of those instructions does.
+class CFGAnalyses {
+public:
+  static AnalysisSetKey *ID() { return &SetKey; }
+
+private:
+  static AnalysisSetKey SetKey;
+};
+
+/// A set of analyses that are preserved following a run of a transformation
+/// pass.
+///
+/// Transformation passes build and return these objects to communicate which
+/// analyses are still valid after the transformation. For most passes this is
+/// fairly simple: if they don't change anything all analyses are preserved,
+/// otherwise only a short list of analyses that have been explicitly updated
+/// are preserved.
+///
+/// This class also lets transformation passes mark abstract *sets* of analyses
+/// as preserved. A transformation that (say) does not alter the CFG can
+/// indicate such by marking a particular AnalysisSetKey as preserved, and
+/// then analyses can query whether that AnalysisSetKey is preserved.
+///
+/// Finally, this class can represent an "abandoned" analysis, which is
+/// not preserved even if it would be covered by some abstract set of analyses.
+///
+/// Given a `PreservedAnalyses` object, an analysis will typically want to
+/// figure out whether it is preserved. In the example below, MyAnalysisType is
+/// preserved if it's not abandoned, and (a) it's explicitly marked as
+/// preserved, (b), the set AllAnalysesOn<MyIRUnit> is preserved, or (c) both
+/// AnalysisSetA and AnalysisSetB are preserved.
+///
+/// ```
+///   auto PAC = PA.getChecker<MyAnalysisType>();
+///   if (PAC.preserved() || PAC.preservedSet<AllAnalysesOn<MyIRUnit>>() ||
+///       (PAC.preservedSet<AnalysisSetA>() &&
+///        PAC.preservedSet<AnalysisSetB>())) {
+///     // The analysis has been successfully preserved ...
+///   }
+/// ```
+class PreservedAnalyses {
+public:
+  /// Convenience factory function for the empty preserved set.
+  static PreservedAnalyses none() { return PreservedAnalyses(); }
+
+  /// Construct a special preserved set that preserves all passes.
+  static PreservedAnalyses all() {
+    PreservedAnalyses PA;
+    PA.PreservedIDs.insert(&AllAnalysesKey);
+    return PA;
+  }
+
+  /// Construct a preserved analyses object with a single preserved set.
+  template <typename AnalysisSetT> static PreservedAnalyses allInSet() {
+    PreservedAnalyses PA;
+    PA.preserveSet<AnalysisSetT>();
+    return PA;
+  }
+
+  /// Mark an analysis as preserved.
+  template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); }
+
+  /// Given an analysis's ID, mark the analysis as preserved, adding it
+  /// to the set.
+  void preserve(AnalysisKey *ID) {
+    // Clear this ID from the explicit not-preserved set if present.
+    NotPreservedAnalysisIDs.erase(ID);
+
+    // If we're not already preserving all analyses (other than those in
+    // NotPreservedAnalysisIDs).
+    if (!areAllPreserved())
+      PreservedIDs.insert(ID);
+  }
+
+  /// Mark an analysis set as preserved.
+  template <typename AnalysisSetT> void preserveSet() {
+    preserveSet(AnalysisSetT::ID());
+  }
+
+  /// Mark an analysis set as preserved using its ID.
+  void preserveSet(AnalysisSetKey *ID) {
+    // If we're not already in the saturated 'all' state, add this set.
+    if (!areAllPreserved())
+      PreservedIDs.insert(ID);
+  }
+
+  /// Mark an analysis as abandoned.
+  ///
+  /// An abandoned analysis is not preserved, even if it is nominally covered
+  /// by some other set or was previously explicitly marked as preserved.
+  ///
+  /// Note that you can only abandon a specific analysis, not a *set* of
+  /// analyses.
+  template <typename AnalysisT> void abandon() { abandon(AnalysisT::ID()); }
+
+  /// Mark an analysis as abandoned using its ID.
+  ///
+  /// An abandoned analysis is not preserved, even if it is nominally covered
+  /// by some other set or was previously explicitly marked as preserved.
+  ///
+  /// Note that you can only abandon a specific analysis, not a *set* of
+  /// analyses.
+  void abandon(AnalysisKey *ID) {
+    PreservedIDs.erase(ID);
+    NotPreservedAnalysisIDs.insert(ID);
+  }
+
+  /// Intersect this set with another in place.
+  ///
+  /// This is a mutating operation on this preserved set, removing all
+  /// preserved passes which are not also preserved in the argument.
+  void intersect(const PreservedAnalyses &Arg) {
+    if (Arg.areAllPreserved())
+      return;
+    if (areAllPreserved()) {
+      *this = Arg;
+      return;
+    }
+    // The intersection requires the *union* of the explicitly not-preserved
+    // IDs and the *intersection* of the preserved IDs.
+    for (auto *ID : Arg.NotPreservedAnalysisIDs) {
+      PreservedIDs.erase(ID);
+      NotPreservedAnalysisIDs.insert(ID);
+    }
+    for (auto *ID : PreservedIDs)
+      if (!Arg.PreservedIDs.count(ID))
+        PreservedIDs.erase(ID);
+  }
+
+  /// Intersect this set with a temporary other set in place.
+  ///
+  /// This is a mutating operation on this preserved set, removing all
+  /// preserved passes which are not also preserved in the argument.
+  void intersect(PreservedAnalyses &&Arg) {
+    if (Arg.areAllPreserved())
+      return;
+    if (areAllPreserved()) {
+      *this = std::move(Arg);
+      return;
+    }
+    // The intersection requires the *union* of the explicitly not-preserved
+    // IDs and the *intersection* of the preserved IDs.
+    for (auto *ID : Arg.NotPreservedAnalysisIDs) {
+      PreservedIDs.erase(ID);
+      NotPreservedAnalysisIDs.insert(ID);
+    }
+    for (auto *ID : PreservedIDs)
+      if (!Arg.PreservedIDs.count(ID))
+        PreservedIDs.erase(ID);
+  }
+
+  /// A checker object that makes it easy to query for whether an analysis or
+  /// some set covering it is preserved.
+  class PreservedAnalysisChecker {
+    friend class PreservedAnalyses;
+
+    const PreservedAnalyses &PA;
+    AnalysisKey *const ID;
+    const bool IsAbandoned;
+
+    /// A PreservedAnalysisChecker is tied to a particular Analysis because
+    /// `preserved()` and `preservedSet()` both return false if the Analysis
+    /// was abandoned.
+    PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID)
+        : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {}
+
+  public:
+    /// Returns true if the checker's analysis was not abandoned and either
+    ///  - the analysis is explicitly preserved or
+    ///  - all analyses are preserved.
+    bool preserved() {
+      return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) ||
+                              PA.PreservedIDs.count(ID));
+    }
+
+    /// Return true if the checker's analysis was not abandoned, i.e. it was not
+    /// explicitly invalidated. Even if the analysis is not explicitly
+    /// preserved, if the analysis is known stateless, then it is preserved.
+    bool preservedWhenStateless() { return !IsAbandoned; }
+
+    /// Returns true if the checker's analysis was not abandoned and either
+    ///  - \p AnalysisSetT is explicitly preserved or
+    ///  - all analyses are preserved.
+    template <typename AnalysisSetT> bool preservedSet() {
+      AnalysisSetKey *SetID = AnalysisSetT::ID();
+      return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) ||
+                              PA.PreservedIDs.count(SetID));
+    }
+  };
+
+  /// Build a checker for this `PreservedAnalyses` and the specified analysis
+  /// type.
+  ///
+  /// You can use the returned object to query whether an analysis was
+  /// preserved. See the example in the comment on `PreservedAnalysis`.
+  template <typename AnalysisT> PreservedAnalysisChecker getChecker() const {
+    return PreservedAnalysisChecker(*this, AnalysisT::ID());
+  }
+
+  /// Build a checker for this `PreservedAnalyses` and the specified analysis
+  /// ID.
+  ///
+  /// You can use the returned object to query whether an analysis was
+  /// preserved. See the example in the comment on `PreservedAnalysis`.
+  PreservedAnalysisChecker getChecker(AnalysisKey *ID) const {
+    return PreservedAnalysisChecker(*this, ID);
+  }
+
+  /// Test whether all analyses are preserved (and none are abandoned).
+  ///
+  /// This is used primarily to optimize for the common case of a transformation
+  /// which makes no changes to the IR.
+  bool areAllPreserved() const {
+    return NotPreservedAnalysisIDs.empty() &&
+           PreservedIDs.count(&AllAnalysesKey);
+  }
+
+  /// Directly test whether a set of analyses is preserved.
+  ///
+  /// This is only true when no analyses have been explicitly abandoned.
+  template <typename AnalysisSetT> bool allAnalysesInSetPreserved() const {
+    return allAnalysesInSetPreserved(AnalysisSetT::ID());
+  }
+
+  /// Directly test whether a set of analyses is preserved.
+  ///
+  /// This is only true when no analyses have been explicitly abandoned.
+  bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const {
+    return NotPreservedAnalysisIDs.empty() &&
+           (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID));
+  }
+
+private:
+  /// A special key used to indicate all analyses.
+  static AnalysisSetKey AllAnalysesKey;
+
+  /// The IDs of analyses and analysis sets that are preserved.
+  SmallPtrSet<void *, 2> PreservedIDs;
+
+  /// The IDs of explicitly not-preserved analyses.
+  ///
+  /// If an analysis in this set is covered by a set in `PreservedIDs`, we
+  /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always
+  /// "wins" over analysis sets in `PreservedIDs`.
+  ///
+  /// Also, a given ID should never occur both here and in `PreservedIDs`.
+  SmallPtrSet<AnalysisKey *, 2> NotPreservedAnalysisIDs;
+};
+} // namespace llvm
+
+#endif
\ No newline at end of file
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index df548fbe9e458..c03d49c3b7b97 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -42,6 +42,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/IR/Analysis.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PassInstrumentation.h"
@@ -80,307 +81,6 @@ template <> inline void doConvertDebugInfoToOld(Module &IR) {
   IR.convertFromNewDbgValues();
 }
 
-/// A special type used by analysis passes to provide an address that
-/// identifies that particular analysis pass type.
-///
-/// Analysis passes should have a static data member of this type and derive
-/// from the \c AnalysisInfoMixin to get a static ID method used to identify
-/// the analysis in the pass management infrastructure.
-struct alignas(8) AnalysisKey {};
-
-/// A special type used to provide an address that identifies a set of related
-/// analyses.  These sets are primarily used below to mark sets of analyses as
-/// preserved.
-///
-/// For example, a transformation can indicate that it preserves the CFG of a
-/// function by preserving the appropriate AnalysisSetKey.  An analysis that
-/// depends only on the CFG can then check if that AnalysisSetKey is preserved;
-/// if it is, the analysis knows that it itself is preserved.
-struct alignas(8) AnalysisSetKey {};
-
-/// This templated class represents "all analyses that operate over \<a
-/// particular IR unit\>" (e.g. a Function or a Module) in instances of
-/// PreservedAnalysis.
-///
-/// This lets a transformation say e.g. "I preserved all function analyses".
-///
-/// Note that you must provide an explicit instantiation declaration and
-/// definition for this template in order to get the correct behavior on
-/// Windows. Otherwise, the address of SetKey will not be stable.
-template <typename IRUnitT> class AllAnalysesOn {
-public:
-  static AnalysisSetKey *ID() { return &SetKey; }
-
-private:
-  static AnalysisSetKey SetKey;
-};
-
-template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
-
-extern template class AllAnalysesOn<Module>;
-extern template class AllAnalysesOn<Function>;
-
-/// Represents analyses that only rely on functions' control flow.
-///
-/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and
-/// to query whether it has been preserved.
-///
-/// The CFG of a function is defined as the set of basic blocks and the edges
-/// between them. Changing the set of basic blocks in a function is enough to
-/// mutate the CFG. Mutating the condition of a branch or argument of an
-/// invoked function does not mutate the CFG, but changing the successor labels
-/// of those instructions does.
-class CFGAnalyses {
-public:
-  static AnalysisSetKey *ID() { return &SetKey; }
-
-private:
-  static AnalysisSetKey SetKey;
-};
-
-/// A set of analyses that are preserved following a run of a transformation
-/// pass.
-///
-/// Transformation passes build and return these objects to communicate which
-/// analyses are still valid after the transformation. For most passes this is
-/// fairly simple: if they don't change anything all analyses are preserved,
-/// otherwise only a short list of analyses that have been explicitly updated
-/// are preserved.
-///
-/// This class also lets transformation passes mark abstract *sets* of analyses
-/// as preserved. A transformation that (say) does not alter the CFG can
-/// indicate such by marking a particular AnalysisSetKey as preserved, and
-/// then analyses can query whether that AnalysisSetKey is preserved.
-///
-/// Finally, this class can represent an "abandoned" analysis, which is
-/// not preserved even if it would be covered by some abstract set of analyses.
-///
-/// Given a `PreservedAnalyses` object, an analysis will typically want to
-/// figure out whether it is preserved. In the example below, MyAnalysisType is
-/// preserved if it's not abandoned, and (a) it's explicitly marked as
-/// preserved, (b), the set AllAnalysesOn<MyIRUnit> is preserved, or (c) both
-/// AnalysisSetA and AnalysisSetB are preserved.
-///
-/// ```
-///   auto PAC = PA.getChecker<MyAnalysisType>();
-///   if (PAC.preserved() || PAC.preservedSet<AllAnalysesOn<MyIRUnit>>() ||
-///       (PAC.preservedSet<AnalysisSetA>() &&
-///        PAC.preservedSet<AnalysisSetB>())) {
-///     // The analysis has been successfully preserved ...
-///   }
-/// ```
-class PreservedAnalyses {
-public:
-  /// Convenience factory function for the empty preserved set.
-  static PreservedAnalyses none() { return PreservedAnalyses(); }
-
-  /// Construct a special preserved set that preserves all passes.
-  static PreservedAnalyses all() {
-    PreservedAnalyses PA;
-    PA.PreservedIDs.insert(&AllAnalysesKey);
-    return PA;
-  }
-
-  /// Construct a preserved analyses object with a single preserved set.
-  template <typename AnalysisSetT>
-  static PreservedAnalyses allInSet() {
-    PreservedAnalyses PA;
-    PA.preserveSet<AnalysisSetT>();
-    return PA;
-  }
-
-  /// Mark an analysis as preserved.
-  template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); }
-
-  /// Given an analysis's ID, mark the analysis as preserved, adding it
-  /// to the set.
-  void preserve(AnalysisKey *ID) {
-    // Clear this ID from the explicit not-preserved set if present.
-    NotPreservedAnalysisIDs.erase(ID);
-
-    // If we're not already preserving all analyses (other than those in
-    // NotPreservedAnalysisIDs).
-    if (!areAllPreserved())
-      PreservedIDs.insert(ID);
-  }
-
-  /// Mark an analysis set as preserved.
-  template <typename AnalysisSetT> void preserveSet() {
-    preserveSet(AnalysisSetT::ID());
-  }
-
-  /// Mark an analysis set as preserved using its ID.
-  void preserveSet(AnalysisSetKey *ID) {
-    // If we're not already in the saturated 'all' state, add this set.
-    if (!areAllPreserved())
-      PreservedIDs.insert(ID);
-  }
-
-  /// Mark an analysis as abandoned.
-  ///
-  /// An abandoned analysis is not preserved, even if it is nominally covered
-  /// by some other set or was previously explicitly marked as preserved.
-  ///
-  /// Note that you can only abandon a specific analysis, not a *set* of
-  /// analyses.
-  template <typename AnalysisT> void abandon() { abandon(AnalysisT::ID()); }
-
-  /// Mark an analysis as abandoned using its ID.
-  ///
-  /// An abandoned analysis is not preserved, even if it is nominally covered
-  /// by some other set or was previously explicitly marked as preserved.
-  ///
-  /// Note that you can only abandon a specific analysis, not a *set* of
-  /// analyses.
-  void abandon(AnalysisKey *ID) {
-    PreservedIDs.erase(ID);
-    NotPreservedAnalysisIDs.insert(ID);
-  }
-
-  /// Intersect this set with another in place.
-  ///
-  /// This is a mutating operation on this preserved set, removing all
-  /// preserved passes which are not also preserved in the argument.
-  void intersect(const PreservedAnalyses &Arg) {
-    if (Arg.areAllPreserved())
-      return;
-    if (areAllPreserved()) {
-      *this = Arg;
-      return;
-    }
-    // The intersection requires the *union* of the explicitly not-preserved
-    // IDs and the *intersection* of the preserved IDs.
-    for (auto *ID : Arg.NotPreservedAnalysisIDs) {
-      PreservedIDs.erase(ID);
-      NotPreservedAnalysisIDs.insert(ID);
-    }
-    for (auto *ID : PreservedIDs)
-      if (!Arg.PreservedIDs.count(ID))
-        PreservedIDs.erase(ID);
-  }
-
-  /// Intersect this set with a temporary other set in place.
-  ///
-  /// This is a mutating operation on this preserved set, removing all
-  /// preserved passes which are not also preserved in the argument.
-  void intersect(PreservedAnalyses &&Arg) {
-    if (Arg.areAllPreserved())
-      return;
-    if (areAllPreserved()) {
-      *this = std::move(Arg);
-      return;
-    }
-    // The intersection requires the *union* of the explicitly not-preserved
-    // IDs and the *intersection* of the preserved IDs.
-    for (auto *ID : Arg.NotPreservedAnalysisIDs) {
-      PreservedIDs.erase(ID);
-      NotPreservedAnalysisIDs.insert(ID);
-    }
-    for (auto *ID : PreservedIDs)
-      if (!Arg.PreservedIDs.count(ID))
-        PreservedIDs.erase(ID);
-  }
-
-  /// A checker object that makes it easy to query for whether an analysis or
-  /// some set covering it is preserved.
-  class PreservedAnalysisChecker {
-    friend class PreservedAnalyses;
-
-    const PreservedAnalyses &PA;
-    AnalysisKey *const ID;
-    const bool IsAbandoned;
-
-    /// A PreservedAnalysisChecker is tied to a particular Analysis because
-    /// `preserved()` and `preservedSet()` both return false if the Analysis
-    /// was abandoned.
-    PreservedAnalysisChecker(const PreservedAnalyses &PA, AnalysisKey *ID)
-        : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {}
-
-  public:
-    /// Returns true if the checker's analysis was not abandoned and either
-    ///  - the analysis is explicitly preserved or
-    ///  - all analyses are preserved.
-    bool preserved() {
-      return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) ||
-                              PA.PreservedIDs.count(ID));
-    }
-
-    /// Return true if the checker's analysis was not abandoned, i.e. it was not
-    /// explicitly invalidated. Even if the analysis is not explicitly
-    /// preserved, if the analysis is known stateless, then it is preserved.
-    bool preservedWhenStateless() {
-      return !IsAbandoned;
-    }
-
-    /// Returns true if the checker's analysis was not abandoned and either
-    ///  - \p AnalysisSetT is explicitly preserved or
-    ///  - all analyses are preserved.
-    template <typename AnalysisSetT> bool preservedSet() {
-      AnalysisSetKey *SetID = AnalysisSetT::ID();
-      return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) ||
-                              PA.PreservedIDs.count(SetID));
-    }
-  };
-
-  /// Build a checker for this `PreservedAnalyses` and the specified analysis
-  /// type.
-  ///
-  /// You can use the returned object to query whether an analysis was
-  /// preserved. See the example in the comment on `PreservedAnalysis`.
-  template <typename AnalysisT> PreservedAnalysisChecker getChecker() const {
-    return PreservedAnalysisChecker(*this, AnalysisT::ID());
-  }
-
-  /// Build a checker for this `PreservedAnalyses` and the specified analysis
-  /// ID.
-  ///
-  /// You can use the returned object to query whether an analysis was
-  /// preserved. See the example in the comment on `PreservedAnalysis`.
-  PreservedAnalysisChecker getChecker(AnalysisKey *ID) const {
-    return PreservedAnalysisChecker(*this, ID);
-  }
-
-  /// Test whether all analyses are preserved (and none are abandoned).
-  ///
-  /// This is used primarily to optimize for the common case of a transformation
-  /// which makes no changes to the IR.
-  bool areAllPreserved() const {
-    return NotPreservedAnalysisIDs.empty() &&
-           PreservedIDs.count(&AllAnalysesKey);
-  }
-
-  /// Directly test whether a set of analyses is preserved.
-  ///
-  /// This is only true when no analyses have been explicitly abandoned.
-  template <typename AnalysisSetT> bool allAnalysesInSetPreserved() const {
-    return allAnalysesInSetPreserved(AnalysisSetT::ID());
-  }
-
-  /// Directly test whether a set of analyses is preserved.
-  ///
-  /// This is only true when no analyses have been explicitly abandoned.
-  bool allAnalysesInSetPreserved(AnalysisSetKey *SetID) const {
-    return NotPreservedAnalysisIDs.empty() &&
-           (PreservedIDs.count(&AllAnalysesKey) || PreservedIDs.count(SetID));
-  }
-
-private:
-  /// A special key used to indicate all analyses.
-  static AnalysisSetKey AllAnalysesKey;
-
-  /// The IDs of analyses and analysis sets that are preserved.
-  SmallPtrSet<void *, 2> PreservedIDs;
-
-  /// The IDs of explicitly not-preserved analyses.
-  ///
-  /// If an analysis in this set is covered by a set in `PreservedIDs`, we
-  /// consider it not-preserved. That is, `NotPreservedAnalysisIDs` always
-  /// "wins" over analysis sets in `PreservedIDs`.
-  ///
-  /// Also, a given ID should never occur both here and in `PreservedIDs`.
-  SmallPtrSet<AnalysisKey *, 2> NotPreservedAnalysisIDs;
-};
-
 // Forward declare the analysis manager template.
 template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
 
@@ -572,8 +272,7 @@ class PassManager : public PassInfoMixin<
       std::enable_if_t<!std::is_same<PassT, PassManager>::value>
       addPass(PassT &&Pass) {
     using PassModelT =
-        detail::PassModel<IRUnitT, PassT, PreservedAnalyses, AnalysisManagerT,
-                          ExtraArgTs...>;
+        detail::PassModel<IRUnitT, PassT, AnalysisManagerT, ExtraArgTs...>;
     // Do not use make_unique or emplace_back, they cause too many template
     // instantiations, causing terrible compile times.
     Passes.push_back(std::unique_ptr<PassConceptT>(
@@ -652,11 +351,9 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
 
 private:
   // Now that we've defined our invalidator, we can define the concept types.
-  using ResultConceptT =
-      detail::AnalysisResultConcept<IRUnitT, PreservedAnalyses, Invalidator>;
+  using ResultConceptT = detail::AnalysisResultConcept<IRUnitT, Invalidator>;
   using PassConceptT =
-      detail::AnalysisPassConcept<IRUnitT, PreservedAnalyses, Invalidator,
-                                  ExtraArgTs...>;
+      detail::AnalysisPassConcept<IRUnitT, Invalidator, ExtraArgTs...>;
 
   /// List of analysis pass IDs and associated concept pointers.
   ///
@@ -708,7 +405,7 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
     bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) {
       using ResultModelT =
           detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
-                                      PreservedAnalyses, Invalidator>;
+                                      Invalidator>;
 
       return invalidateImpl<ResultModelT>(PassT::ID(), IR, PA);
     }
@@ -808,7 +505,7 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
 
     using ResultModelT =
         detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
-                                    PreservedAnalyses, Invalidator>;
+                                    Invalidator>;
 
     return static_cast<ResultModelT &>(ResultConcept).Result;
   }
@@ -829,7 +526,7 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
 
     using ResultModelT =
         detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
-                                    PreservedAnalyses, Invalidator>;
+                                    Invalidator>;
 
     return &static_cast<ResultModelT *>(ResultConcept)->Result;
   }
@@ -865,8 +562,7 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager {
   bool registerPass(PassBuilderT &&PassBuilder) {
     using PassT = decltype(PassBuilder());
     using PassModelT =
-        detail::AnalysisPassModel<IRUnitT, PassT, PreservedAnalyses,
-                                  Invalidator, ExtraArgTs...>;
+        detail::AnalysisPassModel<IRUnitT, PassT, Invalidator, ExtraArgTs...>;
 
     auto &PassPtr = AnalysisPasses[PassT::ID()];
     if (PassPtr)
@@ -1247,8 +943,7 @@ ModuleToFunctionPassAdaptor
 createModuleToFunctionPassAdaptor(FunctionPassT &&Pass,
                                   bool EagerlyInvalidate = false) {
   using PassModelT =
-      detail::PassModel<Function, FunctionPassT, PreservedAnalyses,
-                        FunctionAnalysisManager>;
+      detail::PassModel<Function, FunctionPassT, FunctionAnalysisManager>;
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.
   return ModuleToFunctionPassAdaptor(
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index bcfdcb8206c45..4ada6ee5dd683 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -19,6 +19,7 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Analysis.h"
 #include "llvm/Support/raw_ostream.h"
 #include <memory>
 #include <utility>
@@ -65,8 +66,8 @@ struct PassConcept {
 /// Can be instantiated for any object which provides a \c run method accepting
 /// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
 /// be a copyable object.
-template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
-          typename AnalysisManagerT, typename... ExtraArgTs>
+template <typename IRUnitT, typename PassT, typename AnalysisManagerT,
+          typename... ExtraArgTs>
 struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
   explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
   // We have to explicitly define all the special member functions because MSVC
@@ -84,8 +85,8 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
     return *this;
   }
 
-  PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
-                         ExtraArgTs... ExtraArgs) override {
+  PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
+                        ExtraArgTs... ExtraArgs) override {
     return Pass.run(IR, AM, ExtraArgs...);
   }
 
@@ -120,7 +121,7 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
 ///
 /// This concept is parameterized over the IR unit that this result pertains
 /// to.
-template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT>
+template <typename IRUnitT, typename InvalidatorT>
 struct AnalysisResultConcept {
   virtual ~AnalysisResultConcept() = default;
 
@@ -139,7 +140,7 @@ struct AnalysisResultConcept {
   /// them. See the documentation in the \c AnalysisManager for more details.
   ///
   /// \returns true if the result is indeed invalid (the default).
-  virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
+  virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
                           InvalidatorT &Inv) = 0;
 };
 
@@ -186,7 +187,7 @@ template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
 /// an invalidation handler. It is only selected when the invalidation handler
 /// is not part of the ResultT's interface.
 template <typename IRUnitT, typename PassT, typename ResultT,
-          typename PreservedAnalysesT, typename InvalidatorT,
+          typename InvalidatorT,
           bool HasInvalidateHandler =
               ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
 struct AnalysisResultModel;
@@ -194,10 +195,9 @@ struct AnalysisResultModel;
 /// Specialization of \c AnalysisResultModel which provides the default
 /// invalidate functionality.
 template <typename IRUnitT, typename PassT, typename ResultT,
-          typename PreservedAnalysesT, typename InvalidatorT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
-                           InvalidatorT, false>
-    : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
+          typename InvalidatorT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, InvalidatorT, false>
+    : AnalysisResultConcept<IRUnitT, InvalidatorT> {
   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
   // We have to explicitly define all the special member functions because MSVC
   // refuses to generate them.
@@ -220,7 +220,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
   // FIXME: We should actually use two different concepts for analysis results
   // rather than two different models, and avoid the indirect function call for
   // ones that use the trivial behavior.
-  bool invalidate(IRUnitT &, const PreservedAnalysesT &PA,
+  bool invalidate(IRUnitT &, const PreservedAnalyses &PA,
                   InvalidatorT &) override {
     auto PAC = PA.template getChecker<PassT>();
     return !PAC.preserved() &&
@@ -233,10 +233,9 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
 /// Specialization of \c AnalysisResultModel which delegates invalidate
 /// handling to \c ResultT.
 template <typename IRUnitT, typename PassT, typename ResultT,
-          typename PreservedAnalysesT, typename InvalidatorT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
-                           InvalidatorT, true>
-    : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
+          typename InvalidatorT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, InvalidatorT, true>
+    : AnalysisResultConcept<IRUnitT, InvalidatorT> {
   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
   // We have to explicitly define all the special member functions because MSVC
   // refuses to generate them.
@@ -255,7 +254,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
   }
 
   /// The model delegates to the \c ResultT method.
-  bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
+  bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
                   InvalidatorT &Inv) override {
     return Result.invalidate(IR, PA, Inv);
   }
@@ -267,16 +266,14 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
 ///
 /// This concept is parameterized over the IR unit that it can run over and
 /// produce an analysis result.
-template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT,
-          typename... ExtraArgTs>
+template <typename IRUnitT, typename InvalidatorT, typename... ExtraArgTs>
 struct AnalysisPassConcept {
   virtual ~AnalysisPassConcept() = default;
 
   /// Method to run this analysis over a unit of IR.
   /// \returns A unique_ptr to the analysis result object to be queried by
   /// users.
-  virtual std::unique_ptr<
-      AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
+  virtual std::unique_ptr<AnalysisResultConcept<IRUnitT, InvalidatorT>>
   run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
       ExtraArgTs... ExtraArgs) = 0;
 
@@ -289,10 +286,10 @@ struct AnalysisPassConcept {
 /// Can wrap any type which implements a suitable \c run method. The method
 /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
 /// and produce an object which can be wrapped in a \c AnalysisResultModel.
-template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
-          typename InvalidatorT, typename... ExtraArgTs>
-struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
-                                               InvalidatorT, ExtraArgTs...> {
+template <typename IRUnitT, typename PassT, typename InvalidatorT,
+          typename... ExtraArgTs>
+struct AnalysisPassModel
+    : AnalysisPassConcept<IRUnitT, InvalidatorT, ExtraArgTs...> {
   explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
   // We have to explicitly define all the special member functions because MSVC
   // refuses to generate them.
@@ -311,14 +308,12 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
 
   // FIXME: Replace PassT::Result with type traits when we use C++11.
   using ResultModelT =
-      AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
-                          PreservedAnalysesT, InvalidatorT>;
+      AnalysisResultModel<IRUnitT, PassT, typename PassT::Result, InvalidatorT>;
 
   /// The model delegates to the \c PassT::run method.
   ///
   /// The return is wrapped in an \c AnalysisResultModel.
-  std::unique_ptr<
-      AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
+  std::unique_ptr<AnalysisResultConcept<IRUnitT, InvalidatorT>>
   run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
       ExtraArgTs... ExtraArgs) override {
     return std::make_unique<ResultModelT>(
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
index c8c4d5e9a5392..6aab1f98e6781 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h
@@ -106,7 +106,7 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
       std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value>
       addPass(PassT &&Pass) {
     using LoopPassModelT =
-        detail::PassModel<Loop, PassT, PreservedAnalyses, LoopAnalysisManager,
+        detail::PassModel<Loop, PassT, LoopAnalysisManager,
                           LoopStandardAnalysisResults &, LPMUpdater &>;
     IsLoopNestPass.push_back(false);
     // Do not use make_unique or emplace_back, they cause too many template
@@ -120,9 +120,8 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
       std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value>
       addPass(PassT &&Pass) {
     using LoopNestPassModelT =
-        detail::PassModel<LoopNest, PassT, PreservedAnalyses,
-                          LoopAnalysisManager, LoopStandardAnalysisResults &,
-                          LPMUpdater &>;
+        detail::PassModel<LoopNest, PassT, LoopAnalysisManager,
+                          LoopStandardAnalysisResults &, LPMUpdater &>;
     IsLoopNestPass.push_back(true);
     // Do not use make_unique or emplace_back, they cause too many template
     // instantiations, causing terrible compile times.
@@ -138,9 +137,8 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
       std::enable_if_t<is_detected<HasRunOnLoopT, PassT>::value>
       addPass(RepeatedPass<PassT> &&Pass) {
     using RepeatedLoopPassModelT =
-        detail::PassModel<Loop, RepeatedPass<PassT>, PreservedAnalyses,
-                          LoopAnalysisManager, LoopStandardAnalysisResults &,
-                          LPMUpdater &>;
+        detail::PassModel<Loop, RepeatedPass<PassT>, LoopAnalysisManager,
+                          LoopStandardAnalysisResults &, LPMUpdater &>;
     IsLoopNestPass.push_back(false);
     // Do not use make_unique or emplace_back, they cause too many template
     // instantiations, causing terrible compile times.
@@ -153,9 +151,8 @@ class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
       std::enable_if_t<!is_detected<HasRunOnLoopT, PassT>::value>
       addPass(RepeatedPass<PassT> &&Pass) {
     using RepeatedLoopNestPassModelT =
-        detail::PassModel<LoopNest, RepeatedPass<PassT>, PreservedAnalyses,
-                          LoopAnalysisManager, LoopStandardAnalysisResults &,
-                          LPMUpdater &>;
+        detail::PassModel<LoopNest, RepeatedPass<PassT>, LoopAnalysisManager,
+                          LoopStandardAnalysisResults &, LPMUpdater &>;
     IsLoopNestPass.push_back(true);
     // Do not use make_unique or emplace_back, they cause too many template
     // instantiations, causing terrible compile times.
@@ -482,7 +479,7 @@ createFunctionToLoopPassAdaptor(LoopPassT &&Pass, bool UseMemorySSA = false,
                                 bool UseBlockFrequencyInfo = false,
                                 bool UseBranchProbabilityInfo = false) {
   using PassModelT =
-      detail::PassModel<Loop, LoopPassT, PreservedAnalyses, LoopAnalysisManager,
+      detail::PassModel<Loop, LoopPassT, LoopAnalysisManager,
                         LoopStandardAnalysisResults &, LPMUpdater &>;
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.
@@ -503,9 +500,8 @@ createFunctionToLoopPassAdaptor(LoopNestPassT &&Pass, bool UseMemorySSA = false,
   LoopPassManager LPM;
   LPM.addPass(std::forward<LoopNestPassT>(Pass));
   using PassModelT =
-      detail::PassModel<Loop, LoopPassManager, PreservedAnalyses,
-                        LoopAnalysisManager, LoopStandardAnalysisResults &,
-                        LPMUpdater &>;
+      detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
+                        LoopStandardAnalysisResults &, LPMUpdater &>;
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.
   return FunctionToLoopPassAdaptor(
@@ -524,9 +520,8 @@ createFunctionToLoopPassAdaptor<LoopPassManager>(
   // Check if LPM contains any loop pass and if it does not, returns an adaptor
   // in loop-nest mode.
   using PassModelT =
-      detail::PassModel<Loop, LoopPassManager, PreservedAnalyses,
-                        LoopAnalysisManager, LoopStandardAnalysisResults &,
-                        LPMUpdater &>;
+      detail::PassModel<Loop, LoopPassManager, LoopAnalysisManager,
+                        LoopStandardAnalysisResults &, LPMUpdater &>;
   bool LoopNestMode = (LPM.getNumLoopPasses() == 0);
   // Do not use make_unique, it causes too many template instantiations,
   // causing terrible compile times.

>From 100fc8cb4148ec18c4db7c3c383a403b5205d8ad Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Fri, 2 Feb 2024 04:06:28 +0000
Subject: [PATCH 2/2] Rewrite codegen new PM

---
 .../include/llvm/CodeGen/MachinePassManager.h | 240 ++++++++++--------
 llvm/include/llvm/Passes/CodeGenPassBuilder.h |  71 ++++--
 llvm/include/llvm/Passes/PassBuilder.h        |   3 +-
 llvm/include/llvm/Target/TargetMachine.h      |   8 +-
 llvm/lib/CodeGen/MachinePassManager.cpp       | 164 ++++++------
 llvm/lib/Passes/PassBuilder.cpp               |  10 +-
 llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp |   9 +-
 llvm/lib/Target/X86/X86TargetMachine.h        |   7 +-
 llvm/tools/llc/NewPMDriver.cpp                |  84 ++----
 9 files changed, 300 insertions(+), 296 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index a0ad7d7a95a28..68d9679396e60 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -16,8 +16,6 @@
 // their respective analysis managers such as ModuleAnalysisManager and
 // FunctionAnalysisManager.
 //
-// TODO: Add MachineFunctionProperties support.
-//
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
@@ -25,11 +23,11 @@
 
 #include "llvm/ADT/FunctionExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/IR/PassManager.h"
+#include "llvm/IR/PassManagerInternal.h"
 #include "llvm/Support/Error.h"
 
-#include <map>
-
 namespace llvm {
 class Module;
 class Function;
@@ -43,7 +41,15 @@ extern template class AnalysisManager<MachineFunction>;
 /// automatically mixes in \c PassInfoMixin.
 template <typename DerivedT>
 struct MachinePassInfoMixin : public PassInfoMixin<DerivedT> {
-  // TODO: Add MachineFunctionProperties support.
+  static MachineFunctionProperties getRequiredProperties() {
+    return MachineFunctionProperties();
+  }
+  static MachineFunctionProperties getSetProperties() {
+    return MachineFunctionProperties();
+  }
+  static MachineFunctionProperties getClearedProperties() {
+    return MachineFunctionProperties();
+  }
 };
 
 /// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
@@ -109,7 +115,120 @@ class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
   ModuleAnalysisManager *MAM;
 };
 
-extern template class PassManager<MachineFunction>;
+namespace detail {
+struct MachinePassConcept
+    : PassConcept<MachineFunction, MachineFunctionAnalysisManager> {
+  virtual MachineFunctionProperties getRequiredProperties() const = 0;
+  virtual MachineFunctionProperties getSetProperties() const = 0;
+  virtual MachineFunctionProperties getClearedProperties() const = 0;
+};
+
+template <typename PassT> struct MachinePassModel : MachinePassConcept {
+  explicit MachinePassModel(PassT Pass) : Pass(std::move(Pass)) {}
+  // We have to explicitly define all the special member functions because MSVC
+  // refuses to generate them.
+  MachinePassModel(const MachinePassModel &Arg) : Pass(Arg.Pass) {}
+  MachinePassModel(MachinePassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+
+  friend void swap(MachinePassModel &LHS, MachinePassModel &RHS) {
+    using std::swap;
+    swap(LHS.Pass, RHS.Pass);
+  }
+
+  MachinePassModel &operator=(MachinePassModel RHS) {
+    swap(*this, RHS);
+    return *this;
+  }
+
+  PreservedAnalyses run(MachineFunction &IR,
+                        MachineFunctionAnalysisManager &AM) override {
+    return Pass.run(IR, AM);
+  }
+
+  void printPipeline(
+      raw_ostream &OS,
+      function_ref<StringRef(StringRef)> MapClassName2PassName) override {
+    Pass.printPipeline(OS, MapClassName2PassName);
+  }
+
+  StringRef name() const override { return PassT::name(); }
+
+  template <typename T>
+  using has_required_t = decltype(std::declval<T &>().isRequired());
+
+  template <typename T>
+  static std::enable_if_t<is_detected<has_required_t, T>::value, bool>
+  passIsRequiredImpl() {
+    return T::isRequired();
+  }
+  template <typename T>
+  static std::enable_if_t<!is_detected<has_required_t, T>::value, bool>
+  passIsRequiredImpl() {
+    return false;
+  }
+
+  bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
+
+  MachineFunctionProperties getRequiredProperties() const override {
+    return PassT::getRequiredProperties();
+  }
+  MachineFunctionProperties getSetProperties() const override {
+    return PassT::getSetProperties();
+  }
+  MachineFunctionProperties getClearedProperties() const override {
+    return PassT::getClearedProperties();
+  }
+
+  PassT Pass;
+};
+} // namespace detail
+
+using MachineFunctionAnalysisManagerModuleProxy =
+    InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Module>;
+
+template <>
+bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
+    Module &M, const PreservedAnalyses &PA,
+    ModuleAnalysisManager::Invalidator &Inv);
+extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
+                                                Module>;
+
+extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
+                                                MachineFunction>;
+/// Provide the \c ModuleAnalysisManager to \c Function proxy.
+using ModuleAnalysisManagerMachineFunctionProxy =
+    OuterAnalysisManagerProxy<ModuleAnalysisManager, MachineFunction>;
+
+class ModuleToMachineFunctionPassAdaptor
+    : public PassInfoMixin<ModuleToMachineFunctionPassAdaptor> {
+  using MachinePassConcept = detail::MachinePassConcept;
+
+public:
+  explicit ModuleToMachineFunctionPassAdaptor(
+      std::unique_ptr<MachinePassConcept> Pass)
+      : Pass(std::move(Pass)) {}
+
+  /// Runs the function pass across every function in the module.
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+  void printPipeline(raw_ostream &OS,
+                     function_ref<StringRef(StringRef)> MapClassName2PassName);
+
+  static bool isRequired() { return true; }
+
+private:
+  std::unique_ptr<MachinePassConcept> Pass;
+};
+
+template <typename MachineFunctionPassT>
+ModuleToMachineFunctionPassAdaptor
+createModuleToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) {
+  using PassModelT = detail::MachinePassModel<MachineFunctionPassT>;
+  // Do not use make_unique, it causes too many template instantiations,
+  // causing terrible compile times.
+  return ModuleToMachineFunctionPassAdaptor(
+      std::unique_ptr<detail::MachinePassConcept>(
+          new PassModelT(std::forward<MachineFunctionPassT>(Pass))));
+}
 
 /// MachineFunctionPassManager adds/removes below features to/from the base
 /// PassManager template instantiation.
@@ -139,14 +258,13 @@ extern template class PassManager<MachineFunction>;
 /// - Support codegening in the SCC order. Users include interprocedural
 ///   register allocation (IPRA).
 class MachineFunctionPassManager
-    : public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
-  using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
+    : public MachinePassInfoMixin<MachineFunctionPassManager> {
+  using MachinePassConcept = detail::MachinePassConcept;
+  template <typename T> using MachinePassModel = detail::MachinePassModel<T>;
 
 public:
   MachineFunctionPassManager(bool RequireCodeGenSCCOrder = false,
-                             bool VerifyMachineFunction = false)
-      : RequireCodeGenSCCOrder(RequireCodeGenSCCOrder),
-        VerifyMachineFunction(VerifyMachineFunction) {}
+                             bool VerifyMachineFunction = false) {}
   MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
   MachineFunctionPassManager &
   operator=(MachineFunctionPassManager &&) = default;
@@ -158,103 +276,19 @@ class MachineFunctionPassManager
   /// that we don't yet have the use cases of compositing two instances of
   /// machine pass managers, or compositing machine pass managers with other
   /// types of pass managers.
-  Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &MFAM);
 
   template <typename PassT> void addPass(PassT &&Pass) {
-    Base::addPass(std::forward<PassT>(Pass));
-    PassConceptT *P = Passes.back().get();
-    addDoInitialization<PassT>(P);
-    addDoFinalization<PassT>(P);
-
-    // Add machine module pass.
-    addRunOnModule<PassT>(P);
+    Passes.push_back(std::unique_ptr<MachinePassConcept>(
+        new MachinePassModel<PassT>(std::forward<PassT>(Pass))));
   }
 
-private:
-  template <typename PassT>
-  using has_init_t = decltype(std::declval<PassT &>().doInitialization(
-      std::declval<Module &>(),
-      std::declval<MachineFunctionAnalysisManager &>()));
-
-  template <typename PassT>
-  std::enable_if_t<!is_detected<has_init_t, PassT>::value>
-  addDoInitialization(PassConceptT *Pass) {}
-
-  template <typename PassT>
-  std::enable_if_t<is_detected<has_init_t, PassT>::value>
-  addDoInitialization(PassConceptT *Pass) {
-    using PassModelT = detail::PassModel<MachineFunction, PassT,
-                                         MachineFunctionAnalysisManager>;
-    auto *P = static_cast<PassModelT *>(Pass);
-    InitializationFuncs.emplace_back(
-        [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
-          return P->Pass.doInitialization(M, MFAM);
-        });
-  }
-
-  template <typename PassT>
-  using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
-      std::declval<Module &>(),
-      std::declval<MachineFunctionAnalysisManager &>()));
-
-  template <typename PassT>
-  std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
-  addDoFinalization(PassConceptT *Pass) {}
+  /// Returns if the pass manager contains any passes.
+  bool isEmpty() const { return Passes.empty(); }
 
-  template <typename PassT>
-  std::enable_if_t<is_detected<has_fini_t, PassT>::value>
-  addDoFinalization(PassConceptT *Pass) {
-    using PassModelT = detail::PassModel<MachineFunction, PassT,
-                                         MachineFunctionAnalysisManager>;
-    auto *P = static_cast<PassModelT *>(Pass);
-    FinalizationFuncs.emplace_back(
-        [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
-          return P->Pass.doFinalization(M, MFAM);
-        });
-  }
-
-  template <typename PassT>
-  using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
-      std::declval<Module &>(),
-      std::declval<MachineFunctionAnalysisManager &>()));
-
-  template <typename PassT>
-  using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
-      std::declval<MachineFunction &>(),
-      std::declval<MachineFunctionAnalysisManager &>()));
-
-  template <typename PassT>
-  std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
-  addRunOnModule(PassConceptT *Pass) {}
-
-  template <typename PassT>
-  std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
-  addRunOnModule(PassConceptT *Pass) {
-    static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
-                  "machine module pass needs to define machine function pass "
-                  "api. sorry.");
-
-    using PassModelT = detail::PassModel<MachineFunction, PassT,
-                                         MachineFunctionAnalysisManager>;
-    auto *P = static_cast<PassModelT *>(Pass);
-    MachineModulePasses.emplace(
-        Passes.size() - 1,
-        [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
-          return P->Pass.run(M, MFAM);
-        });
-  }
-
-  using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
-  SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
-  SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
-
-  using PassIndex = decltype(Passes)::size_type;
-  std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
-
-  // Run codegen in the SCC order.
-  bool RequireCodeGenSCCOrder;
-
-  bool VerifyMachineFunction;
+private:
+  std::vector<std::unique_ptr<detail::MachinePassConcept>> Passes;
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
index 2c8073ad551b7..280dd2a906ed9 100644
--- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h
@@ -86,13 +86,9 @@ namespace llvm {
     }                                                                          \
   };
 #define DUMMY_MACHINE_MODULE_PASS(NAME, PASS_NAME, CONSTRUCTOR)                \
-  struct PASS_NAME : public MachinePassInfoMixin<PASS_NAME> {                  \
+  struct PASS_NAME : public PassInfoMixin<PASS_NAME> {                         \
     template <typename... Ts> PASS_NAME(Ts &&...) {}                           \
-    Error run(Module &, MachineFunctionAnalysisManager &) {                    \
-      return Error::success();                                                 \
-    }                                                                          \
-    PreservedAnalyses run(MachineFunction &,                                   \
-                          MachineFunctionAnalysisManager &) {                  \
+    PreservedAnalyses run(Module &, ModuleAnalysisManager &) {                 \
       llvm_unreachable("this api is to make new PM api happy");                \
     }                                                                          \
   };
@@ -143,8 +139,8 @@ template <typename DerivedT> class CodeGenPassBuilder {
       Opt.OptimizeRegAlloc = getOptLevel() != CodeGenOptLevel::None;
   }
 
-  Error buildPipeline(ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
-                      raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+  Error buildPipeline(ModulePassManager &MPM, raw_pwrite_stream &Out,
+                      raw_pwrite_stream *DwoOut,
                       CodeGenFileType FileType) const;
 
   void registerModuleAnalyses(ModuleAnalysisManager &) const;
@@ -171,6 +167,11 @@ template <typename DerivedT> class CodeGenPassBuilder {
   using is_function_pass_t = decltype(std::declval<PassT &>().run(
       std::declval<Function &>(), std::declval<FunctionAnalysisManager &>()));
 
+  template <typename PassT>
+  using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
+      std::declval<MachineFunction &>(),
+      std::declval<MachineFunctionAnalysisManager &>()));
+
   // Function object to maintain state while adding codegen IR passes.
   class AddIRPass {
   public:
@@ -218,31 +219,46 @@ template <typename DerivedT> class CodeGenPassBuilder {
   // Function object to maintain state while adding codegen machine passes.
   class AddMachinePass {
   public:
-    AddMachinePass(MachineFunctionPassManager &PM, const DerivedT &PB)
-        : PM(PM), PB(PB) {}
+    AddMachinePass(ModulePassManager &MPM, const DerivedT &PB)
+        : MPM(MPM), PB(PB) {}
+    ~AddMachinePass() {
+      if (!MFPM.isEmpty())
+        MPM.addPass(createModuleToMachineFunctionPassAdaptor(std::move(MFPM)));
+    }
 
-    template <typename PassT> void operator()(PassT &&Pass) {
-      if (!PB.runBeforeAdding(PassT::name()))
+    template <typename PassT>
+    void operator()(PassT &&Pass, StringRef Name = PassT::name()) {
+      static_assert((is_detected<is_machine_function_pass_t, PassT>::value ||
+                     is_detected<is_module_pass_t, PassT>::value) &&
+                    "Only module pass and function pass are supported.");
+
+      if (!PB.runBeforeAdding(Name))
         return;
 
-      PM.addPass(std::forward<PassT>(Pass));
+      // Add Function Pass
+      if constexpr (is_detected<is_machine_function_pass_t, PassT>::value) {
+        MFPM.addPass(std::forward<PassT>(Pass));
 
-      for (auto &C : PB.AfterCallbacks)
-        C(PassT::name());
-    }
+        for (auto &C : PB.AfterCallbacks)
+          C(Name);
+      } else {
+        // Add Module Pass
+        if (!MFPM.isEmpty()) {
+          MPM.addPass(
+              createModuleToMachineFunctionPassAdaptor(std::move(MFPM)));
+          MFPM = MachineFunctionPassManager();
+        }
 
-    template <typename PassT> void insertPass(StringRef PassName, PassT Pass) {
-      PB.AfterCallbacks.emplace_back(
-          [this, PassName, Pass = std::move(Pass)](StringRef Name) {
-            if (PassName == Name)
-              this->PM.addPass(std::move(Pass));
-          });
-    }
+        MPM.addPass(std::forward<PassT>(Pass));
 
-    MachineFunctionPassManager releasePM() { return std::move(PM); }
+        for (auto &C : PB.AfterCallbacks)
+          C(Name);
+      }
+    }
 
   private:
-    MachineFunctionPassManager &PM;
+    ModulePassManager &MPM;
+    MachineFunctionPassManager MFPM;
     const DerivedT &PB;
   };
 
@@ -497,8 +513,7 @@ template <typename DerivedT> class CodeGenPassBuilder {
 
 template <typename Derived>
 Error CodeGenPassBuilder<Derived>::buildPipeline(
-    ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
-    raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+    ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
     CodeGenFileType FileType) const {
   auto StartStopInfo = TargetPassConfig::getStartStopInfo(*PIC);
   if (!StartStopInfo)
@@ -510,7 +525,7 @@ Error CodeGenPassBuilder<Derived>::buildPipeline(
   addIRPass(RequireAnalysisPass<CollectorMetadataAnalysis, Module>());
   addISelPasses(addIRPass);
 
-  AddMachinePass addPass(MFPM, derived());
+  AddMachinePass addPass(MPM, derived());
   if (auto Err = addCoreISelPasses(addPass))
     return std::move(Err);
 
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 10c5b7c00bae3..92190e0269ae6 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -133,7 +133,8 @@ class PassBuilder {
   void crossRegisterProxies(LoopAnalysisManager &LAM,
                             FunctionAnalysisManager &FAM,
                             CGSCCAnalysisManager &CGAM,
-                            ModuleAnalysisManager &MAM);
+                            ModuleAnalysisManager &MAM,
+                            MachineFunctionAnalysisManager *MFAM = nullptr);
 
   /// Registers all available module analysis passes.
   ///
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index a522a12299bb0..7d4f3458dd78a 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -455,11 +455,9 @@ class LLVMTargetMachine : public TargetMachine {
                       bool DisableVerify = true,
                       MachineModuleInfoWrapperPass *MMIWP = nullptr) override;
 
-  virtual Error buildCodeGenPipeline(ModulePassManager &,
-                                     MachineFunctionPassManager &,
-                                     MachineFunctionAnalysisManager &,
-                                     raw_pwrite_stream &, raw_pwrite_stream *,
-                                     CodeGenFileType, CGPassBuilderOption,
+  virtual Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &,
+                                     raw_pwrite_stream *, CodeGenFileType,
+                                     CGPassBuilderOption,
                                      PassInstrumentationCallbacks *) {
     return make_error<StringError>("buildCodeGenPipeline is not overridden",
                                    inconvertibleErrorCode());
diff --git a/llvm/lib/CodeGen/MachinePassManager.cpp b/llvm/lib/CodeGen/MachinePassManager.cpp
index 0770eba660b45..78cc622dbe9e6 100644
--- a/llvm/lib/CodeGen/MachinePassManager.cpp
+++ b/llvm/lib/CodeGen/MachinePassManager.cpp
@@ -11,7 +11,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/MachinePassManager.h"
-#include "llvm/CodeGen/FreeMachineFunction.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/IR/PassManagerImpl.h"
@@ -19,99 +18,96 @@
 using namespace llvm;
 
 namespace llvm {
-template class AllAnalysesOn<MachineFunction>;
+// template class AllAnalysesOn<MachineFunction>;
 template class AnalysisManager<MachineFunction>;
-template class PassManager<MachineFunction>;
-
-Error MachineFunctionPassManager::run(Module &M,
-                                      MachineFunctionAnalysisManager &MFAM) {
-  // MachineModuleAnalysis is a module analysis pass that is never invalidated
-  // because we don't run any module pass in codegen pipeline. This is very
-  // important because the codegen state is stored in MMI which is the analysis
-  // result of MachineModuleAnalysis. MMI should not be recomputed.
-  auto &MMI = MFAM.getResult<MachineModuleAnalysis>(M);
-
-  (void)RequireCodeGenSCCOrder;
-  assert(!RequireCodeGenSCCOrder && "not implemented");
-
-  // M is unused here
-  PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(M);
-
-  // Add a PIC to verify machine functions.
-  if (VerifyMachineFunction) {
-    // No need to pop this callback later since MIR pipeline is flat which means
-    // current pipeline is the top-level pipeline. Callbacks are not used after
-    // current pipeline.
-    PI.pushBeforeNonSkippedPassCallback([&MFAM](StringRef PassID, Any IR) {
-      assert(llvm::any_cast<const MachineFunction *>(&IR));
-      const MachineFunction *MF = llvm::any_cast<const MachineFunction *>(IR);
-      assert(MF && "Machine function should be valid for printing");
-      std::string Banner = std::string("After ") + std::string(PassID);
-      verifyMachineFunction(&MFAM, Banner, *MF);
-    });
+// template class PassManager<MachineFunction>;
+template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
+                                         Module>;
+template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
+                                         MachineFunction>;
+
+template <>
+bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
+    Module &M, const PreservedAnalyses &PA,
+    ModuleAnalysisManager::Invalidator &Inv) {
+  // If literally everything is preserved, we're done.
+  if (PA.areAllPreserved())
+    return false; // This is still a valid proxy.
+
+  // If this proxy isn't marked as preserved, then even if the result remains
+  // valid, the key itself may no longer be valid, so we clear everything.
+  //
+  // Note that in order to preserve this proxy, a module pass must ensure that
+  // the FAM has been completely updated to handle the deletion of functions.
+  // Specifically, any FAM-cached results for those functions need to have been
+  // forcibly cleared. When preserved, this proxy will only invalidate results
+  // cached on functions *still in the module* at the end of the module pass.
+  auto PAC = PA.getChecker<MachineFunctionAnalysisManagerModuleProxy>();
+  if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
+    InnerAM->clear();
+    return true;
   }
 
-  for (auto &F : InitializationFuncs) {
-    if (auto Err = F(M, MFAM))
-      return Err;
+  // FIXME: be more precise
+  if (!PA.allAnalysesInSetPreserved<AllAnalysesOn<MachineFunction>>()) {
+    InnerAM->clear();
+    return true;
   }
 
-  unsigned Idx = 0;
-  size_t Size = Passes.size();
-  do {
-    // Run machine module passes
-    for (; MachineModulePasses.count(Idx) && Idx != Size; ++Idx) {
-      if (!PI.runBeforePass<Module>(*Passes[Idx], M))
-        continue;
-      if (auto Err = MachineModulePasses.at(Idx)(M, MFAM))
-        return Err;
-      PI.runAfterPass(*Passes[Idx], M, PreservedAnalyses::all());
-    }
-
-    // Finish running all passes.
-    if (Idx == Size)
-      break;
-
-    // Run machine function passes
-
-    // Get index range of machine function passes.
-    unsigned Begin = Idx;
-    for (; !MachineModulePasses.count(Idx) && Idx != Size; ++Idx)
-      ;
-
-    for (Function &F : M) {
-      // Do not codegen any 'available_externally' functions at all, they have
-      // definitions outside the translation unit.
-      if (F.hasAvailableExternallyLinkage())
-        continue;
-
-      MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
-
-      for (unsigned I = Begin, E = Idx; I != E; ++I) {
-        auto *P = Passes[I].get();
-
-        if (!PI.runBeforePass<MachineFunction>(*P, MF))
-          continue;
+  // Return false to indicate that this result is still a valid proxy.
+  return false;
+}
 
-        // TODO: EmitSizeRemarks
-        PreservedAnalyses PassPA = P->run(MF, MFAM);
+PreservedAnalyses
+ModuleToMachineFunctionPassAdaptor ::run(Module &M, ModuleAnalysisManager &AM) {
+  auto &MMI = AM.getResult<MachineModuleAnalysis>(M);
+  MachineFunctionAnalysisManager &MFAM =
+      AM.getResult<MachineFunctionAnalysisManagerModuleProxy>(M).getManager();
+  PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M);
+  PreservedAnalyses PA = PreservedAnalyses::all();
+  for (Function &F : M) {
+    // Do not codegen any 'available_externally' functions at all, they have
+    // definitions outside the translation unit.
+    if (F.hasAvailableExternallyLinkage())
+      continue;
+
+    MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
+
+    if (!PI.runBeforePass<MachineFunction>(*Pass, MF))
+      continue;
+    PreservedAnalyses PassPA = Pass->run(MF, MFAM);
+    MFAM.invalidate(MF, PassPA);
+    // FIXME: MF is dangling after FreeMachineFunctionPass
+    PI.runAfterPass(*Pass, MF, PassPA);
+    PA.intersect(std::move(PassPA));
+  }
 
-        // MF is dangling after FreeMachineFunctionPass
-        if (P->name() != FreeMachineFunctionPass::name()) {
-          MFAM.invalidate(MF, PassPA);
+  return PA;
+}
 
-          PI.runAfterPass(*P, MF, PassPA);
-        }
-      }
-    }
-  } while (true);
+void ModuleToMachineFunctionPassAdaptor::printPipeline(
+    raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
+  OS << "machine-function(";
+  Pass->printPipeline(OS, MapClassName2PassName);
+  OS << ')';
+}
 
-  for (auto &F : FinalizationFuncs) {
-    if (auto Err = F(M, MFAM))
-      return Err;
+PreservedAnalyses
+MachineFunctionPassManager::run(MachineFunction &MF,
+                                MachineFunctionAnalysisManager &MFAM) {
+  PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(MF);
+  PreservedAnalyses PA = PreservedAnalyses::all();
+  for (auto &Pass : Passes) {
+    if (!PI.runBeforePass<MachineFunction>(*Pass, MF))
+      continue;
+
+    PreservedAnalyses PassPA = Pass->run(MF, MFAM);
+    // FIXME: MF is dangling after FreeMachineFunctionPass
+    MFAM.invalidate(MF, PassPA);
+    PI.runAfterPass(*Pass, MF, PassPA);
+    PA.intersect(std::move(PassPA));
   }
-
-  return Error::success();
+  return PA;
 }
 
 } // namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index c934ec42f6eb1..4b441674f2538 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -89,6 +89,7 @@
 #include "llvm/CodeGen/InterleavedLoadCombine.h"
 #include "llvm/CodeGen/JMCInstrumenter.h"
 #include "llvm/CodeGen/LowerEmuTLS.h"
+#include "llvm/CodeGen/MachinePassManager.h"
 #include "llvm/CodeGen/SafeStack.h"
 #include "llvm/CodeGen/SelectOptimize.h"
 #include "llvm/CodeGen/ShadowStackGCLowering.h"
@@ -1939,7 +1940,8 @@ Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
 void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,
                                        FunctionAnalysisManager &FAM,
                                        CGSCCAnalysisManager &CGAM,
-                                       ModuleAnalysisManager &MAM) {
+                                       ModuleAnalysisManager &MAM,
+                                       MachineFunctionAnalysisManager *MFAM) {
   MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
   MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
   CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
@@ -1947,6 +1949,12 @@ void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,
   FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
   FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); });
   LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); });
+  if (MFAM) {
+    MAM.registerPass(
+        [&] { return MachineFunctionAnalysisManagerModuleProxy(*MFAM); });
+    MFAM->registerPass(
+        [&] { return ModuleAnalysisManagerMachineFunctionProxy(MAM); });
+  }
 }
 
 Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index 4a11dd2e31acd..a620ba911ec61 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -47,10 +47,9 @@ Error X86CodeGenPassBuilder::addInstSelector(AddMachinePass &) const {
 } // namespace
 
 Error X86TargetMachine::buildCodeGenPipeline(
-    ModulePassManager &MPM, MachineFunctionPassManager &MFPM,
-    MachineFunctionAnalysisManager &, raw_pwrite_stream &Out,
-    raw_pwrite_stream *DwoOut, CodeGenFileType FileType,
-    CGPassBuilderOption Opt, PassInstrumentationCallbacks *PIC) {
+    ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
+    CodeGenFileType FileType, CGPassBuilderOption Opt,
+    PassInstrumentationCallbacks *PIC) {
   auto CGPB = X86CodeGenPassBuilder(*this, Opt, PIC);
-  return CGPB.buildPipeline(MPM, MFPM, Out, DwoOut, FileType);
+  return CGPB.buildPipeline(MPM, Out, DwoOut, FileType);
 }
diff --git a/llvm/lib/Target/X86/X86TargetMachine.h b/llvm/lib/Target/X86/X86TargetMachine.h
index f31c971df9584..0fd3e47aaefe7 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.h
+++ b/llvm/lib/Target/X86/X86TargetMachine.h
@@ -58,10 +58,9 @@ class X86TargetMachine final : public LLVMTargetMachine {
   createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F,
                             const TargetSubtargetInfo *STI) const override;
 
-  Error buildCodeGenPipeline(ModulePassManager &, MachineFunctionPassManager &,
-                             MachineFunctionAnalysisManager &,
-                             raw_pwrite_stream &, raw_pwrite_stream *,
-                             CodeGenFileType, CGPassBuilderOption,
+  Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &,
+                             raw_pwrite_stream *, CodeGenFileType,
+                             CGPassBuilderOption,
                              PassInstrumentationCallbacks *) override;
 
   bool isJIT() const { return IsJIT; }
diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp
index 8b1c263391b9e..a9351a1a6f363 100644
--- a/llvm/tools/llc/NewPMDriver.cpp
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -89,30 +89,6 @@ bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
 
 static llvm::ExitOnError ExitOnErr;
 
-static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M,
-                      LLVMContext &Context, SmallString<0> &Buffer,
-                      ModulePassManager *MPM, ModuleAnalysisManager *MAM,
-                      MachineFunctionPassManager &MFPM,
-                      MachineFunctionAnalysisManager &MFAM) {
-  assert(M && "invalid input module!");
-
-  // Before executing passes, print the final values of the LLVM options.
-  cl::PrintOptionValues();
-
-  if (MPM) {
-    assert(MAM && "expect a ModuleAnalysisManager!");
-    MPM->run(*M, *MAM);
-  }
-
-  ExitOnErr(MFPM.run(*M, MFAM));
-
-  if (Context.getDiagHandlerPtr()->HasErrors)
-    exit(1);
-
-  if (BOS)
-    Out->os() << Buffer;
-}
-
 int llvm::compileModuleWithNewPM(
     StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
     std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
@@ -131,16 +107,6 @@ int llvm::compileModuleWithNewPM(
 
   raw_pwrite_stream *OS = &Out->os();
 
-  // Manually do the buffering rather than using buffer_ostream,
-  // so we can memcmp the contents in CompileTwice mode in future.
-  SmallString<0> Buffer;
-  std::unique_ptr<raw_svector_ostream> BOS;
-  if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
-       !Out->os().supportsSeeking())) {
-    BOS = std::make_unique<raw_svector_ostream>(Buffer);
-    OS = BOS.get();
-  }
-
   // Fetch options from TargetPassConfig
   CGPassBuilderOption Opt = getCGPassBuilderOption();
   Opt.DisableVerify = NoVerify;
@@ -156,17 +122,19 @@ int llvm::compileModuleWithNewPM(
   FunctionAnalysisManager FAM;
   CGSCCAnalysisManager CGAM;
   ModuleAnalysisManager MAM;
+  MachineFunctionAnalysisManager MFAM(FAM, MAM);
   PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
   PB.registerModuleAnalyses(MAM);
   PB.registerCGSCCAnalyses(CGAM);
   PB.registerFunctionAnalyses(FAM);
   PB.registerLoopAnalyses(LAM);
-  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+  PB.registerMachineFunctionAnalyses(MFAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM, &MFAM);
 
   FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
   MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); });
 
-  MachineFunctionAnalysisManager MFAM(FAM, MAM);
+  ModulePassManager MPM;
 
   if (!PassPipeline.empty()) {
     // Construct a custom pass pipeline that starts after instruction
@@ -177,57 +145,43 @@ int llvm::compileModuleWithNewPM(
       return 1;
     }
 
-    MachineFunctionPassManager MFPM;
-    ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline));
-    MFPM.addPass(PrintMIRPass(*OS));
-    MFPM.addPass(FreeMachineFunctionPass());
+    ExitOnErr(PB.parsePassPipeline(MPM, PassPipeline));
+    // MPM.addPass(PrintMIRPass(*OS));
 
     auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M);
     if (MIR->parseMachineFunctions(*M, MMI))
       return 1;
-
-    RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr, nullptr,
-              MFPM, MFAM);
   } else {
-    ModulePassManager MPM;
-    MachineFunctionPassManager MFPM;
-
-    ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS,
-                                          DwoOut ? &DwoOut->os() : nullptr,
-                                          FileType, Opt, &PIC));
+    ExitOnErr(LLVMTM.buildCodeGenPipeline(
+        MPM, *OS, DwoOut ? &DwoOut->os() : nullptr, FileType, Opt, &PIC));
 
     auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC);
     assert(StartStopInfo && "Expect StartStopInfo!");
     // Add IR or MIR printing pass according the pass type.
 
     if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) {
-      MFPM.addPass(PrintMIRPass(*OS));
-      MFPM.addPass(FreeMachineFunctionPass());
+      // MPM.addPass(PrintMIRPass(*OS));
     }
 
     if (PrintPipelinePasses) {
-      std::string IRPipeline;
-      raw_string_ostream IRSOS(IRPipeline);
+      std::string PipelineStr;
+      raw_string_ostream IRSOS(PipelineStr);
       MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) {
         auto PassName = PIC.getPassNameForClassName(ClassName);
         return PassName.empty() ? ClassName : PassName;
       });
-      outs() << "IR pipeline: " << IRPipeline << '\n';
-
-      std::string MIRPipeline;
-      raw_string_ostream MIRSOS(MIRPipeline);
-      MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) {
-        auto PassName = PIC.getPassNameForClassName(ClassName);
-        return PassName.empty() ? ClassName : PassName;
-      });
-      outs() << "MIR pipeline: " << MIRPipeline << '\n';
       return 0;
     }
-
-    RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM, MFPM,
-              MFAM);
   }
 
+  // Before executing passes, print the final values of the LLVM options.
+  cl::PrintOptionValues();
+
+  MPM.run(*M, MAM);
+
+  if (Context.getDiagHandlerPtr()->HasErrors)
+    exit(1);
+
   // Declare success.
   Out->keep();
   if (DwoOut)



More information about the llvm-commits mailing list