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