RegisterPasses.cpp 31 KB

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