X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_band.c;h=b484e82ca80b6a74c0f500a4b5202402ebe8d8bb;hb=3d9f65131f9da197bca3a30eccf3a70107f50f03;hp=318a7c1c232ba1ba6b8a9910a8cff39b51afc3cf;hpb=056289f285e62c52cc59ee826172e4d3092ef3fe;p=platform%2Fupstream%2Fisl.git diff --git a/isl_band.c b/isl_band.c index 318a7c1..b484e82 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) { @@ -359,27 +365,26 @@ static int multi_aff_tile(__isl_take isl_set *set, struct isl_band_tile_data *data = user; isl_pw_multi_aff *pma; int i, n; - isl_int v; + isl_val *v; n = isl_multi_aff_dim(ma, isl_dim_out); if (isl_vec_size(data->sizes) < n) n = isl_vec_size(data->sizes); - isl_int_init(v); for (i = 0; i < n; ++i) { isl_aff *aff; aff = isl_multi_aff_get_aff(ma, i); - isl_vec_get_element(data->sizes, i, &v); + v = isl_vec_get_element_val(data->sizes, i); - aff = isl_aff_scale_down(aff, v); + aff = isl_aff_scale_down_val(aff, isl_val_copy(v)); aff = isl_aff_floor(aff); if (data->scale) - aff = isl_aff_scale(aff, v); + aff = isl_aff_scale_val(aff, isl_val_copy(v)); + isl_val_free(v); ma = isl_multi_aff_set_aff(ma, i, aff); } - isl_int_clear(v); pma = isl_pw_multi_aff_alloc(set, ma); data->tiled = isl_pw_multi_aff_union_add(data->tiled, pma); @@ -445,13 +450,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,22 +483,150 @@ 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; band->children = list; + 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) {