682 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file composes the individual LLVM-IR passes provided by Polly to a10// functional polyhedral optimizer. The polyhedral optimizer is automatically11// made available to LLVM based compilers by loading the Polly shared library12// into such a compiler.13//14// The Polly optimizer is made available by executing a static constructor that15// registers the individual Polly passes in the LLVM pass manager builder. The16// passes are registered such that the default behaviour of the compiler is not17// 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/IslAst.h"25#include "polly/CodePreparation.h"26#include "polly/DeLICM.h"27#include "polly/DeadCodeElimination.h"28#include "polly/DependenceInfo.h"29#include "polly/ForwardOpTree.h"30#include "polly/JSONExporter.h"31#include "polly/MaximalStaticExpansion.h"32#include "polly/Options.h"33#include "polly/Pass/PollyFunctionPass.h"34#include "polly/PruneUnprofitable.h"35#include "polly/ScheduleOptimizer.h"36#include "polly/ScopDetection.h"37#include "polly/ScopGraphPrinter.h"38#include "polly/ScopInfo.h"39#include "polly/ScopInliner.h"40#include "polly/Simplify.h"41#include "polly/Support/DumpFunctionPass.h"42#include "polly/Support/DumpModulePass.h"43#include "llvm/Analysis/CFGPrinter.h"44#include "llvm/Config/llvm-config.h" // for LLVM_VERSION_STRING45#include "llvm/IR/LegacyPassManager.h"46#include "llvm/IR/PassManager.h"47#include "llvm/IR/Verifier.h"48#include "llvm/Passes/PassBuilder.h"49#include "llvm/Passes/PassPlugin.h"50#include "llvm/Support/CommandLine.h"51#include "llvm/Support/Error.h"52#include "llvm/Support/TargetSelect.h"53#include "llvm/Transforms/IPO.h"54 55using namespace llvm;56using namespace polly;57 58namespace cl = llvm::cl;59using namespace polly;60 61using llvm::FunctionPassManager;62using llvm::OptimizationLevel;63using llvm::PassBuilder;64using llvm::PassInstrumentationCallbacks;65 66cl::OptionCategory PollyCategory("Polly Options",67 "Configure the polly loop optimizer");68 69namespace polly {70static cl::opt<bool>71 PollyEnabled("polly",72 cl::desc("Enable the polly optimizer (with -O1, -O2 or -O3)"),73 cl::cat(PollyCategory));74 75static cl::opt<bool> PollyDetectOnly(76 "polly-only-scop-detection",77 cl::desc("Only run scop detection, but no other optimizations"),78 cl::cat(PollyCategory));79 80enum PassPositionChoice { POSITION_EARLY, POSITION_BEFORE_VECTORIZER };81 82enum OptimizerChoice { OPTIMIZER_NONE, OPTIMIZER_ISL };83 84static cl::opt<PassPositionChoice> PassPosition(85 "polly-position", cl::desc("Where to run polly in the pass pipeline"),86 cl::values(clEnumValN(POSITION_EARLY, "early", "Before everything"),87 clEnumValN(POSITION_BEFORE_VECTORIZER, "before-vectorizer",88 "Right before the vectorizer")),89 cl::Hidden, cl::init(POSITION_BEFORE_VECTORIZER), cl::cat(PollyCategory));90 91static cl::opt<OptimizerChoice>92 Optimizer("polly-optimizer", cl::desc("Select the scheduling optimizer"),93 cl::values(clEnumValN(OPTIMIZER_NONE, "none", "No optimizer"),94 clEnumValN(OPTIMIZER_ISL, "isl",95 "The isl scheduling optimizer")),96 cl::Hidden, cl::init(OPTIMIZER_ISL), cl::cat(PollyCategory));97 98enum CodeGenChoice { CODEGEN_FULL, CODEGEN_AST, CODEGEN_NONE };99static cl::opt<CodeGenChoice> CodeGeneration(100 "polly-code-generation", cl::desc("How much code-generation to perform"),101 cl::values(clEnumValN(CODEGEN_FULL, "full", "AST and IR generation"),102 clEnumValN(CODEGEN_AST, "ast", "Only AST generation"),103 clEnumValN(CODEGEN_NONE, "none", "No code generation")),104 cl::Hidden, cl::init(CODEGEN_FULL), cl::cat(PollyCategory));105 106VectorizerChoice PollyVectorizerChoice;107 108static cl::opt<VectorizerChoice, true> Vectorizer(109 "polly-vectorizer", cl::desc("Select the vectorization strategy"),110 cl::values(111 clEnumValN(VECTORIZER_NONE, "none", "No Vectorization"),112 clEnumValN(113 VECTORIZER_STRIPMINE, "stripmine",114 "Strip-mine outer loops for the loop-vectorizer to trigger")),115 cl::location(PollyVectorizerChoice), cl::init(VECTORIZER_NONE),116 cl::cat(PollyCategory));117 118static cl::opt<bool> ImportJScop(119 "polly-import",120 cl::desc("Import the polyhedral description of the detected Scops"),121 cl::Hidden, cl::cat(PollyCategory));122 123static cl::opt<bool> FullyIndexedStaticExpansion(124 "polly-enable-mse",125 cl::desc("Fully expand the memory accesses of the detected Scops"),126 cl::Hidden, cl::cat(PollyCategory));127 128static cl::opt<bool> ExportJScop(129 "polly-export",130 cl::desc("Export the polyhedral description of the detected Scops"),131 cl::Hidden, cl::cat(PollyCategory));132 133static cl::opt<bool> DeadCodeElim("polly-run-dce",134 cl::desc("Run the dead code elimination"),135 cl::Hidden, cl::cat(PollyCategory));136 137static cl::opt<bool> PollyViewer(138 "polly-show",139 cl::desc("Highlight the code regions that will be optimized in a "140 "(CFG BBs and LLVM-IR instructions)"),141 cl::cat(PollyCategory));142 143static cl::opt<bool> PollyOnlyViewer(144 "polly-show-only",145 cl::desc("Highlight the code regions that will be optimized in "146 "a (CFG only BBs)"),147 cl::init(false), cl::cat(PollyCategory));148 149static cl::opt<bool>150 PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"),151 cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"),152 cl::init(false), cl::cat(PollyCategory));153 154static cl::opt<bool> PollyOnlyPrinter(155 "polly-dot-only",156 cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden,157 cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"),158 cl::init(false), cl::cat(PollyCategory));159 160static cl::opt<bool>161 CFGPrinter("polly-view-cfg",162 cl::desc("Show the Polly CFG right after code generation"),163 cl::Hidden, cl::init(false), cl::cat(PollyCategory));164 165static cl::opt<bool>166 EnableForwardOpTree("polly-enable-optree",167 cl::desc("Enable operand tree forwarding"), cl::Hidden,168 cl::init(true), cl::cat(PollyCategory));169 170static cl::opt<bool>171 DumpBefore("polly-dump-before",172 cl::desc("Dump module before Polly transformations into a file "173 "suffixed with \"-before\""),174 cl::init(false), cl::cat(PollyCategory));175 176static cl::list<std::string> DumpBeforeFile(177 "polly-dump-before-file",178 cl::desc("Dump module before Polly transformations to the given file"),179 cl::cat(PollyCategory));180 181static cl::opt<bool>182 DumpAfter("polly-dump-after",183 cl::desc("Dump module after Polly transformations into a file "184 "suffixed with \"-after\""),185 cl::init(false), cl::cat(PollyCategory));186 187static cl::list<std::string> DumpAfterFile(188 "polly-dump-after-file",189 cl::desc("Dump module after Polly transformations to the given file"),190 cl::cat(PollyCategory));191 192static cl::opt<bool>193 EnableDeLICM("polly-enable-delicm",194 cl::desc("Eliminate scalar loop carried dependences"),195 cl::Hidden, cl::init(true), cl::cat(PollyCategory));196 197static cl::opt<bool>198 EnableSimplify("polly-enable-simplify",199 cl::desc("Simplify SCoP after optimizations"),200 cl::init(true), cl::cat(PollyCategory));201 202static cl::opt<bool> EnablePruneUnprofitable(203 "polly-enable-prune-unprofitable",204 cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden,205 cl::init(true), cl::cat(PollyCategory));206 207static cl::opt<bool>208 PollyPrintDetect("polly-print-detect",209 cl::desc("Polly - Print static control parts (SCoPs)"),210 cl::cat(PollyCategory));211 212static cl::opt<bool>213 PollyPrintScops("polly-print-scops",214 cl::desc("Print polyhedral description of all regions"),215 cl::cat(PollyCategory));216 217static cl::opt<bool> PollyPrintDeps("polly-print-deps",218 cl::desc("Polly - Print dependences"),219 cl::cat(PollyCategory));220 221static bool shouldEnablePollyForOptimization() { return PollyEnabled; }222 223static bool shouldEnablePollyForDiagnostic() {224 // FIXME: PollyTrackFailures is user-controlled, should not be set225 // programmatically.226 if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)227 PollyTrackFailures = true;228 229 return PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||230 ExportJScop;231}232 233/// Parser of parameters for LoopVectorize pass.234static llvm::Expected<PollyPassOptions> parsePollyOptions(StringRef Params,235 bool IsCustom) {236 PassPhase PrevPhase = PassPhase::None;237 238 bool EnableDefaultOpts = !IsCustom;239 bool EnableEnd2End = !IsCustom;240 std::optional<bool>241 PassEnabled[static_cast<size_t>(PassPhase::PassPhaseLast) + 1];242 PassPhase StopAfter = PassPhase::None;243 244 // Passes enabled using command-line flags (can be overridden using245 // 'polly<no-pass>')246 if (PollyPrintDetect)247 PassEnabled[static_cast<size_t>(PassPhase::PrintDetect)] = true;248 if (PollyPrintScops)249 PassEnabled[static_cast<size_t>(PassPhase::PrintScopInfo)] = true;250 if (PollyPrintDeps)251 PassEnabled[static_cast<size_t>(PassPhase::PrintDependences)] = true;252 253 if (PollyViewer)254 PassEnabled[static_cast<size_t>(PassPhase::ViewScops)] = true;255 if (PollyOnlyViewer)256 PassEnabled[static_cast<size_t>(PassPhase::ViewScopsOnly)] = true;257 if (PollyPrinter)258 PassEnabled[static_cast<size_t>(PassPhase::DotScops)] = true;259 if (PollyOnlyPrinter)260 PassEnabled[static_cast<size_t>(PassPhase::DotScopsOnly)] = true;261 if (!EnableSimplify)262 PassEnabled[static_cast<size_t>(PassPhase::Simplify0)] = false;263 if (!EnableForwardOpTree)264 PassEnabled[static_cast<size_t>(PassPhase::Optree)] = false;265 if (!EnableDeLICM)266 PassEnabled[static_cast<size_t>(PassPhase::DeLICM)] = false;267 if (!EnableSimplify)268 PassEnabled[static_cast<size_t>(PassPhase::Simplify1)] = false;269 if (ImportJScop)270 PassEnabled[static_cast<size_t>(PassPhase::ImportJScop)] = true;271 if (DeadCodeElim)272 PassEnabled[static_cast<size_t>(PassPhase::DeadCodeElimination)] = true;273 if (FullyIndexedStaticExpansion)274 PassEnabled[static_cast<size_t>(PassPhase::MaximumStaticExtension)] = true;275 if (!EnablePruneUnprofitable)276 PassEnabled[static_cast<size_t>(PassPhase::PruneUnprofitable)] = false;277 switch (Optimizer) {278 case OPTIMIZER_NONE:279 // explicitly switched off280 PassEnabled[static_cast<size_t>(PassPhase::Optimization)] = false;281 break;282 case OPTIMIZER_ISL:283 // default: enabled284 break;285 }286 if (ExportJScop)287 PassEnabled[static_cast<size_t>(PassPhase::ExportJScop)] = true;288 switch (CodeGeneration) {289 case CODEGEN_AST:290 PassEnabled[static_cast<size_t>(PassPhase::AstGen)] = true;291 PassEnabled[static_cast<size_t>(PassPhase::CodeGen)] = false;292 break;293 case CODEGEN_FULL:294 // default: ast and codegen enabled295 break;296 case CODEGEN_NONE:297 PassEnabled[static_cast<size_t>(PassPhase::AstGen)] = false;298 PassEnabled[static_cast<size_t>(PassPhase::CodeGen)] = false;299 break;300 }301 302 while (!Params.empty()) {303 StringRef Param;304 std::tie(Param, Params) = Params.split(';');305 auto [ParamName, ParamVal] = Param.split('=');306 307 if (ParamName == "stopafter") {308 StopAfter = parsePhase(ParamVal);309 if (StopAfter == PassPhase::None)310 return make_error<StringError>(311 formatv("invalid stopafter parameter value '{0}'", ParamVal).str(),312 inconvertibleErrorCode());313 continue;314 }315 316 if (!ParamVal.empty())317 return make_error<StringError>(318 formatv("parameter '{0}' does not take value", ParamName).str(),319 inconvertibleErrorCode());320 321 bool Enabled = true;322 if (ParamName.starts_with("no-")) {323 Enabled = false;324 ParamName = ParamName.drop_front(3);325 }326 327 if (ParamName == "default-opts") {328 EnableDefaultOpts = Enabled;329 continue;330 }331 332 if (ParamName == "end2end") {333 EnableEnd2End = Enabled;334 continue;335 }336 337 PassPhase Phase;338 339 // Shortcut for both simplifys at the same time340 if (ParamName == "simplify") {341 PassEnabled[static_cast<size_t>(PassPhase::Simplify0)] = Enabled;342 PassEnabled[static_cast<size_t>(PassPhase::Simplify1)] = Enabled;343 Phase = PassPhase::Simplify0;344 } else {345 Phase = parsePhase(ParamName);346 if (Phase == PassPhase::None)347 return make_error<StringError>(348 formatv("invalid Polly parameter/phase name '{0}'", ParamName)349 .str(),350 inconvertibleErrorCode());351 352 if (PrevPhase >= Phase)353 return make_error<StringError>(354 formatv("phases must not be repeated and enumerated in-order: "355 "'{0}' listed before '{1}'",356 getPhaseName(PrevPhase), getPhaseName(Phase))357 .str(),358 inconvertibleErrorCode());359 360 PassEnabled[static_cast<size_t>(Phase)] = Enabled;361 }362 PrevPhase = Phase;363 }364 365 PollyPassOptions Opts;366 Opts.ViewAll = ViewAll;367 Opts.ViewFilter = ViewFilter;368 Opts.PrintDepsAnalysisLevel = OptAnalysisLevel;369 370 // Implicitly enable dependent phases first. May be overriden explicitly371 // on/off later.372 for (PassPhase P : llvm::enum_seq_inclusive(PassPhase::PassPhaseFirst,373 PassPhase::PassPhaseLast)) {374 bool Enabled = PassEnabled[static_cast<size_t>(P)].value_or(false);375 if (!Enabled)376 continue;377 378 if (static_cast<size_t>(PassPhase::Detection) < static_cast<size_t>(P))379 Opts.setPhaseEnabled(PassPhase::Detection);380 381 if (static_cast<size_t>(PassPhase::ScopInfo) < static_cast<size_t>(P))382 Opts.setPhaseEnabled(PassPhase::ScopInfo);383 384 if (dependsOnDependenceInfo(P))385 Opts.setPhaseEnabled(PassPhase::Dependences);386 387 if (static_cast<size_t>(PassPhase::AstGen) < static_cast<size_t>(P))388 Opts.setPhaseEnabled(PassPhase::AstGen);389 }390 391 if (EnableEnd2End)392 Opts.enableEnd2End();393 394 if (EnableDefaultOpts)395 Opts.enableDefaultOpts();396 397 for (PassPhase P : llvm::enum_seq_inclusive(PassPhase::PassPhaseFirst,398 PassPhase::PassPhaseLast)) {399 std::optional<bool> Enabled = PassEnabled[static_cast<size_t>(P)];400 401 // Apply only if set explicitly.402 if (Enabled.has_value())403 Opts.setPhaseEnabled(P, *Enabled);404 }405 406 if (StopAfter != PassPhase::None)407 Opts.disableAfter(StopAfter);408 409 if (Error CheckResult = Opts.checkConsistency())410 return CheckResult;411 412 return Opts;413}414 415static llvm::Expected<PollyPassOptions>416parsePollyDefaultOptions(StringRef Params) {417 return parsePollyOptions(Params, false);418}419 420static llvm::Expected<PollyPassOptions>421parsePollyCustomOptions(StringRef Params) {422 return parsePollyOptions(Params, true);423}424 425/// Register Polly passes such that they form a polyhedral optimizer.426///427/// The individual Polly passes are registered in the pass manager such that428/// they form a full polyhedral optimizer. The flow of the optimizer starts with429/// a set of preparing transformations that canonicalize the LLVM-IR such that430/// the LLVM-IR is easier for us to understand and to optimizes. On the431/// canonicalized LLVM-IR we first run the ScopDetection pass, which detects432/// static control flow regions. Those regions are then translated by the433/// ScopInfo pass into a polyhedral representation. As a next step, a scheduling434/// optimizer is run on the polyhedral representation and finally the optimized435/// polyhedral representation is code generated back to LLVM-IR.436///437/// Besides this core functionality, we optionally schedule passes that provide438/// a graphical view of the scops (Polly[Only]Viewer, Polly[Only]Printer), that439/// allow the export/import of the polyhedral representation440/// (JSCON[Exporter|Importer]) or that show the cfg after code generation.441///442/// For certain parts of the Polly optimizer, several alternatives are provided:443///444/// As scheduling optimizer we support the isl scheduling optimizer445/// (http://freecode.com/projects/isl).446/// It is also possible to run Polly with no optimizer. This mode is mainly447/// provided to analyze the run and compile time changes caused by the448/// scheduling optimizer.449///450/// Polly supports the isl internal code generator.451 452/// Add the pass sequence required for Polly to the New Pass Manager.453///454/// @param PM The pass manager itself.455/// @param Level The optimization level. Used for the cleanup of Polly's456/// output.457/// @param EnableForOpt Whether to add Polly IR transformations. If False, only458/// the analysis passes are added, skipping Polly itself.459/// The IR may still be modified.460static void buildCommonPollyPipeline(FunctionPassManager &PM,461 OptimizationLevel Level,462 bool EnableForOpt) {463 PassBuilder PB;464 465 ExitOnError Err("Inconsistent Polly configuration: ");466 PollyPassOptions &&Opts =467 Err(parsePollyOptions(StringRef(), /*IsCustom=*/false));468 PM.addPass(PollyFunctionPass(Opts));469 470 PM.addPass(PB.buildFunctionSimplificationPipeline(471 Level, llvm::ThinOrFullLTOPhase::None)); // Cleanup472 473 if (CFGPrinter)474 PM.addPass(llvm::CFGPrinterPass());475}476 477static void buildEarlyPollyPipeline(llvm::ModulePassManager &MPM,478 llvm::OptimizationLevel Level) {479 bool EnableForOpt =480 shouldEnablePollyForOptimization() && Level.isOptimizingForSpeed();481 if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)482 return;483 484 FunctionPassManager FPM = buildCanonicalicationPassesForNPM(MPM, Level);485 486 if (DumpBefore || !DumpBeforeFile.empty()) {487 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));488 489 if (DumpBefore)490 MPM.addPass(DumpModulePass("-before", true));491 for (auto &Filename : DumpBeforeFile)492 MPM.addPass(DumpModulePass(Filename, false));493 494 FPM = FunctionPassManager();495 }496 497 buildCommonPollyPipeline(FPM, Level, EnableForOpt);498 MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));499 500 if (DumpAfter)501 MPM.addPass(DumpModulePass("-after", true));502 for (auto &Filename : DumpAfterFile)503 MPM.addPass(DumpModulePass(Filename, false));504}505 506static void buildLatePollyPipeline(FunctionPassManager &PM,507 llvm::OptimizationLevel Level) {508 bool EnableForOpt =509 shouldEnablePollyForOptimization() && Level.isOptimizingForSpeed();510 if (!shouldEnablePollyForDiagnostic() && !EnableForOpt)511 return;512 513 if (DumpBefore)514 PM.addPass(DumpFunctionPass("-before"));515 if (!DumpBeforeFile.empty())516 llvm::report_fatal_error(517 "Option -polly-dump-before-file at -polly-position=late "518 "not supported with NPM",519 false);520 521 buildCommonPollyPipeline(PM, Level, EnableForOpt);522 523 if (DumpAfter)524 PM.addPass(DumpFunctionPass("-after"));525 if (!DumpAfterFile.empty())526 llvm::report_fatal_error(527 "Option -polly-dump-after-file at -polly-position=late "528 "not supported with NPM",529 false);530}531 532static llvm::Expected<std::monostate> parseNoOptions(StringRef Params) {533 if (!Params.empty())534 return make_error<StringError>(535 formatv("'{0}' passed to pass that does not take any options", Params)536 .str(),537 inconvertibleErrorCode());538 539 return std::monostate{};540}541 542static llvm::Expected<bool>543parseCGPipeline(StringRef Name, llvm::CGSCCPassManager &CGPM,544 PassInstrumentationCallbacks *PIC,545 ArrayRef<PassBuilder::PipelineElement> Pipeline) {546#define CGSCC_PASS(NAME, CREATE_PASS, PARSER) \547 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \548 auto Params = PassBuilder::parsePassParameters(PARSER, Name, NAME); \549 if (!Params) \550 return Params.takeError(); \551 CGPM.addPass(CREATE_PASS); \552 return true; \553 }554#include "PollyPasses.def"555 556 return false;557}558 559static llvm::Expected<bool>560parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,561 PassInstrumentationCallbacks *PIC,562 ArrayRef<PassBuilder::PipelineElement> Pipeline) {563 564#define FUNCTION_PASS(NAME, CREATE_PASS, PARSER) \565 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \566 auto ExpectedOpts = PassBuilder::parsePassParameters(PARSER, Name, NAME); \567 if (!ExpectedOpts) \568 return ExpectedOpts.takeError(); \569 auto &&Opts = *ExpectedOpts; \570 (void)Opts; \571 FPM.addPass(CREATE_PASS); \572 return true; \573 }574 575#include "PollyPasses.def"576 return false;577}578 579static llvm::Expected<bool>580parseModulePipeline(StringRef Name, llvm::ModulePassManager &MPM,581 PassInstrumentationCallbacks *PIC,582 ArrayRef<PassBuilder::PipelineElement> Pipeline) {583#define MODULE_PASS(NAME, CREATE_PASS, PARSER) \584 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \585 auto ExpectedOpts = PassBuilder::parsePassParameters(PARSER, Name, NAME); \586 if (!ExpectedOpts) \587 return ExpectedOpts.takeError(); \588 auto &&Opts = *ExpectedOpts; \589 (void)Opts; \590 MPM.addPass(CREATE_PASS); \591 return true; \592 }593 594#include "PollyPasses.def"595 596 return false;597}598 599/// Register Polly to be available as an optimizer600///601///602/// We can currently run Polly at two different points int the pass manager.603/// a) very early, b) right before the vectorizer.604///605/// The default is currently a), to register Polly such that it runs as early as606/// possible. This has several implications:607///608/// 1) We need to schedule more canonicalization passes609///610/// As nothing is run before Polly, it is necessary to run a set of preparing611/// transformations before Polly to canonicalize the LLVM-IR and to allow612/// Polly to detect and understand the code.613///614/// 2) We get the full -O3 optimization sequence after Polly615///616/// The LLVM-IR that is generated by Polly has been optimized on a high level,617/// but it may be rather inefficient on the lower/scalar level. By scheduling618/// Polly before all other passes, we have the full sequence of -O3619/// optimizations behind us, such that inefficiencies on the low level can620/// be optimized away.621///622/// We are currently evaluating the benefit or running Polly at b). b) is nice623/// as everything is fully inlined and canonicalized, but we need to be able to624/// handle LICMed code to make it useful.625void registerPollyPasses(PassBuilder &PB) {626 PassInstrumentationCallbacks *PIC = PB.getPassInstrumentationCallbacks();627 628#define MODULE_PASS(NAME, CREATE_PASS, PARSER) \629 { \630 std::remove_reference_t<decltype(*PARSER(StringRef()))> Opts; \631 (void)Opts; \632 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); \633 }634#define CGSCC_PASS(NAME, CREATE_PASS, PARSER) \635 { \636 std::remove_reference_t<decltype(*PARSER(StringRef()))> Opts; \637 (void)Opts; \638 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); \639 }640#define FUNCTION_PASS(NAME, CREATE_PASS, PARSER) \641 { \642 std::remove_reference_t<decltype(*PARSER(StringRef()))> Opts; \643 (void)Opts; \644 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); \645 }646#include "PollyPasses.def"647 648 PB.registerPipelineParsingCallback(649 [PIC](StringRef Name, FunctionPassManager &FPM,650 ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {651 ExitOnError Err("Unable to parse Polly module pass: ");652 return Err(parseFunctionPipeline(Name, FPM, PIC, Pipeline));653 });654 PB.registerPipelineParsingCallback(655 [PIC](StringRef Name, CGSCCPassManager &CGPM,656 ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {657 ExitOnError Err("Unable to parse Polly call graph pass: ");658 return Err(parseCGPipeline(Name, CGPM, PIC, Pipeline));659 });660 PB.registerPipelineParsingCallback(661 [PIC](StringRef Name, ModulePassManager &MPM,662 ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {663 ExitOnError Err("Unable to parse Polly module pass: ");664 return Err(parseModulePipeline(Name, MPM, PIC, Pipeline));665 });666 667 switch (PassPosition) {668 case POSITION_EARLY:669 PB.registerPipelineStartEPCallback(buildEarlyPollyPipeline);670 break;671 case POSITION_BEFORE_VECTORIZER:672 PB.registerVectorizerStartEPCallback(buildLatePollyPipeline);673 break;674 }675}676} // namespace polly677 678llvm::PassPluginLibraryInfo getPollyPluginInfo() {679 return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING,680 polly::registerPollyPasses};681}682