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   initializeRewriteByrefParamsWrapperPassPass(Registry);
267   initializeCodegenCleanupPass(Registry);
268   initializeFlattenSchedulePass(Registry);
269   initializeForwardOpTreeWrapperPassPass(Registry);
270   initializeDeLICMWrapperPassPass(Registry);
271   initializeSimplifyWrapperPassPass(Registry);
272   initializeDumpModuleWrapperPassPass(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::createDumpModuleWrapperPass("-before", true));
306   for (auto &Filename : DumpBeforeFile)
307     PM.add(polly::createDumpModuleWrapperPass(Filename, false));
308 
309   PM.add(polly::createCodePreparationPass());
310   PM.add(polly::createScopDetectionWrapperPassPass());
311 
312   if (PollyDetectOnly)
313     return;
314 
315   if (PollyViewer)
316     PM.add(polly::createDOTViewerPass());
317   if (PollyOnlyViewer)
318     PM.add(polly::createDOTOnlyViewerPass());
319   if (PollyPrinter)
320     PM.add(polly::createDOTPrinterPass());
321   if (PollyOnlyPrinter)
322     PM.add(polly::createDOTOnlyPrinterPass());
323 
324   PM.add(polly::createScopInfoRegionPassPass());
325   if (EnablePolyhedralInfo)
326     PM.add(polly::createPolyhedralInfoPass());
327 
328   if (EnableSimplify)
329     PM.add(polly::createSimplifyWrapperPass(0));
330   if (EnableForwardOpTree)
331     PM.add(polly::createForwardOpTreeWrapperPass());
332   if (EnableDeLICM)
333     PM.add(polly::createDeLICMWrapperPass());
334   if (EnableSimplify)
335     PM.add(polly::createSimplifyWrapperPass(1));
336 
337   if (ImportJScop)
338     PM.add(polly::createJSONImporterPass());
339 
340   if (DeadCodeElim)
341     PM.add(polly::createDeadCodeElimWrapperPass());
342 
343   if (FullyIndexedStaticExpansion)
344     PM.add(polly::createMaximalStaticExpansionPass());
345 
346   if (EnablePruneUnprofitable)
347     PM.add(polly::createPruneUnprofitableWrapperPass());
348 
349 #ifdef GPU_CODEGEN
350   if (Target == TARGET_HYBRID)
351     PM.add(
352         polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
353 #endif
354   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
355     switch (Optimizer) {
356     case OPTIMIZER_NONE:
357       break; /* Do nothing */
358 
359     case OPTIMIZER_ISL:
360       PM.add(polly::createIslScheduleOptimizerWrapperPass());
361       break;
362     }
363 
364   if (ExportJScop)
365     PM.add(polly::createJSONExporterPass());
366 
367   if (!EnableForOpt)
368     return;
369 
370   if (Target == TARGET_CPU || Target == TARGET_HYBRID)
371     switch (CodeGeneration) {
372     case CODEGEN_AST:
373       PM.add(polly::createIslAstInfoWrapperPassPass());
374       break;
375     case CODEGEN_FULL:
376       PM.add(polly::createCodeGenerationPass());
377       break;
378     case CODEGEN_NONE:
379       break;
380     }
381 #ifdef GPU_CODEGEN
382   else {
383     PM.add(
384         polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
385     PM.add(polly::createManagedMemoryRewritePassPass());
386   }
387 #endif
388 
389 #ifdef GPU_CODEGEN
390   if (Target == TARGET_HYBRID)
391     PM.add(polly::createManagedMemoryRewritePassPass(GPUArchChoice,
392                                                      GPURuntimeChoice));
393 #endif
394 
395   // FIXME: This dummy ModulePass keeps some programs from miscompiling,
396   // probably some not correctly preserved analyses. It acts as a barrier to
397   // force all analysis results to be recomputed.
398   PM.add(createBarrierNoopPass());
399 
400   if (DumpAfter)
401     PM.add(polly::createDumpModuleWrapperPass("-after", true));
402   for (auto &Filename : DumpAfterFile)
403     PM.add(polly::createDumpModuleWrapperPass(Filename, false));
404 
405   if (CFGPrinter)
406     PM.add(llvm::createCFGPrinterLegacyPassPass());
407 }
408 
409 static bool shouldEnablePollyForOptimization() { return PollyEnabled; }
410 
411 static bool shouldEnablePollyForDiagnostic() {
412   // FIXME: PollyTrackFailures is user-controlled, should not be set
413   // programmatically.
414   if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)
415     PollyTrackFailures = true;
416 
417   return PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||
418          ExportJScop;
419 }
420 
421 static void
422 registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
423                                    llvm::legacy::PassManagerBase &PM) {
424   if (PassPosition != POSITION_EARLY)
425     return;
426 
427   bool EnableForOpt = shouldEnablePollyForOptimization() &&
428                       Builder.OptLevel >= 1 && Builder.SizeLevel == 0;
429   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
430     return;
431 
432   registerCanonicalicationPasses(PM);
433   registerPollyPasses(PM, EnableForOpt);
434 }
435 
436 static void
437 registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder,
438                                     llvm::legacy::PassManagerBase &PM) {
439   if (PassPosition != POSITION_AFTER_LOOPOPT)
440     return;
441 
442   bool EnableForOpt = shouldEnablePollyForOptimization() &&
443                       Builder.OptLevel >= 1 && Builder.SizeLevel == 0;
444   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
445     return;
446 
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   polly::registerPollyPasses(PM, EnableForOpt);
464   if (EnableForOpt)
465     PM.add(createCodegenCleanupPass());
466 }
467 
468 /// Add the pass sequence required for Polly to the New Pass Manager.
469 ///
470 /// @param PM           The pass manager itself.
471 /// @param Level        The optimization level. Used for the cleanup of Polly's
472 ///                     output.
473 /// @param EnableForOpt Whether to add Polly IR transformations. If False, only
474 ///                     the analysis passes are added, skipping Polly itself.
475 ///                     The IR may still be modified.
476 static void buildCommonPollyPipeline(FunctionPassManager &PM,
477                                      PassBuilder::OptimizationLevel Level,
478                                      bool EnableForOpt) {
479   PassBuilder PB;
480   ScopPassManager SPM;
481 
482   PM.addPass(CodePreparationPass());
483 
484   // TODO add utility passes for the various command line options, once they're
485   // ported
486 
487   if (PollyDetectOnly) {
488     // Don't add more passes other than the ScopPassManager's detection passes.
489     PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
490     return;
491   }
492 
493   if (PollyViewer)
494     report_fatal_error("Option -polly-show not supported with NPM", false);
495   if (PollyOnlyViewer)
496     report_fatal_error("Option -polly-show-only not supported with NPM", false);
497   if (PollyPrinter)
498     report_fatal_error("Option -polly-dot not supported with NPM", false);
499   if (PollyOnlyPrinter)
500     report_fatal_error("Option -polly-dot-only not supported with NPM", false);
501   if (EnablePolyhedralInfo)
502     report_fatal_error(
503         "Option -polly-enable-polyhedralinfo not supported with NPM", false);
504 
505   if (EnableSimplify)
506     SPM.addPass(SimplifyPass(0));
507   if (EnableForwardOpTree)
508     SPM.addPass(ForwardOpTreePass());
509   if (EnableDeLICM)
510     SPM.addPass(DeLICMPass());
511   if (EnableSimplify)
512     SPM.addPass(SimplifyPass(1));
513 
514   if (ImportJScop)
515     SPM.addPass(JSONImportPass());
516 
517   if (DeadCodeElim)
518     SPM.addPass(DeadCodeElimPass());
519 
520   if (FullyIndexedStaticExpansion)
521     report_fatal_error("Option -polly-enable-mse not supported with NPM",
522                        false);
523 
524   if (EnablePruneUnprofitable)
525     SPM.addPass(PruneUnprofitablePass());
526 
527   if (Target == TARGET_CPU || Target == TARGET_HYBRID) {
528     switch (Optimizer) {
529     case OPTIMIZER_NONE:
530       break; /* Do nothing */
531     case OPTIMIZER_ISL:
532       SPM.addPass(IslScheduleOptimizerPass());
533       break;
534     }
535   }
536 
537   if (ExportJScop)
538     report_fatal_error("Option -polly-export not supported with NPM", false);
539 
540   if (!EnableForOpt)
541     return;
542 
543   if (Target == TARGET_CPU || Target == TARGET_HYBRID) {
544     switch (CodeGeneration) {
545     case CODEGEN_AST:
546       SPM.addPass(
547           RequireAnalysisPass<IslAstAnalysis, Scop, ScopAnalysisManager,
548                               ScopStandardAnalysisResults &, SPMUpdater &>());
549       break;
550     case CODEGEN_FULL:
551       SPM.addPass(CodeGenerationPass());
552       break;
553     case CODEGEN_NONE:
554       break;
555     }
556   }
557 #ifdef GPU_CODEGEN
558   else
559     report_fatal_error("Option -polly-target=gpu not supported for NPM", false);
560 #endif
561 
562 #ifdef GPU_CODEGEN
563   if (Target == TARGET_HYBRID)
564     report_fatal_error("Option -polly-target=hybrid not supported for NPM",
565                        false);
566 #endif
567 
568   PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
569   PM.addPass(PB.buildFunctionSimplificationPipeline(
570       Level, ThinOrFullLTOPhase::None)); // Cleanup
571 
572   if (CFGPrinter)
573     PM.addPass(llvm::CFGPrinterPass());
574 }
575 
576 static void buildEarlyPollyPipeline(ModulePassManager &MPM,
577                                     PassBuilder::OptimizationLevel Level) {
578   bool EnableForOpt =
579       shouldEnablePollyForOptimization() && Level.isOptimizingForSpeed();
580   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
581     return;
582 
583   FunctionPassManager FPM = buildCanonicalicationPassesForNPM(MPM, Level);
584 
585   if (DumpBefore || !DumpBeforeFile.empty()) {
586     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
587 
588     if (DumpBefore)
589       MPM.addPass(DumpModulePass("-before", true));
590     for (auto &Filename : DumpBeforeFile)
591       MPM.addPass(DumpModulePass(Filename, false));
592 
593     FPM = FunctionPassManager();
594   }
595 
596   buildCommonPollyPipeline(FPM, Level, EnableForOpt);
597   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
598 
599   if (DumpAfter)
600     MPM.addPass(DumpModulePass("-after", true));
601   for (auto &Filename : DumpAfterFile)
602     MPM.addPass(DumpModulePass(Filename, false));
603 }
604 
605 static void buildLatePollyPipeline(FunctionPassManager &PM,
606                                    PassBuilder::OptimizationLevel Level) {
607   bool EnableForOpt =
608       shouldEnablePollyForOptimization() && Level.isOptimizingForSpeed();
609   if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)
610     return;
611 
612   if (DumpBefore)
613     report_fatal_error("Option -polly-dump-before not supported with NPM",
614                        false);
615   if (!DumpBeforeFile.empty())
616     report_fatal_error("Option -polly-dump-before-file not supported with NPM",
617                        false);
618 
619   buildCommonPollyPipeline(PM, Level, EnableForOpt);
620 
621   if (DumpAfter)
622     report_fatal_error("Option -polly-dump-after not supported with NPM",
623                        false);
624   if (!DumpAfterFile.empty())
625     report_fatal_error("Option -polly-dump-after-file not supported with NPM",
626                        false);
627 }
628 
629 /// Register Polly to be available as an optimizer
630 ///
631 ///
632 /// We can currently run Polly at three different points int the pass manager.
633 /// a) very early, b) after the canonicalizing loop transformations and c) right
634 /// before the vectorizer.
635 ///
636 /// The default is currently a), to register Polly such that it runs as early as
637 /// possible. This has several implications:
638 ///
639 ///   1) We need to schedule more canonicalization passes
640 ///
641 ///   As nothing is run before Polly, it is necessary to run a set of preparing
642 ///   transformations before Polly to canonicalize the LLVM-IR and to allow
643 ///   Polly to detect and understand the code.
644 ///
645 ///   2) LICM and LoopIdiom pass have not yet been run
646 ///
647 ///   Loop invariant code motion as well as the loop idiom recognition pass make
648 ///   it more difficult for Polly to transform code. LICM may introduce
649 ///   additional data dependences that are hard to eliminate and the loop idiom
650 ///   recognition pass may introduce calls to memset that we currently do not
651 ///   understand. By running Polly early enough (meaning before these passes) we
652 ///   avoid difficulties that may be introduced by these passes.
653 ///
654 ///   3) We get the full -O3 optimization sequence after Polly
655 ///
656 ///   The LLVM-IR that is generated by Polly has been optimized on a high level,
657 ///   but it may be rather inefficient on the lower/scalar level. By scheduling
658 ///   Polly before all other passes, we have the full sequence of -O3
659 ///   optimizations behind us, such that inefficiencies on the low level can
660 ///   be optimized away.
661 ///
662 /// We are currently evaluating the benefit or running Polly at position b) or
663 /// c). b) is likely too early as it interacts with the inliner. c) is nice
664 /// as everything is fully inlined and canonicalized, but we need to be able
665 /// to handle LICMed code to make it useful.
666 static llvm::RegisterStandardPasses RegisterPollyOptimizerEarly(
667     llvm::PassManagerBuilder::EP_ModuleOptimizerEarly,
668     registerPollyEarlyAsPossiblePasses);
669 
670 static llvm::RegisterStandardPasses
671     RegisterPollyOptimizerLoopEnd(llvm::PassManagerBuilder::EP_LoopOptimizerEnd,
672                                   registerPollyLoopOptimizerEndPasses);
673 
674 static llvm::RegisterStandardPasses RegisterPollyOptimizerScalarLate(
675     llvm::PassManagerBuilder::EP_VectorizerStart,
676     registerPollyScalarOptimizerLatePasses);
677 
678 static OwningScopAnalysisManagerFunctionProxy
679 createScopAnalyses(FunctionAnalysisManager &FAM,
680                    PassInstrumentationCallbacks *PIC) {
681   OwningScopAnalysisManagerFunctionProxy Proxy;
682 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
683   Proxy.getManager().registerPass([PIC] {                                      \
684     (void)PIC;                                                                 \
685     return CREATE_PASS;                                                        \
686   });
687 #include "PollyPasses.def"
688 
689   Proxy.getManager().registerPass(
690       [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); });
691   return Proxy;
692 }
693 
694 static void registerFunctionAnalyses(FunctionAnalysisManager &FAM,
695                                      PassInstrumentationCallbacks *PIC) {
696 
697 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
698   FAM.registerPass([] { return CREATE_PASS; });
699 
700 #include "PollyPasses.def"
701 
702   FAM.registerPass([&FAM, PIC] { return createScopAnalyses(FAM, PIC); });
703 }
704 
705 static bool
706 parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,
707                       ArrayRef<PassBuilder::PipelineElement> Pipeline) {
708   if (parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>(
709           "polly-scop-analyses", Name, FPM))
710     return true;
711 
712 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
713   if (parseAnalysisUtilityPasses<                                              \
714           std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
715                                                               FPM))            \
716     return true;
717 
718 #define FUNCTION_PASS(NAME, CREATE_PASS)                                       \
719   if (Name == NAME) {                                                          \
720     FPM.addPass(CREATE_PASS);                                                  \
721     return true;                                                               \
722   }
723 
724 #include "PollyPasses.def"
725   return false;
726 }
727 
728 static bool parseScopPass(StringRef Name, ScopPassManager &SPM,
729                           PassInstrumentationCallbacks *PIC) {
730 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
731   if (parseAnalysisUtilityPasses<                                              \
732           std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
733                                                               SPM))            \
734     return true;
735 
736 #define SCOP_PASS(NAME, CREATE_PASS)                                           \
737   if (Name == NAME) {                                                          \
738     SPM.addPass(CREATE_PASS);                                                  \
739     return true;                                                               \
740   }
741 
742 #include "PollyPasses.def"
743 
744   return false;
745 }
746 
747 static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM,
748                               PassInstrumentationCallbacks *PIC,
749                               ArrayRef<PassBuilder::PipelineElement> Pipeline) {
750   if (Name != "scop")
751     return false;
752   if (!Pipeline.empty()) {
753     ScopPassManager SPM;
754     for (const auto &E : Pipeline)
755       if (!parseScopPass(E.Name, SPM, PIC))
756         return false;
757     FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
758   }
759   return true;
760 }
761 
762 static bool isScopPassName(StringRef Name) {
763 #define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
764   if (Name == "require<" NAME ">")                                             \
765     return true;                                                               \
766   if (Name == "invalidate<" NAME ">")                                          \
767     return true;
768 
769 #define SCOP_PASS(NAME, CREATE_PASS)                                           \
770   if (Name == NAME)                                                            \
771     return true;
772 
773 #include "PollyPasses.def"
774 
775   return false;
776 }
777 
778 static bool
779 parseTopLevelPipeline(ModulePassManager &MPM, PassInstrumentationCallbacks *PIC,
780                       ArrayRef<PassBuilder::PipelineElement> Pipeline) {
781   std::vector<PassBuilder::PipelineElement> FullPipeline;
782   StringRef FirstName = Pipeline.front().Name;
783 
784   if (!isScopPassName(FirstName))
785     return false;
786 
787   FunctionPassManager FPM;
788   ScopPassManager SPM;
789 
790   for (auto &Element : Pipeline) {
791     auto &Name = Element.Name;
792     auto &InnerPipeline = Element.InnerPipeline;
793     if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines
794       return false;
795     if (!parseScopPass(Name, SPM, PIC))
796       return false;
797   }
798 
799   FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
800   MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
801 
802   return true;
803 }
804 
805 void registerPollyPasses(PassBuilder &PB) {
806   PassInstrumentationCallbacks *PIC = PB.getPassInstrumentationCallbacks();
807   PB.registerAnalysisRegistrationCallback([PIC](FunctionAnalysisManager &FAM) {
808     registerFunctionAnalyses(FAM, PIC);
809   });
810   PB.registerPipelineParsingCallback(parseFunctionPipeline);
811   PB.registerPipelineParsingCallback(
812       [PIC](StringRef Name, FunctionPassManager &FPM,
813             ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
814         return parseScopPipeline(Name, FPM, PIC, Pipeline);
815       });
816   PB.registerParseTopLevelPipelineCallback(
817       [PIC](ModulePassManager &MPM,
818             ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
819         return parseTopLevelPipeline(MPM, PIC, Pipeline);
820       });
821 
822   switch (PassPosition) {
823   case POSITION_EARLY:
824     PB.registerPipelineStartEPCallback(buildEarlyPollyPipeline);
825     break;
826   case POSITION_AFTER_LOOPOPT:
827     report_fatal_error(
828         "Option -polly-position=after-loopopt not supported with NPM", false);
829     break;
830   case POSITION_BEFORE_VECTORIZER:
831     PB.registerVectorizerStartEPCallback(buildLatePollyPipeline);
832     break;
833   }
834 }
835 } // namespace polly
836 
837 llvm::PassPluginLibraryInfo getPollyPluginInfo() {
838   return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING,
839           polly::registerPollyPasses};
840 }
841