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