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