Skip to content

Commit fa3693a

Browse files
author
Whitney Tsang
committed
[LoopNest] Handle loop-nest passes in LoopPassManager
Per http://llvm.org/OpenProjects.html#llvm_loopnest, the goal of this patch (and other following patches) is to create facilities that allow implementing loop nest passes that run on top-level loop nests for the New Pass Manager. This patch extends the functionality of LoopPassManager to handle loop-nest passes by specializing the definition of LoopPassManager that accepts both kinds of passes in addPass. Only loop passes are executed if L is not a top-level one, and both kinds of passes are executed if L is top-level. Currently, loop nest passes should have the following run method: PreservedAnalyses run(LoopNest &, LoopAnalysisManager &, LoopStandardAnalysisResults &, LPMUpdater &); Reviewed By: Whitney, ychen Differential Revision: https://reviews.llvm.org/D87045
1 parent c0619d3 commit fa3693a

File tree

6 files changed

+452
-51
lines changed

6 files changed

+452
-51
lines changed

llvm/include/llvm/Analysis/LoopNestAnalysis.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class LoopNest {
128128
[](const Loop *L) { return L->isLoopSimplifyForm(); });
129129
}
130130

131+
StringRef getName() const { return Loops.front()->getName(); }
132+
131133
protected:
132134
const unsigned MaxPerfectDepth; // maximum perfect nesting depth level.
133135
LoopVectorTy Loops; // the loops in the nest (in breadth first order).

llvm/include/llvm/Transforms/Scalar/LoopPassManager.h

Lines changed: 154 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
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.
6970
template <>
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

llvm/lib/Analysis/LoopNestAnalysis.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
306306
return true;
307307
}
308308

309+
AnalysisKey LoopNestAnalysis::Key;
310+
309311
raw_ostream &llvm::operator<<(raw_ostream &OS, const LoopNest &LN) {
310312
OS << "IsPerfect=";
311313
if (LN.getMaxPerfectDepth() == LN.getNestDepth())

0 commit comments

Comments
 (0)