X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_local_space.c;h=ebf222c6499f5f1fb1b2b287b84a099526970cdf;hb=56b7d238929980e62218525b4b3be121af386edf;hp=3fd5ad8d00ebb0138236dc957fc393ca6093669f;hpb=6017212533e2cd9ec43f81fa14666a5329be1538;p=platform%2Fupstream%2Fisl.git diff --git a/isl_local_space.c b/isl_local_space.c index 3fd5ad8..ebf222c 100644 --- a/isl_local_space.c +++ b/isl_local_space.c @@ -8,10 +8,12 @@ * 91893 Orsay, France */ +#include #include #include -#include +#include #include +#include #include isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls) @@ -19,7 +21,7 @@ isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls) return ls ? ls->dim->ctx : NULL; } -__isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_dim *dim, +__isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_space *dim, __isl_take isl_mat *div) { isl_ctx *ctx; @@ -28,7 +30,7 @@ __isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_dim *dim, if (!dim) goto error; - ctx = isl_dim_get_ctx(dim); + ctx = isl_space_get_ctx(dim); ls = isl_calloc_type(ctx, struct isl_local_space); if (!ls) goto error; @@ -39,12 +41,12 @@ __isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_dim *dim, return ls; error: - isl_dim_free(dim); + isl_space_free(dim); isl_local_space_free(ls); return NULL; } -__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_dim *dim, +__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *dim, unsigned n_div) { isl_ctx *ctx; @@ -54,14 +56,14 @@ __isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_dim *dim, if (!dim) return NULL; - total = isl_dim_total(dim); + total = isl_space_dim(dim, isl_dim_all); - ctx = isl_dim_get_ctx(dim); + ctx = isl_space_get_ctx(dim); div = isl_mat_alloc(ctx, n_div, 1 + 1 + total + n_div); return isl_local_space_alloc_div(dim, div); } -__isl_give isl_local_space *isl_local_space_from_dim(__isl_take isl_dim *dim) +__isl_give isl_local_space *isl_local_space_from_space(__isl_take isl_space *dim) { return isl_local_space_alloc(dim, 0); } @@ -80,7 +82,7 @@ __isl_give isl_local_space *isl_local_space_dup(__isl_keep isl_local_space *ls) if (!ls) return NULL; - return isl_local_space_alloc_div(isl_dim_copy(ls->dim), + return isl_local_space_alloc_div(isl_space_copy(ls->dim), isl_mat_copy(ls->div)); } @@ -104,7 +106,7 @@ void *isl_local_space_free(__isl_take isl_local_space *ls) if (--ls->ref > 0) return NULL; - isl_dim_free(ls->dim); + isl_space_free(ls->dim); isl_mat_free(ls->div); free(ls); @@ -112,6 +114,36 @@ 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. + */ +int isl_local_space_is_equal(__isl_keep isl_local_space *ls1, + __isl_keep isl_local_space *ls2) +{ + int equal; + + if (!ls1 || !ls2) + return -1; + + equal = isl_space_is_equal(ls1->dim, ls2->dim); + if (equal < 0 || !equal) + return equal; + + if (!isl_local_space_divs_known(ls1)) + return 0; + if (!isl_local_space_divs_known(ls2)) + return 0; + + return isl_mat_is_equal(ls1->div, ls2->div); +} + int isl_local_space_dim(__isl_keep isl_local_space *ls, enum isl_dim_type type) { @@ -120,14 +152,14 @@ int isl_local_space_dim(__isl_keep isl_local_space *ls, if (type == isl_dim_div) return ls->div->n_row; if (type == isl_dim_all) - return isl_dim_size(ls->dim, isl_dim_all) + ls->div->n_row; - return isl_dim_size(ls->dim, type); + return isl_space_dim(ls->dim, isl_dim_all) + ls->div->n_row; + return isl_space_dim(ls->dim, type); } unsigned isl_local_space_offset(__isl_keep isl_local_space *ls, enum isl_dim_type type) { - isl_dim *dim; + isl_space *dim; if (!ls) return 0; @@ -146,13 +178,13 @@ unsigned isl_local_space_offset(__isl_keep isl_local_space *ls, const char *isl_local_space_get_dim_name(__isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos) { - return ls ? isl_dim_get_name(ls->dim, type, pos) : NULL; + 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; @@ -161,16 +193,115 @@ __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, "index out of bounds", return NULL); - bmap = isl_basic_map_from_local_space(isl_local_space_copy(ls)); - return isl_basic_map_div(bmap, pos); + if (isl_int_is_zero(ls->div->row[pos][0])) + isl_die(isl_local_space_get_ctx(ls), isl_error_invalid, + "expression of div unknown", return NULL); + + 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_dim *isl_local_space_get_dim(__isl_keep isl_local_space *ls) +__isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls) { if (!ls) return NULL; - return isl_dim_copy(ls->dim); + return isl_space_copy(ls->dim); +} + +__isl_give isl_local_space *isl_local_space_set_dim_name( + __isl_take isl_local_space *ls, + enum isl_dim_type type, unsigned pos, const char *s) +{ + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + ls->dim = isl_space_set_dim_name(ls->dim, type, pos, s); + 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) +{ + ls = isl_local_space_cow(ls); + if (!ls || !dim) + goto error; + + isl_space_free(ls->dim); + ls->dim = dim; + + return ls; +error: + isl_local_space_free(ls); + isl_space_free(dim); + return NULL; +} + +/* Reorder the columns of the given div definitions according to the + * given reordering. + * The order of the divs themselves is assumed not to change. + */ +static __isl_give isl_mat *reorder_divs(__isl_take isl_mat *div, + __isl_take isl_reordering *r) +{ + int i, j; + isl_mat *mat; + int extra; + + if (!div || !r) + goto error; + + extra = isl_space_dim(r->dim, isl_dim_all) + div->n_row - r->len; + mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra); + if (!mat) + goto error; + + for (i = 0; i < div->n_row; ++i) { + isl_seq_cpy(mat->row[i], div->row[i], 2); + isl_seq_clr(mat->row[i] + 2, mat->n_col - 2); + for (j = 0; j < r->len; ++j) + isl_int_set(mat->row[i][2 + r->pos[j]], + div->row[i][2 + j]); + } + + isl_reordering_free(r); + isl_mat_free(div); + return mat; +error: + isl_reordering_free(r); + isl_mat_free(div); + return NULL; +} + +/* Reorder the dimensions of "ls" according to the given reordering. + * The reordering r is assumed to have been extended with the local + * variables, leaving them in the same order. + */ +__isl_give isl_local_space *isl_local_space_realign( + __isl_take isl_local_space *ls, __isl_take isl_reordering *r) +{ + ls = isl_local_space_cow(ls); + if (!ls || !r) + goto error; + + ls->div = reorder_divs(ls->div, isl_reordering_copy(r)); + if (!ls->div) + goto error; + + ls = isl_local_space_reset_space(ls, isl_space_copy(r->dim)); + + isl_reordering_free(r); + return ls; +error: + isl_local_space_free(ls); + isl_reordering_free(r); + return NULL; } __isl_give isl_local_space *isl_local_space_add_div( @@ -319,3 +450,268 @@ 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; +} + +/* Construct a local space for a map that has the given local + * space as domain and that has a zero-dimensional range. + */ +__isl_give isl_local_space *isl_local_space_from_domain( + __isl_take isl_local_space *ls) +{ + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + ls->dim = isl_space_from_domain(ls->dim); + if (!ls->dim) + return isl_local_space_free(ls); + return ls; +} + +__isl_give isl_local_space *isl_local_space_add_dims( + __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n) +{ + int pos; + + if (!ls) + return NULL; + pos = isl_local_space_dim(ls, type); + return isl_local_space_insert_dims(ls, type, pos, n); +} + +/* Remove common factor of non-constant terms and denominator. + */ +static void normalize_div(__isl_keep isl_local_space *ls, int div) +{ + isl_ctx *ctx = ls->div->ctx; + unsigned total = ls->div->n_col - 2; + + isl_seq_gcd(ls->div->row[div] + 2, total, &ctx->normalize_gcd); + isl_int_gcd(ctx->normalize_gcd, + ctx->normalize_gcd, ls->div->row[div][0]); + if (isl_int_is_one(ctx->normalize_gcd)) + return; + + isl_seq_scale_down(ls->div->row[div] + 2, ls->div->row[div] + 2, + ctx->normalize_gcd, total); + isl_int_divexact(ls->div->row[div][0], ls->div->row[div][0], + ctx->normalize_gcd); + isl_int_fdiv_q(ls->div->row[div][1], ls->div->row[div][1], + ctx->normalize_gcd); +} + +/* Exploit the equalities in "eq" to simplify the expressions of + * the integer divisions in "ls". + * The integer divisions in "ls" are assumed to appear as regular + * dimensions in "eq". + */ +__isl_give isl_local_space *isl_local_space_substitute_equalities( + __isl_take isl_local_space *ls, __isl_take isl_basic_set *eq) +{ + int i, j, k; + unsigned total; + unsigned n_div; + + ls = isl_local_space_cow(ls); + if (!ls || !eq) + goto error; + + total = isl_space_dim(eq->dim, isl_dim_all); + if (isl_local_space_dim(ls, isl_dim_all) != total) + isl_die(isl_local_space_get_ctx(ls), isl_error_invalid, + "dimensions don't match", goto error); + total++; + n_div = eq->n_div; + for (i = 0; i < eq->n_eq; ++i) { + j = isl_seq_last_non_zero(eq->eq[i], total + n_div); + if (j < 0 || j == 0 || j >= total) + continue; + + for (k = 0; k < ls->div->n_row; ++k) { + if (isl_int_is_zero(ls->div->row[k][1 + j])) + continue; + isl_seq_elim(ls->div->row[k] + 1, eq->eq[i], j, total, + &ls->div->row[k][0]); + normalize_div(ls, k); + } + } + + isl_basic_set_free(eq); + return ls; +error: + isl_basic_set_free(eq); + isl_local_space_free(ls); + return NULL; +} + +int isl_local_space_is_named_or_nested(__isl_keep isl_local_space *ls, + enum isl_dim_type type) +{ + if (!ls) + return -1; + return isl_space_is_named_or_nested(ls->dim, type); +} + +__isl_give isl_local_space *isl_local_space_drop_dims( + __isl_take isl_local_space *ls, + enum isl_dim_type type, unsigned first, unsigned n) +{ + isl_ctx *ctx; + + if (!ls) + return NULL; + if (n == 0 && !isl_local_space_is_named_or_nested(ls, type)) + return ls; + + ctx = isl_local_space_get_ctx(ls); + if (first + n > isl_local_space_dim(ls, type)) + isl_die(ctx, isl_error_invalid, "range out of bounds", + return isl_local_space_free(ls)); + + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + + if (type == isl_dim_div) { + ls->div = isl_mat_drop_rows(ls->div, first, n); + } else { + ls->dim = isl_space_drop_dims(ls->dim, type, first, n); + if (!ls->dim) + return isl_local_space_free(ls); + } + + first += 1 + isl_local_space_offset(ls, type); + ls->div = isl_mat_drop_cols(ls->div, first, n); + if (!ls->div) + return isl_local_space_free(ls); + + return ls; +} + +__isl_give isl_local_space *isl_local_space_insert_dims( + __isl_take isl_local_space *ls, + enum isl_dim_type type, unsigned first, unsigned n) +{ + isl_ctx *ctx; + + if (!ls) + return NULL; + if (n == 0 && !isl_local_space_is_named_or_nested(ls, type)) + return ls; + + ctx = isl_local_space_get_ctx(ls); + if (first > isl_local_space_dim(ls, type)) + isl_die(ctx, isl_error_invalid, "position out of bounds", + return isl_local_space_free(ls)); + + ls = isl_local_space_cow(ls); + if (!ls) + return NULL; + + if (type == isl_dim_div) { + ls->div = isl_mat_insert_zero_rows(ls->div, first, n); + } else { + ls->dim = isl_space_insert_dims(ls->dim, type, first, n); + if (!ls->dim) + return isl_local_space_free(ls); + } + + first += 1 + isl_local_space_offset(ls, type); + ls->div = isl_mat_insert_zero_cols(ls->div, first, n); + if (!ls->div) + return isl_local_space_free(ls); + + return ls; +} + +/* Check if the constraints pointed to by "constraint" is a div + * constraint corresponding to div "div" in "ls". + * + * That is, if div = floor(f/m), then check if the constraint is + * + * f - m d >= 0 + * or + * -(f-(m-1)) + m d >= 0 + */ +int isl_local_space_is_div_constraint(__isl_keep isl_local_space *ls, + isl_int *constraint, unsigned div) +{ + unsigned pos; + + if (!ls) + return -1; + + if (isl_int_is_zero(ls->div->row[div][0])) + return 0; + + pos = isl_local_space_offset(ls, isl_dim_div) + div; + + if (isl_int_eq(constraint[pos], ls->div->row[div][0])) { + int neg; + isl_int_sub(ls->div->row[div][1], + ls->div->row[div][1], ls->div->row[div][0]); + isl_int_add_ui(ls->div->row[div][1], ls->div->row[div][1], 1); + neg = isl_seq_is_neg(constraint, ls->div->row[div]+1, pos); + isl_int_sub_ui(ls->div->row[div][1], ls->div->row[div][1], 1); + isl_int_add(ls->div->row[div][1], + ls->div->row[div][1], ls->div->row[div][0]); + if (!neg) + return 0; + if (isl_seq_first_non_zero(constraint+pos+1, + ls->div->n_row-div-1) != -1) + return 0; + } else if (isl_int_abs_eq(constraint[pos], ls->div->row[div][0])) { + if (!isl_seq_eq(constraint, ls->div->row[div]+1, pos)) + return 0; + if (isl_seq_first_non_zero(constraint+pos+1, + ls->div->n_row-div-1) != -1) + return 0; + } else + return 0; + + 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; +}