X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_aff.c;h=e39d11845247e6f558b6b4ef065d66884d14a7a6;hb=5d157c90e755f6acc8b214acb5344e052136568f;hp=656ebdf098d39b24736b936fe8170665861034f7;hpb=a3e3c35fe631d3dbaa923d3199fc49f615269df7;p=platform%2Fupstream%2Fisl.git diff --git a/isl_aff.c b/isl_aff.c index 656ebdf..e39d118 100644 --- a/isl_aff.c +++ b/isl_aff.c @@ -1,12 +1,14 @@ /* * Copyright 2011 INRIA Saclay * Copyright 2011 Sven Verdoolaege + * Copyright 2012 Ecole Normale Superieure * * Use of this software is governed by the GNU LGPLv2.1 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 @@ -280,6 +282,34 @@ error: return NULL; } +__isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff, + __isl_take isl_space *model) +{ + if (!aff || !model) + goto error; + + if (!isl_space_match(aff->ls->dim, isl_dim_param, + model, isl_dim_param)) { + isl_reordering *exp; + + model = isl_space_drop_dims(model, isl_dim_in, + 0, isl_space_dim(model, isl_dim_in)); + model = isl_space_drop_dims(model, isl_dim_out, + 0, isl_space_dim(model, isl_dim_out)); + exp = isl_parameter_alignment_reordering(aff->ls->dim, model); + exp = isl_reordering_extend_space(exp, + isl_aff_get_domain_space(aff)); + aff = isl_aff_realign_domain(aff, exp); + } + + isl_space_free(model); + return aff; +error: + isl_space_free(model); + isl_aff_free(aff); + return NULL; +} + int isl_aff_plain_is_zero(__isl_keep isl_aff *aff) { if (!aff) @@ -544,6 +574,41 @@ __isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff) return aff; } +/* Remove divs from the local space that do not appear in the affine + * expression. + * We currently only remove divs at the end. + * Some intermediate divs may also not appear directly in the affine + * expression, but we would also need to check that no other divs are + * defined in terms of them. + */ +__isl_give isl_aff *isl_aff_remove_unused_divs( __isl_take isl_aff *aff) +{ + int pos; + int off; + int n; + + if (!aff) + return NULL; + + n = isl_local_space_dim(aff->ls, isl_dim_div); + off = isl_local_space_offset(aff->ls, isl_dim_div); + + pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1; + if (pos == n) + return aff; + + aff = isl_aff_cow(aff); + if (!aff) + return NULL; + + aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos); + aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos); + if (!aff->ls || !aff->v) + return isl_aff_free(aff); + + return aff; +} + __isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff) { if (!aff) @@ -551,6 +616,7 @@ __isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff) aff->v = isl_vec_normalize(aff->v); if (!aff->v) return isl_aff_free(aff); + aff = isl_aff_remove_unused_divs(aff); return aff; } @@ -936,6 +1002,7 @@ static __isl_give isl_aff *isl_aff_substitute_equalities_lifted( } isl_basic_set_free(eq); + aff = isl_aff_normalize(aff); return aff; error: isl_basic_set_free(eq); @@ -1011,10 +1078,13 @@ __isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff, __isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff) { isl_constraint *ineq; + isl_basic_set *bset; ineq = isl_inequality_from_aff(aff); - return isl_basic_set_from_constraint(ineq); + bset = isl_basic_set_from_constraint(ineq); + bset = isl_basic_set_simplify(bset); + return bset; } /* Return a basic set containing those elements in the space @@ -1023,10 +1093,13 @@ __isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff) __isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff) { isl_constraint *ineq; + isl_basic_set *bset; ineq = isl_equality_from_aff(aff); - return isl_basic_set_from_constraint(ineq); + bset = isl_basic_set_from_constraint(ineq); + bset = isl_basic_set_simplify(bset); + return bset; } /* Return a basic set containing those elements in the shared space @@ -1144,6 +1217,30 @@ __isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff, return aff; } +/* Project the domain of the affine expression onto its parameter space. + * The affine expression may not involve any of the domain dimensions. + */ +__isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff) +{ + isl_space *space; + unsigned n; + int involves; + + n = isl_aff_dim(aff, isl_dim_in); + involves = isl_aff_involves_dims(aff, isl_dim_in, 0, n); + if (involves < 0) + return isl_aff_free(aff); + if (involves) + isl_die(isl_aff_get_ctx(aff), isl_error_invalid, + "affine expression involves some of the domain dimensions", + return isl_aff_free(aff)); + aff = isl_aff_drop_dims(aff, isl_dim_in, 0, n); + space = isl_aff_get_domain_space(aff); + space = isl_space_params(space); + aff = isl_aff_reset_domain_space(aff, space); + return aff; +} + __isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff, enum isl_dim_type type, unsigned first, unsigned n) { @@ -1219,6 +1316,8 @@ __isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff) #define IS_ZERO is_empty #undef FIELD #define FIELD aff +#undef DEFAULT_IS_ZERO +#define DEFAULT_IS_ZERO 0 #define NO_EVAL #define NO_OPT @@ -1417,6 +1516,8 @@ static __isl_give isl_map *map_from_pw_aff(__isl_take isl_pw_aff *pwaff) */ __isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff) { + if (!pwaff) + return NULL; if (isl_space_is_set(pwaff->dim)) isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid, "space of input is not a map", @@ -1468,9 +1569,11 @@ __isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff) } /* Return a set containing those elements in the domain - * of pwaff where it is zero. + * of pwaff where it is zero (if complement is 0) or not zero + * (if complement is 1). */ -__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff) +static __isl_give isl_set *pw_aff_zero_set(__isl_take isl_pw_aff *pwaff, + int complement) { int i; isl_set *set; @@ -1482,11 +1585,15 @@ __isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff) for (i = 0; i < pwaff->n; ++i) { isl_basic_set *bset; - isl_set *set_i; + isl_set *set_i, *zero; bset = isl_aff_zero_basic_set(isl_aff_copy(pwaff->p[i].aff)); - set_i = isl_set_from_basic_set(bset); - set_i = isl_set_intersect(set_i, isl_set_copy(pwaff->p[i].set)); + zero = isl_set_from_basic_set(bset); + set_i = isl_set_copy(pwaff->p[i].set); + if (complement) + set_i = isl_set_subtract(set_i, zero); + else + set_i = isl_set_intersect(set_i, zero); set = isl_set_union_disjoint(set, set_i); } @@ -1496,11 +1603,19 @@ __isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff) } /* Return a set containing those elements in the domain + * of pwaff where it is zero. + */ +__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff) +{ + return pw_aff_zero_set(pwaff, 0); +} + +/* Return a set containing those elements in the domain * of pwaff where it is not zero. */ __isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff) { - return isl_set_complement(isl_pw_aff_zero_set(pwaff)); + return pw_aff_zero_set(pwaff, 1); } /* Return a set containing those elements in the shared domain @@ -2090,6 +2205,16 @@ __isl_give isl_multi_aff *isl_multi_aff_drop_dims(__isl_take isl_multi_aff *maff maff->space = isl_space_drop_dims(maff->space, type, first, n); if (!maff->space) return isl_multi_aff_free(maff); + + if (type == isl_dim_out) { + for (i = 0; i < n; ++i) + isl_aff_free(maff->p[first + i]); + for (i = first; i + n < maff->n; ++i) + maff->p[i] = maff->p[i + n]; + maff->n -= n; + return maff; + } + for (i = 0; i < maff->n; ++i) { maff->p[i] = isl_aff_drop_dims(maff->p[i], type, first, n); if (!maff->p[i]) @@ -2111,6 +2236,8 @@ __isl_give isl_multi_aff *isl_multi_aff_drop_dims(__isl_take isl_multi_aff *maff #define IS_ZERO is_empty #undef FIELD #define FIELD maff +#undef DEFAULT_IS_ZERO +#define DEFAULT_IS_ZERO 0 #define NO_NEG #define NO_EVAL @@ -2184,22 +2311,145 @@ __isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma) return isl_map_from_pw_multi_aff(pma); } +/* Given a basic map with a single output dimension that is defined + * in terms of the parameters and input dimensions using an equality, + * extract an isl_aff that expresses the output dimension in terms + * of the parameters and input dimensions. + * + * Since some applications expect the result of isl_pw_multi_aff_from_map + * to only contain integer affine expressions, we compute the floor + * of the expression before returning. + * + * This function shares some similarities with + * isl_basic_map_has_defining_equality and isl_constraint_get_bound. + */ +static __isl_give isl_aff *extract_isl_aff_from_basic_map( + __isl_take isl_basic_map *bmap) +{ + int i; + unsigned offset; + unsigned total; + isl_local_space *ls; + isl_aff *aff; + + if (!bmap) + return NULL; + if (isl_basic_map_dim(bmap, isl_dim_out) != 1) + isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, + "basic map should have a single output dimension", + goto error); + offset = isl_basic_map_offset(bmap, isl_dim_out); + total = isl_basic_map_total_dim(bmap); + for (i = 0; i < bmap->n_eq; ++i) { + if (isl_int_is_zero(bmap->eq[i][offset])) + continue; + if (isl_seq_first_non_zero(bmap->eq[i] + offset + 1, + 1 + total - (offset + 1)) != -1) + continue; + break; + } + if (i >= bmap->n_eq) + isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid, + "unable to find suitable equality", goto error); + ls = isl_basic_map_get_local_space(bmap); + aff = isl_aff_alloc(isl_local_space_domain(ls)); + if (!aff) + goto error; + if (isl_int_is_neg(bmap->eq[i][offset])) + isl_seq_cpy(aff->v->el + 1, bmap->eq[i], offset); + else + isl_seq_neg(aff->v->el + 1, bmap->eq[i], offset); + isl_seq_clr(aff->v->el + 1 + offset, aff->v->size - (1 + offset)); + isl_int_abs(aff->v->el[0], bmap->eq[i][offset]); + isl_basic_map_free(bmap); + + aff = isl_aff_remove_unused_divs(aff); + aff = isl_aff_floor(aff); + return aff; +error: + isl_basic_map_free(bmap); + return NULL; +} + +/* Given a basic map where each output dimension is defined + * in terms of the parameters and input dimensions using an equality, + * extract an isl_multi_aff that expresses the output dimensions in terms + * of the parameters and input dimensions. + */ +static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map( + __isl_take isl_basic_map *bmap) +{ + int i; + unsigned n_out; + isl_multi_aff *ma; + + if (!bmap) + return NULL; + + ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap)); + n_out = isl_basic_map_dim(bmap, isl_dim_out); + + for (i = 0; i < n_out; ++i) { + isl_basic_map *bmap_i; + isl_aff *aff; + + bmap_i = isl_basic_map_copy(bmap); + bmap_i = isl_basic_map_project_out(bmap_i, isl_dim_out, + i + 1, n_out - (1 + i)); + bmap_i = isl_basic_map_project_out(bmap_i, isl_dim_out, 0, i); + aff = extract_isl_aff_from_basic_map(bmap_i); + ma = isl_multi_aff_set_aff(ma, i, aff); + } + + isl_basic_map_free(bmap); + + return ma; +} + +/* Create an isl_pw_multi_aff that is equivalent to + * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain). + * The given basic map is such that each output dimension is defined + * in terms of the parameters and input dimensions using an equality. + */ +static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map( + __isl_take isl_set *domain, __isl_take isl_basic_map *bmap) +{ + isl_multi_aff *ma; + + ma = extract_isl_multi_aff_from_basic_map(bmap); + return isl_pw_multi_aff_alloc(domain, ma); +} + /* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map. * This obivously only works if the input "map" is single-valued. * If so, we compute the lexicographic minimum of the image in the form * of an isl_pw_multi_aff. Since the image is unique, it is equal * to its lexicographic minimum. * If the input is not single-valued, we produce an error. + * + * As a special case, we first check if all output dimensions are uniquely + * defined in terms of the parameters and input dimensions over the entire + * domain. If so, we extract the desired isl_pw_multi_aff directly + * from the affine hull of "map" and its domain. */ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map) { int i; int sv; isl_pw_multi_aff *pma; + isl_basic_map *hull; if (!map) return NULL; + hull = isl_map_affine_hull(isl_map_copy(map)); + sv = isl_basic_map_plain_is_single_valued(hull); + if (sv >= 0 && sv) + return plain_pw_multi_aff_from_map(isl_map_domain(map), hull); + isl_basic_map_free(hull); + if (sv < 0) + goto error; + sv = isl_map_is_single_valued(map); if (sv < 0) goto error; @@ -2510,3 +2760,37 @@ error: isl_local_space_free(*ls); return isl_multi_aff_free(maff); } + + +/* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma". + */ +__isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff( + __isl_keep isl_pw_multi_aff *pma, int pos) +{ + int i; + int n_out; + isl_space *space; + isl_pw_aff *pa; + + if (!pma) + return NULL; + + n_out = isl_pw_multi_aff_dim(pma, isl_dim_out); + if (pos < 0 || pos >= n_out) + isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid, + "index out of bounds", return NULL); + + space = isl_pw_multi_aff_get_space(pma); + space = isl_space_drop_dims(space, isl_dim_out, + pos + 1, n_out - pos - 1); + space = isl_space_drop_dims(space, isl_dim_out, 0, pos); + + pa = isl_pw_aff_alloc_size(space, pma->n); + for (i = 0; i < pma->n; ++i) { + isl_aff *aff; + aff = isl_multi_aff_get_aff(pma->p[i].maff, pos); + pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff); + } + + return pa; +}