Merge branch 'maint'
[platform/upstream/isl.git] / isl_reordering.c
1 /*
2  * Copyright 2010      INRIA Saclay
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 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_dim_private.h>
13 #include <isl_reordering.h>
14
15 __isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int len)
16 {
17         isl_reordering *exp;
18
19         exp = isl_alloc(ctx, struct isl_reordering,
20                         sizeof(struct isl_reordering) + (len - 1) * sizeof(int));
21         if (!exp)
22                 return NULL;
23
24         exp->ref = 1;
25         exp->len = len;
26         exp->dim = NULL;
27
28         return exp;
29 }
30
31 __isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp)
32 {
33         if (!exp)
34                 return NULL;
35
36         exp->ref++;
37         return exp;
38 }
39
40 void isl_reordering_free(__isl_take isl_reordering *exp)
41 {
42         if (!exp)
43                 return;
44
45         if (--exp->ref > 0)
46                 return;
47
48         isl_dim_free(exp->dim);
49         free(exp);
50 }
51
52 /* Construct a reordering that maps the parameters of "alignee"
53  * to the corresponding parameters in a new dimension specification
54  * that has the parameters of "aligner" first, followed by
55  * any remaining parameters of "alignee" that do not occur in "aligner".
56  */
57 __isl_give isl_reordering *isl_parameter_alignment_reordering(
58         __isl_keep isl_dim *alignee, __isl_keep isl_dim *aligner)
59 {
60         int i, j;
61         isl_reordering *exp;
62
63         if (!alignee || !aligner)
64                 return NULL;
65
66         exp = isl_reordering_alloc(alignee->ctx, alignee->nparam);
67         if (!exp)
68                 return NULL;
69
70         exp->dim = isl_dim_copy(aligner);
71
72         for (i = 0; i < alignee->nparam; ++i) {
73                 const char *name_i;
74                 name_i = isl_dim_get_name(alignee, isl_dim_param, i);
75                 if (!name_i)
76                         isl_die(alignee->ctx, isl_error_invalid,
77                                 "cannot align unnamed parameters", goto error);
78                 for (j = 0; j < aligner->nparam; ++j) {
79                         const char *name_j;
80                         name_j = isl_dim_get_name(aligner, isl_dim_param, j);
81                         if (name_i == name_j)
82                                 break;
83                 }
84                 if (j < aligner->nparam)
85                         exp->pos[i] = j;
86                 else {
87                         int pos;
88                         pos = isl_dim_size(exp->dim, isl_dim_param);
89                         exp->dim = isl_dim_add(exp->dim, isl_dim_param, 1);
90                         exp->dim = isl_dim_set_name(exp->dim,
91                                                 isl_dim_param, pos, name_i);
92                         exp->pos[i] = pos;
93                 }
94         }
95
96         return exp;
97 error:
98         isl_reordering_free(exp);
99         return NULL;
100 }
101
102 __isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
103         unsigned extra)
104 {
105         int i;
106         isl_reordering *res;
107         int offset;
108
109         if (!exp)
110                 return NULL;
111         if (extra == 0)
112                 return exp;
113
114         offset = isl_dim_total(exp->dim) - exp->len;
115         res = isl_reordering_alloc(exp->dim->ctx, exp->len + extra);
116         if (!res)
117                 goto error;
118         res->dim = isl_dim_copy(exp->dim);
119         for (i = 0; i < exp->len; ++i)
120                 res->pos[i] = exp->pos[i];
121         for (i = exp->len; i < res->len; ++i)
122                 res->pos[i] = offset + i;
123
124         isl_reordering_free(exp);
125
126         return res;
127 error:
128         isl_reordering_free(exp);
129         return NULL;
130 }
131
132 __isl_give isl_reordering *isl_reordering_extend_dim(
133         __isl_take isl_reordering *exp, __isl_take isl_dim *dim)
134 {
135         isl_reordering *res;
136
137         if (!exp || !dim)
138                 goto error;
139
140         res = isl_reordering_extend(isl_reordering_copy(exp),
141                                             isl_dim_total(dim) - exp->len);
142         if (!res)
143                 goto error;
144         isl_dim_free(res->dim);
145         res->dim = isl_dim_replace(dim, isl_dim_param, exp->dim);
146
147         isl_reordering_free(exp);
148
149         return res;
150 error:
151         isl_reordering_free(exp);
152         isl_dim_free(dim);
153         return NULL;
154 }
155
156 void isl_reordering_dump(__isl_keep isl_reordering *exp)
157 {
158         int i;
159
160         for (i = 0; i < exp->len; ++i)
161                 fprintf(stderr, "%d -> %d; ", i, exp->pos[i]);
162         fprintf(stderr, "\n");
163 }