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