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/DependenceInfo.h" 28 #include "polly/ForwardOpTree.h" 29 #include "polly/JSONExporter.h" 30 #include "polly/LinkAllPasses.h" 31 #include "polly/PolyhedralInfo.h" 32 #include "polly/ScopDetection.h" 33 #include "polly/ScopInfo.h" 34 #include "polly/Simplify.h" 35 #include "polly/Support/DumpModulePass.h" 36 #include "llvm/Analysis/CFGPrinter.h" 37 #include "llvm/IR/LegacyPassManager.h" 38 #include "llvm/IR/Verifier.h" 39 #include "llvm/Passes/PassBuilder.h" 40 #include "llvm/Passes/PassPlugin.h" 41 #include "llvm/Support/CommandLine.h" 42 #include "llvm/Support/TargetSelect.h" 43 #include "llvm/Transforms/IPO.h" 44 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 45 46 using namespace llvm; 47 using namespace polly; 48 49 cl::OptionCategory PollyCategory("Polly Options", 50 "Configure the polly loop optimizer"); 51 52 static cl::opt<bool> 53 PollyEnabled("polly", cl::desc("Enable the polly optimizer (only at -O3)"), 54 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 55 56 static cl::opt<bool> PollyDetectOnly( 57 "polly-only-scop-detection", 58 cl::desc("Only run scop detection, but no other optimizations"), 59 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 60 61 enum PassPositionChoice { 62 POSITION_EARLY, 63 POSITION_AFTER_LOOPOPT, 64 POSITION_BEFORE_VECTORIZER 65 }; 66 67 enum OptimizerChoice { OPTIMIZER_NONE, OPTIMIZER_ISL }; 68 69 static cl::opt<PassPositionChoice> PassPosition( 70 "polly-position", cl::desc("Where to run polly in the pass pipeline"), 71 cl::values( 72 clEnumValN(POSITION_EARLY, "early", "Before everything"), 73 clEnumValN(POSITION_AFTER_LOOPOPT, "after-loopopt", 74 "After the loop optimizer (but within the inline cycle)"), 75 clEnumValN(POSITION_BEFORE_VECTORIZER, "before-vectorizer", 76 "Right before the vectorizer")), 77 cl::Hidden, cl::init(POSITION_BEFORE_VECTORIZER), cl::ZeroOrMore, 78 cl::cat(PollyCategory)); 79 80 static cl::opt<OptimizerChoice> 81 Optimizer("polly-optimizer", cl::desc("Select the scheduling optimizer"), 82 cl::values(clEnumValN(OPTIMIZER_NONE, "none", "No optimizer"), 83 clEnumValN(OPTIMIZER_ISL, "isl", 84 "The isl scheduling optimizer")), 85 cl::Hidden, cl::init(OPTIMIZER_ISL), cl::ZeroOrMore, 86 cl::cat(PollyCategory)); 87 88 enum CodeGenChoice { CODEGEN_FULL, CODEGEN_AST, CODEGEN_NONE }; 89 static cl::opt<CodeGenChoice> CodeGeneration( 90 "polly-code-generation", cl::desc("How much code-generation to perform"), 91 cl::values(clEnumValN(CODEGEN_FULL, "full", "AST and IR generation"), 92 clEnumValN(CODEGEN_AST, "ast", "Only AST generation"), 93 clEnumValN(CODEGEN_NONE, "none", "No code generation")), 94 cl::Hidden, cl::init(CODEGEN_FULL), cl::ZeroOrMore, cl::cat(PollyCategory)); 95 96 enum TargetChoice { TARGET_CPU, TARGET_GPU, TARGET_HYBRID }; 97 static cl::opt<TargetChoice> 98 Target("polly-target", cl::desc("The hardware to target"), 99 cl::values(clEnumValN(TARGET_CPU, "cpu", "generate CPU code") 100 #ifdef GPU_CODEGEN 101 , 102 clEnumValN(TARGET_GPU, "gpu", "generate GPU code"), 103 clEnumValN(TARGET_HYBRID, "hybrid", 104 "generate GPU code (preferably) or CPU code") 105 #endif 106 ), 107 cl::init(TARGET_CPU), cl::ZeroOrMore, cl::cat(PollyCategory)); 108 109 #ifdef GPU_CODEGEN 110 static cl::opt<GPURuntime> GPURuntimeChoice( 111 "polly-gpu-runtime", cl::desc("The GPU Runtime API to target"), 112 cl::values(clEnumValN(GPURuntime::CUDA, "libcudart", 113 "use the CUDA Runtime API"), 114 clEnumValN(GPURuntime::OpenCL, "libopencl", 115 "use the OpenCL Runtime API")), 116 cl::init(GPURuntime::CUDA), cl::ZeroOrMore, cl::cat(PollyCategory)); 117 118 static cl::opt<GPUArch> 119 GPUArchChoice("polly-gpu-arch", cl::desc("The GPU Architecture to target"), 120 cl::values(clEnumValN(GPUArch::NVPTX64, "nvptx64", 121 "target NVIDIA 64-bit architecture"), 122 clEnumValN(GPUArch::SPIR32, "spir32", 123 "target SPIR 32-bit architecture"), 124 clEnumValN(GPUArch::SPIR64, "spir64", 125 "target SPIR 64-bit architecture")), 126 cl::init(GPUArch::NVPTX64), cl::ZeroOrMore, 127 cl::cat(PollyCategory)); 128 #endif 129 130 VectorizerChoice polly::PollyVectorizerChoice; 131 static cl::opt<polly::VectorizerChoice, true> Vectorizer( 132 "polly-vectorizer", cl::desc("Select the vectorization strategy"), 133 cl::values( 134 clEnumValN(polly::VECTORIZER_NONE, "none", "No Vectorization"), 135 clEnumValN(polly::VECTORIZER_POLLY, "polly", 136 "Polly internal vectorizer"), 137 clEnumValN( 138 polly::VECTORIZER_STRIPMINE, "stripmine", 139 "Strip-mine outer loops for the loop-vectorizer to trigger")), 140 cl::location(PollyVectorizerChoice), cl::init(polly::VECTORIZER_NONE), 141 cl::ZeroOrMore, cl::cat(PollyCategory)); 142 143 static cl::opt<bool> ImportJScop( 144 "polly-import", 145 cl::desc("Import the polyhedral description of the detected Scops"), 146 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 147 148 static cl::opt<bool> FullyIndexedStaticExpansion( 149 "polly-enable-mse", 150 cl::desc("Fully expand the memory accesses of the detected Scops"), 151 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 152 153 static cl::opt<bool> ExportJScop( 154 "polly-export", 155 cl::desc("Export the polyhedral description of the detected Scops"), 156 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 157 158 static cl::opt<bool> DeadCodeElim("polly-run-dce", 159 cl::desc("Run the dead code elimination"), 160 cl::Hidden, cl::init(false), cl::ZeroOrMore, 161 cl::cat(PollyCategory)); 162 163 static cl::opt<bool> PollyViewer( 164 "polly-show", 165 cl::desc("Highlight the code regions that will be optimized in a " 166 "(CFG BBs and LLVM-IR instructions)"), 167 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 168 169 static cl::opt<bool> PollyOnlyViewer( 170 "polly-show-only", 171 cl::desc("Highlight the code regions that will be optimized in " 172 "a (CFG only BBs)"), 173 cl::init(false), cl::cat(PollyCategory)); 174 175 static cl::opt<bool> 176 PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"), 177 cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"), 178 cl::init(false), cl::cat(PollyCategory)); 179 180 static cl::opt<bool> PollyOnlyPrinter( 181 "polly-dot-only", 182 cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden, 183 cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"), 184 cl::init(false), cl::cat(PollyCategory)); 185 186 static cl::opt<bool> 187 CFGPrinter("polly-view-cfg", 188 cl::desc("Show the Polly CFG right after code generation"), 189 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 190 191 static cl::opt<bool> 192 EnablePolyhedralInfo("polly-enable-polyhedralinfo", 193 cl::desc("Enable polyhedral interface of Polly"), 194 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 195 196 static cl::opt<bool> 197 EnableForwardOpTree("polly-enable-optree", 198 cl::desc("Enable operand tree forwarding"), cl::Hidden, 199 cl::init(true), cl::cat(PollyCategory)); 200 201 static cl::opt<bool> 202 DumpBefore("polly-dump-before", 203 cl::desc("Dump module before Polly transformations into a file " 204 "suffixed with \"-before\""), 205 cl::init(false), cl::cat(PollyCategory)); 206 207 static cl::list<std::string> DumpBeforeFile( 208 "polly-dump-before-file", 209 cl::desc("Dump module before Polly transformations to the given file"), 210 cl::cat(PollyCategory)); 211 212 static cl::opt<bool> 213 DumpAfter("polly-dump-after", 214 cl::desc("Dump module after Polly transformations into a file " 215 "suffixed with \"-after\""), 216 cl::init(false), cl::cat(PollyCategory)); 217 218 static cl::list<std::string> DumpAfterFile( 219 "polly-dump-after-file", 220 cl::desc("Dump module after Polly transformations to the given file"), 221 cl::ZeroOrMore, cl::cat(PollyCategory)); 222 223 static cl::opt<bool> 224 EnableDeLICM("polly-enable-delicm", 225 cl::desc("Eliminate scalar loop carried dependences"), 226 cl::Hidden, cl::init(true), cl::cat(PollyCategory)); 227 228 static cl::opt<bool> 229 EnableSimplify("polly-enable-simplify", 230 cl::desc("Simplify SCoP after optimizations"), 231 cl::init(true), cl::cat(PollyCategory)); 232 233 static cl::opt<bool> EnablePruneUnprofitable( 234 "polly-enable-prune-unprofitable", 235 cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden, 236 cl::init(true), cl::cat(PollyCategory)); 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 initializeIslScheduleOptimizerPass(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 initializeForwardOpTreePass(Registry); 269 initializeDeLICMPass(Registry); 270 initializeSimplifyPass(Registry); 271 initializeDumpModulePass(Registry); 272 initializePruneUnprofitablePass(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 void registerPollyPasses(llvm::legacy::PassManagerBase &PM) { 302 if (DumpBefore) 303 PM.add(polly::createDumpModulePass("-before", true)); 304 for (auto &Filename : DumpBeforeFile) 305 PM.add(polly::createDumpModulePass(Filename, false)); 306 307 PM.add(polly::createScopDetectionWrapperPassPass()); 308 309 if (PollyDetectOnly) 310 return; 311 312 if (PollyViewer) 313 PM.add(polly::createDOTViewerPass()); 314 if (PollyOnlyViewer) 315 PM.add(polly::createDOTOnlyViewerPass()); 316 if (PollyPrinter) 317 PM.add(polly::createDOTPrinterPass()); 318 if (PollyOnlyPrinter) 319 PM.add(polly::createDOTOnlyPrinterPass()); 320 321 PM.add(polly::createScopInfoRegionPassPass()); 322 if (EnablePolyhedralInfo) 323 PM.add(polly::createPolyhedralInfoPass()); 324 325 if (EnableSimplify) 326 PM.add(polly::createSimplifyPass(0)); 327 if (EnableForwardOpTree) 328 PM.add(polly::createForwardOpTreePass()); 329 if (EnableDeLICM) 330 PM.add(polly::createDeLICMPass()); 331 if (EnableSimplify) 332 PM.add(polly::createSimplifyPass(1)); 333 334 if (ImportJScop) 335 PM.add(polly::createJSONImporterPass()); 336 337 if (DeadCodeElim) 338 PM.add(polly::createDeadCodeElimPass()); 339 340 if (FullyIndexedStaticExpansion) 341 PM.add(polly::createMaximalStaticExpansionPass()); 342 343 if (EnablePruneUnprofitable) 344 PM.add(polly::createPruneUnprofitablePass()); 345 346 #ifdef GPU_CODEGEN 347 if (Target == TARGET_HYBRID) 348 PM.add( 349 polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice)); 350 #endif 351 if (Target == TARGET_CPU || Target == TARGET_HYBRID) 352 switch (Optimizer) { 353 case OPTIMIZER_NONE: 354 break; /* Do nothing */ 355 356 case OPTIMIZER_ISL: 357 PM.add(polly::createIslScheduleOptimizerPass()); 358 break; 359 } 360 361 if (ExportJScop) 362 PM.add(polly::createJSONExporterPass()); 363 364 if (Target == TARGET_CPU || Target == TARGET_HYBRID) 365 switch (CodeGeneration) { 366 case CODEGEN_AST: 367 PM.add(polly::createIslAstInfoWrapperPassPass()); 368 break; 369 case CODEGEN_FULL: 370 PM.add(polly::createCodeGenerationPass()); 371 break; 372 case CODEGEN_NONE: 373 break; 374 } 375 #ifdef GPU_CODEGEN 376 else { 377 PM.add( 378 polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice)); 379 PM.add(polly::createManagedMemoryRewritePassPass()); 380 } 381 #endif 382 383 #ifdef GPU_CODEGEN 384 if (Target == TARGET_HYBRID) 385 PM.add(polly::createManagedMemoryRewritePassPass(GPUArchChoice, 386 GPURuntimeChoice)); 387 #endif 388 389 // FIXME: This dummy ModulePass keeps some programs from miscompiling, 390 // probably some not correctly preserved analyses. It acts as a barrier to 391 // force all analysis results to be recomputed. 392 PM.add(createBarrierNoopPass()); 393 394 if (DumpAfter) 395 PM.add(polly::createDumpModulePass("-after", true)); 396 for (auto &Filename : DumpAfterFile) 397 PM.add(polly::createDumpModulePass(Filename, false)); 398 399 if (CFGPrinter) 400 PM.add(llvm::createCFGPrinterLegacyPassPass()); 401 } 402 403 static bool shouldEnablePolly() { 404 if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer) 405 PollyTrackFailures = true; 406 407 if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer || 408 ExportJScop || ImportJScop) 409 PollyEnabled = true; 410 411 return PollyEnabled; 412 } 413 414 static void 415 registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder, 416 llvm::legacy::PassManagerBase &PM) { 417 if (!polly::shouldEnablePolly()) 418 return; 419 420 if (PassPosition != POSITION_EARLY) 421 return; 422 423 registerCanonicalicationPasses(PM); 424 polly::registerPollyPasses(PM); 425 } 426 427 static void 428 registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder, 429 llvm::legacy::PassManagerBase &PM) { 430 if (!polly::shouldEnablePolly()) 431 return; 432 433 if (PassPosition != POSITION_AFTER_LOOPOPT) 434 return; 435 436 PM.add(polly::createCodePreparationPass()); 437 polly::registerPollyPasses(PM); 438 PM.add(createCodegenCleanupPass()); 439 } 440 441 static void 442 registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder, 443 llvm::legacy::PassManagerBase &PM) { 444 if (!polly::shouldEnablePolly()) 445 return; 446 447 if (PassPosition != POSITION_BEFORE_VECTORIZER) 448 return; 449 450 PM.add(polly::createCodePreparationPass()); 451 polly::registerPollyPasses(PM); 452 PM.add(createCodegenCleanupPass()); 453 } 454 455 static void buildDefaultPollyPipeline(FunctionPassManager &PM, 456 PassBuilder::OptimizationLevel Level) { 457 if (!polly::shouldEnablePolly()) 458 return; 459 PassBuilder PB; 460 ScopPassManager SPM; 461 462 // TODO add utility passes for the various command line options, once they're 463 // ported 464 assert(!DumpBefore && "This option is not implemented"); 465 assert(DumpBeforeFile.empty() && "This option is not implemented"); 466 467 if (PollyDetectOnly) 468 return; 469 470 assert(!PollyViewer && "This option is not implemented"); 471 assert(!PollyOnlyViewer && "This option is not implemented"); 472 assert(!PollyPrinter && "This option is not implemented"); 473 assert(!PollyOnlyPrinter && "This option is not implemented"); 474 assert(!EnablePolyhedralInfo && "This option is not implemented"); 475 assert(!EnableDeLICM && "This option is not implemented"); 476 assert(!EnableSimplify && "This option is not implemented"); 477 if (ImportJScop) 478 SPM.addPass(JSONImportPass()); 479 assert(!DeadCodeElim && "This option is not implemented"); 480 assert(!EnablePruneUnprofitable && "This option is not implemented"); 481 if (Target == TARGET_CPU || Target == TARGET_HYBRID) 482 switch (Optimizer) { 483 case OPTIMIZER_NONE: 484 break; /* Do nothing */ 485 case OPTIMIZER_ISL: 486 llvm_unreachable("ISL optimizer is not implemented"); 487 break; 488 } 489 490 assert(!ExportJScop && "This option is not implemented"); 491 492 if (Target == TARGET_CPU || Target == TARGET_HYBRID) { 493 switch (CodeGeneration) { 494 case CODEGEN_FULL: 495 SPM.addPass(polly::CodeGenerationPass()); 496 break; 497 case CODEGEN_AST: 498 default: // Does it actually make sense to distinguish IslAst codegen? 499 break; 500 } 501 } 502 #ifdef GPU_CODEGEN 503 else 504 llvm_unreachable("Hybrid Target with GPU support is not implemented"); 505 #endif 506 507 PM.addPass(CodePreparationPass()); 508 PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); 509 PM.addPass(PB.buildFunctionSimplificationPipeline( 510 Level, PassBuilder::ThinLTOPhase::None)); // Cleanup 511 512 assert(!DumpAfter && "This option is not implemented"); 513 assert(DumpAfterFile.empty() && "This option is not implemented"); 514 515 if (CFGPrinter) 516 PM.addPass(llvm::CFGPrinterPass()); 517 } 518 519 /// Register Polly to be available as an optimizer 520 /// 521 /// 522 /// We can currently run Polly at three different points int the pass manager. 523 /// a) very early, b) after the canonicalizing loop transformations and c) right 524 /// before the vectorizer. 525 /// 526 /// The default is currently a), to register Polly such that it runs as early as 527 /// possible. This has several implications: 528 /// 529 /// 1) We need to schedule more canonicalization passes 530 /// 531 /// As nothing is run before Polly, it is necessary to run a set of preparing 532 /// transformations before Polly to canonicalize the LLVM-IR and to allow 533 /// Polly to detect and understand the code. 534 /// 535 /// 2) LICM and LoopIdiom pass have not yet been run 536 /// 537 /// Loop invariant code motion as well as the loop idiom recognition pass make 538 /// it more difficult for Polly to transform code. LICM may introduce 539 /// additional data dependences that are hard to eliminate and the loop idiom 540 /// recognition pass may introduce calls to memset that we currently do not 541 /// understand. By running Polly early enough (meaning before these passes) we 542 /// avoid difficulties that may be introduced by these passes. 543 /// 544 /// 3) We get the full -O3 optimization sequence after Polly 545 /// 546 /// The LLVM-IR that is generated by Polly has been optimized on a high level, 547 /// but it may be rather inefficient on the lower/scalar level. By scheduling 548 /// Polly before all other passes, we have the full sequence of -O3 549 /// optimizations behind us, such that inefficiencies on the low level can 550 /// be optimized away. 551 /// 552 /// We are currently evaluating the benefit or running Polly at position b) or 553 /// c). b) is likely too early as it interacts with the inliner. c) is nice 554 /// as everything is fully inlined and canonicalized, but we need to be able 555 /// to handle LICMed code to make it useful. 556 static llvm::RegisterStandardPasses RegisterPollyOptimizerEarly( 557 llvm::PassManagerBuilder::EP_ModuleOptimizerEarly, 558 registerPollyEarlyAsPossiblePasses); 559 560 static llvm::RegisterStandardPasses 561 RegisterPollyOptimizerLoopEnd(llvm::PassManagerBuilder::EP_LoopOptimizerEnd, 562 registerPollyLoopOptimizerEndPasses); 563 564 static llvm::RegisterStandardPasses RegisterPollyOptimizerScalarLate( 565 llvm::PassManagerBuilder::EP_VectorizerStart, 566 registerPollyScalarOptimizerLatePasses); 567 568 static OwningScopAnalysisManagerFunctionProxy 569 createScopAnalyses(FunctionAnalysisManager &FAM) { 570 OwningScopAnalysisManagerFunctionProxy Proxy; 571 #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ 572 Proxy.getManager().registerPass([] { return CREATE_PASS; }); 573 574 #include "PollyPasses.def" 575 576 Proxy.getManager().registerPass( 577 [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); }); 578 return Proxy; 579 } 580 581 static void registerFunctionAnalyses(FunctionAnalysisManager &FAM) { 582 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ 583 FAM.registerPass([] { return CREATE_PASS; }); 584 585 #include "PollyPasses.def" 586 587 FAM.registerPass([&FAM] { return createScopAnalyses(FAM); }); 588 } 589 590 static bool 591 parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM, 592 ArrayRef<PassBuilder::PipelineElement> Pipeline) { 593 if (parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>( 594 "polly-scop-analyses", Name, FPM)) 595 return true; 596 597 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ 598 if (parseAnalysisUtilityPasses< \ 599 std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name, \ 600 FPM)) \ 601 return true; 602 603 #define FUNCTION_PASS(NAME, CREATE_PASS) \ 604 if (Name == NAME) { \ 605 FPM.addPass(CREATE_PASS); \ 606 return true; \ 607 } 608 609 #include "PollyPasses.def" 610 return false; 611 } 612 613 static bool parseScopPass(StringRef Name, ScopPassManager &SPM) { 614 #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ 615 if (parseAnalysisUtilityPasses< \ 616 std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name, \ 617 SPM)) \ 618 return true; 619 620 #define SCOP_PASS(NAME, CREATE_PASS) \ 621 if (Name == NAME) { \ 622 SPM.addPass(CREATE_PASS); \ 623 return true; \ 624 } 625 626 #include "PollyPasses.def" 627 628 return false; 629 } 630 631 static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM, 632 ArrayRef<PassBuilder::PipelineElement> Pipeline) { 633 if (Name != "scop") 634 return false; 635 if (!Pipeline.empty()) { 636 ScopPassManager SPM; 637 for (const auto &E : Pipeline) 638 if (!parseScopPass(E.Name, SPM)) 639 return false; 640 FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); 641 } 642 return true; 643 } 644 645 static bool isScopPassName(StringRef Name) { 646 #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ 647 if (Name == "require<" NAME ">") \ 648 return true; \ 649 if (Name == "invalidate<" NAME ">") \ 650 return true; 651 652 #define SCOP_PASS(NAME, CREATE_PASS) \ 653 if (Name == NAME) \ 654 return true; 655 656 #include "PollyPasses.def" 657 658 return false; 659 } 660 661 static bool 662 parseTopLevelPipeline(ModulePassManager &MPM, 663 ArrayRef<PassBuilder::PipelineElement> Pipeline, 664 bool VerifyEachPass, bool DebugLogging) { 665 std::vector<PassBuilder::PipelineElement> FullPipeline; 666 StringRef FirstName = Pipeline.front().Name; 667 668 if (!isScopPassName(FirstName)) 669 return false; 670 671 FunctionPassManager FPM(DebugLogging); 672 ScopPassManager SPM(DebugLogging); 673 674 for (auto &Element : Pipeline) { 675 auto &Name = Element.Name; 676 auto &InnerPipeline = Element.InnerPipeline; 677 if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines 678 return false; 679 if (!parseScopPass(Name, SPM)) 680 return false; 681 } 682 683 FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); 684 if (VerifyEachPass) 685 FPM.addPass(VerifierPass()); 686 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 687 if (VerifyEachPass) 688 MPM.addPass(VerifierPass()); 689 690 return true; 691 } 692 693 void RegisterPollyPasses(PassBuilder &PB) { 694 PB.registerAnalysisRegistrationCallback(registerFunctionAnalyses); 695 PB.registerPipelineParsingCallback(parseFunctionPipeline); 696 PB.registerPipelineParsingCallback(parseScopPipeline); 697 PB.registerParseTopLevelPipelineCallback(parseTopLevelPipeline); 698 699 if (PassPosition == POSITION_BEFORE_VECTORIZER) 700 PB.registerVectorizerStartEPCallback(buildDefaultPollyPipeline); 701 // FIXME else Error? 702 } 703 } // namespace polly 704 705 // Plugin Entrypoint: 706 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK 707 llvmGetPassPluginInfo() { 708 return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING, 709 polly::RegisterPollyPasses}; 710 } 711