ScheduleTreeTransform.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //===- polly/ScheduleTreeTransform.h ----------------------------*- 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. // Make changes to isl's schedule tree data structure.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef POLLY_SCHEDULETREETRANSFORM_H
  13. #define POLLY_SCHEDULETREETRANSFORM_H
  14. #include "llvm/Support/ErrorHandling.h"
  15. #include "isl/isl-noexceptions.h"
  16. #include <cassert>
  17. namespace polly {
  18. struct BandAttr;
  19. /// This class defines a simple visitor class that may be used for
  20. /// various schedule tree analysis purposes.
  21. template <typename Derived, typename RetTy = void, typename... Args>
  22. struct ScheduleTreeVisitor {
  23. Derived &getDerived() { return *static_cast<Derived *>(this); }
  24. const Derived &getDerived() const {
  25. return *static_cast<const Derived *>(this);
  26. }
  27. RetTy visit(const isl::schedule_node &Node, Args... args) {
  28. assert(!Node.is_null());
  29. switch (isl_schedule_node_get_type(Node.get())) {
  30. case isl_schedule_node_domain:
  31. assert(isl_schedule_node_n_children(Node.get()) == 1);
  32. return getDerived().visitDomain(Node, std::forward<Args>(args)...);
  33. case isl_schedule_node_band:
  34. assert(isl_schedule_node_n_children(Node.get()) == 1);
  35. return getDerived().visitBand(Node, std::forward<Args>(args)...);
  36. case isl_schedule_node_sequence:
  37. assert(isl_schedule_node_n_children(Node.get()) >= 2);
  38. return getDerived().visitSequence(Node, std::forward<Args>(args)...);
  39. case isl_schedule_node_set:
  40. return getDerived().visitSet(Node, std::forward<Args>(args)...);
  41. assert(isl_schedule_node_n_children(Node.get()) >= 2);
  42. case isl_schedule_node_leaf:
  43. assert(isl_schedule_node_n_children(Node.get()) == 0);
  44. return getDerived().visitLeaf(Node, std::forward<Args>(args)...);
  45. case isl_schedule_node_mark:
  46. assert(isl_schedule_node_n_children(Node.get()) == 1);
  47. return getDerived().visitMark(Node, std::forward<Args>(args)...);
  48. case isl_schedule_node_extension:
  49. assert(isl_schedule_node_n_children(Node.get()) == 1);
  50. return getDerived().visitExtension(Node, std::forward<Args>(args)...);
  51. case isl_schedule_node_filter:
  52. assert(isl_schedule_node_n_children(Node.get()) == 1);
  53. return getDerived().visitFilter(Node, std::forward<Args>(args)...);
  54. default:
  55. llvm_unreachable("unimplemented schedule node type");
  56. }
  57. }
  58. RetTy visitDomain(const isl::schedule_node &Domain, Args... args) {
  59. return getDerived().visitSingleChild(Domain, std::forward<Args>(args)...);
  60. }
  61. RetTy visitBand(const isl::schedule_node &Band, Args... args) {
  62. return getDerived().visitSingleChild(Band, std::forward<Args>(args)...);
  63. }
  64. RetTy visitSequence(const isl::schedule_node &Sequence, Args... args) {
  65. return getDerived().visitMultiChild(Sequence, std::forward<Args>(args)...);
  66. }
  67. RetTy visitSet(const isl::schedule_node &Set, Args... args) {
  68. return getDerived().visitMultiChild(Set, std::forward<Args>(args)...);
  69. }
  70. RetTy visitLeaf(const isl::schedule_node &Leaf, Args... args) {
  71. return getDerived().visitNode(Leaf, std::forward<Args>(args)...);
  72. }
  73. RetTy visitMark(const isl::schedule_node &Mark, Args... args) {
  74. return getDerived().visitSingleChild(Mark, std::forward<Args>(args)...);
  75. }
  76. RetTy visitExtension(const isl::schedule_node &Extension, Args... args) {
  77. return getDerived().visitSingleChild(Extension,
  78. std::forward<Args>(args)...);
  79. }
  80. RetTy visitFilter(const isl::schedule_node &Extension, Args... args) {
  81. return getDerived().visitSingleChild(Extension,
  82. std::forward<Args>(args)...);
  83. }
  84. RetTy visitSingleChild(const isl::schedule_node &Node, Args... args) {
  85. return getDerived().visitNode(Node, std::forward<Args>(args)...);
  86. }
  87. RetTy visitMultiChild(const isl::schedule_node &Node, Args... args) {
  88. return getDerived().visitNode(Node, std::forward<Args>(args)...);
  89. }
  90. RetTy visitNode(const isl::schedule_node &Node, Args... args) {
  91. llvm_unreachable("Unimplemented other");
  92. }
  93. };
  94. /// Recursively visit all nodes of a schedule tree.
  95. template <typename Derived, typename RetTy = void, typename... Args>
  96. struct RecursiveScheduleTreeVisitor
  97. : public ScheduleTreeVisitor<Derived, RetTy, Args...> {
  98. using BaseTy = ScheduleTreeVisitor<Derived, RetTy, Args...>;
  99. BaseTy &getBase() { return *this; }
  100. const BaseTy &getBase() const { return *this; }
  101. Derived &getDerived() { return *static_cast<Derived *>(this); }
  102. const Derived &getDerived() const {
  103. return *static_cast<const Derived *>(this);
  104. }
  105. /// When visiting an entire schedule tree, start at its root node.
  106. RetTy visit(const isl::schedule &Schedule, Args... args) {
  107. return getDerived().visit(Schedule.get_root(), std::forward<Args>(args)...);
  108. }
  109. // Necessary to allow overload resolution with the added visit(isl::schedule)
  110. // overload.
  111. RetTy visit(const isl::schedule_node &Node, Args... args) {
  112. return getBase().visit(Node, std::forward<Args>(args)...);
  113. }
  114. /// By default, recursively visit the child nodes.
  115. RetTy visitNode(const isl::schedule_node &Node, Args... args) {
  116. isl_size NumChildren = Node.n_children();
  117. for (isl_size i = 0; i < NumChildren; i += 1)
  118. getDerived().visit(Node.child(i), std::forward<Args>(args)...);
  119. return RetTy();
  120. }
  121. };
  122. /// Is this node the marker for its parent band?
  123. bool isBandMark(const isl::schedule_node &Node);
  124. /// Extract the BandAttr from a band's wrapping marker. Can also pass the band
  125. /// itself and this methods will try to find its wrapping mark. Returns nullptr
  126. /// if the band has not BandAttr.
  127. BandAttr *getBandAttr(isl::schedule_node MarkOrBand);
  128. /// Hoist all domains from extension into the root domain node, such that there
  129. /// are no more extension nodes (which isl does not support for some
  130. /// operations). This assumes that domains added by to extension nodes do not
  131. /// overlap.
  132. isl::schedule hoistExtensionNodes(isl::schedule Sched);
  133. /// Replace the AST band @p BandToUnroll by a sequence of all its iterations.
  134. ///
  135. /// The implementation enumerates all points in the partial schedule and creates
  136. /// an ISL sequence node for each point. The number of iterations must be a
  137. /// constant.
  138. isl::schedule applyFullUnroll(isl::schedule_node BandToUnroll);
  139. /// Replace the AST band @p BandToUnroll by a partially unrolled equivalent.
  140. isl::schedule applyPartialUnroll(isl::schedule_node BandToUnroll, int Factor);
  141. } // namespace polly
  142. #endif // POLLY_SCHEDULETREETRANSFORM_H