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 /* Return the number of scheduling dimensions in the band.
147 int isl_schedule_band_n_member(__isl_keep isl_schedule_band
*band
)
149 return band
? band
->n
: 0;
152 /* Is the given scheduling dimension coincident within the band and
153 * with respect to the coincidence constraints?
155 int isl_schedule_band_member_get_coincident(__isl_keep isl_schedule_band
*band
,
161 if (pos
< 0 || pos
>= band
->n
)
162 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
163 "invalid member position", return -1);
165 return band
->coincident
[pos
];
168 /* Mark the given scheduling dimension as being coincident or not
169 * according to "coincident".
171 __isl_give isl_schedule_band
*isl_schedule_band_member_set_coincident(
172 __isl_take isl_schedule_band
*band
, int pos
, int coincident
)
176 if (isl_schedule_band_member_get_coincident(band
, pos
) == coincident
)
178 band
= isl_schedule_band_cow(band
);
182 if (pos
< 0 || pos
>= band
->n
)
183 isl_die(isl_schedule_band_get_ctx(band
), isl_error_invalid
,
184 "invalid member position",
185 isl_schedule_band_free(band
));
187 band
->coincident
[pos
] = coincident
;
192 /* Is the schedule band mark permutable?
194 int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band
*band
)
198 return band
->permutable
;
201 /* Mark the schedule band permutable or not according to "permutable"?
203 __isl_give isl_schedule_band
*isl_schedule_band_set_permutable(
204 __isl_take isl_schedule_band
*band
, int permutable
)
208 if (band
->permutable
== permutable
)
210 band
= isl_schedule_band_cow(band
);
214 band
->permutable
= permutable
;
219 /* Return the schedule space of the band.
221 __isl_give isl_space
*isl_schedule_band_get_space(
222 __isl_keep isl_schedule_band
*band
)
226 return isl_multi_union_pw_aff_get_space(band
->mupa
);
229 /* Return the schedule of the band in isolation.
231 __isl_give isl_multi_union_pw_aff
*isl_schedule_band_get_partial_schedule(
232 __isl_keep isl_schedule_band
*band
)
234 return band
? isl_multi_union_pw_aff_copy(band
->mupa
) : NULL
;
237 /* Multiply the partial schedule of "band" with the factors in "mv".
238 * Replace the result by its greatest integer part to ensure
239 * that the schedule is always integral.
241 __isl_give isl_schedule_band
*isl_schedule_band_scale(
242 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
244 band
= isl_schedule_band_cow(band
);
247 band
->mupa
= isl_multi_union_pw_aff_scale_multi_val(band
->mupa
, mv
);
248 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
250 return isl_schedule_band_free(band
);
253 isl_schedule_band_free(band
);
254 isl_multi_val_free(mv
);
258 /* Divide the partial schedule of "band" by the factors in "mv".
259 * Replace the result by its greatest integer part to ensure
260 * that the schedule is always integral.
262 __isl_give isl_schedule_band
*isl_schedule_band_scale_down(
263 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*mv
)
265 band
= isl_schedule_band_cow(band
);
268 band
->mupa
= isl_multi_union_pw_aff_scale_down_multi_val(band
->mupa
,
270 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
272 return isl_schedule_band_free(band
);
275 isl_schedule_band_free(band
);
276 isl_multi_val_free(mv
);
280 /* Given the schedule of a band, construct the corresponding
281 * schedule for the tile loops based on the given tile sizes
282 * and return the result.
284 * If the scale tile loops options is set, then the tile loops
285 * are scaled by the tile sizes.
287 * That is replace each schedule dimension "i" by either
288 * "floor(i/s)" or "s * floor(i/s)".
290 static isl_multi_union_pw_aff
*isl_multi_union_pw_aff_tile(
291 __isl_take isl_multi_union_pw_aff
*sched
,
292 __isl_take isl_multi_val
*sizes
)
299 ctx
= isl_multi_val_get_ctx(sizes
);
300 scale
= isl_options_get_tile_scale_tile_loops(ctx
);
302 n
= isl_multi_union_pw_aff_dim(sched
, isl_dim_set
);
303 for (i
= 0; i
< n
; ++i
) {
304 isl_union_pw_aff
*upa
;
306 upa
= isl_multi_union_pw_aff_get_union_pw_aff(sched
, i
);
307 v
= isl_multi_val_get_val(sizes
, i
);
309 upa
= isl_union_pw_aff_scale_down_val(upa
, isl_val_copy(v
));
310 upa
= isl_union_pw_aff_floor(upa
);
312 upa
= isl_union_pw_aff_scale_val(upa
, isl_val_copy(v
));
315 sched
= isl_multi_union_pw_aff_set_union_pw_aff(sched
, i
, upa
);
318 isl_multi_val_free(sizes
);
322 /* Replace "band" by a band corresponding to the tile loops of a tiling
323 * with the given tile sizes.
325 __isl_give isl_schedule_band
*isl_schedule_band_tile(
326 __isl_take isl_schedule_band
*band
, __isl_take isl_multi_val
*sizes
)
328 band
= isl_schedule_band_cow(band
);
331 band
->mupa
= isl_multi_union_pw_aff_tile(band
->mupa
, sizes
);
333 return isl_schedule_band_free(band
);
336 isl_schedule_band_free(band
);
337 isl_multi_val_free(sizes
);
341 /* Replace "band" by a band corresponding to the point loops of a tiling
342 * with the given tile sizes.
343 * "tile" is the corresponding tile loop band.
345 * If the shift point loops option is set, then the point loops
346 * are shifted to start at zero. That is, each schedule dimension "i"
347 * is replaced by "i - s * floor(i/s)".
348 * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
351 * Otherwise, the band is left untouched.
353 __isl_give isl_schedule_band
*isl_schedule_band_point(
354 __isl_take isl_schedule_band
*band
, __isl_keep isl_schedule_band
*tile
,
355 __isl_take isl_multi_val
*sizes
)
358 isl_multi_union_pw_aff
*scaled
;
363 ctx
= isl_schedule_band_get_ctx(band
);
364 if (!isl_options_get_tile_shift_point_loops(ctx
)) {
365 isl_multi_val_free(sizes
);
368 band
= isl_schedule_band_cow(band
);
372 scaled
= isl_schedule_band_get_partial_schedule(tile
);
373 if (!isl_options_get_tile_scale_tile_loops(ctx
))
374 scaled
= isl_multi_union_pw_aff_scale_multi_val(scaled
, sizes
);
376 isl_multi_val_free(sizes
);
377 band
->mupa
= isl_multi_union_pw_aff_sub(band
->mupa
, scaled
);
379 return isl_schedule_band_free(band
);
382 isl_schedule_band_free(band
);
383 isl_multi_val_free(sizes
);
387 /* Drop the "n" dimensions starting at "pos" from "band".
389 * We apply the transformation even if "n" is zero to ensure consistent
390 * behavior with respect to changes in the schedule space.
392 __isl_give isl_schedule_band
*isl_schedule_band_drop(
393 __isl_take isl_schedule_band
*band
, int pos
, int n
)
397 if (pos
< 0 || n
< 0 || pos
+ n
> band
->n
)
398 isl_die(isl_schedule_band_get_ctx(band
), isl_error_internal
,
399 "range out of bounds",
400 return isl_schedule_band_free(band
));
402 band
= isl_schedule_band_cow(band
);
406 band
->mupa
= isl_multi_union_pw_aff_drop_dims(band
->mupa
,
407 isl_dim_set
, pos
, n
);
409 return isl_schedule_band_free(band
);
411 for (i
= pos
+ n
; i
< band
->n
; ++i
)
412 band
->coincident
[i
- n
] = band
->coincident
[i
];