- //===- polly/ScheduleTreeTransform.h ----------------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Make changes to isl's schedule tree data structure. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef POLLY_SCHEDULETREETRANSFORM_H 
- #define POLLY_SCHEDULETREETRANSFORM_H 
-   
- #include "polly/Support/ISLTools.h" 
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/Support/ErrorHandling.h" 
- #include "isl/isl-noexceptions.h" 
- #include <cassert> 
-   
- namespace polly { 
- struct BandAttr; 
-   
- /// This class defines a simple visitor class that may be used for 
- /// various schedule tree analysis purposes. 
- template <typename Derived, typename RetTy = void, typename... Args> 
- struct ScheduleTreeVisitor { 
-   Derived &getDerived() { return *static_cast<Derived *>(this); } 
-   const Derived &getDerived() const { 
-     return *static_cast<const Derived *>(this); 
-   } 
-   
-   RetTy visit(isl::schedule_node Node, Args... args) { 
-     assert(!Node.is_null()); 
-     switch (isl_schedule_node_get_type(Node.get())) { 
-     case isl_schedule_node_domain: 
-       assert(isl_schedule_node_n_children(Node.get()) == 1); 
-       return getDerived().visitDomain(Node.as<isl::schedule_node_domain>(), 
-                                       std::forward<Args>(args)...); 
-     case isl_schedule_node_band: 
-       assert(isl_schedule_node_n_children(Node.get()) == 1); 
-       return getDerived().visitBand(Node.as<isl::schedule_node_band>(), 
-                                     std::forward<Args>(args)...); 
-     case isl_schedule_node_sequence: 
-       assert(isl_schedule_node_n_children(Node.get()) >= 2); 
-       return getDerived().visitSequence(Node.as<isl::schedule_node_sequence>(), 
-                                         std::forward<Args>(args)...); 
-     case isl_schedule_node_set: 
-       return getDerived().visitSet(Node.as<isl::schedule_node_set>(), 
-                                    std::forward<Args>(args)...); 
-       assert(isl_schedule_node_n_children(Node.get()) >= 2); 
-     case isl_schedule_node_leaf: 
-       assert(isl_schedule_node_n_children(Node.get()) == 0); 
-       return getDerived().visitLeaf(Node.as<isl::schedule_node_leaf>(), 
-                                     std::forward<Args>(args)...); 
-     case isl_schedule_node_mark: 
-       assert(isl_schedule_node_n_children(Node.get()) == 1); 
-       return getDerived().visitMark(Node.as<isl::schedule_node_mark>(), 
-                                     std::forward<Args>(args)...); 
-     case isl_schedule_node_extension: 
-       assert(isl_schedule_node_n_children(Node.get()) == 1); 
-       return getDerived().visitExtension( 
-           Node.as<isl::schedule_node_extension>(), std::forward<Args>(args)...); 
-     case isl_schedule_node_filter: 
-       assert(isl_schedule_node_n_children(Node.get()) == 1); 
-       return getDerived().visitFilter(Node.as<isl::schedule_node_filter>(), 
-                                       std::forward<Args>(args)...); 
-     default: 
-       llvm_unreachable("unimplemented schedule node type"); 
-     } 
-   } 
-   
-   RetTy visitDomain(isl::schedule_node_domain Domain, Args... args) { 
-     return getDerived().visitSingleChild(std::move(Domain), 
-                                          std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitBand(isl::schedule_node_band Band, Args... args) { 
-     return getDerived().visitSingleChild(std::move(Band), 
-                                          std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitSequence(isl::schedule_node_sequence Sequence, Args... args) { 
-     return getDerived().visitMultiChild(std::move(Sequence), 
-                                         std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitSet(isl::schedule_node_set Set, Args... args) { 
-     return getDerived().visitMultiChild(std::move(Set), 
-                                         std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitLeaf(isl::schedule_node_leaf Leaf, Args... args) { 
-     return getDerived().visitNode(std::move(Leaf), std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitMark(isl::schedule_node_mark Mark, Args... args) { 
-     return getDerived().visitSingleChild(std::move(Mark), 
-                                          std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitExtension(isl::schedule_node_extension Extension, Args... args) { 
-     return getDerived().visitSingleChild(std::move(Extension), 
-                                          std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitFilter(isl::schedule_node_filter Filter, Args... args) { 
-     return getDerived().visitSingleChild(std::move(Filter), 
-                                          std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitSingleChild(isl::schedule_node Node, Args... args) { 
-     return getDerived().visitNode(std::move(Node), std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitMultiChild(isl::schedule_node Node, Args... args) { 
-     return getDerived().visitNode(std::move(Node), std::forward<Args>(args)...); 
-   } 
-   
-   RetTy visitNode(isl::schedule_node Node, Args... args) { 
-     llvm_unreachable("Unimplemented other"); 
-   } 
- }; 
-   
- /// Recursively visit all nodes of a schedule tree. 
- template <typename Derived, typename RetTy = void, typename... Args> 
- struct RecursiveScheduleTreeVisitor 
-     : ScheduleTreeVisitor<Derived, RetTy, Args...> { 
-   using BaseTy = ScheduleTreeVisitor<Derived, RetTy, Args...>; 
-   BaseTy &getBase() { return *this; } 
-   const BaseTy &getBase() const { return *this; } 
-   Derived &getDerived() { return *static_cast<Derived *>(this); } 
-   const Derived &getDerived() const { 
-     return *static_cast<const Derived *>(this); 
-   } 
-   
-   /// When visiting an entire schedule tree, start at its root node. 
-   RetTy visit(isl::schedule Schedule, Args... args) { 
-     return getDerived().visit(Schedule.get_root(), std::forward<Args>(args)...); 
-   } 
-   
-   // Necessary to allow overload resolution with the added visit(isl::schedule) 
-   // overload. 
-   RetTy visit(isl::schedule_node Node, Args... args) { 
-     return getBase().visit(Node, std::forward<Args>(args)...); 
-   } 
-   
-   /// By default, recursively visit the child nodes. 
-   RetTy visitNode(isl::schedule_node Node, Args... args) { 
-     for (unsigned i : rangeIslSize(0, Node.n_children())) 
-       getDerived().visit(Node.child(i), std::forward<Args>(args)...); 
-     return RetTy(); 
-   } 
- }; 
-   
- /// Recursively visit all nodes of a schedule tree while allowing changes. 
- /// 
- /// The visit methods return an isl::schedule_node that is used to continue 
- /// visiting the tree. Structural changes such as returning a different node 
- /// will confuse the visitor. 
- template <typename Derived, typename... Args> 
- struct ScheduleNodeRewriter 
-     : public RecursiveScheduleTreeVisitor<Derived, isl::schedule_node, 
-                                           Args...> { 
-   Derived &getDerived() { return *static_cast<Derived *>(this); } 
-   const Derived &getDerived() const { 
-     return *static_cast<const Derived *>(this); 
-   } 
-   
-   isl::schedule_node visitNode(isl::schedule_node Node, Args... args) { 
-     return getDerived().visitChildren(Node); 
-   } 
-   
-   isl::schedule_node visitChildren(isl::schedule_node Node, Args... args) { 
-     if (!Node.has_children()) 
-       return Node; 
-   
-     isl::schedule_node It = Node.first_child(); 
-     while (true) { 
-       It = getDerived().visit(It, std::forward<Args>(args)...); 
-       if (!It.has_next_sibling()) 
-         break; 
-       It = It.next_sibling(); 
-     } 
-     return It.parent(); 
-   } 
- }; 
-   
- /// Is this node the marker for its parent band? 
- bool isBandMark(const isl::schedule_node &Node); 
-   
- /// Extract the BandAttr from a band's wrapping marker. Can also pass the band 
- /// itself and this methods will try to find its wrapping mark. Returns nullptr 
- /// if the band has not BandAttr. 
- BandAttr *getBandAttr(isl::schedule_node MarkOrBand); 
-   
- /// Hoist all domains from extension into the root domain node, such that there 
- /// are no more extension nodes (which isl does not support for some 
- /// operations). This assumes that domains added by to extension nodes do not 
- /// overlap. 
- isl::schedule hoistExtensionNodes(isl::schedule Sched); 
-   
- /// Replace the AST band @p BandToUnroll by a sequence of all its iterations. 
- /// 
- /// The implementation enumerates all points in the partial schedule and creates 
- /// an ISL sequence node for each point. The number of iterations must be a 
- /// constant. 
- isl::schedule applyFullUnroll(isl::schedule_node BandToUnroll); 
-   
- /// Replace the AST band @p BandToUnroll by a partially unrolled equivalent. 
- isl::schedule applyPartialUnroll(isl::schedule_node BandToUnroll, int Factor); 
-   
- /// Loop-distribute the band @p BandToFission as much as possible. 
- isl::schedule applyMaxFission(isl::schedule_node BandToFission); 
-   
- /// Build the desired set of partial tile prefixes. 
- /// 
- /// We build a set of partial tile prefixes, which are prefixes of the vector 
- /// loop that have exactly VectorWidth iterations. 
- /// 
- /// 1. Drop all constraints involving the dimension that represents the 
- ///    vector loop. 
- /// 2. Constrain the last dimension to get a set, which has exactly VectorWidth 
- ///    iterations. 
- /// 3. Subtract loop domain from it, project out the vector loop dimension and 
- ///    get a set that contains prefixes, which do not have exactly VectorWidth 
- ///    iterations. 
- /// 4. Project out the vector loop dimension of the set that was build on the 
- ///    first step and subtract the set built on the previous step to get the 
- ///    desired set of prefixes. 
- /// 
- /// @param ScheduleRange A range of a map, which describes a prefix schedule 
- ///                      relation. 
- isl::set getPartialTilePrefixes(isl::set ScheduleRange, int VectorWidth); 
-   
- /// Create an isl::union_set, which describes the isolate option based on 
- /// IsolateDomain. 
- /// 
- /// @param IsolateDomain An isl::set whose @p OutDimsNum last dimensions should 
- ///                      belong to the current band node. 
- /// @param OutDimsNum    A number of dimensions that should belong to 
- ///                      the current band node. 
- isl::union_set getIsolateOptions(isl::set IsolateDomain, unsigned OutDimsNum); 
-   
- /// Create an isl::union_set, which describes the specified option for the 
- /// dimension of the current node. 
- /// 
- /// @param Ctx    An isl::ctx, which is used to create the isl::union_set. 
- /// @param Option The name of the option. 
- isl::union_set getDimOptions(isl::ctx Ctx, const char *Option); 
-   
- /// Tile a schedule node. 
- /// 
- /// @param Node            The node to tile. 
- /// @param Identifier      An name that identifies this kind of tiling and 
- ///                        that is used to mark the tiled loops in the 
- ///                        generated AST. 
- /// @param TileSizes       A vector of tile sizes that should be used for 
- ///                        tiling. 
- /// @param DefaultTileSize A default tile size that is used for dimensions 
- ///                        that are not covered by the TileSizes vector. 
- isl::schedule_node tileNode(isl::schedule_node Node, const char *Identifier, 
-                             llvm::ArrayRef<int> TileSizes, int DefaultTileSize); 
-   
- /// Tile a schedule node and unroll point loops. 
- /// 
- /// @param Node            The node to register tile. 
- /// @param TileSizes       A vector of tile sizes that should be used for 
- ///                        tiling. 
- /// @param DefaultTileSize A default tile size that is used for dimensions 
- isl::schedule_node applyRegisterTiling(isl::schedule_node Node, 
-                                        llvm::ArrayRef<int> TileSizes, 
-                                        int DefaultTileSize); 
-   
- /// Apply greedy fusion. That is, fuse any loop that is possible to be fused 
- /// top-down. 
- /// 
- /// @param Sched  Sched tree to fuse all the loops in. 
- /// @param Deps   Validity constraints that must be preserved. 
- isl::schedule applyGreedyFusion(isl::schedule Sched, 
-                                 const isl::union_map &Deps); 
-   
- } // namespace polly 
-   
- #endif // POLLY_SCHEDULETREETRANSFORM_H 
-