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
);
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
43 __isl_give isl_schedule_band
*isl_schedule_band_from_multi_union_pw_aff(
44 __isl_take isl_multi_union_pw_aff
*mupa
)
47 isl_schedule_band
*band
;
49 mupa
= isl_multi_union_pw_aff_floor(mupa
);
52 ctx
= isl_multi_union_pw_aff_get_ctx(mupa
);
53 band
= isl_schedule_band_alloc(ctx
);
57 band
->n
= isl_multi_union_pw_aff_dim(mupa
, isl_dim_set
);
58 band
->coincident
= isl_calloc_array(ctx
, int, band
->n
);
61 if (band
->n
&& !band
->coincident
)
62 return isl_schedule_band_free(band
);
66 isl_multi_union_pw_aff_free(mupa
);
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
)
77 isl_schedule_band
*dup
;
82 ctx
= isl_schedule_band_get_ctx(band
);
83 dup
= isl_schedule_band_alloc(ctx
);
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
);
98 return isl_schedule_band_free(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
)
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
)
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
)
141 isl_multi_union_pw_aff_free(band
->mupa
);
142 free(band
->coincident
);
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
)
155 if (!band1
|| !band2
)
160 if (band1
->n
!= band2
->n
)
162 for (i
= 0; i
< band1
->n
; ++i
)
163 if (band1
->coincident
[i
] != band2
->coincident
[i
])
165 if (band1
->permutable
!= band2
->permutable
)
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
,
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
)
202 if (isl_schedule_band_member_get_coincident(band
, pos
) == coincident
)
204 band
= isl_schedule_band_cow(band
);
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
;
218 /* Is the schedule band mark permutable?
220 int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band
*band
)
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
)
234 if (band
->permutable
== permutable
)
236 band
= isl_schedule_band_cow(band
);
240 band
->permutable
= permutable
;
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
)
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
);
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
);
276 return isl_schedule_band_free(band
);
279 isl_schedule_band_free(band
);
280 isl_multi_val_free(mv
);
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
);
294 band
->mupa
= isl_multi_union_pw_aff_scale_down_multi_val(band
->mupa
,
296 band
->mupa
= isl_multi_union_pw_aff_floor(band
->mupa
);
298 return isl_schedule_band_free(band
);
301 isl_schedule_band_free(band
);
302 isl_multi_val_free(mv
);
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
)
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
);
338 upa
= isl_union_pw_aff_scale_val(upa
, isl_val_copy(v
));
341 sched
= isl_multi_union_pw_aff_set_union_pw_aff(sched
, i
, upa
);
344 isl_multi_val_free(sizes
);
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
);
357 band
->mupa
= isl_multi_union_pw_aff_tile(band
->mupa
, sizes
);
359 return isl_schedule_band_free(band
);
362 isl_schedule_band_free(band
);
363 isl_multi_val_free(sizes
);
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
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
)
384 isl_multi_union_pw_aff
*scaled
;
389 ctx
= isl_schedule_band_get_ctx(band
);
390 if (!isl_options_get_tile_shift_point_loops(ctx
)) {
391 isl_multi_val_free(sizes
);
394 band
= isl_schedule_band_cow(band
);
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
);
402 isl_multi_val_free(sizes
);
403 band
->mupa
= isl_multi_union_pw_aff_sub(band
->mupa
, scaled
);
405 return isl_schedule_band_free(band
);
408 isl_schedule_band_free(band
);
409 isl_multi_val_free(sizes
);
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
)
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
);
432 band
->mupa
= isl_multi_union_pw_aff_drop_dims(band
->mupa
,
433 isl_dim_set
, pos
, n
);
435 return isl_schedule_band_free(band
);
437 for (i
= pos
+ n
; i
< band
->n
; ++i
)
438 band
->coincident
[i
- n
] = band
->coincident
[i
];
445 /* Reset the user pointer on all identifiers of parameters and tuples
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
);
455 band
->mupa
= isl_multi_union_pw_aff_reset_user(band
->mupa
);
457 return isl_schedule_band_free(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
);
471 band
->mupa
= isl_multi_union_pw_aff_align_params(band
->mupa
, space
);
473 return isl_schedule_band_free(band
);
477 isl_space_free(space
);
478 isl_schedule_band_free(band
);
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
);
494 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band
->mupa
,
497 return isl_schedule_band_free(band
);
501 isl_union_pw_multi_aff_free(upma
);
502 isl_schedule_band_free(band
);
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
)
515 isl_union_set_free(context
);
518 band
= isl_schedule_band_cow(band
);
521 band
->mupa
= isl_multi_union_pw_aff_gist(band
->mupa
, context
);
523 return isl_schedule_band_free(band
);
526 isl_union_set_free(context
);
527 isl_schedule_band_free(band
);