Polly 22.0.0git
PhaseManager.cpp
Go to the documentation of this file.
1//===------ PhaseManager.cpp ------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
13#include "polly/DeLICM.h"
17#include "polly/ForwardOpTree.h"
18#include "polly/JSONExporter.h"
22#include "polly/ScopDetection.h"
25#include "polly/ScopInfo.h"
26#include "polly/Simplify.h"
28#include "llvm/ADT/PriorityWorklist.h"
29#include "llvm/Analysis/AssumptionCache.h"
30#include "llvm/Analysis/OptimizationRemarkEmitter.h"
31#include "llvm/Analysis/TargetTransformInfo.h"
32#include "llvm/IR/Module.h"
33
34#define DEBUG_TYPE "polly-pass"
35
36using namespace polly;
37using namespace llvm;
38
39namespace {
40
41/// Recurse through all subregions and all regions and add them to RQ.
42static void addRegionIntoQueue(Region &R, SmallVector<Region *> &RQ) {
43 RQ.push_back(&R);
44 for (const auto &E : R)
45 addRegionIntoQueue(*E, RQ);
46}
47
48/// The phase pipeline of Polly to be embedded into another pass manager than
49/// runs passes on functions.
50///
51/// Polly holds state besides LLVM-IR (RegionInfo and ScopInfo) between phases
52/// that LLVM pass managers do not consider when scheduling analyses and passes.
53/// That is, the ScopInfo must persist between phases that a pass manager must
54/// not invalidate to recompute later.
55class PhaseManager {
56private:
57 Function &F;
58 FunctionAnalysisManager &FAM;
60
61public:
62 PhaseManager(Function &F, FunctionAnalysisManager &FAM, PollyPassOptions Opts)
63 : F(F), FAM(FAM), Opts(std::move(Opts)) {}
64
65 /// Execute Polly's phases as indicated by the options.
66 bool run() {
67 // Get analyses from the function pass manager.
68 // These must be preserved during all phases so that if processing one SCoP
69 // has finished, the next SCoP can still use them. Recomputing is not an
70 // option because ScopDetection stores references to the old results.
71 // TODO: CodePreparation doesn't actually need these analysis, it just keeps
72 // them up-to-date. If they are not computed yet, can also compute after the
73 // prepare phase.
74 LoopInfo &LI = FAM.getResult<LoopAnalysis>(F);
75 DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
76 bool ModifiedIR = false;
77
78 // Phase: prepare
79 // TODO: Setting ModifiedIR will invalidate any analysis, even if DT, LI are
80 // preserved.
82 if (runCodePreparation(F, &DT, &LI, nullptr)) {
83 PreservedAnalyses PA;
84 PA.preserve<DominatorTreeAnalysis>();
85 PA.preserve<LoopAnalysis>();
86 FAM.invalidate(F, PA);
87 ModifiedIR = true;
88 }
89 }
90
91 // Can't do anything without detection
93 return false;
94
95 AAResults &AA = FAM.getResult<AAManager>(F);
96 ScalarEvolution &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
97 OptimizationRemarkEmitter &ORE =
98 FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
99
100 // ScopDetection is modifying RegionInfo, do not cache it, nor use a cached
101 // version.
102 RegionInfo RI = RegionInfoAnalysis().run(F, FAM);
103
104 // Phase: detection
105 ScopDetection SD(DT, SE, LI, RI, AA, ORE);
106 SD.detect(F);
108 outs() << "Detected Scops in Function " << F.getName() << "\n";
109 for (const Region *R : SD.ValidRegions)
110 outs() << "Valid Region for Scop: " << R->getNameStr() << '\n';
111 outs() << "\n";
112 }
113
115 printGraphForFunction(F, &SD, "scops", false);
117 printGraphForFunction(F, &SD, "scopsonly", true);
118
119 auto ViewScops = [&](const char *Name, bool IsSimply) {
120 if (Opts.ViewFilter.empty() && !F.getName().count(Opts.ViewFilter))
121 return;
122
123 if (Opts.ViewAll || std::distance(SD.begin(), SD.end()) > 0)
124 viewGraphForFunction(F, &SD, Name, IsSimply);
125 };
127 ViewScops("scops", false);
129 ViewScops("scopsonly", true);
130
131 // Phase: scops
132 AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F);
133 const DataLayout &DL = F.getParent()->getDataLayout();
134 ScopInfo Info(DL, SD, SE, LI, AA, DT, AC, ORE);
136 if (Region *TLR = RI.getTopLevelRegion()) {
137 SmallVector<Region *> Regions;
138 addRegionIntoQueue(*TLR, Regions);
139
140 // reverse iteration because the regression tests expect it.
141 for (Region *R : reverse(Regions)) {
142 Scop *S = Info.getScop(R);
143 outs() << "Printing analysis 'Polly - Create polyhedral "
144 "description of Scops' for region: '"
145 << R->getNameStr() << "' in function '" << F.getName()
146 << "':\n";
147 if (S)
148 outs() << *S;
149 else
150 outs() << "Invalid Scop!\n";
151 }
152 }
153 }
154
155 SmallPriorityWorklist<Region *, 4> Worklist;
156 for (auto &[R, S] : Info)
157 if (S)
158 Worklist.insert(R);
159
160 TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
161 while (!Worklist.empty()) {
162 Region *R = Worklist.pop_back_val();
163 Scop *S = Info.getScop(R);
164 if (!S) {
165 // This can happen if codegenning of a previous SCoP made this region
166 // not-a-SCoP anymore.
167 POLLY_DEBUG(dbgs() << "SCoP in Region '" << *R << "' disappeared");
168 continue;
169 }
170
171 if (!SD.isMaxRegionInScop(*R, /*Verify=*/false))
172 continue;
173
174 // Phase: flatten
177
178 // Phase: deps
179 // Actual analysis runs on-demand, so it does not matter whether the phase
180 // is actually enabled, but use this location to print dependencies.
185 D.print(outs());
186 }
187
188 // Phase: import-jscop
190 runImportJSON(*S, DA);
191
192 // Phase: simplify-0
193 bool ModifiedSinceSimplify = true;
195 runSimplify(*S, 0);
196 ModifiedSinceSimplify = false;
197 }
198
199 // Phase: optree
201 bool ModifiedByOptree = runForwardOpTree(*S);
202 ModifiedSinceSimplify |= ModifiedByOptree;
203 }
204
205 // Phase: delicm
207 bool ModifiedByDelicm = runDeLICM(*S);
208 ModifiedSinceSimplify |= ModifiedByDelicm;
209 }
210
211 // Phase: simplify-1
212 // If we have already run simplify-0, do not re-run it if the SCoP has not
213 // changed since then.
214 if (ModifiedSinceSimplify && Opts.isPhaseEnabled(PassPhase::Simplify1)) {
215 runSimplify(*S, 1);
216 ModifiedSinceSimplify = false;
217 }
218
219 // Phase: dce
221 runDeadCodeElim(*S, DA);
222
223 // Phase: mse
226
227 // Phase: prune
230
231 // Phase: opt-isl
233 runIslScheduleOptimizer(*S, &TTI, DA);
234
235 // Phase: import-jscop
238
239 // Phase: ast
240 // Cannot run codegen unless ast is enabled
242 continue;
243 std::unique_ptr<IslAstInfo> IslAst = runIslAstGen(*S, DA);
244
245 // Phase: codegen
247 continue;
248 bool ModifiedByCodeGen = runCodeGeneration(*S, RI, *IslAst);
249 if (ModifiedByCodeGen) {
250 ModifiedIR = true;
251
252 // For all regions, create new polly::Scop objects because the old ones
253 // refere to invalidated LLVM-IR.
254 // FIXME: Adds all SCoPs again to statistics
255 Info.recompute();
256 }
257 }
258
259 return ModifiedIR;
260 }
261};
262} // namespace
263
265 switch (Phase) {
267 return "prepare";
269 return "detect";
271 return "print-detect";
273 return "dot-scops";
275 return "dot-scops-only";
277 return "view-scops";
279 return "view-scops-only";
281 return "scops";
283 return "print-scops";
285 return "flatten";
287 return "deps";
289 return "print-deps";
291 return "import-jscop";
293 return "simplify-0";
295 return "optree";
297 return "delicm";
299 return "simplify-1";
301 return "dce";
303 return "mse";
305 return "prune";
307 return "opt-isl"; // "opt" would conflict with the llvm executable
309 return "export-jscop";
311 return "ast";
313 return "codegen";
314 default:
315 llvm_unreachable("Unexpected phase");
316 }
317}
318
320 return StringSwitch<PassPhase>(Name)
321 .Case("prepare", PassPhase::Prepare)
322 .Case("detect", PassPhase::Detection)
323 .Case("print-detect", PassPhase::PrintDetect)
324 .Case("dot-scops", PassPhase::DotScops)
325 .Case("dot-scops-only", PassPhase::DotScopsOnly)
326 .Case("view-scops", PassPhase::ViewScops)
327 .Case("view-scops-only", PassPhase::ViewScopsOnly)
328 .Case("scops", PassPhase::ScopInfo)
329 .Case("print-scops", PassPhase::PrintScopInfo)
330 .Case("flatten", PassPhase::Flatten)
331 .Case("deps", PassPhase::Dependences)
332 .Case("print-deps", PassPhase::PrintDependences)
333 .Case("import-jscop", PassPhase::ImportJScop)
334 .Case("simplify-0", PassPhase::Simplify0)
335 .Case("optree", PassPhase::Optree)
336 .Case("delicm", PassPhase::DeLICM)
337 .Case("simplify-1", PassPhase::Simplify1)
340 .Case("prune", PassPhase::PruneUnprofitable)
341 .Case("opt-isl", PassPhase::Optimization)
342 .Case("export-jscop", PassPhase::ExportJScop)
343 .Case("ast", PassPhase::AstGen)
344 .Case("codegen", PassPhase::CodeGen)
345 .Default(PassPhase::None);
346}
347
349 // Nothing before dep phase can depend on it
350 if (static_cast<size_t>(Phase) <= static_cast<size_t>(PassPhase::Dependences))
351 return false;
352
353 switch (Phase) {
361 case PassPhase::AstGen: // transitively through codegen
363 return false;
364 default:
365 return true;
366 }
367}
368
376
386
388 assert(Phase != PassPhase::None);
389 for (PassPhase P : enum_seq_inclusive(Phase, PassPhase::PassPhaseLast)) {
390 if (P == Phase)
391 continue;
392 setPhaseEnabled(P, false);
393 }
394}
395
397 for (PassPhase P : enum_seq_inclusive(PassPhase::PassPhaseFirst,
399 if (!isPhaseEnabled(P))
400 continue;
401
402 // Prepare and Detection have no requirements
404 continue;
405
407 return make_error<StringError>(
408 formatv("'{0}' requires 'detect' to be enabled", getPhaseName(P))
409 .str(),
410 inconvertibleErrorCode());
411
412 if (static_cast<size_t>(P) < static_cast<size_t>(PassPhase::ScopInfo))
413 continue;
414
416 return make_error<StringError>(
417 formatv("'{0}' requires 'scops' to be enabled", getPhaseName(P))
418 .str(),
419 inconvertibleErrorCode());
420
422 return make_error<StringError>(
423 formatv("'{0}' requires 'deps' to be enabled", getPhaseName(P)).str(),
424 inconvertibleErrorCode());
425 }
426
428 return make_error<StringError>("'codegen' requires 'ast' to be enabled",
429 inconvertibleErrorCode());
430
431 return Error::success();
432}
433
434bool polly::runPollyPass(Function &F, FunctionAnalysisManager &FAM,
435 PollyPassOptions Opts) {
436 return PhaseManager(F, FAM, std::move(Opts)).run();
437}
#define POLLY_DEBUG(X)
Definition PollyDebug.h:23
The accumulated dependence information for a SCoP.
void print(llvm::raw_ostream &OS) const
Print the stored dependence information.
Options for the Polly pass.
Dependences::AnalysisLevel PrintDepsAnalysisLevel
void enableDefaultOpts()
Enabled the default optimization phases.
void setPhaseEnabled(PassPhase Phase, bool Enabled=true)
void enableEnd2End()
Enable all phases that are necessary for a roundtrip from LLVM-IR back to LLVM-IR.
void disableAfter(PassPhase Phase)
Disable all phases following Phase.
bool isPhaseEnabled(PassPhase Phase) const
llvm::Error checkConsistency() const
Check whether the options are coherent relative to each other.
Pass to detect the maximal static control parts (Scops) of a function.
void detect(Function &F)
bool isMaxRegionInScop(const Region &R, bool Verify=true)
Is the region is the maximum region of a Scop?
Scop * getScop(Region *R) const
Get the Scop object for the given Region.
Definition ScopInfo.h:2704
void recompute()
Recompute the Scop-Information for a function.
Static Control Part.
Definition ScopInfo.h:1625
std::string getNameStr() const
Get the name of this Scop.
#define S(TYPE, NAME)
const char * str
Definition isl_test.c:2095
#define assert(exp)
PassPhase parsePhase(StringRef Name)
void runExportJSON(Scop &S)
This pass exports a scop to a jscop file.
void runImportJSON(Scop &S, DependenceAnalysis::Result &DA)
This pass imports a scop from a jscop file.
StringRef getPhaseName(PassPhase Phase)
bool runCodePreparation(llvm::Function &F, llvm::DominatorTree *DT, llvm::LoopInfo *LI, llvm::RegionInfo *RI)
void runFlattenSchedulePass(Scop &S)
bool runPollyPass(Function &F, llvm::FunctionAnalysisManager &FAM, PollyPassOptions Opts)
Run Polly and its phases on F.
bool runPruneUnprofitable(Scop &S)
bool runDeadCodeElim(Scop &S, DependenceAnalysis::Result &DA)
DependenceAnalysis::Result runDependenceAnalysis(Scop &S)
bool runSimplify(Scop &S, int CallNo)
Definition Simplify.cpp:783
std::unique_ptr< IslAstInfo > runIslAstGen(Scop &S, DependenceAnalysis::Result &DA)
Definition IslAst.cpp:765
bool runCodeGeneration(Scop &S, llvm::RegionInfo &RI, IslAstInfo &AI)
bool dependsOnDependenceInfo(PassPhase Phase)
PassPhase
Phases (in execution order) within the Polly pass.
bool runForwardOpTree(Scop &S)
Pass that redirects scalar reads to array elements that are known to contain the same value.
bool runDeLICM(Scop &S)
Definition DeLICM.cpp:1412
void runIslScheduleOptimizer(Scop &S, llvm::TargetTransformInfo *TTI, DependenceAnalysis::Result &Deps)
void runMaximalStaticExpansion(Scop &S, DependenceAnalysis::Result &DI)
const Dependences & getDependences(Dependences::AnalysisLevel Level)
Return the dependence information for the current SCoP.