X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_local_space.c;h=a57fff1aa24b681ae47c6a4850b2b4407c2f246e;hb=9a647aabdb174e9b7e0f53d3bb2ec515bc63d76b;hp=e051465836c6514cdb8319f182fc1f261485ca74;hpb=d07eed3bf4d0e290118588ca80997a8035eaeb21;p=platform%2Fupstream%2Fisl.git diff --git a/isl_local_space.c b/isl_local_space.c index e051465..a57fff1 100644 --- a/isl_local_space.c +++ b/isl_local_space.c @@ -13,6 +13,7 @@ #include #include #include +#include #include isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls) @@ -113,6 +114,13 @@ void *isl_local_space_free(__isl_take isl_local_space *ls) return NULL; } +/* Is the local space that of a set? + */ +int isl_local_space_is_set(__isl_keep isl_local_space *ls) +{ + return ls ? isl_space_is_set(ls->dim) : -1; +} + /* Return true if the two local spaces are identical, with identical * expressions for the integer divisions. */ @@ -173,10 +181,10 @@ const char *isl_local_space_get_dim_name(__isl_keep isl_local_space *ls, return ls ? isl_space_get_dim_name(ls->dim, type, pos) : NULL; } -__isl_give isl_div *isl_local_space_get_div(__isl_keep isl_local_space *ls, +__isl_give isl_aff *isl_local_space_get_div(__isl_keep isl_local_space *ls, int pos) { - isl_basic_map *bmap; + isl_aff *aff; if (!ls) return NULL; @@ -189,8 +197,11 @@ __isl_give isl_div *isl_local_space_get_div(__isl_keep isl_local_space *ls, isl_die(isl_local_space_get_ctx(ls), isl_error_invalid, "expression of div unknown", return NULL); - bmap = isl_basic_map_from_local_space(isl_local_space_copy(ls)); - return isl_basic_map_div(bmap, pos); + aff = isl_aff_alloc(isl_local_space_copy(ls)); + if (!aff) + return NULL; + isl_seq_cpy(aff->v->el, ls->div->row[pos], aff->v->size); + return aff; } __isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls) @@ -215,6 +226,20 @@ __isl_give isl_local_space *isl_local_space_set_dim_name( return ls; } +__isl_give isl_local_space *isl_local_space_set_dim_id( + __isl_take isl_local_space *ls, + enum isl_dim_type type, unsigned pos, __isl_take isl_id *id) +{ + ls = isl_local_space_cow(ls); + if (!ls) + return isl_id_free(id); + ls->dim = isl_space_set_dim_id(ls->dim, type, pos, id); + if (!ls->dim) + return isl_local_space_free(ls); + + return ls; +} + __isl_give isl_local_space *isl_local_space_reset_space( __isl_take isl_local_space *ls, __isl_take isl_space *dim) { @@ -426,6 +451,59 @@ __isl_give isl_mat *isl_merge_divs(__isl_keep isl_mat *div1, return div; } +/* Construct a local space that contains all the divs in either + * "ls1" or "ls2". + */ +__isl_give isl_local_space *isl_local_space_intersect( + __isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2) +{ + isl_ctx *ctx; + int *exp1 = NULL; + int *exp2 = NULL; + isl_mat *div; + + if (!ls1 || !ls2) + goto error; + + ctx = isl_local_space_get_ctx(ls1); + if (!isl_space_is_equal(ls1->dim, ls2->dim)) + isl_die(ctx, isl_error_invalid, + "spaces should be identical", goto error); + + if (ls2->div->n_row == 0) { + isl_local_space_free(ls2); + return ls1; + } + + if (ls1->div->n_row == 0) { + isl_local_space_free(ls1); + return ls2; + } + + exp1 = isl_alloc_array(ctx, int, ls1->div->n_row); + exp2 = isl_alloc_array(ctx, int, ls2->div->n_row); + if (!exp1 || !exp2) + goto error; + + div = isl_merge_divs(ls1->div, ls2->div, exp1, exp2); + if (!div) + goto error; + + free(exp1); + free(exp2); + isl_local_space_free(ls2); + isl_mat_free(ls1->div); + ls1->div = div; + + return ls1; +error: + free(exp1); + free(exp2); + isl_local_space_free(ls1); + isl_local_space_free(ls2); + return NULL; +} + int isl_local_space_divs_known(__isl_keep isl_local_space *ls) { int i; @@ -440,6 +518,35 @@ int isl_local_space_divs_known(__isl_keep isl_local_space *ls) return 1; } +__isl_give isl_local_space *isl_local_space_domain( + __isl_take isl_local_space *ls) +{ + ls = isl_local_space_drop_dims(ls, isl_dim_out, + 0, isl_local_space_dim(ls, isl_dim_out)); + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + ls->dim = isl_space_domain(ls->dim); + if (!ls->dim) + return isl_local_space_free(ls); + return ls; +} + +__isl_give isl_local_space *isl_local_space_range( + __isl_take isl_local_space *ls) +{ + ls = isl_local_space_drop_dims(ls, isl_dim_in, + 0, isl_local_space_dim(ls, isl_dim_in)); + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + + ls->dim = isl_space_range(ls->dim); + if (!ls->dim) + return isl_local_space_free(ls); + return ls; +} + /* Construct a local space for a map that has the given local * space as domain and that has a zero-dimensional range. */ @@ -531,6 +638,60 @@ error: return NULL; } +/* Plug in "subs" for dimension "type", "pos" in the integer divisions + * of "ls". + * + * Let i be the dimension to replace and let "subs" be of the form + * + * f/d + * + * Any integer division with a non-zero coefficient for i, + * + * floor((a i + g)/m) + * + * is replaced by + * + * floor((a f + d g)/(m d)) + */ +__isl_give isl_local_space *isl_local_space_substitute( + __isl_take isl_local_space *ls, + enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs) +{ + int i; + isl_int v; + + ls = isl_local_space_cow(ls); + if (!ls || !subs) + return isl_local_space_free(ls); + + if (!isl_space_is_equal(ls->dim, subs->ls->dim)) + isl_die(isl_local_space_get_ctx(ls), isl_error_invalid, + "spaces don't match", return isl_local_space_free(ls)); + if (isl_local_space_dim(subs->ls, isl_dim_div) != 0) + isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported, + "cannot handle divs yet", + return isl_local_space_free(ls)); + + pos += isl_local_space_offset(ls, type); + + isl_int_init(v); + for (i = 0; i < ls->div->n_row; ++i) { + if (isl_int_is_zero(ls->div->row[i][1 + pos])) + continue; + isl_int_set(v, ls->div->row[i][1 + pos]); + isl_int_set_si(ls->div->row[i][1 + pos], 0); + isl_seq_combine(ls->div->row[i] + 1, + subs->v->el[0], ls->div->row[i] + 1, + v, subs->v->el + 1, subs->v->size - 1); + isl_int_mul(ls->div->row[i][0], + ls->div->row[i][0], subs->v->el[0]); + normalize_div(ls, i); + } + isl_int_clear(v); + + return ls; +} + int isl_local_space_is_named_or_nested(__isl_keep isl_local_space *ls, enum isl_dim_type type) { @@ -658,3 +819,79 @@ int isl_local_space_is_div_constraint(__isl_keep isl_local_space *ls, return 1; } + +/* + * Set active[i] to 1 if the dimension at position i is involved + * in the linear expression l. + */ +int *isl_local_space_get_active(__isl_keep isl_local_space *ls, isl_int *l) +{ + int i, j; + isl_ctx *ctx; + int *active = NULL; + unsigned total; + unsigned offset; + + ctx = isl_local_space_get_ctx(ls); + total = isl_local_space_dim(ls, isl_dim_all); + active = isl_calloc_array(ctx, int, total); + if (!active) + return NULL; + + for (i = 0; i < total; ++i) + active[i] = !isl_int_is_zero(l[i]); + + offset = isl_local_space_offset(ls, isl_dim_div) - 1; + for (i = ls->div->n_row - 1; i >= 0; --i) { + if (!active[offset + i]) + continue; + for (j = 0; j < total; ++j) + active[j] |= !isl_int_is_zero(ls->div->row[i][2 + j]); + } + + return active; +} + +/* Given a local space "ls" of a set, create a local space + * for the lift of the set. In particular, the result + * is of the form [dim -> local[..]], with ls->div->n_row variables in the + * range of the wrapped map. + */ +__isl_give isl_local_space *isl_local_space_lift( + __isl_take isl_local_space *ls) +{ + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + + ls->dim = isl_space_lift(ls->dim, ls->div->n_row); + ls->div = isl_mat_drop_rows(ls->div, 0, ls->div->n_row); + if (!ls->dim || !ls->div) + return isl_local_space_free(ls); + + return ls; +} + +/* Construct a basic map that maps a set living in local space "ls" + * to the corresponding lifted local space. + */ +__isl_give isl_basic_map *isl_local_space_lifting( + __isl_take isl_local_space *ls) +{ + isl_basic_map *lifting; + isl_basic_set *bset; + + if (!ls) + return NULL; + if (!isl_local_space_is_set(ls)) + isl_die(isl_local_space_get_ctx(ls), isl_error_invalid, + "lifting only defined on set spaces", + return isl_local_space_free(ls)); + + bset = isl_basic_set_from_local_space(ls); + lifting = isl_basic_set_unwrap(isl_basic_set_lift(bset)); + lifting = isl_basic_map_domain_map(lifting); + lifting = isl_basic_map_reverse(lifting); + + return lifting; +}