ScopInliner.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //===---- ScopInliner.cpp - Polyhedral based inliner ----------------------===//
  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. // Take a SCC and:
  10. // 1. If it has more than one component, bail out (contains cycles)
  11. // 2. If it has just one component, and if the function is entirely a scop,
  12. // inline it.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "polly/LinkAllPasses.h"
  16. #include "polly/ScopDetection.h"
  17. #include "llvm/Analysis/CallGraph.h"
  18. #include "llvm/Analysis/CallGraphSCCPass.h"
  19. #include "llvm/IR/PassManager.h"
  20. #include "llvm/Passes/PassBuilder.h"
  21. #include "llvm/Transforms/IPO/AlwaysInliner.h"
  22. #define DEBUG_TYPE "polly-scop-inliner"
  23. using namespace llvm;
  24. using namespace polly;
  25. namespace {
  26. class ScopInliner : public CallGraphSCCPass {
  27. using llvm::Pass::doInitialization;
  28. public:
  29. static char ID;
  30. ScopInliner() : CallGraphSCCPass(ID) {}
  31. bool doInitialization(CallGraph &CG) override {
  32. if (!polly::PollyAllowFullFunction) {
  33. report_fatal_error(
  34. "Aborting from ScopInliner because it only makes sense to run with "
  35. "-polly-allow-full-function. "
  36. "The heurtistic for ScopInliner checks that the full function is a "
  37. "Scop, which happens if and only if polly-allow-full-function is "
  38. " enabled. "
  39. " If not, the entry block is not included in the Scop");
  40. }
  41. return true;
  42. }
  43. bool runOnSCC(CallGraphSCC &SCC) override {
  44. // We do not try to inline non-trivial SCCs because this would lead to
  45. // "infinite" inlining if we are not careful.
  46. if (SCC.size() > 1)
  47. return false;
  48. assert(SCC.size() == 1 && "found empty SCC");
  49. Function *F = (*SCC.begin())->getFunction();
  50. // If the function is a nullptr, or the function is a declaration.
  51. if (!F)
  52. return false;
  53. if (F->isDeclaration()) {
  54. LLVM_DEBUG(dbgs() << "Skipping " << F->getName()
  55. << "because it is a declaration.\n");
  56. return false;
  57. }
  58. PassBuilder PB;
  59. // Populate analysis managers and register Polly-specific analyses.
  60. LoopAnalysisManager LAM;
  61. FunctionAnalysisManager FAM;
  62. CGSCCAnalysisManager CGAM;
  63. ModuleAnalysisManager MAM;
  64. FAM.registerPass([] { return ScopAnalysis(); });
  65. PB.registerModuleAnalyses(MAM);
  66. PB.registerCGSCCAnalyses(CGAM);
  67. PB.registerFunctionAnalyses(FAM);
  68. PB.registerLoopAnalyses(LAM);
  69. PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
  70. RegionInfo &RI = FAM.getResult<RegionInfoAnalysis>(*F);
  71. ScopDetection &SD = FAM.getResult<ScopAnalysis>(*F);
  72. const bool HasScopAsTopLevelRegion =
  73. SD.ValidRegions.contains(RI.getTopLevelRegion());
  74. bool Changed = false;
  75. if (HasScopAsTopLevelRegion) {
  76. LLVM_DEBUG(dbgs() << "Skipping " << F->getName()
  77. << " has scop as top level region");
  78. F->addFnAttr(llvm::Attribute::AlwaysInline);
  79. ModulePassManager MPM;
  80. MPM.addPass(AlwaysInlinerPass());
  81. Module *M = F->getParent();
  82. assert(M && "Function has illegal module");
  83. PreservedAnalyses PA = MPM.run(*M, MAM);
  84. if (!PA.areAllPreserved())
  85. Changed = true;
  86. } else {
  87. LLVM_DEBUG(dbgs() << F->getName()
  88. << " does NOT have scop as top level region\n");
  89. }
  90. return Changed;
  91. };
  92. void getAnalysisUsage(AnalysisUsage &AU) const override {
  93. CallGraphSCCPass::getAnalysisUsage(AU);
  94. }
  95. };
  96. } // namespace
  97. char ScopInliner::ID;
  98. Pass *polly::createScopInlinerPass() {
  99. ScopInliner *pass = new ScopInliner();
  100. return pass;
  101. }
  102. INITIALIZE_PASS_BEGIN(
  103. ScopInliner, "polly-scop-inliner",
  104. "inline functions based on how much of the function is a scop.", false,
  105. false)
  106. INITIALIZE_PASS_END(
  107. ScopInliner, "polly-scop-inliner",
  108. "inline functions based on how much of the function is a scop.", false,
  109. false)