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