/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_local.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2011 INRIA Saclay |
3 | | * Copyright 2014 Ecole Normale Superieure |
4 | | * |
5 | | * Use of this software is governed by the MIT license |
6 | | * |
7 | | * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France, |
8 | | * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod, |
9 | | * 91893 Orsay, France |
10 | | * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France |
11 | | */ |
12 | | |
13 | | #include <isl/space.h> |
14 | | #include <isl_vec_private.h> |
15 | | #include <isl_mat_private.h> |
16 | | #include <isl_reordering.h> |
17 | | #include <isl_seq.h> |
18 | | #include <isl_local.h> |
19 | | |
20 | | /* Return the isl_ctx to which "local" belongs. |
21 | | */ |
22 | | isl_ctx *isl_local_get_ctx(__isl_keep isl_local *local) |
23 | 0 | { |
24 | 0 | if (!local) |
25 | 0 | return NULL; |
26 | 0 | |
27 | 0 | return isl_mat_get_ctx(local); |
28 | 0 | } |
29 | | |
30 | | /* Create an isl_local object from a matrix describing |
31 | | * integer divisions. |
32 | | * |
33 | | * An isl_local object is current defined as exactly such a matrix, |
34 | | * so simply return the input. |
35 | | */ |
36 | | __isl_give isl_local *isl_local_alloc_from_mat(__isl_take isl_mat *mat) |
37 | 10.2k | { |
38 | 10.2k | return mat; |
39 | 10.2k | } |
40 | | |
41 | | /* Free "local" and return NULL. |
42 | | */ |
43 | | __isl_null isl_local *isl_local_free(__isl_take isl_local *local) |
44 | 10.2k | { |
45 | 10.2k | isl_mat_free(local); |
46 | 10.2k | return NULL; |
47 | 10.2k | } |
48 | | |
49 | | /* Return the number of local variables (isl_dim_div), |
50 | | * the number of other variables (isl_dim_set) or |
51 | | * the total number of variables (isl_dim_all) in "local". |
52 | | * |
53 | | * Other types do not have any meaning for an isl_local object. |
54 | | */ |
55 | | int isl_local_dim(__isl_keep isl_local *local, enum isl_dim_type type) |
56 | 504k | { |
57 | 504k | isl_mat *mat = local; |
58 | 504k | |
59 | 504k | if (!local) |
60 | 0 | return 0; |
61 | 504k | if (type == isl_dim_div) |
62 | 503k | return isl_mat_rows(mat); |
63 | 64 | if (type == isl_dim_all) |
64 | 32 | return isl_mat_cols(mat) - 2; |
65 | 32 | if (type == isl_dim_set) |
66 | 32 | return isl_local_dim(local, isl_dim_all) - |
67 | 32 | isl_local_dim(local, isl_dim_div); |
68 | 0 | isl_die(isl_local_get_ctx(local), isl_error_unsupported, |
69 | 0 | "unsupported dimension type", return 0); |
70 | 0 | } |
71 | | |
72 | | /* Check that "pos" is a valid position for a variable in "local". |
73 | | */ |
74 | | static isl_stat isl_local_check_pos(__isl_keep isl_local *local, int pos) |
75 | 170k | { |
76 | 170k | if (!local) |
77 | 0 | return isl_stat_error; |
78 | 170k | if (pos < 0 || pos >= isl_local_dim(local, isl_dim_div)) |
79 | 170k | isl_die0 (isl_local_get_ctx(local), isl_error_invalid, |
80 | 170k | "position out of bounds", return isl_stat_error); |
81 | 170k | return isl_stat_ok; |
82 | 170k | } |
83 | | |
84 | | /* Given local variables "local", |
85 | | * is the variable at position "pos" marked as not having |
86 | | * an explicit representation? |
87 | | * Note that even if this variable is not marked in this way and therefore |
88 | | * does have an explicit representation, this representation may still |
89 | | * depend (indirectly) on other local variables that do not |
90 | | * have an explicit representation. |
91 | | */ |
92 | | isl_bool isl_local_div_is_marked_unknown(__isl_keep isl_local *local, int pos) |
93 | 168k | { |
94 | 168k | isl_mat *mat = local; |
95 | 168k | |
96 | 168k | if (isl_local_check_pos(local, pos) < 0) |
97 | 0 | return isl_bool_error; |
98 | 168k | return isl_int_is_zero(mat->row[pos][0]); |
99 | 168k | } |
100 | | |
101 | | /* Given local variables "local", |
102 | | * does the variable at position "pos" have a complete explicit representation? |
103 | | * Having a complete explicit representation requires not only |
104 | | * an explicit representation, but also that all local variables |
105 | | * that appear in this explicit representation in turn have |
106 | | * a complete explicit representation. |
107 | | */ |
108 | | isl_bool isl_local_div_is_known(__isl_keep isl_local *local, int pos) |
109 | 2.05k | { |
110 | 2.05k | isl_bool marked; |
111 | 2.05k | int i, n, off; |
112 | 2.05k | isl_mat *mat = local; |
113 | 2.05k | |
114 | 2.05k | if (isl_local_check_pos(local, pos) < 0) |
115 | 0 | return isl_bool_error; |
116 | 2.05k | |
117 | 2.05k | marked = isl_local_div_is_marked_unknown(local, pos); |
118 | 2.05k | if (marked < 0 || marked) |
119 | 27 | return isl_bool_not(marked); |
120 | 2.03k | |
121 | 2.03k | n = isl_local_dim(local, isl_dim_div); |
122 | 2.03k | off = isl_mat_cols(mat) - n; |
123 | 2.03k | |
124 | 6.24k | for (i = n - 1; i >= 0; --i4.20k ) { |
125 | 4.20k | isl_bool known; |
126 | 4.20k | |
127 | 4.20k | if (isl_int_is_zero(mat->row[pos][off + i])) |
128 | 4.20k | continue4.20k ; |
129 | 2 | known = isl_local_div_is_known(local, i); |
130 | 2 | if (known < 0 || !known) |
131 | 0 | return known; |
132 | 2 | } |
133 | 2.03k | |
134 | 2.03k | return isl_bool_true; |
135 | 2.03k | } |
136 | | |
137 | | /* Does "local" have an explicit representation for all local variables? |
138 | | */ |
139 | | isl_bool isl_local_divs_known(__isl_keep isl_local *local) |
140 | 331k | { |
141 | 331k | int i, n; |
142 | 331k | |
143 | 331k | if (!local) |
144 | 0 | return isl_bool_error; |
145 | 331k | |
146 | 331k | n = isl_local_dim(local, isl_dim_div); |
147 | 496k | for (i = 0; i < n; ++i165k ) { |
148 | 165k | isl_bool unknown = isl_local_div_is_marked_unknown(local, i); |
149 | 165k | if (unknown < 0 || unknown) |
150 | 0 | return isl_bool_not(unknown); |
151 | 165k | } |
152 | 331k | |
153 | 331k | return isl_bool_true; |
154 | 331k | } |
155 | | |
156 | | /* Compare two sets of local variables, defined over |
157 | | * the same space. |
158 | | * |
159 | | * Return -1 if "local1" is "smaller" than "local2", 1 if "local1" is "greater" |
160 | | * than "local2" and 0 if they are equal. |
161 | | * |
162 | | * The order is fairly arbitrary. We do "prefer" divs that only involve |
163 | | * earlier dimensions in the sense that we consider matrices where |
164 | | * the first differing div involves earlier dimensions to be smaller. |
165 | | */ |
166 | | int isl_local_cmp(__isl_keep isl_local *local1, __isl_keep isl_local *local2) |
167 | 18.2k | { |
168 | 18.2k | int i; |
169 | 18.2k | int cmp; |
170 | 18.2k | isl_bool unknown1, unknown2; |
171 | 18.2k | int last1, last2; |
172 | 18.2k | int n_col; |
173 | 18.2k | isl_mat *mat1 = local1; |
174 | 18.2k | isl_mat *mat2 = local2; |
175 | 18.2k | |
176 | 18.2k | if (local1 == local2) |
177 | 0 | return 0; |
178 | 18.2k | if (!local1) |
179 | 0 | return -1; |
180 | 18.2k | if (!local2) |
181 | 0 | return 1; |
182 | 18.2k | |
183 | 18.2k | if (mat1->n_row != mat2->n_row) |
184 | 1.33k | return mat1->n_row - mat2->n_row; |
185 | 16.8k | |
186 | 16.8k | n_col = isl_mat_cols(mat1); |
187 | 17.0k | for (i = 0; i < mat1->n_row; ++i169 ) { |
188 | 697 | unknown1 = isl_local_div_is_marked_unknown(local1, i); |
189 | 697 | unknown2 = isl_local_div_is_marked_unknown(local2, i); |
190 | 697 | if (unknown1 && unknown20 ) |
191 | 0 | continue; |
192 | 697 | if (unknown1) |
193 | 0 | return 1; |
194 | 697 | if (unknown2) |
195 | 0 | return -1; |
196 | 697 | last1 = isl_seq_last_non_zero(mat1->row[i] + 1, n_col - 1); |
197 | 697 | last2 = isl_seq_last_non_zero(mat2->row[i] + 1, n_col - 1); |
198 | 697 | if (last1 != last2) |
199 | 183 | return last1 - last2; |
200 | 514 | cmp = isl_seq_cmp(mat1->row[i], mat2->row[i], n_col); |
201 | 514 | if (cmp != 0) |
202 | 345 | return cmp; |
203 | 514 | } |
204 | 16.8k | |
205 | 16.8k | return 016.3k ; |
206 | 16.8k | } |
207 | | |
208 | | /* Reorder the columns of the given local variables according to the |
209 | | * given reordering. |
210 | | * The order of the local variables themselves is assumed not to change. |
211 | | */ |
212 | | __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local, |
213 | | __isl_take isl_reordering *r) |
214 | 10.2k | { |
215 | 10.2k | isl_mat *div = local; |
216 | 10.2k | int i, j; |
217 | 10.2k | isl_space *space; |
218 | 10.2k | isl_mat *mat; |
219 | 10.2k | int extra; |
220 | 10.2k | |
221 | 10.2k | if (!local || !r) |
222 | 0 | goto error; |
223 | 10.2k | |
224 | 10.2k | space = isl_reordering_peek_space(r); |
225 | 10.2k | extra = isl_space_dim(space, isl_dim_all) + div->n_row - r->len; |
226 | 10.2k | mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra); |
227 | 10.2k | if (!mat) |
228 | 0 | goto error; |
229 | 10.2k | |
230 | 10.6k | for (i = 0; 10.2k i < div->n_row; ++i405 ) { |
231 | 405 | isl_seq_cpy(mat->row[i], div->row[i], 2); |
232 | 405 | isl_seq_clr(mat->row[i] + 2, mat->n_col - 2); |
233 | 1.89k | for (j = 0; j < r->len; ++j1.48k ) |
234 | 1.48k | isl_int_set(mat->row[i][2 + r->pos[j]], |
235 | 405 | div->row[i][2 + j]); |
236 | 405 | } |
237 | 10.2k | |
238 | 10.2k | isl_reordering_free(r); |
239 | 10.2k | isl_local_free(local); |
240 | 10.2k | return isl_local_alloc_from_mat(mat); |
241 | 0 | error: |
242 | 0 | isl_reordering_free(r); |
243 | 0 | isl_local_free(local); |
244 | 0 | return NULL; |
245 | 10.2k | } |
246 | | |
247 | | /* Extend a vector "v" representing an integer point |
248 | | * in the domain space of "local" |
249 | | * to one that also includes values for the local variables. |
250 | | * All local variables are required to have an explicit representation. |
251 | | */ |
252 | | __isl_give isl_vec *isl_local_extend_point_vec(__isl_keep isl_local *local, |
253 | | __isl_take isl_vec *v) |
254 | 20 | { |
255 | 20 | unsigned n_div; |
256 | 20 | isl_bool known; |
257 | 20 | isl_mat *mat = local; |
258 | 20 | |
259 | 20 | if (!local || !v) |
260 | 0 | return isl_vec_free(v); |
261 | 20 | known = isl_local_divs_known(local); |
262 | 20 | if (known < 0) |
263 | 0 | return isl_vec_free(v); |
264 | 20 | if (!known) |
265 | 20 | isl_die0 (isl_local_get_ctx(local), isl_error_invalid, |
266 | 20 | "unknown local variables", return isl_vec_free(v)); |
267 | 20 | if (isl_vec_size(v) != 1 + isl_local_dim(local, isl_dim_set)) |
268 | 20 | isl_die0 (isl_local_get_ctx(local), isl_error_invalid, |
269 | 20 | "incorrect size", return isl_vec_free(v)); |
270 | 20 | if (!isl_int_is_one(v->el[0])) |
271 | 20 | isl_die0 (isl_local_get_ctx(local), isl_error_invalid, |
272 | 20 | "expecting integer point", return isl_vec_free(v)); |
273 | 20 | n_div = isl_local_dim(local, isl_dim_div); |
274 | 20 | if (n_div != 0) { |
275 | 12 | int i; |
276 | 12 | unsigned dim = isl_local_dim(local, isl_dim_set); |
277 | 12 | v = isl_vec_add_els(v, n_div); |
278 | 12 | if (!v) |
279 | 0 | return NULL; |
280 | 12 | |
281 | 36 | for (i = 0; 12 i < n_div; ++i24 ) { |
282 | 24 | isl_seq_inner_product(mat->row[i] + 1, v->el, |
283 | 24 | 1 + dim + i, &v->el[1+dim+i]); |
284 | 24 | isl_int_fdiv_q(v->el[1+dim+i], v->el[1+dim+i], |
285 | 24 | mat->row[i][0]); |
286 | 24 | } |
287 | 12 | } |
288 | 20 | |
289 | 20 | return v; |
290 | 20 | } |