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