1616// their respective analysis managers such as ModuleAnalysisManager and
1717// FunctionAnalysisManager.
1818//
19- // TODO: Add MachineFunctionProperties support.
20- //
2119// ===----------------------------------------------------------------------===//
2220
2321#ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
@@ -44,23 +42,67 @@ using MachineFunctionAnalysisManager = AnalysisManager<MachineFunction>;
4442// / automatically mixes in \c PassInfoMixin.
4543template <typename DerivedT>
4644struct MachinePassInfoMixin : public PassInfoMixin <DerivedT> {
47- // TODO: Add MachineFunctionProperties support.
45+ protected:
46+ class PropertyChanger {
47+ MachineFunction &MF;
48+
49+ template <typename T>
50+ using has_get_required_properties_t =
51+ decltype (std::declval<T &>().getRequiredProperties());
52+
53+ template <typename T>
54+ using has_get_set_properties_t =
55+ decltype (std::declval<T &>().getSetProperties());
56+
57+ template <typename T>
58+ using has_get_cleared_properties_t =
59+ decltype (std::declval<T &>().getClearedProperties());
60+
61+ public:
62+ PropertyChanger (MachineFunction &MF) : MF(MF) {
63+ #ifndef NDEBUG
64+ if constexpr (is_detected<has_get_required_properties_t ,
65+ DerivedT>::value) {
66+ auto &MFProps = MF.getProperties ();
67+ auto RequiredProperties = DerivedT::getRequiredProperties ();
68+ if (!MFProps.verifyRequiredProperties (RequiredProperties)) {
69+ errs () << " MachineFunctionProperties required by " << DerivedT::name ()
70+ << " pass are not met by function " << MF.getName () << " .\n "
71+ << " Required properties: " ;
72+ RequiredProperties.print (errs ());
73+ errs () << " \n Current properties: " ;
74+ MFProps.print (errs ());
75+ errs () << ' \n ' ;
76+ report_fatal_error (" MachineFunctionProperties check failed" );
77+ }
78+ }
79+ #endif
80+ }
81+
82+ ~PropertyChanger () {
83+ if constexpr (is_detected<has_get_set_properties_t , DerivedT>::value)
84+ MF.getProperties ().set (DerivedT::getSetProperties ());
85+ if constexpr (is_detected<has_get_cleared_properties_t , DerivedT>::value)
86+ MF.getProperties ().reset (DerivedT::getClearedProperties ());
87+ }
88+ };
89+
90+ public:
91+ PreservedAnalyses runImpl (MachineFunction &MF,
92+ MachineFunctionAnalysisManager &MFAM) {
93+ PropertyChanger PC (MF);
94+ return static_cast <DerivedT *>(this )->run (MF, MFAM);
95+ }
4896};
4997
5098namespace detail {
51- struct MachinePassConcept
52- : PassConcept<MachineFunction, MachineFunctionAnalysisManager> {
53- virtual MachineFunctionProperties getRequiredProperties () const = 0;
54- virtual MachineFunctionProperties getSetProperties () const = 0;
55- virtual MachineFunctionProperties getClearedProperties () const = 0;
56- };
5799
58- template <typename PassT> struct MachinePassModel : MachinePassConcept {
59- explicit MachinePassModel (PassT &&Pass) : Pass(std::move(Pass)) {}
60- // We have to explicitly define all the special member functions because MSVC
61- // refuses to generate them.
62- MachinePassModel ( const MachinePassModel &Arg) : Pass(Arg.Pass) {}
63- MachinePassModel (MachinePassModel &&Arg) : Pass( std::move(Arg. Pass)) {}
100+ template <typename PassT>
101+ struct MachinePassModel
102+ : PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager> {
103+ explicit MachinePassModel (PassT &&Pass)
104+ : PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager>(
105+ std::move (Pass)) {}
64106
65107 friend void swap (MachinePassModel &LHS, MachinePassModel &RHS) {
66108 using std::swap;
@@ -75,89 +117,8 @@ template <typename PassT> struct MachinePassModel : MachinePassConcept {
75117 MachinePassModel &operator =(const MachinePassModel &) = delete ;
76118 PreservedAnalyses run (MachineFunction &IR,
77119 MachineFunctionAnalysisManager &AM) override {
78- return Pass.run (IR, AM);
79- }
80-
81- void printPipeline (
82- raw_ostream &OS,
83- function_ref<StringRef(StringRef)> MapClassName2PassName) override {
84- Pass.printPipeline (OS, MapClassName2PassName);
85- }
86-
87- StringRef name () const override { return PassT::name (); }
88-
89- template <typename T>
90- using has_required_t = decltype (std::declval<T &>().isRequired());
91- template <typename T>
92- static std::enable_if_t <is_detected<has_required_t , T>::value, bool >
93- passIsRequiredImpl () {
94- return T::isRequired ();
120+ return this ->Pass .runImpl (IR, AM);
95121 }
96- template <typename T>
97- static std::enable_if_t <!is_detected<has_required_t , T>::value, bool >
98- passIsRequiredImpl () {
99- return false ;
100- }
101- bool isRequired () const override { return passIsRequiredImpl<PassT>(); }
102-
103- template <typename T>
104- using has_get_required_properties_t =
105- decltype (std::declval<T &>().getRequiredProperties());
106- template <typename T>
107- static std::enable_if_t <is_detected<has_get_required_properties_t , T>::value,
108- MachineFunctionProperties>
109- getRequiredPropertiesImpl () {
110- return PassT::getRequiredProperties ();
111- }
112- template <typename T>
113- static std::enable_if_t <!is_detected<has_get_required_properties_t , T>::value,
114- MachineFunctionProperties>
115- getRequiredPropertiesImpl () {
116- return MachineFunctionProperties ();
117- }
118- MachineFunctionProperties getRequiredProperties () const override {
119- return getRequiredPropertiesImpl<PassT>();
120- }
121-
122- template <typename T>
123- using has_get_set_properties_t =
124- decltype (std::declval<T &>().getSetProperties());
125- template <typename T>
126- static std::enable_if_t <is_detected<has_get_set_properties_t , T>::value,
127- MachineFunctionProperties>
128- getSetPropertiesImpl () {
129- return PassT::getSetProperties ();
130- }
131- template <typename T>
132- static std::enable_if_t <!is_detected<has_get_set_properties_t , T>::value,
133- MachineFunctionProperties>
134- getSetPropertiesImpl () {
135- return MachineFunctionProperties ();
136- }
137- MachineFunctionProperties getSetProperties () const override {
138- return getSetPropertiesImpl<PassT>();
139- }
140-
141- template <typename T>
142- using has_get_cleared_properties_t =
143- decltype (std::declval<T &>().getClearedProperties());
144- template <typename T>
145- static std::enable_if_t <is_detected<has_get_cleared_properties_t , T>::value,
146- MachineFunctionProperties>
147- getClearedPropertiesImpl () {
148- return PassT::getClearedProperties ();
149- }
150- template <typename T>
151- static std::enable_if_t <!is_detected<has_get_cleared_properties_t , T>::value,
152- MachineFunctionProperties>
153- getClearedPropertiesImpl () {
154- return MachineFunctionProperties ();
155- }
156- MachineFunctionProperties getClearedProperties () const override {
157- return getClearedPropertiesImpl<PassT>();
158- }
159-
160- PassT Pass;
161122};
162123} // namespace detail
163124
@@ -251,11 +212,12 @@ class FunctionAnalysisManagerMachineFunctionProxy
251212
252213class ModuleToMachineFunctionPassAdaptor
253214 : public PassInfoMixin<ModuleToMachineFunctionPassAdaptor> {
254- using MachinePassConcept = detail::MachinePassConcept;
255-
256215public:
216+ using PassConceptT =
217+ detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>;
218+
257219 explicit ModuleToMachineFunctionPassAdaptor (
258- std::unique_ptr<MachinePassConcept > Pass)
220+ std::unique_ptr<PassConceptT > Pass)
259221 : Pass(std::move(Pass)) {}
260222
261223 // / Runs the function pass across every function in the module.
@@ -266,20 +228,41 @@ class ModuleToMachineFunctionPassAdaptor
266228 static bool isRequired () { return true ; }
267229
268230private:
269- std::unique_ptr<MachinePassConcept > Pass;
231+ std::unique_ptr<PassConceptT > Pass;
270232};
271233
272234template <typename MachineFunctionPassT>
273235ModuleToMachineFunctionPassAdaptor
274236createModuleToMachineFunctionPassAdaptor (MachineFunctionPassT &&Pass) {
275- using PassModelT = detail::MachinePassModel<MachineFunctionPassT>;
237+ using PassModelT = detail::PassModel<MachineFunction, MachineFunctionPassT,
238+ MachineFunctionAnalysisManager>;
276239 // Do not use make_unique, it causes too many template instantiations,
277240 // causing terrible compile times.
278241 return ModuleToMachineFunctionPassAdaptor (
279- std::unique_ptr<detail::MachinePassConcept >(
242+ std::unique_ptr<ModuleToMachineFunctionPassAdaptor::PassConceptT >(
280243 new PassModelT (std::forward<MachineFunctionPassT>(Pass))));
281244}
282245
246+ template <>
247+ template <typename PassT>
248+ void PassManager<MachineFunction>::addPass(PassT &&Pass) {
249+ using PassModelT =
250+ detail::PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager>;
251+ using MachinePassModelT = detail::MachinePassModel<PassT>;
252+ // Do not use make_unique or emplace_back, they cause too many template
253+ // instantiations, causing terrible compile times.
254+ if constexpr (std::is_base_of_v<MachinePassInfoMixin<PassT>, PassT>) {
255+ Passes.push_back (std::unique_ptr<PassConceptT>(
256+ new MachinePassModelT (std::forward<PassT>(Pass))));
257+ } else if constexpr (std::is_same_v<PassT, PassManager<MachineFunction>>) {
258+ for (auto &P : Pass.Passes )
259+ Passes.push_back (std::move (P));
260+ } else {
261+ Passes.push_back (std::unique_ptr<PassConceptT>(
262+ new PassModelT (std::forward<PassT>(Pass))));
263+ }
264+ }
265+
283266template <>
284267PreservedAnalyses
285268PassManager<MachineFunction>::run(MachineFunction &,
0 commit comments