Polly 23.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 // Can't do anything after this without ScopInfo.
133 return false;
134
135 // Phase: scops
136 AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F);
137 const DataLayout &DL = F.getParent()->getDataLayout();
138 ScopInfo Info(DL, SD, SE, LI, AA, DT, AC, ORE);
140 if (Region *TLR = RI.getTopLevelRegion()) {
141 SmallVector<Region *> Regions;
142 addRegionIntoQueue(*TLR, Regions);
143
144 // reverse iteration because the regression tests expect it.
145 for (Region *R : reverse(Regions)) {
146 Scop *S = Info.getScop(R);
147 outs() << "Printing analysis 'Polly - Create polyhedral "
148 "description of Scops' for region: '"
149 << R->getNameStr() << "' in function '" << F.getName()
150 << "':\n";
151 if (S)
152 outs() << *S;
153 else
154 outs() << "Invalid Scop!\n";
155 }
156 }
157 }
158
159 SmallPriorityWorklist<const Region *, 4> Worklist;
160 for (const Region *R : SD)
161 Worklist.insert(R);
162
163 TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);
164 while (!Worklist.empty()) {
165 const Region *R = Worklist.pop_back_val();
166 Scop *S = Info.getScop(R);
167 if (!S) {
168 // This can happen if the region is not maximal, is not determined a
169 // valid SCoP by ScopBuilder, or codegenning of a previous SCoP made
170 // this region not-a-SCoP anymore.
171 POLLY_DEBUG(dbgs() << "SCoP in Region '" << *R << "' disappeared");
172 continue;
173 }
174
175 if (!SD.isMaxRegionInScop(*R, /*Verify=*/false))
176 continue;
177
178 // Phase: flatten
181
182 // Phase: deps
183 // Actual analysis runs on-demand, so it does not matter whether the phase
184 // is actually enabled, but use this location to print dependencies.
189 D.print(outs());
190 }
191
192 // Phase: import-jscop
194 runImportJSON(*S, DA);
195
196 // Phase: simplify-0
197 bool ModifiedSinceSimplify = true;
199 runSimplify(*S, 0);
200 ModifiedSinceSimplify = false;
201 }
202
203 // Phase: optree
205 bool ModifiedByOptree = runForwardOpTree(*S);
206 ModifiedSinceSimplify |= ModifiedByOptree;
207 }
208
209 // Phase: delicm
211 bool ModifiedByDelicm = runDeLICM(*S);
212 ModifiedSinceSimplify |= ModifiedByDelicm;
213 }
214
215 // Phase: simplify-1
216 // If we have already run simplify-0, do not re-run it if the SCoP has not
217 // changed since then.
218 if (ModifiedSinceSimplify && Opts.isPhaseEnabled(PassPhase::Simplify1)) {
219 runSimplify(*S, 1);
220 ModifiedSinceSimplify = false;
221 }
222
223 // Phase: dce
225 runDeadCodeElim(*S, DA);
226
227 // Phase: mse
230
231 // Phase: prune
234
235 // Phase: opt-isl
237 runIslScheduleOptimizer(*S, &TTI, DA);
238
239 // Phase: import-jscop
242
243 // Phase: ast
244 // Cannot run codegen unless ast is enabled
246 continue;
247 std::unique_ptr<IslAstInfo> IslAst = runIslAstGen(*S, DA);
248
249 // Phase: codegen
251 continue;
252 bool ModifiedByCodeGen = runCodeGeneration(*S, RI, *IslAst);
253 if (ModifiedByCodeGen) {
254 ModifiedIR = true;
255
256 // Discard old polly::Scop objects because they may refer to invalidated
257 // LLVM-IR instructions and SCEV expressions. ScopInfo will recreate
258 // them on demand.
259 Info.invalidate();
260 }
261 }
262
263 return ModifiedIR;
264 }
265};
266} // namespace
267
269 switch (Phase) {
271 return "prepare";
273 return "detect";
275 return "print-detect";
277 return "dot-scops";
279 return "dot-scops-only";
281 return "view-scops";
283 return "view-scops-only";
285 return "scops";
287 return "print-scops";
289 return "flatten";
291 return "deps";
293 return "print-deps";
295 return "import-jscop";
297 return "simplify-0";
299 return "optree";
301 return "delicm";
303 return "simplify-1";
305 return "dce";
307 return "mse";
309 return "prune";
311 return "opt-isl"; // "opt" would conflict with the llvm executable
313 return "export-jscop";
315 return "ast";
317 return "codegen";
318 default:
319 llvm_unreachable("Unexpected phase");
320 }
321}
322
324 return StringSwitch<PassPhase>(Name)
325 .Case("prepare", PassPhase::Prepare)
326 .Case("detect", PassPhase::Detection)
327 .Case("print-detect", PassPhase::PrintDetect)
328 .Case("dot-scops", PassPhase::DotScops)
329 .Case("dot-scops-only", PassPhase::DotScopsOnly)
330 .Case("view-scops", PassPhase::ViewScops)
331 .Case("view-scops-only", PassPhase::ViewScopsOnly)
332 .Case("scops", PassPhase::ScopInfo)
333 .Case("print-scops", PassPhase::PrintScopInfo)
334 .Case("flatten", PassPhase::Flatten)
335 .Case("deps", PassPhase::Dependences)
336 .Case("print-deps", PassPhase::PrintDependences)
337 .Case("import-jscop", PassPhase::ImportJScop)
338 .Case("simplify-0", PassPhase::Simplify0)
339 .Case("optree", PassPhase::Optree)
340 .Case("delicm", PassPhase::DeLICM)
341 .Case("simplify-1", PassPhase::Simplify1)
344 .Case("prune", PassPhase::PruneUnprofitable)
345 .Case("opt-isl", PassPhase::Optimization)
346 .Case("export-jscop", PassPhase::ExportJScop)
347 .Case("ast", PassPhase::AstGen)
348 .Case("codegen", PassPhase::CodeGen)
349 .Default(PassPhase::None);
350}
351
353 // Nothing before dep phase can depend on it
354 if (static_cast<size_t>(Phase) <= static_cast<size_t>(PassPhase::Dependences))
355 return false;
356
357 switch (Phase) {
365 case PassPhase::AstGen: // transitively through codegen
367 return false;
368 default:
369 return true;
370 }
371}
372
380
390
392 assert(Phase != PassPhase::None);
393 for (PassPhase P : enum_seq_inclusive(Phase, PassPhase::PassPhaseLast)) {
394 if (P == Phase)
395 continue;
396 setPhaseEnabled(P, false);
397 }
398}
399
401 for (PassPhase P : enum_seq_inclusive(PassPhase::PassPhaseFirst,
403 if (!isPhaseEnabled(P))
404 continue;
405
406 // Prepare and Detection have no requirements
408 continue;
409
411 return make_error<StringError>(
412 formatv("'{0}' requires 'detect' to be enabled", getPhaseName(P))
413 .str(),
414 inconvertibleErrorCode());
415
416 if (static_cast<size_t>(P) < static_cast<size_t>(PassPhase::ScopInfo))
417 continue;
418
420 return make_error<StringError>(
421 formatv("'{0}' requires 'scops' to be enabled", getPhaseName(P))
422 .str(),
423 inconvertibleErrorCode());
424
426 return make_error<StringError>(
427 formatv("'{0}' requires 'deps' to be enabled", getPhaseName(P)).str(),
428 inconvertibleErrorCode());
429 }
430
432 return make_error<StringError>("'codegen' requires 'ast' to be enabled",
433 inconvertibleErrorCode());
434
435 return Error::success();
436}
437
438bool polly::runPollyPass(Function &F, FunctionAnalysisManager &FAM,
439 PollyPassOptions Opts) {
440 return PhaseManager(F, FAM, std::move(Opts)).run();
441}
#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?
void invalidate()
Recompute the Scop-Information for a function.
Scop * getScop(const Region *R)
Get the Scop object for the given Region.
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:1880
#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.