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