From ea08f12a81926bb50c39f3d60f3c9b3ae2fa276d Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Thu, 14 Feb 2013 21:25:58 +0100 Subject: [PATCH] add isl_band_split Signed-off-by: Sven Verdoolaege --- doc/user.pod | 7 ++++ include/isl/band.h | 1 + isl_band.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) diff --git a/doc/user.pod b/doc/user.pod index f786df5c..2893bc88 100644 --- a/doc/user.pod +++ b/doc/user.pod @@ -5128,6 +5128,13 @@ loops iterators should be scaled by the tile sizes. If the C option is set, then the point loops are shifted to start at zero. +A band can be split into two nested bands using the following function. + + int isl_band_split(__isl_keep isl_band *band, int pos); + +The resulting outer band contains the first C dimensions of C +while the inner band contains the remaining dimensions. + A representation of the band can be printed using #include diff --git a/include/isl/band.h b/include/isl/band.h index b0809a80..a94937b0 100644 --- a/include/isl/band.h +++ b/include/isl/band.h @@ -35,6 +35,7 @@ int isl_options_set_tile_shift_point_loops(isl_ctx *ctx, int val); int isl_options_get_tile_shift_point_loops(isl_ctx *ctx); int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes); +int isl_band_split(__isl_keep isl_band *band, int pos); int isl_band_n_member(__isl_keep isl_band *band); int isl_band_member_is_zero_distance(__isl_keep isl_band *band, int pos); diff --git a/isl_band.c b/isl_band.c index 0f8f6c41..18572d02 100644 --- a/isl_band.c +++ b/isl_band.c @@ -511,6 +511,119 @@ error: return -1; } +/* Internal data structure used inside isl_union_pw_multi_aff_drop. + * + * "pos" is the position of the first dimension to drop. + * "n" is the number of dimensions to drop. + * "res" accumulates the result. + */ +struct isl_union_pw_multi_aff_drop_data { + int pos; + int n; + isl_union_pw_multi_aff *res; +}; + +/* Drop the data->n output dimensions starting at data->pos from "pma" + * and add the result to data->res. + */ +static int pw_multi_aff_drop(__isl_take isl_pw_multi_aff *pma, void *user) +{ + struct isl_union_pw_multi_aff_drop_data *data = user; + + pma = isl_pw_multi_aff_drop_dims(pma, isl_dim_out, data->pos, data->n); + + data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma); + if (!data->res) + return -1; + + return 0; +} + +/* Drop the "n" output dimensions starting at "pos" from "sched". + */ +static isl_union_pw_multi_aff *isl_union_pw_multi_aff_drop( + __isl_take isl_union_pw_multi_aff *sched, int pos, int n) +{ + isl_space *space; + struct isl_union_pw_multi_aff_drop_data data = { pos, n }; + + space = isl_union_pw_multi_aff_get_space(sched); + data.res = isl_union_pw_multi_aff_empty(space); + + if (isl_union_pw_multi_aff_foreach_pw_multi_aff(sched, + &pw_multi_aff_drop, &data) < 0) + data.res = isl_union_pw_multi_aff_free(data.res); + + isl_union_pw_multi_aff_free(sched); + return data.res; +} + +/* Drop the "n" dimensions starting at "pos" from "band". + */ +static int isl_band_drop(__isl_keep isl_band *band, int pos, int n) +{ + int i; + isl_union_pw_multi_aff *sched; + + if (!band) + return -1; + if (n == 0) + return 0; + + sched = isl_union_pw_multi_aff_copy(band->pma); + sched = isl_union_pw_multi_aff_drop(sched, pos, n); + if (!sched) + return -1; + + isl_union_pw_multi_aff_free(band->pma); + band->pma = sched; + + for (i = pos + n; i < band->n; ++i) + band->zero[i - n] = band->zero[i]; + + band->n -= n; + + return 0; +} + +/* Split the given band into two nested bands, one with the first "pos" + * dimensions of "band" and one with the remaining band->n - pos dimensions. + */ +int isl_band_split(__isl_keep isl_band *band, int pos) +{ + isl_ctx *ctx; + isl_band *child; + isl_band_list *list; + + if (!band) + return -1; + + ctx = isl_band_get_ctx(band); + + if (pos < 0 || pos > band->n) + isl_die(ctx, isl_error_invalid, "position out of bounds", + return -1); + + child = isl_band_dup(band); + if (isl_band_drop(child, 0, pos) < 0) + child = isl_band_free(child); + list = isl_band_list_alloc(ctx, 1); + list = isl_band_list_add(list, child); + if (!list) + return -1; + + if (isl_band_drop(band, pos, band->n - pos) < 0) { + isl_band_list_free(list); + return -1; + } + + child->children = band->children; + band->children = list; + child->parent = band; + + return 0; +} + __isl_give isl_printer *isl_printer_print_band(__isl_take isl_printer *p, __isl_keep isl_band *band) { -- 2.11.4.GIT