Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright 2010      INRIA Saclay
      3  *
      4  * Use of this software is governed by the MIT license
      5  *
      6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
      7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
      8  * 91893 Orsay, France
      9  */
     10 
     11 #include <isl_ctx_private.h>
     12 #include <isl/id.h>
     13 #include <isl_space_private.h>
     14 #include <isl_reordering.h>
     15 
     16 /* Create a new reordering description based on
     17  * the number of source dimensions "src_len" and
     18  * (an initial value for) the number of target dimensions "dst_len".
     19  *
     20  * The caller still needs to fill in the space field and
     21  * possibly adjust the target dimensionality if this is not known yet
     22  * when this function is called.
     23  */
     24 __isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int src_len,
     25 	int dst_len)
     26 {
     27 	isl_reordering *exp;
     28 
     29 	exp = isl_alloc(ctx, struct isl_reordering,
     30 		sizeof(struct isl_reordering) + (src_len - 1) * sizeof(int));
     31 	if (!exp)
     32 		return NULL;
     33 
     34 	exp->ref = 1;
     35 	exp->src_len = src_len;
     36 	exp->dst_len = dst_len;
     37 	exp->space = NULL;
     38 
     39 	return exp;
     40 }
     41 
     42 /* Set r->dst_len to the total dimensionality of r->space.
     43  */
     44 static __isl_give isl_reordering *isl_reordering_set_dst_len_from_space(
     45 	__isl_take isl_reordering *r)
     46 {
     47 	isl_size n;
     48 
     49 	if (!r)
     50 		return NULL;
     51 
     52 	n = isl_space_dim(r->space, isl_dim_all);
     53 	if (n < 0)
     54 		return isl_reordering_free(r);
     55 	r->dst_len = n;
     56 	return r;
     57 }
     58 
     59 __isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp)
     60 {
     61 	if (!exp)
     62 		return NULL;
     63 
     64 	exp->ref++;
     65 	return exp;
     66 }
     67 
     68 __isl_give isl_reordering *isl_reordering_dup(__isl_keep isl_reordering *r)
     69 {
     70 	int i;
     71 	isl_reordering *dup;
     72 
     73 	if (!r)
     74 		return NULL;
     75 
     76 	dup = isl_reordering_alloc(isl_reordering_get_ctx(r),
     77 				    r->src_len, r->dst_len);
     78 	if (!dup)
     79 		return NULL;
     80 
     81 	dup->space = isl_reordering_get_space(r);
     82 	if (!dup->space)
     83 		return isl_reordering_free(dup);
     84 	for (i = 0; i < dup->src_len; ++i)
     85 		dup->pos[i] = r->pos[i];
     86 
     87 	return dup;
     88 }
     89 
     90 __isl_give isl_reordering *isl_reordering_cow(__isl_take isl_reordering *r)
     91 {
     92 	if (!r)
     93 		return NULL;
     94 
     95 	if (r->ref == 1)
     96 		return r;
     97 	r->ref--;
     98 	return isl_reordering_dup(r);
     99 }
    100 
    101 __isl_null isl_reordering *isl_reordering_free(__isl_take isl_reordering *exp)
    102 {
    103 	if (!exp)
    104 		return NULL;
    105 
    106 	if (--exp->ref > 0)
    107 		return NULL;
    108 
    109 	isl_space_free(exp->space);
    110 	free(exp);
    111 	return NULL;
    112 }
    113 
    114 /* Return the isl_ctx to which "r" belongs.
    115  */
    116 isl_ctx *isl_reordering_get_ctx(__isl_keep isl_reordering *r)
    117 {
    118 	return isl_space_get_ctx(isl_reordering_peek_space(r));
    119 }
    120 
    121 /* Return the space of "r".
    122  */
    123 __isl_keep isl_space *isl_reordering_peek_space(__isl_keep isl_reordering *r)
    124 {
    125 	if (!r)
    126 		return NULL;
    127 	return r->space;
    128 }
    129 
    130 /* Return a copy of the space of "r".
    131  */
    132 __isl_give isl_space *isl_reordering_get_space(__isl_keep isl_reordering *r)
    133 {
    134 	return isl_space_copy(isl_reordering_peek_space(r));
    135 }
    136 
    137 /* Construct a reordering that maps the parameters of "alignee"
    138  * to the corresponding parameters in a new dimension specification
    139  * that has the parameters of "aligner" first, followed by
    140  * any remaining parameters of "alignee" that do not occur in "aligner".
    141  * The other dimensions of "alignee" are mapped to subsequent positions
    142  * in order.
    143  */
    144 __isl_give isl_reordering *isl_parameter_alignment_reordering(
    145 	__isl_keep isl_space *alignee, __isl_keep isl_space *aligner)
    146 {
    147 	int i, j, offset;
    148 	isl_ctx *ctx;
    149 	isl_reordering *exp;
    150 	isl_size dim, n_alignee, n_aligner;
    151 
    152 	dim = isl_space_dim(alignee, isl_dim_all);
    153 	n_alignee = isl_space_dim(alignee, isl_dim_param);
    154 	n_aligner = isl_space_dim(aligner, isl_dim_param);
    155 	if (dim < 0 || n_alignee < 0 || n_aligner < 0)
    156 		return NULL;
    157 
    158 	ctx = isl_space_get_ctx(alignee);
    159 	exp = isl_reordering_alloc(ctx, dim, dim);
    160 	if (!exp)
    161 		return NULL;
    162 
    163 	exp->space = isl_space_replace_params(isl_space_copy(alignee), aligner);
    164 
    165 	for (i = 0; i < n_alignee; ++i) {
    166 		isl_id *id_i;
    167 		id_i = isl_space_get_dim_id(alignee, isl_dim_param, i);
    168 		if (!id_i)
    169 			isl_die(ctx, isl_error_invalid,
    170 				"cannot align unnamed parameters", goto error);
    171 		for (j = 0; j < n_aligner; ++j) {
    172 			isl_id *id_j;
    173 			id_j = isl_space_get_dim_id(aligner, isl_dim_param, j);
    174 			isl_id_free(id_j);
    175 			if (id_i == id_j)
    176 				break;
    177 		}
    178 		if (j < n_aligner) {
    179 			exp->pos[i] = j;
    180 			isl_id_free(id_i);
    181 		} else {
    182 			isl_size pos;
    183 			pos = isl_space_dim(exp->space, isl_dim_param);
    184 			if (pos < 0)
    185 				exp->space = isl_space_free(exp->space);
    186 			exp->space = isl_space_add_dims(exp->space,
    187 						isl_dim_param, 1);
    188 			exp->space = isl_space_set_dim_id(exp->space,
    189 						isl_dim_param, pos, id_i);
    190 			exp->pos[i] = pos;
    191 		}
    192 	}
    193 
    194 	exp = isl_reordering_set_dst_len_from_space(exp);
    195 	if (!exp)
    196 		return NULL;
    197 
    198 	offset = exp->dst_len - exp->src_len;
    199 	for (i = n_alignee; i < dim; ++i)
    200 		exp->pos[i] = offset + i;
    201 
    202 	return exp;
    203 error:
    204 	isl_reordering_free(exp);
    205 	return NULL;
    206 }
    207 
    208 /* Return a reordering that moves the parameters identified by
    209  * the elements of "tuple" to a domain tuple inserted into "space".
    210  * The parameters that remain, are moved from their original positions
    211  * in the list of parameters to their new positions in this list.
    212  * The parameters that get removed, are moved to the corresponding
    213  * positions in the new domain.  Note that these set dimensions
    214  * do not necessarily need to appear as parameters in "space".
    215  * Any other dimensions are shifted by the number of extra dimensions
    216  * introduced, i.e., the number of dimensions in the new domain
    217  * that did not appear as parameters in "space".
    218  */
    219 __isl_give isl_reordering *isl_reordering_unbind_params_insert_domain(
    220 	__isl_keep isl_space *space, __isl_keep isl_multi_id *tuple)
    221 {
    222 	int i, n;
    223 	int offset, first;
    224 	isl_size dim;
    225 	isl_ctx *ctx;
    226 	isl_reordering *r;
    227 
    228 	dim = isl_space_dim(space, isl_dim_all);
    229 	if (dim < 0 || !tuple)
    230 		return NULL;
    231 
    232 	ctx = isl_space_get_ctx(space);
    233 	r = isl_reordering_alloc(ctx, dim, dim);
    234 	if (!r)
    235 		return NULL;
    236 
    237 	r->space = isl_space_copy(space);
    238 	r->space = isl_space_unbind_params_insert_domain(r->space, tuple);
    239 	if (!r->space)
    240 		return isl_reordering_free(r);
    241 
    242 	n = isl_space_dim(r->space, isl_dim_param);
    243 	for (i = 0; i < n; ++i) {
    244 		int pos;
    245 		isl_id *id;
    246 
    247 		id = isl_space_get_dim_id(r->space, isl_dim_param, i);
    248 		if (!id)
    249 			return isl_reordering_free(r);
    250 		pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
    251 		isl_id_free(id);
    252 		r->pos[pos] = i;
    253 	}
    254 
    255 	offset = isl_space_dim(r->space, isl_dim_param);
    256 	n = isl_multi_id_size(tuple);
    257 	for (i = 0; i < n; ++i) {
    258 		int pos;
    259 		isl_id *id;
    260 
    261 		id = isl_multi_id_get_id(tuple, i);
    262 		if (!id)
    263 			return isl_reordering_free(r);
    264 		pos = isl_space_find_dim_by_id(space, isl_dim_param, id);
    265 		isl_id_free(id);
    266 		if (pos < 0)
    267 			continue;
    268 		r->pos[pos] = offset + i;
    269 	}
    270 
    271 	offset = isl_space_dim(r->space, isl_dim_all) - dim;
    272 	first = isl_space_dim(space, isl_dim_param);
    273 	n = dim - first;
    274 	for (i = 0; i < n; ++i)
    275 		r->pos[first + i] = first + offset + i;
    276 
    277 	return isl_reordering_set_dst_len_from_space(r);
    278 }
    279 
    280 __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
    281 	unsigned extra)
    282 {
    283 	int i;
    284 	isl_ctx *ctx;
    285 	isl_reordering *res;
    286 	int offset;
    287 
    288 	if (!exp)
    289 		return NULL;
    290 	if (extra == 0)
    291 		return exp;
    292 
    293 	ctx = isl_reordering_get_ctx(exp);
    294 	offset = exp->dst_len - exp->src_len;
    295 	res = isl_reordering_alloc(ctx, exp->src_len + extra,
    296 					exp->dst_len + extra);
    297 	if (!res)
    298 		goto error;
    299 	res->space = isl_reordering_get_space(exp);
    300 	for (i = 0; i < exp->src_len; ++i)
    301 		res->pos[i] = exp->pos[i];
    302 	for (i = exp->src_len; i < res->src_len; ++i)
    303 		res->pos[i] = offset + i;
    304 
    305 	isl_reordering_free(exp);
    306 
    307 	return res;
    308 error:
    309 	isl_reordering_free(exp);
    310 	return NULL;
    311 }
    312 
    313 __isl_give isl_reordering *isl_reordering_extend_space(
    314 	__isl_take isl_reordering *exp, __isl_take isl_space *space)
    315 {
    316 	isl_space *exp_space;
    317 	isl_reordering *res;
    318 	isl_size dim;
    319 
    320 	dim = isl_space_dim(space, isl_dim_all);
    321 	if (!exp || dim < 0)
    322 		goto error;
    323 
    324 	res = isl_reordering_extend(isl_reordering_copy(exp),
    325 				    dim - exp->src_len);
    326 	res = isl_reordering_cow(res);
    327 	if (!res)
    328 		goto error;
    329 	isl_space_free(res->space);
    330 	exp_space = isl_reordering_peek_space(exp);
    331 	res->space = isl_space_replace_params(space, exp_space);
    332 
    333 	isl_reordering_free(exp);
    334 
    335 	if (!res->space)
    336 		return isl_reordering_free(res);
    337 
    338 	return res;
    339 error:
    340 	isl_reordering_free(exp);
    341 	isl_space_free(space);
    342 	return NULL;
    343 }
    344 
    345 void isl_reordering_dump(__isl_keep isl_reordering *exp)
    346 {
    347 	int i;
    348 
    349 	isl_space_dump(exp->space);
    350 	for (i = 0; i < exp->src_len; ++i)
    351 		fprintf(stderr, "%d -> %d; ", i, exp->pos[i]);
    352 	fprintf(stderr, "\n");
    353 }
    354