1 //===- Schedule.cpp - Calculate an optimized schedule ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This pass the isl to calculate a schedule that is optimized for parallelism
11 // and tileablility. The algorithm used in isl is an optimized version of the
12 // algorithm described in following paper:
13 //
14 // U. Bondhugula, A. Hartono, J. Ramanujam, and P. Sadayappan.
15 // A Practical Automatic Polyhedral Parallelizer and Locality Optimizer.
16 // In Proceedings of the 2008 ACM SIGPLAN Conference On Programming Language
17 // Design and Implementation, PLDI ’08, pages 101–113. ACM, 2008.
18 //===----------------------------------------------------------------------===//
19 
20 #include "polly/ScheduleOptimizer.h"
21 #include "isl/aff.h"
22 #include "isl/band.h"
23 #include "isl/constraint.h"
24 #include "isl/map.h"
25 #include "isl/options.h"
26 #include "isl/schedule.h"
27 #include "isl/space.h"
28 #include "polly/CodeGen/CodeGeneration.h"
29 #include "polly/Dependences.h"
30 #include "polly/LinkAllPasses.h"
31 #include "polly/Options.h"
32 #include "polly/ScopInfo.h"
33 #include "llvm/Support/Debug.h"
34 
35 using namespace llvm;
36 using namespace polly;
37 
38 #define DEBUG_TYPE "polly-opt-isl"
39 
40 namespace polly {
41 bool DisablePollyTiling;
42 }
43 static cl::opt<bool, true>
44 DisableTiling("polly-no-tiling", cl::desc("Disable tiling in the scheduler"),
45               cl::location(polly::DisablePollyTiling), cl::init(false),
46               cl::ZeroOrMore, cl::cat(PollyCategory));
47 
48 static cl::opt<std::string>
49 OptimizeDeps("polly-opt-optimize-only",
50              cl::desc("Only a certain kind of dependences (all/raw)"),
51              cl::Hidden, cl::init("all"), cl::ZeroOrMore,
52              cl::cat(PollyCategory));
53 
54 static cl::opt<std::string>
55 SimplifyDeps("polly-opt-simplify-deps",
56              cl::desc("Dependences should be simplified (yes/no)"), cl::Hidden,
57              cl::init("yes"), cl::ZeroOrMore, cl::cat(PollyCategory));
58 
59 static cl::opt<int>
60 MaxConstantTerm("polly-opt-max-constant-term",
61                 cl::desc("The maximal constant term allowed (-1 is unlimited)"),
62                 cl::Hidden, cl::init(20), cl::ZeroOrMore,
63                 cl::cat(PollyCategory));
64 
65 static cl::opt<int>
66 MaxCoefficient("polly-opt-max-coefficient",
67                cl::desc("The maximal coefficient allowed (-1 is unlimited)"),
68                cl::Hidden, cl::init(20), cl::ZeroOrMore,
69                cl::cat(PollyCategory));
70 
71 static cl::opt<std::string>
72 FusionStrategy("polly-opt-fusion",
73                cl::desc("The fusion strategy to choose (min/max)"), cl::Hidden,
74                cl::init("min"), cl::ZeroOrMore, cl::cat(PollyCategory));
75 
76 static cl::opt<std::string>
77 MaximizeBandDepth("polly-opt-maximize-bands",
78                   cl::desc("Maximize the band depth (yes/no)"), cl::Hidden,
79                   cl::init("yes"), cl::ZeroOrMore, cl::cat(PollyCategory));
80 
81 namespace {
82 
83 class IslScheduleOptimizer : public ScopPass {
84 public:
85   static char ID;
86   explicit IslScheduleOptimizer() : ScopPass(ID) { LastSchedule = nullptr; }
87 
88   ~IslScheduleOptimizer() { isl_schedule_free(LastSchedule); }
89 
90   virtual bool runOnScop(Scop &S);
91   void printScop(llvm::raw_ostream &OS) const;
92   void getAnalysisUsage(AnalysisUsage &AU) const;
93 
94 private:
95   isl_schedule *LastSchedule;
96 
97   static void extendScattering(Scop &S, unsigned NewDimensions);
98 
99   /// @brief Create a map that describes a n-dimensonal tiling.
100   ///
101   /// getTileMap creates a map from a n-dimensional scattering space into an
102   /// 2*n-dimensional scattering space. The map describes a rectangular
103   /// tiling.
104   ///
105   /// Example:
106   ///   scheduleDimensions = 2, parameterDimensions = 1, tileSize = 32
107   ///
108   ///   tileMap := [p0] -> {[s0, s1] -> [t0, t1, s0, s1]:
109   ///                        t0 % 32 = 0 and t0 <= s0 < t0 + 32 and
110   ///                        t1 % 32 = 0 and t1 <= s1 < t1 + 32}
111   ///
112   ///  Before tiling:
113   ///
114   ///  for (i = 0; i < N; i++)
115   ///    for (j = 0; j < M; j++)
116   ///	S(i,j)
117   ///
118   ///  After tiling:
119   ///
120   ///  for (t_i = 0; t_i < N; i+=32)
121   ///    for (t_j = 0; t_j < M; j+=32)
122   ///	for (i = t_i; i < min(t_i + 32, N); i++)  | Unknown that N % 32 = 0
123   ///	  for (j = t_j; j < t_j + 32; j++)        |   Known that M % 32 = 0
124   ///	    S(i,j)
125   ///
126   static isl_basic_map *getTileMap(isl_ctx *ctx, int scheduleDimensions,
127                                    isl_space *SpaceModel, int tileSize = 32);
128 
129   /// @brief Get the schedule for this band.
130   ///
131   /// Polly applies transformations like tiling on top of the isl calculated
132   /// value.  This can influence the number of scheduling dimension. The
133   /// number of schedule dimensions is returned in the parameter 'Dimension'.
134   static isl_union_map *getScheduleForBand(isl_band *Band, int *Dimensions);
135 
136   /// @brief Create a map that pre-vectorizes one scheduling dimension.
137   ///
138   /// getPrevectorMap creates a map that maps each input dimension to the same
139   /// output dimension, except for the dimension DimToVectorize.
140   /// DimToVectorize is strip mined by 'VectorWidth' and the newly created
141   /// point loop of DimToVectorize is moved to the innermost level.
142   ///
143   /// Example (DimToVectorize=0, ScheduleDimensions=2, VectorWidth=4):
144   ///
145   /// | Before transformation
146   /// |
147   /// | A[i,j] -> [i,j]
148   /// |
149   /// | for (i = 0; i < 128; i++)
150   /// |    for (j = 0; j < 128; j++)
151   /// |      A(i,j);
152   ///
153   ///   Prevector map:
154   ///   [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
155   ///
156   /// | After transformation:
157   /// |
158   /// | A[i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
159   /// |
160   /// | for (it = 0; it < 128; it+=4)
161   /// |    for (j = 0; j < 128; j++)
162   /// |      for (ip = max(0,it); ip < min(128, it + 3); ip++)
163   /// |        A(ip,j);
164   ///
165   /// The goal of this transformation is to create a trivially vectorizable
166   /// loop.  This means a parallel loop at the innermost level that has a
167   /// constant number of iterations corresponding to the target vector width.
168   ///
169   /// This transformation creates a loop at the innermost level. The loop has
170   /// a constant number of iterations, if the number of loop iterations at
171   /// DimToVectorize can be divided by VectorWidth. The default VectorWidth is
172   /// currently constant and not yet target specific. This function does not
173   /// reason about parallelism.
174   static isl_map *getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
175                                   int ScheduleDimensions, int VectorWidth = 4);
176 
177   /// @brief Get the scheduling map for a list of bands.
178   ///
179   /// Walk recursively the forest of bands to combine the schedules of the
180   /// individual bands to the overall schedule. In case tiling is requested,
181   /// the individual bands are tiled.
182   static isl_union_map *getScheduleForBandList(isl_band_list *BandList);
183 
184   static isl_union_map *getScheduleMap(isl_schedule *Schedule);
185 
186   using llvm::Pass::doFinalization;
187 
188   virtual bool doFinalization() {
189     isl_schedule_free(LastSchedule);
190     LastSchedule = nullptr;
191     return true;
192   }
193 };
194 }
195 
196 char IslScheduleOptimizer::ID = 0;
197 
198 void IslScheduleOptimizer::extendScattering(Scop &S, unsigned NewDimensions) {
199   for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
200     ScopStmt *Stmt = *SI;
201     unsigned OldDimensions = Stmt->getNumScattering();
202     isl_space *Space;
203     isl_map *Map, *New;
204 
205     Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions);
206     Map = isl_map_universe(Space);
207 
208     for (unsigned i = 0; i < OldDimensions; i++)
209       Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
210 
211     for (unsigned i = OldDimensions; i < NewDimensions; i++)
212       Map = isl_map_fix_si(Map, isl_dim_out, i, 0);
213 
214     Map = isl_map_align_params(Map, S.getParamSpace());
215     New = isl_map_apply_range(Stmt->getScattering(), Map);
216     Stmt->setScattering(New);
217   }
218 }
219 
220 isl_basic_map *IslScheduleOptimizer::getTileMap(isl_ctx *ctx,
221                                                 int scheduleDimensions,
222                                                 isl_space *SpaceModel,
223                                                 int tileSize) {
224   // We construct
225   //
226   // tileMap := [p0] -> {[s0, s1] -> [t0, t1, p0, p1, a0, a1]:
227   //	                  s0 = a0 * 32 and s0 = p0 and t0 <= p0 < t0 + 32 and
228   //	                  s1 = a1 * 32 and s1 = p1 and t1 <= p1 < t1 + 32}
229   //
230   // and project out the auxilary dimensions a0 and a1.
231   isl_space *Space =
232       isl_space_alloc(ctx, 0, scheduleDimensions, scheduleDimensions * 3);
233   isl_basic_map *tileMap = isl_basic_map_universe(isl_space_copy(Space));
234 
235   isl_local_space *LocalSpace = isl_local_space_from_space(Space);
236 
237   for (int x = 0; x < scheduleDimensions; x++) {
238     int sX = x;
239     int tX = x;
240     int pX = scheduleDimensions + x;
241     int aX = 2 * scheduleDimensions + x;
242 
243     isl_constraint *c;
244 
245     // sX = aX * tileSize;
246     c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
247     isl_constraint_set_coefficient_si(c, isl_dim_out, sX, 1);
248     isl_constraint_set_coefficient_si(c, isl_dim_out, aX, -tileSize);
249     tileMap = isl_basic_map_add_constraint(tileMap, c);
250 
251     // pX = sX;
252     c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
253     isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
254     isl_constraint_set_coefficient_si(c, isl_dim_in, sX, -1);
255     tileMap = isl_basic_map_add_constraint(tileMap, c);
256 
257     // tX <= pX
258     c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
259     isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
260     isl_constraint_set_coefficient_si(c, isl_dim_out, tX, -1);
261     tileMap = isl_basic_map_add_constraint(tileMap, c);
262 
263     // pX <= tX + (tileSize - 1)
264     c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
265     isl_constraint_set_coefficient_si(c, isl_dim_out, tX, 1);
266     isl_constraint_set_coefficient_si(c, isl_dim_out, pX, -1);
267     isl_constraint_set_constant_si(c, tileSize - 1);
268     tileMap = isl_basic_map_add_constraint(tileMap, c);
269   }
270 
271   // Project out auxilary dimensions.
272   //
273   // The auxilary dimensions are transformed into existentially quantified ones.
274   // This reduces the number of visible scattering dimensions and allows Cloog
275   // to produces better code.
276   tileMap = isl_basic_map_project_out(
277       tileMap, isl_dim_out, 2 * scheduleDimensions, scheduleDimensions);
278   isl_local_space_free(LocalSpace);
279   return tileMap;
280 }
281 
282 isl_union_map *IslScheduleOptimizer::getScheduleForBand(isl_band *Band,
283                                                         int *Dimensions) {
284   isl_union_map *PartialSchedule;
285   isl_ctx *ctx;
286   isl_space *Space;
287   isl_basic_map *TileMap;
288   isl_union_map *TileUMap;
289 
290   PartialSchedule = isl_band_get_partial_schedule(Band);
291   *Dimensions = isl_band_n_member(Band);
292 
293   if (DisableTiling)
294     return PartialSchedule;
295 
296   // It does not make any sense to tile a band with just one dimension.
297   if (*Dimensions == 1)
298     return PartialSchedule;
299 
300   ctx = isl_union_map_get_ctx(PartialSchedule);
301   Space = isl_union_map_get_space(PartialSchedule);
302 
303   TileMap = getTileMap(ctx, *Dimensions, Space);
304   TileUMap = isl_union_map_from_map(isl_map_from_basic_map(TileMap));
305   TileUMap = isl_union_map_align_params(TileUMap, Space);
306   *Dimensions = 2 * *Dimensions;
307 
308   return isl_union_map_apply_range(PartialSchedule, TileUMap);
309 }
310 
311 isl_map *IslScheduleOptimizer::getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
312                                                int ScheduleDimensions,
313                                                int VectorWidth) {
314   isl_space *Space;
315   isl_local_space *LocalSpace, *LocalSpaceRange;
316   isl_set *Modulo;
317   isl_map *TilingMap;
318   isl_constraint *c;
319   isl_aff *Aff;
320   int PointDimension; /* ip */
321   int TileDimension;  /* it */
322   isl_val *VectorWidthMP;
323 
324   assert(0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);
325 
326   Space = isl_space_alloc(ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
327   TilingMap = isl_map_universe(isl_space_copy(Space));
328   LocalSpace = isl_local_space_from_space(Space);
329   PointDimension = ScheduleDimensions;
330   TileDimension = DimToVectorize;
331 
332   // Create an identity map for everything except DimToVectorize and map
333   // DimToVectorize to the point loop at the innermost dimension.
334   for (int i = 0; i < ScheduleDimensions; i++) {
335     c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
336     isl_constraint_set_coefficient_si(c, isl_dim_in, i, -1);
337 
338     if (i == DimToVectorize)
339       isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
340     else
341       isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
342 
343     TilingMap = isl_map_add_constraint(TilingMap, c);
344   }
345 
346   // it % 'VectorWidth' = 0
347   LocalSpaceRange = isl_local_space_range(isl_local_space_copy(LocalSpace));
348   Aff = isl_aff_zero_on_domain(LocalSpaceRange);
349   Aff = isl_aff_set_constant_si(Aff, VectorWidth);
350   Aff = isl_aff_set_coefficient_si(Aff, isl_dim_in, TileDimension, 1);
351   VectorWidthMP = isl_val_int_from_si(ctx, VectorWidth);
352   Aff = isl_aff_mod_val(Aff, VectorWidthMP);
353   Modulo = isl_pw_aff_zero_set(isl_pw_aff_from_aff(Aff));
354   TilingMap = isl_map_intersect_range(TilingMap, Modulo);
355 
356   // it <= ip
357   c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
358   isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, -1);
359   isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
360   TilingMap = isl_map_add_constraint(TilingMap, c);
361 
362   // ip <= it + ('VectorWidth' - 1)
363   c = isl_inequality_alloc(LocalSpace);
364   isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, 1);
365   isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, -1);
366   isl_constraint_set_constant_si(c, VectorWidth - 1);
367   TilingMap = isl_map_add_constraint(TilingMap, c);
368 
369   return TilingMap;
370 }
371 
372 isl_union_map *
373 IslScheduleOptimizer::getScheduleForBandList(isl_band_list *BandList) {
374   int NumBands;
375   isl_union_map *Schedule;
376   isl_ctx *ctx;
377 
378   ctx = isl_band_list_get_ctx(BandList);
379   NumBands = isl_band_list_n_band(BandList);
380   Schedule = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
381 
382   for (int i = 0; i < NumBands; i++) {
383     isl_band *Band;
384     isl_union_map *PartialSchedule;
385     int ScheduleDimensions;
386     isl_space *Space;
387 
388     Band = isl_band_list_get_band(BandList, i);
389     PartialSchedule = getScheduleForBand(Band, &ScheduleDimensions);
390     Space = isl_union_map_get_space(PartialSchedule);
391 
392     if (isl_band_has_children(Band)) {
393       isl_band_list *Children;
394       isl_union_map *SuffixSchedule;
395 
396       Children = isl_band_get_children(Band);
397       SuffixSchedule = getScheduleForBandList(Children);
398       PartialSchedule =
399           isl_union_map_flat_range_product(PartialSchedule, SuffixSchedule);
400       isl_band_list_free(Children);
401     } else if (PollyVectorizerChoice != VECTORIZER_NONE) {
402       // In case we are at the innermost band, we try to prepare for
403       // vectorization. This means, we look for the innermost parallel loop
404       // and strip mine this loop to the innermost level using a strip-mine
405       // factor corresponding to the number of vector iterations.
406       int NumDims = isl_band_n_member(Band);
407       for (int j = NumDims - 1; j >= 0; j--) {
408         if (isl_band_member_is_coincident(Band, j)) {
409           isl_map *TileMap;
410           isl_union_map *TileUMap;
411 
412           TileMap = getPrevectorMap(ctx, ScheduleDimensions - NumDims + j,
413                                     ScheduleDimensions);
414           TileUMap = isl_union_map_from_map(TileMap);
415           TileUMap =
416               isl_union_map_align_params(TileUMap, isl_space_copy(Space));
417           PartialSchedule =
418               isl_union_map_apply_range(PartialSchedule, TileUMap);
419           break;
420         }
421       }
422     }
423 
424     Schedule = isl_union_map_union(Schedule, PartialSchedule);
425 
426     isl_band_free(Band);
427     isl_space_free(Space);
428   }
429 
430   return Schedule;
431 }
432 
433 isl_union_map *IslScheduleOptimizer::getScheduleMap(isl_schedule *Schedule) {
434   isl_band_list *BandList = isl_schedule_get_band_forest(Schedule);
435   isl_union_map *ScheduleMap = getScheduleForBandList(BandList);
436   isl_band_list_free(BandList);
437   return ScheduleMap;
438 }
439 
440 bool IslScheduleOptimizer::runOnScop(Scop &S) {
441   Dependences *D = &getAnalysis<Dependences>();
442 
443   if (!D->hasValidDependences())
444     return false;
445 
446   isl_schedule_free(LastSchedule);
447   LastSchedule = nullptr;
448 
449   // Build input data.
450   int ValidityKinds =
451       Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
452   int ProximityKinds;
453 
454   if (OptimizeDeps == "all")
455     ProximityKinds =
456         Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
457   else if (OptimizeDeps == "raw")
458     ProximityKinds = Dependences::TYPE_RAW;
459   else {
460     errs() << "Do not know how to optimize for '" << OptimizeDeps << "'"
461            << " Falling back to optimizing all dependences.\n";
462     ProximityKinds =
463         Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW;
464   }
465 
466   isl_union_set *Domain = S.getDomains();
467 
468   if (!Domain)
469     return false;
470 
471   isl_union_map *Validity = D->getDependences(ValidityKinds);
472   isl_union_map *Proximity = D->getDependences(ProximityKinds);
473 
474   // Simplify the dependences by removing the constraints introduced by the
475   // domains. This can speed up the scheduling time significantly, as large
476   // constant coefficients will be removed from the dependences. The
477   // introduction of some additional dependences reduces the possible
478   // transformations, but in most cases, such transformation do not seem to be
479   // interesting anyway. In some cases this option may stop the scheduler to
480   // find any schedule.
481   if (SimplifyDeps == "yes") {
482     Validity = isl_union_map_gist_domain(Validity, isl_union_set_copy(Domain));
483     Validity = isl_union_map_gist_range(Validity, isl_union_set_copy(Domain));
484     Proximity =
485         isl_union_map_gist_domain(Proximity, isl_union_set_copy(Domain));
486     Proximity = isl_union_map_gist_range(Proximity, isl_union_set_copy(Domain));
487   } else if (SimplifyDeps != "no") {
488     errs() << "warning: Option -polly-opt-simplify-deps should either be 'yes' "
489               "or 'no'. Falling back to default: 'yes'\n";
490   }
491 
492   DEBUG(dbgs() << "\n\nCompute schedule from: ");
493   DEBUG(dbgs() << "Domain := "; isl_union_set_dump(Domain); dbgs() << ";\n");
494   DEBUG(dbgs() << "Proximity := "; isl_union_map_dump(Proximity);
495         dbgs() << ";\n");
496   DEBUG(dbgs() << "Validity := "; isl_union_map_dump(Validity);
497         dbgs() << ";\n");
498 
499   int IslFusionStrategy;
500 
501   if (FusionStrategy == "max") {
502     IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX;
503   } else if (FusionStrategy == "min") {
504     IslFusionStrategy = ISL_SCHEDULE_FUSE_MIN;
505   } else {
506     errs() << "warning: Unknown fusion strategy. Falling back to maximal "
507               "fusion.\n";
508     IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX;
509   }
510 
511   int IslMaximizeBands;
512 
513   if (MaximizeBandDepth == "yes") {
514     IslMaximizeBands = 1;
515   } else if (MaximizeBandDepth == "no") {
516     IslMaximizeBands = 0;
517   } else {
518     errs() << "warning: Option -polly-opt-maximize-bands should either be 'yes'"
519               " or 'no'. Falling back to default: 'yes'\n";
520     IslMaximizeBands = 1;
521   }
522 
523   isl_options_set_schedule_fuse(S.getIslCtx(), IslFusionStrategy);
524   isl_options_set_schedule_maximize_band_depth(S.getIslCtx(), IslMaximizeBands);
525   isl_options_set_schedule_max_constant_term(S.getIslCtx(), MaxConstantTerm);
526   isl_options_set_schedule_max_coefficient(S.getIslCtx(), MaxCoefficient);
527 
528   isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE);
529 
530   isl_schedule_constraints *ScheduleConstraints;
531   ScheduleConstraints = isl_schedule_constraints_on_domain(Domain);
532   ScheduleConstraints =
533       isl_schedule_constraints_set_proximity(ScheduleConstraints, Proximity);
534   ScheduleConstraints = isl_schedule_constraints_set_validity(
535       ScheduleConstraints, isl_union_map_copy(Validity));
536   ScheduleConstraints =
537       isl_schedule_constraints_set_coincidence(ScheduleConstraints, Validity);
538   isl_schedule *Schedule;
539   Schedule = isl_schedule_constraints_compute_schedule(ScheduleConstraints);
540   isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT);
541 
542   // In cases the scheduler is not able to optimize the code, we just do not
543   // touch the schedule.
544   if (!Schedule)
545     return false;
546 
547   DEBUG(dbgs() << "Schedule := "; isl_schedule_dump(Schedule); dbgs() << ";\n");
548 
549   isl_union_map *ScheduleMap = getScheduleMap(Schedule);
550 
551   for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
552     ScopStmt *Stmt = *SI;
553     isl_map *StmtSchedule;
554     isl_set *Domain = Stmt->getDomain();
555     isl_union_map *StmtBand;
556     StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(ScheduleMap),
557                                               isl_union_set_from_set(Domain));
558     if (isl_union_map_is_empty(StmtBand)) {
559       StmtSchedule = isl_map_from_domain(isl_set_empty(Stmt->getDomainSpace()));
560       isl_union_map_free(StmtBand);
561     } else {
562       assert(isl_union_map_n_map(StmtBand) == 1);
563       StmtSchedule = isl_map_from_union_map(StmtBand);
564     }
565 
566     Stmt->setScattering(StmtSchedule);
567   }
568 
569   isl_union_map_free(ScheduleMap);
570   LastSchedule = Schedule;
571 
572   unsigned MaxScatDims = 0;
573 
574   for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI)
575     MaxScatDims = std::max((*SI)->getNumScattering(), MaxScatDims);
576 
577   extendScattering(S, MaxScatDims);
578   return false;
579 }
580 
581 void IslScheduleOptimizer::printScop(raw_ostream &OS) const {
582   isl_printer *p;
583   char *ScheduleStr;
584 
585   OS << "Calculated schedule:\n";
586 
587   if (!LastSchedule) {
588     OS << "n/a\n";
589     return;
590   }
591 
592   p = isl_printer_to_str(isl_schedule_get_ctx(LastSchedule));
593   p = isl_printer_print_schedule(p, LastSchedule);
594   ScheduleStr = isl_printer_get_str(p);
595   isl_printer_free(p);
596 
597   OS << ScheduleStr << "\n";
598 }
599 
600 void IslScheduleOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
601   ScopPass::getAnalysisUsage(AU);
602   AU.addRequired<Dependences>();
603 }
604 
605 Pass *polly::createIslScheduleOptimizerPass() {
606   return new IslScheduleOptimizer();
607 }
608 
609 INITIALIZE_PASS_BEGIN(IslScheduleOptimizer, "polly-opt-isl",
610                       "Polly - Optimize schedule of SCoP", false, false);
611 INITIALIZE_PASS_DEPENDENCY(Dependences);
612 INITIALIZE_PASS_DEPENDENCY(ScopInfo);
613 INITIALIZE_PASS_END(IslScheduleOptimizer, "polly-opt-isl",
614                     "Polly - Optimize schedule of SCoP", false, false)
615