PolyhedralInfo.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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::init(false), cl::ZeroOrMore,
  36. cl::cat(PollyCategory));
  37. static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
  38. cl::desc("Check for vectorizable loops"),
  39. cl::Hidden, cl::init(false),
  40. cl::ZeroOrMore, cl::cat(PollyCategory));
  41. void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  42. AU.addRequiredTransitive<DependenceInfoWrapperPass>();
  43. AU.addRequired<LoopInfoWrapperPass>();
  44. AU.addRequiredTransitive<ScopInfoWrapperPass>();
  45. AU.setPreservesAll();
  46. }
  47. bool PolyhedralInfo::runOnFunction(Function &F) {
  48. DI = &getAnalysis<DependenceInfoWrapperPass>();
  49. SI = getAnalysis<ScopInfoWrapperPass>().getSI();
  50. return false;
  51. }
  52. void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
  53. auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
  54. for (auto *TopLevelLoop : LI) {
  55. for (auto *L : depth_first(TopLevelLoop)) {
  56. OS.indent(2) << L->getHeader()->getName() << ":\t";
  57. if (CheckParallel && isParallel(L))
  58. OS << "Loop is parallel.\n";
  59. else if (CheckParallel)
  60. OS << "Loop is not parallel.\n";
  61. }
  62. }
  63. }
  64. bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
  65. bool IsParallel;
  66. const Scop *S = getScopContainingLoop(L);
  67. if (!S)
  68. return false;
  69. const Dependences &D =
  70. DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
  71. if (!D.hasValidDependences())
  72. return false;
  73. LLVM_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
  74. isl_union_map *Deps =
  75. D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
  76. Dependences::TYPE_WAR | Dependences::TYPE_RED)
  77. .release();
  78. LLVM_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null")
  79. << "\n");
  80. isl_union_map *Schedule = getScheduleForLoop(S, L);
  81. LLVM_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null")
  82. << "\n");
  83. IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
  84. isl_union_map_free(Schedule);
  85. return IsParallel;
  86. }
  87. bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
  88. const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
  89. assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
  90. for (auto &It : *SI) {
  91. Region *R = It.first;
  92. if (R->contains(L))
  93. return It.second.get();
  94. }
  95. return nullptr;
  96. }
  97. // Given a Loop and the containing SCoP, we compute the partial schedule
  98. // by taking union of individual schedules of each ScopStmt within the loop
  99. // and projecting out the inner dimensions from the range of the schedule.
  100. // for (i = 0; i < n; i++)
  101. // for (j = 0; j < n; j++)
  102. // A[j] = 1; //Stmt
  103. //
  104. // The original schedule will be
  105. // Stmt[i0, i1] -> [i0, i1]
  106. // The schedule for the outer loop will be
  107. // Stmt[i0, i1] -> [i0]
  108. // The schedule for the inner loop will be
  109. // Stmt[i0, i1] -> [i0, i1]
  110. __isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
  111. Loop *L) const {
  112. isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
  113. int CurrDim = S->getRelativeLoopDepth(L);
  114. LLVM_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
  115. assert(CurrDim >= 0 && "Loop in region should have at least depth one");
  116. for (auto &SS : *S) {
  117. if (L->contains(SS.getSurroundingLoop())) {
  118. unsigned int MaxDim = SS.getNumIterators();
  119. LLVM_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
  120. isl_map *ScheduleMap = SS.getSchedule().release();
  121. assert(
  122. ScheduleMap &&
  123. "Schedules that contain extension nodes require special handling.");
  124. ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
  125. MaxDim - CurrDim - 1);
  126. ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
  127. SS.getDomainId().release());
  128. Schedule =
  129. isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
  130. }
  131. }
  132. Schedule = isl_union_map_coalesce(Schedule);
  133. return Schedule;
  134. }
  135. char PolyhedralInfo::ID = 0;
  136. Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
  137. INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
  138. "Polly - Interface to polyhedral analysis engine", false,
  139. false);
  140. INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
  141. INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
  142. INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
  143. INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
  144. "Polly - Interface to polyhedral analysis engine", false,
  145. false)