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/DeLICM.h"
28 #include "polly/DependenceInfo.h"
29 #include "polly/ForwardOpTree.h"
30 #include "polly/JSONExporter.h"
31 #include "polly/LinkAllPasses.h"
32 #include "polly/PolyhedralInfo.h"
33 #include "polly/PruneUnprofitable.h"
34 #include "polly/ScheduleOptimizer.h"
35 #include "polly/ScopDetection.h"
36 #include "polly/ScopInfo.h"
37 #include "polly/Simplify.h"
38 #include "polly/Support/DumpModulePass.h"
39 #include "llvm/Analysis/CFGPrinter.h"
40 #include "llvm/IR/LegacyPassManager.h"
41 #include "llvm/IR/Verifier.h"
42 #include "llvm/Passes/PassBuilder.h"
43 #include "llvm/Passes/PassPlugin.h"
44 #include "llvm/Support/CommandLine.h"
45 #include "llvm/Support/TargetSelect.h"
46 #include "llvm/Transforms/IPO.h"
47 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
48 
49 using namespace llvm;
50 using namespace polly;
51 
52 cl::OptionCategory PollyCategory("Polly Options",
53                                  "Configure the polly loop optimizer");
54 
55 static cl::opt<bool>
56     PollyEnabled("polly",
57                  cl::desc("Enable the polly optimizer (with -O1, -O2 or -O3)"),
58                  cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
59 
60 static cl::opt<bool> PollyDetectOnly(
61     "polly-only-scop-detection",
62     cl::desc("Only run scop detection, but no other optimizations"),
63     cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
64 
65 enum PassPositionChoice {
66   POSITION_EARLY,
67   POSITION_AFTER_LOOPOPT,
68   POSITION_BEFORE_VECTORIZER
69 };
70 
71 enum OptimizerChoice { OPTIMIZER_NONE, OPTIMIZER_ISL };
72 
73 static cl::opt<PassPositionChoice> PassPosition(
74     "polly-position", cl::desc("Where to run polly in the pass pipeline"),
75     cl::values(
76         clEnumValN(POSITION_EARLY, "early", "Before everything"),
77         clEnumValN(POSITION_AFTER_LOOPOPT, "after-loopopt",
78                    "After the loop optimizer (but within the inline cycle)"),
79         clEnumValN(POSITION_BEFORE_VECTORIZER, "before-vectorizer",
80                    "Right before the vectorizer")),
81     cl::Hidden, cl::init(POSITION_BEFORE_VECTORIZER), cl::ZeroOrMore,
82     cl::cat(PollyCategory));
83 
84 static cl::opt<OptimizerChoice>
85     Optimizer("polly-optimizer", cl::desc("Select the scheduling optimizer"),
86               cl::values(clEnumValN(OPTIMIZER_NONE, "none", "No optimizer"),
87                          clEnumValN(OPTIMIZER_ISL, "isl",
88                                     "The isl scheduling optimizer")),
89               cl::Hidden, cl::init(OPTIMIZER_ISL), cl::ZeroOrMore,
90               cl::cat(PollyCategory));
91 
92 enum CodeGenChoice { CODEGEN_FULL, CODEGEN_AST, CODEGEN_NONE };
93 static cl::opt<CodeGenChoice> CodeGeneration(
94     "polly-code-generation", cl::desc("How much code-generation to perform"),
95     cl::values(clEnumValN(CODEGEN_FULL, "full", "AST and IR generation"),
96                clEnumValN(CODEGEN_AST, "ast", "Only AST generation"),
97                clEnumValN(CODEGEN_NONE, "none", "No code generation")),
98     cl::Hidden, cl::init(CODEGEN_FULL), cl::ZeroOrMore, cl::cat(PollyCategory));
99 
100 enum TargetChoice { TARGET_CPU, TARGET_GPU, TARGET_HYBRID };
101 static cl::opt<TargetChoice>
102     Target("polly-target", cl::desc("The hardware to target"),
103            cl::values(clEnumValN(TARGET_CPU, "cpu", "generate CPU code")
104 #ifdef GPU_CODEGEN
105                           ,
106                       clEnumValN(TARGET_GPU, "gpu", "generate GPU code"),
107                       clEnumValN(TARGET_HYBRID, "hybrid",
108                                  "generate GPU code (preferably) or CPU code")
109 #endif
110                           ),
111            cl::init(TARGET_CPU), cl::ZeroOrMore, cl::cat(PollyCategory));
112 
113 VectorizerChoice polly::PollyVectorizerChoice;
114 static cl::opt<polly::VectorizerChoice, true> Vectorizer(
115     "polly-vectorizer", cl::desc("Select the vectorization strategy"),
116     cl::values(
117         clEnumValN(polly::VECTORIZER_NONE, "none", "No Vectorization"),
118         clEnumValN(polly::VECTORIZER_POLLY, "polly",
119                    "Polly internal vectorizer"),
120         clEnumValN(
121             polly::VECTORIZER_STRIPMINE, "stripmine",
122             "Strip-mine outer loops for the loop-vectorizer to trigger")),
123     cl::location(PollyVectorizerChoice), cl::init(polly::VECTORIZER_NONE),
124     cl::ZeroOrMore, cl::cat(PollyCategory));
125 
126 static cl::opt<bool> ImportJScop(
127     "polly-import",
128     cl::desc("Import the polyhedral description of the detected Scops"),
129     cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
130 
131 static cl::opt<bool> FullyIndexedStaticExpansion(
132     "polly-enable-mse",
133     cl::desc("Fully expand the memory accesses of the detected Scops"),
134     cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
135 
136 static cl::opt<bool> ExportJScop(
137     "polly-export",
138     cl::desc("Export the polyhedral description of the detected Scops"),
139     cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
140 
141 static cl::opt<bool> DeadCodeElim("polly-run-dce",
142                                   cl::desc("Run the dead code elimination"),
143                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
144                                   cl::cat(PollyCategory));
145 
146 static cl::opt<bool> PollyViewer(
147     "polly-show",
148     cl::desc("Highlight the code regions that will be optimized in a "
149              "(CFG BBs and LLVM-IR instructions)"),
150     cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
151 
152 static cl::opt<bool> PollyOnlyViewer(
153     "polly-show-only",
154     cl::desc("Highlight the code regions that will be optimized in "
155              "a (CFG only BBs)"),
156     cl::init(false), cl::cat(PollyCategory));
157 
158 static cl::opt<bool>
159     PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"),
160                  cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"),
161                  cl::init(false), cl::cat(PollyCategory));
162 
163 static cl::opt<bool> PollyOnlyPrinter(
164     "polly-dot-only",
165     cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden,
166     cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"),
167     cl::init(false), cl::cat(PollyCategory));
168 
169 static cl::opt<bool>
170     CFGPrinter("polly-view-cfg",
171                cl::desc("Show the Polly CFG right after code generation"),
172                cl::Hidden, cl::init(false), cl::cat(PollyCategory));
173 
174 static cl::opt<bool>
175     EnablePolyhedralInfo("polly-enable-polyhedralinfo",
176                          cl::desc("Enable polyhedral interface of Polly"),
177                          cl::Hidden, cl::init(false), cl::cat(PollyCategory));
178 
179 static cl::opt<bool>
180     EnableForwardOpTree("polly-enable-optree",
181                         cl::desc("Enable operand tree forwarding"), cl::Hidden,
182                         cl::init(true), cl::cat(PollyCategory));
183 
184 static cl::opt<bool>
185     DumpBefore("polly-dump-before",
186                cl::desc("Dump module before Polly transformations into a file "
187                         "suffixed with \"-before\""),
188                cl::init(false), cl::cat(PollyCategory));
189 
190 static cl::list<std::string> DumpBeforeFile(
191     "polly-dump-before-file",
192     cl::desc("Dump module before Polly transformations to the given file"),
193     cl::cat(PollyCategory));
194 
195 static cl::opt<bool>
196     DumpAfter("polly-dump-after",
197               cl::desc("Dump module after Polly transformations into a file "
198                        "suffixed with \"-after\""),
199               cl::init(false), cl::cat(PollyCategory));
200 
201 static cl::list<std::string> DumpAfterFile(
202     "polly-dump-after-file",
203     cl::desc("Dump module after Polly transformations to the given file"),
204     cl::ZeroOrMore, cl::cat(PollyCategory));
205 
206 static cl::opt<bool>
207     EnableDeLICM("polly-enable-delicm",
208                  cl::desc("Eliminate scalar loop carried dependences"),
209                  cl::Hidden, cl::init(true), cl::cat(PollyCategory));
210 
211 static cl::opt<bool>
212     EnableSimplify("polly-enable-simplify",
213                    cl::desc("Simplify SCoP after optimizations"),
214                    cl::init(true), cl::cat(PollyCategory));
215 
216 static cl::opt<bool> EnablePruneUnprofitable(
217     "polly-enable-prune-unprofitable",
218     cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden,
219     cl::init(true), cl::cat(PollyCategory));
220 
221 namespace {
222 
223 /// Initialize Polly passes when library is loaded.
224 ///
225 /// We use the constructor of a statically declared object to initialize the
226 /// different Polly passes right after the Polly library is loaded. This ensures
227 /// that the Polly passes are available e.g. in the 'opt' tool.
228 class StaticInitializer {
229 public:
230   StaticInitializer() {
231     llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
232     polly::initializePollyPasses(Registry);
233   }
234 };
235 static StaticInitializer InitializeEverything;
236 } // end of anonymous namespace.
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   initializeIslScheduleOptimizerWrapperPassPass(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   initializeForwardOpTreeWrapperPassPass(Registry);
269   initializeDeLICMWrapperPassPass(Registry);
270   initializeSimplifyWrapperPassPass(Registry);
271   initializeDumpModulePass(Registry);
272   initializePruneUnprofitableWrapperPassPass(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 static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
302                                 bool EnableForOpt) {
303   if (DumpBefore)
304     PM.add(polly::createDumpModulePass("-before", true));
305   for (auto &Filename : DumpBeforeFile)
306     PM.add(polly::createDumpModulePass(Filename, false));
307 
308   PM.add(polly::createScopDetectionWrapperPassPass());
309 
310   if (PollyDetectOnly)
311     return;
312 
313   if (PollyViewer)
314     PM.add(polly::createDOTViewerPass());
315   if (PollyOnlyViewer)
316     PM.add(polly::createDOTOnlyViewerPass());
317   if (PollyPrinter)
318     PM.add(polly::createDOTPrinterPass());
319   if (PollyOnlyPrinter)
320     PM.add(polly::createDOTOnlyPrinterPass());
321 
322   PM.add(polly::createScopInfoRegionPassPass());
323   if (EnablePolyhedralInfo)
324     PM.add(polly::createPolyhedralInfoPass());
325 
326   if (EnableSimplify)
327     PM.add(polly::createSimplifyWrapperPass(0));
328   if (EnableForwardOpTree)
329     PM.add(polly::createForwardOpTreeWrapperPass());
330   if (EnableDeLICM)
331     PM.add(polly::createDeLICMWrapperPass());
332   if (EnableSimplify)
333     PM.add(polly::createSimplifyWrapperPass(1));
334 
335   if (ImportJScop)
336     PM.add(polly::createJSONImporterPass());
337 
338   if (DeadCodeElim)
339     PM.add(polly::createDeadCodeElimPass());
340 
341   if (FullyIndexedStaticExpansion)
342     PM.add(polly::createMaximalStaticExpansionPass());
343 
344   if (EnablePruneUnprofitable)
345     PM.add(polly::createPruneUnprofitableWrapperPass());
346 
347 #ifdef GPU_CODEGEN
348   if (Target == TARGET_HYBRID)
349     PM.add(
350         polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
351 #endif
352   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
353     switch (Optimizer) {
354     case OPTIMIZER_NONE:
355       break; /* Do nothing */
356 
357     case OPTIMIZER_ISL:
358       PM.add(polly::createIslScheduleOptimizerWrapperPass());
359       break;
360     }
361 
362   if (ExportJScop)
363     PM.add(polly::createJSONExporterPass());
364 
365   if (!EnableForOpt)
366     return;
367 
368   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
369     switch (CodeGeneration) {
370     case CODEGEN_AST:
371       PM.add(polly::createIslAstInfoWrapperPassPass());
372       break;
373     case CODEGEN_FULL:
374       PM.add(polly::createCodeGenerationPass());
375       break;
376     case CODEGEN_NONE:
377       break;
378     }
379 #ifdef GPU_CODEGEN
380   else {
381     PM.add(
382         polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
383     PM.add(polly::createManagedMemoryRewritePassPass());
384   }
385 #endif
386 
387 #ifdef GPU_CODEGEN
388   if (Target == TARGET_HYBRID)
389     PM.add(polly::createManagedMemoryRewritePassPass(GPUArchChoice,
390                                                      GPURuntimeChoice));
391 #endif
392 
393   // FIXME: This dummy ModulePass keeps some programs from miscompiling,
394   // probably some not correctly preserved analyses. It acts as a barrier to
395   // force all analysis results to be recomputed.
396   PM.add(createBarrierNoopPass());
397 
398   if (DumpAfter)
399     PM.add(polly::createDumpModulePass("-after", true));
400   for (auto &Filename : DumpAfterFile)
401     PM.add(polly::createDumpModulePass(Filename, false));
402 
403   if (CFGPrinter)
404     PM.add(llvm::createCFGPrinterLegacyPassPass());
405 }
406 
407 static bool shouldEnablePollyForOptimization() { return PollyEnabled; }
408 
409 static bool shouldEnablePollyForDiagnostic() {
410   // FIXME: PollyTrackFailures is user-controlled, should not be set
411   // programmatically.
412   if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)
413     PollyTrackFailures = true;
414 
415   return PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||
416          ExportJScop;
417 }
418 
419 static void
420 registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
421                                    llvm::legacy::PassManagerBase &PM) {
422   if (PassPosition != POSITION_EARLY)
423     return;
424 
425   bool EnableForOpt = shouldEnablePollyForOptimization() &&
426                       Builder.OptLevel >= 1 && Builder.SizeLevel == 0;
427   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
428     return;
429 
430   registerCanonicalicationPasses(PM);
431   registerPollyPasses(PM, EnableForOpt);
432 }
433 
434 static void
435 registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder,
436                                     llvm::legacy::PassManagerBase &PM) {
437   if (PassPosition != POSITION_AFTER_LOOPOPT)
438     return;
439 
440   bool EnableForOpt = shouldEnablePollyForOptimization() &&
441                       Builder.OptLevel >= 1 && Builder.SizeLevel == 0;
442   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
443     return;
444 
445   PM.add(polly::createCodePreparationPass());
446   registerPollyPasses(PM, EnableForOpt);
447   if (EnableForOpt)
448     PM.add(createCodegenCleanupPass());
449 }
450 
451 static void
452 registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder,
453                                        llvm::legacy::PassManagerBase &PM) {
454   if (PassPosition != POSITION_BEFORE_VECTORIZER)
455     return;
456 
457   bool EnableForOpt = shouldEnablePollyForOptimization() &&
458                       Builder.OptLevel >= 1 && Builder.SizeLevel == 0;
459   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
460     return;
461 
462   PM.add(polly::createCodePreparationPass());
463   polly::registerPollyPasses(PM, EnableForOpt);
464   if (EnableForOpt)
465     PM.add(createCodegenCleanupPass());
466 }
467 
468 static void buildDefaultPollyPipeline(FunctionPassManager &PM,
469                                       PassBuilder::OptimizationLevel Level) {
470   bool EnableForOpt =
471       shouldEnablePollyForOptimization() && Level.isOptimizingForSpeed();
472   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
473     return;
474 
475   PassBuilder PB;
476   ScopPassManager SPM;
477 
478   PM.addPass(CodePreparationPass());
479 
480   // TODO add utility passes for the various command line options, once they're
481   // ported
482   if (DumpBefore)
483     report_fatal_error("Option -polly-dump-before not supported with NPM",
484                        false);
485   if (!DumpBeforeFile.empty())
486     report_fatal_error("Option -polly-dump-before-file not supported with NPM",
487                        false);
488 
489   if (PollyDetectOnly) {
490     // Don't add more passes other than the ScopPassManager's detection passes.
491     PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
492     return;
493   }
494 
495   if (PollyViewer)
496     report_fatal_error("Option -polly-show not supported with NPM", false);
497   if (PollyOnlyViewer)
498     report_fatal_error("Option -polly-show-only not supported with NPM", false);
499   if (PollyPrinter)
500     report_fatal_error("Option -polly-dot not supported with NPM", false);
501   if (PollyOnlyPrinter)
502     report_fatal_error("Option -polly-dot-only not supported with NPM", false);
503   if (EnablePolyhedralInfo)
504     report_fatal_error(
505         "Option -polly-enable-polyhedralinfo not supported with NPM", false);
506 
507   if (EnableSimplify)
508     SPM.addPass(SimplifyPass(0));
509   if (EnableForwardOpTree)
510     SPM.addPass(ForwardOpTreePass());
511   if (EnableDeLICM)
512     SPM.addPass(DeLICMPass());
513   if (EnableSimplify)
514     SPM.addPass(SimplifyPass(1));
515 
516   if (ImportJScop)
517     SPM.addPass(JSONImportPass());
518 
519   if (DeadCodeElim)
520     report_fatal_error("Option -polly-run-dce not supported with NPM", false);
521 
522   if (FullyIndexedStaticExpansion)
523     report_fatal_error("Option -polly-enable-mse not supported with NPM",
524                        false);
525 
526   if (EnablePruneUnprofitable)
527     SPM.addPass(PruneUnprofitablePass());
528 
529   if (Target == TARGET_CPU || Target == TARGET_HYBRID) {
530     switch (Optimizer) {
531     case OPTIMIZER_NONE:
532       break; /* Do nothing */
533     case OPTIMIZER_ISL:
534       SPM.addPass(IslScheduleOptimizerPass());
535       break;
536     }
537   }
538 
539   if (ExportJScop)
540     report_fatal_error("Option -polly-export not supported with NPM", false);
541 
542   if (!EnableForOpt)
543     return;
544 
545   if (Target == TARGET_CPU || Target == TARGET_HYBRID) {
546     switch (CodeGeneration) {
547     case CODEGEN_AST:
548       SPM.addPass(
549           RequireAnalysisPass<IslAstAnalysis, Scop, ScopAnalysisManager,
550                               ScopStandardAnalysisResults &, SPMUpdater &>());
551       break;
552     case CODEGEN_FULL:
553       SPM.addPass(CodeGenerationPass());
554       break;
555     case CODEGEN_NONE:
556       break;
557     }
558   }
559 #ifdef GPU_CODEGEN
560   else
561     report_fatal_error("Option -polly-target=gpu not supported for NPM", false);
562 #endif
563 
564 #ifdef GPU_CODEGEN
565   if (Target == TARGET_HYBRID)
566     report_fatal_error("Option -polly-target=hybrid not supported for NPM",
567                        false);
568 #endif
569 
570   PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
571   PM.addPass(PB.buildFunctionSimplificationPipeline(
572       Level, ThinOrFullLTOPhase::None)); // Cleanup
573 
574   if (DumpAfter)
575     report_fatal_error("Option -polly-dump-after not supported with NPM",
576                        false);
577   if (!DumpAfterFile.empty())
578     report_fatal_error("Option -polly-dump-after-file not supported with NPM",
579                        false);
580 
581   if (CFGPrinter)
582     PM.addPass(llvm::CFGPrinterPass());
583 }
584 
585 /// Register Polly to be available as an optimizer
586 ///
587 ///
588 /// We can currently run Polly at three different points int the pass manager.
589 /// a) very early, b) after the canonicalizing loop transformations and c) right
590 /// before the vectorizer.
591 ///
592 /// The default is currently a), to register Polly such that it runs as early as
593 /// possible. This has several implications:
594 ///
595 ///   1) We need to schedule more canonicalization passes
596 ///
597 ///   As nothing is run before Polly, it is necessary to run a set of preparing
598 ///   transformations before Polly to canonicalize the LLVM-IR and to allow
599 ///   Polly to detect and understand the code.
600 ///
601 ///   2) LICM and LoopIdiom pass have not yet been run
602 ///
603 ///   Loop invariant code motion as well as the loop idiom recognition pass make
604 ///   it more difficult for Polly to transform code. LICM may introduce
605 ///   additional data dependences that are hard to eliminate and the loop idiom
606 ///   recognition pass may introduce calls to memset that we currently do not
607 ///   understand. By running Polly early enough (meaning before these passes) we
608 ///   avoid difficulties that may be introduced by these passes.
609 ///
610 ///   3) We get the full -O3 optimization sequence after Polly
611 ///
612 ///   The LLVM-IR that is generated by Polly has been optimized on a high level,
613 ///   but it may be rather inefficient on the lower/scalar level. By scheduling
614 ///   Polly before all other passes, we have the full sequence of -O3
615 ///   optimizations behind us, such that inefficiencies on the low level can
616 ///   be optimized away.
617 ///
618 /// We are currently evaluating the benefit or running Polly at position b) or
619 /// c). b) is likely too early as it interacts with the inliner. c) is nice
620 /// as everything is fully inlined and canonicalized, but we need to be able
621 /// to handle LICMed code to make it useful.
622 static llvm::RegisterStandardPasses RegisterPollyOptimizerEarly(
623     llvm::PassManagerBuilder::EP_ModuleOptimizerEarly,
624     registerPollyEarlyAsPossiblePasses);
625 
626 static llvm::RegisterStandardPasses
627     RegisterPollyOptimizerLoopEnd(llvm::PassManagerBuilder::EP_LoopOptimizerEnd,
628                                   registerPollyLoopOptimizerEndPasses);
629 
630 static llvm::RegisterStandardPasses RegisterPollyOptimizerScalarLate(
631     llvm::PassManagerBuilder::EP_VectorizerStart,
632     registerPollyScalarOptimizerLatePasses);
633 
634 static OwningScopAnalysisManagerFunctionProxy
635 createScopAnalyses(FunctionAnalysisManager &FAM,
636                    PassInstrumentationCallbacks *PIC) {
637   OwningScopAnalysisManagerFunctionProxy Proxy;
638 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
639   Proxy.getManager().registerPass([PIC] {                                      \
640     (void)PIC;                                                                 \
641     return CREATE_PASS;                                                        \
642   });
643 #include "PollyPasses.def"
644 
645   Proxy.getManager().registerPass(
646       [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); });
647   return Proxy;
648 }
649 
650 static void registerFunctionAnalyses(FunctionAnalysisManager &FAM,
651                                      PassInstrumentationCallbacks *PIC) {
652 
653 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
654   FAM.registerPass([] { return CREATE_PASS; });
655 
656 #include "PollyPasses.def"
657 
658   FAM.registerPass([&FAM, PIC] { return createScopAnalyses(FAM, PIC); });
659 }
660 
661 static bool
662 parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,
663                       ArrayRef<PassBuilder::PipelineElement> Pipeline) {
664   if (parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>(
665           "polly-scop-analyses", Name, FPM))
666     return true;
667 
668 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
669   if (parseAnalysisUtilityPasses<                                              \
670           std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
671                                                               FPM))            \
672     return true;
673 
674 #define FUNCTION_PASS(NAME, CREATE_PASS)                                       \
675   if (Name == NAME) {                                                          \
676     FPM.addPass(CREATE_PASS);                                                  \
677     return true;                                                               \
678   }
679 
680 #include "PollyPasses.def"
681   return false;
682 }
683 
684 static bool parseScopPass(StringRef Name, ScopPassManager &SPM,
685                           PassInstrumentationCallbacks *PIC) {
686 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
687   if (parseAnalysisUtilityPasses<                                              \
688           std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
689                                                               SPM))            \
690     return true;
691 
692 #define SCOP_PASS(NAME, CREATE_PASS)                                           \
693   if (Name == NAME) {                                                          \
694     SPM.addPass(CREATE_PASS);                                                  \
695     return true;                                                               \
696   }
697 
698 #include "PollyPasses.def"
699 
700   return false;
701 }
702 
703 static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM,
704                               PassInstrumentationCallbacks *PIC,
705                               ArrayRef<PassBuilder::PipelineElement> Pipeline) {
706   if (Name != "scop")
707     return false;
708   if (!Pipeline.empty()) {
709     ScopPassManager SPM;
710     for (const auto &E : Pipeline)
711       if (!parseScopPass(E.Name, SPM, PIC))
712         return false;
713     FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
714   }
715   return true;
716 }
717 
718 static bool isScopPassName(StringRef Name) {
719 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
720   if (Name == "require<" NAME ">")                                             \
721     return true;                                                               \
722   if (Name == "invalidate<" NAME ">")                                          \
723     return true;
724 
725 #define SCOP_PASS(NAME, CREATE_PASS)                                           \
726   if (Name == NAME)                                                            \
727     return true;
728 
729 #include "PollyPasses.def"
730 
731   return false;
732 }
733 
734 static bool
735 parseTopLevelPipeline(ModulePassManager &MPM, PassInstrumentationCallbacks *PIC,
736                       ArrayRef<PassBuilder::PipelineElement> Pipeline,
737                       bool DebugLogging) {
738   std::vector<PassBuilder::PipelineElement> FullPipeline;
739   StringRef FirstName = Pipeline.front().Name;
740 
741   if (!isScopPassName(FirstName))
742     return false;
743 
744   FunctionPassManager FPM(DebugLogging);
745   ScopPassManager SPM(DebugLogging);
746 
747   for (auto &Element : Pipeline) {
748     auto &Name = Element.Name;
749     auto &InnerPipeline = Element.InnerPipeline;
750     if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines
751       return false;
752     if (!parseScopPass(Name, SPM, PIC))
753       return false;
754   }
755 
756   FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
757   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
758 
759   return true;
760 }
761 
762 void registerPollyPasses(PassBuilder &PB) {
763   PassInstrumentationCallbacks *PIC = PB.getPassInstrumentationCallbacks();
764   PB.registerAnalysisRegistrationCallback([PIC](FunctionAnalysisManager &FAM) {
765     registerFunctionAnalyses(FAM, PIC);
766   });
767   PB.registerPipelineParsingCallback(parseFunctionPipeline);
768   PB.registerPipelineParsingCallback(
769       [PIC](StringRef Name, FunctionPassManager &FPM,
770             ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
771         return parseScopPipeline(Name, FPM, PIC, Pipeline);
772       });
773   PB.registerParseTopLevelPipelineCallback(
774       [PIC](ModulePassManager &MPM,
775             ArrayRef<PassBuilder::PipelineElement> Pipeline,
776             bool DebugLogging) -> bool {
777         return parseTopLevelPipeline(MPM, PIC, Pipeline, DebugLogging);
778       });
779 
780   if (PassPosition != POSITION_BEFORE_VECTORIZER)
781     report_fatal_error("Option -polly-position not supported with NPM", false);
782   PB.registerVectorizerStartEPCallback(buildDefaultPollyPipeline);
783 }
784 } // namespace polly
785 
786 llvm::PassPluginLibraryInfo getPollyPluginInfo() {
787   return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING,
788           polly::registerPollyPasses};
789 }
790