1 //===------ RegisterPasses.cpp - Add the Polly Passes to default passes --===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file composes the individual LLVM-IR passes provided by Polly to a 11 // functional polyhedral optimizer. The polyhedral optimizer is automatically 12 // made available to LLVM based compilers by loading the Polly shared library 13 // into such a compiler. 14 // 15 // The Polly optimizer is made available by executing a static constructor that 16 // registers the individual Polly passes in the LLVM pass manager builder. The 17 // passes are registered such that the default behaviour of the compiler is not 18 // changed, but that the flag '-polly' provided at optimization level '-O3' 19 // enables additional polyhedral optimizations. 20 //===----------------------------------------------------------------------===// 21 22 #include "polly/RegisterPasses.h" 23 #include "polly/Canonicalization.h" 24 #include "polly/CodeGen/CodeGeneration.h" 25 #include "polly/CodeGen/CodegenCleanup.h" 26 #include "polly/CodeGen/IslAst.h" 27 #include "polly/CodeGen/PPCGCodeGeneration.h" 28 #include "polly/CodePreparation.h" 29 #include "polly/DeLICM.h" 30 #include "polly/DependenceInfo.h" 31 #include "polly/FlattenSchedule.h" 32 #include "polly/ForwardOpTree.h" 33 #include "polly/JSONExporter.h" 34 #include "polly/LinkAllPasses.h" 35 #include "polly/Options.h" 36 #include "polly/PolyhedralInfo.h" 37 #include "polly/ScopDetection.h" 38 #include "polly/ScopInfo.h" 39 #include "polly/Simplify.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/Support/TargetSelect.h" 46 #include "llvm/Transforms/IPO.h" 47 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 48 #include "llvm/Transforms/Scalar.h" 49 #include "llvm/Transforms/Vectorize.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", cl::desc("Enable the polly optimizer (only at -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 #ifdef GPU_CODEGEN 115 static cl::opt<GPURuntime> GPURuntimeChoice( 116 "polly-gpu-runtime", cl::desc("The GPU Runtime API to target"), 117 cl::values(clEnumValN(GPURuntime::CUDA, "libcudart", 118 "use the CUDA Runtime API"), 119 clEnumValN(GPURuntime::OpenCL, "libopencl", 120 "use the OpenCL Runtime API")), 121 cl::init(GPURuntime::CUDA), cl::ZeroOrMore, cl::cat(PollyCategory)); 122 123 static cl::opt<GPUArch> 124 GPUArchChoice("polly-gpu-arch", cl::desc("The GPU Architecture to target"), 125 cl::values(clEnumValN(GPUArch::NVPTX64, "nvptx64", 126 "target NVIDIA 64-bit architecture"), 127 clEnumValN(GPUArch::SPIR32, "spir32", 128 "target SPIR 32-bit architecture"), 129 clEnumValN(GPUArch::SPIR64, "spir64", 130 "target SPIR 64-bit architecture")), 131 cl::init(GPUArch::NVPTX64), cl::ZeroOrMore, 132 cl::cat(PollyCategory)); 133 #endif 134 135 VectorizerChoice polly::PollyVectorizerChoice; 136 static cl::opt<polly::VectorizerChoice, true> Vectorizer( 137 "polly-vectorizer", cl::desc("Select the vectorization strategy"), 138 cl::values( 139 clEnumValN(polly::VECTORIZER_NONE, "none", "No Vectorization"), 140 clEnumValN(polly::VECTORIZER_POLLY, "polly", 141 "Polly internal vectorizer"), 142 clEnumValN( 143 polly::VECTORIZER_STRIPMINE, "stripmine", 144 "Strip-mine outer loops for the loop-vectorizer to trigger")), 145 cl::location(PollyVectorizerChoice), cl::init(polly::VECTORIZER_NONE), 146 cl::ZeroOrMore, cl::cat(PollyCategory)); 147 148 static cl::opt<bool> ImportJScop( 149 "polly-import", 150 cl::desc("Import the polyhedral description of the detected Scops"), 151 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 152 153 static cl::opt<bool> FullyIndexedStaticExpansion( 154 "polly-enable-mse", 155 cl::desc("Fully expand the memory accesses of the detected Scops"), 156 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 157 158 static cl::opt<bool> ExportJScop( 159 "polly-export", 160 cl::desc("Export the polyhedral description of the detected Scops"), 161 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 162 163 static cl::opt<bool> DeadCodeElim("polly-run-dce", 164 cl::desc("Run the dead code elimination"), 165 cl::Hidden, cl::init(false), cl::ZeroOrMore, 166 cl::cat(PollyCategory)); 167 168 static cl::opt<bool> PollyViewer( 169 "polly-show", 170 cl::desc("Highlight the code regions that will be optimized in a " 171 "(CFG BBs and LLVM-IR instructions)"), 172 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 173 174 static cl::opt<bool> PollyOnlyViewer( 175 "polly-show-only", 176 cl::desc("Highlight the code regions that will be optimized in " 177 "a (CFG only BBs)"), 178 cl::init(false), cl::cat(PollyCategory)); 179 180 static cl::opt<bool> 181 PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"), 182 cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"), 183 cl::init(false), cl::cat(PollyCategory)); 184 185 static cl::opt<bool> PollyOnlyPrinter( 186 "polly-dot-only", 187 cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden, 188 cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"), 189 cl::init(false), cl::cat(PollyCategory)); 190 191 static cl::opt<bool> 192 CFGPrinter("polly-view-cfg", 193 cl::desc("Show the Polly CFG right after code generation"), 194 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 195 196 static cl::opt<bool> 197 EnablePolyhedralInfo("polly-enable-polyhedralinfo", 198 cl::desc("Enable polyhedral interface of Polly"), 199 cl::Hidden, cl::init(false), cl::cat(PollyCategory)); 200 201 static cl::opt<bool> 202 EnableForwardOpTree("polly-enable-optree", 203 cl::desc("Enable operand tree forwarding"), cl::Hidden, 204 cl::init(true), cl::cat(PollyCategory)); 205 206 static cl::opt<bool> 207 DumpBefore("polly-dump-before", 208 cl::desc("Dump module before Polly transformations into a file " 209 "suffixed with \"-before\""), 210 cl::init(false), cl::cat(PollyCategory)); 211 212 static cl::list<std::string> DumpBeforeFile( 213 "polly-dump-before-file", 214 cl::desc("Dump module before Polly transformations to the given file"), 215 cl::cat(PollyCategory)); 216 217 static cl::opt<bool> 218 DumpAfter("polly-dump-after", 219 cl::desc("Dump module after Polly transformations into a file " 220 "suffixed with \"-after\""), 221 cl::init(false), cl::cat(PollyCategory)); 222 223 static cl::list<std::string> DumpAfterFile( 224 "polly-dump-after-file", 225 cl::desc("Dump module after Polly transformations to the given file"), 226 cl::ZeroOrMore, cl::cat(PollyCategory)); 227 228 static cl::opt<bool> 229 EnableDeLICM("polly-enable-delicm", 230 cl::desc("Eliminate scalar loop carried dependences"), 231 cl::Hidden, cl::init(true), cl::cat(PollyCategory)); 232 233 static cl::opt<bool> 234 EnableSimplify("polly-enable-simplify", 235 cl::desc("Simplify SCoP after optimizations"), 236 cl::init(true), cl::cat(PollyCategory)); 237 238 static cl::opt<bool> EnablePruneUnprofitable( 239 "polly-enable-prune-unprofitable", 240 cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden, 241 cl::init(true), cl::cat(PollyCategory)); 242 243 namespace polly { 244 void initializePollyPasses(PassRegistry &Registry) { 245 initializeCodeGenerationPass(Registry); 246 247 #ifdef GPU_CODEGEN 248 initializePPCGCodeGenerationPass(Registry); 249 initializeManagedMemoryRewritePassPass(Registry); 250 LLVMInitializeNVPTXTarget(); 251 LLVMInitializeNVPTXTargetInfo(); 252 LLVMInitializeNVPTXTargetMC(); 253 LLVMInitializeNVPTXAsmPrinter(); 254 #endif 255 initializeCodePreparationPass(Registry); 256 initializeDeadCodeElimPass(Registry); 257 initializeDependenceInfoPass(Registry); 258 initializeDependenceInfoWrapperPassPass(Registry); 259 initializeJSONExporterPass(Registry); 260 initializeJSONImporterPass(Registry); 261 initializeMaximalStaticExpanderPass(Registry); 262 initializeIslAstInfoWrapperPassPass(Registry); 263 initializeIslScheduleOptimizerPass(Registry); 264 initializePollyCanonicalizePass(Registry); 265 initializePolyhedralInfoPass(Registry); 266 initializeScopDetectionWrapperPassPass(Registry); 267 initializeScopInlinerPass(Registry); 268 initializeScopInfoRegionPassPass(Registry); 269 initializeScopInfoWrapperPassPass(Registry); 270 initializeRewriteByrefParamsPass(Registry); 271 initializeCodegenCleanupPass(Registry); 272 initializeFlattenSchedulePass(Registry); 273 initializeForwardOpTreePass(Registry); 274 initializeDeLICMPass(Registry); 275 initializeSimplifyPass(Registry); 276 initializeDumpModulePass(Registry); 277 initializePruneUnprofitablePass(Registry); 278 } 279 280 /// Register Polly passes such that they form a polyhedral optimizer. 281 /// 282 /// The individual Polly passes are registered in the pass manager such that 283 /// they form a full polyhedral optimizer. The flow of the optimizer starts with 284 /// a set of preparing transformations that canonicalize the LLVM-IR such that 285 /// the LLVM-IR is easier for us to understand and to optimizes. On the 286 /// canonicalized LLVM-IR we first run the ScopDetection pass, which detects 287 /// static control flow regions. Those regions are then translated by the 288 /// ScopInfo pass into a polyhedral representation. As a next step, a scheduling 289 /// optimizer is run on the polyhedral representation and finally the optimized 290 /// polyhedral representation is code generated back to LLVM-IR. 291 /// 292 /// Besides this core functionality, we optionally schedule passes that provide 293 /// a graphical view of the scops (Polly[Only]Viewer, Polly[Only]Printer), that 294 /// allow the export/import of the polyhedral representation 295 /// (JSCON[Exporter|Importer]) or that show the cfg after code generation. 296 /// 297 /// For certain parts of the Polly optimizer, several alternatives are provided: 298 /// 299 /// As scheduling optimizer we support the isl scheduling optimizer 300 /// (http://freecode.com/projects/isl). 301 /// It is also possible to run Polly with no optimizer. This mode is mainly 302 /// provided to analyze the run and compile time changes caused by the 303 /// scheduling optimizer. 304 /// 305 /// Polly supports the isl internal code generator. 306 void registerPollyPasses(llvm::legacy::PassManagerBase &PM) { 307 if (DumpBefore) 308 PM.add(polly::createDumpModulePass("-before", true)); 309 for (auto &Filename : DumpBeforeFile) 310 PM.add(polly::createDumpModulePass(Filename, false)); 311 312 PM.add(polly::createScopDetectionWrapperPassPass()); 313 314 if (PollyDetectOnly) 315 return; 316 317 if (PollyViewer) 318 PM.add(polly::createDOTViewerPass()); 319 if (PollyOnlyViewer) 320 PM.add(polly::createDOTOnlyViewerPass()); 321 if (PollyPrinter) 322 PM.add(polly::createDOTPrinterPass()); 323 if (PollyOnlyPrinter) 324 PM.add(polly::createDOTOnlyPrinterPass()); 325 326 PM.add(polly::createScopInfoRegionPassPass()); 327 if (EnablePolyhedralInfo) 328 PM.add(polly::createPolyhedralInfoPass()); 329 330 if (EnableSimplify) 331 PM.add(polly::createSimplifyPass(0)); 332 if (EnableForwardOpTree) 333 PM.add(polly::createForwardOpTreePass()); 334 if (EnableDeLICM) 335 PM.add(polly::createDeLICMPass()); 336 if (EnableSimplify) 337 PM.add(polly::createSimplifyPass(1)); 338 339 if (ImportJScop) 340 PM.add(polly::createJSONImporterPass()); 341 342 if (DeadCodeElim) 343 PM.add(polly::createDeadCodeElimPass()); 344 345 if (FullyIndexedStaticExpansion) 346 PM.add(polly::createMaximalStaticExpansionPass()); 347 348 if (EnablePruneUnprofitable) 349 PM.add(polly::createPruneUnprofitablePass()); 350 351 #ifdef GPU_CODEGEN 352 if (Target == TARGET_HYBRID) { 353 PM.add( 354 polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice)); 355 PM.add(polly::createManagedMemoryRewritePassPass(GPUArchChoice, 356 GPURuntimeChoice)); 357 } 358 #endif 359 if (Target == TARGET_CPU || Target == TARGET_HYBRID) 360 switch (Optimizer) { 361 case OPTIMIZER_NONE: 362 break; /* Do nothing */ 363 364 case OPTIMIZER_ISL: 365 PM.add(polly::createIslScheduleOptimizerPass()); 366 break; 367 } 368 369 if (ExportJScop) 370 PM.add(polly::createJSONExporterPass()); 371 372 if (Target == TARGET_CPU || Target == TARGET_HYBRID) 373 switch (CodeGeneration) { 374 case CODEGEN_AST: 375 PM.add(polly::createIslAstInfoWrapperPassPass()); 376 break; 377 case CODEGEN_FULL: 378 PM.add(polly::createCodeGenerationPass()); 379 break; 380 case CODEGEN_NONE: 381 break; 382 } 383 #ifdef GPU_CODEGEN 384 else { 385 PM.add( 386 polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice)); 387 PM.add(polly::createManagedMemoryRewritePassPass()); 388 } 389 #endif 390 391 // FIXME: This dummy ModulePass keeps some programs from miscompiling, 392 // probably some not correctly preserved analyses. It acts as a barrier to 393 // force all analysis results to be recomputed. 394 PM.add(createBarrierNoopPass()); 395 396 if (DumpAfter) 397 PM.add(polly::createDumpModulePass("-after", true)); 398 for (auto &Filename : DumpAfterFile) 399 PM.add(polly::createDumpModulePass(Filename, false)); 400 401 if (CFGPrinter) 402 PM.add(llvm::createCFGPrinterLegacyPassPass()); 403 } 404 405 static bool shouldEnablePolly() { 406 if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer) 407 PollyTrackFailures = true; 408 409 if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer || 410 ExportJScop || ImportJScop) 411 PollyEnabled = true; 412 413 return PollyEnabled; 414 } 415 416 static void 417 registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder, 418 llvm::legacy::PassManagerBase &PM) { 419 if (!polly::shouldEnablePolly()) 420 return; 421 422 if (PassPosition != POSITION_EARLY) 423 return; 424 425 registerCanonicalicationPasses(PM); 426 polly::registerPollyPasses(PM); 427 } 428 429 static void 430 registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder, 431 llvm::legacy::PassManagerBase &PM) { 432 if (!polly::shouldEnablePolly()) 433 return; 434 435 if (PassPosition != POSITION_AFTER_LOOPOPT) 436 return; 437 438 PM.add(polly::createCodePreparationPass()); 439 polly::registerPollyPasses(PM); 440 PM.add(createCodegenCleanupPass()); 441 } 442 443 static void 444 registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder, 445 llvm::legacy::PassManagerBase &PM) { 446 if (!polly::shouldEnablePolly()) 447 return; 448 449 if (PassPosition != POSITION_BEFORE_VECTORIZER) 450 return; 451 452 PM.add(polly::createCodePreparationPass()); 453 polly::registerPollyPasses(PM); 454 PM.add(createCodegenCleanupPass()); 455 } 456 457 static void buildDefaultPollyPipeline(FunctionPassManager &PM, 458 PassBuilder::OptimizationLevel Level) { 459 if (!polly::shouldEnablePolly()) 460 return; 461 PassBuilder PB; 462 ScopPassManager SPM; 463 464 // TODO add utility passes for the various command line options, once they're 465 // ported 466 assert(!DumpBefore && "This option is not implemented"); 467 assert(DumpBeforeFile.empty() && "This option is not implemented"); 468 469 if (PollyDetectOnly) 470 return; 471 472 assert(!PollyViewer && "This option is not implemented"); 473 assert(!PollyOnlyViewer && "This option is not implemented"); 474 assert(!PollyPrinter && "This option is not implemented"); 475 assert(!PollyOnlyPrinter && "This option is not implemented"); 476 assert(!EnablePolyhedralInfo && "This option is not implemented"); 477 assert(!EnableDeLICM && "This option is not implemented"); 478 assert(!EnableSimplify && "This option is not implemented"); 479 if (ImportJScop) 480 SPM.addPass(JSONImportPass()); 481 assert(!DeadCodeElim && "This option is not implemented"); 482 assert(!EnablePruneUnprofitable && "This option is not implemented"); 483 if (Target == TARGET_CPU || Target == TARGET_HYBRID) 484 switch (Optimizer) { 485 case OPTIMIZER_NONE: 486 break; /* Do nothing */ 487 case OPTIMIZER_ISL: 488 llvm_unreachable("ISL optimizer is not implemented"); 489 break; 490 } 491 492 assert(!ExportJScop && "This option is not implemented"); 493 494 if (Target == TARGET_CPU || Target == TARGET_HYBRID) { 495 switch (CodeGeneration) { 496 case CODEGEN_FULL: 497 SPM.addPass(polly::CodeGenerationPass()); 498 break; 499 case CODEGEN_AST: 500 default: // Does it actually make sense to distinguish IslAst codegen? 501 break; 502 } 503 } 504 #ifdef GPU_CODEGEN 505 else 506 llvm_unreachable("Hybrid Target with GPU support is not implemented"); 507 #endif 508 509 PM.addPass(CodePreparationPass()); 510 PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); 511 PM.addPass(PB.buildFunctionSimplificationPipeline( 512 Level, PassBuilder::ThinLTOPhase::None)); // Cleanup 513 514 assert(!DumpAfter && "This option is not implemented"); 515 assert(DumpAfterFile.empty() && "This option is not implemented"); 516 517 if (CFGPrinter) 518 PM.addPass(llvm::CFGPrinterPass()); 519 } 520 521 /// Register Polly to be available as an optimizer 522 /// 523 /// 524 /// We can currently run Polly at three different points int the pass manager. 525 /// a) very early, b) after the canonicalizing loop transformations and c) right 526 /// before the vectorizer. 527 /// 528 /// The default is currently a), to register Polly such that it runs as early as 529 /// possible. This has several implications: 530 /// 531 /// 1) We need to schedule more canonicalization passes 532 /// 533 /// As nothing is run before Polly, it is necessary to run a set of preparing 534 /// transformations before Polly to canonicalize the LLVM-IR and to allow 535 /// Polly to detect and understand the code. 536 /// 537 /// 2) LICM and LoopIdiom pass have not yet been run 538 /// 539 /// Loop invariant code motion as well as the loop idiom recognition pass make 540 /// it more difficult for Polly to transform code. LICM may introduce 541 /// additional data dependences that are hard to eliminate and the loop idiom 542 /// recognition pass may introduce calls to memset that we currently do not 543 /// understand. By running Polly early enough (meaning before these passes) we 544 /// avoid difficulties that may be introduced by these passes. 545 /// 546 /// 3) We get the full -O3 optimization sequence after Polly 547 /// 548 /// The LLVM-IR that is generated by Polly has been optimized on a high level, 549 /// but it may be rather inefficient on the lower/scalar level. By scheduling 550 /// Polly before all other passes, we have the full sequence of -O3 551 /// optimizations behind us, such that inefficiencies on the low level can 552 /// be optimized away. 553 /// 554 /// We are currently evaluating the benefit or running Polly at position b) or 555 /// c). b) is likely too early as it interacts with the inliner. c) is nice 556 /// as everything is fully inlined and canonicalized, but we need to be able 557 /// to handle LICMed code to make it useful. 558 static llvm::RegisterStandardPasses RegisterPollyOptimizerEarly( 559 llvm::PassManagerBuilder::EP_ModuleOptimizerEarly, 560 registerPollyEarlyAsPossiblePasses); 561 562 static llvm::RegisterStandardPasses 563 RegisterPollyOptimizerLoopEnd(llvm::PassManagerBuilder::EP_LoopOptimizerEnd, 564 registerPollyLoopOptimizerEndPasses); 565 566 static llvm::RegisterStandardPasses RegisterPollyOptimizerScalarLate( 567 llvm::PassManagerBuilder::EP_VectorizerStart, 568 registerPollyScalarOptimizerLatePasses); 569 570 static OwningScopAnalysisManagerFunctionProxy 571 createScopAnalyses(FunctionAnalysisManager &FAM) { 572 OwningScopAnalysisManagerFunctionProxy Proxy; 573 #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ 574 Proxy.getManager().registerPass([] { return CREATE_PASS; }); 575 576 #include "PollyPasses.def" 577 578 Proxy.getManager().registerPass( 579 [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); }); 580 return Proxy; 581 } 582 583 static void registerFunctionAnalyses(FunctionAnalysisManager &FAM) { 584 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ 585 FAM.registerPass([] { return CREATE_PASS; }); 586 587 #include "PollyPasses.def" 588 589 FAM.registerPass([&FAM] { return createScopAnalyses(FAM); }); 590 } 591 592 static bool 593 parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM, 594 ArrayRef<PassBuilder::PipelineElement> Pipeline) { 595 if (parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>( 596 "polly-scop-analyses", Name, FPM)) 597 return true; 598 599 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ 600 if (parseAnalysisUtilityPasses< \ 601 std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name, \ 602 FPM)) \ 603 return true; 604 605 #define FUNCTION_PASS(NAME, CREATE_PASS) \ 606 if (Name == NAME) { \ 607 FPM.addPass(CREATE_PASS); \ 608 return true; \ 609 } 610 611 #include "PollyPasses.def" 612 return false; 613 } 614 615 static bool parseScopPass(StringRef Name, ScopPassManager &SPM) { 616 #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ 617 if (parseAnalysisUtilityPasses< \ 618 std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name, \ 619 SPM)) \ 620 return true; 621 622 #define SCOP_PASS(NAME, CREATE_PASS) \ 623 if (Name == NAME) { \ 624 SPM.addPass(CREATE_PASS); \ 625 return true; \ 626 } 627 628 #include "PollyPasses.def" 629 630 return false; 631 } 632 633 static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM, 634 ArrayRef<PassBuilder::PipelineElement> Pipeline) { 635 if (Name != "scop") 636 return false; 637 if (!Pipeline.empty()) { 638 ScopPassManager SPM; 639 for (const auto &E : Pipeline) 640 if (!parseScopPass(E.Name, SPM)) 641 return false; 642 FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); 643 } 644 return true; 645 } 646 647 static bool isScopPassName(StringRef Name) { 648 #define SCOP_ANALYSIS(NAME, CREATE_PASS) \ 649 if (Name == "require<" NAME ">") \ 650 return true; \ 651 if (Name == "invalidate<" NAME ">") \ 652 return true; 653 654 #define SCOP_PASS(NAME, CREATE_PASS) \ 655 if (Name == NAME) \ 656 return true; 657 658 #include "PollyPasses.def" 659 660 return false; 661 } 662 663 static bool 664 parseTopLevelPipeline(ModulePassManager &MPM, 665 ArrayRef<PassBuilder::PipelineElement> Pipeline, 666 bool VerifyEachPass, bool DebugLogging) { 667 std::vector<PassBuilder::PipelineElement> FullPipeline; 668 StringRef FirstName = Pipeline.front().Name; 669 670 if (!isScopPassName(FirstName)) 671 return false; 672 673 FunctionPassManager FPM(DebugLogging); 674 ScopPassManager SPM(DebugLogging); 675 676 for (auto &Element : Pipeline) { 677 auto &Name = Element.Name; 678 auto &InnerPipeline = Element.InnerPipeline; 679 if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines 680 return false; 681 if (!parseScopPass(Name, SPM)) 682 return false; 683 } 684 685 FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); 686 if (VerifyEachPass) 687 FPM.addPass(VerifierPass()); 688 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 689 if (VerifyEachPass) 690 MPM.addPass(VerifierPass()); 691 692 return true; 693 } 694 695 void RegisterPollyPasses(PassBuilder &PB) { 696 PB.registerAnalysisRegistrationCallback(registerFunctionAnalyses); 697 PB.registerPipelineParsingCallback(parseFunctionPipeline); 698 PB.registerPipelineParsingCallback(parseScopPipeline); 699 PB.registerParseTopLevelPipelineCallback(parseTopLevelPipeline); 700 701 if (PassPosition == POSITION_BEFORE_VECTORIZER) 702 PB.registerVectorizerStartEPCallback(buildDefaultPollyPipeline); 703 // FIXME else Error? 704 } 705 } // namespace polly 706