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