4545#include " llvm/Analysis/GlobalsModRef.h"
4646#include " llvm/Analysis/LoopAnalysisManager.h"
4747#include " llvm/Analysis/LoopInfo.h"
48+ #include " llvm/Analysis/LoopNestAnalysis.h"
4849#include " llvm/Analysis/MemorySSA.h"
4950#include " llvm/Analysis/ScalarEvolution.h"
5051#include " llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
@@ -67,13 +68,136 @@ class LPMUpdater;
6768// See the comments on the definition of the specialization for details on how
6869// it differs from the primary template.
6970template <>
70- PreservedAnalyses
71- PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
72- LPMUpdater &>::run(Loop &InitialL, LoopAnalysisManager &AM,
73- LoopStandardAnalysisResults &AnalysisResults,
74- LPMUpdater &U);
75- extern template class PassManager <Loop, LoopAnalysisManager,
76- LoopStandardAnalysisResults &, LPMUpdater &>;
71+ class PassManager <Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
72+ LPMUpdater &>
73+ : public PassInfoMixin<
74+ PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &,
75+ LPMUpdater &>> {
76+ private:
77+ template <typename PassT>
78+ using HasRunOnLoopT = decltype (std::declval<PassT>().run(
79+ std::declval<Loop &>(), std::declval<LoopAnalysisManager &>(),
80+ std::declval<LoopStandardAnalysisResults &>(),
81+ std::declval<LPMUpdater &>()));
82+
83+ public:
84+ // / Construct a pass manager.
85+ // /
86+ // / If \p DebugLogging is true, we'll log our progress to llvm::dbgs().
87+ explicit PassManager (bool DebugLogging = false )
88+ : DebugLogging(DebugLogging) {}
89+
90+ // FIXME: These are equivalent to the default move constructor/move
91+ // assignment. However, using = default triggers linker errors due to the
92+ // explicit instantiations below. Find a way to use the default and remove the
93+ // duplicated code here.
94+ PassManager (PassManager &&Arg)
95+ : IsLoopNestPass(std::move(Arg.IsLoopNestPass)),
96+ LoopPasses (std::move(Arg.LoopPasses)),
97+ LoopNestPasses(std::move(Arg.LoopNestPasses)),
98+ DebugLogging(std::move(Arg.DebugLogging)) {}
99+
100+ PassManager &operator =(PassManager &&RHS) {
101+ IsLoopNestPass = std::move (RHS.IsLoopNestPass );
102+ LoopPasses = std::move (RHS.LoopPasses );
103+ LoopNestPasses = std::move (RHS.LoopNestPasses );
104+ DebugLogging = std::move (RHS.DebugLogging );
105+ return *this ;
106+ }
107+
108+ PreservedAnalyses run (Loop &L, LoopAnalysisManager &AM,
109+ LoopStandardAnalysisResults &AR, LPMUpdater &U);
110+
111+ // / Add either a loop pass or a loop-nest pass to the pass manager. Append \p
112+ // / Pass to the list of loop passes if it has a dedicated \fn run() method for
113+ // / loops and to the list of loop-nest passes if the \fn run() method is for
114+ // / loop-nests instead. Also append whether \p Pass is loop-nest pass or not
115+ // / to the end of \var IsLoopNestPass so we can easily identify the types of
116+ // / passes in the pass manager later.
117+ template <typename PassT>
118+ std::enable_if_t <is_detected<HasRunOnLoopT, PassT>::value>
119+ addPass (PassT Pass) {
120+ using LoopPassModelT =
121+ detail::PassModel<Loop, PassT, PreservedAnalyses, LoopAnalysisManager,
122+ LoopStandardAnalysisResults &, LPMUpdater &>;
123+ IsLoopNestPass.push_back (false );
124+ LoopPasses.emplace_back (new LoopPassModelT (std::move (Pass)));
125+ }
126+
127+ template <typename PassT>
128+ std::enable_if_t <!is_detected<HasRunOnLoopT, PassT>::value>
129+ addPass (PassT Pass) {
130+ using LoopNestPassModelT =
131+ detail::PassModel<LoopNest, PassT, PreservedAnalyses,
132+ LoopAnalysisManager, LoopStandardAnalysisResults &,
133+ LPMUpdater &>;
134+ IsLoopNestPass.push_back (true );
135+ LoopNestPasses.emplace_back (new LoopNestPassModelT (std::move (Pass)));
136+ }
137+
138+ // Specializations of `addPass` for `RepeatedPass`. These are necessary since
139+ // `RepeatedPass` has a templated `run` method that will result in incorrect
140+ // detection of `HasRunOnLoopT`.
141+ template <typename PassT>
142+ std::enable_if_t <is_detected<HasRunOnLoopT, PassT>::value>
143+ addPass (RepeatedPass<PassT> Pass) {
144+ using RepeatedLoopPassModelT =
145+ detail::PassModel<Loop, RepeatedPass<PassT>, PreservedAnalyses,
146+ LoopAnalysisManager, LoopStandardAnalysisResults &,
147+ LPMUpdater &>;
148+ IsLoopNestPass.push_back (false );
149+ LoopPasses.emplace_back (new RepeatedLoopPassModelT (std::move (Pass)));
150+ }
151+
152+ template <typename PassT>
153+ std::enable_if_t <!is_detected<HasRunOnLoopT, PassT>::value>
154+ addPass (RepeatedPass<PassT> Pass) {
155+ using RepeatedLoopNestPassModelT =
156+ detail::PassModel<LoopNest, RepeatedPass<PassT>, PreservedAnalyses,
157+ LoopAnalysisManager, LoopStandardAnalysisResults &,
158+ LPMUpdater &>;
159+ IsLoopNestPass.push_back (true );
160+ LoopNestPasses.emplace_back (
161+ new RepeatedLoopNestPassModelT (std::move (Pass)));
162+ }
163+
164+ bool isEmpty () const { return LoopPasses.empty () && LoopNestPasses.empty (); }
165+
166+ static bool isRequired () { return true ; }
167+
168+ protected:
169+ using LoopPassConceptT =
170+ detail::PassConcept<Loop, LoopAnalysisManager,
171+ LoopStandardAnalysisResults &, LPMUpdater &>;
172+ using LoopNestPassConceptT =
173+ detail::PassConcept<LoopNest, LoopAnalysisManager,
174+ LoopStandardAnalysisResults &, LPMUpdater &>;
175+
176+ // BitVector that identifies whether the passes are loop passes or loop-nest
177+ // passes (true for loop-nest passes).
178+ BitVector IsLoopNestPass;
179+ std::vector<std::unique_ptr<LoopPassConceptT>> LoopPasses;
180+ std::vector<std::unique_ptr<LoopNestPassConceptT>> LoopNestPasses;
181+
182+ // / Flag indicating whether we should do debug logging.
183+ bool DebugLogging;
184+
185+ // / Run either a loop pass or a loop-nest pass. Returns `None` if
186+ // / PassInstrumentation's BeforePass returns false. Otherwise, returns the
187+ // / preserved analyses of the pass.
188+ template <typename IRUnitT, typename PassT>
189+ Optional<PreservedAnalyses>
190+ runSinglePass (IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
191+ LoopStandardAnalysisResults &AR, LPMUpdater &U,
192+ PassInstrumentation &PI);
193+
194+ PreservedAnalyses runWithLoopNestPasses (Loop &L, LoopAnalysisManager &AM,
195+ LoopStandardAnalysisResults &AR,
196+ LPMUpdater &U);
197+ PreservedAnalyses runWithoutLoopNestPasses (Loop &L, LoopAnalysisManager &AM,
198+ LoopStandardAnalysisResults &AR,
199+ LPMUpdater &U);
200+ };
77201
78202// / The Loop pass manager.
79203// /
@@ -223,6 +347,29 @@ class LPMUpdater {
223347 : Worklist(Worklist), LAM(LAM) {}
224348};
225349
350+ template <typename IRUnitT, typename PassT>
351+ Optional<PreservedAnalyses> LoopPassManager::runSinglePass (
352+ IRUnitT &IR, PassT &Pass, LoopAnalysisManager &AM,
353+ LoopStandardAnalysisResults &AR, LPMUpdater &U, PassInstrumentation &PI) {
354+ // Check the PassInstrumentation's BeforePass callbacks before running the
355+ // pass, skip its execution completely if asked to (callback returns false).
356+ if (!PI.runBeforePass <IRUnitT>(*Pass, IR))
357+ return None;
358+
359+ PreservedAnalyses PA;
360+ {
361+ TimeTraceScope TimeScope (Pass->name (), IR.getName ());
362+ PA = Pass->run (IR, AM, AR, U);
363+ }
364+
365+ // do not pass deleted Loop into the instrumentation
366+ if (U.skipCurrentLoop ())
367+ PI.runAfterPassInvalidated <IRUnitT>(*Pass, PA);
368+ else
369+ PI.runAfterPass <IRUnitT>(*Pass, IR, PA);
370+ return PA;
371+ }
372+
226373// / Adaptor that maps from a function to its loops.
227374// /
228375// / Designed to allow composition of a LoopPass(Manager) and a
0 commit comments