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