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