Skip to content

Commit e987ab1

Browse files
authored
[Polly] Introduce PhaseManager and remove LPM support (#125442)
Instead of relying on any pass manager to schedule Polly's passes, add Polly's own pipeline manager which is seen as a monolithic pass in LLVM's pass manager. Polly's former passes are now phases of the new PhaseManager component. Relying on LLVM's pass manager (the legacy as well as the New Pass Manager) to manage Polly's phases never was a good fit that the PhaseManager resolves: * Polly passes were modifying analysis results, in particular RegionInfo and ScopInfo. This means that there was not just one unique and "definite" analysis result, the actual result depended on which analyses ran prior, and the pass manager was not allowed to throw away cached analyses or prior SCoP optimizations would have been forgotten. The LLVM pass manger's persistance of analysis results is not contractual but designed for caching. * Polly depends on a particular execution order of passes and regions (e.g. regression tests, invalidation of consecutive SCoPs). LLVM's pass manager does not guarantee any excecution order. * Polly does not completely preserve DominatorTree, RegionInfo, LoopInfo, or ScalarEvolution, but only as-needed for Polly's own uses. Because the ScopDetection object stores references to those analyses, it still had to lie to the pass manager that they would be preserved, or the pass manager would have released and recomputed the invalidated analysis objects that ScopDetection/ScopInfo was still referencing. To ensure that no non-Polly pass would see these not-completely-preserved analyses, all analyses still had to be thrown away after the ScopPassManager, respectively with a BarrierNoopPass in case of the LPM. * The NPM's PassInstrumentation wraps the IR unit into an `llvm::Any` object, but implementations such as PrintIRInstrumentation call llvm_unreachable on encountering an unknown IR unit, such as SCoPs, with no extension points to add support. Hence LLVM crashes when dumping IR between SCoP passes (such as `-print-before-changed` with Polly being active). The new PhaseManager uses some command line options that previously belonged to Polly's legacy passes, such as `-polly-print-detect` (so the option will continue to work). Hence the LPM support is incompatible with the new approach and support for it is removed.
1 parent 0e3612e commit e987ab1

File tree

1,143 files changed

+2700
-4460
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,143 files changed

+2700
-4460
lines changed

polly/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ In Polly |version| the following important changes have been incorporated.
1313

1414
* ScopInliner has been updated for the New Pass Manager.
1515

16+
* Polly now is a monolithic pass split into phases.
17+
18+
* Polly's support for the legacy pass manager has been removed.
19+

polly/include/polly/Canonicalization.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@
1111

1212
#include "llvm/Passes/PassBuilder.h"
1313

14-
namespace llvm {
15-
namespace legacy {
16-
class PassManagerBase;
17-
}
18-
} // namespace llvm
19-
2014
namespace polly {
2115

2216
/// Schedule a set of canonicalization passes to prepare for Polly.
@@ -26,8 +20,6 @@ namespace polly {
2620
/// into a canonical form that simplifies the analysis and optimization passes
2721
/// of Polly. The set of optimization passes scheduled here is probably not yet
2822
/// optimal. TODO: Optimize the set of canonicalization passes.
29-
void registerCanonicalicationPasses(llvm::legacy::PassManagerBase &PM);
30-
3123
llvm::FunctionPassManager
3224
buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM,
3325
llvm::OptimizationLevel Level);

polly/include/polly/CodeGen/CodeGeneration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/IR/PassManager.h"
1515

1616
namespace polly {
17+
class IslAstInfo;
1718

1819
enum VectorizerChoice {
1920
VECTORIZER_NONE,
@@ -33,6 +34,8 @@ struct CodeGenerationPass final : PassInfoMixin<CodeGenerationPass> {
3334
};
3435

3536
extern bool PerfMonitoring;
37+
38+
bool runCodeGeneration(Scop &S, llvm::RegionInfo &RI, IslAstInfo &AI);
3639
} // namespace polly
3740

3841
#endif // POLLY_CODEGENERATION_H

polly/include/polly/CodeGen/IslAst.h

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#ifndef POLLY_ISLAST_H
2222
#define POLLY_ISLAST_H
2323

24+
#include "polly/DependenceInfo.h"
2425
#include "polly/ScopPass.h"
2526
#include "llvm/ADT/SmallPtrSet.h"
2627
#include "llvm/IR/PassManager.h"
@@ -172,33 +173,6 @@ struct IslAstAnalysis : AnalysisInfoMixin<IslAstAnalysis> {
172173
ScopStandardAnalysisResults &SAR);
173174
};
174175

175-
class IslAstInfoWrapperPass final : public ScopPass {
176-
std::unique_ptr<IslAstInfo> Ast;
177-
178-
public:
179-
static char ID;
180-
181-
IslAstInfoWrapperPass() : ScopPass(ID) {}
182-
183-
IslAstInfo &getAI() { return *Ast; }
184-
const IslAstInfo &getAI() const { return *Ast; }
185-
186-
/// Build the AST for the given SCoP @p S.
187-
bool runOnScop(Scop &S) override;
188-
189-
/// Register all analyses and transformation required.
190-
void getAnalysisUsage(AnalysisUsage &AU) const override;
191-
192-
/// Release the internal memory.
193-
void releaseMemory() override;
194-
195-
/// Print a source code representation of the program.
196-
void printScop(raw_ostream &OS, Scop &S) const override;
197-
};
198-
199-
llvm::Pass *createIslAstInfoWrapperPassPass();
200-
llvm::Pass *createIslAstInfoPrinterLegacyPass(llvm::raw_ostream &OS);
201-
202176
struct IslAstPrinterPass final : PassInfoMixin<IslAstPrinterPass> {
203177
IslAstPrinterPass(raw_ostream &OS) : OS(OS) {}
204178

@@ -207,11 +181,9 @@ struct IslAstPrinterPass final : PassInfoMixin<IslAstPrinterPass> {
207181

208182
raw_ostream &OS;
209183
};
210-
} // namespace polly
211184

212-
namespace llvm {
213-
void initializeIslAstInfoWrapperPassPass(llvm::PassRegistry &);
214-
void initializeIslAstInfoPrinterLegacyPassPass(llvm::PassRegistry &);
215-
} // namespace llvm
185+
std::unique_ptr<IslAstInfo> runIslAstGen(Scop &S,
186+
DependenceAnalysis::Result &DA);
187+
} // namespace polly
216188

217189
#endif // POLLY_ISLAST_H

polly/include/polly/CodePreparation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515

1616
#include "llvm/IR/PassManager.h"
1717

18+
namespace llvm {
19+
class DominatorTree;
20+
class LoopInfo;
21+
class RegionInfo;
22+
} // namespace llvm
23+
1824
namespace polly {
1925
struct CodePreparationPass final : llvm::PassInfoMixin<CodePreparationPass> {
2026
llvm::PreservedAnalyses run(llvm::Function &F,

polly/include/polly/DeLICM.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,10 @@
2121
#include "isl/isl-noexceptions.h"
2222

2323
namespace llvm {
24-
class PassRegistry;
25-
class Pass;
2624
class raw_ostream;
2725
} // namespace llvm
2826

2927
namespace polly {
30-
/// Create a new DeLICM pass instance.
31-
llvm::Pass *createDeLICMWrapperPass();
32-
llvm::Pass *createDeLICMPrinterLegacyPass(llvm::raw_ostream &OS);
3328

3429
struct DeLICMPass final : llvm::PassInfoMixin<DeLICMPass> {
3530
DeLICMPass() {}
@@ -59,11 +54,7 @@ bool isConflicting(isl::union_set ExistingOccupied,
5954
isl::union_map ProposedWrites,
6055
llvm::raw_ostream *OS = nullptr, unsigned Indent = 0);
6156

57+
bool runDeLICM(Scop &S);
6258
} // namespace polly
6359

64-
namespace llvm {
65-
void initializeDeLICMWrapperPassPass(llvm::PassRegistry &);
66-
void initializeDeLICMPrinterLegacyPassPass(llvm::PassRegistry &);
67-
} // namespace llvm
68-
6960
#endif /* POLLY_DELICM_H */

polly/include/polly/DeadCodeElimination.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,10 @@
1313
#ifndef POLLY_DEADCODEELIMINATION_H
1414
#define POLLY_DEADCODEELIMINATION_H
1515

16+
#include "polly/DependenceInfo.h"
1617
#include "polly/ScopPass.h"
1718

18-
namespace llvm {
19-
class PassRegistry;
20-
class Pass;
21-
class raw_ostream;
22-
} // namespace llvm
23-
2419
namespace polly {
25-
llvm::Pass *createDeadCodeElimWrapperPass();
2620

2721
struct DeadCodeElimPass final : llvm::PassInfoMixin<DeadCodeElimPass> {
2822
DeadCodeElimPass() {}
@@ -31,10 +25,7 @@ struct DeadCodeElimPass final : llvm::PassInfoMixin<DeadCodeElimPass> {
3125
ScopStandardAnalysisResults &SAR, SPMUpdater &U);
3226
};
3327

28+
bool runDeadCodeElim(Scop &S, DependenceAnalysis::Result &DA);
3429
} // namespace polly
3530

36-
namespace llvm {
37-
void initializeDeadCodeElimWrapperPassPass(llvm::PassRegistry &);
38-
} // namespace llvm
39-
4031
#endif /* POLLY_DEADCODEELIMINATION_H */

polly/include/polly/DependenceInfo.h

Lines changed: 3 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ class Dependences final {
145145
friend struct DependenceAnalysis;
146146
friend struct DependenceInfoPrinterPass;
147147
friend class DependenceInfo;
148-
friend class DependenceInfoWrapperPass;
149148

150149
/// Destructor that will free internal objects.
151150
~Dependences() { releaseMemory(); }
@@ -192,6 +191,8 @@ class Dependences final {
192191
const AnalysisLevel Level;
193192
};
194193

194+
extern Dependences::AnalysisLevel OptAnalysisLevel;
195+
195196
struct DependenceAnalysis final : public AnalysisInfoMixin<DependenceAnalysis> {
196197
static AnalysisKey Key;
197198
struct Result {
@@ -232,108 +233,7 @@ struct DependenceInfoPrinterPass final
232233
raw_ostream &OS;
233234
};
234235

235-
class DependenceInfo final : public ScopPass {
236-
public:
237-
static char ID;
238-
239-
/// Construct a new DependenceInfo pass.
240-
DependenceInfo() : ScopPass(ID) {}
241-
242-
/// Return the dependence information for the current SCoP.
243-
///
244-
/// @param Level The granularity of dependence analysis result.
245-
///
246-
/// @return The dependence analysis result
247-
///
248-
const Dependences &getDependences(Dependences::AnalysisLevel Level);
249-
250-
/// Recompute dependences from schedule and memory accesses.
251-
const Dependences &recomputeDependences(Dependences::AnalysisLevel Level);
252-
253-
/// Invalidate the dependence information and recompute it when needed again.
254-
/// May be required when the underlying Scop was changed in a way that would
255-
/// add new dependencies (e.g. between new statement instances insierted into
256-
/// the SCoP) or intentionally breaks existing ones. It is not required when
257-
/// updating the schedule that conforms the existing dependencies.
258-
void abandonDependences();
259-
260-
/// Compute the dependence information for the SCoP @p S.
261-
bool runOnScop(Scop &S) override;
262-
263-
/// Print the dependences for the given SCoP to @p OS.
264-
void printScop(raw_ostream &OS, Scop &) const override;
265-
266-
/// Release the internal memory.
267-
void releaseMemory() override {
268-
for (auto &d : D)
269-
d.reset();
270-
}
271-
272-
/// Register all analyses and transformation required.
273-
void getAnalysisUsage(AnalysisUsage &AU) const override;
274-
275-
private:
276-
Scop *S;
277-
278-
/// Dependences struct for the current SCoP.
279-
std::unique_ptr<Dependences> D[Dependences::NumAnalysisLevels];
280-
};
281-
282-
llvm::Pass *createDependenceInfoPass();
283-
llvm::Pass *createDependenceInfoPrinterLegacyPass(llvm::raw_ostream &OS);
284-
285-
/// Construct a new DependenceInfoWrapper pass.
286-
class DependenceInfoWrapperPass final : public FunctionPass {
287-
public:
288-
static char ID;
289-
290-
/// Construct a new DependenceInfoWrapper pass.
291-
DependenceInfoWrapperPass() : FunctionPass(ID) {}
292-
293-
/// Return the dependence information for the given SCoP.
294-
///
295-
/// @param S SCoP object.
296-
/// @param Level The granularity of dependence analysis result.
297-
///
298-
/// @return The dependence analysis result
299-
///
300-
const Dependences &getDependences(Scop *S, Dependences::AnalysisLevel Level);
301-
302-
/// Recompute dependences from schedule and memory accesses.
303-
const Dependences &recomputeDependences(Scop *S,
304-
Dependences::AnalysisLevel Level);
305-
306-
/// Compute the dependence information on-the-fly for the function.
307-
bool runOnFunction(Function &F) override;
308-
309-
/// Print the dependences for the current function to @p OS.
310-
void print(raw_ostream &OS, const Module *M = nullptr) const override;
311-
312-
/// Release the internal memory.
313-
void releaseMemory() override { ScopToDepsMap.clear(); }
314-
315-
/// Register all analyses and transformation required.
316-
void getAnalysisUsage(AnalysisUsage &AU) const override;
317-
318-
private:
319-
using ScopToDepsMapTy = DenseMap<Scop *, std::unique_ptr<Dependences>>;
320-
321-
/// Scop to Dependence map for the current function.
322-
ScopToDepsMapTy ScopToDepsMap;
323-
};
324-
325-
llvm::Pass *createDependenceInfoWrapperPassPass();
326-
llvm::Pass *
327-
createDependenceInfoPrinterLegacyFunctionPass(llvm::raw_ostream &OS);
328-
236+
DependenceAnalysis::Result runDependenceAnalysis(Scop &S);
329237
} // namespace polly
330238

331-
namespace llvm {
332-
void initializeDependenceInfoPass(llvm::PassRegistry &);
333-
void initializeDependenceInfoPrinterLegacyPassPass(llvm::PassRegistry &);
334-
void initializeDependenceInfoWrapperPassPass(llvm::PassRegistry &);
335-
void initializeDependenceInfoPrinterLegacyFunctionPassPass(
336-
llvm::PassRegistry &);
337-
} // namespace llvm
338-
339239
#endif

polly/include/polly/FlattenSchedule.h

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,10 @@
1515
#ifndef POLLY_FLATTENSCHEDULE_H
1616
#define POLLY_FLATTENSCHEDULE_H
1717

18-
namespace llvm {
19-
class PassRegistry;
20-
class Pass;
21-
class raw_ostream;
22-
} // namespace llvm
23-
2418
namespace polly {
25-
llvm::Pass *createFlattenSchedulePass();
26-
llvm::Pass *createFlattenSchedulePrinterLegacyPass(llvm::raw_ostream &OS);
27-
} // namespace polly
19+
class Scop;
2820

29-
namespace llvm {
30-
void initializeFlattenSchedulePass(llvm::PassRegistry &);
31-
void initializeFlattenSchedulePrinterLegacyPassPass(llvm::PassRegistry &);
32-
} // namespace llvm
21+
void runFlattenSchedulePass(Scop &S);
22+
} // namespace polly
3323

3424
#endif /* POLLY_FLATTENSCHEDULE_H */

polly/include/polly/ForwardOpTree.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@
1515

1616
#include "polly/ScopPass.h"
1717

18-
namespace llvm {
19-
class PassRegistry;
20-
} // namespace llvm
21-
2218
namespace polly {
23-
llvm::Pass *createForwardOpTreeWrapperPass();
24-
llvm::Pass *createForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS);
2519

2620
struct ForwardOpTreePass final : llvm::PassInfoMixin<ForwardOpTreePass> {
2721
ForwardOpTreePass() {}
@@ -41,11 +35,15 @@ struct ForwardOpTreePrinterPass final
4135
llvm::raw_ostream &OS;
4236
};
4337

38+
/// Pass that redirects scalar reads to array elements that are known to contain
39+
/// the same value.
40+
///
41+
/// This reduces the number of scalar accesses and therefore potentially
42+
/// increases the freedom of the scheduler. In the ideal case, all reads of a
43+
/// scalar definition are redirected (We currently do not care about removing
44+
/// the write in this case). This is also useful for the main DeLICM pass as
45+
/// there are less scalars to be mapped.
46+
bool runForwardOpTree(Scop &S);
4447
} // namespace polly
4548

46-
namespace llvm {
47-
void initializeForwardOpTreeWrapperPassPass(PassRegistry &);
48-
void initializeForwardOpTreePrinterLegacyPassPass(PassRegistry &);
49-
} // namespace llvm
50-
5149
#endif // POLLY_FORWARDOPTREE_H

0 commit comments

Comments
 (0)