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