replace isl_union_map_compute_flow by isl_union_access_info_compute_flow
[isl.git] / isl_schedule_band.c
blob6c0b391e3acb6786aca691c354940952edc96e89
1 /*
2 * Copyright 2013-2014 Ecole Normale Superieure
3 * Copyright 2014 INRIA Rocquencourt
5 * Use of this software is governed by the MIT license
7 * Written by Sven Verdoolaege,
8 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
9 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
10 * B.P. 105 - 78153 Le Chesnay, France
13 #include <isl/schedule_node.h>
14 #include <isl_schedule_band.h>
15 #include <isl_schedule_private.h>
17 isl_ctx *isl_schedule_band_get_ctx(__isl_keep isl_schedule_band *band)
19 return band ? isl_multi_union_pw_aff_get_ctx(band->mupa) : NULL;
22 /* Return a new uninitialized isl_schedule_band.
24 static __isl_give isl_schedule_band *isl_schedule_band_alloc(isl_ctx *ctx)
26 isl_schedule_band *band;
28 band = isl_calloc_type(ctx, isl_schedule_band);
29 if (!band)
30 return NULL;
32 band->ref = 1;
34 return band;
37 /* Return a new isl_schedule_band with partial schedule "mupa".
38 * First replace "mupa" by its greatest integer part to ensure
39 * that the schedule is always integral.
40 * The band is not marked permutable and the dimensions are not
41 * marked coincident.
43 __isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
44 __isl_take isl_multi_union_pw_aff *mupa)
46 isl_ctx *ctx;
47 isl_schedule_band *band;
49 mupa = isl_multi_union_pw_aff_floor(mupa);
50 if (!mupa)
51 return NULL;
52 ctx = isl_multi_union_pw_aff_get_ctx(mupa);
53 band = isl_schedule_band_alloc(ctx);
54 if (!band)
55 goto error;
57 band->n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
58 band->coincident = isl_calloc_array(ctx, int, band->n);
59 band->mupa = mupa;
61 if (band->n && !band->coincident)
62 return isl_schedule_band_free(band);
64 return band;
65 error:
66 isl_multi_union_pw_aff_free(mupa);
67 return NULL;
70 /* Create a duplicate of the given isl_schedule_band.
72 __isl_give isl_schedule_band *isl_schedule_band_dup(
73 __isl_keep isl_schedule_band *band)
75 int i;
76 isl_ctx *ctx;
77 isl_schedule_band *dup;
79 if (!band)
80 return NULL;
82 ctx = isl_schedule_band_get_ctx(band);
83 dup = isl_schedule_band_alloc(ctx);
84 if (!dup)
85 return NULL;
87 dup->n = band->n;
88 dup->coincident = isl_alloc_array(ctx, int, band->n);
89 if (band->n && !dup->coincident)
90 return isl_schedule_band_free(dup);
92 for (i = 0; i < band->n; ++i)
93 dup->coincident[i] = band->coincident[i];
94 dup->permutable = band->permutable;
96 dup->mupa = isl_multi_union_pw_aff_copy(band->mupa);
97 if (!dup->mupa)
98 return isl_schedule_band_free(dup);
100 return dup;
103 /* Return an isl_schedule_band that is equal to "band" and that has only
104 * a single reference.
106 __isl_give isl_schedule_band *isl_schedule_band_cow(
107 __isl_take isl_schedule_band *band)
109 if (!band)
110 return NULL;
112 if (band->ref == 1)
113 return band;
114 band->ref--;
115 return isl_schedule_band_dup(band);
118 /* Return a new reference to "band".
120 __isl_give isl_schedule_band *isl_schedule_band_copy(
121 __isl_keep isl_schedule_band *band)
123 if (!band)
124 return NULL;
126 band->ref++;
127 return band;
130 /* Free a reference to "band" and return NULL.
132 __isl_null isl_schedule_band *isl_schedule_band_free(
133 __isl_take isl_schedule_band *band)
135 if (!band)
136 return NULL;
138 if (--band->ref > 0)
139 return NULL;
141 isl_multi_union_pw_aff_free(band->mupa);
142 free(band->coincident);
143 free(band);
145 return NULL;
148 /* Are "band1" and "band2" obviously equal?
150 int isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band *band1,
151 __isl_keep isl_schedule_band *band2)
153 int i;
155 if (!band1 || !band2)
156 return -1;
157 if (band1 == band2)
158 return 1;
160 if (band1->n != band2->n)
161 return 0;
162 for (i = 0; i < band1->n; ++i)
163 if (band1->coincident[i] != band2->coincident[i])
164 return 0;
165 if (band1->permutable != band2->permutable)
166 return 0;
168 return isl_multi_union_pw_aff_plain_is_equal(band1->mupa, band2->mupa);
171 /* Return the number of scheduling dimensions in the band.
173 int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
175 return band ? band->n : 0;
178 /* Is the given scheduling dimension coincident within the band and
179 * with respect to the coincidence constraints?
181 int isl_schedule_band_member_get_coincident(__isl_keep isl_schedule_band *band,
182 int pos)
184 if (!band)
185 return -1;
187 if (pos < 0 || pos >= band->n)
188 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
189 "invalid member position", return -1);
191 return band->coincident[pos];
194 /* Mark the given scheduling dimension as being coincident or not
195 * according to "coincident".
197 __isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(
198 __isl_take isl_schedule_band *band, int pos, int coincident)
200 if (!band)
201 return NULL;
202 if (isl_schedule_band_member_get_coincident(band, pos) == coincident)
203 return band;
204 band = isl_schedule_band_cow(band);
205 if (!band)
206 return NULL;
208 if (pos < 0 || pos >= band->n)
209 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
210 "invalid member position",
211 isl_schedule_band_free(band));
213 band->coincident[pos] = coincident;
215 return band;
218 /* Is the schedule band mark permutable?
220 int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band)
222 if (!band)
223 return -1;
224 return band->permutable;
227 /* Mark the schedule band permutable or not according to "permutable"?
229 __isl_give isl_schedule_band *isl_schedule_band_set_permutable(
230 __isl_take isl_schedule_band *band, int permutable)
232 if (!band)
233 return NULL;
234 if (band->permutable == permutable)
235 return band;
236 band = isl_schedule_band_cow(band);
237 if (!band)
238 return NULL;
240 band->permutable = permutable;
242 return band;
245 /* Return the schedule space of the band.
247 __isl_give isl_space *isl_schedule_band_get_space(
248 __isl_keep isl_schedule_band *band)
250 if (!band)
251 return NULL;
252 return isl_multi_union_pw_aff_get_space(band->mupa);
255 /* Return the schedule of the band in isolation.
257 __isl_give isl_multi_union_pw_aff *isl_schedule_band_get_partial_schedule(
258 __isl_keep isl_schedule_band *band)
260 return band ? isl_multi_union_pw_aff_copy(band->mupa) : NULL;
263 /* Multiply the partial schedule of "band" with the factors in "mv".
264 * Replace the result by its greatest integer part to ensure
265 * that the schedule is always integral.
267 __isl_give isl_schedule_band *isl_schedule_band_scale(
268 __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
270 band = isl_schedule_band_cow(band);
271 if (!band || !mv)
272 goto error;
273 band->mupa = isl_multi_union_pw_aff_scale_multi_val(band->mupa, mv);
274 band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
275 if (!band->mupa)
276 return isl_schedule_band_free(band);
277 return band;
278 error:
279 isl_schedule_band_free(band);
280 isl_multi_val_free(mv);
281 return NULL;
284 /* Divide the partial schedule of "band" by the factors in "mv".
285 * Replace the result by its greatest integer part to ensure
286 * that the schedule is always integral.
288 __isl_give isl_schedule_band *isl_schedule_band_scale_down(
289 __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
291 band = isl_schedule_band_cow(band);
292 if (!band || !mv)
293 goto error;
294 band->mupa = isl_multi_union_pw_aff_scale_down_multi_val(band->mupa,
295 mv);
296 band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
297 if (!band->mupa)
298 return isl_schedule_band_free(band);
299 return band;
300 error:
301 isl_schedule_band_free(band);
302 isl_multi_val_free(mv);
303 return NULL;
306 /* Given the schedule of a band, construct the corresponding
307 * schedule for the tile loops based on the given tile sizes
308 * and return the result.
310 * If the scale tile loops options is set, then the tile loops
311 * are scaled by the tile sizes.
313 * That is replace each schedule dimension "i" by either
314 * "floor(i/s)" or "s * floor(i/s)".
316 static isl_multi_union_pw_aff *isl_multi_union_pw_aff_tile(
317 __isl_take isl_multi_union_pw_aff *sched,
318 __isl_take isl_multi_val *sizes)
320 isl_ctx *ctx;
321 int i, n;
322 isl_val *v;
323 int scale;
325 ctx = isl_multi_val_get_ctx(sizes);
326 scale = isl_options_get_tile_scale_tile_loops(ctx);
328 n = isl_multi_union_pw_aff_dim(sched, isl_dim_set);
329 for (i = 0; i < n; ++i) {
330 isl_union_pw_aff *upa;
332 upa = isl_multi_union_pw_aff_get_union_pw_aff(sched, i);
333 v = isl_multi_val_get_val(sizes, i);
335 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(v));
336 upa = isl_union_pw_aff_floor(upa);
337 if (scale)
338 upa = isl_union_pw_aff_scale_val(upa, isl_val_copy(v));
339 isl_val_free(v);
341 sched = isl_multi_union_pw_aff_set_union_pw_aff(sched, i, upa);
344 isl_multi_val_free(sizes);
345 return sched;
348 /* Replace "band" by a band corresponding to the tile loops of a tiling
349 * with the given tile sizes.
351 __isl_give isl_schedule_band *isl_schedule_band_tile(
352 __isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes)
354 band = isl_schedule_band_cow(band);
355 if (!band || !sizes)
356 goto error;
357 band->mupa = isl_multi_union_pw_aff_tile(band->mupa, sizes);
358 if (!band->mupa)
359 return isl_schedule_band_free(band);
360 return band;
361 error:
362 isl_schedule_band_free(band);
363 isl_multi_val_free(sizes);
364 return NULL;
367 /* Replace "band" by a band corresponding to the point loops of a tiling
368 * with the given tile sizes.
369 * "tile" is the corresponding tile loop band.
371 * If the shift point loops option is set, then the point loops
372 * are shifted to start at zero. That is, each schedule dimension "i"
373 * is replaced by "i - s * floor(i/s)".
374 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
375 * the tile band.
377 * Otherwise, the band is left untouched.
379 __isl_give isl_schedule_band *isl_schedule_band_point(
380 __isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
381 __isl_take isl_multi_val *sizes)
383 isl_ctx *ctx;
384 isl_multi_union_pw_aff *scaled;
386 if (!band || !sizes)
387 goto error;
389 ctx = isl_schedule_band_get_ctx(band);
390 if (!isl_options_get_tile_shift_point_loops(ctx)) {
391 isl_multi_val_free(sizes);
392 return band;
394 band = isl_schedule_band_cow(band);
395 if (!band)
396 goto error;
398 scaled = isl_schedule_band_get_partial_schedule(tile);
399 if (!isl_options_get_tile_scale_tile_loops(ctx))
400 scaled = isl_multi_union_pw_aff_scale_multi_val(scaled, sizes);
401 else
402 isl_multi_val_free(sizes);
403 band->mupa = isl_multi_union_pw_aff_sub(band->mupa, scaled);
404 if (!band->mupa)
405 return isl_schedule_band_free(band);
406 return band;
407 error:
408 isl_schedule_band_free(band);
409 isl_multi_val_free(sizes);
410 return NULL;
413 /* Drop the "n" dimensions starting at "pos" from "band".
415 * We apply the transformation even if "n" is zero to ensure consistent
416 * behavior with respect to changes in the schedule space.
418 __isl_give isl_schedule_band *isl_schedule_band_drop(
419 __isl_take isl_schedule_band *band, int pos, int n)
421 int i;
423 if (pos < 0 || n < 0 || pos + n > band->n)
424 isl_die(isl_schedule_band_get_ctx(band), isl_error_internal,
425 "range out of bounds",
426 return isl_schedule_band_free(band));
428 band = isl_schedule_band_cow(band);
429 if (!band)
430 return NULL;
432 band->mupa = isl_multi_union_pw_aff_drop_dims(band->mupa,
433 isl_dim_set, pos, n);
434 if (!band->mupa)
435 return isl_schedule_band_free(band);
437 for (i = pos + n; i < band->n; ++i)
438 band->coincident[i - n] = band->coincident[i];
440 band->n -= n;
442 return band;
445 /* Reset the user pointer on all identifiers of parameters and tuples
446 * in "band".
448 __isl_give isl_schedule_band *isl_schedule_band_reset_user(
449 __isl_take isl_schedule_band *band)
451 band = isl_schedule_band_cow(band);
452 if (!band)
453 return NULL;
455 band->mupa = isl_multi_union_pw_aff_reset_user(band->mupa);
456 if (!band->mupa)
457 return isl_schedule_band_free(band);
459 return band;
462 /* Align the parameters of "band" to those of "space".
464 __isl_give isl_schedule_band *isl_schedule_band_align_params(
465 __isl_take isl_schedule_band *band, __isl_take isl_space *space)
467 band = isl_schedule_band_cow(band);
468 if (!band || !space)
469 goto error;
471 band->mupa = isl_multi_union_pw_aff_align_params(band->mupa, space);
472 if (!band->mupa)
473 return isl_schedule_band_free(band);
475 return band;
476 error:
477 isl_space_free(space);
478 isl_schedule_band_free(band);
479 return NULL;
482 /* Compute the pullback of "band" by the function represented by "upma".
483 * In other words, plug in "upma" in the iteration domains of "band".
485 __isl_give isl_schedule_band *isl_schedule_band_pullback_union_pw_multi_aff(
486 __isl_take isl_schedule_band *band,
487 __isl_take isl_union_pw_multi_aff *upma)
489 band = isl_schedule_band_cow(band);
490 if (!band || !upma)
491 goto error;
493 band->mupa =
494 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band->mupa,
495 upma);
496 if (!band->mupa)
497 return isl_schedule_band_free(band);
499 return band;
500 error:
501 isl_union_pw_multi_aff_free(upma);
502 isl_schedule_band_free(band);
503 return NULL;
506 /* Compute the gist of "band" with respect to "context".
507 * In particular, compute the gist of the associated partial schedule.
509 __isl_give isl_schedule_band *isl_schedule_band_gist(
510 __isl_take isl_schedule_band *band, __isl_take isl_union_set *context)
512 if (!band || !context)
513 goto error;
514 if (band->n == 0) {
515 isl_union_set_free(context);
516 return band;
518 band = isl_schedule_band_cow(band);
519 if (!band)
520 goto error;
521 band->mupa = isl_multi_union_pw_aff_gist(band->mupa, context);
522 if (!band->mupa)
523 return isl_schedule_band_free(band);
524 return band;
525 error:
526 isl_union_set_free(context);
527 isl_schedule_band_free(band);
528 return NULL;