1ced20c66SMichael Kruse //===- ScheduleOptimizer.cpp - Calculate an optimized schedule ------------===//
219523ed2SAndreas Simbuerger //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
619523ed2SAndreas Simbuerger //
719523ed2SAndreas Simbuerger //===----------------------------------------------------------------------===//
819523ed2SAndreas Simbuerger //
92219d157STobias Grosser // This pass generates an entirely new schedule tree from the data dependences
10234a4827STobias Grosser // and iteration domains. The new schedule tree is computed in two steps:
11234a4827STobias Grosser //
12234a4827STobias Grosser // 1) The isl scheduling optimizer is run
13234a4827STobias Grosser //
14234a4827STobias Grosser // The isl scheduling optimizer creates a new schedule tree that maximizes
15234a4827STobias Grosser // parallelism and tileability and minimizes data-dependence distances. The
16234a4827STobias Grosser // algorithm used is a modified version of the ``Pluto'' algorithm:
1719523ed2SAndreas Simbuerger //
1819523ed2SAndreas Simbuerger //   U. Bondhugula, A. Hartono, J. Ramanujam, and P. Sadayappan.
1919523ed2SAndreas Simbuerger //   A Practical Automatic Polyhedral Parallelizer and Locality Optimizer.
2019523ed2SAndreas Simbuerger //   In Proceedings of the 2008 ACM SIGPLAN Conference On Programming Language
2119523ed2SAndreas Simbuerger //   Design and Implementation, PLDI ’08, pages 101–113. ACM, 2008.
22234a4827STobias Grosser //
23234a4827STobias Grosser // 2) A set of post-scheduling transformations is applied on the schedule tree.
24234a4827STobias Grosser //
25234a4827STobias Grosser // These optimizations include:
26234a4827STobias Grosser //
27234a4827STobias Grosser //  - Tiling of the innermost tilable bands
283e4a7d38SSiddharth Bhat //  - Prevectorization - The choice of a possible outer loop that is strip-mined
29234a4827STobias Grosser //                       to the innermost level to enable inner-loop
30234a4827STobias Grosser //                       vectorization.
31234a4827STobias Grosser //  - Some optimizations for spatial locality are also planned.
32234a4827STobias Grosser //
33234a4827STobias Grosser // For a detailed description of the schedule tree itself please see section 6
34234a4827STobias Grosser // of:
35234a4827STobias Grosser //
36234a4827STobias Grosser // Polyhedral AST generation is more than scanning polyhedra
37234a4827STobias Grosser // Tobias Grosser, Sven Verdoolaege, Albert Cohen
383e4a7d38SSiddharth Bhat // ACM Transactions on Programming Languages and Systems (TOPLAS),
39234a4827STobias Grosser // 37(4), July 2015
40234a4827STobias Grosser // http://www.grosser.es/#pub-polyhedral-AST-generation
41234a4827STobias Grosser //
42234a4827STobias Grosser // This publication also contains a detailed discussion of the different options
43234a4827STobias Grosser // for polyhedral loop unrolling, full/partial tile separation and other uses
44234a4827STobias Grosser // of the schedule tree.
45234a4827STobias Grosser //
4619523ed2SAndreas Simbuerger //===----------------------------------------------------------------------===//
4719523ed2SAndreas Simbuerger 
4819523ed2SAndreas Simbuerger #include "polly/ScheduleOptimizer.h"
49ba0d0922STobias Grosser #include "polly/CodeGen/CodeGeneration.h"
50ba0d0922STobias Grosser #include "polly/DependenceInfo.h"
513f170eb1SMichael Kruse #include "polly/ManualOptimizer.h"
52d123e983SMichael Kruse #include "polly/MatmulOptimizer.h"
53ba0d0922STobias Grosser #include "polly/Options.h"
54aa8a9761SMichael Kruse #include "polly/ScheduleTreeTransform.h"
557205f93aSTobias Grosser #include "polly/Support/ISLOStream.h"
5644596fe6SRiccardo Mori #include "polly/Support/ISLTools.h"
57ab0556bbSMichael Kruse #include "llvm/ADT/Sequence.h"
589248fde5SEugene Zelenko #include "llvm/ADT/Statistic.h"
59e470f926SMichael Kruse #include "llvm/Analysis/OptimizationRemarkEmitter.h"
6005da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
619248fde5SEugene Zelenko #include "llvm/Support/CommandLine.h"
6219523ed2SAndreas Simbuerger #include "isl/options.h"
6319523ed2SAndreas Simbuerger 
6419523ed2SAndreas Simbuerger using namespace llvm;
6519523ed2SAndreas Simbuerger using namespace polly;
6619523ed2SAndreas Simbuerger 
67d123e983SMichael Kruse namespace llvm {
68d123e983SMichael Kruse class Loop;
69d123e983SMichael Kruse class Module;
70d123e983SMichael Kruse } // namespace llvm
71d123e983SMichael Kruse 
7295fef944SChandler Carruth #define DEBUG_TYPE "polly-opt-isl"
7395fef944SChandler Carruth 
7419523ed2SAndreas Simbuerger static cl::opt<std::string>
7519523ed2SAndreas Simbuerger     OptimizeDeps("polly-opt-optimize-only",
7619523ed2SAndreas Simbuerger                  cl::desc("Only a certain kind of dependences (all/raw)"),
7736c7d79dSFangrui Song                  cl::Hidden, cl::init("all"), cl::cat(PollyCategory));
7819523ed2SAndreas Simbuerger 
7919523ed2SAndreas Simbuerger static cl::opt<std::string>
8019523ed2SAndreas Simbuerger     SimplifyDeps("polly-opt-simplify-deps",
81483a90d1STobias Grosser                  cl::desc("Dependences should be simplified (yes/no)"),
8236c7d79dSFangrui Song                  cl::Hidden, cl::init("yes"), cl::cat(PollyCategory));
8319523ed2SAndreas Simbuerger 
84483a90d1STobias Grosser static cl::opt<int> MaxConstantTerm(
85483a90d1STobias Grosser     "polly-opt-max-constant-term",
86483a90d1STobias Grosser     cl::desc("The maximal constant term allowed (-1 is unlimited)"), cl::Hidden,
8736c7d79dSFangrui Song     cl::init(20), cl::cat(PollyCategory));
8819523ed2SAndreas Simbuerger 
89483a90d1STobias Grosser static cl::opt<int> MaxCoefficient(
90483a90d1STobias Grosser     "polly-opt-max-coefficient",
91483a90d1STobias Grosser     cl::desc("The maximal coefficient allowed (-1 is unlimited)"), cl::Hidden,
9236c7d79dSFangrui Song     cl::init(20), cl::cat(PollyCategory));
93483a90d1STobias Grosser 
9419523ed2SAndreas Simbuerger static cl::opt<std::string>
9519523ed2SAndreas Simbuerger     MaximizeBandDepth("polly-opt-maximize-bands",
9619523ed2SAndreas Simbuerger                       cl::desc("Maximize the band depth (yes/no)"), cl::Hidden,
9736c7d79dSFangrui Song                       cl::init("yes"), cl::cat(PollyCategory));
9819523ed2SAndreas Simbuerger 
9964489255SMichael Kruse static cl::opt<bool>
10064489255SMichael Kruse     GreedyFusion("polly-loopfusion-greedy",
10164489255SMichael Kruse                  cl::desc("Aggressively try to fuse everything"), cl::Hidden,
102d86a206fSFangrui Song                  cl::cat(PollyCategory));
10364489255SMichael Kruse 
104315aa327SMichael Kruse static cl::opt<std::string> OuterCoincidence(
105315aa327SMichael Kruse     "polly-opt-outer-coincidence",
106315aa327SMichael Kruse     cl::desc("Try to construct schedules where the outer member of each band "
107315aa327SMichael Kruse              "satisfies the coincidence constraints (yes/no)"),
10836c7d79dSFangrui Song     cl::Hidden, cl::init("no"), cl::cat(PollyCategory));
109315aa327SMichael Kruse 
11007c1c2fcSTobias Grosser static cl::opt<int> PrevectorWidth(
11107c1c2fcSTobias Grosser     "polly-prevect-width",
11207c1c2fcSTobias Grosser     cl::desc(
11307c1c2fcSTobias Grosser         "The number of loop iterations to strip-mine for pre-vectorization"),
11436c7d79dSFangrui Song     cl::Hidden, cl::init(4), cl::cat(PollyCategory));
11507c1c2fcSTobias Grosser 
11604832716STobias Grosser static cl::opt<bool> FirstLevelTiling("polly-tiling",
11704832716STobias Grosser                                       cl::desc("Enable loop tiling"),
11836c7d79dSFangrui Song                                       cl::init(true), cl::cat(PollyCategory));
11904832716STobias Grosser 
12004832716STobias Grosser static cl::opt<int> FirstLevelDefaultTileSize(
121483a90d1STobias Grosser     "polly-default-tile-size",
122c3958b21SJohannes Doerfert     cl::desc("The default tile size (if not enough were provided by"
123c3958b21SJohannes Doerfert              " --polly-tile-sizes)"),
12495a13425SFangrui Song     cl::Hidden, cl::init(32), cl::cat(PollyCategory));
125c3958b21SJohannes Doerfert 
12621a059afSTobias Grosser static cl::list<int>
12721a059afSTobias Grosser     FirstLevelTileSizes("polly-tile-sizes",
12821a059afSTobias Grosser                         cl::desc("A tile size for each loop dimension, filled "
12904832716STobias Grosser                                  "with --polly-default-tile-size"),
130d0d1c416SFangrui Song                         cl::Hidden, cl::CommaSeparated, cl::cat(PollyCategory));
13104832716STobias Grosser 
13204832716STobias Grosser static cl::opt<bool>
13304832716STobias Grosser     SecondLevelTiling("polly-2nd-level-tiling",
13404832716STobias Grosser                       cl::desc("Enable a 2nd level loop of loop tiling"),
13536c7d79dSFangrui Song                       cl::cat(PollyCategory));
13604832716STobias Grosser 
13704832716STobias Grosser static cl::opt<int> SecondLevelDefaultTileSize(
13804832716STobias Grosser     "polly-2nd-level-default-tile-size",
13904832716STobias Grosser     cl::desc("The default 2nd-level tile size (if not enough were provided by"
14004832716STobias Grosser              " --polly-2nd-level-tile-sizes)"),
14136c7d79dSFangrui Song     cl::Hidden, cl::init(16), cl::cat(PollyCategory));
14204832716STobias Grosser 
14304832716STobias Grosser static cl::list<int>
14404832716STobias Grosser     SecondLevelTileSizes("polly-2nd-level-tile-sizes",
14504832716STobias Grosser                          cl::desc("A tile size for each loop dimension, filled "
14604832716STobias Grosser                                   "with --polly-default-tile-size"),
147d0d1c416SFangrui Song                          cl::Hidden, cl::CommaSeparated,
148c3958b21SJohannes Doerfert                          cl::cat(PollyCategory));
14904832716STobias Grosser 
15042e24895STobias Grosser static cl::opt<bool> RegisterTiling("polly-register-tiling",
15142e24895STobias Grosser                                     cl::desc("Enable register tiling"),
15242e24895STobias Grosser                                     cl::cat(PollyCategory));
15342e24895STobias Grosser 
15442e24895STobias Grosser static cl::opt<int> RegisterDefaultTileSize(
15542e24895STobias Grosser     "polly-register-tiling-default-tile-size",
15642e24895STobias Grosser     cl::desc("The default register tile size (if not enough were provided by"
15742e24895STobias Grosser              " --polly-register-tile-sizes)"),
15895a13425SFangrui Song     cl::Hidden, cl::init(2), cl::cat(PollyCategory));
15942e24895STobias Grosser 
16042e24895STobias Grosser static cl::list<int>
16142e24895STobias Grosser     RegisterTileSizes("polly-register-tile-sizes",
16242e24895STobias Grosser                       cl::desc("A tile size for each loop dimension, filled "
16342e24895STobias Grosser                                "with --polly-register-tile-size"),
164d0d1c416SFangrui Song                       cl::Hidden, cl::CommaSeparated, cl::cat(PollyCategory));
16542e24895STobias Grosser 
1663f170eb1SMichael Kruse static cl::opt<bool> PragmaBasedOpts(
1673f170eb1SMichael Kruse     "polly-pragma-based-opts",
1683f170eb1SMichael Kruse     cl::desc("Apply user-directed transformation from metadata"),
16936c7d79dSFangrui Song     cl::init(true), cl::cat(PollyCategory));
1703f170eb1SMichael Kruse 
171ced20c66SMichael Kruse static cl::opt<bool> EnableReschedule("polly-reschedule",
172ced20c66SMichael Kruse                                       cl::desc("Optimize SCoPs using ISL"),
17336c7d79dSFangrui Song                                       cl::init(true), cl::cat(PollyCategory));
174ced20c66SMichael Kruse 
1759c3eb596SRoman Gareev static cl::opt<bool>
1769c3eb596SRoman Gareev     PMBasedOpts("polly-pattern-matching-based-opts",
1779c3eb596SRoman Gareev                 cl::desc("Perform optimizations based on pattern matching"),
17836c7d79dSFangrui Song                 cl::init(true), cl::cat(PollyCategory));
1799c3eb596SRoman Gareev 
180ced20c66SMichael Kruse static cl::opt<bool>
181ced20c66SMichael Kruse     EnablePostopts("polly-postopts",
182ced20c66SMichael Kruse                    cl::desc("Apply post-rescheduling optimizations such as "
183ced20c66SMichael Kruse                             "tiling (requires -polly-reschedule)"),
18436c7d79dSFangrui Song                    cl::init(true), cl::cat(PollyCategory));
185ced20c66SMichael Kruse 
1865f99f865SRoman Gareev static cl::opt<bool> OptimizedScops(
1875f99f865SRoman Gareev     "polly-optimized-scops",
1885f99f865SRoman Gareev     cl::desc("Polly - Dump polyhedral description of Scops optimized with "
1895f99f865SRoman Gareev              "the isl scheduling optimizer and the set of post-scheduling "
1905f99f865SRoman Gareev              "transformations is applied on the schedule tree"),
19195a13425SFangrui Song     cl::cat(PollyCategory));
1925f99f865SRoman Gareev 
19306ed5292SMichael Kruse STATISTIC(ScopsProcessed, "Number of scops processed");
19406ed5292SMichael Kruse STATISTIC(ScopsRescheduled, "Number of scops rescheduled");
19506ed5292SMichael Kruse STATISTIC(ScopsOptimized, "Number of scops optimized");
19606ed5292SMichael Kruse 
19706ed5292SMichael Kruse STATISTIC(NumAffineLoopsOptimized, "Number of affine loops optimized");
19806ed5292SMichael Kruse STATISTIC(NumBoxedLoopsOptimized, "Number of boxed loops optimized");
19906ed5292SMichael Kruse 
20006ed5292SMichael Kruse #define THREE_STATISTICS(VARNAME, DESC)                                        \
2019248fde5SEugene Zelenko   static Statistic VARNAME[3] = {                                              \
202126158f0SVolodymyr Sapsai       {DEBUG_TYPE, #VARNAME "0", DESC " (original)"},                          \
203126158f0SVolodymyr Sapsai       {DEBUG_TYPE, #VARNAME "1", DESC " (after scheduler)"},                   \
204126158f0SVolodymyr Sapsai       {DEBUG_TYPE, #VARNAME "2", DESC " (after optimizer)"}}
20506ed5292SMichael Kruse 
20606ed5292SMichael Kruse THREE_STATISTICS(NumBands, "Number of bands");
20706ed5292SMichael Kruse THREE_STATISTICS(NumBandMembers, "Number of band members");
20806ed5292SMichael Kruse THREE_STATISTICS(NumCoincident, "Number of coincident band members");
20906ed5292SMichael Kruse THREE_STATISTICS(NumPermutable, "Number of permutable bands");
21006ed5292SMichael Kruse THREE_STATISTICS(NumFilters, "Number of filter nodes");
21106ed5292SMichael Kruse THREE_STATISTICS(NumExtension, "Number of extension nodes");
21206ed5292SMichael Kruse 
21306ed5292SMichael Kruse STATISTIC(FirstLevelTileOpts, "Number of first level tiling applied");
21406ed5292SMichael Kruse STATISTIC(SecondLevelTileOpts, "Number of second level tiling applied");
21506ed5292SMichael Kruse STATISTIC(RegisterTileOpts, "Number of register tiling applied");
21606ed5292SMichael Kruse STATISTIC(PrevectOpts, "Number of strip-mining for prevectorization applied");
21706ed5292SMichael Kruse STATISTIC(MatMulOpts,
21806ed5292SMichael Kruse           "Number of matrix multiplication patterns detected and optimized");
21906ed5292SMichael Kruse 
2207387f33bSMichael Kruse namespace {
2217387f33bSMichael Kruse /// Additional parameters of the schedule optimizer.
2227387f33bSMichael Kruse ///
2237387f33bSMichael Kruse /// Target Transform Info and the SCoP dependencies used by the schedule
2247387f33bSMichael Kruse /// optimizer.
2257387f33bSMichael Kruse struct OptimizerAdditionalInfoTy {
2267387f33bSMichael Kruse   const llvm::TargetTransformInfo *TTI;
2277387f33bSMichael Kruse   const Dependences *D;
228ced20c66SMichael Kruse   bool PatternOpts;
229ced20c66SMichael Kruse   bool Postopts;
230ced20c66SMichael Kruse   bool Prevect;
231*6fa65f8aSMichael Kruse   bool &DepsChanged;
2327387f33bSMichael Kruse };
2337387f33bSMichael Kruse 
234bd93df93SMichael Kruse class ScheduleTreeOptimizer final {
2357387f33bSMichael Kruse public:
2367387f33bSMichael Kruse   /// Apply schedule tree transformations.
2377387f33bSMichael Kruse   ///
2387387f33bSMichael Kruse   /// This function takes an (possibly already optimized) schedule tree and
2397387f33bSMichael Kruse   /// applies a set of additional optimizations on the schedule tree. The
2407387f33bSMichael Kruse   /// transformations applied include:
2417387f33bSMichael Kruse   ///
242ced20c66SMichael Kruse   ///   - Pattern-based optimizations
2437387f33bSMichael Kruse   ///   - Tiling
2447387f33bSMichael Kruse   ///   - Prevectorization
2457387f33bSMichael Kruse   ///
2467387f33bSMichael Kruse   /// @param Schedule The schedule object the transformations will be applied
2477387f33bSMichael Kruse   ///                 to.
2487387f33bSMichael Kruse   /// @param OAI      Target Transform Info and the SCoP dependencies.
2497387f33bSMichael Kruse   /// @returns        The transformed schedule.
2507387f33bSMichael Kruse   static isl::schedule
2517387f33bSMichael Kruse   optimizeSchedule(isl::schedule Schedule,
2527387f33bSMichael Kruse                    const OptimizerAdditionalInfoTy *OAI = nullptr);
2537387f33bSMichael Kruse 
2547387f33bSMichael Kruse   /// Apply schedule tree transformations.
2557387f33bSMichael Kruse   ///
2567387f33bSMichael Kruse   /// This function takes a node in an (possibly already optimized) schedule
2577387f33bSMichael Kruse   /// tree and applies a set of additional optimizations on this schedule tree
2587387f33bSMichael Kruse   /// node and its descendants. The transformations applied include:
2597387f33bSMichael Kruse   ///
260ced20c66SMichael Kruse   ///   - Pattern-based optimizations
2617387f33bSMichael Kruse   ///   - Tiling
2627387f33bSMichael Kruse   ///   - Prevectorization
2637387f33bSMichael Kruse   ///
2647387f33bSMichael Kruse   /// @param Node The schedule object post-transformations will be applied to.
2657387f33bSMichael Kruse   /// @param OAI  Target Transform Info and the SCoP dependencies.
2667387f33bSMichael Kruse   /// @returns    The transformed schedule.
2677387f33bSMichael Kruse   static isl::schedule_node
2687387f33bSMichael Kruse   optimizeScheduleNode(isl::schedule_node Node,
2697387f33bSMichael Kruse                        const OptimizerAdditionalInfoTy *OAI = nullptr);
2707387f33bSMichael Kruse 
2717387f33bSMichael Kruse   /// Decide if the @p NewSchedule is profitable for @p S.
2727387f33bSMichael Kruse   ///
2737387f33bSMichael Kruse   /// @param S           The SCoP we optimize.
2747387f33bSMichael Kruse   /// @param NewSchedule The new schedule we computed.
2757387f33bSMichael Kruse   ///
2767387f33bSMichael Kruse   /// @return True, if we believe @p NewSchedule is an improvement for @p S.
2777387f33bSMichael Kruse   static bool isProfitableSchedule(polly::Scop &S, isl::schedule NewSchedule);
2787387f33bSMichael Kruse 
2797387f33bSMichael Kruse   /// Isolate a set of partial tile prefixes.
2807387f33bSMichael Kruse   ///
2817387f33bSMichael Kruse   /// This set should ensure that it contains only partial tile prefixes that
2827387f33bSMichael Kruse   /// have exactly VectorWidth iterations.
2837387f33bSMichael Kruse   ///
2847387f33bSMichael Kruse   /// @param Node A schedule node band, which is a parent of a band node,
2857387f33bSMichael Kruse   ///             that contains a vector loop.
2867387f33bSMichael Kruse   /// @return Modified isl_schedule_node.
2877387f33bSMichael Kruse   static isl::schedule_node isolateFullPartialTiles(isl::schedule_node Node,
2887387f33bSMichael Kruse                                                     int VectorWidth);
2897387f33bSMichael Kruse 
2907387f33bSMichael Kruse private:
2917387f33bSMichael Kruse   /// Check if this node is a band node we want to tile.
2927387f33bSMichael Kruse   ///
2937387f33bSMichael Kruse   /// We look for innermost band nodes where individual dimensions are marked as
2947387f33bSMichael Kruse   /// permutable.
2957387f33bSMichael Kruse   ///
2967387f33bSMichael Kruse   /// @param Node The node to check.
2977387f33bSMichael Kruse   static bool isTileableBandNode(isl::schedule_node Node);
2987387f33bSMichael Kruse 
2997387f33bSMichael Kruse   /// Pre-vectorizes one scheduling dimension of a schedule band.
3007387f33bSMichael Kruse   ///
3017387f33bSMichael Kruse   /// prevectSchedBand splits out the dimension DimToVectorize, tiles it and
3027387f33bSMichael Kruse   /// sinks the resulting point loop.
3037387f33bSMichael Kruse   ///
3047387f33bSMichael Kruse   /// Example (DimToVectorize=0, VectorWidth=4):
3057387f33bSMichael Kruse   ///
3067387f33bSMichael Kruse   /// | Before transformation:
3077387f33bSMichael Kruse   /// |
3087387f33bSMichael Kruse   /// | A[i,j] -> [i,j]
3097387f33bSMichael Kruse   /// |
3107387f33bSMichael Kruse   /// | for (i = 0; i < 128; i++)
3117387f33bSMichael Kruse   /// |    for (j = 0; j < 128; j++)
3127387f33bSMichael Kruse   /// |      A(i,j);
3137387f33bSMichael Kruse   ///
3147387f33bSMichael Kruse   /// | After transformation:
3157387f33bSMichael Kruse   /// |
3167387f33bSMichael Kruse   /// | for (it = 0; it < 32; it+=1)
3177387f33bSMichael Kruse   /// |    for (j = 0; j < 128; j++)
3187387f33bSMichael Kruse   /// |      for (ip = 0; ip <= 3; ip++)
3197387f33bSMichael Kruse   /// |        A(4 * it + ip,j);
3207387f33bSMichael Kruse   ///
3217387f33bSMichael Kruse   /// The goal of this transformation is to create a trivially vectorizable
3227387f33bSMichael Kruse   /// loop.  This means a parallel loop at the innermost level that has a
3237387f33bSMichael Kruse   /// constant number of iterations corresponding to the target vector width.
3247387f33bSMichael Kruse   ///
3257387f33bSMichael Kruse   /// This transformation creates a loop at the innermost level. The loop has
3267387f33bSMichael Kruse   /// a constant number of iterations, if the number of loop iterations at
3277387f33bSMichael Kruse   /// DimToVectorize can be divided by VectorWidth. The default VectorWidth is
3287387f33bSMichael Kruse   /// currently constant and not yet target specific. This function does not
3297387f33bSMichael Kruse   /// reason about parallelism.
3307387f33bSMichael Kruse   static isl::schedule_node prevectSchedBand(isl::schedule_node Node,
3317387f33bSMichael Kruse                                              unsigned DimToVectorize,
3327387f33bSMichael Kruse                                              int VectorWidth);
3337387f33bSMichael Kruse 
3347387f33bSMichael Kruse   /// Apply additional optimizations on the bands in the schedule tree.
3357387f33bSMichael Kruse   ///
3367387f33bSMichael Kruse   /// We are looking for an innermost band node and apply the following
3377387f33bSMichael Kruse   /// transformations:
3387387f33bSMichael Kruse   ///
3397387f33bSMichael Kruse   ///  - Tile the band
3407387f33bSMichael Kruse   ///      - if the band is tileable
3417387f33bSMichael Kruse   ///      - if the band has more than one loop dimension
3427387f33bSMichael Kruse   ///
3437387f33bSMichael Kruse   ///  - Prevectorize the schedule of the band (or the point loop in case of
3447387f33bSMichael Kruse   ///    tiling).
3457387f33bSMichael Kruse   ///      - if vectorization is enabled
3467387f33bSMichael Kruse   ///
3477387f33bSMichael Kruse   /// @param Node The schedule node to (possibly) optimize.
3487387f33bSMichael Kruse   /// @param User A pointer to forward some use information
3497387f33bSMichael Kruse   ///        (currently unused).
3507387f33bSMichael Kruse   static isl_schedule_node *optimizeBand(isl_schedule_node *Node, void *User);
3517387f33bSMichael Kruse 
352ced20c66SMichael Kruse   /// Apply tiling optimizations on the bands in the schedule tree.
3537387f33bSMichael Kruse   ///
3547387f33bSMichael Kruse   /// @param Node The schedule node to (possibly) optimize.
355ced20c66SMichael Kruse   static isl::schedule_node applyTileBandOpt(isl::schedule_node Node);
356ced20c66SMichael Kruse 
357ced20c66SMichael Kruse   /// Apply prevectorization on the bands in the schedule tree.
358ced20c66SMichael Kruse   ///
359ced20c66SMichael Kruse   /// @param Node The schedule node to (possibly) prevectorize.
360ced20c66SMichael Kruse   static isl::schedule_node applyPrevectBandOpt(isl::schedule_node Node);
3617387f33bSMichael Kruse };
3627387f33bSMichael Kruse 
3632fb3ed20STobias Grosser isl::schedule_node
isolateFullPartialTiles(isl::schedule_node Node,int VectorWidth)3642fb3ed20STobias Grosser ScheduleTreeOptimizer::isolateFullPartialTiles(isl::schedule_node Node,
3652fb3ed20STobias Grosser                                                int VectorWidth) {
3662fb3ed20STobias Grosser   assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band);
3672fb3ed20STobias Grosser   Node = Node.child(0).child(0);
3682fb3ed20STobias Grosser   isl::union_map SchedRelUMap = Node.get_prefix_schedule_relation();
369c0bc9954SMichael Kruse   isl::union_set ScheduleRangeUSet = SchedRelUMap.range();
370c0bc9954SMichael Kruse   isl::set ScheduleRange{ScheduleRangeUSet};
3712fb3ed20STobias Grosser   isl::set IsolateDomain = getPartialTilePrefixes(ScheduleRange, VectorWidth);
3720813bd16SRiccardo Mori   auto AtomicOption = getDimOptions(IsolateDomain.ctx(), "atomic");
3732fb3ed20STobias Grosser   isl::union_set IsolateOption = getIsolateOptions(IsolateDomain, 1);
3742fb3ed20STobias Grosser   Node = Node.parent().parent();
3752fb3ed20STobias Grosser   isl::union_set Options = IsolateOption.unite(AtomicOption);
376d3fdbda6SRiccardo Mori   isl::schedule_node_band Result =
377d3fdbda6SRiccardo Mori       Node.as<isl::schedule_node_band>().set_ast_build_options(Options);
378d3fdbda6SRiccardo Mori   return Result;
379ca7f5bb7STobias Grosser }
380ca7f5bb7STobias Grosser 
381bd93df93SMichael Kruse struct InsertSimdMarkers final : ScheduleNodeRewriter<InsertSimdMarkers> {
visitBand__anonc229ce900111::InsertSimdMarkers382937b00abSMichael Kruse   isl::schedule_node visitBand(isl::schedule_node_band Band) {
383937b00abSMichael Kruse     isl::schedule_node Node = visitChildren(Band);
384937b00abSMichael Kruse 
385937b00abSMichael Kruse     // Only add SIMD markers to innermost bands.
386937b00abSMichael Kruse     if (!Node.first_child().isa<isl::schedule_node_leaf>())
387937b00abSMichael Kruse       return Node;
388937b00abSMichael Kruse 
389937b00abSMichael Kruse     isl::id LoopMarker = isl::id::alloc(Band.ctx(), "SIMD", nullptr);
390937b00abSMichael Kruse     return Band.insert_mark(LoopMarker);
391937b00abSMichael Kruse   }
392937b00abSMichael Kruse };
393937b00abSMichael Kruse 
prevectSchedBand(isl::schedule_node Node,unsigned DimToVectorize,int VectorWidth)3942e580538SRoman Gareev isl::schedule_node ScheduleTreeOptimizer::prevectSchedBand(
3952e580538SRoman Gareev     isl::schedule_node Node, unsigned DimToVectorize, int VectorWidth) {
3962e580538SRoman Gareev   assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band);
39719523ed2SAndreas Simbuerger 
3982e580538SRoman Gareev   auto Space = isl::manage(isl_schedule_node_band_get_space(Node.get()));
39944596fe6SRiccardo Mori   unsigned ScheduleDimensions = unsignedFromIslSize(Space.dim(isl::dim::set));
40044596fe6SRiccardo Mori   assert(DimToVectorize < ScheduleDimensions);
40119523ed2SAndreas Simbuerger 
402b241d928STobias Grosser   if (DimToVectorize > 0) {
4032e580538SRoman Gareev     Node = isl::manage(
4042e580538SRoman Gareev         isl_schedule_node_band_split(Node.release(), DimToVectorize));
4052e580538SRoman Gareev     Node = Node.child(0);
406b241d928STobias Grosser   }
40744596fe6SRiccardo Mori   if (DimToVectorize < ScheduleDimensions - 1)
4082e580538SRoman Gareev     Node = isl::manage(isl_schedule_node_band_split(Node.release(), 1));
4092e580538SRoman Gareev   Space = isl::manage(isl_schedule_node_band_get_space(Node.get()));
4102e580538SRoman Gareev   auto Sizes = isl::multi_val::zero(Space);
4110813bd16SRiccardo Mori   Sizes = Sizes.set_val(0, isl::val(Node.ctx(), VectorWidth));
4122e580538SRoman Gareev   Node =
4132e580538SRoman Gareev       isl::manage(isl_schedule_node_band_tile(Node.release(), Sizes.release()));
4142e580538SRoman Gareev   Node = isolateFullPartialTiles(Node, VectorWidth);
4152e580538SRoman Gareev   Node = Node.child(0);
41642e24895STobias Grosser   // Make sure the "trivially vectorizable loop" is not unrolled. Otherwise,
41742e24895STobias Grosser   // we will have troubles to match it in the backend.
418937b00abSMichael Kruse   Node = Node.as<isl::schedule_node_band>().set_ast_build_options(
4190813bd16SRiccardo Mori       isl::union_set(Node.ctx(), "{ unroll[x]: 1 = 0 }"));
420937b00abSMichael Kruse 
421937b00abSMichael Kruse   // Sink the inner loop into the smallest possible statements to make them
422937b00abSMichael Kruse   // represent a single vector instruction if possible.
423937b00abSMichael Kruse   Node = isl::manage(isl_schedule_node_band_sink(Node.release()));
424937b00abSMichael Kruse 
425937b00abSMichael Kruse   // Add SIMD markers to those vector statements.
426937b00abSMichael Kruse   InsertSimdMarkers SimdMarkerInserter;
427937b00abSMichael Kruse   Node = SimdMarkerInserter.visit(Node);
428937b00abSMichael Kruse 
42906ed5292SMichael Kruse   PrevectOpts++;
430937b00abSMichael Kruse   return Node.parent();
43119523ed2SAndreas Simbuerger }
43219523ed2SAndreas Simbuerger 
isSimpleInnermostBand(const isl::schedule_node & Node)4339248fde5SEugene Zelenko static bool isSimpleInnermostBand(const isl::schedule_node &Node) {
434d3d3d6b7STobias Grosser   assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band);
435d3d3d6b7STobias Grosser   assert(isl_schedule_node_n_children(Node.get()) == 1);
436c9d4cb2fSTobias Grosser 
437d3d3d6b7STobias Grosser   auto ChildType = isl_schedule_node_get_type(Node.child(0).get());
438c9d4cb2fSTobias Grosser 
439c9d4cb2fSTobias Grosser   if (ChildType == isl_schedule_node_leaf)
440c9d4cb2fSTobias Grosser     return true;
441c9d4cb2fSTobias Grosser 
442c9d4cb2fSTobias Grosser   if (ChildType != isl_schedule_node_sequence)
443c9d4cb2fSTobias Grosser     return false;
444c9d4cb2fSTobias Grosser 
445c9d4cb2fSTobias Grosser   auto Sequence = Node.child(0);
446c9d4cb2fSTobias Grosser 
447d3d3d6b7STobias Grosser   for (int c = 0, nc = isl_schedule_node_n_children(Sequence.get()); c < nc;
448c9d4cb2fSTobias Grosser        ++c) {
449c9d4cb2fSTobias Grosser     auto Child = Sequence.child(c);
450d3d3d6b7STobias Grosser     if (isl_schedule_node_get_type(Child.get()) != isl_schedule_node_filter)
451c9d4cb2fSTobias Grosser       return false;
452d3d3d6b7STobias Grosser     if (isl_schedule_node_get_type(Child.child(0).get()) !=
453c9d4cb2fSTobias Grosser         isl_schedule_node_leaf)
454c9d4cb2fSTobias Grosser       return false;
455c9d4cb2fSTobias Grosser   }
456c9d4cb2fSTobias Grosser   return true;
457c9d4cb2fSTobias Grosser }
458c9d4cb2fSTobias Grosser 
isTileableBandNode(isl::schedule_node Node)4592e580538SRoman Gareev bool ScheduleTreeOptimizer::isTileableBandNode(isl::schedule_node Node) {
4602e580538SRoman Gareev   if (isl_schedule_node_get_type(Node.get()) != isl_schedule_node_band)
461862b9b52STobias Grosser     return false;
46219523ed2SAndreas Simbuerger 
4632e580538SRoman Gareev   if (isl_schedule_node_n_children(Node.get()) != 1)
464862b9b52STobias Grosser     return false;
46519523ed2SAndreas Simbuerger 
4662e580538SRoman Gareev   if (!isl_schedule_node_band_get_permutable(Node.get()))
467862b9b52STobias Grosser     return false;
46819523ed2SAndreas Simbuerger 
4692e580538SRoman Gareev   auto Space = isl::manage(isl_schedule_node_band_get_space(Node.get()));
4709bdea573STobias Grosser 
47144596fe6SRiccardo Mori   if (unsignedFromIslSize(Space.dim(isl::dim::set)) <= 1u)
472862b9b52STobias Grosser     return false;
47319523ed2SAndreas Simbuerger 
4742e580538SRoman Gareev   return isSimpleInnermostBand(Node);
475862b9b52STobias Grosser }
476862b9b52STobias Grosser 
4772e580538SRoman Gareev __isl_give isl::schedule_node
applyTileBandOpt(isl::schedule_node Node)478ced20c66SMichael Kruse ScheduleTreeOptimizer::applyTileBandOpt(isl::schedule_node Node) {
47906ed5292SMichael Kruse   if (FirstLevelTiling) {
4801ac884d7STobias Grosser     Node = tileNode(Node, "1st level tiling", FirstLevelTileSizes,
4811ac884d7STobias Grosser                     FirstLevelDefaultTileSize);
48206ed5292SMichael Kruse     FirstLevelTileOpts++;
48306ed5292SMichael Kruse   }
48404832716STobias Grosser 
48506ed5292SMichael Kruse   if (SecondLevelTiling) {
4861ac884d7STobias Grosser     Node = tileNode(Node, "2nd level tiling", SecondLevelTileSizes,
4871ac884d7STobias Grosser                     SecondLevelDefaultTileSize);
48806ed5292SMichael Kruse     SecondLevelTileOpts++;
48906ed5292SMichael Kruse   }
490bbb4cec2STobias Grosser 
49106ed5292SMichael Kruse   if (RegisterTiling) {
492b17b9a83SRoman Gareev     Node =
493b17b9a83SRoman Gareev         applyRegisterTiling(Node, RegisterTileSizes, RegisterDefaultTileSize);
49406ed5292SMichael Kruse     RegisterTileOpts++;
49506ed5292SMichael Kruse   }
49642e24895STobias Grosser 
497f10f4636STobias Grosser   return Node;
498ced20c66SMichael Kruse }
499bbb4cec2STobias Grosser 
500ced20c66SMichael Kruse isl::schedule_node
applyPrevectBandOpt(isl::schedule_node Node)501ced20c66SMichael Kruse ScheduleTreeOptimizer::applyPrevectBandOpt(isl::schedule_node Node) {
5022e580538SRoman Gareev   auto Space = isl::manage(isl_schedule_node_band_get_space(Node.get()));
50344596fe6SRiccardo Mori   int Dims = unsignedFromIslSize(Space.dim(isl::dim::set));
504862b9b52STobias Grosser 
505b241d928STobias Grosser   for (int i = Dims - 1; i >= 0; i--)
506d3fdbda6SRiccardo Mori     if (Node.as<isl::schedule_node_band>().member_get_coincident(i)) {
507fa57e9b7STobias Grosser       Node = prevectSchedBand(Node, i, PrevectorWidth);
50819523ed2SAndreas Simbuerger       break;
50919523ed2SAndreas Simbuerger     }
51019523ed2SAndreas Simbuerger 
511f10f4636STobias Grosser   return Node;
51219523ed2SAndreas Simbuerger }
51319523ed2SAndreas Simbuerger 
5149c3eb596SRoman Gareev __isl_give isl_schedule_node *
optimizeBand(__isl_take isl_schedule_node * NodeArg,void * User)515ced20c66SMichael Kruse ScheduleTreeOptimizer::optimizeBand(__isl_take isl_schedule_node *NodeArg,
5169c3eb596SRoman Gareev                                     void *User) {
51798075fe1SRoman Gareev   const OptimizerAdditionalInfoTy *OAI =
51898075fe1SRoman Gareev       static_cast<const OptimizerAdditionalInfoTy *>(User);
519ced20c66SMichael Kruse   assert(OAI && "Expecting optimization options");
52098075fe1SRoman Gareev 
521ced20c66SMichael Kruse   isl::schedule_node Node = isl::manage(NodeArg);
522ced20c66SMichael Kruse   if (!isTileableBandNode(Node))
523ced20c66SMichael Kruse     return Node.release();
524ced20c66SMichael Kruse 
525ced20c66SMichael Kruse   if (OAI->PatternOpts) {
5267c7978a1Spatacca     isl::schedule_node PatternOptimizedSchedule =
527ced20c66SMichael Kruse         tryOptimizeMatMulPattern(Node, OAI->TTI, OAI->D);
5287c7978a1Spatacca     if (!PatternOptimizedSchedule.is_null()) {
52906ed5292SMichael Kruse       MatMulOpts++;
530*6fa65f8aSMichael Kruse       OAI->DepsChanged = true;
531d123e983SMichael Kruse       return PatternOptimizedSchedule.release();
532d123e983SMichael Kruse     }
53342402c9eSRoman Gareev   }
5349c3eb596SRoman Gareev 
535ced20c66SMichael Kruse   if (OAI->Postopts)
536ced20c66SMichael Kruse     Node = applyTileBandOpt(Node);
537ced20c66SMichael Kruse 
538ced20c66SMichael Kruse   if (OAI->Prevect) {
539ced20c66SMichael Kruse     // FIXME: Prevectorization requirements are different from those checked by
540ced20c66SMichael Kruse     // isTileableBandNode.
541ced20c66SMichael Kruse     Node = applyPrevectBandOpt(Node);
542ced20c66SMichael Kruse   }
543ced20c66SMichael Kruse 
544ced20c66SMichael Kruse   return Node.release();
5459c3eb596SRoman Gareev }
5469c3eb596SRoman Gareev 
5472e580538SRoman Gareev isl::schedule
optimizeSchedule(isl::schedule Schedule,const OptimizerAdditionalInfoTy * OAI)5482e580538SRoman Gareev ScheduleTreeOptimizer::optimizeSchedule(isl::schedule Schedule,
54998075fe1SRoman Gareev                                         const OptimizerAdditionalInfoTy *OAI) {
5502e580538SRoman Gareev   auto Root = Schedule.get_root();
55198075fe1SRoman Gareev   Root = optimizeScheduleNode(Root, OAI);
5522e580538SRoman Gareev   return Root.get_schedule();
55319523ed2SAndreas Simbuerger }
55419523ed2SAndreas Simbuerger 
optimizeScheduleNode(isl::schedule_node Node,const OptimizerAdditionalInfoTy * OAI)5552e580538SRoman Gareev isl::schedule_node ScheduleTreeOptimizer::optimizeScheduleNode(
5562e580538SRoman Gareev     isl::schedule_node Node, const OptimizerAdditionalInfoTy *OAI) {
5572e580538SRoman Gareev   Node = isl::manage(isl_schedule_node_map_descendant_bottom_up(
5582e580538SRoman Gareev       Node.release(), optimizeBand,
5592e580538SRoman Gareev       const_cast<void *>(static_cast<const void *>(OAI))));
560fa57e9b7STobias Grosser   return Node;
561fa57e9b7STobias Grosser }
562fa57e9b7STobias Grosser 
isProfitableSchedule(Scop & S,isl::schedule NewSchedule)5632e580538SRoman Gareev bool ScheduleTreeOptimizer::isProfitableSchedule(Scop &S,
5642e580538SRoman Gareev                                                  isl::schedule NewSchedule) {
5657ceb0402SJohannes Doerfert   // To understand if the schedule has been optimized we check if the schedule
5667ceb0402SJohannes Doerfert   // has changed at all.
5677ceb0402SJohannes Doerfert   // TODO: We can improve this by tracking if any necessarily beneficial
5687ceb0402SJohannes Doerfert   // transformations have been performed. This can e.g. be tiling, loop
5697ceb0402SJohannes Doerfert   // interchange, or ...) We can track this either at the place where the
5707ceb0402SJohannes Doerfert   // transformation has been performed or, in case of automatic ILP based
5717ceb0402SJohannes Doerfert   // optimizations, by comparing (yet to be defined) performance metrics
5727ceb0402SJohannes Doerfert   // before/after the scheduling optimizer
5737ceb0402SJohannes Doerfert   // (e.g., #stride-one accesses)
574ced20c66SMichael Kruse   // FIXME: A schedule tree whose union_map-conversion is identical to the
575ced20c66SMichael Kruse   // original schedule map may still allow for parallelization, i.e. can still
576ced20c66SMichael Kruse   // be profitable.
5772e580538SRoman Gareev   auto NewScheduleMap = NewSchedule.get_map();
57861bd3a48STobias Grosser   auto OldSchedule = S.getSchedule();
5797c7978a1Spatacca   assert(!OldSchedule.is_null() &&
5807c7978a1Spatacca          "Only IslScheduleOptimizer can insert extension nodes "
581b3224adfSRoman Gareev          "that make Scop::getSchedule() return nullptr.");
5822e580538SRoman Gareev   bool changed = !OldSchedule.is_equal(NewScheduleMap);
5837ceb0402SJohannes Doerfert   return changed;
5847ceb0402SJohannes Doerfert }
5857ceb0402SJohannes Doerfert 
586bd93df93SMichael Kruse class IslScheduleOptimizerWrapperPass final : public ScopPass {
587fa57e9b7STobias Grosser public:
588fa57e9b7STobias Grosser   static char ID;
589fa57e9b7STobias Grosser 
IslScheduleOptimizerWrapperPass()590e200df95SMichael Kruse   explicit IslScheduleOptimizerWrapperPass() : ScopPass(ID) {}
5919248fde5SEugene Zelenko 
592c80d6979STobias Grosser   /// Optimize the schedule of the SCoP @p S.
593fa57e9b7STobias Grosser   bool runOnScop(Scop &S) override;
594fa57e9b7STobias Grosser 
595c80d6979STobias Grosser   /// Print the new schedule for the SCoP @p S.
59645be6446SJohannes Doerfert   void printScop(raw_ostream &OS, Scop &S) const override;
59745be6446SJohannes Doerfert 
598c80d6979STobias Grosser   /// Register all analyses and transformation required.
59945be6446SJohannes Doerfert   void getAnalysisUsage(AnalysisUsage &AU) const override;
600fa57e9b7STobias Grosser 
601c80d6979STobias Grosser   /// Release the internal memory.
releaseMemory()6020f376308SJohannes Doerfert   void releaseMemory() override {
6039b41d095Spatacca     LastSchedule = {};
60432bf4684SMichael Kruse     IslCtx.reset();
605fa57e9b7STobias Grosser   }
60645be6446SJohannes Doerfert 
60745be6446SJohannes Doerfert private:
60832bf4684SMichael Kruse   std::shared_ptr<isl_ctx> IslCtx;
609e200df95SMichael Kruse   isl::schedule LastSchedule;
610fa57e9b7STobias Grosser };
611fa57e9b7STobias Grosser 
612e200df95SMichael Kruse char IslScheduleOptimizerWrapperPass::ID = 0;
613fa57e9b7STobias Grosser 
614927050afSFangrui Song #ifndef NDEBUG
printSchedule(llvm::raw_ostream & OS,const isl::schedule & Schedule,StringRef Desc)6153f170eb1SMichael Kruse static void printSchedule(llvm::raw_ostream &OS, const isl::schedule &Schedule,
6163f170eb1SMichael Kruse                           StringRef Desc) {
6170813bd16SRiccardo Mori   isl::ctx Ctx = Schedule.ctx();
6183f170eb1SMichael Kruse   isl_printer *P = isl_printer_to_str(Ctx.get());
6193f170eb1SMichael Kruse   P = isl_printer_set_yaml_style(P, ISL_YAML_STYLE_BLOCK);
6203f170eb1SMichael Kruse   P = isl_printer_print_schedule(P, Schedule.get());
6213f170eb1SMichael Kruse   char *Str = isl_printer_get_str(P);
6223f170eb1SMichael Kruse   OS << Desc << ": \n" << Str << "\n";
6233f170eb1SMichael Kruse   free(Str);
6243f170eb1SMichael Kruse   isl_printer_free(P);
6253f170eb1SMichael Kruse }
626927050afSFangrui Song #endif
6273f170eb1SMichael Kruse 
62806ed5292SMichael Kruse /// Collect statistics for the schedule tree.
62906ed5292SMichael Kruse ///
63006ed5292SMichael Kruse /// @param Schedule The schedule tree to analyze. If not a schedule tree it is
63106ed5292SMichael Kruse /// ignored.
63206ed5292SMichael Kruse /// @param Version  The version of the schedule tree that is analyzed.
63306ed5292SMichael Kruse ///                 0 for the original schedule tree before any transformation.
63406ed5292SMichael Kruse ///                 1 for the schedule tree after isl's rescheduling.
63506ed5292SMichael Kruse ///                 2 for the schedule tree after optimizations are applied
63606ed5292SMichael Kruse ///                 (tiling, pattern matching)
walkScheduleTreeForStatistics(isl::schedule Schedule,int Version)63706ed5292SMichael Kruse static void walkScheduleTreeForStatistics(isl::schedule Schedule, int Version) {
63806ed5292SMichael Kruse   auto Root = Schedule.get_root();
6397c7978a1Spatacca   if (Root.is_null())
64006ed5292SMichael Kruse     return;
64106ed5292SMichael Kruse 
6428dceb760SMichael Kruse   isl_schedule_node_foreach_descendant_top_down(
6438dceb760SMichael Kruse       Root.get(),
6448dceb760SMichael Kruse       [](__isl_keep isl_schedule_node *nodeptr, void *user) -> isl_bool {
645718d04c6STobias Grosser         isl::schedule_node Node = isl::manage_copy(nodeptr);
6468dceb760SMichael Kruse         int Version = *static_cast<int *>(user);
6478dceb760SMichael Kruse 
64806ed5292SMichael Kruse         switch (isl_schedule_node_get_type(Node.get())) {
64906ed5292SMichael Kruse         case isl_schedule_node_band: {
65006ed5292SMichael Kruse           NumBands[Version]++;
6518dceb760SMichael Kruse           if (isl_schedule_node_band_get_permutable(Node.get()) ==
6528dceb760SMichael Kruse               isl_bool_true)
65306ed5292SMichael Kruse             NumPermutable[Version]++;
65406ed5292SMichael Kruse 
65506ed5292SMichael Kruse           int CountMembers = isl_schedule_node_band_n_member(Node.get());
65606ed5292SMichael Kruse           NumBandMembers[Version] += CountMembers;
65706ed5292SMichael Kruse           for (int i = 0; i < CountMembers; i += 1) {
658d3fdbda6SRiccardo Mori             if (Node.as<isl::schedule_node_band>().member_get_coincident(i))
65906ed5292SMichael Kruse               NumCoincident[Version]++;
66006ed5292SMichael Kruse           }
6619248fde5SEugene Zelenko           break;
6629248fde5SEugene Zelenko         }
66306ed5292SMichael Kruse 
66406ed5292SMichael Kruse         case isl_schedule_node_filter:
66506ed5292SMichael Kruse           NumFilters[Version]++;
66606ed5292SMichael Kruse           break;
66706ed5292SMichael Kruse 
66806ed5292SMichael Kruse         case isl_schedule_node_extension:
66906ed5292SMichael Kruse           NumExtension[Version]++;
67006ed5292SMichael Kruse           break;
67106ed5292SMichael Kruse 
67206ed5292SMichael Kruse         default:
67306ed5292SMichael Kruse           break;
67406ed5292SMichael Kruse         }
67506ed5292SMichael Kruse 
6768dceb760SMichael Kruse         return isl_bool_true;
6778dceb760SMichael Kruse       },
6788dceb760SMichael Kruse       &Version);
67906ed5292SMichael Kruse }
68006ed5292SMichael Kruse 
runIslScheduleOptimizer(Scop & S,function_ref<const Dependences & (Dependences::AnalysisLevel)> GetDeps,TargetTransformInfo * TTI,OptimizationRemarkEmitter * ORE,isl::schedule & LastSchedule,bool & DepsChanged)681*6fa65f8aSMichael Kruse static void runIslScheduleOptimizer(
682e200df95SMichael Kruse     Scop &S,
683e200df95SMichael Kruse     function_ref<const Dependences &(Dependences::AnalysisLevel)> GetDeps,
684e470f926SMichael Kruse     TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE,
685*6fa65f8aSMichael Kruse     isl::schedule &LastSchedule, bool &DepsChanged) {
686e470f926SMichael Kruse 
68702ca346eSSingapuram Sanjay Srivallabh   // Skip SCoPs in case they're already optimised by PPCGCodeGeneration
68802ca346eSSingapuram Sanjay Srivallabh   if (S.isToBeSkipped())
689*6fa65f8aSMichael Kruse     return;
69002ca346eSSingapuram Sanjay Srivallabh 
6916f7921f2SJohannes Doerfert   // Skip empty SCoPs but still allow code generation as it will delete the
6926f7921f2SJohannes Doerfert   // loops present but not needed.
6936f7921f2SJohannes Doerfert   if (S.getSize() == 0) {
6946f7921f2SJohannes Doerfert     S.markAsOptimized();
695*6fa65f8aSMichael Kruse     return;
6966f7921f2SJohannes Doerfert   }
6976f7921f2SJohannes Doerfert 
6983f170eb1SMichael Kruse   ScopsProcessed++;
69919523ed2SAndreas Simbuerger 
7003f170eb1SMichael Kruse   // Schedule without optimizations.
7013f170eb1SMichael Kruse   isl::schedule Schedule = S.getScheduleTree();
7023f170eb1SMichael Kruse   walkScheduleTreeForStatistics(S.getScheduleTree(), 0);
7033f170eb1SMichael Kruse   LLVM_DEBUG(printSchedule(dbgs(), Schedule, "Original schedule tree"));
7043f170eb1SMichael Kruse 
7053f170eb1SMichael Kruse   bool HasUserTransformation = false;
7063f170eb1SMichael Kruse   if (PragmaBasedOpts) {
707e470f926SMichael Kruse     isl::schedule ManuallyTransformed = applyManualTransformations(
708e470f926SMichael Kruse         &S, Schedule, GetDeps(Dependences::AL_Statement), ORE);
7097c7978a1Spatacca     if (ManuallyTransformed.is_null()) {
7103f170eb1SMichael Kruse       LLVM_DEBUG(dbgs() << "Error during manual optimization\n");
711*6fa65f8aSMichael Kruse       return;
7123f170eb1SMichael Kruse     }
7133f170eb1SMichael Kruse 
7143f170eb1SMichael Kruse     if (ManuallyTransformed.get() != Schedule.get()) {
7153f170eb1SMichael Kruse       // User transformations have precedence over other transformations.
7163f170eb1SMichael Kruse       HasUserTransformation = true;
7173f170eb1SMichael Kruse       Schedule = std::move(ManuallyTransformed);
7183f170eb1SMichael Kruse       LLVM_DEBUG(
7193f170eb1SMichael Kruse           printSchedule(dbgs(), Schedule, "After manual transformations"));
7203f170eb1SMichael Kruse     }
7213f170eb1SMichael Kruse   }
7223f170eb1SMichael Kruse 
7233f170eb1SMichael Kruse   // Only continue if either manual transformations have been applied or we are
7243f170eb1SMichael Kruse   // allowed to apply heuristics.
7253f170eb1SMichael Kruse   // TODO: Detect disabled heuristics and no user-directed transformation
7263f170eb1SMichael Kruse   // metadata earlier in ScopDetection.
7273f170eb1SMichael Kruse   if (!HasUserTransformation && S.hasDisableHeuristicsHint()) {
7283f170eb1SMichael Kruse     LLVM_DEBUG(dbgs() << "Heuristic optimizations disabled by metadata\n");
729*6fa65f8aSMichael Kruse     return;
7303f170eb1SMichael Kruse   }
7313f170eb1SMichael Kruse 
7323f170eb1SMichael Kruse   // Get dependency analysis.
7333f170eb1SMichael Kruse   const Dependences &D = GetDeps(Dependences::AL_Statement);
7340e370cf1SMichael Kruse   if (D.getSharedIslCtx() != S.getSharedIslCtx()) {
735349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "DependenceInfo for another SCoP/isl_ctx\n");
736*6fa65f8aSMichael Kruse     return;
7370e370cf1SMichael Kruse   }
7383f170eb1SMichael Kruse   if (!D.hasValidDependences()) {
7393f170eb1SMichael Kruse     LLVM_DEBUG(dbgs() << "Dependency information not available\n");
740*6fa65f8aSMichael Kruse     return;
7413f170eb1SMichael Kruse   }
74219523ed2SAndreas Simbuerger 
7433f170eb1SMichael Kruse   // Apply ISL's algorithm only if not overriden by the user. Note that
7443f170eb1SMichael Kruse   // post-rescheduling optimizations (tiling, pattern-based, prevectorization)
7453f170eb1SMichael Kruse   // rely on the coincidence/permutable annotations on schedule tree bands that
7463f170eb1SMichael Kruse   // are added by the rescheduling analyzer. Therefore, disabling the
7473f170eb1SMichael Kruse   // rescheduler implicitly also disables these optimizations.
748ced20c66SMichael Kruse   if (!EnableReschedule) {
749ced20c66SMichael Kruse     LLVM_DEBUG(dbgs() << "Skipping rescheduling due to command line option\n");
750ced20c66SMichael Kruse   } else if (HasUserTransformation) {
7513f170eb1SMichael Kruse     LLVM_DEBUG(
7523f170eb1SMichael Kruse         dbgs() << "Skipping rescheduling due to manual transformation\n");
7533f170eb1SMichael Kruse   } else {
75419523ed2SAndreas Simbuerger     // Build input data.
7557e6424baSJohannes Doerfert     int ValidityKinds =
7567e6424baSJohannes Doerfert         Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
75719523ed2SAndreas Simbuerger     int ProximityKinds;
75819523ed2SAndreas Simbuerger 
75919523ed2SAndreas Simbuerger     if (OptimizeDeps == "all")
7607e6424baSJohannes Doerfert       ProximityKinds =
7617e6424baSJohannes Doerfert           Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
76219523ed2SAndreas Simbuerger     else if (OptimizeDeps == "raw")
7637e6424baSJohannes Doerfert       ProximityKinds = Dependences::TYPE_RAW;
76419523ed2SAndreas Simbuerger     else {
76519523ed2SAndreas Simbuerger       errs() << "Do not know how to optimize for '" << OptimizeDeps << "'"
76619523ed2SAndreas Simbuerger              << " Falling back to optimizing all dependences.\n";
7677e6424baSJohannes Doerfert       ProximityKinds =
7687e6424baSJohannes Doerfert           Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
76919523ed2SAndreas Simbuerger     }
77019523ed2SAndreas Simbuerger 
77131df6f31STobias Grosser     isl::union_set Domain = S.getDomains();
77219523ed2SAndreas Simbuerger 
7737c7978a1Spatacca     if (Domain.is_null())
774*6fa65f8aSMichael Kruse       return;
77519523ed2SAndreas Simbuerger 
7766a6d9df7STobias Grosser     isl::union_map Validity = D.getDependences(ValidityKinds);
7776a6d9df7STobias Grosser     isl::union_map Proximity = D.getDependences(ProximityKinds);
77819523ed2SAndreas Simbuerger 
77919523ed2SAndreas Simbuerger     // Simplify the dependences by removing the constraints introduced by the
78019523ed2SAndreas Simbuerger     // domains. This can speed up the scheduling time significantly, as large
78119523ed2SAndreas Simbuerger     // constant coefficients will be removed from the dependences. The
78219523ed2SAndreas Simbuerger     // introduction of some additional dependences reduces the possible
78319523ed2SAndreas Simbuerger     // transformations, but in most cases, such transformation do not seem to be
78419523ed2SAndreas Simbuerger     // interesting anyway. In some cases this option may stop the scheduler to
78519523ed2SAndreas Simbuerger     // find any schedule.
78619523ed2SAndreas Simbuerger     if (SimplifyDeps == "yes") {
7877205f93aSTobias Grosser       Validity = Validity.gist_domain(Domain);
7887205f93aSTobias Grosser       Validity = Validity.gist_range(Domain);
7897205f93aSTobias Grosser       Proximity = Proximity.gist_domain(Domain);
7907205f93aSTobias Grosser       Proximity = Proximity.gist_range(Domain);
79119523ed2SAndreas Simbuerger     } else if (SimplifyDeps != "no") {
7923f170eb1SMichael Kruse       errs()
7933f170eb1SMichael Kruse           << "warning: Option -polly-opt-simplify-deps should either be 'yes' "
79419523ed2SAndreas Simbuerger              "or 'no'. Falling back to default: 'yes'\n";
79519523ed2SAndreas Simbuerger     }
79619523ed2SAndreas Simbuerger 
797349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "\n\nCompute schedule from: ");
798349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "Domain := " << Domain << ";\n");
799349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "Proximity := " << Proximity << ";\n");
800349506a9SNicola Zaghen     LLVM_DEBUG(dbgs() << "Validity := " << Validity << ";\n");
80119523ed2SAndreas Simbuerger 
80219523ed2SAndreas Simbuerger     int IslMaximizeBands;
80319523ed2SAndreas Simbuerger     if (MaximizeBandDepth == "yes") {
80419523ed2SAndreas Simbuerger       IslMaximizeBands = 1;
80519523ed2SAndreas Simbuerger     } else if (MaximizeBandDepth == "no") {
80619523ed2SAndreas Simbuerger       IslMaximizeBands = 0;
80719523ed2SAndreas Simbuerger     } else {
8083f170eb1SMichael Kruse       errs()
8093f170eb1SMichael Kruse           << "warning: Option -polly-opt-maximize-bands should either be 'yes'"
81019523ed2SAndreas Simbuerger              " or 'no'. Falling back to default: 'yes'\n";
81119523ed2SAndreas Simbuerger       IslMaximizeBands = 1;
81219523ed2SAndreas Simbuerger     }
81319523ed2SAndreas Simbuerger 
814315aa327SMichael Kruse     int IslOuterCoincidence;
815315aa327SMichael Kruse     if (OuterCoincidence == "yes") {
816315aa327SMichael Kruse       IslOuterCoincidence = 1;
817315aa327SMichael Kruse     } else if (OuterCoincidence == "no") {
818315aa327SMichael Kruse       IslOuterCoincidence = 0;
819315aa327SMichael Kruse     } else {
820315aa327SMichael Kruse       errs() << "warning: Option -polly-opt-outer-coincidence should either be "
821315aa327SMichael Kruse                 "'yes' or 'no'. Falling back to default: 'no'\n";
822315aa327SMichael Kruse       IslOuterCoincidence = 0;
823315aa327SMichael Kruse     }
824315aa327SMichael Kruse 
82500fd43b3SPhilip Pfaffe     isl_ctx *Ctx = S.getIslCtx().get();
82619523ed2SAndreas Simbuerger 
827af149930STobias Grosser     isl_options_set_schedule_outer_coincidence(Ctx, IslOuterCoincidence);
828af149930STobias Grosser     isl_options_set_schedule_maximize_band_depth(Ctx, IslMaximizeBands);
829af149930STobias Grosser     isl_options_set_schedule_max_constant_term(Ctx, MaxConstantTerm);
830af149930STobias Grosser     isl_options_set_schedule_max_coefficient(Ctx, MaxCoefficient);
831af149930STobias Grosser     isl_options_set_tile_scale_tile_loops(Ctx, 0);
832af149930STobias Grosser 
8333898a046STobias Grosser     auto OnErrorStatus = isl_options_get_on_error(Ctx);
834af149930STobias Grosser     isl_options_set_on_error(Ctx, ISL_ON_ERROR_CONTINUE);
83519523ed2SAndreas Simbuerger 
8367205f93aSTobias Grosser     auto SC = isl::schedule_constraints::on_domain(Domain);
8377205f93aSTobias Grosser     SC = SC.set_proximity(Proximity);
8387205f93aSTobias Grosser     SC = SC.set_validity(Validity);
8397205f93aSTobias Grosser     SC = SC.set_coincidence(Validity);
8403f170eb1SMichael Kruse     Schedule = SC.compute_schedule();
8413898a046STobias Grosser     isl_options_set_on_error(Ctx, OnErrorStatus);
84219523ed2SAndreas Simbuerger 
8433f170eb1SMichael Kruse     ScopsRescheduled++;
8443f170eb1SMichael Kruse     LLVM_DEBUG(printSchedule(dbgs(), Schedule, "After rescheduling"));
8453f170eb1SMichael Kruse   }
8463f170eb1SMichael Kruse 
84706ed5292SMichael Kruse   walkScheduleTreeForStatistics(Schedule, 1);
84806ed5292SMichael Kruse 
84919523ed2SAndreas Simbuerger   // In cases the scheduler is not able to optimize the code, we just do not
85019523ed2SAndreas Simbuerger   // touch the schedule.
8517c7978a1Spatacca   if (Schedule.is_null())
852*6fa65f8aSMichael Kruse     return;
85319523ed2SAndreas Simbuerger 
85464489255SMichael Kruse   if (GreedyFusion) {
85564489255SMichael Kruse     isl::union_map Validity = D.getDependences(
85664489255SMichael Kruse         Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW);
85764489255SMichael Kruse     Schedule = applyGreedyFusion(Schedule, Validity);
85864489255SMichael Kruse     assert(!Schedule.is_null());
85964489255SMichael Kruse   }
86064489255SMichael Kruse 
861ced20c66SMichael Kruse   // Apply post-rescheduling optimizations (if enabled) and/or prevectorization.
862ced20c66SMichael Kruse   const OptimizerAdditionalInfoTy OAI = {
863*6fa65f8aSMichael Kruse       TTI,
864*6fa65f8aSMichael Kruse       const_cast<Dependences *>(&D),
865ced20c66SMichael Kruse       /*PatternOpts=*/!HasUserTransformation && PMBasedOpts,
866ced20c66SMichael Kruse       /*Postopts=*/!HasUserTransformation && EnablePostopts,
867*6fa65f8aSMichael Kruse       /*Prevect=*/PollyVectorizerChoice != VECTORIZER_NONE,
868*6fa65f8aSMichael Kruse       DepsChanged};
869ced20c66SMichael Kruse   if (OAI.PatternOpts || OAI.Postopts || OAI.Prevect) {
8703f170eb1SMichael Kruse     Schedule = ScheduleTreeOptimizer::optimizeSchedule(Schedule, &OAI);
8713f170eb1SMichael Kruse     Schedule = hoistExtensionNodes(Schedule);
8723f170eb1SMichael Kruse     LLVM_DEBUG(printSchedule(dbgs(), Schedule, "After post-optimizations"));
8733f170eb1SMichael Kruse     walkScheduleTreeForStatistics(Schedule, 2);
874ced20c66SMichael Kruse   }
8757ceb0402SJohannes Doerfert 
876e470f926SMichael Kruse   // Skip profitability check if user transformation(s) have been applied.
877e470f926SMichael Kruse   if (!HasUserTransformation &&
878e470f926SMichael Kruse       !ScheduleTreeOptimizer::isProfitableSchedule(S, Schedule))
879*6fa65f8aSMichael Kruse     return;
8807ceb0402SJohannes Doerfert 
88106ed5292SMichael Kruse   auto ScopStats = S.getStatistics();
88206ed5292SMichael Kruse   ScopsOptimized++;
88306ed5292SMichael Kruse   NumAffineLoopsOptimized += ScopStats.NumAffineLoops;
88406ed5292SMichael Kruse   NumBoxedLoopsOptimized += ScopStats.NumBoxedLoops;
8853f170eb1SMichael Kruse   LastSchedule = Schedule;
88606ed5292SMichael Kruse 
8873f170eb1SMichael Kruse   S.setScheduleTree(Schedule);
8887ceb0402SJohannes Doerfert   S.markAsOptimized();
88919523ed2SAndreas Simbuerger 
8905f99f865SRoman Gareev   if (OptimizedScops)
891cd4c977bSMichael Kruse     errs() << S;
89219523ed2SAndreas Simbuerger }
89319523ed2SAndreas Simbuerger 
runOnScop(Scop & S)894e200df95SMichael Kruse bool IslScheduleOptimizerWrapperPass::runOnScop(Scop &S) {
895e200df95SMichael Kruse   releaseMemory();
896e200df95SMichael Kruse 
897e200df95SMichael Kruse   Function &F = S.getFunction();
898e200df95SMichael Kruse   IslCtx = S.getSharedIslCtx();
899e200df95SMichael Kruse 
900e200df95SMichael Kruse   auto getDependences =
901e200df95SMichael Kruse       [this](Dependences::AnalysisLevel) -> const Dependences & {
902e200df95SMichael Kruse     return getAnalysis<DependenceInfo>().getDependences(
903e200df95SMichael Kruse         Dependences::AL_Statement);
904e200df95SMichael Kruse   };
905e470f926SMichael Kruse   OptimizationRemarkEmitter &ORE =
906e470f926SMichael Kruse       getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
907e200df95SMichael Kruse   TargetTransformInfo *TTI =
908e200df95SMichael Kruse       &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
909*6fa65f8aSMichael Kruse 
910*6fa65f8aSMichael Kruse   bool DepsChanged = false;
911*6fa65f8aSMichael Kruse   runIslScheduleOptimizer(S, getDependences, TTI, &ORE, LastSchedule,
912*6fa65f8aSMichael Kruse                           DepsChanged);
913*6fa65f8aSMichael Kruse   if (DepsChanged)
914*6fa65f8aSMichael Kruse     getAnalysis<DependenceInfo>().abandonDependences();
915*6fa65f8aSMichael Kruse   return false;
916e200df95SMichael Kruse }
917e200df95SMichael Kruse 
runScheduleOptimizerPrinter(raw_ostream & OS,isl::schedule LastSchedule)918e200df95SMichael Kruse static void runScheduleOptimizerPrinter(raw_ostream &OS,
919e200df95SMichael Kruse                                         isl::schedule LastSchedule) {
92019523ed2SAndreas Simbuerger   isl_printer *p;
92119523ed2SAndreas Simbuerger   char *ScheduleStr;
92219523ed2SAndreas Simbuerger 
92319523ed2SAndreas Simbuerger   OS << "Calculated schedule:\n";
92419523ed2SAndreas Simbuerger 
9257c7978a1Spatacca   if (LastSchedule.is_null()) {
92619523ed2SAndreas Simbuerger     OS << "n/a\n";
92719523ed2SAndreas Simbuerger     return;
92819523ed2SAndreas Simbuerger   }
92919523ed2SAndreas Simbuerger 
9300813bd16SRiccardo Mori   p = isl_printer_to_str(LastSchedule.ctx().get());
93132bf4684SMichael Kruse   p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
932e200df95SMichael Kruse   p = isl_printer_print_schedule(p, LastSchedule.get());
93319523ed2SAndreas Simbuerger   ScheduleStr = isl_printer_get_str(p);
93419523ed2SAndreas Simbuerger   isl_printer_free(p);
93519523ed2SAndreas Simbuerger 
93619523ed2SAndreas Simbuerger   OS << ScheduleStr << "\n";
937243511a2SMichael Kruse 
938243511a2SMichael Kruse   free(ScheduleStr);
93919523ed2SAndreas Simbuerger }
94019523ed2SAndreas Simbuerger 
printScop(raw_ostream & OS,Scop &) const941e200df95SMichael Kruse void IslScheduleOptimizerWrapperPass::printScop(raw_ostream &OS, Scop &) const {
942e200df95SMichael Kruse   runScheduleOptimizerPrinter(OS, LastSchedule);
943e200df95SMichael Kruse }
944e200df95SMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const945e200df95SMichael Kruse void IslScheduleOptimizerWrapperPass::getAnalysisUsage(
946e200df95SMichael Kruse     AnalysisUsage &AU) const {
94719523ed2SAndreas Simbuerger   ScopPass::getAnalysisUsage(AU);
948f6557f98SJohannes Doerfert   AU.addRequired<DependenceInfo>();
94942402c9eSRoman Gareev   AU.addRequired<TargetTransformInfoWrapperPass>();
950e470f926SMichael Kruse   AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
951a4f447c2SMichael Kruse 
952a4f447c2SMichael Kruse   AU.addPreserved<DependenceInfo>();
953e470f926SMichael Kruse   AU.addPreserved<OptimizationRemarkEmitterWrapperPass>();
95419523ed2SAndreas Simbuerger }
95519523ed2SAndreas Simbuerger 
9567387f33bSMichael Kruse } // namespace
9577387f33bSMichael Kruse 
createIslScheduleOptimizerWrapperPass()958e200df95SMichael Kruse Pass *polly::createIslScheduleOptimizerWrapperPass() {
959e200df95SMichael Kruse   return new IslScheduleOptimizerWrapperPass();
96019523ed2SAndreas Simbuerger }
96119523ed2SAndreas Simbuerger 
962e200df95SMichael Kruse INITIALIZE_PASS_BEGIN(IslScheduleOptimizerWrapperPass, "polly-opt-isl",
96319523ed2SAndreas Simbuerger                       "Polly - Optimize schedule of SCoP", false, false);
964f6557f98SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(DependenceInfo);
96599191c78SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass);
96642402c9eSRoman Gareev INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass);
967e470f926SMichael Kruse INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass);
968e200df95SMichael Kruse INITIALIZE_PASS_END(IslScheduleOptimizerWrapperPass, "polly-opt-isl",
96919523ed2SAndreas Simbuerger                     "Polly - Optimize schedule of SCoP", false, false)
970e200df95SMichael Kruse 
971e200df95SMichael Kruse static llvm::PreservedAnalyses
runIslScheduleOptimizerUsingNPM(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U,raw_ostream * OS)972e200df95SMichael Kruse runIslScheduleOptimizerUsingNPM(Scop &S, ScopAnalysisManager &SAM,
973e200df95SMichael Kruse                                 ScopStandardAnalysisResults &SAR, SPMUpdater &U,
974e200df95SMichael Kruse                                 raw_ostream *OS) {
975e200df95SMichael Kruse   DependenceAnalysis::Result &Deps = SAM.getResult<DependenceAnalysis>(S, SAR);
976e200df95SMichael Kruse   auto GetDeps = [&Deps](Dependences::AnalysisLevel) -> const Dependences & {
977e200df95SMichael Kruse     return Deps.getDependences(Dependences::AL_Statement);
978e200df95SMichael Kruse   };
979e470f926SMichael Kruse   OptimizationRemarkEmitter ORE(&S.getFunction());
980e200df95SMichael Kruse   TargetTransformInfo *TTI = &SAR.TTI;
981e200df95SMichael Kruse   isl::schedule LastSchedule;
982*6fa65f8aSMichael Kruse   bool DepsChanged = false;
983*6fa65f8aSMichael Kruse   runIslScheduleOptimizer(S, GetDeps, TTI, &ORE, LastSchedule, DepsChanged);
984*6fa65f8aSMichael Kruse   if (DepsChanged)
985*6fa65f8aSMichael Kruse     Deps.abandonDependences();
986*6fa65f8aSMichael Kruse 
987e200df95SMichael Kruse   if (OS) {
988e200df95SMichael Kruse     *OS << "Printing analysis 'Polly - Optimize schedule of SCoP' for region: '"
989e200df95SMichael Kruse         << S.getName() << "' in function '" << S.getFunction().getName()
990e200df95SMichael Kruse         << "':\n";
991e200df95SMichael Kruse     runScheduleOptimizerPrinter(*OS, LastSchedule);
992e200df95SMichael Kruse   }
993e200df95SMichael Kruse   return PreservedAnalyses::all();
994e200df95SMichael Kruse }
995e200df95SMichael Kruse 
996e200df95SMichael Kruse llvm::PreservedAnalyses
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)997e200df95SMichael Kruse IslScheduleOptimizerPass::run(Scop &S, ScopAnalysisManager &SAM,
998e200df95SMichael Kruse                               ScopStandardAnalysisResults &SAR, SPMUpdater &U) {
999e200df95SMichael Kruse   return runIslScheduleOptimizerUsingNPM(S, SAM, SAR, U, nullptr);
1000e200df95SMichael Kruse }
1001e200df95SMichael Kruse 
1002e200df95SMichael Kruse llvm::PreservedAnalyses
run(Scop & S,ScopAnalysisManager & SAM,ScopStandardAnalysisResults & SAR,SPMUpdater & U)1003e200df95SMichael Kruse IslScheduleOptimizerPrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
1004e200df95SMichael Kruse                                      ScopStandardAnalysisResults &SAR,
1005e200df95SMichael Kruse                                      SPMUpdater &U) {
1006e200df95SMichael Kruse   return runIslScheduleOptimizerUsingNPM(S, SAM, SAR, U, &OS);
1007e200df95SMichael Kruse }
10085c028081SMichael Kruse 
10095c028081SMichael Kruse //===----------------------------------------------------------------------===//
10105c028081SMichael Kruse 
10115c028081SMichael Kruse namespace {
10125c028081SMichael Kruse /// Print result from IslScheduleOptimizerWrapperPass.
1013bd93df93SMichael Kruse class IslScheduleOptimizerPrinterLegacyPass final : public ScopPass {
10145c028081SMichael Kruse public:
10155c028081SMichael Kruse   static char ID;
10165c028081SMichael Kruse 
IslScheduleOptimizerPrinterLegacyPass()10175c028081SMichael Kruse   IslScheduleOptimizerPrinterLegacyPass()
10185c028081SMichael Kruse       : IslScheduleOptimizerPrinterLegacyPass(outs()) {}
IslScheduleOptimizerPrinterLegacyPass(llvm::raw_ostream & OS)10195c028081SMichael Kruse   explicit IslScheduleOptimizerPrinterLegacyPass(llvm::raw_ostream &OS)
10205c028081SMichael Kruse       : ScopPass(ID), OS(OS) {}
10215c028081SMichael Kruse 
runOnScop(Scop & S)10225c028081SMichael Kruse   bool runOnScop(Scop &S) override {
10235c028081SMichael Kruse     IslScheduleOptimizerWrapperPass &P =
10245c028081SMichael Kruse         getAnalysis<IslScheduleOptimizerWrapperPass>();
10255c028081SMichael Kruse 
10265c028081SMichael Kruse     OS << "Printing analysis '" << P.getPassName() << "' for region: '"
10275c028081SMichael Kruse        << S.getRegion().getNameStr() << "' in function '"
10285c028081SMichael Kruse        << S.getFunction().getName() << "':\n";
10295c028081SMichael Kruse     P.printScop(OS, S);
10305c028081SMichael Kruse 
10315c028081SMichael Kruse     return false;
10325c028081SMichael Kruse   }
10335c028081SMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const10345c028081SMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
10355c028081SMichael Kruse     ScopPass::getAnalysisUsage(AU);
10365c028081SMichael Kruse     AU.addRequired<IslScheduleOptimizerWrapperPass>();
10375c028081SMichael Kruse     AU.setPreservesAll();
10385c028081SMichael Kruse   }
10395c028081SMichael Kruse 
10405c028081SMichael Kruse private:
10415c028081SMichael Kruse   llvm::raw_ostream &OS;
10425c028081SMichael Kruse };
10435c028081SMichael Kruse 
10445c028081SMichael Kruse char IslScheduleOptimizerPrinterLegacyPass::ID = 0;
10455c028081SMichael Kruse } // namespace
10465c028081SMichael Kruse 
createIslScheduleOptimizerPrinterLegacyPass(raw_ostream & OS)10475c028081SMichael Kruse Pass *polly::createIslScheduleOptimizerPrinterLegacyPass(raw_ostream &OS) {
10485c028081SMichael Kruse   return new IslScheduleOptimizerPrinterLegacyPass(OS);
10495c028081SMichael Kruse }
10505c028081SMichael Kruse 
10515c028081SMichael Kruse INITIALIZE_PASS_BEGIN(IslScheduleOptimizerPrinterLegacyPass,
10525c028081SMichael Kruse                       "polly-print-opt-isl",
10535c028081SMichael Kruse                       "Polly - Print optimizer schedule of SCoP", false, false);
10545c028081SMichael Kruse INITIALIZE_PASS_DEPENDENCY(IslScheduleOptimizerWrapperPass)
10555c028081SMichael Kruse INITIALIZE_PASS_END(IslScheduleOptimizerPrinterLegacyPass,
10565c028081SMichael Kruse                     "polly-print-opt-isl",
10575c028081SMichael Kruse                     "Polly - Print optimizer schedule of SCoP", false, false)
1058