X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_band.c;h=43e9f016dc49de9ab95559da2a290c75dcb791c6;hb=63fb8a7f484648c3caa25351c8c94ac2395ec563;hp=e545a8a4dc3c7eafbe584da1595f501dd463a1a7;hpb=1a9c7afa1e0ca242fb348575afbf8e493deffbfd;p=platform%2Fupstream%2Fisl.git diff --git a/isl_band.c b/isl_band.c index e545a8a..43e9f01 100644 --- a/isl_band.c +++ b/isl_band.c @@ -1,16 +1,22 @@ /* * Copyright 2011 INRIA Saclay + * Copyright 2012-2013 Ecole Normale Superieure * * Use of this software is governed by the MIT license * * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, * 91893 Orsay, France + * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France */ #include #include -#include + +#undef BASE +#define BASE band + +#include isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band) { @@ -445,13 +451,26 @@ error: * a child band is created to refer to the point loops. * The children of this point loop band are the children * of the original band. + * + * If the scale tile loops option is set, then the tile loops + * are scaled by the tile sizes. If the shift point loops option is set, + * then the point loops are shifted to start at zero. + * In particular, these options affect the tile and point loop schedules + * as follows + * + * scale shift original tile point + * + * 0 0 i floor(i/s) i + * 1 0 i s * floor(i/s) i + * 0 1 i floor(i/s) i - s * floor(i/s) + * 1 1 i s * floor(i/s) i - s * floor(i/s) */ int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes) { isl_ctx *ctx; isl_band *child; isl_band_list *list = NULL; - isl_union_pw_multi_aff *sched; + isl_union_pw_multi_aff *sched = NULL, *child_sched = NULL; if (!band || !sizes) goto error; @@ -465,7 +484,17 @@ int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes) sched = isl_union_pw_multi_aff_copy(band->pma); sched = isl_union_pw_multi_aff_tile(sched, sizes); - if (!sched) + + child_sched = isl_union_pw_multi_aff_copy(child->pma); + if (isl_options_get_tile_shift_point_loops(ctx)) { + isl_union_pw_multi_aff *scaled; + scaled = isl_union_pw_multi_aff_copy(sched); + if (!isl_options_get_tile_scale_tile_loops(ctx)) + scaled = isl_union_pw_multi_aff_scale_vec(scaled, + isl_vec_copy(sizes)); + child_sched = isl_union_pw_multi_aff_sub(child_sched, scaled); + } + if (!sched || !child_sched) goto error; child->children = band->children; @@ -473,15 +502,132 @@ int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes) child->parent = band; isl_union_pw_multi_aff_free(band->pma); band->pma = sched; + isl_union_pw_multi_aff_free(child->pma); + child->pma = child_sched; isl_vec_free(sizes); return 0; error: + isl_union_pw_multi_aff_free(sched); + isl_union_pw_multi_aff_free(child_sched); isl_band_list_free(list); isl_vec_free(sizes); 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) {