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