ScopPass.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. //===--------- ScopPass.h - Pass for Static Control Parts --------*-C++ -*-===//
  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 defines the ScopPass class. ScopPasses are just RegionPasses,
  10. // except they operate on Polly IR (Scop and ScopStmt) built by ScopInfo Pass.
  11. // Because they operate on Polly IR, not the LLVM IR, ScopPasses are not allowed
  12. // to modify the LLVM IR. Due to this limitation, the ScopPass class takes
  13. // care of declaring that no LLVM passes are invalidated.
  14. //
  15. //===----------------------------------------------------------------------===//
  16. #ifndef POLLY_SCOP_PASS_H
  17. #define POLLY_SCOP_PASS_H
  18. #include "polly/ScopInfo.h"
  19. #include "llvm/ADT/PriorityWorklist.h"
  20. #include "llvm/Analysis/RegionPass.h"
  21. #include "llvm/Analysis/TargetTransformInfo.h"
  22. #include "llvm/IR/PassManager.h"
  23. #include "llvm/IR/PassManagerImpl.h"
  24. namespace polly {
  25. using llvm::AllAnalysesOn;
  26. using llvm::AnalysisManager;
  27. using llvm::DominatorTreeAnalysis;
  28. using llvm::InnerAnalysisManagerProxy;
  29. using llvm::LoopAnalysis;
  30. using llvm::OuterAnalysisManagerProxy;
  31. using llvm::PassManager;
  32. using llvm::RegionInfoAnalysis;
  33. using llvm::ScalarEvolutionAnalysis;
  34. using llvm::SmallPriorityWorklist;
  35. using llvm::TargetIRAnalysis;
  36. using llvm::TargetTransformInfo;
  37. class Scop;
  38. class SPMUpdater;
  39. struct ScopStandardAnalysisResults;
  40. using ScopAnalysisManager =
  41. AnalysisManager<Scop, ScopStandardAnalysisResults &>;
  42. using ScopAnalysisManagerFunctionProxy =
  43. InnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
  44. using FunctionAnalysisManagerScopProxy =
  45. OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop,
  46. ScopStandardAnalysisResults &>;
  47. } // namespace polly
  48. namespace llvm {
  49. using polly::Scop;
  50. using polly::ScopAnalysisManager;
  51. using polly::ScopAnalysisManagerFunctionProxy;
  52. using polly::ScopInfo;
  53. using polly::ScopStandardAnalysisResults;
  54. using polly::SPMUpdater;
  55. template <>
  56. class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result {
  57. public:
  58. explicit Result(ScopAnalysisManager &InnerAM, ScopInfo &SI)
  59. : InnerAM(&InnerAM), SI(&SI) {}
  60. Result(Result &&R) : InnerAM(std::move(R.InnerAM)), SI(R.SI) {
  61. R.InnerAM = nullptr;
  62. }
  63. Result &operator=(Result &&RHS) {
  64. InnerAM = RHS.InnerAM;
  65. SI = RHS.SI;
  66. RHS.InnerAM = nullptr;
  67. return *this;
  68. }
  69. ~Result() {
  70. if (!InnerAM)
  71. return;
  72. InnerAM->clear();
  73. }
  74. ScopAnalysisManager &getManager() { return *InnerAM; }
  75. bool invalidate(Function &F, const PreservedAnalyses &PA,
  76. FunctionAnalysisManager::Invalidator &Inv);
  77. private:
  78. ScopAnalysisManager *InnerAM;
  79. ScopInfo *SI;
  80. };
  81. // A partial specialization of the require analysis template pass to handle
  82. // extra parameters
  83. template <typename AnalysisT>
  84. struct RequireAnalysisPass<AnalysisT, Scop, ScopAnalysisManager,
  85. ScopStandardAnalysisResults &, SPMUpdater &>
  86. : PassInfoMixin<
  87. RequireAnalysisPass<AnalysisT, Scop, ScopAnalysisManager,
  88. ScopStandardAnalysisResults &, SPMUpdater &>> {
  89. PreservedAnalyses run(Scop &L, ScopAnalysisManager &AM,
  90. ScopStandardAnalysisResults &AR, SPMUpdater &) {
  91. (void)AM.template getResult<AnalysisT>(L, AR);
  92. return PreservedAnalyses::all();
  93. }
  94. };
  95. template <>
  96. InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result
  97. InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::run(
  98. Function &F, FunctionAnalysisManager &FAM);
  99. template <>
  100. PreservedAnalyses
  101. PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &,
  102. SPMUpdater &>::run(Scop &InitialS, ScopAnalysisManager &AM,
  103. ScopStandardAnalysisResults &, SPMUpdater &);
  104. extern template class PassManager<Scop, ScopAnalysisManager,
  105. ScopStandardAnalysisResults &, SPMUpdater &>;
  106. extern template class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
  107. extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop,
  108. ScopStandardAnalysisResults &>;
  109. } // namespace llvm
  110. namespace polly {
  111. template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
  112. class OwningInnerAnalysisManagerProxy
  113. : public InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT> {
  114. public:
  115. OwningInnerAnalysisManagerProxy()
  116. : InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>(InnerAM) {}
  117. using Result = typename InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT,
  118. ExtraArgTs...>::Result;
  119. Result run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
  120. ExtraArgTs...) {
  121. return Result(InnerAM);
  122. }
  123. AnalysisManagerT &getManager() { return InnerAM; }
  124. private:
  125. AnalysisManagerT InnerAM;
  126. };
  127. template <>
  128. OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result
  129. OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>::run(
  130. Function &F, FunctionAnalysisManager &FAM);
  131. extern template class OwningInnerAnalysisManagerProxy<ScopAnalysisManager,
  132. Function>;
  133. using OwningScopAnalysisManagerFunctionProxy =
  134. OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
  135. using ScopPassManager =
  136. PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &,
  137. SPMUpdater &>;
  138. /// ScopPass - This class adapts the RegionPass interface to allow convenient
  139. /// creation of passes that operate on the Polly IR. Instead of overriding
  140. /// runOnRegion, subclasses override runOnScop.
  141. class ScopPass : public RegionPass {
  142. Scop *S;
  143. protected:
  144. explicit ScopPass(char &ID) : RegionPass(ID), S(0) {}
  145. /// runOnScop - This method must be overloaded to perform the
  146. /// desired Polyhedral transformation or analysis.
  147. ///
  148. virtual bool runOnScop(Scop &S) = 0;
  149. /// Print method for SCoPs.
  150. virtual void printScop(raw_ostream &OS, Scop &S) const {}
  151. /// getAnalysisUsage - Subclasses that override getAnalysisUsage
  152. /// must call this.
  153. ///
  154. virtual void getAnalysisUsage(AnalysisUsage &AU) const override;
  155. private:
  156. bool runOnRegion(Region *R, RGPassManager &RGM) override;
  157. void print(raw_ostream &OS, const Module *) const override;
  158. };
  159. struct ScopStandardAnalysisResults {
  160. DominatorTree &DT;
  161. ScopInfo &SI;
  162. ScalarEvolution &SE;
  163. LoopInfo &LI;
  164. RegionInfo &RI;
  165. TargetTransformInfo &TTI;
  166. };
  167. class SPMUpdater {
  168. public:
  169. SPMUpdater(SmallPriorityWorklist<Region *, 4> &Worklist,
  170. ScopAnalysisManager &SAM)
  171. : InvalidateCurrentScop(false), Worklist(Worklist), SAM(SAM) {}
  172. bool invalidateCurrentScop() const { return InvalidateCurrentScop; }
  173. void invalidateScop(Scop &S) {
  174. if (&S == CurrentScop)
  175. InvalidateCurrentScop = true;
  176. Worklist.erase(&S.getRegion());
  177. SAM.clear(S, S.getName());
  178. }
  179. private:
  180. Scop *CurrentScop;
  181. bool InvalidateCurrentScop;
  182. SmallPriorityWorklist<Region *, 4> &Worklist;
  183. ScopAnalysisManager &SAM;
  184. template <typename ScopPassT> friend class FunctionToScopPassAdaptor;
  185. };
  186. template <typename ScopPassT>
  187. class FunctionToScopPassAdaptor
  188. : public PassInfoMixin<FunctionToScopPassAdaptor<ScopPassT>> {
  189. public:
  190. explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {}
  191. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
  192. ScopDetection &SD = AM.getResult<ScopAnalysis>(F);
  193. ScopInfo &SI = AM.getResult<ScopInfoAnalysis>(F);
  194. if (SI.empty()) {
  195. // With no scops having been detected, no IR changes have been made and
  196. // therefore all analyses are preserved. However, we must still free the
  197. // Scop analysis results which may hold AssertingVH that cause an error
  198. // if its value is destroyed.
  199. PreservedAnalyses PA = PreservedAnalyses::all();
  200. PA.abandon<ScopInfoAnalysis>();
  201. PA.abandon<ScopAnalysis>();
  202. AM.invalidate(F, PA);
  203. return PreservedAnalyses::all();
  204. }
  205. SmallPriorityWorklist<Region *, 4> Worklist;
  206. for (auto &S : SI)
  207. if (S.second)
  208. Worklist.insert(S.first);
  209. ScopStandardAnalysisResults AR = {AM.getResult<DominatorTreeAnalysis>(F),
  210. AM.getResult<ScopInfoAnalysis>(F),
  211. AM.getResult<ScalarEvolutionAnalysis>(F),
  212. AM.getResult<LoopAnalysis>(F),
  213. AM.getResult<RegionInfoAnalysis>(F),
  214. AM.getResult<TargetIRAnalysis>(F)};
  215. ScopAnalysisManager &SAM =
  216. AM.getResult<ScopAnalysisManagerFunctionProxy>(F).getManager();
  217. SPMUpdater Updater{Worklist, SAM};
  218. while (!Worklist.empty()) {
  219. Region *R = Worklist.pop_back_val();
  220. if (!SD.isMaxRegionInScop(*R, /*Verifying=*/false))
  221. continue;
  222. Scop *scop = SI.getScop(R);
  223. if (!scop)
  224. continue;
  225. Updater.CurrentScop = scop;
  226. Updater.InvalidateCurrentScop = false;
  227. PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR, Updater);
  228. SAM.invalidate(*scop, PassPA);
  229. if (Updater.invalidateCurrentScop())
  230. SI.recompute();
  231. };
  232. // FIXME: For the same reason as we add a BarrierNoopPass in the legacy pass
  233. // manager, do not preserve any analyses. While CodeGeneration may preserve
  234. // IR analyses sufficiently to process another Scop in the same function (it
  235. // has to, otherwise the ScopDetection result itself would need to be
  236. // invalidated), it is not sufficient for other purposes. For instance,
  237. // CodeGeneration does not inform LoopInfo about new loops in the
  238. // Polly-generated IR.
  239. return PreservedAnalyses::none();
  240. }
  241. private:
  242. ScopPassT Pass;
  243. };
  244. template <typename ScopPassT>
  245. FunctionToScopPassAdaptor<ScopPassT>
  246. createFunctionToScopPassAdaptor(ScopPassT Pass) {
  247. return FunctionToScopPassAdaptor<ScopPassT>(std::move(Pass));
  248. }
  249. } // namespace polly
  250. #endif