2 * Copyright 2013-2014 Ecole Normale Superieure
4 * Use of this software is governed by the MIT license
6 * Written by Sven Verdoolaege,
7 * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
10 #include <isl/schedule_node.h>
11 #include <isl_schedule_band.h>
12 #include <isl_schedule_private.h>
14 isl_ctx
*isl_schedule_band_get_ctx(__isl_keep isl_schedule_band
*band
)
16 return band
? isl_multi_union_pw_aff_get_ctx(band
->mupa
) : NULL
;
19 /* Return a new uninitialized isl_schedule_band.
21 static __isl_give isl_schedule_band
*isl_schedule_band_alloc(isl_ctx
*ctx
)
23 isl_schedule_band
*band
;
25 band
= isl_calloc_type(ctx
, isl_schedule_band
);
34 /* Return a new isl_schedule_band with partial schedule "mupa".
35 * First replace "mupa" by its greatest integer part to ensure
36 * that the schedule is always integral.
37 * The band is not marked permutable and the dimensions are not
40 __isl_give isl_schedule_band
*isl_schedule_band_from_multi_union_pw_aff(
41 __isl_take isl_multi_union_pw_aff
*mupa
)
44 isl_schedule_band
*band
;
46 mupa
= isl_multi_union_pw_aff_floor(mupa
);
49 ctx
= isl_multi_union_pw_aff_get_ctx(mupa
);
50 band
= isl_schedule_band_alloc(ctx
);
54 band
->n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
55 band
->coincident
= isl_calloc_array(ctx
, int, band
->n
);
58 if (band
->n
&& !band
->coincident
)
59 return isl_schedule_band_free(band
);
63 isl_multi_union_pw_aff_free(mupa
);
67 /* Create a duplicate of the given isl_schedule_band.
69 __isl_give isl_schedule_band
*isl_schedule_band_dup(
70 __isl_keep isl_schedule_band
*band
)
74 isl_schedule_band
*dup
;
79 ctx
= isl_schedule_band_get_ctx(band
);
80 dup
= isl_schedule_band_alloc(ctx
);
85 dup
->coincident
= isl_alloc_array(ctx
, int, band
->n
);
86 if (band
->n
&& !dup
->coincident
)
87 return isl_schedule_band_free(dup
);
89 for (i
= 0; i
< band
->n
; ++i
)
90 dup
->coincident
[i
] = band
->coincident
[i
];
91 dup
->permutable
= band
->permutable
;
93 dup
->mupa
= isl_multi_union_pw_aff_copy(band
->mupa
);
95 return isl_schedule_band_free(dup
);
100 /* Return an isl_schedule_band that is equal to "band" and that has only
101 * a single reference.
103 __isl_give isl_schedule_band
*isl_schedule_band_cow(
104 __isl_take isl_schedule_band
*band
)
112 return isl_schedule_band_dup(band
);
115 /* Return a new reference to "band".
117 __isl_give isl_schedule_band
*isl_schedule_band_copy(
118 __isl_keep isl_schedule_band
*band
)
127 /* Free a reference to "band" and return NULL.
129 __isl_null isl_schedule_band
*isl_schedule_band_free(
130 __isl_take isl_schedule_band
*band
)
138 isl_multi_union_pw_aff_free(band
->mupa
);
139 free(band
->coincident
);
145 /* Are "band1" and "band2" obviously equal?
147 int isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band
*band1
,
148 __isl_keep isl_schedule_band
*band2
)
152 if (!band1
|| !band2
)
157 if (band1
->n
!= band2
->n
)
159 for (i
= 0; i
< band1
->n
; ++i
)
160 if (band1
->coincident
[i
] != band2
->coincident
[i
])
162 if (band1
->permutable
!= band2
->permutable
)
165 return isl_multi_union_pw_aff_plain_is_equal(band1
->mupa
, band2
->mupa
);
168 /* Return the number of scheduling dimensions in the band.
170 int isl_schedule_band_n_member(__isl_keep isl_schedule_band
*band
)
172 return band
? band
->n
: 0;
175 /* Is the given scheduling dimension coincident within the band and
176 * with respect to the coincidence constraints?
178 int isl_schedule_band_member_get_coincident(__isl_keep isl_schedule_band
*band
,
184 if (pos
< 0 || pos
>= band
->n
)
185 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
186 "invalid member position", return -1);
188 return band
->coincident
[pos
];
191 /* Mark the given scheduling dimension as being coincident or not
192 * according to "coincident".
194 __isl_give isl_schedule_band
*isl_schedule_band_member_set_coincident(
195 __isl_take isl_schedule_band
*band
, int pos
, int coincident
)
199 if (isl_schedule_band_member_get_coincident(band
, pos
) == coincident
)
201 band
= isl_schedule_band_cow(band
);
205 if (pos
< 0 || pos
>= band
->n
)
206 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
207 "invalid member position",
208 isl_schedule_band_free(band
));
210 band
->coincident
[pos
] = coincident
;
215 /* Is the schedule band mark permutable?
217 int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band
*band
)
221 return band
->permutable
;
224 /* Mark the schedule band permutable or not according to "permutable"?
226 __isl_give isl_schedule_band
*isl_schedule_band_set_permutable(
227 __isl_take isl_schedule_band
*band
, int permutable
)
231 if (band
->permutable
== permutable
)
233 band
= isl_schedule_band_cow(band
);
237 band
->permutable
= permutable
;
242 /* Return the schedule space of the band.
244 __isl_give isl_space
*isl_schedule_band_get_space(
245 __isl_keep isl_schedule_band
*band
)
249 return isl_multi_union_pw_aff_get_space(band
->mupa
);
252 /* Return the schedule of the band in isolation.
254 __isl_give isl_multi_union_pw_aff
*isl_schedule_band_get_partial_schedule(
255 __isl_keep isl_schedule_band
*band
)
257 return band
? isl_multi_union_pw_aff_copy(band
->mupa
) : NULL
;
260 /* Multiply the partial schedule of "band" with the factors in "mv".
261 * Replace the result by its greatest integer part to ensure
262 * that the schedule is always integral.
264 __isl_give isl_schedule_band
*isl_schedule_band_scale(
265 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
267 band
= isl_schedule_band_cow(band
);
270 band
->mupa
= isl_multi_union_pw_aff_scale_multi_val(band
->mupa
, mv
);
271 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
273 return isl_schedule_band_free(band
);
276 isl_schedule_band_free(band
);
277 isl_multi_val_free(mv
);
281 /* Divide the partial schedule of "band" by the factors in "mv".
282 * Replace the result by its greatest integer part to ensure
283 * that the schedule is always integral.
285 __isl_give isl_schedule_band
*isl_schedule_band_scale_down(
286 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
288 band
= isl_schedule_band_cow(band
);
291 band
->mupa
= isl_multi_union_pw_aff_scale_down_multi_val(band
->mupa
,
293 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
295 return isl_schedule_band_free(band
);
298 isl_schedule_band_free(band
);
299 isl_multi_val_free(mv
);
303 /* Given the schedule of a band, construct the corresponding
304 * schedule for the tile loops based on the given tile sizes
305 * and return the result.
307 * If the scale tile loops options is set, then the tile loops
308 * are scaled by the tile sizes.
310 * That is replace each schedule dimension "i" by either
311 * "floor(i/s)" or "s * floor(i/s)".
313 static isl_multi_union_pw_aff
*isl_multi_union_pw_aff_tile(
314 __isl_take isl_multi_union_pw_aff
*sched
,
315 __isl_take isl_multi_val
*sizes
)
322 ctx
= isl_multi_val_get_ctx(sizes
);
323 scale
= isl_options_get_tile_scale_tile_loops(ctx
);
325 n
= isl_multi_union_pw_aff_dim(sched
, isl_dim_set
);
326 for (i
= 0; i
< n
; ++i
) {
327 isl_union_pw_aff
*upa
;
329 upa
= isl_multi_union_pw_aff_get_union_pw_aff(sched
, i
);
330 v
= isl_multi_val_get_val(sizes
, i
);
332 upa
= isl_union_pw_aff_scale_down_val(upa
, isl_val_copy(v
));
333 upa
= isl_union_pw_aff_floor(upa
);
335 upa
= isl_union_pw_aff_scale_val(upa
, isl_val_copy(v
));
338 sched
= isl_multi_union_pw_aff_set_union_pw_aff(sched
, i
, upa
);
341 isl_multi_val_free(sizes
);
345 /* Replace "band" by a band corresponding to the tile loops of a tiling
346 * with the given tile sizes.
348 __isl_give isl_schedule_band
*isl_schedule_band_tile(
349 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*sizes
)
351 band
= isl_schedule_band_cow(band
);
354 band
->mupa
= isl_multi_union_pw_aff_tile(band
->mupa
, sizes
);
356 return isl_schedule_band_free(band
);
359 isl_schedule_band_free(band
);
360 isl_multi_val_free(sizes
);
364 /* Replace "band" by a band corresponding to the point loops of a tiling
365 * with the given tile sizes.
366 * "tile" is the corresponding tile loop band.
368 * If the shift point loops option is set, then the point loops
369 * are shifted to start at zero. That is, each schedule dimension "i"
370 * is replaced by "i - s * floor(i/s)".
371 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
374 * Otherwise, the band is left untouched.
376 __isl_give isl_schedule_band
*isl_schedule_band_point(
377 __isl_take isl_schedule_band
*band
, __isl_keep isl_schedule_band
*tile
,
378 __isl_take isl_multi_val
*sizes
)
381 isl_multi_union_pw_aff
*scaled
;
386 ctx
= isl_schedule_band_get_ctx(band
);
387 if (!isl_options_get_tile_shift_point_loops(ctx
)) {
388 isl_multi_val_free(sizes
);
391 band
= isl_schedule_band_cow(band
);
395 scaled
= isl_schedule_band_get_partial_schedule(tile
);
396 if (!isl_options_get_tile_scale_tile_loops(ctx
))
397 scaled
= isl_multi_union_pw_aff_scale_multi_val(scaled
, sizes
);
399 isl_multi_val_free(sizes
);
400 band
->mupa
= isl_multi_union_pw_aff_sub(band
->mupa
, scaled
);
402 return isl_schedule_band_free(band
);
405 isl_schedule_band_free(band
);
406 isl_multi_val_free(sizes
);
410 /* Drop the "n" dimensions starting at "pos" from "band".
412 * We apply the transformation even if "n" is zero to ensure consistent
413 * behavior with respect to changes in the schedule space.
415 __isl_give isl_schedule_band
*isl_schedule_band_drop(
416 __isl_take isl_schedule_band
*band
, int pos
, int n
)
420 if (pos
< 0 || n
< 0 || pos
+ n
> band
->n
)
421 isl_die(isl_schedule_band_get_ctx(band
), isl_error_internal
,
422 "range out of bounds",
423 return isl_schedule_band_free(band
));
425 band
= isl_schedule_band_cow(band
);
429 band
->mupa
= isl_multi_union_pw_aff_drop_dims(band
->mupa
,
430 isl_dim_set
, pos
, n
);
432 return isl_schedule_band_free(band
);
434 for (i
= pos
+ n
; i
< band
->n
; ++i
)
435 band
->coincident
[i
- n
] = band
->coincident
[i
];
442 /* Reset the user pointer on all identifiers of parameters and tuples
445 __isl_give isl_schedule_band
*isl_schedule_band_reset_user(
446 __isl_take isl_schedule_band
*band
)
448 band
= isl_schedule_band_cow(band
);
452 band
->mupa
= isl_multi_union_pw_aff_reset_user(band
->mupa
);
454 return isl_schedule_band_free(band
);