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