[llvm] [CodeGen] Support MachineFunctionProperties in PassConcept (PR #79749)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 29 01:49:02 PST 2024


https://github.com/paperchalice updated https://github.com/llvm/llvm-project/pull/79749

>From bb6d4da80b2e7c5c51dba0a5662f14546c375eee Mon Sep 17 00:00:00 2001
From: PaperChalice <liujunchang97 at outlook.com>
Date: Sun, 28 Jan 2024 21:48:59 +0800
Subject: [PATCH] [CodeGen] Support MachineFunctionProperties in PassConcept

---
 .../include/llvm/CodeGen/MachinePassManager.h | 50 ++++++++++----
 .../llvm/CodeGen/MachinePassManagerInternal.h | 68 ++++++++++++++++++
 llvm/include/llvm/IR/PassManager.h            | 69 ++++++++++++++++++-
 llvm/include/llvm/IR/PassManagerInternal.h    | 17 ++++-
 llvm/unittests/CodeGen/PassManagerTest.cpp    | 10 +--
 .../MIR/PassBuilderCallbacksTest.cpp          |  4 +-
 6 files changed, 194 insertions(+), 24 deletions(-)
 create mode 100644 llvm/include/llvm/CodeGen/MachinePassManagerInternal.h

diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
index 662b7e8689717dc..c8f113a3f83c545 100644
--- a/llvm/include/llvm/CodeGen/MachinePassManager.h
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -25,15 +25,13 @@
 
 #include "llvm/ADT/FunctionExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachinePassManagerInternal.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/Error.h"
 
 #include <map>
 
 namespace llvm {
-class Module;
-class Function;
-class MachineFunction;
 
 extern template class AnalysisManager<MachineFunction>;
 
@@ -43,7 +41,28 @@ 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();
+  }
+};
+
+/// A CRTP mix-in that provides informational APIs needed for MachineFunction
+/// analysis passes. See also \c PassInfoMixin.
+template <typename DerivedT>
+struct MachineFunctionAnalysisInfoMixin
+    : public MachinePassInfoMixin<DerivedT> {
+  static AnalysisKey *ID() {
+    static_assert(
+        std::is_base_of<MachineFunctionAnalysisInfoMixin, DerivedT>::value,
+        "Must pass the derived type as the template argument!");
+    return &DerivedT::Key;
+  }
 };
 
 /// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
@@ -170,6 +189,17 @@ class MachineFunctionPassManager
     addRunOnModule<PassT>(P);
   }
 
+  // Avoid diamond problem.
+  static MachineFunctionProperties getRequiredProperties() {
+    return MachineFunctionProperties();
+  }
+  static MachineFunctionProperties getSetProperties() {
+    return MachineFunctionProperties();
+  }
+  static MachineFunctionProperties getClearedProperties() {
+    return MachineFunctionProperties();
+  }
+
 private:
   template <typename PassT>
   using has_init_t = decltype(std::declval<PassT &>().doInitialization(
@@ -183,9 +213,7 @@ 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::MachinePassModel<PassT>;
     auto *P = static_cast<PassModelT *>(Pass);
     InitializationFuncs.emplace_back(
         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
@@ -205,9 +233,7 @@ 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::MachinePassModel<PassT>;
     auto *P = static_cast<PassModelT *>(Pass);
     FinalizationFuncs.emplace_back(
         [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
@@ -236,9 +262,7 @@ class MachineFunctionPassManager
                   "machine module pass needs to define machine function pass "
                   "api. sorry.");
 
-    using PassModelT =
-        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
-                          MachineFunctionAnalysisManager>;
+    using PassModelT = detail::MachinePassModel<PassT>;
     auto *P = static_cast<PassModelT *>(Pass);
     MachineModulePasses.emplace(
         Passes.size() - 1,
diff --git a/llvm/include/llvm/CodeGen/MachinePassManagerInternal.h b/llvm/include/llvm/CodeGen/MachinePassManagerInternal.h
new file mode 100644
index 000000000000000..bbac8cb86affe9a
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/MachinePassManagerInternal.h
@@ -0,0 +1,68 @@
+//===- MachinePassManagerInternal.h --------------------------- -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This header provides internal APIs and implementation details used by the
+/// pass management interfaces exposed in MachinePassManager.h. Most of them are
+/// copied from PassManagerInternal.h.
+/// See also PassManagerInternal.h.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEPASSMANAGERINTERNAL_H
+#define LLVM_CODEGEN_MACHINEPASSMANAGERINTERNAL_H
+
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class MachineFunctionAnalysisManager;
+
+using MachinePassConcept =
+    detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>;
+
+namespace detail {
+
+/// Template for the abstract base class used to dispatch
+/// polymorphically over pass objects. See also \c PassConcept.
+template <>
+struct PassConcept<MachineFunction, MachineFunctionAnalysisManager>
+    : public PassConceptBase<MachineFunction, MachineFunctionAnalysisManager> {
+  /// MachineFunction Properties.
+  PassConcept(MachineFunctionProperties RequiredProperties,
+              MachineFunctionProperties SetProperties,
+              MachineFunctionProperties ClearedProperties)
+      : RequiredProperties(RequiredProperties), SetProperties(SetProperties),
+        ClearedProperties(ClearedProperties) {}
+
+  MachineFunctionProperties RequiredProperties;
+  MachineFunctionProperties SetProperties;
+  MachineFunctionProperties ClearedProperties;
+};
+
+template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
+          typename AnalysisManagerT, typename... ExtraArgTs>
+template <typename MachineFunctionT, typename>
+PassModel<IRUnitT, PassT, PreservedAnalysesT, AnalysisManagerT, ExtraArgTs...>::
+    PassModel(PassT Pass, MachineFunctionProperties RequiredProperties,
+              MachineFunctionProperties SetProperties,
+              MachineFunctionProperties ClearedProperties)
+    : PassConcept<MachineFunction, MachineFunctionAnalysisManager>(
+          RequiredProperties, SetProperties, ClearedProperties),
+      Pass(std::move(Pass)) {}
+
+template <typename PassT>
+using MachinePassModel = PassModel<MachineFunction, PassT, PreservedAnalyses,
+                                   MachineFunctionAnalysisManager>;
+
+} // namespace detail
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_MACHINEPASSMANAGERINTERNAL_H
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index df548fbe9e458c4..f87d71ad1f6d7e3 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -576,8 +576,14 @@ class PassManager : public PassInfoMixin<
                           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>(
-        new PassModelT(std::forward<PassT>(Pass))));
+    if constexpr (std::is_same_v<IRUnitT, MachineFunction>) {
+      Passes.push_back(std::unique_ptr<PassConceptT>(new PassModelT(
+          std::forward<PassT>(Pass), PassT::getRequiredProperties(),
+          PassT::getSetProperties(), PassT::getClearedProperties())));
+    } else {
+      Passes.push_back(std::unique_ptr<PassConceptT>(
+          new PassModelT(std::forward<PassT>(Pass))));
+    }
   }
 
   /// When adding a pass manager pass that has the same type as this pass
@@ -1292,9 +1298,37 @@ struct RequireAnalysisPass
     OS << "require<" << PassName << '>';
   }
   static bool isRequired() { return true; }
+
+  // MachineFunctionPass interface, define Define these separately to prevent
+  // dependency on CodeGen
+  template <typename MachineFunctionT = IRUnitT,
+            typename MachineFunctionPropertiesT = MachineFunctionProperties,
+            typename = std::enable_if_t<
+                std::is_same_v<MachineFunctionT, MachineFunction>>>
+  static MachineFunctionPropertiesT getRequiredProperties() {
+    return MachineFunctionPropertiesT();
+  }
+
+  template <typename MachineFunctionT = IRUnitT,
+            typename MachineFunctionPropertiesT = MachineFunctionProperties,
+            typename = std::enable_if_t<
+                std::is_same_v<MachineFunctionT, MachineFunction>>>
+  static MachineFunctionPropertiesT getSetProperties() {
+    return MachineFunctionPropertiesT();
+  }
+
+  template <typename MachineFunctionT = IRUnitT,
+            typename MachineFunctionPropertiesT = MachineFunctionProperties,
+            typename = std::enable_if_t<
+                std::is_same_v<MachineFunctionT, MachineFunction>>>
+  static MachineFunctionPropertiesT getClearedProperties() {
+    return MachineFunctionPropertiesT();
+  }
 };
 
-/// A no-op pass template which simply forces a specific analysis result
+template <typename DerivedT> struct MachineFunctionAnalysisInfoMixin;
+
+/// A no-op IR pass template which simply forces a specific analysis result
 /// to be invalidated.
 template <typename AnalysisT>
 struct InvalidateAnalysisPass
@@ -1317,6 +1351,35 @@ struct InvalidateAnalysisPass
     auto PassName = MapClassName2PassName(ClassName);
     OS << "invalidate<" << PassName << '>';
   }
+
+  // MachineFunctionPass interface, define Define these separately to prevent
+  // dependency on CodeGen
+  template <typename MachineFunctionPropertiesT = MachineFunctionProperties,
+            typename MachineFunctionAnalysisT = AnalysisT,
+            typename = std::enable_if_t<std::is_base_of_v<
+                MachineFunctionAnalysisInfoMixin<MachineFunctionAnalysisT>,
+                MachineFunctionAnalysisT>>>
+  static MachineFunctionPropertiesT getRequiredProperties() {
+    return MachineFunctionPropertiesT();
+  }
+
+  template <typename MachineFunctionPropertiesT = MachineFunctionProperties,
+            typename MachineFunctionAnalysisT = AnalysisT,
+            typename = std::enable_if_t<std::is_base_of_v<
+                MachineFunctionAnalysisInfoMixin<MachineFunctionAnalysisT>,
+                MachineFunctionAnalysisT>>>
+  static MachineFunctionPropertiesT getSetProperties() {
+    return MachineFunctionPropertiesT();
+  }
+
+  template <typename MachineFunctionPropertiesT = MachineFunctionProperties,
+            typename MachineFunctionAnalysisT = AnalysisT,
+            typename = std::enable_if_t<std::is_base_of_v<
+                MachineFunctionAnalysisInfoMixin<MachineFunctionAnalysisT>,
+                MachineFunctionAnalysisT>>>
+  static MachineFunctionPropertiesT getClearedProperties() {
+    return MachineFunctionPropertiesT();
+  }
 };
 
 /// A utility pass that does nothing, but preserves no analyses.
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index bcfdcb8206c45ee..8bdbdaa9dfdbd88 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -28,6 +28,8 @@ namespace llvm {
 template <typename IRUnitT> class AllAnalysesOn;
 template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
 class PreservedAnalyses;
+class MachineFunction;
+class MachineFunctionProperties;
 
 // Implementation details of the pass manager interfaces.
 namespace detail {
@@ -35,9 +37,9 @@ namespace detail {
 /// Template for the abstract base class used to dispatch
 /// polymorphically over pass objects.
 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
-struct PassConcept {
+struct PassConceptBase {
   // Boiler plate necessary for the container of derived classes.
-  virtual ~PassConcept() = default;
+  virtual ~PassConceptBase() = default;
 
   /// The polymorphic API which runs the pass over a given IR entity.
   ///
@@ -60,6 +62,10 @@ struct PassConcept {
   virtual bool isRequired() const = 0;
 };
 
+template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
+struct PassConcept
+    : public PassConceptBase<IRUnitT, AnalysisManagerT, ExtraArgTs...> {};
+
 /// A template wrapper used to implement the polymorphic API.
 ///
 /// Can be instantiated for any object which provides a \c run method accepting
@@ -69,6 +75,13 @@ template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
           typename AnalysisManagerT, typename... ExtraArgTs>
 struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
   explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
+
+  template <typename MachineFunctionT = IRUnitT,
+            typename = std::enable_if_t<
+                std::is_same_v<MachineFunctionT, MachineFunction>>>
+  explicit PassModel(PassT Pass, MachineFunctionProperties RequiredProperties,
+                     MachineFunctionProperties SetProperties,
+                     MachineFunctionProperties ClearedProperties);
   // We have to explicitly define all the special member functions because MSVC
   // refuses to generate them.
   PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
diff --git a/llvm/unittests/CodeGen/PassManagerTest.cpp b/llvm/unittests/CodeGen/PassManagerTest.cpp
index 4d2c8b7bdb5f455..1682fa8a8a96a70 100644
--- a/llvm/unittests/CodeGen/PassManagerTest.cpp
+++ b/llvm/unittests/CodeGen/PassManagerTest.cpp
@@ -52,7 +52,7 @@ class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
 AnalysisKey TestFunctionAnalysis::Key;
 
 class TestMachineFunctionAnalysis
-    : public AnalysisInfoMixin<TestMachineFunctionAnalysis> {
+    : public MachineFunctionAnalysisInfoMixin<TestMachineFunctionAnalysis> {
 public:
   struct Result {
     Result(int Count) : InstructionCount(Count) {}
@@ -70,7 +70,7 @@ class TestMachineFunctionAnalysis
   }
 
 private:
-  friend AnalysisInfoMixin<TestMachineFunctionAnalysis>;
+  friend MachineFunctionAnalysisInfoMixin<TestMachineFunctionAnalysis>;
   static AnalysisKey Key;
 };
 
@@ -79,7 +79,8 @@ AnalysisKey TestMachineFunctionAnalysis::Key;
 const std::string DoInitErrMsg = "doInitialization failed";
 const std::string DoFinalErrMsg = "doFinalization failed";
 
-struct TestMachineFunctionPass : public PassInfoMixin<TestMachineFunctionPass> {
+struct TestMachineFunctionPass
+    : public MachinePassInfoMixin<TestMachineFunctionPass> {
   TestMachineFunctionPass(int &Count, std::vector<int> &BeforeInitialization,
                           std::vector<int> &BeforeFinalization,
                           std::vector<int> &MachineFunctionPassCount)
@@ -139,7 +140,8 @@ struct TestMachineFunctionPass : public PassInfoMixin<TestMachineFunctionPass> {
   std::vector<int> &MachineFunctionPassCount;
 };
 
-struct TestMachineModulePass : public PassInfoMixin<TestMachineModulePass> {
+struct TestMachineModulePass
+    : public MachinePassInfoMixin<TestMachineModulePass> {
   TestMachineModulePass(int &Count, std::vector<int> &MachineModulePassCount)
       : Count(Count), MachineModulePassCount(MachineModulePassCount) {}
 
diff --git a/llvm/unittests/MIR/PassBuilderCallbacksTest.cpp b/llvm/unittests/MIR/PassBuilderCallbacksTest.cpp
index 88522d45bc6bfa9..e0bd93aafddd8bc 100644
--- a/llvm/unittests/MIR/PassBuilderCallbacksTest.cpp
+++ b/llvm/unittests/MIR/PassBuilderCallbacksTest.cpp
@@ -174,8 +174,8 @@ struct MockPassInstrumentationCallbacks {
 
 template <typename DerivedT> class MockAnalysisHandleBase {
 public:
-  class Analysis : public AnalysisInfoMixin<Analysis> {
-    friend AnalysisInfoMixin<Analysis>;
+  class Analysis : public MachineFunctionAnalysisInfoMixin<Analysis> {
+    friend MachineFunctionAnalysisInfoMixin<Analysis>;
     friend MockAnalysisHandleBase;
     static AnalysisKey Key;
 



More information about the llvm-commits mailing list