| /* |
| * Copyright 2010 INRIA Saclay |
| * |
| * 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 |
| */ |
| |
| #include <isl_ctx_private.h> |
| #include <isl/id.h> |
| #include <isl_space_private.h> |
| #include <isl_reordering.h> |
| |
| __isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int len) |
| { |
| isl_reordering *exp; |
| |
| exp = isl_alloc(ctx, struct isl_reordering, |
| sizeof(struct isl_reordering) + (len - 1) * sizeof(int)); |
| if (!exp) |
| return NULL; |
| |
| exp->ref = 1; |
| exp->len = len; |
| exp->space = NULL; |
| |
| return exp; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp) |
| { |
| if (!exp) |
| return NULL; |
| |
| exp->ref++; |
| return exp; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_dup(__isl_keep isl_reordering *r) |
| { |
| int i; |
| isl_reordering *dup; |
| |
| if (!r) |
| return NULL; |
| |
| dup = isl_reordering_alloc(isl_reordering_get_ctx(r), r->len); |
| if (!dup) |
| return NULL; |
| |
| dup->space = isl_reordering_get_space(r); |
| if (!dup->space) |
| return isl_reordering_free(dup); |
| for (i = 0; i < dup->len; ++i) |
| dup->pos[i] = r->pos[i]; |
| |
| return dup; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_cow(__isl_take isl_reordering *r) |
| { |
| if (!r) |
| return NULL; |
| |
| if (r->ref == 1) |
| return r; |
| r->ref--; |
| return isl_reordering_dup(r); |
| } |
| |
| __isl_null isl_reordering *isl_reordering_free(__isl_take isl_reordering *exp) |
| { |
| if (!exp) |
| return NULL; |
| |
| if (--exp->ref > 0) |
| return NULL; |
| |
| isl_space_free(exp->space); |
| free(exp); |
| return NULL; |
| } |
| |
| /* Return the isl_ctx to which "r" belongs. |
| */ |
| isl_ctx *isl_reordering_get_ctx(__isl_keep isl_reordering *r) |
| { |
| return isl_space_get_ctx(isl_reordering_peek_space(r)); |
| } |
| |
| /* Return the space of "r". |
| */ |
| __isl_keep isl_space *isl_reordering_peek_space(__isl_keep isl_reordering *r) |
| { |
| if (!r) |
| return NULL; |
| return r->space; |
| } |
| |
| /* Return a copy of the space of "r". |
| */ |
| __isl_give isl_space *isl_reordering_get_space(__isl_keep isl_reordering *r) |
| { |
| return isl_space_copy(isl_reordering_peek_space(r)); |
| } |
| |
| /* Construct a reordering that maps the parameters of "alignee" |
| * to the corresponding parameters in a new dimension specification |
| * that has the parameters of "aligner" first, followed by |
| * any remaining parameters of "alignee" that do not occur in "aligner". |
| */ |
| __isl_give isl_reordering *isl_parameter_alignment_reordering( |
| __isl_keep isl_space *alignee, __isl_keep isl_space *aligner) |
| { |
| int i, j; |
| isl_reordering *exp; |
| |
| if (!alignee || !aligner) |
| return NULL; |
| |
| exp = isl_reordering_alloc(alignee->ctx, alignee->nparam); |
| if (!exp) |
| return NULL; |
| |
| exp->space = isl_space_params(isl_space_copy(aligner)); |
| |
| for (i = 0; i < alignee->nparam; ++i) { |
| isl_id *id_i; |
| id_i = isl_space_get_dim_id(alignee, isl_dim_param, i); |
| if (!id_i) |
| isl_die(alignee->ctx, isl_error_invalid, |
| "cannot align unnamed parameters", goto error); |
| for (j = 0; j < aligner->nparam; ++j) { |
| isl_id *id_j; |
| id_j = isl_space_get_dim_id(aligner, isl_dim_param, j); |
| isl_id_free(id_j); |
| if (id_i == id_j) |
| break; |
| } |
| if (j < aligner->nparam) { |
| exp->pos[i] = j; |
| isl_id_free(id_i); |
| } else { |
| isl_size pos; |
| pos = isl_space_dim(exp->space, isl_dim_param); |
| if (pos < 0) |
| exp->space = isl_space_free(exp->space); |
| exp->space = isl_space_add_dims(exp->space, |
| isl_dim_param, 1); |
| exp->space = isl_space_set_dim_id(exp->space, |
| isl_dim_param, pos, id_i); |
| exp->pos[i] = pos; |
| } |
| } |
| |
| if (!exp->space) |
| return isl_reordering_free(exp); |
| return exp; |
| error: |
| isl_reordering_free(exp); |
| return NULL; |
| } |
| |
| /* Return a reordering that moves the parameters identified by |
| * the elements of "tuple" to a domain tuple inserted into "space". |
| * The parameters that remain, are moved from their original positions |
| * in the list of parameters to their new positions in this list. |
| * The parameters that get removed, are moved to the corresponding |
| * positions in the new domain. Note that these set dimensions |
| * do not necessarily need to appear as parameters in "space". |
| * Any other dimensions are shifted by the number of extra dimensions |
| * introduced, i.e., the number of dimensions in the new domain |
| * that did not appear as parameters in "space". |
| */ |
| __isl_give isl_reordering *isl_reordering_unbind_params_insert_domain( |
| __isl_keep isl_space *space, __isl_keep isl_multi_id *tuple) |
| { |
| int i, n; |
| int offset, first; |
| isl_ctx *ctx; |
| isl_reordering *r; |
| |
| if (!space || !tuple) |
| return NULL; |
| |
| ctx = isl_space_get_ctx(space); |
| r = isl_reordering_alloc(ctx, isl_space_dim(space, isl_dim_all)); |
| if (!r) |
| return NULL; |
| |
| r->space = isl_space_copy(space); |
| r->space = isl_space_unbind_params_insert_domain(r->space, tuple); |
| if (!r->space) |
| return isl_reordering_free(r); |
| |
| n = isl_space_dim(r->space, isl_dim_param); |
| for (i = 0; i < n; ++i) { |
| int pos; |
| isl_id *id; |
| |
| id = isl_space_get_dim_id(r->space, isl_dim_param, i); |
| if (!id) |
| return isl_reordering_free(r); |
| pos = isl_space_find_dim_by_id(space, isl_dim_param, id); |
| isl_id_free(id); |
| r->pos[pos] = i; |
| } |
| |
| offset = isl_space_dim(r->space, isl_dim_param); |
| n = isl_multi_id_size(tuple); |
| for (i = 0; i < n; ++i) { |
| int pos; |
| isl_id *id; |
| |
| id = isl_multi_id_get_id(tuple, i); |
| if (!id) |
| return isl_reordering_free(r); |
| pos = isl_space_find_dim_by_id(space, isl_dim_param, id); |
| isl_id_free(id); |
| if (pos < 0) |
| continue; |
| r->pos[pos] = offset + i; |
| } |
| |
| offset = isl_space_dim(r->space, isl_dim_all) - r->len; |
| first = isl_space_dim(space, isl_dim_param); |
| n = r->len - first; |
| for (i = 0; i < n; ++i) |
| r->pos[first + i] = first + offset + i; |
| |
| return r; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp, |
| unsigned extra) |
| { |
| int i; |
| isl_ctx *ctx; |
| isl_space *space; |
| isl_reordering *res; |
| int offset; |
| isl_size dim; |
| |
| if (!exp) |
| return NULL; |
| if (extra == 0) |
| return exp; |
| |
| ctx = isl_reordering_get_ctx(exp); |
| space = isl_reordering_peek_space(exp); |
| dim = isl_space_dim(space, isl_dim_all); |
| if (dim < 0) |
| return isl_reordering_free(exp); |
| offset = dim - exp->len; |
| res = isl_reordering_alloc(ctx, exp->len + extra); |
| if (!res) |
| goto error; |
| res->space = isl_reordering_get_space(exp); |
| for (i = 0; i < exp->len; ++i) |
| res->pos[i] = exp->pos[i]; |
| for (i = exp->len; i < res->len; ++i) |
| res->pos[i] = offset + i; |
| |
| isl_reordering_free(exp); |
| |
| return res; |
| error: |
| isl_reordering_free(exp); |
| return NULL; |
| } |
| |
| __isl_give isl_reordering *isl_reordering_extend_space( |
| __isl_take isl_reordering *exp, __isl_take isl_space *space) |
| { |
| isl_space *exp_space; |
| isl_reordering *res; |
| isl_size dim; |
| |
| dim = isl_space_dim(space, isl_dim_all); |
| if (!exp || dim < 0) |
| goto error; |
| |
| res = isl_reordering_extend(isl_reordering_copy(exp), dim - exp->len); |
| res = isl_reordering_cow(res); |
| if (!res) |
| goto error; |
| isl_space_free(res->space); |
| exp_space = isl_reordering_peek_space(exp); |
| res->space = isl_space_replace_params(space, exp_space); |
| |
| isl_reordering_free(exp); |
| |
| if (!res->space) |
| return isl_reordering_free(res); |
| |
| return res; |
| error: |
| isl_reordering_free(exp); |
| isl_space_free(space); |
| return NULL; |
| } |
| |
| void isl_reordering_dump(__isl_keep isl_reordering *exp) |
| { |
| int i; |
| |
| isl_space_dump(exp->space); |
| for (i = 0; i < exp->len; ++i) |
| fprintf(stderr, "%d -> %d; ", i, exp->pos[i]); |
| fprintf(stderr, "\n"); |
| } |