PolyhedralInfo.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //===--------- PolyhedralInfo.cpp - Create Scops from LLVM IR-------------===//
  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. // An interface to the Polyhedral analysis engine(Polly) of LLVM.
  10. //
  11. // This pass provides an interface to the polyhedral analysis performed by
  12. // Polly.
  13. //
  14. // This interface provides basic interface like isParallel, isVectorizable
  15. // that can be used in LLVM transformation passes.
  16. //
  17. // Work in progress, this file is subject to change.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #include "polly/PolyhedralInfo.h"
  21. #include "polly/DependenceInfo.h"
  22. #include "polly/LinkAllPasses.h"
  23. #include "polly/Options.h"
  24. #include "polly/ScopInfo.h"
  25. #include "polly/Support/GICHelper.h"
  26. #include "llvm/Analysis/LoopInfo.h"
  27. #include "llvm/InitializePasses.h"
  28. #include "llvm/Support/Debug.h"
  29. #include "isl/union_map.h"
  30. using namespace llvm;
  31. using namespace polly;
  32. #define DEBUG_TYPE "polyhedral-info"
  33. static cl::opt<bool> CheckParallel("polly-check-parallel",
  34. cl::desc("Check for parallel loops"),
  35. cl::Hidden, cl::cat(PollyCategory));
  36. static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
  37. cl::desc("Check for vectorizable loops"),
  38. cl::Hidden, cl::cat(PollyCategory));
  39. void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  40. AU.addRequiredTransitive<DependenceInfoWrapperPass>();
  41. AU.addRequired<LoopInfoWrapperPass>();
  42. AU.addRequiredTransitive<ScopInfoWrapperPass>();
  43. AU.setPreservesAll();
  44. }
  45. bool PolyhedralInfo::runOnFunction(Function &F) {
  46. DI = &getAnalysis<DependenceInfoWrapperPass>();
  47. SI = getAnalysis<ScopInfoWrapperPass>().getSI();
  48. return false;
  49. }
  50. void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
  51. auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
  52. for (auto *TopLevelLoop : LI) {
  53. for (auto *L : depth_first(TopLevelLoop)) {
  54. OS.indent(2) << L->getHeader()->getName() << ":\t";
  55. if (CheckParallel && isParallel(L))
  56. OS << "Loop is parallel.\n";
  57. else if (CheckParallel)
  58. OS << "Loop is not parallel.\n";
  59. }
  60. }
  61. }
  62. bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
  63. bool IsParallel;
  64. const Scop *S = getScopContainingLoop(L);
  65. if (!S)
  66. return false;
  67. const Dependences &D =
  68. DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
  69. if (!D.hasValidDependences())
  70. return false;
  71. LLVM_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
  72. isl_union_map *Deps =
  73. D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
  74. Dependences::TYPE_WAR | Dependences::TYPE_RED)
  75. .release();
  76. LLVM_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null")
  77. << "\n");
  78. isl_union_map *Schedule = getScheduleForLoop(S, L);
  79. LLVM_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null")
  80. << "\n");
  81. IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
  82. isl_union_map_free(Schedule);
  83. return IsParallel;
  84. }
  85. bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
  86. const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
  87. assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
  88. for (auto &It : *SI) {
  89. Region *R = It.first;
  90. if (R->contains(L))
  91. return It.second.get();
  92. }
  93. return nullptr;
  94. }
  95. // Given a Loop and the containing SCoP, we compute the partial schedule
  96. // by taking union of individual schedules of each ScopStmt within the loop
  97. // and projecting out the inner dimensions from the range of the schedule.
  98. // for (i = 0; i < n; i++)
  99. // for (j = 0; j < n; j++)
  100. // A[j] = 1; //Stmt
  101. //
  102. // The original schedule will be
  103. // Stmt[i0, i1] -> [i0, i1]
  104. // The schedule for the outer loop will be
  105. // Stmt[i0, i1] -> [i0]
  106. // The schedule for the inner loop will be
  107. // Stmt[i0, i1] -> [i0, i1]
  108. __isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
  109. Loop *L) const {
  110. isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
  111. int CurrDim = S->getRelativeLoopDepth(L);
  112. LLVM_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
  113. assert(CurrDim >= 0 && "Loop in region should have at least depth one");
  114. for (auto &SS : *S) {
  115. if (L->contains(SS.getSurroundingLoop())) {
  116. unsigned int MaxDim = SS.getNumIterators();
  117. LLVM_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
  118. isl_map *ScheduleMap = SS.getSchedule().release();
  119. assert(
  120. ScheduleMap &&
  121. "Schedules that contain extension nodes require special handling.");
  122. ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
  123. MaxDim - CurrDim - 1);
  124. ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
  125. SS.getDomainId().release());
  126. Schedule =
  127. isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
  128. }
  129. }
  130. Schedule = isl_union_map_coalesce(Schedule);
  131. return Schedule;
  132. }
  133. char PolyhedralInfo::ID = 0;
  134. Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
  135. INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
  136. "Polly - Interface to polyhedral analysis engine", false,
  137. false);
  138. INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
  139. INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
  140. INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
  141. INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
  142. "Polly - Interface to polyhedral analysis engine", false,
  143. false)
  144. //===----------------------------------------------------------------------===//
  145. namespace {
  146. /// Print result from PolyhedralInfo.
  147. class PolyhedralInfoPrinterLegacyPass final : public FunctionPass {
  148. public:
  149. static char ID;
  150. PolyhedralInfoPrinterLegacyPass() : PolyhedralInfoPrinterLegacyPass(outs()) {}
  151. explicit PolyhedralInfoPrinterLegacyPass(llvm::raw_ostream &OS)
  152. : FunctionPass(ID), OS(OS) {}
  153. bool runOnFunction(Function &F) override {
  154. PolyhedralInfo &P = getAnalysis<PolyhedralInfo>();
  155. OS << "Printing analysis '" << P.getPassName() << "' for function '"
  156. << F.getName() << "':\n";
  157. P.print(OS);
  158. return false;
  159. }
  160. void getAnalysisUsage(AnalysisUsage &AU) const override {
  161. FunctionPass::getAnalysisUsage(AU);
  162. AU.addRequired<PolyhedralInfo>();
  163. AU.setPreservesAll();
  164. }
  165. private:
  166. llvm::raw_ostream &OS;
  167. };
  168. char PolyhedralInfoPrinterLegacyPass::ID = 0;
  169. } // namespace
  170. Pass *polly::createPolyhedralInfoPrinterLegacyPass(raw_ostream &OS) {
  171. return new PolyhedralInfoPrinterLegacyPass(OS);
  172. }
  173. INITIALIZE_PASS_BEGIN(
  174. PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
  175. "Polly - Print interface to polyhedral analysis engine analysis", false,
  176. false);
  177. INITIALIZE_PASS_DEPENDENCY(PolyhedralInfo);
  178. INITIALIZE_PASS_END(
  179. PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
  180. "Polly - Print interface to polyhedral analysis engine analysis", false,
  181. false)