1 //===------ RegisterPasses.cpp - Add the Polly Passes to default passes  --===//
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 //
9 // This file composes the individual LLVM-IR passes provided by Polly to a
10 // functional polyhedral optimizer. The polyhedral optimizer is automatically
11 // made available to LLVM based compilers by loading the Polly shared library
12 // into such a compiler.
13 //
14 // The Polly optimizer is made available by executing a static constructor that
15 // registers the individual Polly passes in the LLVM pass manager builder. The
16 // passes are registered such that the default behaviour of the compiler is not
17 // changed, but that the flag '-polly' provided at optimization level '-O3'
18 // enables additional polyhedral optimizations.
19 //===----------------------------------------------------------------------===//
20 
21 #include "polly/RegisterPasses.h"
22 #include "polly/Canonicalization.h"
23 #include "polly/CodeGen/CodeGeneration.h"
24 #include "polly/CodeGen/CodegenCleanup.h"
25 #include "polly/CodeGen/IslAst.h"
26 #include "polly/CodePreparation.h"
27 #include "polly/DependenceInfo.h"
28 #include "polly/ForwardOpTree.h"
29 #include "polly/JSONExporter.h"
30 #include "polly/LinkAllPasses.h"
31 #include "polly/PolyhedralInfo.h"
32 #include "polly/ScopDetection.h"
33 #include "polly/ScopInfo.h"
34 #include "polly/Simplify.h"
35 #include "polly/Support/DumpModulePass.h"
36 #include "llvm/Analysis/CFGPrinter.h"
37 #include "llvm/IR/LegacyPassManager.h"
38 #include "llvm/IR/Verifier.h"
39 #include "llvm/Passes/PassBuilder.h"
40 #include "llvm/Passes/PassPlugin.h"
41 #include "llvm/Support/CommandLine.h"
42 #include "llvm/Support/TargetSelect.h"
43 #include "llvm/Transforms/IPO.h"
44 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
45 
46 using namespace llvm;
47 using namespace polly;
48 
49 cl::OptionCategory PollyCategory("Polly Options",
50                                  "Configure the polly loop optimizer");
51 
52 static cl::opt<bool>
53     PollyEnabled("polly", cl::desc("Enable the polly optimizer (only at -O3)"),
54                  cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
55 
56 static cl::opt<bool> PollyDetectOnly(
57     "polly-only-scop-detection",
58     cl::desc("Only run scop detection, but no other optimizations"),
59     cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
60 
61 enum PassPositionChoice {
62   POSITION_EARLY,
63   POSITION_AFTER_LOOPOPT,
64   POSITION_BEFORE_VECTORIZER
65 };
66 
67 enum OptimizerChoice { OPTIMIZER_NONE, OPTIMIZER_ISL };
68 
69 static cl::opt<PassPositionChoice> PassPosition(
70     "polly-position", cl::desc("Where to run polly in the pass pipeline"),
71     cl::values(
72         clEnumValN(POSITION_EARLY, "early", "Before everything"),
73         clEnumValN(POSITION_AFTER_LOOPOPT, "after-loopopt",
74                    "After the loop optimizer (but within the inline cycle)"),
75         clEnumValN(POSITION_BEFORE_VECTORIZER, "before-vectorizer",
76                    "Right before the vectorizer")),
77     cl::Hidden, cl::init(POSITION_BEFORE_VECTORIZER), cl::ZeroOrMore,
78     cl::cat(PollyCategory));
79 
80 static cl::opt<OptimizerChoice>
81     Optimizer("polly-optimizer", cl::desc("Select the scheduling optimizer"),
82               cl::values(clEnumValN(OPTIMIZER_NONE, "none", "No optimizer"),
83                          clEnumValN(OPTIMIZER_ISL, "isl",
84                                     "The isl scheduling optimizer")),
85               cl::Hidden, cl::init(OPTIMIZER_ISL), cl::ZeroOrMore,
86               cl::cat(PollyCategory));
87 
88 enum CodeGenChoice { CODEGEN_FULL, CODEGEN_AST, CODEGEN_NONE };
89 static cl::opt<CodeGenChoice> CodeGeneration(
90     "polly-code-generation", cl::desc("How much code-generation to perform"),
91     cl::values(clEnumValN(CODEGEN_FULL, "full", "AST and IR generation"),
92                clEnumValN(CODEGEN_AST, "ast", "Only AST generation"),
93                clEnumValN(CODEGEN_NONE, "none", "No code generation")),
94     cl::Hidden, cl::init(CODEGEN_FULL), cl::ZeroOrMore, cl::cat(PollyCategory));
95 
96 enum TargetChoice { TARGET_CPU, TARGET_GPU, TARGET_HYBRID };
97 static cl::opt<TargetChoice>
98     Target("polly-target", cl::desc("The hardware to target"),
99            cl::values(clEnumValN(TARGET_CPU, "cpu", "generate CPU code")
100 #ifdef GPU_CODEGEN
101                           ,
102                       clEnumValN(TARGET_GPU, "gpu", "generate GPU code"),
103                       clEnumValN(TARGET_HYBRID, "hybrid",
104                                  "generate GPU code (preferably) or CPU code")
105 #endif
106                           ),
107            cl::init(TARGET_CPU), cl::ZeroOrMore, cl::cat(PollyCategory));
108 
109 #ifdef GPU_CODEGEN
110 static cl::opt<GPURuntime> GPURuntimeChoice(
111     "polly-gpu-runtime", cl::desc("The GPU Runtime API to target"),
112     cl::values(clEnumValN(GPURuntime::CUDA, "libcudart",
113                           "use the CUDA Runtime API"),
114                clEnumValN(GPURuntime::OpenCL, "libopencl",
115                           "use the OpenCL Runtime API")),
116     cl::init(GPURuntime::CUDA), cl::ZeroOrMore, cl::cat(PollyCategory));
117 
118 static cl::opt<GPUArch>
119     GPUArchChoice("polly-gpu-arch", cl::desc("The GPU Architecture to target"),
120                   cl::values(clEnumValN(GPUArch::NVPTX64, "nvptx64",
121                                         "target NVIDIA 64-bit architecture"),
122                              clEnumValN(GPUArch::SPIR32, "spir32",
123                                         "target SPIR 32-bit architecture"),
124                              clEnumValN(GPUArch::SPIR64, "spir64",
125                                         "target SPIR 64-bit architecture")),
126                   cl::init(GPUArch::NVPTX64), cl::ZeroOrMore,
127                   cl::cat(PollyCategory));
128 #endif
129 
130 VectorizerChoice polly::PollyVectorizerChoice;
131 static cl::opt<polly::VectorizerChoice, true> Vectorizer(
132     "polly-vectorizer", cl::desc("Select the vectorization strategy"),
133     cl::values(
134         clEnumValN(polly::VECTORIZER_NONE, "none", "No Vectorization"),
135         clEnumValN(polly::VECTORIZER_POLLY, "polly",
136                    "Polly internal vectorizer"),
137         clEnumValN(
138             polly::VECTORIZER_STRIPMINE, "stripmine",
139             "Strip-mine outer loops for the loop-vectorizer to trigger")),
140     cl::location(PollyVectorizerChoice), cl::init(polly::VECTORIZER_NONE),
141     cl::ZeroOrMore, cl::cat(PollyCategory));
142 
143 static cl::opt<bool> ImportJScop(
144     "polly-import",
145     cl::desc("Import the polyhedral description of the detected Scops"),
146     cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
147 
148 static cl::opt<bool> FullyIndexedStaticExpansion(
149     "polly-enable-mse",
150     cl::desc("Fully expand the memory accesses of the detected Scops"),
151     cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
152 
153 static cl::opt<bool> ExportJScop(
154     "polly-export",
155     cl::desc("Export the polyhedral description of the detected Scops"),
156     cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
157 
158 static cl::opt<bool> DeadCodeElim("polly-run-dce",
159                                   cl::desc("Run the dead code elimination"),
160                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
161                                   cl::cat(PollyCategory));
162 
163 static cl::opt<bool> PollyViewer(
164     "polly-show",
165     cl::desc("Highlight the code regions that will be optimized in a "
166              "(CFG BBs and LLVM-IR instructions)"),
167     cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
168 
169 static cl::opt<bool> PollyOnlyViewer(
170     "polly-show-only",
171     cl::desc("Highlight the code regions that will be optimized in "
172              "a (CFG only BBs)"),
173     cl::init(false), cl::cat(PollyCategory));
174 
175 static cl::opt<bool>
176     PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"),
177                  cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"),
178                  cl::init(false), cl::cat(PollyCategory));
179 
180 static cl::opt<bool> PollyOnlyPrinter(
181     "polly-dot-only",
182     cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden,
183     cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"),
184     cl::init(false), cl::cat(PollyCategory));
185 
186 static cl::opt<bool>
187     CFGPrinter("polly-view-cfg",
188                cl::desc("Show the Polly CFG right after code generation"),
189                cl::Hidden, cl::init(false), cl::cat(PollyCategory));
190 
191 static cl::opt<bool>
192     EnablePolyhedralInfo("polly-enable-polyhedralinfo",
193                          cl::desc("Enable polyhedral interface of Polly"),
194                          cl::Hidden, cl::init(false), cl::cat(PollyCategory));
195 
196 static cl::opt<bool>
197     EnableForwardOpTree("polly-enable-optree",
198                         cl::desc("Enable operand tree forwarding"), cl::Hidden,
199                         cl::init(true), cl::cat(PollyCategory));
200 
201 static cl::opt<bool>
202     DumpBefore("polly-dump-before",
203                cl::desc("Dump module before Polly transformations into a file "
204                         "suffixed with \"-before\""),
205                cl::init(false), cl::cat(PollyCategory));
206 
207 static cl::list<std::string> DumpBeforeFile(
208     "polly-dump-before-file",
209     cl::desc("Dump module before Polly transformations to the given file"),
210     cl::cat(PollyCategory));
211 
212 static cl::opt<bool>
213     DumpAfter("polly-dump-after",
214               cl::desc("Dump module after Polly transformations into a file "
215                        "suffixed with \"-after\""),
216               cl::init(false), cl::cat(PollyCategory));
217 
218 static cl::list<std::string> DumpAfterFile(
219     "polly-dump-after-file",
220     cl::desc("Dump module after Polly transformations to the given file"),
221     cl::ZeroOrMore, cl::cat(PollyCategory));
222 
223 static cl::opt<bool>
224     EnableDeLICM("polly-enable-delicm",
225                  cl::desc("Eliminate scalar loop carried dependences"),
226                  cl::Hidden, cl::init(true), cl::cat(PollyCategory));
227 
228 static cl::opt<bool>
229     EnableSimplify("polly-enable-simplify",
230                    cl::desc("Simplify SCoP after optimizations"),
231                    cl::init(true), cl::cat(PollyCategory));
232 
233 static cl::opt<bool> EnablePruneUnprofitable(
234     "polly-enable-prune-unprofitable",
235     cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden,
236     cl::init(true), cl::cat(PollyCategory));
237 
238 namespace polly {
239 void initializePollyPasses(PassRegistry &Registry) {
240   initializeCodeGenerationPass(Registry);
241 
242 #ifdef GPU_CODEGEN
243   initializePPCGCodeGenerationPass(Registry);
244   initializeManagedMemoryRewritePassPass(Registry);
245   LLVMInitializeNVPTXTarget();
246   LLVMInitializeNVPTXTargetInfo();
247   LLVMInitializeNVPTXTargetMC();
248   LLVMInitializeNVPTXAsmPrinter();
249 #endif
250   initializeCodePreparationPass(Registry);
251   initializeDeadCodeElimPass(Registry);
252   initializeDependenceInfoPass(Registry);
253   initializeDependenceInfoWrapperPassPass(Registry);
254   initializeJSONExporterPass(Registry);
255   initializeJSONImporterPass(Registry);
256   initializeMaximalStaticExpanderPass(Registry);
257   initializeIslAstInfoWrapperPassPass(Registry);
258   initializeIslScheduleOptimizerPass(Registry);
259   initializePollyCanonicalizePass(Registry);
260   initializePolyhedralInfoPass(Registry);
261   initializeScopDetectionWrapperPassPass(Registry);
262   initializeScopInlinerPass(Registry);
263   initializeScopInfoRegionPassPass(Registry);
264   initializeScopInfoWrapperPassPass(Registry);
265   initializeRewriteByrefParamsPass(Registry);
266   initializeCodegenCleanupPass(Registry);
267   initializeFlattenSchedulePass(Registry);
268   initializeForwardOpTreePass(Registry);
269   initializeDeLICMPass(Registry);
270   initializeSimplifyPass(Registry);
271   initializeDumpModulePass(Registry);
272   initializePruneUnprofitablePass(Registry);
273 }
274 
275 /// Register Polly passes such that they form a polyhedral optimizer.
276 ///
277 /// The individual Polly passes are registered in the pass manager such that
278 /// they form a full polyhedral optimizer. The flow of the optimizer starts with
279 /// a set of preparing transformations that canonicalize the LLVM-IR such that
280 /// the LLVM-IR is easier for us to understand and to optimizes. On the
281 /// canonicalized LLVM-IR we first run the ScopDetection pass, which detects
282 /// static control flow regions. Those regions are then translated by the
283 /// ScopInfo pass into a polyhedral representation. As a next step, a scheduling
284 /// optimizer is run on the polyhedral representation and finally the optimized
285 /// polyhedral representation is code generated back to LLVM-IR.
286 ///
287 /// Besides this core functionality, we optionally schedule passes that provide
288 /// a graphical view of the scops (Polly[Only]Viewer, Polly[Only]Printer), that
289 /// allow the export/import of the polyhedral representation
290 /// (JSCON[Exporter|Importer]) or that show the cfg after code generation.
291 ///
292 /// For certain parts of the Polly optimizer, several alternatives are provided:
293 ///
294 /// As scheduling optimizer we support the isl scheduling optimizer
295 /// (http://freecode.com/projects/isl).
296 /// It is also possible to run Polly with no optimizer. This mode is mainly
297 /// provided to analyze the run and compile time changes caused by the
298 /// scheduling optimizer.
299 ///
300 /// Polly supports the isl internal code generator.
301 void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
302   if (DumpBefore)
303     PM.add(polly::createDumpModulePass("-before", true));
304   for (auto &Filename : DumpBeforeFile)
305     PM.add(polly::createDumpModulePass(Filename, false));
306 
307   PM.add(polly::createScopDetectionWrapperPassPass());
308 
309   if (PollyDetectOnly)
310     return;
311 
312   if (PollyViewer)
313     PM.add(polly::createDOTViewerPass());
314   if (PollyOnlyViewer)
315     PM.add(polly::createDOTOnlyViewerPass());
316   if (PollyPrinter)
317     PM.add(polly::createDOTPrinterPass());
318   if (PollyOnlyPrinter)
319     PM.add(polly::createDOTOnlyPrinterPass());
320 
321   PM.add(polly::createScopInfoRegionPassPass());
322   if (EnablePolyhedralInfo)
323     PM.add(polly::createPolyhedralInfoPass());
324 
325   if (EnableSimplify)
326     PM.add(polly::createSimplifyPass(0));
327   if (EnableForwardOpTree)
328     PM.add(polly::createForwardOpTreePass());
329   if (EnableDeLICM)
330     PM.add(polly::createDeLICMPass());
331   if (EnableSimplify)
332     PM.add(polly::createSimplifyPass(1));
333 
334   if (ImportJScop)
335     PM.add(polly::createJSONImporterPass());
336 
337   if (DeadCodeElim)
338     PM.add(polly::createDeadCodeElimPass());
339 
340   if (FullyIndexedStaticExpansion)
341     PM.add(polly::createMaximalStaticExpansionPass());
342 
343   if (EnablePruneUnprofitable)
344     PM.add(polly::createPruneUnprofitablePass());
345 
346 #ifdef GPU_CODEGEN
347   if (Target == TARGET_HYBRID)
348     PM.add(
349         polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
350 #endif
351   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
352     switch (Optimizer) {
353     case OPTIMIZER_NONE:
354       break; /* Do nothing */
355 
356     case OPTIMIZER_ISL:
357       PM.add(polly::createIslScheduleOptimizerPass());
358       break;
359     }
360 
361   if (ExportJScop)
362     PM.add(polly::createJSONExporterPass());
363 
364   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
365     switch (CodeGeneration) {
366     case CODEGEN_AST:
367       PM.add(polly::createIslAstInfoWrapperPassPass());
368       break;
369     case CODEGEN_FULL:
370       PM.add(polly::createCodeGenerationPass());
371       break;
372     case CODEGEN_NONE:
373       break;
374     }
375 #ifdef GPU_CODEGEN
376   else {
377     PM.add(
378         polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
379     PM.add(polly::createManagedMemoryRewritePassPass());
380   }
381 #endif
382 
383 #ifdef GPU_CODEGEN
384   if (Target == TARGET_HYBRID)
385     PM.add(polly::createManagedMemoryRewritePassPass(GPUArchChoice,
386                                                      GPURuntimeChoice));
387 #endif
388 
389   // FIXME: This dummy ModulePass keeps some programs from miscompiling,
390   // probably some not correctly preserved analyses. It acts as a barrier to
391   // force all analysis results to be recomputed.
392   PM.add(createBarrierNoopPass());
393 
394   if (DumpAfter)
395     PM.add(polly::createDumpModulePass("-after", true));
396   for (auto &Filename : DumpAfterFile)
397     PM.add(polly::createDumpModulePass(Filename, false));
398 
399   if (CFGPrinter)
400     PM.add(llvm::createCFGPrinterLegacyPassPass());
401 }
402 
403 static bool shouldEnablePolly() {
404   if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)
405     PollyTrackFailures = true;
406 
407   if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||
408       ExportJScop || ImportJScop)
409     PollyEnabled = true;
410 
411   return PollyEnabled;
412 }
413 
414 static void
415 registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
416                                    llvm::legacy::PassManagerBase &PM) {
417   if (!polly::shouldEnablePolly())
418     return;
419 
420   if (PassPosition != POSITION_EARLY)
421     return;
422 
423   registerCanonicalicationPasses(PM);
424   polly::registerPollyPasses(PM);
425 }
426 
427 static void
428 registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder,
429                                     llvm::legacy::PassManagerBase &PM) {
430   if (!polly::shouldEnablePolly())
431     return;
432 
433   if (PassPosition != POSITION_AFTER_LOOPOPT)
434     return;
435 
436   PM.add(polly::createCodePreparationPass());
437   polly::registerPollyPasses(PM);
438   PM.add(createCodegenCleanupPass());
439 }
440 
441 static void
442 registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder,
443                                        llvm::legacy::PassManagerBase &PM) {
444   if (!polly::shouldEnablePolly())
445     return;
446 
447   if (PassPosition != POSITION_BEFORE_VECTORIZER)
448     return;
449 
450   PM.add(polly::createCodePreparationPass());
451   polly::registerPollyPasses(PM);
452   PM.add(createCodegenCleanupPass());
453 }
454 
455 static void buildDefaultPollyPipeline(FunctionPassManager &PM,
456                                       PassBuilder::OptimizationLevel Level) {
457   if (!polly::shouldEnablePolly())
458     return;
459   PassBuilder PB;
460   ScopPassManager SPM;
461 
462   // TODO add utility passes for the various command line options, once they're
463   // ported
464   assert(!DumpBefore && "This option is not implemented");
465   assert(DumpBeforeFile.empty() && "This option is not implemented");
466 
467   if (PollyDetectOnly)
468     return;
469 
470   assert(!PollyViewer && "This option is not implemented");
471   assert(!PollyOnlyViewer && "This option is not implemented");
472   assert(!PollyPrinter && "This option is not implemented");
473   assert(!PollyOnlyPrinter && "This option is not implemented");
474   assert(!EnablePolyhedralInfo && "This option is not implemented");
475   assert(!EnableDeLICM && "This option is not implemented");
476   assert(!EnableSimplify && "This option is not implemented");
477   if (ImportJScop)
478     SPM.addPass(JSONImportPass());
479   assert(!DeadCodeElim && "This option is not implemented");
480   assert(!EnablePruneUnprofitable && "This option is not implemented");
481   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
482     switch (Optimizer) {
483     case OPTIMIZER_NONE:
484       break; /* Do nothing */
485     case OPTIMIZER_ISL:
486       llvm_unreachable("ISL optimizer is not implemented");
487       break;
488     }
489 
490   assert(!ExportJScop && "This option is not implemented");
491 
492   if (Target == TARGET_CPU || Target == TARGET_HYBRID) {
493     switch (CodeGeneration) {
494     case CODEGEN_FULL:
495       SPM.addPass(polly::CodeGenerationPass());
496       break;
497     case CODEGEN_AST:
498     default: // Does it actually make sense to distinguish IslAst codegen?
499       break;
500     }
501   }
502 #ifdef GPU_CODEGEN
503   else
504     llvm_unreachable("Hybrid Target with GPU support is not implemented");
505 #endif
506 
507   PM.addPass(CodePreparationPass());
508   PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
509   PM.addPass(PB.buildFunctionSimplificationPipeline(
510       Level, PassBuilder::ThinLTOPhase::None)); // Cleanup
511 
512   assert(!DumpAfter && "This option is not implemented");
513   assert(DumpAfterFile.empty() && "This option is not implemented");
514 
515   if (CFGPrinter)
516     PM.addPass(llvm::CFGPrinterPass());
517 }
518 
519 /// Register Polly to be available as an optimizer
520 ///
521 ///
522 /// We can currently run Polly at three different points int the pass manager.
523 /// a) very early, b) after the canonicalizing loop transformations and c) right
524 /// before the vectorizer.
525 ///
526 /// The default is currently a), to register Polly such that it runs as early as
527 /// possible. This has several implications:
528 ///
529 ///   1) We need to schedule more canonicalization passes
530 ///
531 ///   As nothing is run before Polly, it is necessary to run a set of preparing
532 ///   transformations before Polly to canonicalize the LLVM-IR and to allow
533 ///   Polly to detect and understand the code.
534 ///
535 ///   2) LICM and LoopIdiom pass have not yet been run
536 ///
537 ///   Loop invariant code motion as well as the loop idiom recognition pass make
538 ///   it more difficult for Polly to transform code. LICM may introduce
539 ///   additional data dependences that are hard to eliminate and the loop idiom
540 ///   recognition pass may introduce calls to memset that we currently do not
541 ///   understand. By running Polly early enough (meaning before these passes) we
542 ///   avoid difficulties that may be introduced by these passes.
543 ///
544 ///   3) We get the full -O3 optimization sequence after Polly
545 ///
546 ///   The LLVM-IR that is generated by Polly has been optimized on a high level,
547 ///   but it may be rather inefficient on the lower/scalar level. By scheduling
548 ///   Polly before all other passes, we have the full sequence of -O3
549 ///   optimizations behind us, such that inefficiencies on the low level can
550 ///   be optimized away.
551 ///
552 /// We are currently evaluating the benefit or running Polly at position b) or
553 /// c). b) is likely too early as it interacts with the inliner. c) is nice
554 /// as everything is fully inlined and canonicalized, but we need to be able
555 /// to handle LICMed code to make it useful.
556 static llvm::RegisterStandardPasses RegisterPollyOptimizerEarly(
557     llvm::PassManagerBuilder::EP_ModuleOptimizerEarly,
558     registerPollyEarlyAsPossiblePasses);
559 
560 static llvm::RegisterStandardPasses
561     RegisterPollyOptimizerLoopEnd(llvm::PassManagerBuilder::EP_LoopOptimizerEnd,
562                                   registerPollyLoopOptimizerEndPasses);
563 
564 static llvm::RegisterStandardPasses RegisterPollyOptimizerScalarLate(
565     llvm::PassManagerBuilder::EP_VectorizerStart,
566     registerPollyScalarOptimizerLatePasses);
567 
568 static OwningScopAnalysisManagerFunctionProxy
569 createScopAnalyses(FunctionAnalysisManager &FAM) {
570   OwningScopAnalysisManagerFunctionProxy Proxy;
571 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
572   Proxy.getManager().registerPass([] { return CREATE_PASS; });
573 
574 #include "PollyPasses.def"
575 
576   Proxy.getManager().registerPass(
577       [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); });
578   return Proxy;
579 }
580 
581 static void registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
582 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
583   FAM.registerPass([] { return CREATE_PASS; });
584 
585 #include "PollyPasses.def"
586 
587   FAM.registerPass([&FAM] { return createScopAnalyses(FAM); });
588 }
589 
590 static bool
591 parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,
592                       ArrayRef<PassBuilder::PipelineElement> Pipeline) {
593   if (parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>(
594           "polly-scop-analyses", Name, FPM))
595     return true;
596 
597 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
598   if (parseAnalysisUtilityPasses<                                              \
599           std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
600                                                               FPM))            \
601     return true;
602 
603 #define FUNCTION_PASS(NAME, CREATE_PASS)                                       \
604   if (Name == NAME) {                                                          \
605     FPM.addPass(CREATE_PASS);                                                  \
606     return true;                                                               \
607   }
608 
609 #include "PollyPasses.def"
610   return false;
611 }
612 
613 static bool parseScopPass(StringRef Name, ScopPassManager &SPM) {
614 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
615   if (parseAnalysisUtilityPasses<                                              \
616           std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
617                                                               SPM))            \
618     return true;
619 
620 #define SCOP_PASS(NAME, CREATE_PASS)                                           \
621   if (Name == NAME) {                                                          \
622     SPM.addPass(CREATE_PASS);                                                  \
623     return true;                                                               \
624   }
625 
626 #include "PollyPasses.def"
627 
628   return false;
629 }
630 
631 static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM,
632                               ArrayRef<PassBuilder::PipelineElement> Pipeline) {
633   if (Name != "scop")
634     return false;
635   if (!Pipeline.empty()) {
636     ScopPassManager SPM;
637     for (const auto &E : Pipeline)
638       if (!parseScopPass(E.Name, SPM))
639         return false;
640     FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
641   }
642   return true;
643 }
644 
645 static bool isScopPassName(StringRef Name) {
646 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
647   if (Name == "require<" NAME ">")                                             \
648     return true;                                                               \
649   if (Name == "invalidate<" NAME ">")                                          \
650     return true;
651 
652 #define SCOP_PASS(NAME, CREATE_PASS)                                           \
653   if (Name == NAME)                                                            \
654     return true;
655 
656 #include "PollyPasses.def"
657 
658   return false;
659 }
660 
661 static bool
662 parseTopLevelPipeline(ModulePassManager &MPM,
663                       ArrayRef<PassBuilder::PipelineElement> Pipeline,
664                       bool VerifyEachPass, bool DebugLogging) {
665   std::vector<PassBuilder::PipelineElement> FullPipeline;
666   StringRef FirstName = Pipeline.front().Name;
667 
668   if (!isScopPassName(FirstName))
669     return false;
670 
671   FunctionPassManager FPM(DebugLogging);
672   ScopPassManager SPM(DebugLogging);
673 
674   for (auto &Element : Pipeline) {
675     auto &Name = Element.Name;
676     auto &InnerPipeline = Element.InnerPipeline;
677     if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines
678       return false;
679     if (!parseScopPass(Name, SPM))
680       return false;
681   }
682 
683   FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
684   if (VerifyEachPass)
685     FPM.addPass(VerifierPass());
686   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
687   if (VerifyEachPass)
688     MPM.addPass(VerifierPass());
689 
690   return true;
691 }
692 
693 void RegisterPollyPasses(PassBuilder &PB) {
694   PB.registerAnalysisRegistrationCallback(registerFunctionAnalyses);
695   PB.registerPipelineParsingCallback(parseFunctionPipeline);
696   PB.registerPipelineParsingCallback(parseScopPipeline);
697   PB.registerParseTopLevelPipelineCallback(parseTopLevelPipeline);
698 
699   if (PassPosition == POSITION_BEFORE_VECTORIZER)
700     PB.registerVectorizerStartEPCallback(buildDefaultPollyPipeline);
701   // FIXME else Error?
702 }
703 } // namespace polly
704 
705 // Plugin Entrypoint:
706 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
707 llvmGetPassPluginInfo() {
708   return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING,
709           polly::RegisterPollyPasses};
710 }
711