1/* A scheduling optimizer for Graphite
2   Copyright (C) 2012-2015 Free Software Foundation, Inc.
3   Contributed by Tobias Grosser <tobias@grosser.es>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3.  If not see
19<http://www.gnu.org/licenses/>.  */
20
21#include "config.h"
22
23#ifdef HAVE_isl
24#include <isl/constraint.h>
25#include <isl/set.h>
26#include <isl/union_set.h>
27#include <isl/map.h>
28#include <isl/union_map.h>
29#include <isl/schedule.h>
30#include <isl/band.h>
31#include <isl/aff.h>
32#include <isl/options.h>
33#endif
34
35#include "system.h"
36#include "coretypes.h"
37#include "hash-set.h"
38#include "machmode.h"
39#include "vec.h"
40#include "double-int.h"
41#include "input.h"
42#include "alias.h"
43#include "symtab.h"
44#include "options.h"
45#include "wide-int.h"
46#include "inchash.h"
47#include "tree.h"
48#include "fold-const.h"
49#include "predict.h"
50#include "tm.h"
51#include "hard-reg-set.h"
52#include "input.h"
53#include "function.h"
54#include "dominance.h"
55#include "cfg.h"
56#include "basic-block.h"
57#include "tree-ssa-alias.h"
58#include "internal-fn.h"
59#include "gimple-expr.h"
60#include "is-a.h"
61#include "gimple.h"
62#include "gimple-iterator.h"
63#include "tree-ssa-loop.h"
64#include "dumpfile.h"
65#include "cfgloop.h"
66#include "tree-chrec.h"
67#include "tree-data-ref.h"
68#include "tree-scalar-evolution.h"
69#include "sese.h"
70
71#ifdef HAVE_isl
72#include "graphite-poly.h"
73
74static isl_union_set *
75scop_get_domains (scop_p scop ATTRIBUTE_UNUSED)
76{
77  int i;
78  poly_bb_p pbb;
79  isl_space *space = isl_set_get_space (scop->context);
80  isl_union_set *res = isl_union_set_empty (space);
81
82  FOR_EACH_VEC_ELT (scop->bbs, i, pbb)
83    res = isl_union_set_add_set (res, isl_set_copy (pbb->domain));
84
85  return res;
86}
87
88/* getTileMap - Create a map that describes a n-dimensonal tiling.
89
90   getTileMap creates a map from a n-dimensional scattering space into an
91   2*n-dimensional scattering space. The map describes a rectangular tiling.
92
93   Example:
94     scheduleDimensions = 2, parameterDimensions = 1, tileSize = 32
95
96    tileMap := [p0] -> {[s0, s1] -> [t0, t1, s0, s1]:
97                         t0 % 32 = 0 and t0 <= s0 < t0 + 32 and
98                         t1 % 32 = 0 and t1 <= s1 < t1 + 32}
99
100   Before tiling:
101
102   for (i = 0; i < N; i++)
103     for (j = 0; j < M; j++)
104 	S(i,j)
105
106   After tiling:
107
108   for (t_i = 0; t_i < N; i+=32)
109     for (t_j = 0; t_j < M; j+=32)
110 	for (i = t_i; i < min(t_i + 32, N); i++)  | Unknown that N % 32 = 0
111 	  for (j = t_j; j < t_j + 32; j++)        |   Known that M % 32 = 0
112 	    S(i,j)
113   */
114
115static isl_basic_map *
116getTileMap (isl_ctx *ctx, int scheduleDimensions, int tileSize)
117{
118  int x;
119  /* We construct
120
121     tileMap := [p0] -> {[s0, s1] -> [t0, t1, p0, p1, a0, a1]:
122    	                s0 = a0 * 32 and s0 = p0 and t0 <= p0 < t0 + 32 and
123    	                s1 = a1 * 32 and s1 = p1 and t1 <= p1 < t1 + 32}
124
125     and project out the auxilary dimensions a0 and a1.  */
126  isl_space *Space = isl_space_alloc (ctx, 0, scheduleDimensions,
127				      scheduleDimensions * 3);
128  isl_basic_map *tileMap = isl_basic_map_universe (isl_space_copy (Space));
129
130  isl_local_space *LocalSpace = isl_local_space_from_space (Space);
131
132  for (x = 0; x < scheduleDimensions; x++)
133    {
134      int sX = x;
135      int tX = x;
136      int pX = scheduleDimensions + x;
137      int aX = 2 * scheduleDimensions + x;
138
139      isl_constraint *c;
140
141      /* sX = aX * tileSize; */
142      c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
143      isl_constraint_set_coefficient_si (c, isl_dim_out, sX, 1);
144      isl_constraint_set_coefficient_si (c, isl_dim_out, aX, -tileSize);
145      tileMap = isl_basic_map_add_constraint (tileMap, c);
146
147      /* pX = sX; */
148      c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
149      isl_constraint_set_coefficient_si (c, isl_dim_out, pX, 1);
150      isl_constraint_set_coefficient_si (c, isl_dim_in, sX, -1);
151      tileMap = isl_basic_map_add_constraint (tileMap, c);
152
153      /* tX <= pX */
154      c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
155      isl_constraint_set_coefficient_si (c, isl_dim_out, pX, 1);
156      isl_constraint_set_coefficient_si (c, isl_dim_out, tX, -1);
157      tileMap = isl_basic_map_add_constraint (tileMap, c);
158
159      /* pX <= tX + (tileSize - 1) */
160      c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
161      isl_constraint_set_coefficient_si (c, isl_dim_out, tX, 1);
162      isl_constraint_set_coefficient_si (c, isl_dim_out, pX, -1);
163      isl_constraint_set_constant_si (c, tileSize - 1);
164      tileMap = isl_basic_map_add_constraint (tileMap, c);
165    }
166
167  /* Project out auxiliary dimensions.
168
169     The auxiliary dimensions are transformed into existentially quantified ones.
170     This reduces the number of visible scattering dimensions and allows Cloog
171     to produces better code.  */
172  tileMap = isl_basic_map_project_out (tileMap, isl_dim_out,
173				       2 * scheduleDimensions,
174				       scheduleDimensions);
175  isl_local_space_free (LocalSpace);
176  return tileMap;
177}
178
179/* getScheduleForBand - Get the schedule for this band.
180
181   Polly applies transformations like tiling on top of the isl calculated value.
182   This can influence the number of scheduling dimension. The number of
183   schedule dimensions is returned in the parameter 'Dimension'.  */
184static bool DisableTiling = false;
185
186static isl_union_map *
187getScheduleForBand (isl_band *Band, int *Dimensions)
188{
189  isl_union_map *PartialSchedule;
190  isl_ctx *ctx;
191  isl_space *Space;
192  isl_basic_map *TileMap;
193  isl_union_map *TileUMap;
194
195  PartialSchedule = isl_band_get_partial_schedule (Band);
196  *Dimensions = isl_band_n_member (Band);
197
198  if (DisableTiling || flag_loop_unroll_jam)
199    return PartialSchedule;
200
201  /* It does not make any sense to tile a band with just one dimension.  */
202  if (*Dimensions == 1)
203    return PartialSchedule;
204
205  ctx = isl_union_map_get_ctx (PartialSchedule);
206  Space = isl_union_map_get_space (PartialSchedule);
207
208  TileMap = getTileMap (ctx, *Dimensions, 32);
209  TileUMap = isl_union_map_from_map (isl_map_from_basic_map (TileMap));
210  TileUMap = isl_union_map_align_params (TileUMap, Space);
211  *Dimensions = 2 * *Dimensions;
212
213  return isl_union_map_apply_range (PartialSchedule, TileUMap);
214}
215
216/* Create a map that pre-vectorizes one scheduling dimension.
217
218   getPrevectorMap creates a map that maps each input dimension to the same
219   output dimension, except for the dimension DimToVectorize. DimToVectorize is
220   strip mined by 'VectorWidth' and the newly created point loop of
221   DimToVectorize is moved to the innermost level.
222
223   Example (DimToVectorize=0, ScheduleDimensions=2, VectorWidth=4):
224
225   | Before transformation
226   |
227   | A[i,j] -> [i,j]
228   |
229   | for (i = 0; i < 128; i++)
230   |    for (j = 0; j < 128; j++)
231   |      A(i,j);
232
233     Prevector map:
234     [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
235
236   | After transformation:
237   |
238   | A[i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
239   |
240   | for (it = 0; it < 128; it+=4)
241   |    for (j = 0; j < 128; j++)
242   |      for (ip = max(0,it); ip < min(128, it + 3); ip++)
243   |        A(ip,j);
244
245   The goal of this transformation is to create a trivially vectorizable loop.
246   This means a parallel loop at the innermost level that has a constant number
247   of iterations corresponding to the target vector width.
248
249   This transformation creates a loop at the innermost level. The loop has a
250   constant number of iterations, if the number of loop iterations at
251   DimToVectorize can be devided by VectorWidth. The default VectorWidth is
252   currently constant and not yet target specific. This function does not reason
253   about parallelism.
254
255  */
256static isl_map *
257getPrevectorMap (isl_ctx *ctx, int DimToVectorize,
258		 int ScheduleDimensions,
259		 int VectorWidth)
260{
261  isl_space *Space;
262  isl_local_space *LocalSpace, *LocalSpaceRange;
263  isl_set *Modulo;
264  isl_map *TilingMap;
265  isl_constraint *c;
266  isl_aff *Aff;
267  int PointDimension; /* ip */
268  int TileDimension;  /* it */
269  isl_val *VectorWidthMP;
270  int i;
271
272  /* assert (0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);*/
273
274  Space = isl_space_alloc (ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
275  TilingMap = isl_map_universe (isl_space_copy (Space));
276  LocalSpace = isl_local_space_from_space (Space);
277  PointDimension = ScheduleDimensions;
278  TileDimension = DimToVectorize;
279
280  /* Create an identity map for everything except DimToVectorize and map
281     DimToVectorize to the point loop at the innermost dimension.  */
282  for (i = 0; i < ScheduleDimensions; i++)
283    {
284      c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
285      isl_constraint_set_coefficient_si (c, isl_dim_in, i, -1);
286
287      if (i == DimToVectorize)
288	isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1);
289      else
290	isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
291
292      TilingMap = isl_map_add_constraint (TilingMap, c);
293    }
294
295  /* it % 'VectorWidth' = 0  */
296  LocalSpaceRange = isl_local_space_range (isl_local_space_copy (LocalSpace));
297  Aff = isl_aff_zero_on_domain (LocalSpaceRange);
298  Aff = isl_aff_set_constant_si (Aff, VectorWidth);
299  Aff = isl_aff_set_coefficient_si (Aff, isl_dim_in, TileDimension, 1);
300
301  VectorWidthMP = isl_val_int_from_si (ctx, VectorWidth);
302  Aff = isl_aff_mod_val (Aff, VectorWidthMP);
303  Modulo = isl_pw_aff_zero_set (isl_pw_aff_from_aff (Aff));
304  TilingMap = isl_map_intersect_range (TilingMap, Modulo);
305
306  /* it <= ip */
307  c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
308  isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, -1);
309  isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1);
310  TilingMap = isl_map_add_constraint (TilingMap, c);
311
312  /* ip <= it + ('VectorWidth' - 1) */
313  c = isl_inequality_alloc (LocalSpace);
314  isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, 1);
315  isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, -1);
316  isl_constraint_set_constant_si (c, VectorWidth - 1);
317  TilingMap = isl_map_add_constraint (TilingMap, c);
318
319  return TilingMap;
320}
321
322/* Compute an auxiliary map to getPrevectorMap, for computing the separating
323   class defined by full tiles.  Used in graphite_isl_ast_to_gimple.c to set the
324   corresponding option for AST build.
325
326   The map (for VectorWidth=4):
327
328   [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and it + 3 = i and
329                        ip >= 0
330
331   The image of this map is the separation class. The range of this map includes
332   all the i multiple of 4 in the domain such as i + 3 is in the domain too.
333
334 */
335static isl_map *
336getPrevectorMap_full (isl_ctx *ctx, int DimToVectorize,
337		 int ScheduleDimensions,
338		 int VectorWidth)
339{
340  isl_space *Space;
341  isl_local_space *LocalSpace, *LocalSpaceRange;
342  isl_set *Modulo;
343  isl_map *TilingMap;
344  isl_constraint *c;
345  isl_aff *Aff;
346  int PointDimension; /* ip */
347  int TileDimension;  /* it */
348  isl_val *VectorWidthMP;
349  int i;
350
351  /* assert (0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);*/
352
353  Space = isl_space_alloc (ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
354  TilingMap = isl_map_universe (isl_space_copy (Space));
355  LocalSpace = isl_local_space_from_space (Space);
356  PointDimension = ScheduleDimensions;
357  TileDimension = DimToVectorize;
358
359  /* Create an identity map for everything except DimToVectorize and the
360     point loop. */
361  for (i = 0; i < ScheduleDimensions; i++)
362    {
363      if (i == DimToVectorize)
364        continue;
365
366      c = isl_equality_alloc (isl_local_space_copy (LocalSpace));
367
368      isl_constraint_set_coefficient_si (c, isl_dim_in, i, -1);
369      isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
370
371      TilingMap = isl_map_add_constraint (TilingMap, c);
372    }
373
374  /* it % 'VectorWidth' = 0  */
375  LocalSpaceRange = isl_local_space_range (isl_local_space_copy (LocalSpace));
376  Aff = isl_aff_zero_on_domain (LocalSpaceRange);
377  Aff = isl_aff_set_constant_si (Aff, VectorWidth);
378  Aff = isl_aff_set_coefficient_si (Aff, isl_dim_in, TileDimension, 1);
379
380  VectorWidthMP = isl_val_int_from_si (ctx, VectorWidth);
381  Aff = isl_aff_mod_val (Aff, VectorWidthMP);
382  Modulo = isl_pw_aff_zero_set (isl_pw_aff_from_aff (Aff));
383  TilingMap = isl_map_intersect_range (TilingMap, Modulo);
384
385  /* it + ('VectorWidth' - 1) = i0  */
386  c = isl_equality_alloc (isl_local_space_copy(LocalSpace));
387  isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension,-1);
388  isl_constraint_set_coefficient_si (c, isl_dim_in, TileDimension, 1);
389  isl_constraint_set_constant_si (c, -VectorWidth + 1);
390  TilingMap = isl_map_add_constraint (TilingMap, c);
391
392  /* ip >= 0 */
393  c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
394  isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1);
395  isl_constraint_set_constant_si (c, 0);
396  TilingMap = isl_map_add_constraint (TilingMap, c);
397
398  /* it <= ip */
399  c = isl_inequality_alloc (isl_local_space_copy (LocalSpace));
400  isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, -1);
401  isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1);
402  TilingMap = isl_map_add_constraint (TilingMap, c);
403
404  /* ip <= it + ('VectorWidth' - 1) */
405  c = isl_inequality_alloc (LocalSpace);
406  isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, 1);
407  isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, -1);
408  isl_constraint_set_constant_si (c, VectorWidth - 1);
409  TilingMap = isl_map_add_constraint (TilingMap, c);
410
411  return TilingMap;
412}
413
414static bool EnablePollyVector = false;
415
416/* getScheduleForBandList - Get the scheduling map for a list of bands.
417
418   We walk recursively the forest of bands to combine the schedules of the
419   individual bands to the overall schedule. In case tiling is requested,
420   the individual bands are tiled.
421   For unroll and jam the map the schedule for full tiles of the unrolled
422   dimnesion is computed.  */
423static isl_union_map *
424getScheduleForBandList (isl_band_list *BandList, isl_union_map **map_sepcl)
425{
426  int NumBands, i;
427  isl_union_map *Schedule;
428  isl_ctx *ctx;
429
430  ctx = isl_band_list_get_ctx (BandList);
431  NumBands = isl_band_list_n_band (BandList);
432  Schedule = isl_union_map_empty (isl_space_params_alloc (ctx, 0));
433
434  for (i = 0; i < NumBands; i++)
435    {
436      isl_band *Band;
437      isl_union_map *PartialSchedule;
438      int ScheduleDimensions;
439      isl_space *Space;
440
441      isl_union_map *PartialSchedule_f;
442
443      Band = isl_band_list_get_band (BandList, i);
444      PartialSchedule = getScheduleForBand (Band, &ScheduleDimensions);
445      Space = isl_union_map_get_space (PartialSchedule);
446
447      PartialSchedule_f = NULL;
448
449      if (isl_band_has_children (Band))
450	{
451	  isl_band_list *Children;
452	  isl_union_map *SuffixSchedule;
453
454	  Children = isl_band_get_children (Band);
455	  SuffixSchedule = getScheduleForBandList (Children, map_sepcl);
456	  PartialSchedule = isl_union_map_flat_range_product (PartialSchedule,
457							      SuffixSchedule);
458	  isl_band_list_free (Children);
459	}
460      else if (EnablePollyVector || flag_loop_unroll_jam)
461	{
462	  int i;
463	  int depth;
464
465 	  depth = PARAM_VALUE (PARAM_LOOP_UNROLL_JAM_DEPTH);
466
467	  for (i = ScheduleDimensions - 1 ;  i >= 0 ; i--)
468	    {
469	      if (flag_loop_unroll_jam && (i != (ScheduleDimensions - depth)))
470		continue;
471
472#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE
473	      if (isl_band_member_is_coincident (Band, i))
474#else
475	      if (isl_band_member_is_zero_distance (Band, i))
476#endif
477		{
478		  isl_map *TileMap;
479		  isl_union_map *TileUMap;
480		  int stride;
481
482                  stride = PARAM_VALUE (PARAM_LOOP_UNROLL_JAM_SIZE);
483
484		  TileMap = getPrevectorMap_full (ctx, i, ScheduleDimensions,
485						  stride);
486 		  TileUMap = isl_union_map_from_map (TileMap);
487		  TileUMap = isl_union_map_align_params
488		    (TileUMap, isl_space_copy (Space));
489		  PartialSchedule_f = isl_union_map_apply_range
490		    (isl_union_map_copy (PartialSchedule), TileUMap);
491
492		  TileMap = getPrevectorMap (ctx, i, ScheduleDimensions, stride);
493		  TileUMap = isl_union_map_from_map (TileMap);
494		  TileUMap = isl_union_map_align_params
495		    (TileUMap, isl_space_copy (Space));
496		  PartialSchedule = isl_union_map_apply_range
497		    (PartialSchedule, TileUMap);
498		  break;
499		}
500	    }
501	}
502      Schedule = isl_union_map_union (Schedule,
503                                      isl_union_map_copy(PartialSchedule));
504
505      isl_band_free (Band);
506      isl_space_free (Space);
507
508      if (!flag_loop_unroll_jam)
509	{
510          isl_union_map_free (PartialSchedule);
511          continue;
512	}
513
514      if (PartialSchedule_f)
515	{
516	  *map_sepcl = isl_union_map_union (*map_sepcl, PartialSchedule_f);
517          isl_union_map_free (PartialSchedule);
518	}
519      else
520        *map_sepcl = isl_union_map_union (*map_sepcl, PartialSchedule);
521    }
522
523  return Schedule;
524}
525
526static isl_union_map *
527getScheduleMap (isl_schedule *Schedule, isl_union_map **map_sepcl)
528{
529  isl_band_list *BandList = isl_schedule_get_band_forest (Schedule);
530  isl_union_map *ScheduleMap = getScheduleForBandList (BandList, map_sepcl);
531  isl_band_list_free (BandList);
532  return ScheduleMap;
533}
534
535static isl_stat
536getSingleMap (__isl_take isl_map *map, void *user)
537{
538  isl_map **singleMap = (isl_map **) user;
539  *singleMap = map;
540
541  return isl_stat_ok;
542}
543
544static void
545apply_schedule_map_to_scop (scop_p scop, isl_union_map *schedule_map, bool sepcl)
546{
547  int i;
548  poly_bb_p pbb;
549
550  FOR_EACH_VEC_ELT (scop->bbs, i, pbb)
551    {
552      isl_set *domain = isl_set_copy (pbb->domain);
553      isl_union_map *stmtBand;
554      isl_map *stmtSchedule;
555
556      stmtBand = isl_union_map_intersect_domain
557	(isl_union_map_copy (schedule_map),
558	 isl_union_set_from_set (domain));
559      isl_union_map_foreach_map (stmtBand, getSingleMap, &stmtSchedule);
560
561      if (!sepcl)
562	{
563	  isl_map_free (pbb->transformed);
564	  pbb->transformed = stmtSchedule;
565	}
566      else
567	  pbb->map_sepclass = stmtSchedule;
568
569      isl_union_map_free (stmtBand);
570    }
571}
572
573static const int CONSTANT_BOUND = 20;
574
575bool
576optimize_isl (scop_p scop)
577{
578
579  isl_schedule *schedule;
580#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE
581  isl_schedule_constraints *schedule_constraints;
582#endif
583  isl_union_set *domain;
584  isl_union_map *validity, *proximity, *dependences;
585  isl_union_map *schedule_map;
586  isl_union_map *schedule_map_f;
587
588  domain = scop_get_domains (scop);
589  dependences = scop_get_dependences (scop);
590  dependences = isl_union_map_gist_domain (dependences,
591					   isl_union_set_copy (domain));
592  dependences = isl_union_map_gist_range (dependences,
593					  isl_union_set_copy (domain));
594  validity = dependences;
595
596  proximity = isl_union_map_copy (validity);
597
598#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE
599  schedule_constraints = isl_schedule_constraints_on_domain (domain);
600  schedule_constraints
601	= isl_schedule_constraints_set_proximity (schedule_constraints,
602						  proximity);
603  schedule_constraints
604	= isl_schedule_constraints_set_validity (schedule_constraints,
605						 isl_union_map_copy (validity));
606  schedule_constraints
607	= isl_schedule_constraints_set_coincidence (schedule_constraints,
608						    validity);
609#endif
610
611  isl_options_set_schedule_max_constant_term (scop->ctx, CONSTANT_BOUND);
612  isl_options_set_schedule_maximize_band_depth (scop->ctx, 1);
613#ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
614  isl_options_set_schedule_serialize_sccs (scop->ctx, 1);
615#else
616  isl_options_set_schedule_fuse (scop->ctx, ISL_SCHEDULE_FUSE_MIN);
617#endif
618  isl_options_set_on_error (scop->ctx, ISL_ON_ERROR_CONTINUE);
619
620#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE
621  schedule = isl_schedule_constraints_compute_schedule(schedule_constraints);
622#else
623  schedule = isl_union_set_compute_schedule (domain, validity, proximity);
624#endif
625
626  isl_options_set_on_error (scop->ctx, ISL_ON_ERROR_ABORT);
627
628  if (!schedule)
629    return false;
630
631  schedule_map_f = isl_union_map_empty (isl_space_params_alloc (scop->ctx, 0));
632  schedule_map = getScheduleMap (schedule, &schedule_map_f);
633
634  apply_schedule_map_to_scop (scop, schedule_map, false);
635  if (!isl_union_map_is_empty (schedule_map_f))
636    apply_schedule_map_to_scop (scop, schedule_map_f, true);
637  isl_union_map_free (schedule_map_f);
638
639  isl_schedule_free (schedule);
640  isl_union_map_free (schedule_map);
641
642  return true;
643}
644
645#endif
646