/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/External/isl/isl_map_simplify.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2008-2009 Katholieke Universiteit Leuven |
3 | | * Copyright 2012-2013 Ecole Normale Superieure |
4 | | * Copyright 2014-2015 INRIA Rocquencourt |
5 | | * Copyright 2016 Sven Verdoolaege |
6 | | * |
7 | | * Use of this software is governed by the MIT license |
8 | | * |
9 | | * Written by Sven Verdoolaege, K.U.Leuven, Departement |
10 | | * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium |
11 | | * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France |
12 | | * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt, |
13 | | * B.P. 105 - 78153 Le Chesnay, France |
14 | | */ |
15 | | |
16 | | #include <isl_ctx_private.h> |
17 | | #include <isl_map_private.h> |
18 | | #include "isl_equalities.h" |
19 | | #include <isl/map.h> |
20 | | #include <isl_seq.h> |
21 | | #include "isl_tab.h" |
22 | | #include <isl_space_private.h> |
23 | | #include <isl_mat_private.h> |
24 | | #include <isl_vec_private.h> |
25 | | |
26 | | #include <bset_to_bmap.c> |
27 | | #include <bset_from_bmap.c> |
28 | | #include <set_to_map.c> |
29 | | #include <set_from_map.c> |
30 | | |
31 | | static void swap_equality(struct isl_basic_map *bmap, int a, int b) |
32 | 1.52M | { |
33 | 1.52M | isl_int *t = bmap->eq[a]; |
34 | 1.52M | bmap->eq[a] = bmap->eq[b]; |
35 | 1.52M | bmap->eq[b] = t; |
36 | 1.52M | } |
37 | | |
38 | | static void swap_inequality(struct isl_basic_map *bmap, int a, int b) |
39 | 126k | { |
40 | 126k | if (a != b) { |
41 | 126k | isl_int *t = bmap->ineq[a]; |
42 | 126k | bmap->ineq[a] = bmap->ineq[b]; |
43 | 126k | bmap->ineq[b] = t; |
44 | 126k | } |
45 | 126k | } |
46 | | |
47 | | __isl_give isl_basic_map *isl_basic_map_normalize_constraints( |
48 | | __isl_take isl_basic_map *bmap) |
49 | 5.18M | { |
50 | 5.18M | int i; |
51 | 5.18M | isl_int gcd; |
52 | 5.18M | unsigned total = isl_basic_map_total_dim(bmap); |
53 | 5.18M | |
54 | 5.18M | if (!bmap) |
55 | 0 | return NULL; |
56 | 5.18M | |
57 | 5.18M | isl_int_init(gcd); |
58 | 12.3M | for (i = bmap->n_eq - 1; i >= 0; --i7.17M ) { |
59 | 7.17M | isl_seq_gcd(bmap->eq[i]+1, total, &gcd); |
60 | 7.17M | if (isl_int_is_zero(gcd)) { |
61 | 717k | if (!isl_int_is_zero(bmap->eq[i][0])) { |
62 | 559 | bmap = isl_basic_map_set_to_empty(bmap); |
63 | 559 | break; |
64 | 559 | } |
65 | 716k | isl_basic_map_drop_equality(bmap, i); |
66 | 716k | continue; |
67 | 716k | } |
68 | 6.46M | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) |
69 | 6.46M | isl_int_gcd189k (gcd, gcd, bmap->eq[i][0]); |
70 | 6.46M | if (isl_int_is_one(gcd)) |
71 | 6.46M | continue6.42M ; |
72 | 35.9k | if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) { |
73 | 1.37k | bmap = isl_basic_map_set_to_empty(bmap); |
74 | 1.37k | break; |
75 | 1.37k | } |
76 | 34.6k | isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total); |
77 | 34.6k | } |
78 | 5.18M | |
79 | 29.8M | for (i = bmap->n_ineq - 1; i >= 0; --i24.6M ) { |
80 | 24.7M | isl_seq_gcd(bmap->ineq[i]+1, total, &gcd); |
81 | 24.7M | if (isl_int_is_zero(gcd)) { |
82 | 1.06M | if (isl_int_is_neg(bmap->ineq[i][0])) { |
83 | 91.6k | bmap = isl_basic_map_set_to_empty(bmap); |
84 | 91.6k | break; |
85 | 91.6k | } |
86 | 974k | isl_basic_map_drop_inequality(bmap, i); |
87 | 974k | continue; |
88 | 974k | } |
89 | 23.7M | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) |
90 | 23.7M | isl_int_gcd370k (gcd, gcd, bmap->ineq[i][0]); |
91 | 23.7M | if (isl_int_is_one(gcd)) |
92 | 23.7M | continue23.5M ; |
93 | 192k | isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd); |
94 | 192k | isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total); |
95 | 192k | } |
96 | 5.18M | isl_int_clear(gcd); |
97 | 5.18M | |
98 | 5.18M | return bmap; |
99 | 5.18M | } |
100 | | |
101 | | __isl_give isl_basic_set *isl_basic_set_normalize_constraints( |
102 | | __isl_take isl_basic_set *bset) |
103 | 693k | { |
104 | 693k | isl_basic_map *bmap = bset_to_bmap(bset); |
105 | 693k | return bset_from_bmap(isl_basic_map_normalize_constraints(bmap)); |
106 | 693k | } |
107 | | |
108 | | /* Reduce the coefficient of the variable at position "pos" |
109 | | * in integer division "div", such that it lies in the half-open |
110 | | * interval (1/2,1/2], extracting any excess value from this integer division. |
111 | | * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0 |
112 | | * corresponds to the constant term. |
113 | | * |
114 | | * That is, the integer division is of the form |
115 | | * |
116 | | * floor((... + (c * d + r) * x_pos + ...)/d) |
117 | | * |
118 | | * with -d < 2 * r <= d. |
119 | | * Replace it by |
120 | | * |
121 | | * floor((... + r * x_pos + ...)/d) + c * x_pos |
122 | | * |
123 | | * If 2 * ((c * d + r) % d) <= d, then c = floor((c * d + r)/d). |
124 | | * Otherwise, c = floor((c * d + r)/d) + 1. |
125 | | * |
126 | | * This is the same normalization that is performed by isl_aff_floor. |
127 | | */ |
128 | | static __isl_give isl_basic_map *reduce_coefficient_in_div( |
129 | | __isl_take isl_basic_map *bmap, int div, int pos) |
130 | 17.5k | { |
131 | 17.5k | isl_int shift; |
132 | 17.5k | int add_one; |
133 | 17.5k | |
134 | 17.5k | isl_int_init(shift); |
135 | 17.5k | isl_int_fdiv_r(shift, bmap->div[div][1 + pos], bmap->div[div][0]); |
136 | 17.5k | isl_int_mul_ui(shift, shift, 2); |
137 | 17.5k | add_one = isl_int_gt(shift, bmap->div[div][0]); |
138 | 17.5k | isl_int_fdiv_q(shift, bmap->div[div][1 + pos], bmap->div[div][0]); |
139 | 17.5k | if (add_one) |
140 | 17.5k | isl_int_add_ui4.42k (shift, shift, 1); |
141 | 17.5k | isl_int_neg(shift, shift); |
142 | 17.5k | bmap = isl_basic_map_shift_div(bmap, div, pos, shift); |
143 | 17.5k | isl_int_clear(shift); |
144 | 17.5k | |
145 | 17.5k | return bmap; |
146 | 17.5k | } |
147 | | |
148 | | /* Does the coefficient of the variable at position "pos" |
149 | | * in integer division "div" need to be reduced? |
150 | | * That is, does it lie outside the half-open interval (1/2,1/2]? |
151 | | * The coefficient c/d lies outside this interval if abs(2 * c) >= d and |
152 | | * 2 * c != d. |
153 | | */ |
154 | | static isl_bool needs_reduction(__isl_keep isl_basic_map *bmap, int div, |
155 | | int pos) |
156 | 1.91M | { |
157 | 1.91M | isl_bool r; |
158 | 1.91M | |
159 | 1.91M | if (isl_int_is_zero(bmap->div[div][1 + pos])) |
160 | 1.91M | return isl_bool_false1.59M ; |
161 | 317k | |
162 | 317k | isl_int_mul_ui(bmap->div[div][1 + pos], bmap->div[div][1 + pos], 2); |
163 | 317k | r = isl_int_abs_ge(bmap->div[div][1 + pos], bmap->div[div][0]) && |
164 | 317k | !108k isl_int_eq108k (bmap->div[div][1 + pos], bmap->div[div][0]); |
165 | 317k | isl_int_divexact_ui(bmap->div[div][1 + pos], |
166 | 317k | bmap->div[div][1 + pos], 2); |
167 | 317k | |
168 | 317k | return r; |
169 | 317k | } |
170 | | |
171 | | /* Reduce the coefficients (including the constant term) of |
172 | | * integer division "div", if needed. |
173 | | * In particular, make sure all coefficients lie in |
174 | | * the half-open interval (1/2,1/2]. |
175 | | */ |
176 | | static __isl_give isl_basic_map *reduce_div_coefficients_of_div( |
177 | | __isl_take isl_basic_map *bmap, int div) |
178 | 185k | { |
179 | 185k | int i; |
180 | 185k | unsigned total = 1 + isl_basic_map_total_dim(bmap); |
181 | 185k | |
182 | 2.09M | for (i = 0; i < total; ++i1.91M ) { |
183 | 1.91M | isl_bool reduce; |
184 | 1.91M | |
185 | 1.91M | reduce = needs_reduction(bmap, div, i); |
186 | 1.91M | if (reduce < 0) |
187 | 0 | return isl_basic_map_free(bmap); |
188 | 1.91M | if (!reduce) |
189 | 1.89M | continue; |
190 | 17.5k | bmap = reduce_coefficient_in_div(bmap, div, i); |
191 | 17.5k | if (!bmap) |
192 | 0 | break; |
193 | 17.5k | } |
194 | 185k | |
195 | 185k | return bmap; |
196 | 185k | } |
197 | | |
198 | | /* Reduce the coefficients (including the constant term) of |
199 | | * the known integer divisions, if needed |
200 | | * In particular, make sure all coefficients lie in |
201 | | * the half-open interval (1/2,1/2]. |
202 | | */ |
203 | | static __isl_give isl_basic_map *reduce_div_coefficients( |
204 | | __isl_take isl_basic_map *bmap) |
205 | 4.45M | { |
206 | 4.45M | int i; |
207 | 4.45M | |
208 | 4.45M | if (!bmap) |
209 | 0 | return NULL; |
210 | 4.45M | if (bmap->n_div == 0) |
211 | 4.10M | return bmap; |
212 | 356k | |
213 | 1.12M | for (i = 0; 356k i < bmap->n_div; ++i768k ) { |
214 | 768k | if (isl_int_is_zero(bmap->div[i][0])) |
215 | 768k | continue582k ; |
216 | 185k | bmap = reduce_div_coefficients_of_div(bmap, i); |
217 | 185k | if (!bmap) |
218 | 0 | break; |
219 | 185k | } |
220 | 356k | |
221 | 356k | return bmap; |
222 | 356k | } |
223 | | |
224 | | /* Remove any common factor in numerator and denominator of the div expression, |
225 | | * not taking into account the constant term. |
226 | | * That is, if the div is of the form |
227 | | * |
228 | | * floor((a + m f(x))/(m d)) |
229 | | * |
230 | | * then replace it by |
231 | | * |
232 | | * floor((floor(a/m) + f(x))/d) |
233 | | * |
234 | | * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d |
235 | | * and can therefore not influence the result of the floor. |
236 | | */ |
237 | | static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div) |
238 | 789k | { |
239 | 789k | unsigned total = isl_basic_map_total_dim(bmap); |
240 | 789k | isl_ctx *ctx = bmap->ctx; |
241 | 789k | |
242 | 789k | if (isl_int_is_zero(bmap->div[div][0])) |
243 | 789k | return582k ; |
244 | 206k | isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd); |
245 | 206k | isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0]); |
246 | 206k | if (isl_int_is_one(ctx->normalize_gcd)) |
247 | 206k | return199k ; |
248 | 7.12k | isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1], |
249 | 7.12k | ctx->normalize_gcd); |
250 | 7.12k | isl_int_divexact(bmap->div[div][0], bmap->div[div][0], |
251 | 7.12k | ctx->normalize_gcd); |
252 | 7.12k | isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2, |
253 | 7.12k | ctx->normalize_gcd, total); |
254 | 7.12k | } |
255 | | |
256 | | /* Remove any common factor in numerator and denominator of a div expression, |
257 | | * not taking into account the constant term. |
258 | | * That is, look for any div of the form |
259 | | * |
260 | | * floor((a + m f(x))/(m d)) |
261 | | * |
262 | | * and replace it by |
263 | | * |
264 | | * floor((floor(a/m) + f(x))/d) |
265 | | * |
266 | | * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d |
267 | | * and can therefore not influence the result of the floor. |
268 | | */ |
269 | | static __isl_give isl_basic_map *normalize_div_expressions( |
270 | | __isl_take isl_basic_map *bmap) |
271 | 4.45M | { |
272 | 4.45M | int i; |
273 | 4.45M | |
274 | 4.45M | if (!bmap) |
275 | 0 | return NULL; |
276 | 4.45M | if (bmap->n_div == 0) |
277 | 4.10M | return bmap; |
278 | 356k | |
279 | 1.12M | for (i = 0; 356k i < bmap->n_div; ++i768k ) |
280 | 768k | normalize_div_expression(bmap, i); |
281 | 356k | |
282 | 356k | return bmap; |
283 | 356k | } |
284 | | |
285 | | /* Assumes divs have been ordered if keep_divs is set. |
286 | | */ |
287 | | static void eliminate_var_using_equality(struct isl_basic_map *bmap, |
288 | | unsigned pos, isl_int *eq, int keep_divs, int *progress) |
289 | 9.02M | { |
290 | 9.02M | unsigned total; |
291 | 9.02M | unsigned space_total; |
292 | 9.02M | int k; |
293 | 9.02M | int last_div; |
294 | 9.02M | |
295 | 9.02M | total = isl_basic_map_total_dim(bmap); |
296 | 9.02M | space_total = isl_space_dim(bmap->dim, isl_dim_all); |
297 | 9.02M | last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div); |
298 | 59.8M | for (k = 0; k < bmap->n_eq; ++k50.8M ) { |
299 | 50.8M | if (bmap->eq[k] == eq) |
300 | 9.01M | continue; |
301 | 41.7M | if (isl_int_is_zero(bmap->eq[k][1+pos])) |
302 | 41.7M | continue39.5M ; |
303 | 2.28M | if (progress) |
304 | 383k | *progress = 1; |
305 | 2.28M | isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL); |
306 | 2.28M | isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total); |
307 | 2.28M | } |
308 | 9.02M | |
309 | 60.2M | for (k = 0; k < bmap->n_ineq; ++k51.2M ) { |
310 | 51.2M | if (isl_int_is_zero(bmap->ineq[k][1+pos])) |
311 | 51.2M | continue49.8M ; |
312 | 1.41M | if (progress) |
313 | 785k | *progress = 1; |
314 | 1.41M | isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL); |
315 | 1.41M | isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total); |
316 | 1.41M | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
317 | 1.41M | } |
318 | 9.02M | |
319 | 10.8M | for (k = 0; k < bmap->n_div; ++k1.77M ) { |
320 | 1.77M | if (isl_int_is_zero(bmap->div[k][0])) |
321 | 1.77M | continue1.21M ; |
322 | 568k | if (isl_int_is_zero(bmap->div[k][1+1+pos])) |
323 | 568k | continue547k ; |
324 | 21.2k | if (progress) |
325 | 12.9k | *progress = 1; |
326 | 21.2k | /* We need to be careful about circular definitions, |
327 | 21.2k | * so for now we just remove the definition of div k |
328 | 21.2k | * if the equality contains any divs. |
329 | 21.2k | * If keep_divs is set, then the divs have been ordered |
330 | 21.2k | * and we can keep the definition as long as the result |
331 | 21.2k | * is still ordered. |
332 | 21.2k | */ |
333 | 21.2k | if (last_div == -1 || (6.39k keep_divs6.39k && last_div < k6.39k )) { |
334 | 21.2k | isl_seq_elim(bmap->div[k]+1, eq, |
335 | 21.2k | 1+pos, 1+total, &bmap->div[k][0]); |
336 | 21.2k | normalize_div_expression(bmap, k); |
337 | 21.2k | } else |
338 | 0 | isl_seq_clr(bmap->div[k], 1 + total); |
339 | 21.2k | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
340 | 21.2k | } |
341 | 9.02M | } |
342 | | |
343 | | /* Assumes divs have been ordered if keep_divs is set. |
344 | | */ |
345 | | static __isl_give isl_basic_map *eliminate_div(__isl_take isl_basic_map *bmap, |
346 | | isl_int *eq, unsigned div, int keep_divs) |
347 | 483k | { |
348 | 483k | unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div; |
349 | 483k | |
350 | 483k | eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL); |
351 | 483k | |
352 | 483k | bmap = isl_basic_map_drop_div(bmap, div); |
353 | 483k | |
354 | 483k | return bmap; |
355 | 483k | } |
356 | | |
357 | | /* Check if elimination of div "div" using equality "eq" would not |
358 | | * result in a div depending on a later div. |
359 | | */ |
360 | | static isl_bool ok_to_eliminate_div(__isl_keep isl_basic_map *bmap, isl_int *eq, |
361 | | unsigned div) |
362 | 482k | { |
363 | 482k | int k; |
364 | 482k | int last_div; |
365 | 482k | unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all); |
366 | 482k | unsigned pos = space_total + div; |
367 | 482k | |
368 | 482k | last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div); |
369 | 482k | if (last_div < 0 || last_div <= div) |
370 | 470k | return isl_bool_true; |
371 | 12.0k | |
372 | 40.3k | for (k = 0; 12.0k k <= last_div; ++k28.2k ) { |
373 | 39.4k | if (isl_int_is_zero(bmap->div[k][0])) |
374 | 39.4k | continue15.7k ; |
375 | 23.7k | if (!isl_int_is_zero(bmap->div[k][1 + 1 + pos])) |
376 | 23.7k | return isl_bool_false11.2k ; |
377 | 23.7k | } |
378 | 12.0k | |
379 | 12.0k | return isl_bool_true851 ; |
380 | 12.0k | } |
381 | | |
382 | | /* Eliminate divs based on equalities |
383 | | */ |
384 | | static __isl_give isl_basic_map *eliminate_divs_eq( |
385 | | __isl_take isl_basic_map *bmap, int *progress) |
386 | 4.65M | { |
387 | 4.65M | int d; |
388 | 4.65M | int i; |
389 | 4.65M | int modified = 0; |
390 | 4.65M | unsigned off; |
391 | 4.65M | |
392 | 4.65M | bmap = isl_basic_map_order_divs(bmap); |
393 | 4.65M | |
394 | 4.65M | if (!bmap) |
395 | 0 | return NULL; |
396 | 4.65M | |
397 | 4.65M | off = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
398 | 4.65M | |
399 | 5.46M | for (d = bmap->n_div - 1; d >= 0 ; --d809k ) { |
400 | 2.09M | for (i = 0; i < bmap->n_eq; ++i1.28M ) { |
401 | 1.75M | isl_bool ok; |
402 | 1.75M | |
403 | 1.75M | if (!isl_int_is_one(bmap->eq[i][off + d]) && |
404 | 1.75M | !1.34M isl_int_is_negone1.34M (bmap->eq[i][off + d])) |
405 | 1.75M | continue1.27M ; |
406 | 482k | ok = ok_to_eliminate_div(bmap, bmap->eq[i], d); |
407 | 482k | if (ok < 0) |
408 | 0 | return isl_basic_map_free(bmap); |
409 | 482k | if (!ok) |
410 | 11.2k | continue; |
411 | 470k | modified = 1; |
412 | 470k | *progress = 1; |
413 | 470k | bmap = eliminate_div(bmap, bmap->eq[i], d, 1); |
414 | 470k | if (isl_basic_map_drop_equality(bmap, i) < 0) |
415 | 0 | return isl_basic_map_free(bmap); |
416 | 470k | break; |
417 | 470k | } |
418 | 809k | } |
419 | 4.65M | if (modified) |
420 | 200k | return eliminate_divs_eq(bmap, progress); |
421 | 4.45M | return bmap; |
422 | 4.45M | } |
423 | | |
424 | | /* Eliminate divs based on inequalities |
425 | | */ |
426 | | static __isl_give isl_basic_map *eliminate_divs_ineq( |
427 | | __isl_take isl_basic_map *bmap, int *progress) |
428 | 4.45M | { |
429 | 4.45M | int d; |
430 | 4.45M | int i; |
431 | 4.45M | unsigned off; |
432 | 4.45M | struct isl_ctx *ctx; |
433 | 4.45M | |
434 | 4.45M | if (!bmap) |
435 | 0 | return NULL; |
436 | 4.45M | |
437 | 4.45M | ctx = bmap->ctx; |
438 | 4.45M | off = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
439 | 4.45M | |
440 | 4.74M | for (d = bmap->n_div - 1; d >= 0 ; --d284k ) { |
441 | 591k | for (i = 0; i < bmap->n_eq; ++i307k ) |
442 | 395k | if (!isl_int_is_zero(bmap->eq[i][off + d])) |
443 | 395k | break88.4k ; |
444 | 284k | if (i < bmap->n_eq) |
445 | 88.4k | continue; |
446 | 1.06M | for (i = 0; 196k i < bmap->n_ineq; ++i867k ) |
447 | 969k | if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one)) |
448 | 969k | break102k ; |
449 | 196k | if (i < bmap->n_ineq) |
450 | 102k | continue; |
451 | 93.6k | *progress = 1; |
452 | 93.6k | bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1); |
453 | 93.6k | if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) |
454 | 93.6k | break238 ; |
455 | 93.4k | bmap = isl_basic_map_drop_div(bmap, d); |
456 | 93.4k | if (!bmap) |
457 | 0 | break; |
458 | 93.4k | } |
459 | 4.45M | return bmap; |
460 | 4.45M | } |
461 | | |
462 | | /* Does the equality constraint at position "eq" in "bmap" involve |
463 | | * any local variables in the range [first, first + n) |
464 | | * that are not marked as having an explicit representation? |
465 | | */ |
466 | | static isl_bool bmap_eq_involves_unknown_divs(__isl_keep isl_basic_map *bmap, |
467 | | int eq, unsigned first, unsigned n) |
468 | 5.19k | { |
469 | 5.19k | unsigned o_div; |
470 | 5.19k | int i; |
471 | 5.19k | |
472 | 5.19k | if (!bmap) |
473 | 0 | return isl_bool_error; |
474 | 5.19k | |
475 | 5.19k | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
476 | 7.62k | for (i = 0; i < n; ++i2.42k ) { |
477 | 4.17k | isl_bool unknown; |
478 | 4.17k | |
479 | 4.17k | if (isl_int_is_zero(bmap->eq[eq][o_div + first + i])) |
480 | 4.17k | continue2.29k ; |
481 | 1.87k | unknown = isl_basic_map_div_is_marked_unknown(bmap, first + i); |
482 | 1.87k | if (unknown < 0) |
483 | 0 | return isl_bool_error; |
484 | 1.87k | if (unknown) |
485 | 1.74k | return isl_bool_true; |
486 | 1.87k | } |
487 | 5.19k | |
488 | 5.19k | return isl_bool_false3.45k ; |
489 | 5.19k | } |
490 | | |
491 | | /* The last local variable involved in the equality constraint |
492 | | * at position "eq" in "bmap" is the local variable at position "div". |
493 | | * It can therefore be used to extract an explicit representation |
494 | | * for that variable. |
495 | | * Do so unless the local variable already has an explicit representation or |
496 | | * the explicit representation would involve any other local variables |
497 | | * that in turn do not have an explicit representation. |
498 | | * An equality constraint involving local variables without an explicit |
499 | | * representation can be used in isl_basic_map_drop_redundant_divs |
500 | | * to separate out an independent local variable. Introducing |
501 | | * an explicit representation here would block this transformation, |
502 | | * while the partial explicit representation in itself is not very useful. |
503 | | * Set *progress if anything is changed. |
504 | | * |
505 | | * The equality constraint is of the form |
506 | | * |
507 | | * f(x) + n e >= 0 |
508 | | * |
509 | | * with n a positive number. The explicit representation derived from |
510 | | * this constraint is |
511 | | * |
512 | | * floor((-f(x))/n) |
513 | | */ |
514 | | static __isl_give isl_basic_map *set_div_from_eq(__isl_take isl_basic_map *bmap, |
515 | | int div, int eq, int *progress) |
516 | 101k | { |
517 | 101k | unsigned total, o_div; |
518 | 101k | isl_bool involves; |
519 | 101k | |
520 | 101k | if (!bmap) |
521 | 0 | return NULL; |
522 | 101k | |
523 | 101k | if (!isl_int_is_zero(bmap->div[div][0])) |
524 | 101k | return bmap96.7k ; |
525 | 5.19k | |
526 | 5.19k | involves = bmap_eq_involves_unknown_divs(bmap, eq, 0, div); |
527 | 5.19k | if (involves < 0) |
528 | 0 | return isl_basic_map_free(bmap); |
529 | 5.19k | if (involves) |
530 | 1.74k | return bmap; |
531 | 3.45k | |
532 | 3.45k | total = isl_basic_map_dim(bmap, isl_dim_all); |
533 | 3.45k | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
534 | 3.45k | isl_seq_neg(bmap->div[div] + 1, bmap->eq[eq], 1 + total); |
535 | 3.45k | isl_int_set_si(bmap->div[div][1 + o_div + div], 0); |
536 | 3.45k | isl_int_set(bmap->div[div][0], bmap->eq[eq][o_div + div]); |
537 | 3.45k | if (progress) |
538 | 2.90k | *progress = 1; |
539 | 3.45k | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
540 | 3.45k | |
541 | 3.45k | return bmap; |
542 | 3.45k | } |
543 | | |
544 | | __isl_give isl_basic_map *isl_basic_map_gauss(__isl_take isl_basic_map *bmap, |
545 | | int *progress) |
546 | 7.16M | { |
547 | 7.16M | int k; |
548 | 7.16M | int done; |
549 | 7.16M | int last_var; |
550 | 7.16M | unsigned total_var; |
551 | 7.16M | unsigned total; |
552 | 7.16M | |
553 | 7.16M | bmap = isl_basic_map_order_divs(bmap); |
554 | 7.16M | |
555 | 7.16M | if (!bmap) |
556 | 0 | return NULL; |
557 | 7.16M | |
558 | 7.16M | total = isl_basic_map_total_dim(bmap); |
559 | 7.16M | total_var = total - bmap->n_div; |
560 | 7.16M | |
561 | 7.16M | last_var = total - 1; |
562 | 15.7M | for (done = 0; done < bmap->n_eq; ++done8.54M ) { |
563 | 22.8M | for (; last_var >= 0; --last_var13.7M ) { |
564 | 69.9M | for (k = done; k < bmap->n_eq; ++k47.6M ) |
565 | 56.1M | if (!isl_int_is_zero(bmap->eq[k][1+last_var])) |
566 | 56.1M | break8.54M ; |
567 | 22.2M | if (k < bmap->n_eq) |
568 | 8.54M | break; |
569 | 22.2M | } |
570 | 9.12M | if (last_var < 0) |
571 | 578k | break; |
572 | 8.54M | if (k != done) |
573 | 1.52M | swap_equality(bmap, k, done); |
574 | 8.54M | if (isl_int_is_neg(bmap->eq[done][1+last_var])) |
575 | 8.54M | isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total)627k ; |
576 | 8.54M | |
577 | 8.54M | eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1, |
578 | 8.54M | progress); |
579 | 8.54M | |
580 | 8.54M | if (last_var >= total_var) |
581 | 101k | bmap = set_div_from_eq(bmap, last_var - total_var, |
582 | 101k | done, progress); |
583 | 8.54M | if (!bmap) |
584 | 0 | return NULL; |
585 | 8.54M | } |
586 | 7.16M | if (done == bmap->n_eq) |
587 | 6.58M | return bmap; |
588 | 1.90M | for (k = done; 578k k < bmap->n_eq; ++k1.32M ) { |
589 | 1.47M | if (isl_int_is_zero(bmap->eq[k][0])) |
590 | 1.47M | continue1.32M ; |
591 | 141k | return isl_basic_map_set_to_empty(bmap); |
592 | 141k | } |
593 | 578k | isl_basic_map_free_equality(bmap, bmap->n_eq-done); |
594 | 436k | return bmap; |
595 | 578k | } |
596 | | |
597 | | __isl_give isl_basic_set *isl_basic_set_gauss( |
598 | | __isl_take isl_basic_set *bset, int *progress) |
599 | 307k | { |
600 | 307k | return bset_from_bmap(isl_basic_map_gauss(bset_to_bmap(bset), |
601 | 307k | progress)); |
602 | 307k | } |
603 | | |
604 | | |
605 | | static unsigned int round_up(unsigned int v) |
606 | 3.31M | { |
607 | 3.31M | int old_v = v; |
608 | 3.31M | |
609 | 10.6M | while (v) { |
610 | 7.30M | old_v = v; |
611 | 7.30M | v ^= v & -v; |
612 | 7.30M | } |
613 | 3.31M | return old_v << 1; |
614 | 3.31M | } |
615 | | |
616 | | /* Hash table of inequalities in a basic map. |
617 | | * "index" is an array of addresses of inequalities in the basic map, some |
618 | | * of which are NULL. The inequalities are hashed on the coefficients |
619 | | * except the constant term. |
620 | | * "size" is the number of elements in the array and is always a power of two |
621 | | * "bits" is the number of bits need to represent an index into the array. |
622 | | * "total" is the total dimension of the basic map. |
623 | | */ |
624 | | struct isl_constraint_index { |
625 | | unsigned int size; |
626 | | int bits; |
627 | | isl_int ***index; |
628 | | unsigned total; |
629 | | }; |
630 | | |
631 | | /* Fill in the "ci" data structure for holding the inequalities of "bmap". |
632 | | */ |
633 | | static isl_stat create_constraint_index(struct isl_constraint_index *ci, |
634 | | __isl_keep isl_basic_map *bmap) |
635 | 3.26M | { |
636 | 3.26M | isl_ctx *ctx; |
637 | 3.26M | |
638 | 3.26M | ci->index = NULL; |
639 | 3.26M | if (!bmap) |
640 | 0 | return isl_stat_error; |
641 | 3.26M | ci->total = isl_basic_set_total_dim(bmap); |
642 | 3.26M | if (bmap->n_ineq == 0) |
643 | 0 | return isl_stat_ok; |
644 | 3.26M | ci->size = round_up(4 * (bmap->n_ineq + 1) / 3 - 1); |
645 | 3.26M | ci->bits = ffs(ci->size) - 1; |
646 | 3.26M | ctx = isl_basic_map_get_ctx(bmap); |
647 | 3.26M | ci->index = isl_calloc_array(ctx, isl_int **, ci->size); |
648 | 3.26M | if (!ci->index) |
649 | 0 | return isl_stat_error; |
650 | 3.26M | |
651 | 3.26M | return isl_stat_ok; |
652 | 3.26M | } |
653 | | |
654 | | /* Free the memory allocated by create_constraint_index. |
655 | | */ |
656 | | static void constraint_index_free(struct isl_constraint_index *ci) |
657 | 3.26M | { |
658 | 3.26M | free(ci->index); |
659 | 3.26M | } |
660 | | |
661 | | /* Return the position in ci->index that contains the address of |
662 | | * an inequality that is equal to *ineq up to the constant term, |
663 | | * provided this address is not identical to "ineq". |
664 | | * If there is no such inequality, then return the position where |
665 | | * such an inequality should be inserted. |
666 | | */ |
667 | | static int hash_index_ineq(struct isl_constraint_index *ci, isl_int **ineq) |
668 | 37.1M | { |
669 | 37.1M | int h; |
670 | 37.1M | uint32_t hash = isl_seq_get_hash_bits((*ineq) + 1, ci->total, ci->bits); |
671 | 54.5M | for (h = hash; ci->index[h]; h = (h+1) % ci->size17.3M ) |
672 | 32.3M | if (ineq != ci->index[h] && |
673 | 32.3M | isl_seq_eq((*ineq) + 1, ci->index[h][0]+1, ci->total)31.2M ) |
674 | 15.0M | break; |
675 | 37.1M | return h; |
676 | 37.1M | } |
677 | | |
678 | | /* Return the position in ci->index that contains the address of |
679 | | * an inequality that is equal to the k'th inequality of "bmap" |
680 | | * up to the constant term, provided it does not point to the very |
681 | | * same inequality. |
682 | | * If there is no such inequality, then return the position where |
683 | | * such an inequality should be inserted. |
684 | | */ |
685 | | static int hash_index(struct isl_constraint_index *ci, |
686 | | __isl_keep isl_basic_map *bmap, int k) |
687 | 37.1M | { |
688 | 37.1M | return hash_index_ineq(ci, &bmap->ineq[k]); |
689 | 37.1M | } |
690 | | |
691 | | static int set_hash_index(struct isl_constraint_index *ci, |
692 | | __isl_keep isl_basic_set *bset, int k) |
693 | 81.0k | { |
694 | 81.0k | return hash_index(ci, bset, k); |
695 | 81.0k | } |
696 | | |
697 | | /* Fill in the "ci" data structure with the inequalities of "bset". |
698 | | */ |
699 | | static isl_stat setup_constraint_index(struct isl_constraint_index *ci, |
700 | | __isl_keep isl_basic_set *bset) |
701 | 16.2k | { |
702 | 16.2k | int k, h; |
703 | 16.2k | |
704 | 16.2k | if (create_constraint_index(ci, bset) < 0) |
705 | 0 | return isl_stat_error; |
706 | 16.2k | |
707 | 97.2k | for (k = 0; 16.2k k < bset->n_ineq; ++k81.0k ) { |
708 | 81.0k | h = set_hash_index(ci, bset, k); |
709 | 81.0k | ci->index[h] = &bset->ineq[k]; |
710 | 81.0k | } |
711 | 16.2k | |
712 | 16.2k | return isl_stat_ok; |
713 | 16.2k | } |
714 | | |
715 | | /* Is the inequality ineq (obviously) redundant with respect |
716 | | * to the constraints in "ci"? |
717 | | * |
718 | | * Look for an inequality in "ci" with the same coefficients and then |
719 | | * check if the contant term of "ineq" is greater than or equal |
720 | | * to the constant term of that inequality. If so, "ineq" is clearly |
721 | | * redundant. |
722 | | * |
723 | | * Note that hash_index_ineq ignores a stored constraint if it has |
724 | | * the same address as the passed inequality. It is ok to pass |
725 | | * the address of a local variable here since it will never be |
726 | | * the same as the address of a constraint in "ci". |
727 | | */ |
728 | | static isl_bool constraint_index_is_redundant(struct isl_constraint_index *ci, |
729 | | isl_int *ineq) |
730 | 69.1k | { |
731 | 69.1k | int h; |
732 | 69.1k | |
733 | 69.1k | h = hash_index_ineq(ci, &ineq); |
734 | 69.1k | if (!ci->index[h]) |
735 | 16.6k | return isl_bool_false; |
736 | 52.4k | return isl_int_ge(ineq[0], (*ci->index[h])[0]); |
737 | 52.4k | } |
738 | | |
739 | | /* If we can eliminate more than one div, then we need to make |
740 | | * sure we do it from last div to first div, in order not to |
741 | | * change the position of the other divs that still need to |
742 | | * be removed. |
743 | | */ |
744 | | static __isl_give isl_basic_map *remove_duplicate_divs( |
745 | | __isl_take isl_basic_map *bmap, int *progress) |
746 | 4.45M | { |
747 | 4.45M | unsigned int size; |
748 | 4.45M | int *index; |
749 | 4.45M | int *elim_for; |
750 | 4.45M | int k, l, h; |
751 | 4.45M | int bits; |
752 | 4.45M | struct isl_blk eq; |
753 | 4.45M | unsigned total_var; |
754 | 4.45M | unsigned total; |
755 | 4.45M | struct isl_ctx *ctx; |
756 | 4.45M | |
757 | 4.45M | bmap = isl_basic_map_order_divs(bmap); |
758 | 4.45M | if (!bmap || bmap->n_div <= 1) |
759 | 4.27M | return bmap; |
760 | 184k | |
761 | 184k | total_var = isl_space_dim(bmap->dim, isl_dim_all); |
762 | 184k | total = total_var + bmap->n_div; |
763 | 184k | |
764 | 184k | ctx = bmap->ctx; |
765 | 632k | for (k = bmap->n_div - 1; k >= 0; --k447k ) |
766 | 501k | if (!isl_int_is_zero(bmap->div[k][0])) |
767 | 501k | break53.8k ; |
768 | 184k | if (k <= 0) |
769 | 134k | return bmap; |
770 | 50.0k | |
771 | 50.0k | size = round_up(4 * bmap->n_div / 3 - 1); |
772 | 50.0k | if (size == 0) |
773 | 0 | return bmap; |
774 | 50.0k | elim_for = isl_calloc_array(ctx, int, bmap->n_div); |
775 | 50.0k | bits = ffs(size) - 1; |
776 | 50.0k | index = isl_calloc_array(ctx, int, size); |
777 | 50.0k | if (!elim_for || !index) |
778 | 0 | goto out; |
779 | 50.0k | eq = isl_blk_alloc(ctx, 1+total); |
780 | 50.0k | if (isl_blk_is_error(eq)) |
781 | 0 | goto out; |
782 | 50.0k | |
783 | 50.0k | isl_seq_clr(eq.data, 1+total); |
784 | 50.0k | index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1; |
785 | 145k | for (--k; k >= 0; --k95.3k ) { |
786 | 95.3k | uint32_t hash; |
787 | 95.3k | |
788 | 95.3k | if (isl_int_is_zero(bmap->div[k][0])) |
789 | 95.3k | continue24.2k ; |
790 | 71.0k | |
791 | 71.0k | hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits); |
792 | 90.0k | for (h = hash; index[h]; h = (h+1) % size19.0k ) |
793 | 31.3k | if (isl_seq_eq(bmap->div[k], |
794 | 31.3k | bmap->div[index[h]-1], 2+total)) |
795 | 12.2k | break; |
796 | 71.0k | if (index[h]) { |
797 | 12.2k | *progress = 1; |
798 | 12.2k | l = index[h] - 1; |
799 | 12.2k | elim_for[l] = k + 1; |
800 | 12.2k | } |
801 | 71.0k | index[h] = k+1; |
802 | 71.0k | } |
803 | 205k | for (l = bmap->n_div - 1; l >= 0; --l155k ) { |
804 | 155k | if (!elim_for[l]) |
805 | 143k | continue; |
806 | 12.2k | k = elim_for[l] - 1; |
807 | 12.2k | isl_int_set_si(eq.data[1+total_var+k], -1); |
808 | 12.2k | isl_int_set_si(eq.data[1+total_var+l], 1); |
809 | 12.2k | bmap = eliminate_div(bmap, eq.data, l, 1); |
810 | 12.2k | if (!bmap) |
811 | 0 | break; |
812 | 12.2k | isl_int_set_si(eq.data[1+total_var+k], 0); |
813 | 12.2k | isl_int_set_si(eq.data[1+total_var+l], 0); |
814 | 12.2k | } |
815 | 50.0k | |
816 | 50.0k | isl_blk_free(ctx, eq); |
817 | 50.0k | out: |
818 | 50.0k | free(index); |
819 | 50.0k | free(elim_for); |
820 | 50.0k | return bmap; |
821 | 50.0k | } |
822 | | |
823 | | static int n_pure_div_eq(struct isl_basic_map *bmap) |
824 | 45.4k | { |
825 | 45.4k | int i, j; |
826 | 45.4k | unsigned total; |
827 | 45.4k | |
828 | 45.4k | total = isl_space_dim(bmap->dim, isl_dim_all); |
829 | 74.7k | for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i29.3k ) { |
830 | 125k | while (j >= 0 && isl_int_is_zero91.3k (bmap->eq[i][1 + total + j])) |
831 | 67.6k | --j58.1k ; |
832 | 67.6k | if (j < 0) |
833 | 34.4k | break; |
834 | 33.2k | if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1) |
835 | 3.84k | return 0; |
836 | 33.2k | } |
837 | 45.4k | return i41.5k ; |
838 | 45.4k | } |
839 | | |
840 | | /* Normalize divs that appear in equalities. |
841 | | * |
842 | | * In particular, we assume that bmap contains some equalities |
843 | | * of the form |
844 | | * |
845 | | * a x = m * e_i |
846 | | * |
847 | | * and we want to replace the set of e_i by a minimal set and |
848 | | * such that the new e_i have a canonical representation in terms |
849 | | * of the vector x. |
850 | | * If any of the equalities involves more than one divs, then |
851 | | * we currently simply bail out. |
852 | | * |
853 | | * Let us first additionally assume that all equalities involve |
854 | | * a div. The equalities then express modulo constraints on the |
855 | | * remaining variables and we can use "parameter compression" |
856 | | * to find a minimal set of constraints. The result is a transformation |
857 | | * |
858 | | * x = T(x') = x_0 + G x' |
859 | | * |
860 | | * with G a lower-triangular matrix with all elements below the diagonal |
861 | | * non-negative and smaller than the diagonal element on the same row. |
862 | | * We first normalize x_0 by making the same property hold in the affine |
863 | | * T matrix. |
864 | | * The rows i of G with a 1 on the diagonal do not impose any modulo |
865 | | * constraint and simply express x_i = x'_i. |
866 | | * For each of the remaining rows i, we introduce a div and a corresponding |
867 | | * equality. In particular |
868 | | * |
869 | | * g_ii e_j = x_i - g_i(x') |
870 | | * |
871 | | * where each x'_k is replaced either by x_k (if g_kk = 1) or the |
872 | | * corresponding div (if g_kk != 1). |
873 | | * |
874 | | * If there are any equalities not involving any div, then we |
875 | | * first apply a variable compression on the variables x: |
876 | | * |
877 | | * x = C x'' x'' = C_2 x |
878 | | * |
879 | | * and perform the above parameter compression on A C instead of on A. |
880 | | * The resulting compression is then of the form |
881 | | * |
882 | | * x'' = T(x') = x_0 + G x' |
883 | | * |
884 | | * and in constructing the new divs and the corresponding equalities, |
885 | | * we have to replace each x'', i.e., the x'_k with (g_kk = 1), |
886 | | * by the corresponding row from C_2. |
887 | | */ |
888 | | static __isl_give isl_basic_map *normalize_divs(__isl_take isl_basic_map *bmap, |
889 | | int *progress) |
890 | 4.45M | { |
891 | 4.45M | int i, j, k; |
892 | 4.45M | int total; |
893 | 4.45M | int div_eq; |
894 | 4.45M | struct isl_mat *B; |
895 | 4.45M | struct isl_vec *d; |
896 | 4.45M | struct isl_mat *T = NULL; |
897 | 4.45M | struct isl_mat *C = NULL; |
898 | 4.45M | struct isl_mat *C2 = NULL; |
899 | 4.45M | isl_int v; |
900 | 4.45M | int *pos = NULL; |
901 | 4.45M | int dropped, needed; |
902 | 4.45M | |
903 | 4.45M | if (!bmap) |
904 | 0 | return NULL; |
905 | 4.45M | |
906 | 4.45M | if (bmap->n_div == 0) |
907 | 4.34M | return bmap; |
908 | 110k | |
909 | 110k | if (bmap->n_eq == 0) |
910 | 32.0k | return bmap; |
911 | 78.8k | |
912 | 78.8k | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS)) |
913 | 78.8k | return bmap33.4k ; |
914 | 45.4k | |
915 | 45.4k | total = isl_space_dim(bmap->dim, isl_dim_all); |
916 | 45.4k | div_eq = n_pure_div_eq(bmap); |
917 | 45.4k | if (div_eq == 0) |
918 | 21.9k | return bmap; |
919 | 23.4k | |
920 | 23.4k | if (div_eq < bmap->n_eq) { |
921 | 16.3k | B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq, |
922 | 16.3k | bmap->n_eq - div_eq, 0, 1 + total); |
923 | 16.3k | C = isl_mat_variable_compression(B, &C2); |
924 | 16.3k | if (!C || !C2) |
925 | 0 | goto error; |
926 | 16.3k | if (C->n_col == 0) { |
927 | 1 | bmap = isl_basic_map_set_to_empty(bmap); |
928 | 1 | isl_mat_free(C); |
929 | 1 | isl_mat_free(C2); |
930 | 1 | goto done; |
931 | 1 | } |
932 | 23.4k | } |
933 | 23.4k | |
934 | 23.4k | d = isl_vec_alloc(bmap->ctx, div_eq); |
935 | 23.4k | if (!d) |
936 | 0 | goto error; |
937 | 52.7k | for (i = 0, j = bmap->n_div-1; 23.4k i < div_eq; ++i29.2k ) { |
938 | 38.3k | while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j])) |
939 | 29.2k | --j9.10k ; |
940 | 29.2k | isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]); |
941 | 29.2k | } |
942 | 23.4k | B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total); |
943 | 23.4k | |
944 | 23.4k | if (C) { |
945 | 16.3k | B = isl_mat_product(B, C); |
946 | 16.3k | C = NULL; |
947 | 16.3k | } |
948 | 23.4k | |
949 | 23.4k | T = isl_mat_parameter_compression(B, d); |
950 | 23.4k | if (!T) |
951 | 0 | goto error; |
952 | 23.4k | if (T->n_col == 0) { |
953 | 1.92k | bmap = isl_basic_map_set_to_empty(bmap); |
954 | 1.92k | isl_mat_free(C2); |
955 | 1.92k | isl_mat_free(T); |
956 | 1.92k | goto done; |
957 | 1.92k | } |
958 | 21.5k | isl_int_init(v); |
959 | 120k | for (i = 0; i < T->n_row - 1; ++i99.0k ) { |
960 | 99.0k | isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i]); |
961 | 99.0k | if (isl_int_is_zero(v)) |
962 | 99.0k | continue90.7k ; |
963 | 8.32k | isl_mat_col_submul(T, 0, v, 1 + i); |
964 | 8.32k | } |
965 | 21.5k | isl_int_clear(v); |
966 | 21.5k | pos = isl_alloc_array(bmap->ctx, int, T->n_row); |
967 | 21.5k | if (!pos) |
968 | 0 | goto error; |
969 | 21.5k | /* We have to be careful because dropping equalities may reorder them */ |
970 | 21.5k | dropped = 0; |
971 | 58.7k | for (j = bmap->n_div - 1; j >= 0; --j37.2k ) { |
972 | 63.6k | for (i = 0; i < bmap->n_eq; ++i26.4k ) |
973 | 52.6k | if (!isl_int_is_zero(bmap->eq[i][1 + total + j])) |
974 | 52.6k | break26.2k ; |
975 | 37.2k | if (i < bmap->n_eq) { |
976 | 26.2k | bmap = isl_basic_map_drop_div(bmap, j); |
977 | 26.2k | isl_basic_map_drop_equality(bmap, i); |
978 | 26.2k | ++dropped; |
979 | 26.2k | } |
980 | 37.2k | } |
981 | 21.5k | pos[0] = 0; |
982 | 21.5k | needed = 0; |
983 | 120k | for (i = 1; i < T->n_row; ++i99.0k ) { |
984 | 99.0k | if (isl_int_is_one(T->row[i][i])) |
985 | 99.0k | pos[i] = i76.0k ; |
986 | 23.0k | else |
987 | 23.0k | needed++; |
988 | 99.0k | } |
989 | 21.5k | if (needed > dropped) { |
990 | 18 | bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), |
991 | 18 | needed, needed, 0); |
992 | 18 | if (!bmap) |
993 | 0 | goto error; |
994 | 21.5k | } |
995 | 120k | for (i = 1; 21.5k i < T->n_row; ++i99.0k ) { |
996 | 99.0k | if (isl_int_is_one(T->row[i][i])) |
997 | 99.0k | continue76.0k ; |
998 | 23.0k | k = isl_basic_map_alloc_div(bmap); |
999 | 23.0k | pos[i] = 1 + total + k; |
1000 | 23.0k | isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div); |
1001 | 23.0k | isl_int_set(bmap->div[k][0], T->row[i][i]); |
1002 | 23.0k | if (C2) |
1003 | 15.1k | isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total); |
1004 | 23.0k | else |
1005 | 23.0k | isl_int_set_si7.88k (bmap->div[k][1 + i], 1); |
1006 | 109k | for (j = 0; j < i; ++j86.1k ) { |
1007 | 86.1k | if (isl_int_is_zero(T->row[i][j])) |
1008 | 86.1k | continue66.8k ; |
1009 | 19.3k | if (pos[j] < T->n_row && C219.2k ) |
1010 | 12.6k | isl_seq_submul(bmap->div[k] + 1, T->row[i][j], |
1011 | 12.6k | C2->row[pos[j]], 1 + total); |
1012 | 19.3k | else |
1013 | 19.3k | isl_int_neg6.71k (bmap->div[k][1 + pos[j]], |
1014 | 19.3k | T->row[i][j]); |
1015 | 19.3k | } |
1016 | 23.0k | j = isl_basic_map_alloc_equality(bmap); |
1017 | 23.0k | isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div); |
1018 | 23.0k | isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]); |
1019 | 23.0k | } |
1020 | 21.5k | free(pos); |
1021 | 21.5k | isl_mat_free(C2); |
1022 | 21.5k | isl_mat_free(T); |
1023 | 21.5k | |
1024 | 21.5k | if (progress) |
1025 | 21.5k | *progress = 1; |
1026 | 23.4k | done: |
1027 | 23.4k | ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS); |
1028 | 23.4k | |
1029 | 23.4k | return bmap; |
1030 | 0 | error: |
1031 | 0 | free(pos); |
1032 | 0 | isl_mat_free(C); |
1033 | 0 | isl_mat_free(C2); |
1034 | 0 | isl_mat_free(T); |
1035 | 0 | return bmap; |
1036 | 21.5k | } |
1037 | | |
1038 | | static __isl_give isl_basic_map *set_div_from_lower_bound( |
1039 | | __isl_take isl_basic_map *bmap, int div, int ineq) |
1040 | 2.56k | { |
1041 | 2.56k | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
1042 | 2.56k | |
1043 | 2.56k | isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div); |
1044 | 2.56k | isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div]); |
1045 | 2.56k | isl_int_add(bmap->div[div][1], bmap->div[div][1], bmap->div[div][0]); |
1046 | 2.56k | isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1); |
1047 | 2.56k | isl_int_set_si(bmap->div[div][1 + total + div], 0); |
1048 | 2.56k | |
1049 | 2.56k | return bmap; |
1050 | 2.56k | } |
1051 | | |
1052 | | /* Check whether it is ok to define a div based on an inequality. |
1053 | | * To avoid the introduction of circular definitions of divs, we |
1054 | | * do not allow such a definition if the resulting expression would refer to |
1055 | | * any other undefined divs or if any known div is defined in |
1056 | | * terms of the unknown div. |
1057 | | */ |
1058 | | static isl_bool ok_to_set_div_from_bound(__isl_keep isl_basic_map *bmap, |
1059 | | int div, int ineq) |
1060 | 7.83k | { |
1061 | 7.83k | int j; |
1062 | 7.83k | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
1063 | 7.83k | |
1064 | 7.83k | /* Not defined in terms of unknown divs */ |
1065 | 25.1k | for (j = 0; j < bmap->n_div; ++j17.2k ) { |
1066 | 22.4k | if (div == j) |
1067 | 7.11k | continue; |
1068 | 15.2k | if (isl_int_is_zero(bmap->ineq[ineq][total + j])) |
1069 | 15.2k | continue10.0k ; |
1070 | 5.24k | if (isl_int_is_zero(bmap->div[j][0])) |
1071 | 5.24k | return isl_bool_false5.11k ; |
1072 | 5.24k | } |
1073 | 7.83k | |
1074 | 7.83k | /* No other div defined in terms of this one => avoid loops */ |
1075 | 10.2k | for (j = 0; 2.72k j < bmap->n_div; ++j7.50k ) { |
1076 | 7.65k | if (div == j) |
1077 | 2.72k | continue; |
1078 | 4.93k | if (isl_int_is_zero(bmap->div[j][0])) |
1079 | 4.93k | continue1.61k ; |
1080 | 3.31k | if (!isl_int_is_zero(bmap->div[j][1 + total + div])) |
1081 | 3.31k | return isl_bool_false153 ; |
1082 | 3.31k | } |
1083 | 2.72k | |
1084 | 2.72k | return isl_bool_true2.56k ; |
1085 | 2.72k | } |
1086 | | |
1087 | | /* Would an expression for div "div" based on inequality "ineq" of "bmap" |
1088 | | * be a better expression than the current one? |
1089 | | * |
1090 | | * If we do not have any expression yet, then any expression would be better. |
1091 | | * Otherwise we check if the last variable involved in the inequality |
1092 | | * (disregarding the div that it would define) is in an earlier position |
1093 | | * than the last variable involved in the current div expression. |
1094 | | */ |
1095 | | static isl_bool better_div_constraint(__isl_keep isl_basic_map *bmap, |
1096 | | int div, int ineq) |
1097 | 139k | { |
1098 | 139k | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
1099 | 139k | int last_div; |
1100 | 139k | int last_ineq; |
1101 | 139k | |
1102 | 139k | if (isl_int_is_zero(bmap->div[div][0])) |
1103 | 139k | return isl_bool_true7.62k ; |
1104 | 132k | |
1105 | 132k | if (isl_seq_last_non_zero(bmap->ineq[ineq] + total + div + 1, |
1106 | 132k | bmap->n_div - (div + 1)) >= 0) |
1107 | 984 | return isl_bool_false; |
1108 | 131k | |
1109 | 131k | last_ineq = isl_seq_last_non_zero(bmap->ineq[ineq], total + div); |
1110 | 131k | last_div = isl_seq_last_non_zero(bmap->div[div] + 1, |
1111 | 131k | total + bmap->n_div); |
1112 | 131k | |
1113 | 131k | return last_ineq < last_div; |
1114 | 131k | } |
1115 | | |
1116 | | /* Given two constraints "k" and "l" that are opposite to each other, |
1117 | | * except for the constant term, check if we can use them |
1118 | | * to obtain an expression for one of the hitherto unknown divs or |
1119 | | * a "better" expression for a div for which we already have an expression. |
1120 | | * "sum" is the sum of the constant terms of the constraints. |
1121 | | * If this sum is strictly smaller than the coefficient of one |
1122 | | * of the divs, then this pair can be used define the div. |
1123 | | * To avoid the introduction of circular definitions of divs, we |
1124 | | * do not use the pair if the resulting expression would refer to |
1125 | | * any other undefined divs or if any known div is defined in |
1126 | | * terms of the unknown div. |
1127 | | */ |
1128 | | static __isl_give isl_basic_map *check_for_div_constraints( |
1129 | | __isl_take isl_basic_map *bmap, int k, int l, isl_int sum, |
1130 | | int *progress) |
1131 | 13.1M | { |
1132 | 13.1M | int i; |
1133 | 13.1M | unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
1134 | 13.1M | |
1135 | 13.6M | for (i = 0; i < bmap->n_div; ++i563k ) { |
1136 | 703k | isl_bool set_div; |
1137 | 703k | |
1138 | 703k | if (isl_int_is_zero(bmap->ineq[k][total + i])) |
1139 | 703k | continue534k ; |
1140 | 168k | if (isl_int_abs_ge(sum, bmap->ineq[k][total + i])) |
1141 | 168k | continue29.0k ; |
1142 | 139k | set_div = better_div_constraint(bmap, i, k); |
1143 | 139k | if (set_div >= 0 && set_div) |
1144 | 7.83k | set_div = ok_to_set_div_from_bound(bmap, i, k); |
1145 | 139k | if (set_div < 0) |
1146 | 0 | return isl_basic_map_free(bmap); |
1147 | 139k | if (!set_div) |
1148 | 137k | break; |
1149 | 2.56k | if (isl_int_is_pos(bmap->ineq[k][total + i])) |
1150 | 2.56k | bmap = set_div_from_lower_bound(bmap, i, k)1.30k ; |
1151 | 1.26k | else |
1152 | 1.26k | bmap = set_div_from_lower_bound(bmap, i, l); |
1153 | 2.56k | if (progress) |
1154 | 2.56k | *progress = 1; |
1155 | 2.56k | break; |
1156 | 2.56k | } |
1157 | 13.1M | return bmap; |
1158 | 13.1M | } |
1159 | | |
1160 | | __isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints( |
1161 | | __isl_take isl_basic_map *bmap, int *progress, int detect_divs) |
1162 | 4.49M | { |
1163 | 4.49M | struct isl_constraint_index ci; |
1164 | 4.49M | int k, l, h; |
1165 | 4.49M | unsigned total = isl_basic_map_total_dim(bmap); |
1166 | 4.49M | isl_int sum; |
1167 | 4.49M | |
1168 | 4.49M | if (!bmap || bmap->n_ineq <= 1) |
1169 | 1.24M | return bmap; |
1170 | 3.24M | |
1171 | 3.24M | if (create_constraint_index(&ci, bmap) < 0) |
1172 | 0 | return bmap; |
1173 | 3.24M | |
1174 | 3.24M | h = isl_seq_get_hash_bits(bmap->ineq[0] + 1, total, ci.bits); |
1175 | 3.24M | ci.index[h] = &bmap->ineq[0]; |
1176 | 22.8M | for (k = 1; k < bmap->n_ineq; ++k19.5M ) { |
1177 | 19.5M | h = hash_index(&ci, bmap, k); |
1178 | 19.5M | if (!ci.index[h]) { |
1179 | 17.8M | ci.index[h] = &bmap->ineq[k]; |
1180 | 17.8M | continue; |
1181 | 17.8M | } |
1182 | 1.68M | if (progress) |
1183 | 1.66M | *progress = 1; |
1184 | 1.68M | l = ci.index[h] - &bmap->ineq[0]; |
1185 | 1.68M | if (isl_int_lt(bmap->ineq[k][0], bmap->ineq[l][0])) |
1186 | 1.68M | swap_inequality(bmap, k, l)126k ; |
1187 | 1.68M | isl_basic_map_drop_inequality(bmap, k); |
1188 | 1.68M | --k; |
1189 | 1.68M | } |
1190 | 3.24M | isl_int_init(sum); |
1191 | 20.5M | for (k = 0; k < bmap->n_ineq-1; ++k17.3M ) { |
1192 | 17.4M | isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total); |
1193 | 17.4M | h = hash_index(&ci, bmap, k); |
1194 | 17.4M | isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total); |
1195 | 17.4M | if (!ci.index[h]) |
1196 | 4.15M | continue; |
1197 | 13.2M | l = ci.index[h] - &bmap->ineq[0]; |
1198 | 13.2M | isl_int_add(sum, bmap->ineq[k][0], bmap->ineq[l][0]); |
1199 | 13.2M | if (isl_int_is_pos(sum)) { |
1200 | 13.1M | if (detect_divs) |
1201 | 13.1M | bmap = check_for_div_constraints(bmap, k, l, |
1202 | 13.1M | sum, progress); |
1203 | 13.1M | continue; |
1204 | 13.1M | } |
1205 | 111k | if (isl_int_is_zero(sum)) { |
1206 | 18.9k | /* We need to break out of the loop after these |
1207 | 18.9k | * changes since the contents of the hash |
1208 | 18.9k | * will no longer be valid. |
1209 | 18.9k | * Plus, we probably we want to regauss first. |
1210 | 18.9k | */ |
1211 | 18.9k | if (progress) |
1212 | 18.4k | *progress = 1; |
1213 | 18.9k | isl_basic_map_drop_inequality(bmap, l); |
1214 | 18.9k | isl_basic_map_inequality_to_equality(bmap, k); |
1215 | 18.9k | } else |
1216 | 92.6k | bmap = isl_basic_map_set_to_empty(bmap); |
1217 | 111k | break; |
1218 | 111k | } |
1219 | 3.24M | isl_int_clear(sum); |
1220 | 3.24M | |
1221 | 3.24M | constraint_index_free(&ci); |
1222 | 3.24M | return bmap; |
1223 | 3.24M | } |
1224 | | |
1225 | | /* Detect all pairs of inequalities that form an equality. |
1226 | | * |
1227 | | * isl_basic_map_remove_duplicate_constraints detects at most one such pair. |
1228 | | * Call it repeatedly while it is making progress. |
1229 | | */ |
1230 | | __isl_give isl_basic_map *isl_basic_map_detect_inequality_pairs( |
1231 | | __isl_take isl_basic_map *bmap, int *progress) |
1232 | 876 | { |
1233 | 876 | int duplicate; |
1234 | 876 | |
1235 | 1.43k | do { |
1236 | 1.43k | duplicate = 0; |
1237 | 1.43k | bmap = isl_basic_map_remove_duplicate_constraints(bmap, |
1238 | 1.43k | &duplicate, 0); |
1239 | 1.43k | if (progress && duplicate558 ) |
1240 | 87 | *progress = 1; |
1241 | 1.43k | } while (duplicate); |
1242 | 876 | |
1243 | 876 | return bmap; |
1244 | 876 | } |
1245 | | |
1246 | | /* Eliminate knowns divs from constraints where they appear with |
1247 | | * a (positive or negative) unit coefficient. |
1248 | | * |
1249 | | * That is, replace |
1250 | | * |
1251 | | * floor(e/m) + f >= 0 |
1252 | | * |
1253 | | * by |
1254 | | * |
1255 | | * e + m f >= 0 |
1256 | | * |
1257 | | * and |
1258 | | * |
1259 | | * -floor(e/m) + f >= 0 |
1260 | | * |
1261 | | * by |
1262 | | * |
1263 | | * -e + m f + m - 1 >= 0 |
1264 | | * |
1265 | | * The first conversion is valid because floor(e/m) >= -f is equivalent |
1266 | | * to e/m >= -f because -f is an integral expression. |
1267 | | * The second conversion follows from the fact that |
1268 | | * |
1269 | | * -floor(e/m) = ceil(-e/m) = floor((-e + m - 1)/m) |
1270 | | * |
1271 | | * |
1272 | | * Note that one of the div constraints may have been eliminated |
1273 | | * due to being redundant with respect to the constraint that is |
1274 | | * being modified by this function. The modified constraint may |
1275 | | * no longer imply this div constraint, so we add it back to make |
1276 | | * sure we do not lose any information. |
1277 | | * |
1278 | | * We skip integral divs, i.e., those with denominator 1, as we would |
1279 | | * risk eliminating the div from the div constraints. We do not need |
1280 | | * to handle those divs here anyway since the div constraints will turn |
1281 | | * out to form an equality and this equality can then be used to eliminate |
1282 | | * the div from all constraints. |
1283 | | */ |
1284 | | static __isl_give isl_basic_map *eliminate_unit_divs( |
1285 | | __isl_take isl_basic_map *bmap, int *progress) |
1286 | 4.45M | { |
1287 | 4.45M | int i, j; |
1288 | 4.45M | isl_ctx *ctx; |
1289 | 4.45M | unsigned total; |
1290 | 4.45M | |
1291 | 4.45M | if (!bmap) |
1292 | 0 | return NULL; |
1293 | 4.45M | |
1294 | 4.45M | ctx = isl_basic_map_get_ctx(bmap); |
1295 | 4.45M | total = 1 + isl_space_dim(bmap->dim, isl_dim_all); |
1296 | 4.45M | |
1297 | 5.21M | for (i = 0; i < bmap->n_div; ++i755k ) { |
1298 | 755k | if (isl_int_is_zero(bmap->div[i][0])) |
1299 | 755k | continue582k ; |
1300 | 173k | if (isl_int_is_one(bmap->div[i][0])) |
1301 | 173k | continue667 ; |
1302 | 1.89M | for (j = 0; 172k j < bmap->n_ineq; ++j1.71M ) { |
1303 | 1.71M | int s; |
1304 | 1.71M | |
1305 | 1.71M | if (!isl_int_is_one(bmap->ineq[j][total + i]) && |
1306 | 1.71M | !1.71M isl_int_is_negone1.71M (bmap->ineq[j][total + i])) |
1307 | 1.71M | continue1.70M ; |
1308 | 9.69k | |
1309 | 9.69k | *progress = 1; |
1310 | 9.69k | |
1311 | 9.69k | s = isl_int_sgn(bmap->ineq[j][total + i]); |
1312 | 9.69k | isl_int_set_si(bmap->ineq[j][total + i], 0); |
1313 | 9.69k | if (s < 0) |
1314 | 4.41k | isl_seq_combine(bmap->ineq[j], |
1315 | 4.41k | ctx->negone, bmap->div[i] + 1, |
1316 | 4.41k | bmap->div[i][0], bmap->ineq[j], |
1317 | 4.41k | total + bmap->n_div); |
1318 | 5.28k | else |
1319 | 5.28k | isl_seq_combine(bmap->ineq[j], |
1320 | 5.28k | ctx->one, bmap->div[i] + 1, |
1321 | 5.28k | bmap->div[i][0], bmap->ineq[j], |
1322 | 5.28k | total + bmap->n_div); |
1323 | 9.69k | if (s < 0) { |
1324 | 4.41k | isl_int_add(bmap->ineq[j][0], |
1325 | 4.41k | bmap->ineq[j][0], bmap->div[i][0]); |
1326 | 4.41k | isl_int_sub_ui(bmap->ineq[j][0], |
1327 | 4.41k | bmap->ineq[j][0], 1); |
1328 | 4.41k | } |
1329 | 9.69k | |
1330 | 9.69k | bmap = isl_basic_map_extend_constraints(bmap, 0, 1); |
1331 | 9.69k | if (isl_basic_map_add_div_constraint(bmap, i, s) < 0) |
1332 | 0 | return isl_basic_map_free(bmap); |
1333 | 9.69k | } |
1334 | 172k | } |
1335 | 4.45M | |
1336 | 4.45M | return bmap; |
1337 | 4.45M | } |
1338 | | |
1339 | | __isl_give isl_basic_map *isl_basic_map_simplify(__isl_take isl_basic_map *bmap) |
1340 | 3.80M | { |
1341 | 3.80M | int progress = 1; |
1342 | 3.80M | if (!bmap) |
1343 | 1 | return NULL; |
1344 | 8.26M | while (3.80M progress) { |
1345 | 4.56M | isl_bool empty; |
1346 | 4.56M | |
1347 | 4.56M | progress = 0; |
1348 | 4.56M | empty = isl_basic_map_plain_is_empty(bmap); |
1349 | 4.56M | if (empty < 0) |
1350 | 0 | return isl_basic_map_free(bmap); |
1351 | 4.56M | if (empty) |
1352 | 105k | break; |
1353 | 4.45M | bmap = isl_basic_map_normalize_constraints(bmap); |
1354 | 4.45M | bmap = reduce_div_coefficients(bmap); |
1355 | 4.45M | bmap = normalize_div_expressions(bmap); |
1356 | 4.45M | bmap = remove_duplicate_divs(bmap, &progress); |
1357 | 4.45M | bmap = eliminate_unit_divs(bmap, &progress); |
1358 | 4.45M | bmap = eliminate_divs_eq(bmap, &progress); |
1359 | 4.45M | bmap = eliminate_divs_ineq(bmap, &progress); |
1360 | 4.45M | bmap = isl_basic_map_gauss(bmap, &progress); |
1361 | 4.45M | /* requires equalities in normal form */ |
1362 | 4.45M | bmap = normalize_divs(bmap, &progress); |
1363 | 4.45M | bmap = isl_basic_map_remove_duplicate_constraints(bmap, |
1364 | 4.45M | &progress, 1); |
1365 | 4.45M | if (bmap && progress) |
1366 | 4.45M | ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS); |
1367 | 4.45M | } |
1368 | 3.80M | return bmap; |
1369 | 3.80M | } |
1370 | | |
1371 | | struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset) |
1372 | 1.52M | { |
1373 | 1.52M | return bset_from_bmap(isl_basic_map_simplify(bset_to_bmap(bset))); |
1374 | 1.52M | } |
1375 | | |
1376 | | |
1377 | | isl_bool isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap, |
1378 | | isl_int *constraint, unsigned div) |
1379 | 104k | { |
1380 | 104k | unsigned pos; |
1381 | 104k | |
1382 | 104k | if (!bmap) |
1383 | 0 | return isl_bool_error; |
1384 | 104k | |
1385 | 104k | pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div; |
1386 | 104k | |
1387 | 104k | if (isl_int_eq(constraint[pos], bmap->div[div][0])) { |
1388 | 50.2k | int neg; |
1389 | 50.2k | isl_int_sub(bmap->div[div][1], |
1390 | 50.2k | bmap->div[div][1], bmap->div[div][0]); |
1391 | 50.2k | isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1); |
1392 | 50.2k | neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos); |
1393 | 50.2k | isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1); |
1394 | 50.2k | isl_int_add(bmap->div[div][1], |
1395 | 50.2k | bmap->div[div][1], bmap->div[div][0]); |
1396 | 50.2k | if (!neg) |
1397 | 18.0k | return isl_bool_false; |
1398 | 32.1k | if (isl_seq_first_non_zero(constraint+pos+1, |
1399 | 32.1k | bmap->n_div-div-1) != -1) |
1400 | 0 | return isl_bool_false; |
1401 | 53.8k | } else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])) { |
1402 | 46.1k | if (!isl_seq_eq(constraint, bmap->div[div]+1, pos)) |
1403 | 25.5k | return isl_bool_false; |
1404 | 20.5k | if (isl_seq_first_non_zero(constraint+pos+1, |
1405 | 20.5k | bmap->n_div-div-1) != -1) |
1406 | 1 | return isl_bool_false; |
1407 | 7.71k | } else |
1408 | 7.71k | return isl_bool_false; |
1409 | 52.7k | |
1410 | 52.7k | return isl_bool_true; |
1411 | 52.7k | } |
1412 | | |
1413 | | isl_bool isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset, |
1414 | | isl_int *constraint, unsigned div) |
1415 | 0 | { |
1416 | 0 | return isl_basic_map_is_div_constraint(bset, constraint, div); |
1417 | 0 | } |
1418 | | |
1419 | | |
1420 | | /* If the only constraints a div d=floor(f/m) |
1421 | | * appears in are its two defining constraints |
1422 | | * |
1423 | | * f - m d >=0 |
1424 | | * -(f - (m - 1)) + m d >= 0 |
1425 | | * |
1426 | | * then it can safely be removed. |
1427 | | */ |
1428 | | static isl_bool div_is_redundant(__isl_keep isl_basic_map *bmap, int div) |
1429 | 151k | { |
1430 | 151k | int i; |
1431 | 151k | unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div; |
1432 | 151k | |
1433 | 234k | for (i = 0; i < bmap->n_eq; ++i82.9k ) |
1434 | 147k | if (!isl_int_is_zero(bmap->eq[i][pos])) |
1435 | 147k | return isl_bool_false64.4k ; |
1436 | 151k | |
1437 | 477k | for (i = 0; 87.3k i < bmap->n_ineq; ++i390k ) { |
1438 | 441k | isl_bool red; |
1439 | 441k | |
1440 | 441k | if (isl_int_is_zero(bmap->ineq[i][pos])) |
1441 | 441k | continue337k ; |
1442 | 103k | red = isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div); |
1443 | 103k | if (red < 0 || !red) |
1444 | 51.1k | return red; |
1445 | 103k | } |
1446 | 87.3k | |
1447 | 87.3k | for (i = 0; 36.2k i < bmap->n_div82.9k ; ++i46.7k ) { |
1448 | 46.7k | if (isl_int_is_zero(bmap->div[i][0])) |
1449 | 46.7k | continue697 ; |
1450 | 46.0k | if (!isl_int_is_zero(bmap->div[i][1+pos])) |
1451 | 46.0k | return isl_bool_false1 ; |
1452 | 46.0k | } |
1453 | 36.2k | |
1454 | 36.2k | return isl_bool_true36.2k ; |
1455 | 36.2k | } |
1456 | | |
1457 | | /* |
1458 | | * Remove divs that don't occur in any of the constraints or other divs. |
1459 | | * These can arise when dropping constraints from a basic map or |
1460 | | * when the divs of a basic map have been temporarily aligned |
1461 | | * with the divs of another basic map. |
1462 | | */ |
1463 | | static __isl_give isl_basic_map *remove_redundant_divs( |
1464 | | __isl_take isl_basic_map *bmap) |
1465 | 7.61M | { |
1466 | 7.61M | int i; |
1467 | 7.61M | |
1468 | 7.61M | if (!bmap) |
1469 | 1 | return NULL; |
1470 | 7.61M | |
1471 | 7.76M | for (i = bmap->n_div-1; 7.61M i >= 0; --i151k ) { |
1472 | 151k | isl_bool redundant; |
1473 | 151k | |
1474 | 151k | redundant = div_is_redundant(bmap, i); |
1475 | 151k | if (redundant < 0) |
1476 | 0 | return isl_basic_map_free(bmap); |
1477 | 151k | if (!redundant) |
1478 | 115k | continue; |
1479 | 36.2k | bmap = isl_basic_map_drop_div(bmap, i); |
1480 | 36.2k | } |
1481 | 7.61M | return bmap; |
1482 | 7.61M | } |
1483 | | |
1484 | | /* Mark "bmap" as final, without checking for obviously redundant |
1485 | | * integer divisions. This function should be used when "bmap" |
1486 | | * is known not to involve any such integer divisions. |
1487 | | */ |
1488 | | __isl_give isl_basic_map *isl_basic_map_mark_final( |
1489 | | __isl_take isl_basic_map *bmap) |
1490 | 7.62M | { |
1491 | 7.62M | if (!bmap) |
1492 | 1 | return NULL; |
1493 | 7.62M | ISL_F_SET(bmap, ISL_BASIC_SET_FINAL); |
1494 | 7.62M | return bmap; |
1495 | 7.62M | } |
1496 | | |
1497 | | /* Mark "bmap" as final, after removing obviously redundant integer divisions. |
1498 | | */ |
1499 | | __isl_give isl_basic_map *isl_basic_map_finalize(__isl_take isl_basic_map *bmap) |
1500 | 7.61M | { |
1501 | 7.61M | bmap = remove_redundant_divs(bmap); |
1502 | 7.61M | bmap = isl_basic_map_mark_final(bmap); |
1503 | 7.61M | return bmap; |
1504 | 7.61M | } |
1505 | | |
1506 | | struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset) |
1507 | 1.71M | { |
1508 | 1.71M | return bset_from_bmap(isl_basic_map_finalize(bset_to_bmap(bset))); |
1509 | 1.71M | } |
1510 | | |
1511 | | /* Remove definition of any div that is defined in terms of the given variable. |
1512 | | * The div itself is not removed. Functions such as |
1513 | | * eliminate_divs_ineq depend on the other divs remaining in place. |
1514 | | */ |
1515 | | static __isl_give isl_basic_map *remove_dependent_vars( |
1516 | | __isl_take isl_basic_map *bmap, int pos) |
1517 | 133k | { |
1518 | 133k | int i; |
1519 | 133k | |
1520 | 133k | if (!bmap) |
1521 | 0 | return NULL; |
1522 | 133k | |
1523 | 289k | for (i = 0; 133k i < bmap->n_div; ++i156k ) { |
1524 | 156k | if (isl_int_is_zero(bmap->div[i][0])) |
1525 | 156k | continue151k ; |
1526 | 4.34k | if (isl_int_is_zero(bmap->div[i][1+1+pos])) |
1527 | 4.34k | continue4.23k ; |
1528 | 101 | bmap = isl_basic_map_mark_div_unknown(bmap, i); |
1529 | 101 | if (!bmap) |
1530 | 0 | return NULL; |
1531 | 101 | } |
1532 | 133k | return bmap; |
1533 | 133k | } |
1534 | | |
1535 | | /* Eliminate the specified variables from the constraints using |
1536 | | * Fourier-Motzkin. The variables themselves are not removed. |
1537 | | */ |
1538 | | __isl_give isl_basic_map *isl_basic_map_eliminate_vars( |
1539 | | __isl_take isl_basic_map *bmap, unsigned pos, unsigned n) |
1540 | 133k | { |
1541 | 133k | int d; |
1542 | 133k | int i, j, k; |
1543 | 133k | unsigned total; |
1544 | 133k | int need_gauss = 0; |
1545 | 133k | |
1546 | 133k | if (n == 0) |
1547 | 2.36k | return bmap; |
1548 | 131k | if (!bmap) |
1549 | 0 | return NULL; |
1550 | 131k | total = isl_basic_map_total_dim(bmap); |
1551 | 131k | |
1552 | 131k | bmap = isl_basic_map_cow(bmap); |
1553 | 264k | for (d = pos + n - 1; d >= 0 && d >= pos243k ; --d133k ) |
1554 | 133k | bmap = remove_dependent_vars(bmap, d); |
1555 | 131k | if (!bmap) |
1556 | 0 | return NULL; |
1557 | 131k | |
1558 | 131k | for (d = pos + n - 1; |
1559 | 226k | d >= 0 && d >= total - bmap->n_div213k && d >= pos122k ; --d95.6k ) |
1560 | 95.6k | isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total); |
1561 | 264k | for (d = pos + n - 1; d >= 0 && d >= pos243k ; --d132k ) { |
1562 | 133k | int n_lower, n_upper; |
1563 | 133k | if (!bmap) |
1564 | 0 | return NULL; |
1565 | 206k | for (i = 0; 133k i < bmap->n_eq; ++i72.7k ) { |
1566 | 76.3k | if (isl_int_is_zero(bmap->eq[i][1+d])) |
1567 | 76.3k | continue72.7k ; |
1568 | 3.56k | eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL); |
1569 | 3.56k | isl_basic_map_drop_equality(bmap, i); |
1570 | 3.56k | need_gauss = 1; |
1571 | 3.56k | break; |
1572 | 3.56k | } |
1573 | 133k | if (i < bmap->n_eq) |
1574 | 1.31k | continue; |
1575 | 131k | n_lower = 0; |
1576 | 131k | n_upper = 0; |
1577 | 512k | for (i = 0; i < bmap->n_ineq; ++i380k ) { |
1578 | 380k | if (isl_int_is_pos(bmap->ineq[i][1+d])) |
1579 | 380k | n_lower++38.5k ; |
1580 | 342k | else if (isl_int_is_neg(bmap->ineq[i][1+d])) |
1581 | 342k | n_upper++37.9k ; |
1582 | 380k | } |
1583 | 131k | bmap = isl_basic_map_extend_constraints(bmap, |
1584 | 131k | 0, n_lower * n_upper); |
1585 | 131k | if (!bmap) |
1586 | 0 | goto error; |
1587 | 435k | for (i = bmap->n_ineq - 1; 131k i >= 0; --i303k ) { |
1588 | 303k | int last; |
1589 | 303k | if (isl_int_is_zero(bmap->ineq[i][1+d])) |
1590 | 303k | continue227k ; |
1591 | 76.4k | last = -1; |
1592 | 354k | for (j = 0; j < i; ++j278k ) { |
1593 | 278k | if (isl_int_is_zero(bmap->ineq[j][1+d])) |
1594 | 278k | continue206k ; |
1595 | 71.3k | last = j; |
1596 | 71.3k | if (isl_int_sgn(bmap->ineq[i][1+d]) == |
1597 | 71.3k | isl_int_sgn(bmap->ineq[j][1+d])) |
1598 | 71.3k | continue18.3k ; |
1599 | 52.9k | k = isl_basic_map_alloc_inequality(bmap); |
1600 | 52.9k | if (k < 0) |
1601 | 0 | goto error; |
1602 | 52.9k | isl_seq_cpy(bmap->ineq[k], bmap->ineq[i], |
1603 | 52.9k | 1+total); |
1604 | 52.9k | isl_seq_elim(bmap->ineq[k], bmap->ineq[j], |
1605 | 52.9k | 1+d, 1+total, NULL); |
1606 | 52.9k | } |
1607 | 76.4k | isl_basic_map_drop_inequality(bmap, i); |
1608 | 76.4k | i = last + 1; |
1609 | 76.4k | } |
1610 | 131k | if (n_lower > 0 && n_upper > 031.7k ) { |
1611 | 30.4k | bmap = isl_basic_map_normalize_constraints(bmap); |
1612 | 30.4k | bmap = isl_basic_map_remove_duplicate_constraints(bmap, |
1613 | 30.4k | NULL, 0); |
1614 | 30.4k | bmap = isl_basic_map_gauss(bmap, NULL); |
1615 | 30.4k | bmap = isl_basic_map_remove_redundancies(bmap); |
1616 | 30.4k | need_gauss = 0; |
1617 | 30.4k | if (!bmap) |
1618 | 0 | goto error; |
1619 | 30.4k | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) |
1620 | 30.4k | break269 ; |
1621 | 30.4k | } |
1622 | 131k | } |
1623 | 131k | ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED); |
1624 | 131k | if (need_gauss) |
1625 | 1.73k | bmap = isl_basic_map_gauss(bmap, NULL); |
1626 | 131k | return bmap; |
1627 | 0 | error: |
1628 | 0 | isl_basic_map_free(bmap); |
1629 | 0 | return NULL; |
1630 | 131k | } |
1631 | | |
1632 | | struct isl_basic_set *isl_basic_set_eliminate_vars( |
1633 | | struct isl_basic_set *bset, unsigned pos, unsigned n) |
1634 | 34.5k | { |
1635 | 34.5k | return bset_from_bmap(isl_basic_map_eliminate_vars(bset_to_bmap(bset), |
1636 | 34.5k | pos, n)); |
1637 | 34.5k | } |
1638 | | |
1639 | | /* Eliminate the specified n dimensions starting at first from the |
1640 | | * constraints, without removing the dimensions from the space. |
1641 | | * If the set is rational, the dimensions are eliminated using Fourier-Motzkin. |
1642 | | * Otherwise, they are projected out and the original space is restored. |
1643 | | */ |
1644 | | __isl_give isl_basic_map *isl_basic_map_eliminate( |
1645 | | __isl_take isl_basic_map *bmap, |
1646 | | enum isl_dim_type type, unsigned first, unsigned n) |
1647 | 32.3k | { |
1648 | 32.3k | isl_space *space; |
1649 | 32.3k | |
1650 | 32.3k | if (!bmap) |
1651 | 0 | return NULL; |
1652 | 32.3k | if (n == 0) |
1653 | 0 | return bmap; |
1654 | 32.3k | |
1655 | 32.3k | if (first + n > isl_basic_map_dim(bmap, type) || first + n < first) |
1656 | 32.3k | isl_die0 (bmap->ctx, isl_error_invalid, |
1657 | 32.3k | "index out of bounds", goto error); |
1658 | 32.3k | |
1659 | 32.3k | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) { |
1660 | 0 | first += isl_basic_map_offset(bmap, type) - 1; |
1661 | 0 | bmap = isl_basic_map_eliminate_vars(bmap, first, n); |
1662 | 0 | return isl_basic_map_finalize(bmap); |
1663 | 0 | } |
1664 | 32.3k | |
1665 | 32.3k | space = isl_basic_map_get_space(bmap); |
1666 | 32.3k | bmap = isl_basic_map_project_out(bmap, type, first, n); |
1667 | 32.3k | bmap = isl_basic_map_insert_dims(bmap, type, first, n); |
1668 | 32.3k | bmap = isl_basic_map_reset_space(bmap, space); |
1669 | 32.3k | return bmap; |
1670 | 0 | error: |
1671 | 0 | isl_basic_map_free(bmap); |
1672 | 0 | return NULL; |
1673 | 32.3k | } |
1674 | | |
1675 | | __isl_give isl_basic_set *isl_basic_set_eliminate( |
1676 | | __isl_take isl_basic_set *bset, |
1677 | | enum isl_dim_type type, unsigned first, unsigned n) |
1678 | 5.99k | { |
1679 | 5.99k | return isl_basic_map_eliminate(bset, type, first, n); |
1680 | 5.99k | } |
1681 | | |
1682 | | /* Remove all constraints from "bmap" that reference any unknown local |
1683 | | * variables (directly or indirectly). |
1684 | | * |
1685 | | * Dropping all constraints on a local variable will make it redundant, |
1686 | | * so it will get removed implicitly by |
1687 | | * isl_basic_map_drop_constraints_involving_dims. Some other local |
1688 | | * variables may also end up becoming redundant if they only appear |
1689 | | * in constraints together with the unknown local variable. |
1690 | | * Therefore, start over after calling |
1691 | | * isl_basic_map_drop_constraints_involving_dims. |
1692 | | */ |
1693 | | __isl_give isl_basic_map *isl_basic_map_drop_constraint_involving_unknown_divs( |
1694 | | __isl_take isl_basic_map *bmap) |
1695 | 8.18k | { |
1696 | 8.18k | isl_bool known; |
1697 | 8.18k | int i, n_div, o_div; |
1698 | 8.18k | |
1699 | 8.18k | known = isl_basic_map_divs_known(bmap); |
1700 | 8.18k | if (known < 0) |
1701 | 0 | return isl_basic_map_free(bmap); |
1702 | 8.18k | if (known) |
1703 | 8.18k | return bmap; |
1704 | 0 | |
1705 | 0 | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
1706 | 0 | o_div = isl_basic_map_offset(bmap, isl_dim_div) - 1; |
1707 | 0 |
|
1708 | 0 | for (i = 0; i < n_div; ++i) { |
1709 | 0 | known = isl_basic_map_div_is_known(bmap, i); |
1710 | 0 | if (known < 0) |
1711 | 0 | return isl_basic_map_free(bmap); |
1712 | 0 | if (known) |
1713 | 0 | continue; |
1714 | 0 | bmap = remove_dependent_vars(bmap, o_div + i); |
1715 | 0 | bmap = isl_basic_map_drop_constraints_involving_dims(bmap, |
1716 | 0 | isl_dim_div, i, 1); |
1717 | 0 | if (!bmap) |
1718 | 0 | return NULL; |
1719 | 0 | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
1720 | 0 | i = -1; |
1721 | 0 | } |
1722 | 0 |
|
1723 | 0 | return bmap; |
1724 | 0 | } |
1725 | | |
1726 | | /* Remove all constraints from "map" that reference any unknown local |
1727 | | * variables (directly or indirectly). |
1728 | | * |
1729 | | * Since constraints may get dropped from the basic maps, |
1730 | | * they may no longer be disjoint from each other. |
1731 | | */ |
1732 | | __isl_give isl_map *isl_map_drop_constraint_involving_unknown_divs( |
1733 | | __isl_take isl_map *map) |
1734 | 507 | { |
1735 | 507 | int i; |
1736 | 507 | isl_bool known; |
1737 | 507 | |
1738 | 507 | known = isl_map_divs_known(map); |
1739 | 507 | if (known < 0) |
1740 | 0 | return isl_map_free(map); |
1741 | 507 | if (known) |
1742 | 507 | return map; |
1743 | 0 | |
1744 | 0 | map = isl_map_cow(map); |
1745 | 0 | if (!map) |
1746 | 0 | return NULL; |
1747 | 0 | |
1748 | 0 | for (i = 0; i < map->n; ++i) { |
1749 | 0 | map->p[i] = |
1750 | 0 | isl_basic_map_drop_constraint_involving_unknown_divs( |
1751 | 0 | map->p[i]); |
1752 | 0 | if (!map->p[i]) |
1753 | 0 | return isl_map_free(map); |
1754 | 0 | } |
1755 | 0 |
|
1756 | 0 | if (map->n > 1) |
1757 | 0 | ISL_F_CLR(map, ISL_MAP_DISJOINT); |
1758 | 0 |
|
1759 | 0 | return map; |
1760 | 0 | } |
1761 | | |
1762 | | /* Don't assume equalities are in order, because align_divs |
1763 | | * may have changed the order of the divs. |
1764 | | */ |
1765 | | static void compute_elimination_index(__isl_keep isl_basic_map *bmap, int *elim) |
1766 | 57.8k | { |
1767 | 57.8k | int d, i; |
1768 | 57.8k | unsigned total; |
1769 | 57.8k | |
1770 | 57.8k | total = isl_space_dim(bmap->dim, isl_dim_all); |
1771 | 526k | for (d = 0; d < total; ++d468k ) |
1772 | 468k | elim[d] = -1; |
1773 | 158k | for (i = 0; i < bmap->n_eq; ++i100k ) { |
1774 | 377k | for (d = total - 1; d >= 0; --d277k ) { |
1775 | 377k | if (isl_int_is_zero(bmap->eq[i][1+d])) |
1776 | 377k | continue277k ; |
1777 | 100k | elim[d] = i; |
1778 | 100k | break; |
1779 | 100k | } |
1780 | 100k | } |
1781 | 57.8k | } |
1782 | | |
1783 | | static void set_compute_elimination_index(__isl_keep isl_basic_set *bset, |
1784 | | int *elim) |
1785 | 647 | { |
1786 | 647 | compute_elimination_index(bset_to_bmap(bset), elim); |
1787 | 647 | } |
1788 | | |
1789 | | static int reduced_using_equalities(isl_int *dst, isl_int *src, |
1790 | | __isl_keep isl_basic_map *bmap, int *elim) |
1791 | 524k | { |
1792 | 524k | int d; |
1793 | 524k | int copied = 0; |
1794 | 524k | unsigned total; |
1795 | 524k | |
1796 | 524k | total = isl_space_dim(bmap->dim, isl_dim_all); |
1797 | 5.11M | for (d = total - 1; d >= 0; --d4.59M ) { |
1798 | 4.59M | if (isl_int_is_zero(src[1+d])) |
1799 | 4.59M | continue3.99M ; |
1800 | 594k | if (elim[d] == -1) |
1801 | 462k | continue; |
1802 | 132k | if (!copied) { |
1803 | 131k | isl_seq_cpy(dst, src, 1 + total); |
1804 | 131k | copied = 1; |
1805 | 131k | } |
1806 | 132k | isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL); |
1807 | 132k | } |
1808 | 524k | return copied; |
1809 | 524k | } |
1810 | | |
1811 | | static int set_reduced_using_equalities(isl_int *dst, isl_int *src, |
1812 | | __isl_keep isl_basic_set *bset, int *elim) |
1813 | 1.83k | { |
1814 | 1.83k | return reduced_using_equalities(dst, src, |
1815 | 1.83k | bset_to_bmap(bset), elim); |
1816 | 1.83k | } |
1817 | | |
1818 | | static __isl_give isl_basic_set *isl_basic_set_reduce_using_equalities( |
1819 | | __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context) |
1820 | 11.8k | { |
1821 | 11.8k | int i; |
1822 | 11.8k | int *elim; |
1823 | 11.8k | |
1824 | 11.8k | if (!bset || !context) |
1825 | 0 | goto error; |
1826 | 11.8k | |
1827 | 11.8k | if (context->n_eq == 0) { |
1828 | 11.2k | isl_basic_set_free(context); |
1829 | 11.2k | return bset; |
1830 | 11.2k | } |
1831 | 647 | |
1832 | 647 | bset = isl_basic_set_cow(bset); |
1833 | 647 | if (!bset) |
1834 | 0 | goto error; |
1835 | 647 | |
1836 | 647 | elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset)); |
1837 | 647 | if (!elim) |
1838 | 0 | goto error; |
1839 | 647 | set_compute_elimination_index(context, elim); |
1840 | 2.21k | for (i = 0; i < bset->n_eq; ++i1.57k ) |
1841 | 1.57k | set_reduced_using_equalities(bset->eq[i], bset->eq[i], |
1842 | 1.57k | context, elim); |
1843 | 907 | for (i = 0; i < bset->n_ineq; ++i260 ) |
1844 | 260 | set_reduced_using_equalities(bset->ineq[i], bset->ineq[i], |
1845 | 260 | context, elim); |
1846 | 647 | isl_basic_set_free(context); |
1847 | 647 | free(elim); |
1848 | 647 | bset = isl_basic_set_simplify(bset); |
1849 | 647 | bset = isl_basic_set_finalize(bset); |
1850 | 647 | return bset; |
1851 | 0 | error: |
1852 | 0 | isl_basic_set_free(bset); |
1853 | 0 | isl_basic_set_free(context); |
1854 | 0 | return NULL; |
1855 | 647 | } |
1856 | | |
1857 | | /* For each inequality in "ineq" that is a shifted (more relaxed) |
1858 | | * copy of an inequality in "context", mark the corresponding entry |
1859 | | * in "row" with -1. |
1860 | | * If an inequality only has a non-negative constant term, then |
1861 | | * mark it as well. |
1862 | | */ |
1863 | | static isl_stat mark_shifted_constraints(__isl_keep isl_mat *ineq, |
1864 | | __isl_keep isl_basic_set *context, int *row) |
1865 | 16.1k | { |
1866 | 16.1k | struct isl_constraint_index ci; |
1867 | 16.1k | int n_ineq; |
1868 | 16.1k | unsigned total; |
1869 | 16.1k | int k; |
1870 | 16.1k | |
1871 | 16.1k | if (!ineq || !context) |
1872 | 0 | return isl_stat_error; |
1873 | 16.1k | if (context->n_ineq == 0) |
1874 | 0 | return isl_stat_ok; |
1875 | 16.1k | if (setup_constraint_index(&ci, context) < 0) |
1876 | 0 | return isl_stat_error; |
1877 | 16.1k | |
1878 | 16.1k | n_ineq = isl_mat_rows(ineq); |
1879 | 16.1k | total = isl_mat_cols(ineq) - 1; |
1880 | 84.8k | for (k = 0; k < n_ineq; ++k68.7k ) { |
1881 | 68.7k | int l; |
1882 | 68.7k | isl_bool redundant; |
1883 | 68.7k | |
1884 | 68.7k | l = isl_seq_first_non_zero(ineq->row[k] + 1, total); |
1885 | 68.7k | if (l < 0 && isl_int_is_nonneg4 (ineq->row[k][0])) { |
1886 | 0 | row[k] = -1; |
1887 | 0 | continue; |
1888 | 0 | } |
1889 | 68.7k | redundant = constraint_index_is_redundant(&ci, ineq->row[k]); |
1890 | 68.7k | if (redundant < 0) |
1891 | 0 | goto error; |
1892 | 68.7k | if (!redundant) |
1893 | 25.6k | continue; |
1894 | 43.0k | row[k] = -1; |
1895 | 43.0k | } |
1896 | 16.1k | constraint_index_free(&ci); |
1897 | 16.1k | return isl_stat_ok; |
1898 | 0 | error: |
1899 | 0 | constraint_index_free(&ci); |
1900 | 0 | return isl_stat_error; |
1901 | 16.1k | } |
1902 | | |
1903 | | static __isl_give isl_basic_set *remove_shifted_constraints( |
1904 | | __isl_take isl_basic_set *bset, __isl_keep isl_basic_set *context) |
1905 | 84 | { |
1906 | 84 | struct isl_constraint_index ci; |
1907 | 84 | int k; |
1908 | 84 | |
1909 | 84 | if (!bset || !context) |
1910 | 0 | return bset; |
1911 | 84 | |
1912 | 84 | if (context->n_ineq == 0) |
1913 | 0 | return bset; |
1914 | 84 | if (setup_constraint_index(&ci, context) < 0) |
1915 | 0 | return bset; |
1916 | 84 | |
1917 | 572 | for (k = 0; 84 k < bset->n_ineq; ++k488 ) { |
1918 | 488 | isl_bool redundant; |
1919 | 488 | |
1920 | 488 | redundant = constraint_index_is_redundant(&ci, bset->ineq[k]); |
1921 | 488 | if (redundant < 0) |
1922 | 0 | goto error; |
1923 | 488 | if (!redundant) |
1924 | 163 | continue; |
1925 | 325 | bset = isl_basic_set_cow(bset); |
1926 | 325 | if (!bset) |
1927 | 0 | goto error; |
1928 | 325 | isl_basic_set_drop_inequality(bset, k); |
1929 | 325 | --k; |
1930 | 325 | } |
1931 | 84 | constraint_index_free(&ci); |
1932 | 84 | return bset; |
1933 | 0 | error: |
1934 | 0 | constraint_index_free(&ci); |
1935 | 0 | return bset; |
1936 | 84 | } |
1937 | | |
1938 | | /* Remove constraints from "bmap" that are identical to constraints |
1939 | | * in "context" or that are more relaxed (greater constant term). |
1940 | | * |
1941 | | * We perform the test for shifted copies on the pure constraints |
1942 | | * in remove_shifted_constraints. |
1943 | | */ |
1944 | | static __isl_give isl_basic_map *isl_basic_map_remove_shifted_constraints( |
1945 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context) |
1946 | 608 | { |
1947 | 608 | isl_basic_set *bset, *bset_context; |
1948 | 608 | |
1949 | 608 | if (!bmap || !context) |
1950 | 0 | goto error; |
1951 | 608 | |
1952 | 608 | if (bmap->n_ineq == 0 || context->n_ineq == 084 ) { |
1953 | 524 | isl_basic_map_free(context); |
1954 | 524 | return bmap; |
1955 | 524 | } |
1956 | 84 | |
1957 | 84 | context = isl_basic_map_align_divs(context, bmap); |
1958 | 84 | bmap = isl_basic_map_align_divs(bmap, context); |
1959 | 84 | |
1960 | 84 | bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); |
1961 | 84 | bset_context = isl_basic_map_underlying_set(context); |
1962 | 84 | bset = remove_shifted_constraints(bset, bset_context); |
1963 | 84 | isl_basic_set_free(bset_context); |
1964 | 84 | |
1965 | 84 | bmap = isl_basic_map_overlying_set(bset, bmap); |
1966 | 84 | |
1967 | 84 | return bmap; |
1968 | 0 | error: |
1969 | 0 | isl_basic_map_free(bmap); |
1970 | 0 | isl_basic_map_free(context); |
1971 | 0 | return NULL; |
1972 | 84 | } |
1973 | | |
1974 | | /* Does the (linear part of a) constraint "c" involve any of the "len" |
1975 | | * "relevant" dimensions? |
1976 | | */ |
1977 | | static int is_related(isl_int *c, int len, int *relevant) |
1978 | 428k | { |
1979 | 428k | int i; |
1980 | 428k | |
1981 | 4.14M | for (i = 0; i < len; ++i3.71M ) { |
1982 | 3.98M | if (!relevant[i]) |
1983 | 2.61M | continue; |
1984 | 1.37M | if (!isl_int_is_zero(c[i])) |
1985 | 1.37M | return 1270k ; |
1986 | 1.37M | } |
1987 | 428k | |
1988 | 428k | return 0157k ; |
1989 | 428k | } |
1990 | | |
1991 | | /* Drop constraints from "bmap" that do not involve any of |
1992 | | * the dimensions marked "relevant". |
1993 | | */ |
1994 | | static __isl_give isl_basic_map *drop_unrelated_constraints( |
1995 | | __isl_take isl_basic_map *bmap, int *relevant) |
1996 | 85.7k | { |
1997 | 85.7k | int i, dim; |
1998 | 85.7k | |
1999 | 85.7k | dim = isl_basic_map_dim(bmap, isl_dim_all); |
2000 | 458k | for (i = 0; i < dim; ++i372k ) |
2001 | 427k | if (!relevant[i]) |
2002 | 55.2k | break; |
2003 | 85.7k | if (i >= dim) |
2004 | 30.5k | return bmap; |
2005 | 55.2k | |
2006 | 117k | for (i = bmap->n_eq - 1; 55.2k i >= 0; --i62.6k ) |
2007 | 62.6k | if (!is_related(bmap->eq[i] + 1, dim, relevant)) { |
2008 | 24.3k | bmap = isl_basic_map_cow(bmap); |
2009 | 24.3k | if (isl_basic_map_drop_equality(bmap, i) < 0) |
2010 | 0 | return isl_basic_map_free(bmap); |
2011 | 24.3k | } |
2012 | 55.2k | |
2013 | 420k | for (i = bmap->n_ineq - 1; 55.2k i >= 0; --i365k ) |
2014 | 365k | if (!is_related(bmap->ineq[i] + 1, dim, relevant)) { |
2015 | 133k | bmap = isl_basic_map_cow(bmap); |
2016 | 133k | if (isl_basic_map_drop_inequality(bmap, i) < 0) |
2017 | 0 | return isl_basic_map_free(bmap); |
2018 | 133k | } |
2019 | 55.2k | |
2020 | 55.2k | return bmap; |
2021 | 55.2k | } |
2022 | | |
2023 | | /* Update the groups in "group" based on the (linear part of a) constraint "c". |
2024 | | * |
2025 | | * In particular, for any variable involved in the constraint, |
2026 | | * find the actual group id from before and replace the group |
2027 | | * of the corresponding variable by the minimal group of all |
2028 | | * the variables involved in the constraint considered so far |
2029 | | * (if this minimum is smaller) or replace the minimum by this group |
2030 | | * (if the minimum is larger). |
2031 | | * |
2032 | | * At the end, all the variables in "c" will (indirectly) point |
2033 | | * to the minimal of the groups that they referred to originally. |
2034 | | */ |
2035 | | static void update_groups(int dim, int *group, isl_int *c) |
2036 | 661k | { |
2037 | 661k | int j; |
2038 | 661k | int min = dim; |
2039 | 661k | |
2040 | 8.65M | for (j = 0; j < dim; ++j7.99M ) { |
2041 | 7.99M | if (isl_int_is_zero(c[j])) |
2042 | 7.99M | continue7.12M ; |
2043 | 870k | while (870k group[j] >= 0 && group[group[j]] != group[j]261k ) |
2044 | 218 | group[j] = group[group[j]]; |
2045 | 870k | if (group[j] == min) |
2046 | 125k | continue; |
2047 | 745k | if (group[j] < min) { |
2048 | 670k | if (min >= 0 && min < dim) |
2049 | 9.15k | group[min] = group[j]; |
2050 | 670k | min = group[j]; |
2051 | 670k | } else |
2052 | 74.5k | group[group[j]] = min; |
2053 | 745k | } |
2054 | 661k | } |
2055 | | |
2056 | | /* Allocate an array of groups of variables, one for each variable |
2057 | | * in "context", initialized to zero. |
2058 | | */ |
2059 | | static int *alloc_groups(__isl_keep isl_basic_set *context) |
2060 | 36.0k | { |
2061 | 36.0k | isl_ctx *ctx; |
2062 | 36.0k | int dim; |
2063 | 36.0k | |
2064 | 36.0k | dim = isl_basic_set_dim(context, isl_dim_set); |
2065 | 36.0k | ctx = isl_basic_set_get_ctx(context); |
2066 | 36.0k | return isl_calloc_array(ctx, int, dim); |
2067 | 36.0k | } |
2068 | | |
2069 | | /* Drop constraints from "bmap" that only involve variables that are |
2070 | | * not related to any of the variables marked with a "-1" in "group". |
2071 | | * |
2072 | | * We construct groups of variables that collect variables that |
2073 | | * (indirectly) appear in some common constraint of "bmap". |
2074 | | * Each group is identified by the first variable in the group, |
2075 | | * except for the special group of variables that was already identified |
2076 | | * in the input as -1 (or are related to those variables). |
2077 | | * If group[i] is equal to i (or -1), then the group of i is i (or -1), |
2078 | | * otherwise the group of i is the group of group[i]. |
2079 | | * |
2080 | | * We first initialize groups for the remaining variables. |
2081 | | * Then we iterate over the constraints of "bmap" and update the |
2082 | | * group of the variables in the constraint by the smallest group. |
2083 | | * Finally, we resolve indirect references to groups by running over |
2084 | | * the variables. |
2085 | | * |
2086 | | * After computing the groups, we drop constraints that do not involve |
2087 | | * any variables in the -1 group. |
2088 | | */ |
2089 | | __isl_give isl_basic_map *isl_basic_map_drop_unrelated_constraints( |
2090 | | __isl_take isl_basic_map *bmap, __isl_take int *group) |
2091 | 99.1k | { |
2092 | 99.1k | int dim; |
2093 | 99.1k | int i; |
2094 | 99.1k | int last; |
2095 | 99.1k | |
2096 | 99.1k | if (!bmap) |
2097 | 0 | return NULL; |
2098 | 99.1k | |
2099 | 99.1k | dim = isl_basic_map_dim(bmap, isl_dim_all); |
2100 | 99.1k | |
2101 | 99.1k | last = -1; |
2102 | 729k | for (i = 0; i < dim; ++i630k ) |
2103 | 630k | if (group[i] >= 0) |
2104 | 240k | last = group[i] = i; |
2105 | 99.1k | if (last < 0) { |
2106 | 13.4k | free(group); |
2107 | 13.4k | return bmap; |
2108 | 13.4k | } |
2109 | 85.7k | |
2110 | 222k | for (i = 0; 85.7k i < bmap->n_eq; ++i136k ) |
2111 | 136k | update_groups(dim, group, bmap->eq[i] + 1); |
2112 | 610k | for (i = 0; i < bmap->n_ineq; ++i524k ) |
2113 | 524k | update_groups(dim, group, bmap->ineq[i] + 1); |
2114 | 85.7k | |
2115 | 684k | for (i = 0; i < dim; ++i598k ) |
2116 | 598k | if (group[i] >= 0) |
2117 | 165k | group[i] = group[group[i]]; |
2118 | 85.7k | |
2119 | 684k | for (i = 0; i < dim; ++i598k ) |
2120 | 598k | group[i] = group[i] == -1; |
2121 | 85.7k | |
2122 | 85.7k | bmap = drop_unrelated_constraints(bmap, group); |
2123 | 85.7k | |
2124 | 85.7k | free(group); |
2125 | 85.7k | return bmap; |
2126 | 85.7k | } |
2127 | | |
2128 | | /* Drop constraints from "context" that are irrelevant for computing |
2129 | | * the gist of "bset". |
2130 | | * |
2131 | | * In particular, drop constraints in variables that are not related |
2132 | | * to any of the variables involved in the constraints of "bset" |
2133 | | * in the sense that there is no sequence of constraints that connects them. |
2134 | | * |
2135 | | * We first mark all variables that appear in "bset" as belonging |
2136 | | * to a "-1" group and then continue with group_and_drop_irrelevant_constraints. |
2137 | | */ |
2138 | | static __isl_give isl_basic_set *drop_irrelevant_constraints( |
2139 | | __isl_take isl_basic_set *context, __isl_keep isl_basic_set *bset) |
2140 | 22.7k | { |
2141 | 22.7k | int *group; |
2142 | 22.7k | int dim; |
2143 | 22.7k | int i, j; |
2144 | 22.7k | |
2145 | 22.7k | if (!context || !bset) |
2146 | 0 | return isl_basic_set_free(context); |
2147 | 22.7k | |
2148 | 22.7k | group = alloc_groups(context); |
2149 | 22.7k | |
2150 | 22.7k | if (!group) |
2151 | 0 | return isl_basic_set_free(context); |
2152 | 22.7k | |
2153 | 22.7k | dim = isl_basic_set_dim(bset, isl_dim_set); |
2154 | 167k | for (i = 0; i < dim; ++i144k ) { |
2155 | 247k | for (j = 0; j < bset->n_eq; ++j103k ) |
2156 | 140k | if (!isl_int_is_zero(bset->eq[j][1 + i])) |
2157 | 140k | break36.6k ; |
2158 | 144k | if (j < bset->n_eq) { |
2159 | 36.6k | group[i] = -1; |
2160 | 36.6k | continue; |
2161 | 36.6k | } |
2162 | 449k | for (j = 0; 107k j < bset->n_ineq; ++j341k ) |
2163 | 379k | if (!isl_int_is_zero(bset->ineq[j][1 + i])) |
2164 | 379k | break37.7k ; |
2165 | 107k | if (j < bset->n_ineq) |
2166 | 37.7k | group[i] = -1; |
2167 | 107k | } |
2168 | 22.7k | |
2169 | 22.7k | return isl_basic_map_drop_unrelated_constraints(context, group); |
2170 | 22.7k | } |
2171 | | |
2172 | | /* Drop constraints from "context" that are irrelevant for computing |
2173 | | * the gist of the inequalities "ineq". |
2174 | | * Inequalities in "ineq" for which the corresponding element of row |
2175 | | * is set to -1 have already been marked for removal and should be ignored. |
2176 | | * |
2177 | | * In particular, drop constraints in variables that are not related |
2178 | | * to any of the variables involved in "ineq" |
2179 | | * in the sense that there is no sequence of constraints that connects them. |
2180 | | * |
2181 | | * We first mark all variables that appear in "bset" as belonging |
2182 | | * to a "-1" group and then continue with group_and_drop_irrelevant_constraints. |
2183 | | */ |
2184 | | static __isl_give isl_basic_set *drop_irrelevant_constraints_marked( |
2185 | | __isl_take isl_basic_set *context, __isl_keep isl_mat *ineq, int *row) |
2186 | 13.3k | { |
2187 | 13.3k | int *group; |
2188 | 13.3k | int dim; |
2189 | 13.3k | int i, j, n; |
2190 | 13.3k | |
2191 | 13.3k | if (!context || !ineq) |
2192 | 0 | return isl_basic_set_free(context); |
2193 | 13.3k | |
2194 | 13.3k | group = alloc_groups(context); |
2195 | 13.3k | |
2196 | 13.3k | if (!group) |
2197 | 0 | return isl_basic_set_free(context); |
2198 | 13.3k | |
2199 | 13.3k | dim = isl_basic_set_dim(context, isl_dim_set); |
2200 | 13.3k | n = isl_mat_rows(ineq); |
2201 | 97.7k | for (i = 0; i < dim; ++i84.3k ) { |
2202 | 497k | for (j = 0; j < n; ++j412k ) { |
2203 | 440k | if (row[j] < 0) |
2204 | 256k | continue; |
2205 | 183k | if (!isl_int_is_zero(ineq->row[j][1 + i])) |
2206 | 183k | break27.6k ; |
2207 | 183k | } |
2208 | 84.3k | if (j < n) |
2209 | 27.6k | group[i] = -1; |
2210 | 84.3k | } |
2211 | 13.3k | |
2212 | 13.3k | return isl_basic_map_drop_unrelated_constraints(context, group); |
2213 | 13.3k | } |
2214 | | |
2215 | | /* Do all "n" entries of "row" contain a negative value? |
2216 | | */ |
2217 | | static int all_neg(int *row, int n) |
2218 | 16.1k | { |
2219 | 16.1k | int i; |
2220 | 16.1k | |
2221 | 48.2k | for (i = 0; i < n; ++i32.1k ) |
2222 | 45.4k | if (row[i] >= 0) |
2223 | 13.3k | return 0; |
2224 | 16.1k | |
2225 | 16.1k | return 12.77k ; |
2226 | 16.1k | } |
2227 | | |
2228 | | /* Update the inequalities in "bset" based on the information in "row" |
2229 | | * and "tab". |
2230 | | * |
2231 | | * In particular, the array "row" contains either -1, meaning that |
2232 | | * the corresponding inequality of "bset" is redundant, or the index |
2233 | | * of an inequality in "tab". |
2234 | | * |
2235 | | * If the row entry is -1, then drop the inequality. |
2236 | | * Otherwise, if the constraint is marked redundant in the tableau, |
2237 | | * then drop the inequality. Similarly, if it is marked as an equality |
2238 | | * in the tableau, then turn the inequality into an equality and |
2239 | | * perform Gaussian elimination. |
2240 | | */ |
2241 | | static __isl_give isl_basic_set *update_ineq(__isl_take isl_basic_set *bset, |
2242 | | __isl_keep int *row, struct isl_tab *tab) |
2243 | 16.1k | { |
2244 | 16.1k | int i; |
2245 | 16.1k | unsigned n_ineq; |
2246 | 16.1k | unsigned n_eq; |
2247 | 16.1k | int found_equality = 0; |
2248 | 16.1k | |
2249 | 16.1k | if (!bset) |
2250 | 0 | return NULL; |
2251 | 16.1k | if (tab && tab->empty13.0k ) |
2252 | 2.46k | return isl_basic_set_set_to_empty(bset); |
2253 | 13.6k | |
2254 | 13.6k | n_ineq = bset->n_ineq; |
2255 | 76.2k | for (i = n_ineq - 1; i >= 0; --i62.5k ) { |
2256 | 62.5k | if (row[i] < 0) { |
2257 | 42.4k | if (isl_basic_set_drop_inequality(bset, i) < 0) |
2258 | 0 | return isl_basic_set_free(bset); |
2259 | 42.4k | continue; |
2260 | 42.4k | } |
2261 | 20.1k | if (!tab) |
2262 | 481 | continue; |
2263 | 19.6k | n_eq = tab->n_eq; |
2264 | 19.6k | if (isl_tab_is_equality(tab, n_eq + row[i])) { |
2265 | 174 | isl_basic_map_inequality_to_equality(bset, i); |
2266 | 174 | found_equality = 1; |
2267 | 19.4k | } else if (isl_tab_is_redundant(tab, n_eq + row[i])) { |
2268 | 2.12k | if (isl_basic_set_drop_inequality(bset, i) < 0) |
2269 | 0 | return isl_basic_set_free(bset); |
2270 | 2.12k | } |
2271 | 19.6k | } |
2272 | 13.6k | |
2273 | 13.6k | if (found_equality) |
2274 | 169 | bset = isl_basic_set_gauss(bset, NULL); |
2275 | 13.6k | bset = isl_basic_set_finalize(bset); |
2276 | 13.6k | return bset; |
2277 | 13.6k | } |
2278 | | |
2279 | | /* Update the inequalities in "bset" based on the information in "row" |
2280 | | * and "tab" and free all arguments (other than "bset"). |
2281 | | */ |
2282 | | static __isl_give isl_basic_set *update_ineq_free( |
2283 | | __isl_take isl_basic_set *bset, __isl_take isl_mat *ineq, |
2284 | | __isl_take isl_basic_set *context, __isl_take int *row, |
2285 | | struct isl_tab *tab) |
2286 | 16.1k | { |
2287 | 16.1k | isl_mat_free(ineq); |
2288 | 16.1k | isl_basic_set_free(context); |
2289 | 16.1k | |
2290 | 16.1k | bset = update_ineq(bset, row, tab); |
2291 | 16.1k | |
2292 | 16.1k | free(row); |
2293 | 16.1k | isl_tab_free(tab); |
2294 | 16.1k | return bset; |
2295 | 16.1k | } |
2296 | | |
2297 | | /* Remove all information from bset that is redundant in the context |
2298 | | * of context. |
2299 | | * "ineq" contains the (possibly transformed) inequalities of "bset", |
2300 | | * in the same order. |
2301 | | * The (explicit) equalities of "bset" are assumed to have been taken |
2302 | | * into account by the transformation such that only the inequalities |
2303 | | * are relevant. |
2304 | | * "context" is assumed not to be empty. |
2305 | | * |
2306 | | * "row" keeps track of the constraint index of a "bset" inequality in "tab". |
2307 | | * A value of -1 means that the inequality is obviously redundant and may |
2308 | | * not even appear in "tab". |
2309 | | * |
2310 | | * We first mark the inequalities of "bset" |
2311 | | * that are obviously redundant with respect to some inequality in "context". |
2312 | | * Then we remove those constraints from "context" that have become |
2313 | | * irrelevant for computing the gist of "bset". |
2314 | | * Note that this removal of constraints cannot be replaced by |
2315 | | * a factorization because factors in "bset" may still be connected |
2316 | | * to each other through constraints in "context". |
2317 | | * |
2318 | | * If there are any inequalities left, we construct a tableau for |
2319 | | * the context and then add the inequalities of "bset". |
2320 | | * Before adding these inequalities, we freeze all constraints such that |
2321 | | * they won't be considered redundant in terms of the constraints of "bset". |
2322 | | * Then we detect all redundant constraints (among the |
2323 | | * constraints that weren't frozen), first by checking for redundancy in the |
2324 | | * the tableau and then by checking if replacing a constraint by its negation |
2325 | | * would lead to an empty set. This last step is fairly expensive |
2326 | | * and could be optimized by more reuse of the tableau. |
2327 | | * Finally, we update bset according to the results. |
2328 | | */ |
2329 | | static __isl_give isl_basic_set *uset_gist_full(__isl_take isl_basic_set *bset, |
2330 | | __isl_take isl_mat *ineq, __isl_take isl_basic_set *context) |
2331 | 22.6k | { |
2332 | 22.6k | int i, r; |
2333 | 22.6k | int *row = NULL; |
2334 | 22.6k | isl_ctx *ctx; |
2335 | 22.6k | isl_basic_set *combined = NULL; |
2336 | 22.6k | struct isl_tab *tab = NULL; |
2337 | 22.6k | unsigned n_eq, context_ineq; |
2338 | 22.6k | |
2339 | 22.6k | if (!bset || !ineq || !context) |
2340 | 0 | goto error; |
2341 | 22.6k | |
2342 | 22.6k | if (bset->n_ineq == 0 || isl_basic_set_plain_is_universe(context)16.8k ) { |
2343 | 6.54k | isl_basic_set_free(context); |
2344 | 6.54k | isl_mat_free(ineq); |
2345 | 6.54k | return bset; |
2346 | 6.54k | } |
2347 | 16.1k | |
2348 | 16.1k | ctx = isl_basic_set_get_ctx(context); |
2349 | 16.1k | row = isl_calloc_array(ctx, int, bset->n_ineq); |
2350 | 16.1k | if (!row) |
2351 | 0 | goto error; |
2352 | 16.1k | |
2353 | 16.1k | if (mark_shifted_constraints(ineq, context, row) < 0) |
2354 | 0 | goto error; |
2355 | 16.1k | if (all_neg(row, bset->n_ineq)) |
2356 | 2.77k | return update_ineq_free(bset, ineq, context, row, NULL); |
2357 | 13.3k | |
2358 | 13.3k | context = drop_irrelevant_constraints_marked(context, ineq, row); |
2359 | 13.3k | if (!context) |
2360 | 0 | goto error; |
2361 | 13.3k | if (isl_basic_set_plain_is_universe(context)) |
2362 | 280 | return update_ineq_free(bset, ineq, context, row, NULL); |
2363 | 13.0k | |
2364 | 13.0k | n_eq = context->n_eq; |
2365 | 13.0k | context_ineq = context->n_ineq; |
2366 | 13.0k | combined = isl_basic_set_cow(isl_basic_set_copy(context)); |
2367 | 13.0k | combined = isl_basic_set_extend_constraints(combined, 0, bset->n_ineq); |
2368 | 13.0k | tab = isl_tab_from_basic_set(combined, 0); |
2369 | 60.1k | for (i = 0; i < context_ineq; ++i47.0k ) |
2370 | 47.0k | if (isl_tab_freeze_constraint(tab, n_eq + i) < 0) |
2371 | 0 | goto error; |
2372 | 13.0k | if (isl_tab_extend_cons(tab, bset->n_ineq) < 0) |
2373 | 0 | goto error; |
2374 | 13.0k | r = context_ineq; |
2375 | 67.3k | for (i = 0; i < bset->n_ineq; ++i54.2k ) { |
2376 | 54.2k | if (row[i] < 0) |
2377 | 29.1k | continue; |
2378 | 25.1k | combined = isl_basic_set_add_ineq(combined, ineq->row[i]); |
2379 | 25.1k | if (isl_tab_add_ineq(tab, ineq->row[i]) < 0) |
2380 | 0 | goto error; |
2381 | 25.1k | row[i] = r++; |
2382 | 25.1k | } |
2383 | 13.0k | if (isl_tab_detect_implicit_equalities(tab) < 0) |
2384 | 0 | goto error; |
2385 | 13.0k | if (isl_tab_detect_redundant(tab) < 0) |
2386 | 0 | goto error; |
2387 | 67.3k | for (i = bset->n_ineq - 1; 13.0k i >= 0; --i54.2k ) { |
2388 | 54.2k | isl_basic_set *test; |
2389 | 54.2k | int is_empty; |
2390 | 54.2k | |
2391 | 54.2k | if (row[i] < 0) |
2392 | 29.1k | continue; |
2393 | 25.1k | r = row[i]; |
2394 | 25.1k | if (tab->con[n_eq + r].is_redundant) |
2395 | 2.30k | continue; |
2396 | 22.8k | test = isl_basic_set_dup(combined); |
2397 | 22.8k | if (isl_inequality_negate(test, r) < 0) |
2398 | 0 | test = isl_basic_set_free(test); |
2399 | 22.8k | test = isl_basic_set_update_from_tab(test, tab); |
2400 | 22.8k | is_empty = isl_basic_set_is_empty(test); |
2401 | 22.8k | isl_basic_set_free(test); |
2402 | 22.8k | if (is_empty < 0) |
2403 | 0 | goto error; |
2404 | 22.8k | if (is_empty) |
2405 | 5.50k | tab->con[n_eq + r].is_redundant = 1; |
2406 | 22.8k | } |
2407 | 13.0k | bset = update_ineq_free(bset, ineq, context, row, tab); |
2408 | 13.0k | if (bset) { |
2409 | 13.0k | ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT); |
2410 | 13.0k | ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT); |
2411 | 13.0k | } |
2412 | 13.0k | |
2413 | 13.0k | isl_basic_set_free(combined); |
2414 | 13.0k | return bset; |
2415 | 0 | error: |
2416 | 0 | free(row); |
2417 | 0 | isl_mat_free(ineq); |
2418 | 0 | isl_tab_free(tab); |
2419 | 0 | isl_basic_set_free(combined); |
2420 | 0 | isl_basic_set_free(context); |
2421 | 0 | isl_basic_set_free(bset); |
2422 | 0 | return NULL; |
2423 | 13.0k | } |
2424 | | |
2425 | | /* Extract the inequalities of "bset" as an isl_mat. |
2426 | | */ |
2427 | | static __isl_give isl_mat *extract_ineq(__isl_keep isl_basic_set *bset) |
2428 | 22.7k | { |
2429 | 22.7k | unsigned total; |
2430 | 22.7k | isl_ctx *ctx; |
2431 | 22.7k | isl_mat *ineq; |
2432 | 22.7k | |
2433 | 22.7k | if (!bset) |
2434 | 0 | return NULL; |
2435 | 22.7k | |
2436 | 22.7k | ctx = isl_basic_set_get_ctx(bset); |
2437 | 22.7k | total = isl_basic_set_total_dim(bset); |
2438 | 22.7k | ineq = isl_mat_sub_alloc6(ctx, bset->ineq, 0, bset->n_ineq, |
2439 | 22.7k | 0, 1 + total); |
2440 | 22.7k | |
2441 | 22.7k | return ineq; |
2442 | 22.7k | } |
2443 | | |
2444 | | /* Remove all information from "bset" that is redundant in the context |
2445 | | * of "context", for the case where both "bset" and "context" are |
2446 | | * full-dimensional. |
2447 | | */ |
2448 | | static __isl_give isl_basic_set *uset_gist_uncompressed( |
2449 | | __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context) |
2450 | 10.8k | { |
2451 | 10.8k | isl_mat *ineq; |
2452 | 10.8k | |
2453 | 10.8k | ineq = extract_ineq(bset); |
2454 | 10.8k | return uset_gist_full(bset, ineq, context); |
2455 | 10.8k | } |
2456 | | |
2457 | | /* Remove all information from "bset" that is redundant in the context |
2458 | | * of "context", for the case where the combined equalities of |
2459 | | * "bset" and "context" allow for a compression that can be obtained |
2460 | | * by preapplication of "T". |
2461 | | * |
2462 | | * "bset" itself is not transformed by "T". Instead, the inequalities |
2463 | | * are extracted from "bset" and those are transformed by "T". |
2464 | | * uset_gist_full then determines which of the transformed inequalities |
2465 | | * are redundant with respect to the transformed "context" and removes |
2466 | | * the corresponding inequalities from "bset". |
2467 | | * |
2468 | | * After preapplying "T" to the inequalities, any common factor is |
2469 | | * removed from the coefficients. If this results in a tightening |
2470 | | * of the constant term, then the same tightening is applied to |
2471 | | * the corresponding untransformed inequality in "bset". |
2472 | | * That is, if after plugging in T, a constraint f(x) >= 0 is of the form |
2473 | | * |
2474 | | * g f'(x) + r >= 0 |
2475 | | * |
2476 | | * with 0 <= r < g, then it is equivalent to |
2477 | | * |
2478 | | * f'(x) >= 0 |
2479 | | * |
2480 | | * This means that f(x) >= 0 is equivalent to f(x) - r >= 0 in the affine |
2481 | | * subspace compressed by T since the latter would be transformed to |
2482 | | * |
2483 | | * g f'(x) >= 0 |
2484 | | */ |
2485 | | static __isl_give isl_basic_set *uset_gist_compressed( |
2486 | | __isl_take isl_basic_set *bset, __isl_take isl_basic_set *context, |
2487 | | __isl_take isl_mat *T) |
2488 | 11.8k | { |
2489 | 11.8k | isl_ctx *ctx; |
2490 | 11.8k | isl_mat *ineq; |
2491 | 11.8k | int i, n_row, n_col; |
2492 | 11.8k | isl_int rem; |
2493 | 11.8k | |
2494 | 11.8k | ineq = extract_ineq(bset); |
2495 | 11.8k | ineq = isl_mat_product(ineq, isl_mat_copy(T)); |
2496 | 11.8k | context = isl_basic_set_preimage(context, T); |
2497 | 11.8k | |
2498 | 11.8k | if (!ineq || !context) |
2499 | 0 | goto error; |
2500 | 11.8k | if (isl_basic_set_plain_is_empty(context)) { |
2501 | 9 | isl_mat_free(ineq); |
2502 | 9 | isl_basic_set_free(context); |
2503 | 9 | return isl_basic_set_set_to_empty(bset); |
2504 | 9 | } |
2505 | 11.8k | |
2506 | 11.8k | ctx = isl_mat_get_ctx(ineq); |
2507 | 11.8k | n_row = isl_mat_rows(ineq); |
2508 | 11.8k | n_col = isl_mat_cols(ineq); |
2509 | 11.8k | isl_int_init(rem); |
2510 | 44.5k | for (i = 0; i < n_row; ++i32.7k ) { |
2511 | 32.7k | isl_seq_gcd(ineq->row[i] + 1, n_col - 1, &ctx->normalize_gcd); |
2512 | 32.7k | if (isl_int_is_zero(ctx->normalize_gcd)) |
2513 | 32.7k | continue37 ; |
2514 | 32.6k | if (isl_int_is_one(ctx->normalize_gcd)) |
2515 | 32.6k | continue31.7k ; |
2516 | 900 | isl_seq_scale_down(ineq->row[i] + 1, ineq->row[i] + 1, |
2517 | 900 | ctx->normalize_gcd, n_col - 1); |
2518 | 900 | isl_int_fdiv_r(rem, ineq->row[i][0], ctx->normalize_gcd); |
2519 | 900 | isl_int_fdiv_q(ineq->row[i][0], |
2520 | 900 | ineq->row[i][0], ctx->normalize_gcd); |
2521 | 900 | if (isl_int_is_zero(rem)) |
2522 | 900 | continue650 ; |
2523 | 250 | bset = isl_basic_set_cow(bset); |
2524 | 250 | if (!bset) |
2525 | 0 | break; |
2526 | 250 | isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], rem); |
2527 | 250 | } |
2528 | 11.8k | isl_int_clear(rem); |
2529 | 11.8k | |
2530 | 11.8k | return uset_gist_full(bset, ineq, context); |
2531 | 0 | error: |
2532 | 0 | isl_mat_free(ineq); |
2533 | 0 | isl_basic_set_free(context); |
2534 | 0 | isl_basic_set_free(bset); |
2535 | 0 | return NULL; |
2536 | 11.8k | } |
2537 | | |
2538 | | /* Project "bset" onto the variables that are involved in "template". |
2539 | | */ |
2540 | | static __isl_give isl_basic_set *project_onto_involved( |
2541 | | __isl_take isl_basic_set *bset, __isl_keep isl_basic_set *template) |
2542 | 11.8k | { |
2543 | 11.8k | int i, n; |
2544 | 11.8k | |
2545 | 11.8k | if (!bset || !template) |
2546 | 0 | return isl_basic_set_free(bset); |
2547 | 11.8k | |
2548 | 11.8k | n = isl_basic_set_dim(template, isl_dim_set); |
2549 | 11.8k | |
2550 | 92.0k | for (i = 0; i < n; ++i80.1k ) { |
2551 | 80.1k | isl_bool involved; |
2552 | 80.1k | |
2553 | 80.1k | involved = isl_basic_set_involves_dims(template, |
2554 | 80.1k | isl_dim_set, i, 1); |
2555 | 80.1k | if (involved < 0) |
2556 | 0 | return isl_basic_set_free(bset); |
2557 | 80.1k | if (involved) |
2558 | 45.6k | continue; |
2559 | 34.5k | bset = isl_basic_set_eliminate_vars(bset, i, 1); |
2560 | 34.5k | } |
2561 | 11.8k | |
2562 | 11.8k | return bset; |
2563 | 11.8k | } |
2564 | | |
2565 | | /* Remove all information from bset that is redundant in the context |
2566 | | * of context. In particular, equalities that are linear combinations |
2567 | | * of those in context are removed. Then the inequalities that are |
2568 | | * redundant in the context of the equalities and inequalities of |
2569 | | * context are removed. |
2570 | | * |
2571 | | * First of all, we drop those constraints from "context" |
2572 | | * that are irrelevant for computing the gist of "bset". |
2573 | | * Alternatively, we could factorize the intersection of "context" and "bset". |
2574 | | * |
2575 | | * We first compute the intersection of the integer affine hulls |
2576 | | * of "bset" and "context", |
2577 | | * compute the gist inside this intersection and then reduce |
2578 | | * the constraints with respect to the equalities of the context |
2579 | | * that only involve variables already involved in the input. |
2580 | | * |
2581 | | * If two constraints are mutually redundant, then uset_gist_full |
2582 | | * will remove the second of those constraints. We therefore first |
2583 | | * sort the constraints so that constraints not involving existentially |
2584 | | * quantified variables are given precedence over those that do. |
2585 | | * We have to perform this sorting before the variable compression, |
2586 | | * because that may effect the order of the variables. |
2587 | | */ |
2588 | | static __isl_give isl_basic_set *uset_gist(__isl_take isl_basic_set *bset, |
2589 | | __isl_take isl_basic_set *context) |
2590 | 22.7k | { |
2591 | 22.7k | isl_mat *eq; |
2592 | 22.7k | isl_mat *T; |
2593 | 22.7k | isl_basic_set *aff; |
2594 | 22.7k | isl_basic_set *aff_context; |
2595 | 22.7k | unsigned total; |
2596 | 22.7k | |
2597 | 22.7k | if (!bset || !context) |
2598 | 0 | goto error; |
2599 | 22.7k | |
2600 | 22.7k | context = drop_irrelevant_constraints(context, bset); |
2601 | 22.7k | |
2602 | 22.7k | bset = isl_basic_set_detect_equalities(bset); |
2603 | 22.7k | aff = isl_basic_set_copy(bset); |
2604 | 22.7k | aff = isl_basic_set_plain_affine_hull(aff); |
2605 | 22.7k | context = isl_basic_set_detect_equalities(context); |
2606 | 22.7k | aff_context = isl_basic_set_copy(context); |
2607 | 22.7k | aff_context = isl_basic_set_plain_affine_hull(aff_context); |
2608 | 22.7k | aff = isl_basic_set_intersect(aff, aff_context); |
2609 | 22.7k | if (!aff) |
2610 | 0 | goto error; |
2611 | 22.7k | if (isl_basic_set_plain_is_empty(aff)) { |
2612 | 1 | isl_basic_set_free(bset); |
2613 | 1 | isl_basic_set_free(context); |
2614 | 1 | return aff; |
2615 | 1 | } |
2616 | 22.7k | bset = isl_basic_set_sort_constraints(bset); |
2617 | 22.7k | if (aff->n_eq == 0) { |
2618 | 10.8k | isl_basic_set_free(aff); |
2619 | 10.8k | return uset_gist_uncompressed(bset, context); |
2620 | 10.8k | } |
2621 | 11.8k | total = isl_basic_set_total_dim(bset); |
2622 | 11.8k | eq = isl_mat_sub_alloc6(bset->ctx, aff->eq, 0, aff->n_eq, 0, 1 + total); |
2623 | 11.8k | eq = isl_mat_cow(eq); |
2624 | 11.8k | T = isl_mat_variable_compression(eq, NULL); |
2625 | 11.8k | isl_basic_set_free(aff); |
2626 | 11.8k | if (T && T->n_col == 0) { |
2627 | 0 | isl_mat_free(T); |
2628 | 0 | isl_basic_set_free(context); |
2629 | 0 | return isl_basic_set_set_to_empty(bset); |
2630 | 0 | } |
2631 | 11.8k | |
2632 | 11.8k | aff_context = isl_basic_set_affine_hull(isl_basic_set_copy(context)); |
2633 | 11.8k | aff_context = project_onto_involved(aff_context, bset); |
2634 | 11.8k | |
2635 | 11.8k | bset = uset_gist_compressed(bset, context, T); |
2636 | 11.8k | bset = isl_basic_set_reduce_using_equalities(bset, aff_context); |
2637 | 11.8k | |
2638 | 11.8k | if (bset) { |
2639 | 11.8k | ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT); |
2640 | 11.8k | ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT); |
2641 | 11.8k | } |
2642 | 11.8k | |
2643 | 11.8k | return bset; |
2644 | 0 | error: |
2645 | 0 | isl_basic_set_free(bset); |
2646 | 0 | isl_basic_set_free(context); |
2647 | 0 | return NULL; |
2648 | 11.8k | } |
2649 | | |
2650 | | /* Return the number of equality constraints in "bmap" that involve |
2651 | | * local variables. This function assumes that Gaussian elimination |
2652 | | * has been applied to the equality constraints. |
2653 | | */ |
2654 | | static int n_div_eq(__isl_keep isl_basic_map *bmap) |
2655 | 1.21k | { |
2656 | 1.21k | int i; |
2657 | 1.21k | int total, n_div; |
2658 | 1.21k | |
2659 | 1.21k | if (!bmap) |
2660 | 0 | return -1; |
2661 | 1.21k | |
2662 | 1.21k | if (bmap->n_eq == 0) |
2663 | 480 | return 0; |
2664 | 736 | |
2665 | 736 | total = isl_basic_map_dim(bmap, isl_dim_all); |
2666 | 736 | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
2667 | 736 | total -= n_div; |
2668 | 736 | |
2669 | 1.28k | for (i = 0; i < bmap->n_eq; ++i550 ) |
2670 | 879 | if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, |
2671 | 879 | n_div) == -1) |
2672 | 329 | return i; |
2673 | 736 | |
2674 | 736 | return bmap->n_eq407 ; |
2675 | 736 | } |
2676 | | |
2677 | | /* Construct a basic map in "space" defined by the equality constraints in "eq". |
2678 | | * The constraints are assumed not to involve any local variables. |
2679 | | */ |
2680 | | static __isl_give isl_basic_map *basic_map_from_equalities( |
2681 | | __isl_take isl_space *space, __isl_take isl_mat *eq) |
2682 | 2 | { |
2683 | 2 | int i, k; |
2684 | 2 | isl_basic_map *bmap = NULL; |
2685 | 2 | |
2686 | 2 | if (!space || !eq) |
2687 | 0 | goto error; |
2688 | 2 | |
2689 | 2 | if (1 + isl_space_dim(space, isl_dim_all) != eq->n_col) |
2690 | 2 | isl_die0 (isl_space_get_ctx(space), isl_error_internal, |
2691 | 2 | "unexpected number of columns", goto error); |
2692 | 2 | |
2693 | 2 | bmap = isl_basic_map_alloc_space(isl_space_copy(space), |
2694 | 2 | 0, eq->n_row, 0); |
2695 | 6 | for (i = 0; i < eq->n_row; ++i4 ) { |
2696 | 4 | k = isl_basic_map_alloc_equality(bmap); |
2697 | 4 | if (k < 0) |
2698 | 0 | goto error; |
2699 | 4 | isl_seq_cpy(bmap->eq[k], eq->row[i], eq->n_col); |
2700 | 4 | } |
2701 | 2 | |
2702 | 2 | isl_space_free(space); |
2703 | 2 | isl_mat_free(eq); |
2704 | 2 | return bmap; |
2705 | 0 | error: |
2706 | 0 | isl_space_free(space); |
2707 | 0 | isl_mat_free(eq); |
2708 | 0 | isl_basic_map_free(bmap); |
2709 | 0 | return NULL; |
2710 | 2 | } |
2711 | | |
2712 | | /* Construct and return a variable compression based on the equality |
2713 | | * constraints in "bmap1" and "bmap2" that do not involve the local variables. |
2714 | | * "n1" is the number of (initial) equality constraints in "bmap1" |
2715 | | * that do involve local variables. |
2716 | | * "n2" is the number of (initial) equality constraints in "bmap2" |
2717 | | * that do involve local variables. |
2718 | | * "total" is the total number of other variables. |
2719 | | * This function assumes that Gaussian elimination |
2720 | | * has been applied to the equality constraints in both "bmap1" and "bmap2" |
2721 | | * such that the equality constraints not involving local variables |
2722 | | * are those that start at "n1" or "n2". |
2723 | | * |
2724 | | * If either of "bmap1" and "bmap2" does not have such equality constraints, |
2725 | | * then simply compute the compression based on the equality constraints |
2726 | | * in the other basic map. |
2727 | | * Otherwise, combine the equality constraints from both into a new |
2728 | | * basic map such that Gaussian elimination can be applied to this combination |
2729 | | * and then construct a variable compression from the resulting |
2730 | | * equality constraints. |
2731 | | */ |
2732 | | static __isl_give isl_mat *combined_variable_compression( |
2733 | | __isl_keep isl_basic_map *bmap1, int n1, |
2734 | | __isl_keep isl_basic_map *bmap2, int n2, int total) |
2735 | 7 | { |
2736 | 7 | isl_ctx *ctx; |
2737 | 7 | isl_mat *E1, *E2, *V; |
2738 | 7 | isl_basic_map *bmap; |
2739 | 7 | |
2740 | 7 | ctx = isl_basic_map_get_ctx(bmap1); |
2741 | 7 | if (bmap1->n_eq == n1) { |
2742 | 3 | E2 = isl_mat_sub_alloc6(ctx, bmap2->eq, |
2743 | 3 | n2, bmap2->n_eq - n2, 0, 1 + total); |
2744 | 3 | return isl_mat_variable_compression(E2, NULL); |
2745 | 3 | } |
2746 | 4 | if (bmap2->n_eq == n2) { |
2747 | 2 | E1 = isl_mat_sub_alloc6(ctx, bmap1->eq, |
2748 | 2 | n1, bmap1->n_eq - n1, 0, 1 + total); |
2749 | 2 | return isl_mat_variable_compression(E1, NULL); |
2750 | 2 | } |
2751 | 2 | E1 = isl_mat_sub_alloc6(ctx, bmap1->eq, |
2752 | 2 | n1, bmap1->n_eq - n1, 0, 1 + total); |
2753 | 2 | E2 = isl_mat_sub_alloc6(ctx, bmap2->eq, |
2754 | 2 | n2, bmap2->n_eq - n2, 0, 1 + total); |
2755 | 2 | E1 = isl_mat_concat(E1, E2); |
2756 | 2 | bmap = basic_map_from_equalities(isl_basic_map_get_space(bmap1), E1); |
2757 | 2 | bmap = isl_basic_map_gauss(bmap, NULL); |
2758 | 2 | if (!bmap) |
2759 | 0 | return NULL; |
2760 | 2 | E1 = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total); |
2761 | 2 | V = isl_mat_variable_compression(E1, NULL); |
2762 | 2 | isl_basic_map_free(bmap); |
2763 | 2 | |
2764 | 2 | return V; |
2765 | 2 | } |
2766 | | |
2767 | | /* Extract the stride constraints from "bmap", compressed |
2768 | | * with respect to both the stride constraints in "context" and |
2769 | | * the remaining equality constraints in both "bmap" and "context". |
2770 | | * "bmap_n_eq" is the number of (initial) stride constraints in "bmap". |
2771 | | * "context_n_eq" is the number of (initial) stride constraints in "context". |
2772 | | * |
2773 | | * Let x be all variables in "bmap" (and "context") other than the local |
2774 | | * variables. First compute a variable compression |
2775 | | * |
2776 | | * x = V x' |
2777 | | * |
2778 | | * based on the non-stride equality constraints in "bmap" and "context". |
2779 | | * Consider the stride constraints of "context", |
2780 | | * |
2781 | | * A(x) + B(y) = 0 |
2782 | | * |
2783 | | * with y the local variables and plug in the variable compression, |
2784 | | * resulting in |
2785 | | * |
2786 | | * A(V x') + B(y) = 0 |
2787 | | * |
2788 | | * Use these constraints to compute a parameter compression on x' |
2789 | | * |
2790 | | * x' = T x'' |
2791 | | * |
2792 | | * Now consider the stride constraints of "bmap" |
2793 | | * |
2794 | | * C(x) + D(y) = 0 |
2795 | | * |
2796 | | * and plug in x = V*T x''. |
2797 | | * That is, return A = [C*V*T D]. |
2798 | | */ |
2799 | | static __isl_give isl_mat *extract_compressed_stride_constraints( |
2800 | | __isl_keep isl_basic_map *bmap, int bmap_n_eq, |
2801 | | __isl_keep isl_basic_map *context, int context_n_eq) |
2802 | 7 | { |
2803 | 7 | int total, n_div; |
2804 | 7 | isl_ctx *ctx; |
2805 | 7 | isl_mat *A, *B, *T, *V; |
2806 | 7 | |
2807 | 7 | total = isl_basic_map_dim(context, isl_dim_all); |
2808 | 7 | n_div = isl_basic_map_dim(context, isl_dim_div); |
2809 | 7 | total -= n_div; |
2810 | 7 | |
2811 | 7 | ctx = isl_basic_map_get_ctx(bmap); |
2812 | 7 | |
2813 | 7 | V = combined_variable_compression(bmap, bmap_n_eq, |
2814 | 7 | context, context_n_eq, total); |
2815 | 7 | |
2816 | 7 | A = isl_mat_sub_alloc6(ctx, context->eq, 0, context_n_eq, 0, 1 + total); |
2817 | 7 | B = isl_mat_sub_alloc6(ctx, context->eq, |
2818 | 7 | 0, context_n_eq, 1 + total, n_div); |
2819 | 7 | A = isl_mat_product(A, isl_mat_copy(V)); |
2820 | 7 | T = isl_mat_parameter_compression_ext(A, B); |
2821 | 7 | T = isl_mat_product(V, T); |
2822 | 7 | |
2823 | 7 | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
2824 | 7 | T = isl_mat_diagonal(T, isl_mat_identity(ctx, n_div)); |
2825 | 7 | |
2826 | 7 | A = isl_mat_sub_alloc6(ctx, bmap->eq, |
2827 | 7 | 0, bmap_n_eq, 0, 1 + total + n_div); |
2828 | 7 | A = isl_mat_product(A, T); |
2829 | 7 | |
2830 | 7 | return A; |
2831 | 7 | } |
2832 | | |
2833 | | /* Remove the prime factors from *g that have an exponent that |
2834 | | * is strictly smaller than the exponent in "c". |
2835 | | * All exponents in *g are known to be smaller than or equal |
2836 | | * to those in "c". |
2837 | | * |
2838 | | * That is, if *g is equal to |
2839 | | * |
2840 | | * p_1^{e_1} p_2^{e_2} ... p_n^{e_n} |
2841 | | * |
2842 | | * and "c" is equal to |
2843 | | * |
2844 | | * p_1^{f_1} p_2^{f_2} ... p_n^{f_n} |
2845 | | * |
2846 | | * then update *g to |
2847 | | * |
2848 | | * p_1^{e_1 * (e_1 = f_1)} p_2^{e_2 * (e_2 = f_2)} ... |
2849 | | * p_n^{e_n * (e_n = f_n)} |
2850 | | * |
2851 | | * If e_i = f_i, then c / *g does not have any p_i factors and therefore |
2852 | | * neither does the gcd of *g and c / *g. |
2853 | | * If e_i < f_i, then the gcd of *g and c / *g has a positive |
2854 | | * power min(e_i, s_i) of p_i with s_i = f_i - e_i among its factors. |
2855 | | * Dividing *g by this gcd therefore strictly reduces the exponent |
2856 | | * of the prime factors that need to be removed, while leaving the |
2857 | | * other prime factors untouched. |
2858 | | * Repeating this process until gcd(*g, c / *g) = 1 therefore |
2859 | | * removes all undesired factors, without removing any others. |
2860 | | */ |
2861 | | static void remove_incomplete_powers(isl_int *g, isl_int c) |
2862 | 6 | { |
2863 | 6 | isl_int t; |
2864 | 6 | |
2865 | 6 | isl_int_init(t); |
2866 | 9 | for (;;) { |
2867 | 9 | isl_int_divexact(t, c, *g); |
2868 | 9 | isl_int_gcd(t, t, *g); |
2869 | 9 | if (isl_int_is_one(t)) |
2870 | 9 | break6 ; |
2871 | 3 | isl_int_divexact(*g, *g, t); |
2872 | 3 | } |
2873 | 6 | isl_int_clear(t); |
2874 | 6 | } |
2875 | | |
2876 | | /* Reduce the "n" stride constraints in "bmap" based on a copy "A" |
2877 | | * of the same stride constraints in a compressed space that exploits |
2878 | | * all equalities in the context and the other equalities in "bmap". |
2879 | | * |
2880 | | * If the stride constraints of "bmap" are of the form |
2881 | | * |
2882 | | * C(x) + D(y) = 0 |
2883 | | * |
2884 | | * then A is of the form |
2885 | | * |
2886 | | * B(x') + D(y) = 0 |
2887 | | * |
2888 | | * If any of these constraints involves only a single local variable y, |
2889 | | * then the constraint appears as |
2890 | | * |
2891 | | * f(x) + m y_i = 0 |
2892 | | * |
2893 | | * in "bmap" and as |
2894 | | * |
2895 | | * h(x') + m y_i = 0 |
2896 | | * |
2897 | | * in "A". |
2898 | | * |
2899 | | * Let g be the gcd of m and the coefficients of h. |
2900 | | * Then, in particular, g is a divisor of the coefficients of h and |
2901 | | * |
2902 | | * f(x) = h(x') |
2903 | | * |
2904 | | * is known to be a multiple of g. |
2905 | | * If some prime factor in m appears with the same exponent in g, |
2906 | | * then it can be removed from m because f(x) is already known |
2907 | | * to be a multiple of g and therefore in particular of this power |
2908 | | * of the prime factors. |
2909 | | * Prime factors that appear with a smaller exponent in g cannot |
2910 | | * be removed from m. |
2911 | | * Let g' be the divisor of g containing all prime factors that |
2912 | | * appear with the same exponent in m and g, then |
2913 | | * |
2914 | | * f(x) + m y_i = 0 |
2915 | | * |
2916 | | * can be replaced by |
2917 | | * |
2918 | | * f(x) + m/g' y_i' = 0 |
2919 | | * |
2920 | | * Note that (if g' != 1) this changes the explicit representation |
2921 | | * of y_i to that of y_i', so the integer division at position i |
2922 | | * is marked unknown and later recomputed by a call to |
2923 | | * isl_basic_map_gauss. |
2924 | | */ |
2925 | | static __isl_give isl_basic_map *reduce_stride_constraints( |
2926 | | __isl_take isl_basic_map *bmap, int n, __isl_keep isl_mat *A) |
2927 | 7 | { |
2928 | 7 | int i; |
2929 | 7 | int total, n_div; |
2930 | 7 | int any = 0; |
2931 | 7 | isl_int gcd; |
2932 | 7 | |
2933 | 7 | if (!bmap || !A) |
2934 | 0 | return isl_basic_map_free(bmap); |
2935 | 7 | |
2936 | 7 | total = isl_basic_map_dim(bmap, isl_dim_all); |
2937 | 7 | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
2938 | 7 | total -= n_div; |
2939 | 7 | |
2940 | 7 | isl_int_init(gcd); |
2941 | 14 | for (i = 0; i < n; ++i7 ) { |
2942 | 7 | int div; |
2943 | 7 | |
2944 | 7 | div = isl_seq_first_non_zero(bmap->eq[i] + 1 + total, n_div); |
2945 | 7 | if (div < 0) |
2946 | 7 | isl_die0 (isl_basic_map_get_ctx(bmap), isl_error_internal, |
2947 | 7 | "equality constraints modified unexpectedly", |
2948 | 7 | goto error); |
2949 | 7 | if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total + div + 1, |
2950 | 7 | n_div - div - 1) != -1) |
2951 | 0 | continue; |
2952 | 7 | if (isl_mat_row_gcd(A, i, &gcd) < 0) |
2953 | 0 | goto error; |
2954 | 7 | if (isl_int_is_one(gcd)) |
2955 | 7 | continue1 ; |
2956 | 6 | remove_incomplete_powers(&gcd, bmap->eq[i][1 + total + div]); |
2957 | 6 | if (isl_int_is_one(gcd)) |
2958 | 6 | continue1 ; |
2959 | 5 | isl_int_divexact(bmap->eq[i][1 + total + div], |
2960 | 5 | bmap->eq[i][1 + total + div], gcd); |
2961 | 5 | bmap = isl_basic_map_mark_div_unknown(bmap, div); |
2962 | 5 | if (!bmap) |
2963 | 0 | goto error; |
2964 | 5 | any = 1; |
2965 | 5 | } |
2966 | 7 | isl_int_clear(gcd); |
2967 | 7 | |
2968 | 7 | if (any) |
2969 | 5 | bmap = isl_basic_map_gauss(bmap, NULL); |
2970 | 7 | |
2971 | 7 | return bmap; |
2972 | 0 | error: |
2973 | 0 | isl_int_clear(gcd); |
2974 | 0 | isl_basic_map_free(bmap); |
2975 | 0 | return NULL; |
2976 | 7 | } |
2977 | | |
2978 | | /* Simplify the stride constraints in "bmap" based on |
2979 | | * the remaining equality constraints in "bmap" and all equality |
2980 | | * constraints in "context". |
2981 | | * Only do this if both "bmap" and "context" have stride constraints. |
2982 | | * |
2983 | | * First extract a copy of the stride constraints in "bmap" in a compressed |
2984 | | * space exploiting all the other equality constraints and then |
2985 | | * use this compressed copy to simplify the original stride constraints. |
2986 | | */ |
2987 | | static __isl_give isl_basic_map *gist_strides(__isl_take isl_basic_map *bmap, |
2988 | | __isl_keep isl_basic_map *context) |
2989 | 608 | { |
2990 | 608 | int bmap_n_eq, context_n_eq; |
2991 | 608 | isl_mat *A; |
2992 | 608 | |
2993 | 608 | if (!bmap || !context) |
2994 | 0 | return isl_basic_map_free(bmap); |
2995 | 608 | |
2996 | 608 | bmap_n_eq = n_div_eq(bmap); |
2997 | 608 | context_n_eq = n_div_eq(context); |
2998 | 608 | |
2999 | 608 | if (bmap_n_eq < 0 || context_n_eq < 0) |
3000 | 0 | return isl_basic_map_free(bmap); |
3001 | 608 | if (bmap_n_eq == 0 || context_n_eq == 0389 ) |
3002 | 601 | return bmap; |
3003 | 7 | |
3004 | 7 | A = extract_compressed_stride_constraints(bmap, bmap_n_eq, |
3005 | 7 | context, context_n_eq); |
3006 | 7 | bmap = reduce_stride_constraints(bmap, bmap_n_eq, A); |
3007 | 7 | |
3008 | 7 | isl_mat_free(A); |
3009 | 7 | |
3010 | 7 | return bmap; |
3011 | 7 | } |
3012 | | |
3013 | | /* Return a basic map that has the same intersection with "context" as "bmap" |
3014 | | * and that is as "simple" as possible. |
3015 | | * |
3016 | | * The core computation is performed on the pure constraints. |
3017 | | * When we add back the meaning of the integer divisions, we need |
3018 | | * to (re)introduce the div constraints. If we happen to have |
3019 | | * discovered that some of these integer divisions are equal to |
3020 | | * some affine combination of other variables, then these div |
3021 | | * constraints may end up getting simplified in terms of the equalities, |
3022 | | * resulting in extra inequalities on the other variables that |
3023 | | * may have been removed already or that may not even have been |
3024 | | * part of the input. We try and remove those constraints of |
3025 | | * this form that are most obviously redundant with respect to |
3026 | | * the context. We also remove those div constraints that are |
3027 | | * redundant with respect to the other constraints in the result. |
3028 | | * |
3029 | | * The stride constraints among the equality constraints in "bmap" are |
3030 | | * also simplified with respecting to the other equality constraints |
3031 | | * in "bmap" and with respect to all equality constraints in "context". |
3032 | | */ |
3033 | | __isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap, |
3034 | | __isl_take isl_basic_map *context) |
3035 | 25.6k | { |
3036 | 25.6k | isl_basic_set *bset, *eq; |
3037 | 25.6k | isl_basic_map *eq_bmap; |
3038 | 25.6k | unsigned total, n_div, extra, n_eq, n_ineq; |
3039 | 25.6k | |
3040 | 25.6k | if (!bmap || !context) |
3041 | 0 | goto error; |
3042 | 25.6k | |
3043 | 25.6k | if (isl_basic_map_plain_is_universe(bmap)) { |
3044 | 2.96k | isl_basic_map_free(context); |
3045 | 2.96k | return bmap; |
3046 | 2.96k | } |
3047 | 22.7k | if (isl_basic_map_plain_is_empty(context)) { |
3048 | 0 | isl_space *space = isl_basic_map_get_space(bmap); |
3049 | 0 | isl_basic_map_free(bmap); |
3050 | 0 | isl_basic_map_free(context); |
3051 | 0 | return isl_basic_map_universe(space); |
3052 | 0 | } |
3053 | 22.7k | if (isl_basic_map_plain_is_empty(bmap)) { |
3054 | 0 | isl_basic_map_free(context); |
3055 | 0 | return bmap; |
3056 | 0 | } |
3057 | 22.7k | |
3058 | 22.7k | bmap = isl_basic_map_remove_redundancies(bmap); |
3059 | 22.7k | context = isl_basic_map_remove_redundancies(context); |
3060 | 22.7k | context = isl_basic_map_align_divs(context, bmap); |
3061 | 22.7k | if (!context) |
3062 | 1 | goto error; |
3063 | 22.7k | |
3064 | 22.7k | n_div = isl_basic_map_dim(context, isl_dim_div); |
3065 | 22.7k | total = isl_basic_map_dim(bmap, isl_dim_all); |
3066 | 22.7k | extra = n_div - isl_basic_map_dim(bmap, isl_dim_div); |
3067 | 22.7k | |
3068 | 22.7k | bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap)); |
3069 | 22.7k | bset = isl_basic_set_add_dims(bset, isl_dim_set, extra); |
3070 | 22.7k | bset = uset_gist(bset, |
3071 | 22.7k | isl_basic_map_underlying_set(isl_basic_map_copy(context))); |
3072 | 22.7k | bset = isl_basic_set_project_out(bset, isl_dim_set, total, extra); |
3073 | 22.7k | |
3074 | 22.7k | if (!bset || bset->n_eq == 0 || n_div == 013.7k || |
3075 | 22.7k | isl_basic_set_plain_is_empty(bset)728 ) { |
3076 | 22.0k | isl_basic_map_free(context); |
3077 | 22.0k | return isl_basic_map_overlying_set(bset, bmap); |
3078 | 22.0k | } |
3079 | 608 | |
3080 | 608 | n_eq = bset->n_eq; |
3081 | 608 | n_ineq = bset->n_ineq; |
3082 | 608 | eq = isl_basic_set_copy(bset); |
3083 | 608 | eq = isl_basic_set_cow(eq); |
3084 | 608 | if (isl_basic_set_free_inequality(eq, n_ineq) < 0) |
3085 | 0 | eq = isl_basic_set_free(eq); |
3086 | 608 | if (isl_basic_set_free_equality(bset, n_eq) < 0) |
3087 | 0 | bset = isl_basic_set_free(bset); |
3088 | 608 | |
3089 | 608 | eq_bmap = isl_basic_map_overlying_set(eq, isl_basic_map_copy(bmap)); |
3090 | 608 | eq_bmap = gist_strides(eq_bmap, context); |
3091 | 608 | eq_bmap = isl_basic_map_remove_shifted_constraints(eq_bmap, context); |
3092 | 608 | bmap = isl_basic_map_overlying_set(bset, bmap); |
3093 | 608 | bmap = isl_basic_map_intersect(bmap, eq_bmap); |
3094 | 608 | bmap = isl_basic_map_remove_redundancies(bmap); |
3095 | 608 | |
3096 | 608 | return bmap; |
3097 | 1 | error: |
3098 | 1 | isl_basic_map_free(bmap); |
3099 | 1 | isl_basic_map_free(context); |
3100 | 1 | return NULL; |
3101 | 608 | } |
3102 | | |
3103 | | /* |
3104 | | * Assumes context has no implicit divs. |
3105 | | */ |
3106 | | __isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map, |
3107 | | __isl_take isl_basic_map *context) |
3108 | 24.3k | { |
3109 | 24.3k | int i; |
3110 | 24.3k | |
3111 | 24.3k | if (!map || !context) |
3112 | 0 | goto error; |
3113 | 24.3k | |
3114 | 24.3k | if (isl_basic_map_plain_is_empty(context)) { |
3115 | 0 | isl_space *space = isl_map_get_space(map); |
3116 | 0 | isl_map_free(map); |
3117 | 0 | isl_basic_map_free(context); |
3118 | 0 | return isl_map_universe(space); |
3119 | 0 | } |
3120 | 24.3k | |
3121 | 24.3k | context = isl_basic_map_remove_redundancies(context); |
3122 | 24.3k | map = isl_map_cow(map); |
3123 | 24.3k | if (!map || !context) |
3124 | 0 | goto error; |
3125 | 24.3k | isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error); |
3126 | 24.3k | map = isl_map_compute_divs(map); |
3127 | 24.3k | if (!map) |
3128 | 0 | goto error; |
3129 | 49.1k | for (i = map->n - 1; 24.3k i >= 0; --i24.8k ) { |
3130 | 24.8k | map->p[i] = isl_basic_map_gist(map->p[i], |
3131 | 24.8k | isl_basic_map_copy(context)); |
3132 | 24.8k | if (!map->p[i]) |
3133 | 0 | goto error; |
3134 | 24.8k | if (isl_basic_map_plain_is_empty(map->p[i])) { |
3135 | 2.51k | isl_basic_map_free(map->p[i]); |
3136 | 2.51k | if (i != map->n - 1) |
3137 | 1.07k | map->p[i] = map->p[map->n - 1]; |
3138 | 2.51k | map->n--; |
3139 | 2.51k | } |
3140 | 24.8k | } |
3141 | 24.3k | isl_basic_map_free(context); |
3142 | 24.3k | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
3143 | 24.3k | return map; |
3144 | 0 | error: |
3145 | 0 | isl_map_free(map); |
3146 | 0 | isl_basic_map_free(context); |
3147 | 0 | return NULL; |
3148 | 24.3k | } |
3149 | | |
3150 | | /* Drop all inequalities from "bmap" that also appear in "context". |
3151 | | * "context" is assumed to have only known local variables and |
3152 | | * the initial local variables of "bmap" are assumed to be the same |
3153 | | * as those of "context". |
3154 | | * The constraints of both "bmap" and "context" are assumed |
3155 | | * to have been sorted using isl_basic_map_sort_constraints. |
3156 | | * |
3157 | | * Run through the inequality constraints of "bmap" and "context" |
3158 | | * in sorted order. |
3159 | | * If a constraint of "bmap" involves variables not in "context", |
3160 | | * then it cannot appear in "context". |
3161 | | * If a matching constraint is found, it is removed from "bmap". |
3162 | | */ |
3163 | | static __isl_give isl_basic_map *drop_inequalities( |
3164 | | __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context) |
3165 | 379 | { |
3166 | 379 | int i1, i2; |
3167 | 379 | unsigned total, extra; |
3168 | 379 | |
3169 | 379 | if (!bmap || !context) |
3170 | 0 | return isl_basic_map_free(bmap); |
3171 | 379 | |
3172 | 379 | total = isl_basic_map_total_dim(context); |
3173 | 379 | extra = isl_basic_map_total_dim(bmap) - total; |
3174 | 379 | |
3175 | 379 | i1 = bmap->n_ineq - 1; |
3176 | 379 | i2 = context->n_ineq - 1; |
3177 | 1.46k | while (bmap && i1 >= 0 && i2 >= 01.22k ) { |
3178 | 1.08k | int cmp; |
3179 | 1.08k | |
3180 | 1.08k | if (isl_seq_first_non_zero(bmap->ineq[i1] + 1 + total, |
3181 | 1.08k | extra) != -1) { |
3182 | 18 | --i1; |
3183 | 18 | continue; |
3184 | 18 | } |
3185 | 1.06k | cmp = isl_basic_map_constraint_cmp(context, bmap->ineq[i1], |
3186 | 1.06k | context->ineq[i2]); |
3187 | 1.06k | if (cmp < 0) { |
3188 | 0 | --i2; |
3189 | 0 | continue; |
3190 | 0 | } |
3191 | 1.06k | if (cmp > 0) { |
3192 | 303 | --i1; |
3193 | 303 | continue; |
3194 | 303 | } |
3195 | 763 | if (isl_int_eq(bmap->ineq[i1][0], context->ineq[i2][0])) { |
3196 | 692 | bmap = isl_basic_map_cow(bmap); |
3197 | 692 | if (isl_basic_map_drop_inequality(bmap, i1) < 0) |
3198 | 0 | bmap = isl_basic_map_free(bmap); |
3199 | 692 | } |
3200 | 763 | --i1; |
3201 | 763 | --i2; |
3202 | 763 | } |
3203 | 379 | |
3204 | 379 | return bmap; |
3205 | 379 | } |
3206 | | |
3207 | | /* Drop all equalities from "bmap" that also appear in "context". |
3208 | | * "context" is assumed to have only known local variables and |
3209 | | * the initial local variables of "bmap" are assumed to be the same |
3210 | | * as those of "context". |
3211 | | * |
3212 | | * Run through the equality constraints of "bmap" and "context" |
3213 | | * in sorted order. |
3214 | | * If a constraint of "bmap" involves variables not in "context", |
3215 | | * then it cannot appear in "context". |
3216 | | * If a matching constraint is found, it is removed from "bmap". |
3217 | | */ |
3218 | | static __isl_give isl_basic_map *drop_equalities( |
3219 | | __isl_take isl_basic_map *bmap, __isl_keep isl_basic_map *context) |
3220 | 379 | { |
3221 | 379 | int i1, i2; |
3222 | 379 | unsigned total, extra; |
3223 | 379 | |
3224 | 379 | if (!bmap || !context) |
3225 | 0 | return isl_basic_map_free(bmap); |
3226 | 379 | |
3227 | 379 | total = isl_basic_map_total_dim(context); |
3228 | 379 | extra = isl_basic_map_total_dim(bmap) - total; |
3229 | 379 | |
3230 | 379 | i1 = bmap->n_eq - 1; |
3231 | 379 | i2 = context->n_eq - 1; |
3232 | 379 | |
3233 | 411 | while (bmap && i1 >= 0 && i2 >= 071 ) { |
3234 | 32 | int last1, last2; |
3235 | 32 | |
3236 | 32 | if (isl_seq_first_non_zero(bmap->eq[i1] + 1 + total, |
3237 | 32 | extra) != -1) |
3238 | 0 | break; |
3239 | 32 | last1 = isl_seq_last_non_zero(bmap->eq[i1] + 1, total); |
3240 | 32 | last2 = isl_seq_last_non_zero(context->eq[i2] + 1, total); |
3241 | 32 | if (last1 > last2) { |
3242 | 0 | --i2; |
3243 | 0 | continue; |
3244 | 0 | } |
3245 | 32 | if (last1 < last2) { |
3246 | 3 | --i1; |
3247 | 3 | continue; |
3248 | 3 | } |
3249 | 29 | if (isl_seq_eq(bmap->eq[i1], context->eq[i2], 1 + total)) { |
3250 | 29 | bmap = isl_basic_map_cow(bmap); |
3251 | 29 | if (isl_basic_map_drop_equality(bmap, i1) < 0) |
3252 | 0 | bmap = isl_basic_map_free(bmap); |
3253 | 29 | } |
3254 | 29 | --i1; |
3255 | 29 | --i2; |
3256 | 29 | } |
3257 | 379 | |
3258 | 379 | return bmap; |
3259 | 379 | } |
3260 | | |
3261 | | /* Remove the constraints in "context" from "bmap". |
3262 | | * "context" is assumed to have explicit representations |
3263 | | * for all local variables. |
3264 | | * |
3265 | | * First align the divs of "bmap" to those of "context" and |
3266 | | * sort the constraints. Then drop all constraints from "bmap" |
3267 | | * that appear in "context". |
3268 | | */ |
3269 | | __isl_give isl_basic_map *isl_basic_map_plain_gist( |
3270 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context) |
3271 | 379 | { |
3272 | 379 | isl_bool done, known; |
3273 | 379 | |
3274 | 379 | done = isl_basic_map_plain_is_universe(context); |
3275 | 379 | if (done == isl_bool_false) |
3276 | 379 | done = isl_basic_map_plain_is_universe(bmap); |
3277 | 379 | if (done == isl_bool_false) |
3278 | 379 | done = isl_basic_map_plain_is_empty(context); |
3279 | 379 | if (done == isl_bool_false) |
3280 | 379 | done = isl_basic_map_plain_is_empty(bmap); |
3281 | 379 | if (done < 0) |
3282 | 0 | goto error; |
3283 | 379 | if (done) { |
3284 | 0 | isl_basic_map_free(context); |
3285 | 0 | return bmap; |
3286 | 0 | } |
3287 | 379 | known = isl_basic_map_divs_known(context); |
3288 | 379 | if (known < 0) |
3289 | 0 | goto error; |
3290 | 379 | if (!known) |
3291 | 379 | isl_die0 (isl_basic_map_get_ctx(bmap), isl_error_invalid, |
3292 | 379 | "context has unknown divs", goto error); |
3293 | 379 | |
3294 | 379 | bmap = isl_basic_map_align_divs(bmap, context); |
3295 | 379 | bmap = isl_basic_map_gauss(bmap, NULL); |
3296 | 379 | bmap = isl_basic_map_sort_constraints(bmap); |
3297 | 379 | context = isl_basic_map_sort_constraints(context); |
3298 | 379 | |
3299 | 379 | bmap = drop_inequalities(bmap, context); |
3300 | 379 | bmap = drop_equalities(bmap, context); |
3301 | 379 | |
3302 | 379 | isl_basic_map_free(context); |
3303 | 379 | bmap = isl_basic_map_finalize(bmap); |
3304 | 379 | return bmap; |
3305 | 0 | error: |
3306 | 0 | isl_basic_map_free(bmap); |
3307 | 0 | isl_basic_map_free(context); |
3308 | 0 | return NULL; |
3309 | 379 | } |
3310 | | |
3311 | | /* Replace "map" by the disjunct at position "pos" and free "context". |
3312 | | */ |
3313 | | static __isl_give isl_map *replace_by_disjunct(__isl_take isl_map *map, |
3314 | | int pos, __isl_take isl_basic_map *context) |
3315 | 4 | { |
3316 | 4 | isl_basic_map *bmap; |
3317 | 4 | |
3318 | 4 | bmap = isl_basic_map_copy(map->p[pos]); |
3319 | 4 | isl_map_free(map); |
3320 | 4 | isl_basic_map_free(context); |
3321 | 4 | return isl_map_from_basic_map(bmap); |
3322 | 4 | } |
3323 | | |
3324 | | /* Remove the constraints in "context" from "map". |
3325 | | * If any of the disjuncts in the result turns out to be the universe, |
3326 | | * then return this universe. |
3327 | | * "context" is assumed to have explicit representations |
3328 | | * for all local variables. |
3329 | | */ |
3330 | | __isl_give isl_map *isl_map_plain_gist_basic_map(__isl_take isl_map *map, |
3331 | | __isl_take isl_basic_map *context) |
3332 | 280 | { |
3333 | 280 | int i; |
3334 | 280 | isl_bool univ, known; |
3335 | 280 | |
3336 | 280 | univ = isl_basic_map_plain_is_universe(context); |
3337 | 280 | if (univ < 0) |
3338 | 0 | goto error; |
3339 | 280 | if (univ) { |
3340 | 89 | isl_basic_map_free(context); |
3341 | 89 | return map; |
3342 | 89 | } |
3343 | 191 | known = isl_basic_map_divs_known(context); |
3344 | 191 | if (known < 0) |
3345 | 0 | goto error; |
3346 | 191 | if (!known) |
3347 | 191 | isl_die0 (isl_map_get_ctx(map), isl_error_invalid, |
3348 | 191 | "context has unknown divs", goto error); |
3349 | 191 | |
3350 | 191 | map = isl_map_cow(map); |
3351 | 191 | if (!map) |
3352 | 0 | goto error; |
3353 | 566 | for (i = 0; 191 i < map->n; ++i375 ) { |
3354 | 379 | map->p[i] = isl_basic_map_plain_gist(map->p[i], |
3355 | 379 | isl_basic_map_copy(context)); |
3356 | 379 | univ = isl_basic_map_plain_is_universe(map->p[i]); |
3357 | 379 | if (univ < 0) |
3358 | 0 | goto error; |
3359 | 379 | if (univ && map->n > 14 ) |
3360 | 4 | return replace_by_disjunct(map, i, context); |
3361 | 379 | } |
3362 | 191 | |
3363 | 191 | isl_basic_map_free(context); |
3364 | 187 | ISL_F_CLR(map, ISL_MAP_NORMALIZED); |
3365 | 187 | if (map->n > 1) |
3366 | 187 | ISL_F_CLR(map, ISL_MAP_DISJOINT); |
3367 | 187 | return map; |
3368 | 0 | error: |
3369 | 0 | isl_map_free(map); |
3370 | 0 | isl_basic_map_free(context); |
3371 | 0 | return NULL; |
3372 | 191 | } |
3373 | | |
3374 | | /* Remove the constraints in "context" from "set". |
3375 | | * If any of the disjuncts in the result turns out to be the universe, |
3376 | | * then return this universe. |
3377 | | * "context" is assumed to have explicit representations |
3378 | | * for all local variables. |
3379 | | */ |
3380 | | __isl_give isl_set *isl_set_plain_gist_basic_set(__isl_take isl_set *set, |
3381 | | __isl_take isl_basic_set *context) |
3382 | 101 | { |
3383 | 101 | return set_from_map(isl_map_plain_gist_basic_map(set_to_map(set), |
3384 | 101 | bset_to_bmap(context))); |
3385 | 101 | } |
3386 | | |
3387 | | /* Remove the constraints in "context" from "map". |
3388 | | * If any of the disjuncts in the result turns out to be the universe, |
3389 | | * then return this universe. |
3390 | | * "context" is assumed to consist of a single disjunct and |
3391 | | * to have explicit representations for all local variables. |
3392 | | */ |
3393 | | __isl_give isl_map *isl_map_plain_gist(__isl_take isl_map *map, |
3394 | | __isl_take isl_map *context) |
3395 | 20 | { |
3396 | 20 | isl_basic_map *hull; |
3397 | 20 | |
3398 | 20 | hull = isl_map_unshifted_simple_hull(context); |
3399 | 20 | return isl_map_plain_gist_basic_map(map, hull); |
3400 | 20 | } |
3401 | | |
3402 | | /* Replace "map" by a universe map in the same space and free "drop". |
3403 | | */ |
3404 | | static __isl_give isl_map *replace_by_universe(__isl_take isl_map *map, |
3405 | | __isl_take isl_map *drop) |
3406 | 9.17k | { |
3407 | 9.17k | isl_map *res; |
3408 | 9.17k | |
3409 | 9.17k | res = isl_map_universe(isl_map_get_space(map)); |
3410 | 9.17k | isl_map_free(map); |
3411 | 9.17k | isl_map_free(drop); |
3412 | 9.17k | return res; |
3413 | 9.17k | } |
3414 | | |
3415 | | /* Return a map that has the same intersection with "context" as "map" |
3416 | | * and that is as "simple" as possible. |
3417 | | * |
3418 | | * If "map" is already the universe, then we cannot make it any simpler. |
3419 | | * Similarly, if "context" is the universe, then we cannot exploit it |
3420 | | * to simplify "map" |
3421 | | * If "map" and "context" are identical to each other, then we can |
3422 | | * return the corresponding universe. |
3423 | | * |
3424 | | * If either "map" or "context" consists of multiple disjuncts, |
3425 | | * then check if "context" happens to be a subset of "map", |
3426 | | * in which case all constraints can be removed. |
3427 | | * In case of multiple disjuncts, the standard procedure |
3428 | | * may not be able to detect that all constraints can be removed. |
3429 | | * |
3430 | | * If none of these cases apply, we have to work a bit harder. |
3431 | | * During this computation, we make use of a single disjunct context, |
3432 | | * so if the original context consists of more than one disjunct |
3433 | | * then we need to approximate the context by a single disjunct set. |
3434 | | * Simply taking the simple hull may drop constraints that are |
3435 | | * only implicitly available in each disjunct. We therefore also |
3436 | | * look for constraints among those defining "map" that are valid |
3437 | | * for the context. These can then be used to simplify away |
3438 | | * the corresponding constraints in "map". |
3439 | | */ |
3440 | | static __isl_give isl_map *map_gist(__isl_take isl_map *map, |
3441 | | __isl_take isl_map *context) |
3442 | 60.7k | { |
3443 | 60.7k | int equal; |
3444 | 60.7k | int is_universe; |
3445 | 60.7k | int single_disjunct_map, single_disjunct_context; |
3446 | 60.7k | isl_bool subset; |
3447 | 60.7k | isl_basic_map *hull; |
3448 | 60.7k | |
3449 | 60.7k | is_universe = isl_map_plain_is_universe(map); |
3450 | 60.7k | if (is_universe >= 0 && !is_universe) |
3451 | 37.8k | is_universe = isl_map_plain_is_universe(context); |
3452 | 60.7k | if (is_universe < 0) |
3453 | 0 | goto error; |
3454 | 60.7k | if (is_universe) { |
3455 | 31.6k | isl_map_free(context); |
3456 | 31.6k | return map; |
3457 | 31.6k | } |
3458 | 29.1k | |
3459 | 29.1k | equal = isl_map_plain_is_equal(map, context); |
3460 | 29.1k | if (equal < 0) |
3461 | 0 | goto error; |
3462 | 29.1k | if (equal) |
3463 | 9.08k | return replace_by_universe(map, context); |
3464 | 20.1k | |
3465 | 20.1k | single_disjunct_map = isl_map_n_basic_map(map) == 1; |
3466 | 20.1k | single_disjunct_context = isl_map_n_basic_map(context) == 1; |
3467 | 20.1k | if (!single_disjunct_map || !single_disjunct_context14.5k ) { |
3468 | 6.43k | subset = isl_map_is_subset(context, map); |
3469 | 6.43k | if (subset < 0) |
3470 | 0 | goto error; |
3471 | 6.43k | if (subset) |
3472 | 92 | return replace_by_universe(map, context); |
3473 | 20.0k | } |
3474 | 20.0k | |
3475 | 20.0k | context = isl_map_compute_divs(context); |
3476 | 20.0k | if (!context) |
3477 | 0 | goto error; |
3478 | 20.0k | if (single_disjunct_context) { |
3479 | 18.8k | hull = isl_map_simple_hull(context); |
3480 | 18.8k | } else { |
3481 | 1.16k | isl_ctx *ctx; |
3482 | 1.16k | isl_map_list *list; |
3483 | 1.16k | |
3484 | 1.16k | ctx = isl_map_get_ctx(map); |
3485 | 1.16k | list = isl_map_list_alloc(ctx, 2); |
3486 | 1.16k | list = isl_map_list_add(list, isl_map_copy(context)); |
3487 | 1.16k | list = isl_map_list_add(list, isl_map_copy(map)); |
3488 | 1.16k | hull = isl_map_unshifted_simple_hull_from_map_list(context, |
3489 | 1.16k | list); |
3490 | 1.16k | } |
3491 | 20.0k | return isl_map_gist_basic_map(map, hull); |
3492 | 0 | error: |
3493 | 0 | isl_map_free(map); |
3494 | 0 | isl_map_free(context); |
3495 | 0 | return NULL; |
3496 | 20.0k | } |
3497 | | |
3498 | | __isl_give isl_map *isl_map_gist(__isl_take isl_map *map, |
3499 | | __isl_take isl_map *context) |
3500 | 60.7k | { |
3501 | 60.7k | return isl_map_align_params_map_map_and(map, context, &map_gist); |
3502 | 60.7k | } |
3503 | | |
3504 | | struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset, |
3505 | | struct isl_basic_set *context) |
3506 | 858 | { |
3507 | 858 | return bset_from_bmap(isl_basic_map_gist(bset_to_bmap(bset), |
3508 | 858 | bset_to_bmap(context))); |
3509 | 858 | } |
3510 | | |
3511 | | __isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set, |
3512 | | __isl_take isl_basic_set *context) |
3513 | 4.30k | { |
3514 | 4.30k | return set_from_map(isl_map_gist_basic_map(set_to_map(set), |
3515 | 4.30k | bset_to_bmap(context))); |
3516 | 4.30k | } |
3517 | | |
3518 | | __isl_give isl_set *isl_set_gist_params_basic_set(__isl_take isl_set *set, |
3519 | | __isl_take isl_basic_set *context) |
3520 | 0 | { |
3521 | 0 | isl_space *space = isl_set_get_space(set); |
3522 | 0 | isl_basic_set *dom_context = isl_basic_set_universe(space); |
3523 | 0 | dom_context = isl_basic_set_intersect_params(dom_context, context); |
3524 | 0 | return isl_set_gist_basic_set(set, dom_context); |
3525 | 0 | } |
3526 | | |
3527 | | __isl_give isl_set *isl_set_gist(__isl_take isl_set *set, |
3528 | | __isl_take isl_set *context) |
3529 | 14.9k | { |
3530 | 14.9k | return set_from_map(isl_map_gist(set_to_map(set), set_to_map(context))); |
3531 | 14.9k | } |
3532 | | |
3533 | | /* Compute the gist of "bmap" with respect to the constraints "context" |
3534 | | * on the domain. |
3535 | | */ |
3536 | | __isl_give isl_basic_map *isl_basic_map_gist_domain( |
3537 | | __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *context) |
3538 | 0 | { |
3539 | 0 | isl_space *space = isl_basic_map_get_space(bmap); |
3540 | 0 | isl_basic_map *bmap_context = isl_basic_map_universe(space); |
3541 | 0 |
|
3542 | 0 | bmap_context = isl_basic_map_intersect_domain(bmap_context, context); |
3543 | 0 | return isl_basic_map_gist(bmap, bmap_context); |
3544 | 0 | } |
3545 | | |
3546 | | __isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map, |
3547 | | __isl_take isl_set *context) |
3548 | 8.21k | { |
3549 | 8.21k | isl_map *map_context = isl_map_universe(isl_map_get_space(map)); |
3550 | 8.21k | map_context = isl_map_intersect_domain(map_context, context); |
3551 | 8.21k | return isl_map_gist(map, map_context); |
3552 | 8.21k | } |
3553 | | |
3554 | | __isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map, |
3555 | | __isl_take isl_set *context) |
3556 | 100 | { |
3557 | 100 | isl_map *map_context = isl_map_universe(isl_map_get_space(map)); |
3558 | 100 | map_context = isl_map_intersect_range(map_context, context); |
3559 | 100 | return isl_map_gist(map, map_context); |
3560 | 100 | } |
3561 | | |
3562 | | __isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map, |
3563 | | __isl_take isl_set *context) |
3564 | 31.7k | { |
3565 | 31.7k | isl_map *map_context = isl_map_universe(isl_map_get_space(map)); |
3566 | 31.7k | map_context = isl_map_intersect_params(map_context, context); |
3567 | 31.7k | return isl_map_gist(map, map_context); |
3568 | 31.7k | } |
3569 | | |
3570 | | __isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set, |
3571 | | __isl_take isl_set *context) |
3572 | 24.6k | { |
3573 | 24.6k | return isl_map_gist_params(set, context); |
3574 | 24.6k | } |
3575 | | |
3576 | | /* Quick check to see if two basic maps are disjoint. |
3577 | | * In particular, we reduce the equalities and inequalities of |
3578 | | * one basic map in the context of the equalities of the other |
3579 | | * basic map and check if we get a contradiction. |
3580 | | */ |
3581 | | isl_bool isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1, |
3582 | | __isl_keep isl_basic_map *bmap2) |
3583 | 54.6k | { |
3584 | 54.6k | struct isl_vec *v = NULL; |
3585 | 54.6k | int *elim = NULL; |
3586 | 54.6k | unsigned total; |
3587 | 54.6k | int i; |
3588 | 54.6k | |
3589 | 54.6k | if (!bmap1 || !bmap2) |
3590 | 0 | return isl_bool_error; |
3591 | 54.6k | isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), |
3592 | 54.6k | return isl_bool_error); |
3593 | 54.6k | if (bmap1->n_div || bmap2->n_div50.3k ) |
3594 | 5.80k | return isl_bool_false; |
3595 | 48.8k | if (!bmap1->n_eq && !bmap2->n_eq6.76k ) |
3596 | 5.24k | return isl_bool_false; |
3597 | 43.5k | |
3598 | 43.5k | total = isl_space_dim(bmap1->dim, isl_dim_all); |
3599 | 43.5k | if (total == 0) |
3600 | 0 | return isl_bool_false; |
3601 | 43.5k | v = isl_vec_alloc(bmap1->ctx, 1 + total); |
3602 | 43.5k | if (!v) |
3603 | 0 | goto error; |
3604 | 43.5k | elim = isl_alloc_array(bmap1->ctx, int, total); |
3605 | 43.5k | if (!elim) |
3606 | 0 | goto error; |
3607 | 43.5k | compute_elimination_index(bmap1, elim); |
3608 | 91.3k | for (i = 0; i < bmap2->n_eq; ++i47.7k ) { |
3609 | 50.3k | int reduced; |
3610 | 50.3k | reduced = reduced_using_equalities(v->block.data, bmap2->eq[i], |
3611 | 50.3k | bmap1, elim); |
3612 | 50.3k | if (reduced && !12.3k isl_int_is_zero12.3k (v->block.data[0]) && |
3613 | 50.3k | isl_seq_first_non_zero(v->block.data + 1, total) == -13.44k ) |
3614 | 2.60k | goto disjoint; |
3615 | 50.3k | } |
3616 | 405k | for (i = 0; 40.9k i < bmap2->n_ineq; ++i364k ) { |
3617 | 392k | int reduced; |
3618 | 392k | reduced = reduced_using_equalities(v->block.data, |
3619 | 392k | bmap2->ineq[i], bmap1, elim); |
3620 | 392k | if (reduced && isl_int_is_neg111k (v->block.data[0]) && |
3621 | 392k | isl_seq_first_non_zero(v->block.data + 1, total) == -127.9k ) |
3622 | 27.3k | goto disjoint; |
3623 | 392k | } |
3624 | 40.9k | compute_elimination_index(bmap2, elim); |
3625 | 88.5k | for (i = 0; i < bmap1->n_ineq; ++i74.9k ) { |
3626 | 80.3k | int reduced; |
3627 | 80.3k | reduced = reduced_using_equalities(v->block.data, |
3628 | 80.3k | bmap1->ineq[i], bmap2, elim); |
3629 | 80.3k | if (reduced && isl_int_is_neg6.77k (v->block.data[0]) && |
3630 | 80.3k | isl_seq_first_non_zero(v->block.data + 1, total) == -15.66k ) |
3631 | 5.42k | goto disjoint; |
3632 | 80.3k | } |
3633 | 13.6k | isl_vec_free(v); |
3634 | 8.18k | free(elim); |
3635 | 8.18k | return isl_bool_false; |
3636 | 35.3k | disjoint: |
3637 | 35.3k | isl_vec_free(v); |
3638 | 35.3k | free(elim); |
3639 | 35.3k | return isl_bool_true; |
3640 | 0 | error: |
3641 | 0 | isl_vec_free(v); |
3642 | 0 | free(elim); |
3643 | 0 | return isl_bool_error; |
3644 | 13.6k | } |
3645 | | |
3646 | | int isl_basic_set_plain_is_disjoint(__isl_keep isl_basic_set *bset1, |
3647 | | __isl_keep isl_basic_set *bset2) |
3648 | 0 | { |
3649 | 0 | return isl_basic_map_plain_is_disjoint(bset_to_bmap(bset1), |
3650 | 0 | bset_to_bmap(bset2)); |
3651 | 0 | } |
3652 | | |
3653 | | /* Does "test" hold for all pairs of basic maps in "map1" and "map2"? |
3654 | | */ |
3655 | | static isl_bool all_pairs(__isl_keep isl_map *map1, __isl_keep isl_map *map2, |
3656 | | isl_bool (*test)(__isl_keep isl_basic_map *bmap1, |
3657 | | __isl_keep isl_basic_map *bmap2)) |
3658 | 19.8k | { |
3659 | 19.8k | int i, j; |
3660 | 19.8k | |
3661 | 19.8k | if (!map1 || !map2) |
3662 | 0 | return isl_bool_error; |
3663 | 19.8k | |
3664 | 62.1k | for (i = 0; 19.8k i < map1->n; ++i42.2k ) { |
3665 | 96.8k | for (j = 0; j < map2->n; ++j43.5k ) { |
3666 | 54.5k | isl_bool d = test(map1->p[i], map2->p[j]); |
3667 | 54.5k | if (d != isl_bool_true) |
3668 | 11.0k | return d; |
3669 | 54.5k | } |
3670 | 53.2k | } |
3671 | 19.8k | |
3672 | 19.8k | return isl_bool_true8.86k ; |
3673 | 19.8k | } |
3674 | | |
3675 | | /* Are "map1" and "map2" obviously disjoint, based on information |
3676 | | * that can be derived without looking at the individual basic maps? |
3677 | | * |
3678 | | * In particular, if one of them is empty or if they live in different spaces |
3679 | | * (ignoring parameters), then they are clearly disjoint. |
3680 | | */ |
3681 | | static isl_bool isl_map_plain_is_disjoint_global(__isl_keep isl_map *map1, |
3682 | | __isl_keep isl_map *map2) |
3683 | 44.6k | { |
3684 | 44.6k | isl_bool disjoint; |
3685 | 44.6k | isl_bool match; |
3686 | 44.6k | |
3687 | 44.6k | if (!map1 || !map2) |
3688 | 0 | return isl_bool_error; |
3689 | 44.6k | |
3690 | 44.6k | disjoint = isl_map_plain_is_empty(map1); |
3691 | 44.6k | if (disjoint < 0 || disjoint) |
3692 | 5.72k | return disjoint; |
3693 | 38.9k | |
3694 | 38.9k | disjoint = isl_map_plain_is_empty(map2); |
3695 | 38.9k | if (disjoint < 0 || disjoint) |
3696 | 9.71k | return disjoint; |
3697 | 29.2k | |
3698 | 29.2k | match = isl_space_tuple_is_equal(map1->dim, isl_dim_in, |
3699 | 29.2k | map2->dim, isl_dim_in); |
3700 | 29.2k | if (match < 0 || !match) |
3701 | 0 | return match < 0 ? isl_bool_error : isl_bool_true; |
3702 | 29.2k | |
3703 | 29.2k | match = isl_space_tuple_is_equal(map1->dim, isl_dim_out, |
3704 | 29.2k | map2->dim, isl_dim_out); |
3705 | 29.2k | if (match < 0 || !match) |
3706 | 0 | return match < 0 ? isl_bool_error : isl_bool_true; |
3707 | 29.2k | |
3708 | 29.2k | return isl_bool_false; |
3709 | 29.2k | } |
3710 | | |
3711 | | /* Are "map1" and "map2" obviously disjoint? |
3712 | | * |
3713 | | * If one of them is empty or if they live in different spaces (ignoring |
3714 | | * parameters), then they are clearly disjoint. |
3715 | | * This is checked by isl_map_plain_is_disjoint_global. |
3716 | | * |
3717 | | * If they have different parameters, then we skip any further tests. |
3718 | | * |
3719 | | * If they are obviously equal, but not obviously empty, then we will |
3720 | | * not be able to detect if they are disjoint. |
3721 | | * |
3722 | | * Otherwise we check if each basic map in "map1" is obviously disjoint |
3723 | | * from each basic map in "map2". |
3724 | | */ |
3725 | | isl_bool isl_map_plain_is_disjoint(__isl_keep isl_map *map1, |
3726 | | __isl_keep isl_map *map2) |
3727 | 0 | { |
3728 | 0 | isl_bool disjoint; |
3729 | 0 | isl_bool intersect; |
3730 | 0 | isl_bool match; |
3731 | 0 |
|
3732 | 0 | disjoint = isl_map_plain_is_disjoint_global(map1, map2); |
3733 | 0 | if (disjoint < 0 || disjoint) |
3734 | 0 | return disjoint; |
3735 | 0 | |
3736 | 0 | match = isl_map_has_equal_params(map1, map2); |
3737 | 0 | if (match < 0 || !match) |
3738 | 0 | return match < 0 ? isl_bool_error : isl_bool_false; |
3739 | 0 | |
3740 | 0 | intersect = isl_map_plain_is_equal(map1, map2); |
3741 | 0 | if (intersect < 0 || intersect) |
3742 | 0 | return intersect < 0 ? isl_bool_error : isl_bool_false; |
3743 | 0 | |
3744 | 0 | return all_pairs(map1, map2, &isl_basic_map_plain_is_disjoint); |
3745 | 0 | } |
3746 | | |
3747 | | /* Are "map1" and "map2" disjoint? |
3748 | | * The parameters are assumed to have been aligned. |
3749 | | * |
3750 | | * In particular, check whether all pairs of basic maps are disjoint. |
3751 | | */ |
3752 | | static isl_bool isl_map_is_disjoint_aligned(__isl_keep isl_map *map1, |
3753 | | __isl_keep isl_map *map2) |
3754 | 19.8k | { |
3755 | 19.8k | return all_pairs(map1, map2, &isl_basic_map_is_disjoint); |
3756 | 19.8k | } |
3757 | | |
3758 | | /* Are "map1" and "map2" disjoint? |
3759 | | * |
3760 | | * They are disjoint if they are "obviously disjoint" or if one of them |
3761 | | * is empty. Otherwise, they are not disjoint if one of them is universal. |
3762 | | * If the two inputs are (obviously) equal and not empty, then they are |
3763 | | * not disjoint. |
3764 | | * If none of these cases apply, then check if all pairs of basic maps |
3765 | | * are disjoint after aligning the parameters. |
3766 | | */ |
3767 | | isl_bool isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2) |
3768 | 44.6k | { |
3769 | 44.6k | isl_bool disjoint; |
3770 | 44.6k | isl_bool intersect; |
3771 | 44.6k | |
3772 | 44.6k | disjoint = isl_map_plain_is_disjoint_global(map1, map2); |
3773 | 44.6k | if (disjoint < 0 || disjoint) |
3774 | 15.4k | return disjoint; |
3775 | 29.2k | |
3776 | 29.2k | disjoint = isl_map_is_empty(map1); |
3777 | 29.2k | if (disjoint < 0 || disjoint) |
3778 | 0 | return disjoint; |
3779 | 29.2k | |
3780 | 29.2k | disjoint = isl_map_is_empty(map2); |
3781 | 29.2k | if (disjoint < 0 || disjoint) |
3782 | 0 | return disjoint; |
3783 | 29.2k | |
3784 | 29.2k | intersect = isl_map_plain_is_universe(map1); |
3785 | 29.2k | if (intersect < 0 || intersect) |
3786 | 6.66k | return intersect < 0 ? isl_bool_error0 : isl_bool_false; |
3787 | 22.5k | |
3788 | 22.5k | intersect = isl_map_plain_is_universe(map2); |
3789 | 22.5k | if (intersect < 0 || intersect) |
3790 | 2.16k | return intersect < 0 ? isl_bool_error0 : isl_bool_false; |
3791 | 20.4k | |
3792 | 20.4k | intersect = isl_map_plain_is_equal(map1, map2); |
3793 | 20.4k | if (intersect < 0 || intersect) |
3794 | 531 | return isl_bool_not(intersect); |
3795 | 19.8k | |
3796 | 19.8k | return isl_map_align_params_map_map_and_test(map1, map2, |
3797 | 19.8k | &isl_map_is_disjoint_aligned); |
3798 | 19.8k | } |
3799 | | |
3800 | | /* Are "bmap1" and "bmap2" disjoint? |
3801 | | * |
3802 | | * They are disjoint if they are "obviously disjoint" or if one of them |
3803 | | * is empty. Otherwise, they are not disjoint if one of them is universal. |
3804 | | * If none of these cases apply, we compute the intersection and see if |
3805 | | * the result is empty. |
3806 | | */ |
3807 | | isl_bool isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1, |
3808 | | __isl_keep isl_basic_map *bmap2) |
3809 | 54.6k | { |
3810 | 54.6k | isl_bool disjoint; |
3811 | 54.6k | isl_bool intersect; |
3812 | 54.6k | isl_basic_map *test; |
3813 | 54.6k | |
3814 | 54.6k | disjoint = isl_basic_map_plain_is_disjoint(bmap1, bmap2); |
3815 | 54.6k | if (disjoint < 0 || disjoint) |
3816 | 35.3k | return disjoint; |
3817 | 19.2k | |
3818 | 19.2k | disjoint = isl_basic_map_is_empty(bmap1); |
3819 | 19.2k | if (disjoint < 0 || disjoint) |
3820 | 0 | return disjoint; |
3821 | 19.2k | |
3822 | 19.2k | disjoint = isl_basic_map_is_empty(bmap2); |
3823 | 19.2k | if (disjoint < 0 || disjoint) |
3824 | 0 | return disjoint; |
3825 | 19.2k | |
3826 | 19.2k | intersect = isl_basic_map_plain_is_universe(bmap1); |
3827 | 19.2k | if (intersect < 0 || intersect) |
3828 | 0 | return intersect < 0 ? isl_bool_error : isl_bool_false; |
3829 | 19.2k | |
3830 | 19.2k | intersect = isl_basic_map_plain_is_universe(bmap2); |
3831 | 19.2k | if (intersect < 0 || intersect) |
3832 | 0 | return intersect < 0 ? isl_bool_error : isl_bool_false; |
3833 | 19.2k | |
3834 | 19.2k | test = isl_basic_map_intersect(isl_basic_map_copy(bmap1), |
3835 | 19.2k | isl_basic_map_copy(bmap2)); |
3836 | 19.2k | disjoint = isl_basic_map_is_empty(test); |
3837 | 19.2k | isl_basic_map_free(test); |
3838 | 19.2k | |
3839 | 19.2k | return disjoint; |
3840 | 19.2k | } |
3841 | | |
3842 | | /* Are "bset1" and "bset2" disjoint? |
3843 | | */ |
3844 | | isl_bool isl_basic_set_is_disjoint(__isl_keep isl_basic_set *bset1, |
3845 | | __isl_keep isl_basic_set *bset2) |
3846 | 21 | { |
3847 | 21 | return isl_basic_map_is_disjoint(bset1, bset2); |
3848 | 21 | } |
3849 | | |
3850 | | isl_bool isl_set_plain_is_disjoint(__isl_keep isl_set *set1, |
3851 | | __isl_keep isl_set *set2) |
3852 | 0 | { |
3853 | 0 | return isl_map_plain_is_disjoint(set_to_map(set1), set_to_map(set2)); |
3854 | 0 | } |
3855 | | |
3856 | | /* Are "set1" and "set2" disjoint? |
3857 | | */ |
3858 | | isl_bool isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2) |
3859 | 16.3k | { |
3860 | 16.3k | return isl_map_is_disjoint(set1, set2); |
3861 | 16.3k | } |
3862 | | |
3863 | | /* Is "v" equal to 0, 1 or -1? |
3864 | | */ |
3865 | | static int is_zero_or_one(isl_int v) |
3866 | 310 | { |
3867 | 310 | return isl_int_is_zero(v) || isl_int_is_one73 (v) || isl_int_is_negone48 (v); |
3868 | 310 | } |
3869 | | |
3870 | | /* Check if we can combine a given div with lower bound l and upper |
3871 | | * bound u with some other div and if so return that other div. |
3872 | | * Otherwise return -1. |
3873 | | * |
3874 | | * We first check that |
3875 | | * - the bounds are opposites of each other (except for the constant |
3876 | | * term) |
3877 | | * - the bounds do not reference any other div |
3878 | | * - no div is defined in terms of this div |
3879 | | * |
3880 | | * Let m be the size of the range allowed on the div by the bounds. |
3881 | | * That is, the bounds are of the form |
3882 | | * |
3883 | | * e <= a <= e + m - 1 |
3884 | | * |
3885 | | * with e some expression in the other variables. |
3886 | | * We look for another div b such that no third div is defined in terms |
3887 | | * of this second div b and such that in any constraint that contains |
3888 | | * a (except for the given lower and upper bound), also contains b |
3889 | | * with a coefficient that is m times that of b. |
3890 | | * That is, all constraints (except for the lower and upper bound) |
3891 | | * are of the form |
3892 | | * |
3893 | | * e + f (a + m b) >= 0 |
3894 | | * |
3895 | | * Furthermore, in the constraints that only contain b, the coefficient |
3896 | | * of b should be equal to 1 or -1. |
3897 | | * If so, we return b so that "a + m b" can be replaced by |
3898 | | * a single div "c = a + m b". |
3899 | | */ |
3900 | | static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs, |
3901 | | unsigned div, unsigned l, unsigned u) |
3902 | 1.13k | { |
3903 | 1.13k | int i, j; |
3904 | 1.13k | unsigned dim; |
3905 | 1.13k | int coalesce = -1; |
3906 | 1.13k | |
3907 | 1.13k | if (bmap->n_div <= 1) |
3908 | 334 | return -1; |
3909 | 805 | dim = isl_space_dim(bmap->dim, isl_dim_all); |
3910 | 805 | if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1) |
3911 | 567 | return -1; |
3912 | 238 | if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1, |
3913 | 238 | bmap->n_div - div - 1) != -1) |
3914 | 28 | return -1; |
3915 | 210 | if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1, |
3916 | 210 | dim + bmap->n_div)) |
3917 | 92 | return -1; |
3918 | 118 | |
3919 | 430 | for (i = 0; 118 i < bmap->n_div; ++i312 ) { |
3920 | 312 | if (isl_int_is_zero(bmap->div[i][0])) |
3921 | 312 | continue231 ; |
3922 | 81 | if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div])) |
3923 | 81 | return -10 ; |
3924 | 81 | } |
3925 | 118 | |
3926 | 118 | isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]); |
3927 | 118 | if (isl_int_is_neg(bmap->ineq[l][0])) { |
3928 | 0 | isl_int_sub(bmap->ineq[l][0], |
3929 | 0 | bmap->ineq[l][0], bmap->ineq[u][0]); |
3930 | 0 | bmap = isl_basic_map_copy(bmap); |
3931 | 0 | bmap = isl_basic_map_set_to_empty(bmap); |
3932 | 0 | isl_basic_map_free(bmap); |
3933 | 0 | return -1; |
3934 | 0 | } |
3935 | 118 | isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1); |
3936 | 420 | for (i = 0; i < bmap->n_div; ++i302 ) { |
3937 | 307 | if (i == div) |
3938 | 113 | continue; |
3939 | 194 | if (!pairs[i]) |
3940 | 103 | continue; |
3941 | 415 | for (j = 0; 91 j < bmap->n_div; ++j324 ) { |
3942 | 324 | if (isl_int_is_zero(bmap->div[j][0])) |
3943 | 324 | continue231 ; |
3944 | 93 | if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i])) |
3945 | 93 | break0 ; |
3946 | 93 | } |
3947 | 91 | if (j < bmap->n_div) |
3948 | 0 | continue; |
3949 | 490 | for (j = 0; 91 j < bmap->n_ineq; ++j399 ) { |
3950 | 485 | int valid; |
3951 | 485 | if (j == l || j == u434 ) |
3952 | 97 | continue; |
3953 | 388 | if (isl_int_is_zero(bmap->ineq[j][1 + dim + div])) { |
3954 | 310 | if (is_zero_or_one(bmap->ineq[j][1 + dim + i])) |
3955 | 286 | continue; |
3956 | 24 | break; |
3957 | 24 | } |
3958 | 78 | if (isl_int_is_zero(bmap->ineq[j][1 + dim + i])) |
3959 | 78 | break43 ; |
3960 | 35 | isl_int_mul(bmap->ineq[j][1 + dim + div], |
3961 | 35 | bmap->ineq[j][1 + dim + div], |
3962 | 35 | bmap->ineq[l][0]); |
3963 | 35 | valid = isl_int_eq(bmap->ineq[j][1 + dim + div], |
3964 | 35 | bmap->ineq[j][1 + dim + i]); |
3965 | 35 | isl_int_divexact(bmap->ineq[j][1 + dim + div], |
3966 | 35 | bmap->ineq[j][1 + dim + div], |
3967 | 35 | bmap->ineq[l][0]); |
3968 | 35 | if (!valid) |
3969 | 19 | break; |
3970 | 35 | } |
3971 | 91 | if (j < bmap->n_ineq) |
3972 | 86 | continue; |
3973 | 5 | coalesce = i; |
3974 | 5 | break; |
3975 | 5 | } |
3976 | 118 | isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1); |
3977 | 118 | isl_int_sub(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]); |
3978 | 118 | return coalesce; |
3979 | 118 | } |
3980 | | |
3981 | | /* Internal data structure used during the construction and/or evaluation of |
3982 | | * an inequality that ensures that a pair of bounds always allows |
3983 | | * for an integer value. |
3984 | | * |
3985 | | * "tab" is the tableau in which the inequality is evaluated. It may |
3986 | | * be NULL until it is actually needed. |
3987 | | * "v" contains the inequality coefficients. |
3988 | | * "g", "fl" and "fu" are temporary scalars used during the construction and |
3989 | | * evaluation. |
3990 | | */ |
3991 | | struct test_ineq_data { |
3992 | | struct isl_tab *tab; |
3993 | | isl_vec *v; |
3994 | | isl_int g; |
3995 | | isl_int fl; |
3996 | | isl_int fu; |
3997 | | }; |
3998 | | |
3999 | | /* Free all the memory allocated by the fields of "data". |
4000 | | */ |
4001 | | static void test_ineq_data_clear(struct test_ineq_data *data) |
4002 | 1.98k | { |
4003 | 1.98k | isl_tab_free(data->tab); |
4004 | 1.98k | isl_vec_free(data->v); |
4005 | 1.98k | isl_int_clear(data->g); |
4006 | 1.98k | isl_int_clear(data->fl); |
4007 | 1.98k | isl_int_clear(data->fu); |
4008 | 1.98k | } |
4009 | | |
4010 | | /* Is the inequality stored in data->v satisfied by "bmap"? |
4011 | | * That is, does it only attain non-negative values? |
4012 | | * data->tab is a tableau corresponding to "bmap". |
4013 | | */ |
4014 | | static isl_bool test_ineq_is_satisfied(__isl_keep isl_basic_map *bmap, |
4015 | | struct test_ineq_data *data) |
4016 | 2.00k | { |
4017 | 2.00k | isl_ctx *ctx; |
4018 | 2.00k | enum isl_lp_result res; |
4019 | 2.00k | |
4020 | 2.00k | ctx = isl_basic_map_get_ctx(bmap); |
4021 | 2.00k | if (!data->tab) |
4022 | 1.50k | data->tab = isl_tab_from_basic_map(bmap, 0); |
4023 | 2.00k | res = isl_tab_min(data->tab, data->v->el, ctx->one, &data->g, NULL, 0); |
4024 | 2.00k | if (res == isl_lp_error) |
4025 | 0 | return isl_bool_error; |
4026 | 2.00k | return res == isl_lp_ok && isl_int_is_nonneg2.00k (data->g); |
4027 | 2.00k | } |
4028 | | |
4029 | | /* Given a lower and an upper bound on div i, do they always allow |
4030 | | * for an integer value of the given div? |
4031 | | * Determine this property by constructing an inequality |
4032 | | * such that the property is guaranteed when the inequality is nonnegative. |
4033 | | * The lower bound is inequality l, while the upper bound is inequality u. |
4034 | | * The constructed inequality is stored in data->v. |
4035 | | * |
4036 | | * Let the upper bound be |
4037 | | * |
4038 | | * -n_u a + e_u >= 0 |
4039 | | * |
4040 | | * and the lower bound |
4041 | | * |
4042 | | * n_l a + e_l >= 0 |
4043 | | * |
4044 | | * Let n_u = f_u g and n_l = f_l g, with g = gcd(n_u, n_l). |
4045 | | * We have |
4046 | | * |
4047 | | * - f_u e_l <= f_u f_l g a <= f_l e_u |
4048 | | * |
4049 | | * Since all variables are integer valued, this is equivalent to |
4050 | | * |
4051 | | * - f_u e_l - (f_u - 1) <= f_u f_l g a <= f_l e_u + (f_l - 1) |
4052 | | * |
4053 | | * If this interval is at least f_u f_l g, then it contains at least |
4054 | | * one integer value for a. |
4055 | | * That is, the test constraint is |
4056 | | * |
4057 | | * f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 >= f_u f_l g |
4058 | | * |
4059 | | * or |
4060 | | * |
4061 | | * f_l e_u + f_u e_l + f_l - 1 + f_u - 1 + 1 - f_u f_l g >= 0 |
4062 | | * |
4063 | | * If the coefficients of f_l e_u + f_u e_l have a common divisor g', |
4064 | | * then the constraint can be scaled down by a factor g', |
4065 | | * with the constant term replaced by |
4066 | | * floor((f_l e_{u,0} + f_u e_{l,0} + f_l - 1 + f_u - 1 + 1 - f_u f_l g)/g'). |
4067 | | * Note that the result of applying Fourier-Motzkin to this pair |
4068 | | * of constraints is |
4069 | | * |
4070 | | * f_l e_u + f_u e_l >= 0 |
4071 | | * |
4072 | | * If the constant term of the scaled down version of this constraint, |
4073 | | * i.e., floor((f_l e_{u,0} + f_u e_{l,0})/g') is equal to the constant |
4074 | | * term of the scaled down test constraint, then the test constraint |
4075 | | * is known to hold and no explicit evaluation is required. |
4076 | | * This is essentially the Omega test. |
4077 | | * |
4078 | | * If the test constraint consists of only a constant term, then |
4079 | | * it is sufficient to look at the sign of this constant term. |
4080 | | */ |
4081 | | static isl_bool int_between_bounds(__isl_keep isl_basic_map *bmap, int i, |
4082 | | int l, int u, struct test_ineq_data *data) |
4083 | 4.02k | { |
4084 | 4.02k | unsigned offset, n_div; |
4085 | 4.02k | offset = isl_basic_map_offset(bmap, isl_dim_div); |
4086 | 4.02k | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4087 | 4.02k | |
4088 | 4.02k | isl_int_gcd(data->g, |
4089 | 4.02k | bmap->ineq[l][offset + i], bmap->ineq[u][offset + i]); |
4090 | 4.02k | isl_int_divexact(data->fl, bmap->ineq[l][offset + i], data->g); |
4091 | 4.02k | isl_int_divexact(data->fu, bmap->ineq[u][offset + i], data->g); |
4092 | 4.02k | isl_int_neg(data->fu, data->fu); |
4093 | 4.02k | isl_seq_combine(data->v->el, data->fl, bmap->ineq[u], |
4094 | 4.02k | data->fu, bmap->ineq[l], offset + n_div); |
4095 | 4.02k | isl_int_mul(data->g, data->g, data->fl); |
4096 | 4.02k | isl_int_mul(data->g, data->g, data->fu); |
4097 | 4.02k | isl_int_sub(data->g, data->g, data->fl); |
4098 | 4.02k | isl_int_sub(data->g, data->g, data->fu); |
4099 | 4.02k | isl_int_add_ui(data->g, data->g, 1); |
4100 | 4.02k | isl_int_sub(data->fl, data->v->el[0], data->g); |
4101 | 4.02k | |
4102 | 4.02k | isl_seq_gcd(data->v->el + 1, offset - 1 + n_div, &data->g); |
4103 | 4.02k | if (isl_int_is_zero(data->g)) |
4104 | 4.02k | return 1.19k isl_int_is_nonneg1.19k (data->fl); |
4105 | 2.83k | if (isl_int_is_one(data->g)) { |
4106 | 1.64k | isl_int_set(data->v->el[0], data->fl); |
4107 | 1.64k | return test_ineq_is_satisfied(bmap, data); |
4108 | 1.64k | } |
4109 | 1.18k | isl_int_fdiv_q(data->fl, data->fl, data->g); |
4110 | 1.18k | isl_int_fdiv_q(data->v->el[0], data->v->el[0], data->g); |
4111 | 1.18k | if (isl_int_eq(data->fl, data->v->el[0])) |
4112 | 1.18k | return isl_bool_true823 ; |
4113 | 360 | isl_int_set(data->v->el[0], data->fl); |
4114 | 360 | isl_seq_scale_down(data->v->el + 1, data->v->el + 1, data->g, |
4115 | 360 | offset - 1 + n_div); |
4116 | 360 | |
4117 | 360 | return test_ineq_is_satisfied(bmap, data); |
4118 | 360 | } |
4119 | | |
4120 | | /* Remove more kinds of divs that are not strictly needed. |
4121 | | * In particular, if all pairs of lower and upper bounds on a div |
4122 | | * are such that they allow at least one integer value of the div, |
4123 | | * then we can eliminate the div using Fourier-Motzkin without |
4124 | | * introducing any spurious solutions. |
4125 | | * |
4126 | | * If at least one of the two constraints has a unit coefficient for the div, |
4127 | | * then the presence of such a value is guaranteed so there is no need to check. |
4128 | | * In particular, the value attained by the bound with unit coefficient |
4129 | | * can serve as this intermediate value. |
4130 | | */ |
4131 | | static __isl_give isl_basic_map *drop_more_redundant_divs( |
4132 | | __isl_take isl_basic_map *bmap, __isl_take int *pairs, int n) |
4133 | 1.98k | { |
4134 | 1.98k | isl_ctx *ctx; |
4135 | 1.98k | struct test_ineq_data data = { NULL, NULL }; |
4136 | 1.98k | unsigned off, n_div; |
4137 | 1.98k | int remove = -1; |
4138 | 1.98k | |
4139 | 1.98k | isl_int_init(data.g); |
4140 | 1.98k | isl_int_init(data.fl); |
4141 | 1.98k | isl_int_init(data.fu); |
4142 | 1.98k | |
4143 | 1.98k | if (!bmap) |
4144 | 0 | goto error; |
4145 | 1.98k | |
4146 | 1.98k | ctx = isl_basic_map_get_ctx(bmap); |
4147 | 1.98k | off = isl_basic_map_offset(bmap, isl_dim_div); |
4148 | 1.98k | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4149 | 1.98k | data.v = isl_vec_alloc(ctx, off + n_div); |
4150 | 1.98k | if (!data.v) |
4151 | 0 | goto error; |
4152 | 1.98k | |
4153 | 3.77k | while (1.98k n > 0) { |
4154 | 2.51k | int i, l, u; |
4155 | 2.51k | int best = -1; |
4156 | 2.51k | isl_bool has_int; |
4157 | 2.51k | |
4158 | 9.03k | for (i = 0; i < n_div; ++i6.52k ) { |
4159 | 6.52k | if (!pairs[i]) |
4160 | 3.23k | continue; |
4161 | 3.29k | if (best >= 0 && pairs[best] <= pairs[i]782 ) |
4162 | 597 | continue; |
4163 | 2.69k | best = i; |
4164 | 2.69k | } |
4165 | 2.51k | |
4166 | 2.51k | i = best; |
4167 | 19.7k | for (l = 0; l < bmap->n_ineq; ++l17.2k ) { |
4168 | 19.0k | if (!isl_int_is_pos(bmap->ineq[l][off + i])) |
4169 | 19.0k | continue15.3k ; |
4170 | 3.70k | if (isl_int_is_one(bmap->ineq[l][off + i])) |
4171 | 3.70k | continue834 ; |
4172 | 27.6k | for (u = 0; 2.87k u < bmap->n_ineq; ++u24.7k ) { |
4173 | 26.5k | if (!isl_int_is_neg(bmap->ineq[u][off + i])) |
4174 | 26.5k | continue21.6k ; |
4175 | 4.91k | if (isl_int_is_negone(bmap->ineq[u][off + i])) |
4176 | 4.91k | continue887 ; |
4177 | 4.02k | has_int = int_between_bounds(bmap, i, l, u, |
4178 | 4.02k | &data); |
4179 | 4.02k | if (has_int < 0) |
4180 | 0 | goto error; |
4181 | 4.02k | if (data.tab && data.tab->empty3.10k ) |
4182 | 7 | break; |
4183 | 4.01k | if (!has_int) |
4184 | 1.79k | break; |
4185 | 4.01k | } |
4186 | 2.87k | if (u < bmap->n_ineq) |
4187 | 1.80k | break; |
4188 | 2.87k | } |
4189 | 2.51k | if (data.tab && data.tab->empty1.99k ) { |
4190 | 7 | bmap = isl_basic_map_set_to_empty(bmap); |
4191 | 7 | break; |
4192 | 7 | } |
4193 | 2.50k | if (l == bmap->n_ineq) { |
4194 | 710 | remove = i; |
4195 | 710 | break; |
4196 | 710 | } |
4197 | 1.79k | pairs[i] = 0; |
4198 | 1.79k | --n; |
4199 | 1.79k | } |
4200 | 1.98k | |
4201 | 1.98k | test_ineq_data_clear(&data); |
4202 | 1.98k | |
4203 | 1.98k | free(pairs); |
4204 | 1.98k | |
4205 | 1.98k | if (remove < 0) |
4206 | 1.27k | return bmap; |
4207 | 710 | |
4208 | 710 | bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1); |
4209 | 710 | return isl_basic_map_drop_redundant_divs(bmap); |
4210 | 0 | error: |
4211 | 0 | free(pairs); |
4212 | 0 | isl_basic_map_free(bmap); |
4213 | 0 | test_ineq_data_clear(&data); |
4214 | 0 | return NULL; |
4215 | 710 | } |
4216 | | |
4217 | | /* Given a pair of divs div1 and div2 such that, except for the lower bound l |
4218 | | * and the upper bound u, div1 always occurs together with div2 in the form |
4219 | | * (div1 + m div2), where m is the constant range on the variable div1 |
4220 | | * allowed by l and u, replace the pair div1 and div2 by a single |
4221 | | * div that is equal to div1 + m div2. |
4222 | | * |
4223 | | * The new div will appear in the location that contains div2. |
4224 | | * We need to modify all constraints that contain |
4225 | | * div2 = (div - div1) / m |
4226 | | * The coefficient of div2 is known to be equal to 1 or -1. |
4227 | | * (If a constraint does not contain div2, it will also not contain div1.) |
4228 | | * If the constraint also contains div1, then we know they appear |
4229 | | * as f (div1 + m div2) and we can simply replace (div1 + m div2) by div, |
4230 | | * i.e., the coefficient of div is f. |
4231 | | * |
4232 | | * Otherwise, we first need to introduce div1 into the constraint. |
4233 | | * Let l be |
4234 | | * |
4235 | | * div1 + f >=0 |
4236 | | * |
4237 | | * and u |
4238 | | * |
4239 | | * -div1 + f' >= 0 |
4240 | | * |
4241 | | * A lower bound on div2 |
4242 | | * |
4243 | | * div2 + t >= 0 |
4244 | | * |
4245 | | * can be replaced by |
4246 | | * |
4247 | | * m div2 + div1 + m t + f >= 0 |
4248 | | * |
4249 | | * An upper bound |
4250 | | * |
4251 | | * -div2 + t >= 0 |
4252 | | * |
4253 | | * can be replaced by |
4254 | | * |
4255 | | * -(m div2 + div1) + m t + f' >= 0 |
4256 | | * |
4257 | | * These constraint are those that we would obtain from eliminating |
4258 | | * div1 using Fourier-Motzkin. |
4259 | | * |
4260 | | * After all constraints have been modified, we drop the lower and upper |
4261 | | * bound and then drop div1. |
4262 | | * Since the new div is only placed in the same location that used |
4263 | | * to store div2, but otherwise has a different meaning, any possible |
4264 | | * explicit representation of the original div2 is removed. |
4265 | | */ |
4266 | | static __isl_give isl_basic_map *coalesce_divs(__isl_take isl_basic_map *bmap, |
4267 | | unsigned div1, unsigned div2, unsigned l, unsigned u) |
4268 | 5 | { |
4269 | 5 | isl_ctx *ctx; |
4270 | 5 | isl_int m; |
4271 | 5 | unsigned dim, total; |
4272 | 5 | int i; |
4273 | 5 | |
4274 | 5 | ctx = isl_basic_map_get_ctx(bmap); |
4275 | 5 | |
4276 | 5 | dim = isl_space_dim(bmap->dim, isl_dim_all); |
4277 | 5 | total = 1 + dim + bmap->n_div; |
4278 | 5 | |
4279 | 5 | isl_int_init(m); |
4280 | 5 | isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]); |
4281 | 5 | isl_int_add_ui(m, m, 1); |
4282 | 5 | |
4283 | 72 | for (i = 0; i < bmap->n_ineq; ++i67 ) { |
4284 | 67 | if (i == l || i == u62 ) |
4285 | 10 | continue; |
4286 | 57 | if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2])) |
4287 | 57 | continue40 ; |
4288 | 17 | if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) { |
4289 | 3 | if (isl_int_is_pos(bmap->ineq[i][1 + dim + div2])) |
4290 | 3 | isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i], |
4291 | 2 | ctx->one, bmap->ineq[l], total); |
4292 | 1 | else |
4293 | 1 | isl_seq_combine(bmap->ineq[i], m, bmap->ineq[i], |
4294 | 1 | ctx->one, bmap->ineq[u], total); |
4295 | 3 | } |
4296 | 17 | isl_int_set(bmap->ineq[i][1 + dim + div2], |
4297 | 17 | bmap->ineq[i][1 + dim + div1]); |
4298 | 17 | isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0); |
4299 | 17 | } |
4300 | 5 | |
4301 | 5 | isl_int_clear(m); |
4302 | 5 | if (l > u) { |
4303 | 0 | isl_basic_map_drop_inequality(bmap, l); |
4304 | 0 | isl_basic_map_drop_inequality(bmap, u); |
4305 | 5 | } else { |
4306 | 5 | isl_basic_map_drop_inequality(bmap, u); |
4307 | 5 | isl_basic_map_drop_inequality(bmap, l); |
4308 | 5 | } |
4309 | 5 | bmap = isl_basic_map_mark_div_unknown(bmap, div2); |
4310 | 5 | bmap = isl_basic_map_drop_div(bmap, div1); |
4311 | 5 | return bmap; |
4312 | 5 | } |
4313 | | |
4314 | | /* First check if we can coalesce any pair of divs and |
4315 | | * then continue with dropping more redundant divs. |
4316 | | * |
4317 | | * We loop over all pairs of lower and upper bounds on a div |
4318 | | * with coefficient 1 and -1, respectively, check if there |
4319 | | * is any other div "c" with which we can coalesce the div |
4320 | | * and if so, perform the coalescing. |
4321 | | */ |
4322 | | static __isl_give isl_basic_map *coalesce_or_drop_more_redundant_divs( |
4323 | | __isl_take isl_basic_map *bmap, int *pairs, int n) |
4324 | 1.99k | { |
4325 | 1.99k | int i, l, u; |
4326 | 1.99k | unsigned dim; |
4327 | 1.99k | |
4328 | 1.99k | dim = isl_space_dim(bmap->dim, isl_dim_all); |
4329 | 1.99k | |
4330 | 6.56k | for (i = 0; i < bmap->n_div; ++i4.57k ) { |
4331 | 4.58k | if (!pairs[i]) |
4332 | 1.95k | continue; |
4333 | 34.0k | for (l = 0; 2.62k l < bmap->n_ineq; ++l31.3k ) { |
4334 | 31.3k | if (!isl_int_is_one(bmap->ineq[l][1 + dim + i])) |
4335 | 31.3k | continue30.2k ; |
4336 | 13.0k | for (u = 0; 1.14k u < bmap->n_ineq; ++u11.9k ) { |
4337 | 11.9k | int c; |
4338 | 11.9k | |
4339 | 11.9k | if (!isl_int_is_negone(bmap->ineq[u][1+dim+i])) |
4340 | 11.9k | continue10.8k ; |
4341 | 1.13k | c = div_find_coalesce(bmap, pairs, i, l, u); |
4342 | 1.13k | if (c < 0) |
4343 | 1.13k | continue; |
4344 | 5 | free(pairs); |
4345 | 5 | bmap = coalesce_divs(bmap, i, c, l, u); |
4346 | 5 | return isl_basic_map_drop_redundant_divs(bmap); |
4347 | 5 | } |
4348 | 1.14k | } |
4349 | 2.62k | } |
4350 | 1.99k | |
4351 | 1.99k | if (1.98k ISL_F_ISSET1.98k (bmap, ISL_BASIC_MAP_EMPTY)) { |
4352 | 0 | free(pairs); |
4353 | 0 | return bmap; |
4354 | 0 | } |
4355 | 1.98k | |
4356 | 1.98k | return drop_more_redundant_divs(bmap, pairs, n); |
4357 | 1.98k | } |
4358 | | |
4359 | | /* Are the "n" coefficients starting at "first" of inequality constraints |
4360 | | * "i" and "j" of "bmap" equal to each other? |
4361 | | */ |
4362 | | static int is_parallel_part(__isl_keep isl_basic_map *bmap, int i, int j, |
4363 | | int first, int n) |
4364 | 522 | { |
4365 | 522 | return isl_seq_eq(bmap->ineq[i] + first, bmap->ineq[j] + first, n); |
4366 | 522 | } |
4367 | | |
4368 | | /* Are the "n" coefficients starting at "first" of inequality constraints |
4369 | | * "i" and "j" of "bmap" opposite to each other? |
4370 | | */ |
4371 | | static int is_opposite_part(__isl_keep isl_basic_map *bmap, int i, int j, |
4372 | | int first, int n) |
4373 | 6.61k | { |
4374 | 6.61k | return isl_seq_is_neg(bmap->ineq[i] + first, bmap->ineq[j] + first, n); |
4375 | 6.61k | } |
4376 | | |
4377 | | /* Are inequality constraints "i" and "j" of "bmap" opposite to each other, |
4378 | | * apart from the constant term? |
4379 | | */ |
4380 | | static isl_bool is_opposite(__isl_keep isl_basic_map *bmap, int i, int j) |
4381 | 6.03k | { |
4382 | 6.03k | unsigned total; |
4383 | 6.03k | |
4384 | 6.03k | total = isl_basic_map_dim(bmap, isl_dim_all); |
4385 | 6.03k | return is_opposite_part(bmap, i, j, 1, total); |
4386 | 6.03k | } |
4387 | | |
4388 | | /* Are inequality constraints "i" and "j" of "bmap" equal to each other, |
4389 | | * apart from the constant term and the coefficient at position "pos"? |
4390 | | */ |
4391 | | static int is_parallel_except(__isl_keep isl_basic_map *bmap, int i, int j, |
4392 | | int pos) |
4393 | 499 | { |
4394 | 499 | unsigned total; |
4395 | 499 | |
4396 | 499 | total = isl_basic_map_dim(bmap, isl_dim_all); |
4397 | 499 | return is_parallel_part(bmap, i, j, 1, pos - 1) && |
4398 | 499 | is_parallel_part(bmap, i, j, pos + 1, total - pos)23 ; |
4399 | 499 | } |
4400 | | |
4401 | | /* Are inequality constraints "i" and "j" of "bmap" opposite to each other, |
4402 | | * apart from the constant term and the coefficient at position "pos"? |
4403 | | */ |
4404 | | static int is_opposite_except(__isl_keep isl_basic_map *bmap, int i, int j, |
4405 | | int pos) |
4406 | 487 | { |
4407 | 487 | unsigned total; |
4408 | 487 | |
4409 | 487 | total = isl_basic_map_dim(bmap, isl_dim_all); |
4410 | 487 | return is_opposite_part(bmap, i, j, 1, pos - 1) && |
4411 | 487 | is_opposite_part(bmap, i, j, pos + 1, total - pos)93 ; |
4412 | 487 | } |
4413 | | |
4414 | | /* Restart isl_basic_map_drop_redundant_divs after "bmap" has |
4415 | | * been modified, simplying it if "simplify" is set. |
4416 | | * Free the temporary data structure "pairs" that was associated |
4417 | | * to the old version of "bmap". |
4418 | | */ |
4419 | | static __isl_give isl_basic_map *drop_redundant_divs_again( |
4420 | | __isl_take isl_basic_map *bmap, __isl_take int *pairs, int simplify) |
4421 | 13.8k | { |
4422 | 13.8k | if (simplify) |
4423 | 1.76k | bmap = isl_basic_map_simplify(bmap); |
4424 | 13.8k | free(pairs); |
4425 | 13.8k | return isl_basic_map_drop_redundant_divs(bmap); |
4426 | 13.8k | } |
4427 | | |
4428 | | /* Is "div" the single unknown existentially quantified variable |
4429 | | * in inequality constraint "ineq" of "bmap"? |
4430 | | * "div" is known to have a non-zero coefficient in "ineq". |
4431 | | */ |
4432 | | static isl_bool single_unknown(__isl_keep isl_basic_map *bmap, int ineq, |
4433 | | int div) |
4434 | 2.22k | { |
4435 | 2.22k | int i; |
4436 | 2.22k | unsigned n_div, o_div; |
4437 | 2.22k | isl_bool known; |
4438 | 2.22k | |
4439 | 2.22k | known = isl_basic_map_div_is_known(bmap, div); |
4440 | 2.22k | if (known < 0 || known) |
4441 | 257 | return isl_bool_not(known); |
4442 | 1.97k | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4443 | 1.97k | if (n_div == 1) |
4444 | 1.11k | return isl_bool_true; |
4445 | 853 | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
4446 | 3.05k | for (i = 0; i < n_div; ++i2.20k ) { |
4447 | 2.24k | isl_bool known; |
4448 | 2.24k | |
4449 | 2.24k | if (i == div) |
4450 | 834 | continue; |
4451 | 1.40k | if (isl_int_is_zero(bmap->ineq[ineq][o_div + i])) |
4452 | 1.40k | continue1.33k ; |
4453 | 71 | known = isl_basic_map_div_is_known(bmap, i); |
4454 | 71 | if (known < 0 || !known) |
4455 | 40 | return known; |
4456 | 71 | } |
4457 | 853 | |
4458 | 853 | return isl_bool_true813 ; |
4459 | 853 | } |
4460 | | |
4461 | | /* Does integer division "div" have coefficient 1 in inequality constraint |
4462 | | * "ineq" of "map"? |
4463 | | */ |
4464 | | static isl_bool has_coef_one(__isl_keep isl_basic_map *bmap, int div, int ineq) |
4465 | 1.93k | { |
4466 | 1.93k | unsigned o_div; |
4467 | 1.93k | |
4468 | 1.93k | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
4469 | 1.93k | if (isl_int_is_one(bmap->ineq[ineq][o_div + div])) |
4470 | 1.93k | return isl_bool_true1.76k ; |
4471 | 171 | |
4472 | 171 | return isl_bool_false; |
4473 | 171 | } |
4474 | | |
4475 | | /* Turn inequality constraint "ineq" of "bmap" into an equality and |
4476 | | * then try and drop redundant divs again, |
4477 | | * freeing the temporary data structure "pairs" that was associated |
4478 | | * to the old version of "bmap". |
4479 | | */ |
4480 | | static __isl_give isl_basic_map *set_eq_and_try_again( |
4481 | | __isl_take isl_basic_map *bmap, int ineq, __isl_take int *pairs) |
4482 | 1.76k | { |
4483 | 1.76k | bmap = isl_basic_map_cow(bmap); |
4484 | 1.76k | isl_basic_map_inequality_to_equality(bmap, ineq); |
4485 | 1.76k | return drop_redundant_divs_again(bmap, pairs, 1); |
4486 | 1.76k | } |
4487 | | |
4488 | | /* Drop the integer division at position "div", along with the two |
4489 | | * inequality constraints "ineq1" and "ineq2" in which it appears |
4490 | | * from "bmap" and then try and drop redundant divs again, |
4491 | | * freeing the temporary data structure "pairs" that was associated |
4492 | | * to the old version of "bmap". |
4493 | | */ |
4494 | | static __isl_give isl_basic_map *drop_div_and_try_again( |
4495 | | __isl_take isl_basic_map *bmap, int div, int ineq1, int ineq2, |
4496 | | __isl_take int *pairs) |
4497 | 1.51k | { |
4498 | 1.51k | if (ineq1 > ineq2) { |
4499 | 712 | isl_basic_map_drop_inequality(bmap, ineq1); |
4500 | 712 | isl_basic_map_drop_inequality(bmap, ineq2); |
4501 | 805 | } else { |
4502 | 805 | isl_basic_map_drop_inequality(bmap, ineq2); |
4503 | 805 | isl_basic_map_drop_inequality(bmap, ineq1); |
4504 | 805 | } |
4505 | 1.51k | bmap = isl_basic_map_drop_div(bmap, div); |
4506 | 1.51k | return drop_redundant_divs_again(bmap, pairs, 0); |
4507 | 1.51k | } |
4508 | | |
4509 | | /* Given two inequality constraints |
4510 | | * |
4511 | | * f(x) + n d + c >= 0, (ineq) |
4512 | | * |
4513 | | * with d the variable at position "pos", and |
4514 | | * |
4515 | | * f(x) + c0 >= 0, (lower) |
4516 | | * |
4517 | | * compute the maximal value of the lower bound ceil((-f(x) - c)/n) |
4518 | | * determined by the first constraint. |
4519 | | * That is, store |
4520 | | * |
4521 | | * ceil((c0 - c)/n) |
4522 | | * |
4523 | | * in *l. |
4524 | | */ |
4525 | | static void lower_bound_from_parallel(__isl_keep isl_basic_map *bmap, |
4526 | | int ineq, int lower, int pos, isl_int *l) |
4527 | 24 | { |
4528 | 24 | isl_int_neg(*l, bmap->ineq[ineq][0]); |
4529 | 24 | isl_int_add(*l, *l, bmap->ineq[lower][0]); |
4530 | 24 | isl_int_cdiv_q(*l, *l, bmap->ineq[ineq][pos]); |
4531 | 24 | } |
4532 | | |
4533 | | /* Given two inequality constraints |
4534 | | * |
4535 | | * f(x) + n d + c >= 0, (ineq) |
4536 | | * |
4537 | | * with d the variable at position "pos", and |
4538 | | * |
4539 | | * -f(x) - c0 >= 0, (upper) |
4540 | | * |
4541 | | * compute the minimal value of the lower bound ceil((-f(x) - c)/n) |
4542 | | * determined by the first constraint. |
4543 | | * That is, store |
4544 | | * |
4545 | | * ceil((-c1 - c)/n) |
4546 | | * |
4547 | | * in *u. |
4548 | | */ |
4549 | | static void lower_bound_from_opposite(__isl_keep isl_basic_map *bmap, |
4550 | | int ineq, int upper, int pos, isl_int *u) |
4551 | 17 | { |
4552 | 17 | isl_int_neg(*u, bmap->ineq[ineq][0]); |
4553 | 17 | isl_int_sub(*u, *u, bmap->ineq[upper][0]); |
4554 | 17 | isl_int_cdiv_q(*u, *u, bmap->ineq[ineq][pos]); |
4555 | 17 | } |
4556 | | |
4557 | | /* Given a lower bound constraint "ineq" on "div" in "bmap", |
4558 | | * does the corresponding lower bound have a fixed value in "bmap"? |
4559 | | * |
4560 | | * In particular, "ineq" is of the form |
4561 | | * |
4562 | | * f(x) + n d + c >= 0 |
4563 | | * |
4564 | | * with n > 0, c the constant term and |
4565 | | * d the existentially quantified variable "div". |
4566 | | * That is, the lower bound is |
4567 | | * |
4568 | | * ceil((-f(x) - c)/n) |
4569 | | * |
4570 | | * Look for a pair of constraints |
4571 | | * |
4572 | | * f(x) + c0 >= 0 |
4573 | | * -f(x) + c1 >= 0 |
4574 | | * |
4575 | | * i.e., -c1 <= -f(x) <= c0, that fix ceil((-f(x) - c)/n) to a constant value. |
4576 | | * That is, check that |
4577 | | * |
4578 | | * ceil((-c1 - c)/n) = ceil((c0 - c)/n) |
4579 | | * |
4580 | | * If so, return the index of inequality f(x) + c0 >= 0. |
4581 | | * Otherwise, return -1. |
4582 | | */ |
4583 | | static int lower_bound_is_cst(__isl_keep isl_basic_map *bmap, int div, int ineq) |
4584 | 171 | { |
4585 | 171 | int i; |
4586 | 171 | int lower = -1, upper = -1; |
4587 | 171 | unsigned o_div; |
4588 | 171 | isl_int l, u; |
4589 | 171 | int equal; |
4590 | 171 | |
4591 | 171 | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
4592 | 1.07k | for (i = 0; i < bmap->n_ineq && (914 lower < 0914 || upper < 055 ); ++i899 ) { |
4593 | 899 | if (i == ineq) |
4594 | 156 | continue; |
4595 | 743 | if (!isl_int_is_zero(bmap->ineq[i][o_div + div])) |
4596 | 743 | continue217 ; |
4597 | 526 | if (lower < 0 && |
4598 | 526 | is_parallel_except(bmap, ineq, i, o_div + div)499 ) { |
4599 | 22 | lower = i; |
4600 | 22 | continue; |
4601 | 22 | } |
4602 | 504 | if (upper < 0 && |
4603 | 504 | is_opposite_except(bmap, ineq, i, o_div + div)487 ) { |
4604 | 92 | upper = i; |
4605 | 92 | } |
4606 | 504 | } |
4607 | 171 | |
4608 | 171 | if (lower < 0 || upper < 022 ) |
4609 | 154 | return -1; |
4610 | 17 | |
4611 | 17 | isl_int_init(l); |
4612 | 17 | isl_int_init(u); |
4613 | 17 | |
4614 | 17 | lower_bound_from_parallel(bmap, ineq, lower, o_div + div, &l); |
4615 | 17 | lower_bound_from_opposite(bmap, ineq, upper, o_div + div, &u); |
4616 | 17 | |
4617 | 17 | equal = isl_int_eq(l, u); |
4618 | 17 | |
4619 | 17 | isl_int_clear(l); |
4620 | 17 | isl_int_clear(u); |
4621 | 17 | |
4622 | 17 | return equal ? lower7 : -110 ; |
4623 | 17 | } |
4624 | | |
4625 | | /* Given a lower bound constraint "ineq" on the existentially quantified |
4626 | | * variable "div", such that the corresponding lower bound has |
4627 | | * a fixed value in "bmap", assign this fixed value to the variable and |
4628 | | * then try and drop redundant divs again, |
4629 | | * freeing the temporary data structure "pairs" that was associated |
4630 | | * to the old version of "bmap". |
4631 | | * "lower" determines the constant value for the lower bound. |
4632 | | * |
4633 | | * In particular, "ineq" is of the form |
4634 | | * |
4635 | | * f(x) + n d + c >= 0, |
4636 | | * |
4637 | | * while "lower" is of the form |
4638 | | * |
4639 | | * f(x) + c0 >= 0 |
4640 | | * |
4641 | | * The lower bound is ceil((-f(x) - c)/n) and its constant value |
4642 | | * is ceil((c0 - c)/n). |
4643 | | */ |
4644 | | static __isl_give isl_basic_map *fix_cst_lower(__isl_take isl_basic_map *bmap, |
4645 | | int div, int ineq, int lower, int *pairs) |
4646 | 7 | { |
4647 | 7 | isl_int c; |
4648 | 7 | unsigned o_div; |
4649 | 7 | |
4650 | 7 | isl_int_init(c); |
4651 | 7 | |
4652 | 7 | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
4653 | 7 | lower_bound_from_parallel(bmap, ineq, lower, o_div + div, &c); |
4654 | 7 | bmap = isl_basic_map_fix(bmap, isl_dim_div, div, c); |
4655 | 7 | free(pairs); |
4656 | 7 | |
4657 | 7 | isl_int_clear(c); |
4658 | 7 | |
4659 | 7 | return isl_basic_map_drop_redundant_divs(bmap); |
4660 | 7 | } |
4661 | | |
4662 | | /* Remove divs that are not strictly needed based on the inequality |
4663 | | * constraints. |
4664 | | * In particular, if a div only occurs positively (or negatively) |
4665 | | * in constraints, then it can simply be dropped. |
4666 | | * Also, if a div occurs in only two constraints and if moreover |
4667 | | * those two constraints are opposite to each other, except for the constant |
4668 | | * term and if the sum of the constant terms is such that for any value |
4669 | | * of the other values, there is always at least one integer value of the |
4670 | | * div, i.e., if one plus this sum is greater than or equal to |
4671 | | * the (absolute value) of the coefficient of the div in the constraints, |
4672 | | * then we can also simply drop the div. |
4673 | | * |
4674 | | * If an existentially quantified variable does not have an explicit |
4675 | | * representation, appears in only a single lower bound that does not |
4676 | | * involve any other such existentially quantified variables and appears |
4677 | | * in this lower bound with coefficient 1, |
4678 | | * then fix the variable to the value of the lower bound. That is, |
4679 | | * turn the inequality into an equality. |
4680 | | * If for any value of the other variables, there is any value |
4681 | | * for the existentially quantified variable satisfying the constraints, |
4682 | | * then this lower bound also satisfies the constraints. |
4683 | | * It is therefore safe to pick this lower bound. |
4684 | | * |
4685 | | * The same reasoning holds even if the coefficient is not one. |
4686 | | * However, fixing the variable to the value of the lower bound may |
4687 | | * in general introduce an extra integer division, in which case |
4688 | | * it may be better to pick another value. |
4689 | | * If this integer division has a known constant value, then plugging |
4690 | | * in this constant value removes the existentially quantified variable |
4691 | | * completely. In particular, if the lower bound is of the form |
4692 | | * ceil((-f(x) - c)/n) and there are two constraints, f(x) + c0 >= 0 and |
4693 | | * -f(x) + c1 >= 0 such that ceil((-c1 - c)/n) = ceil((c0 - c)/n), |
4694 | | * then the existentially quantified variable can be assigned this |
4695 | | * shared value. |
4696 | | * |
4697 | | * We skip divs that appear in equalities or in the definition of other divs. |
4698 | | * Divs that appear in the definition of other divs usually occur in at least |
4699 | | * 4 constraints, but the constraints may have been simplified. |
4700 | | * |
4701 | | * If any divs are left after these simple checks then we move on |
4702 | | * to more complicated cases in drop_more_redundant_divs. |
4703 | | */ |
4704 | | static __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs_ineq( |
4705 | | __isl_take isl_basic_map *bmap) |
4706 | 300k | { |
4707 | 300k | int i, j; |
4708 | 300k | unsigned off; |
4709 | 300k | int *pairs = NULL; |
4710 | 300k | int n = 0; |
4711 | 300k | |
4712 | 300k | if (!bmap) |
4713 | 0 | goto error; |
4714 | 300k | if (bmap->n_div == 0) |
4715 | 277k | return bmap; |
4716 | 22.8k | |
4717 | 22.8k | off = isl_space_dim(bmap->dim, isl_dim_all); |
4718 | 22.8k | pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div); |
4719 | 22.8k | if (!pairs) |
4720 | 0 | goto error; |
4721 | 22.8k | |
4722 | 38.1k | for (i = 0; 22.8k i < bmap->n_div; ++i15.2k ) { |
4723 | 29.0k | int pos, neg; |
4724 | 29.0k | int last_pos, last_neg; |
4725 | 29.0k | int redundant; |
4726 | 29.0k | int defined; |
4727 | 29.0k | isl_bool opp, set_div; |
4728 | 29.0k | |
4729 | 29.0k | defined = !isl_int_is_zero(bmap->div[i][0]); |
4730 | 68.7k | for (j = i; j < bmap->n_div; ++j39.6k ) |
4731 | 40.7k | if (!isl_int_is_zero(bmap->div[j][1 + 1 + off + i])) |
4732 | 40.7k | break1.04k ; |
4733 | 29.0k | if (j < bmap->n_div) |
4734 | 1.04k | continue; |
4735 | 51.1k | for (j = 0; 28.0k j < bmap->n_eq; ++j23.1k ) |
4736 | 31.4k | if (!isl_int_is_zero(bmap->eq[j][1 + off + i])) |
4737 | 31.4k | break8.32k ; |
4738 | 28.0k | if (j < bmap->n_eq) |
4739 | 8.32k | continue; |
4740 | 19.6k | ++n; |
4741 | 19.6k | pos = neg = 0; |
4742 | 113k | for (j = 0; j < bmap->n_ineq; ++j93.6k ) { |
4743 | 93.6k | if (isl_int_is_pos(bmap->ineq[j][1 + off + i])) { |
4744 | 12.7k | last_pos = j; |
4745 | 12.7k | ++pos; |
4746 | 12.7k | } |
4747 | 93.6k | if (isl_int_is_neg(bmap->ineq[j][1 + off + i])) { |
4748 | 12.6k | last_neg = j; |
4749 | 12.6k | ++neg; |
4750 | 12.6k | } |
4751 | 93.6k | } |
4752 | 19.6k | pairs[i] = pos * neg; |
4753 | 19.6k | if (pairs[i] == 0) { |
4754 | 10.8k | for (j = bmap->n_ineq - 1; j >= 0; --j329 ) |
4755 | 329 | if (!isl_int_is_zero(bmap->ineq[j][1+off+i])) |
4756 | 329 | isl_basic_map_drop_inequality(bmap, j)283 ; |
4757 | 10.5k | bmap = isl_basic_map_drop_div(bmap, i); |
4758 | 10.5k | return drop_redundant_divs_again(bmap, pairs, 0); |
4759 | 10.5k | } |
4760 | 9.12k | if (pairs[i] != 1) |
4761 | 3.09k | opp = isl_bool_false; |
4762 | 6.03k | else |
4763 | 6.03k | opp = is_opposite(bmap, last_pos, last_neg); |
4764 | 9.12k | if (opp < 0) |
4765 | 0 | goto error; |
4766 | 9.12k | if (!opp) { |
4767 | 4.66k | int lower; |
4768 | 4.66k | isl_bool single, one; |
4769 | 4.66k | |
4770 | 4.66k | if (pos != 1) |
4771 | 2.43k | continue; |
4772 | 2.22k | single = single_unknown(bmap, last_pos, i); |
4773 | 2.22k | if (single < 0) |
4774 | 0 | goto error; |
4775 | 2.22k | if (!single) |
4776 | 297 | continue; |
4777 | 1.93k | one = has_coef_one(bmap, i, last_pos); |
4778 | 1.93k | if (one < 0) |
4779 | 0 | goto error; |
4780 | 1.93k | if (one) |
4781 | 1.76k | return set_eq_and_try_again(bmap, last_pos, |
4782 | 1.76k | pairs); |
4783 | 171 | lower = lower_bound_is_cst(bmap, i, last_pos); |
4784 | 171 | if (lower >= 0) |
4785 | 7 | return fix_cst_lower(bmap, i, last_pos, lower, |
4786 | 7 | pairs); |
4787 | 164 | continue; |
4788 | 164 | } |
4789 | 4.46k | |
4790 | 4.46k | isl_int_add(bmap->ineq[last_pos][0], |
4791 | 4.46k | bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]); |
4792 | 4.46k | isl_int_add_ui(bmap->ineq[last_pos][0], |
4793 | 4.46k | bmap->ineq[last_pos][0], 1); |
4794 | 4.46k | redundant = isl_int_ge(bmap->ineq[last_pos][0], |
4795 | 4.46k | bmap->ineq[last_pos][1+off+i]); |
4796 | 4.46k | isl_int_sub_ui(bmap->ineq[last_pos][0], |
4797 | 4.46k | bmap->ineq[last_pos][0], 1); |
4798 | 4.46k | isl_int_sub(bmap->ineq[last_pos][0], |
4799 | 4.46k | bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]); |
4800 | 4.46k | if (redundant) |
4801 | 1.51k | return drop_div_and_try_again(bmap, i, |
4802 | 1.51k | last_pos, last_neg, pairs); |
4803 | 2.94k | if (defined) |
4804 | 2.94k | set_div = isl_bool_false; |
4805 | 7 | else |
4806 | 7 | set_div = ok_to_set_div_from_bound(bmap, i, last_pos); |
4807 | 2.94k | if (set_div < 0) |
4808 | 0 | return isl_basic_map_free(bmap); |
4809 | 2.94k | if (set_div) { |
4810 | 1 | bmap = set_div_from_lower_bound(bmap, i, last_pos); |
4811 | 1 | return drop_redundant_divs_again(bmap, pairs, 1); |
4812 | 1 | } |
4813 | 2.94k | pairs[i] = 0; |
4814 | 2.94k | --n; |
4815 | 2.94k | } |
4816 | 22.8k | |
4817 | 22.8k | if (9.05k n > 09.05k ) |
4818 | 1.99k | return coalesce_or_drop_more_redundant_divs(bmap, pairs, n); |
4819 | 7.06k | |
4820 | 7.06k | free(pairs); |
4821 | 7.06k | return bmap; |
4822 | 0 | error: |
4823 | 0 | free(pairs); |
4824 | 0 | isl_basic_map_free(bmap); |
4825 | 0 | return NULL; |
4826 | 7.06k | } |
4827 | | |
4828 | | /* Consider the coefficients at "c" as a row vector and replace |
4829 | | * them with their product with "T". "T" is assumed to be a square matrix. |
4830 | | */ |
4831 | | static isl_stat preimage(isl_int *c, __isl_keep isl_mat *T) |
4832 | 30.9k | { |
4833 | 30.9k | int n; |
4834 | 30.9k | isl_ctx *ctx; |
4835 | 30.9k | isl_vec *v; |
4836 | 30.9k | |
4837 | 30.9k | if (!T) |
4838 | 0 | return isl_stat_error; |
4839 | 30.9k | n = isl_mat_rows(T); |
4840 | 30.9k | if (isl_seq_first_non_zero(c, n) == -1) |
4841 | 18.8k | return isl_stat_ok; |
4842 | 12.0k | ctx = isl_mat_get_ctx(T); |
4843 | 12.0k | v = isl_vec_alloc(ctx, n); |
4844 | 12.0k | if (!v) |
4845 | 0 | return isl_stat_error; |
4846 | 12.0k | isl_seq_swp_or_cpy(v->el, c, n); |
4847 | 12.0k | v = isl_vec_mat_product(v, isl_mat_copy(T)); |
4848 | 12.0k | if (!v) |
4849 | 0 | return isl_stat_error; |
4850 | 12.0k | isl_seq_swp_or_cpy(c, v->el, n); |
4851 | 12.0k | isl_vec_free(v); |
4852 | 12.0k | |
4853 | 12.0k | return isl_stat_ok; |
4854 | 12.0k | } |
4855 | | |
4856 | | /* Plug in T for the variables in "bmap" starting at "pos". |
4857 | | * T is a linear unimodular matrix, i.e., without constant term. |
4858 | | */ |
4859 | | static __isl_give isl_basic_map *isl_basic_map_preimage_vars( |
4860 | | __isl_take isl_basic_map *bmap, unsigned pos, __isl_take isl_mat *T) |
4861 | 2.78k | { |
4862 | 2.78k | int i; |
4863 | 2.78k | unsigned n, total; |
4864 | 2.78k | |
4865 | 2.78k | bmap = isl_basic_map_cow(bmap); |
4866 | 2.78k | if (!bmap || !T) |
4867 | 0 | goto error; |
4868 | 2.78k | |
4869 | 2.78k | n = isl_mat_cols(T); |
4870 | 2.78k | if (n != isl_mat_rows(T)) |
4871 | 2.78k | isl_die0 (isl_mat_get_ctx(T), isl_error_invalid, |
4872 | 2.78k | "expecting square matrix", goto error); |
4873 | 2.78k | |
4874 | 2.78k | total = isl_basic_map_dim(bmap, isl_dim_all); |
4875 | 2.78k | if (pos + n > total || pos + n < pos) |
4876 | 2.78k | isl_die0 (isl_mat_get_ctx(T), isl_error_invalid, |
4877 | 2.78k | "invalid range", goto error); |
4878 | 2.78k | |
4879 | 9.23k | for (i = 0; 2.78k i < bmap->n_eq; ++i6.45k ) |
4880 | 6.45k | if (preimage(bmap->eq[i] + 1 + pos, T) < 0) |
4881 | 0 | goto error; |
4882 | 25.8k | for (i = 0; 2.78k i < bmap->n_ineq; ++i23.1k ) |
4883 | 23.1k | if (preimage(bmap->ineq[i] + 1 + pos, T) < 0) |
4884 | 0 | goto error; |
4885 | 10.7k | for (i = 0; 2.78k i < bmap->n_div; ++i7.93k ) { |
4886 | 7.93k | if (isl_basic_map_div_is_marked_unknown(bmap, i)) |
4887 | 6.53k | continue; |
4888 | 1.40k | if (preimage(bmap->div[i] + 1 + 1 + pos, T) < 0) |
4889 | 0 | goto error; |
4890 | 1.40k | } |
4891 | 2.78k | |
4892 | 2.78k | isl_mat_free(T); |
4893 | 2.78k | return bmap; |
4894 | 0 | error: |
4895 | 0 | isl_basic_map_free(bmap); |
4896 | 0 | isl_mat_free(T); |
4897 | 0 | return NULL; |
4898 | 2.78k | } |
4899 | | |
4900 | | /* Remove divs that are not strictly needed. |
4901 | | * |
4902 | | * First look for an equality constraint involving two or more |
4903 | | * existentially quantified variables without an explicit |
4904 | | * representation. Replace the combination that appears |
4905 | | * in the equality constraint by a single existentially quantified |
4906 | | * variable such that the equality can be used to derive |
4907 | | * an explicit representation for the variable. |
4908 | | * If there are no more such equality constraints, then continue |
4909 | | * with isl_basic_map_drop_redundant_divs_ineq. |
4910 | | * |
4911 | | * In particular, if the equality constraint is of the form |
4912 | | * |
4913 | | * f(x) + \sum_i c_i a_i = 0 |
4914 | | * |
4915 | | * with a_i existentially quantified variable without explicit |
4916 | | * representation, then apply a transformation on the existentially |
4917 | | * quantified variables to turn the constraint into |
4918 | | * |
4919 | | * f(x) + g a_1' = 0 |
4920 | | * |
4921 | | * with g the gcd of the c_i. |
4922 | | * In order to easily identify which existentially quantified variables |
4923 | | * have a complete explicit representation, i.e., without being defined |
4924 | | * in terms of other existentially quantified variables without |
4925 | | * an explicit representation, the existentially quantified variables |
4926 | | * are first sorted. |
4927 | | * |
4928 | | * The variable transformation is computed by extending the row |
4929 | | * [c_1/g ... c_n/g] to a unimodular matrix, obtaining the transformation |
4930 | | * |
4931 | | * [a_1'] [c_1/g ... c_n/g] [ a_1 ] |
4932 | | * [a_2'] [ a_2 ] |
4933 | | * ... = U .... |
4934 | | * [a_n'] [ a_n ] |
4935 | | * |
4936 | | * with [c_1/g ... c_n/g] representing the first row of U. |
4937 | | * The inverse of U is then plugged into the original constraints. |
4938 | | * The call to isl_basic_map_simplify makes sure the explicit |
4939 | | * representation for a_1' is extracted from the equality constraint. |
4940 | | */ |
4941 | | __isl_give isl_basic_map *isl_basic_map_drop_redundant_divs( |
4942 | | __isl_take isl_basic_map *bmap) |
4943 | 303k | { |
4944 | 303k | int first; |
4945 | 303k | int i; |
4946 | 303k | unsigned o_div, n_div; |
4947 | 303k | int l; |
4948 | 303k | isl_ctx *ctx; |
4949 | 303k | isl_mat *T; |
4950 | 303k | |
4951 | 303k | if (!bmap) |
4952 | 0 | return NULL; |
4953 | 303k | if (isl_basic_map_divs_known(bmap)) |
4954 | 286k | return isl_basic_map_drop_redundant_divs_ineq(bmap); |
4955 | 16.4k | if (bmap->n_eq == 0) |
4956 | 1.69k | return isl_basic_map_drop_redundant_divs_ineq(bmap); |
4957 | 14.7k | bmap = isl_basic_map_sort_divs(bmap); |
4958 | 14.7k | if (!bmap) |
4959 | 0 | return NULL; |
4960 | 14.7k | |
4961 | 14.7k | first = isl_basic_map_first_unknown_div(bmap); |
4962 | 14.7k | if (first < 0) |
4963 | 0 | return isl_basic_map_free(bmap); |
4964 | 14.7k | |
4965 | 14.7k | o_div = isl_basic_map_offset(bmap, isl_dim_div); |
4966 | 14.7k | n_div = isl_basic_map_dim(bmap, isl_dim_div); |
4967 | 14.7k | |
4968 | 29.1k | for (i = 0; i < bmap->n_eq; ++i14.3k ) { |
4969 | 17.1k | l = isl_seq_first_non_zero(bmap->eq[i] + o_div + first, |
4970 | 17.1k | n_div - (first)); |
4971 | 17.1k | if (l < 0) |
4972 | 14.3k | continue; |
4973 | 2.78k | l += first; |
4974 | 2.78k | if (isl_seq_first_non_zero(bmap->eq[i] + o_div + l + 1, |
4975 | 2.78k | n_div - (l + 1)) == -1) |
4976 | 0 | continue; |
4977 | 2.78k | break; |
4978 | 2.78k | } |
4979 | 14.7k | if (i >= bmap->n_eq) |
4980 | 12.0k | return isl_basic_map_drop_redundant_divs_ineq(bmap); |
4981 | 2.78k | |
4982 | 2.78k | ctx = isl_basic_map_get_ctx(bmap); |
4983 | 2.78k | T = isl_mat_alloc(ctx, n_div - l, n_div - l); |
4984 | 2.78k | if (!T) |
4985 | 0 | return isl_basic_map_free(bmap); |
4986 | 2.78k | isl_seq_cpy(T->row[0], bmap->eq[i] + o_div + l, n_div - l); |
4987 | 2.78k | T = isl_mat_normalize_row(T, 0); |
4988 | 2.78k | T = isl_mat_unimodular_complete(T, 1); |
4989 | 2.78k | T = isl_mat_right_inverse(T); |
4990 | 2.78k | |
4991 | 9.19k | for (i = l; i < n_div; ++i6.40k ) |
4992 | 6.40k | bmap = isl_basic_map_mark_div_unknown(bmap, i); |
4993 | 2.78k | bmap = isl_basic_map_preimage_vars(bmap, o_div - 1 + l, T); |
4994 | 2.78k | bmap = isl_basic_map_simplify(bmap); |
4995 | 2.78k | |
4996 | 2.78k | return isl_basic_map_drop_redundant_divs(bmap); |
4997 | 2.78k | } |
4998 | | |
4999 | | /* Does "bmap" satisfy any equality that involves more than 2 variables |
5000 | | * and/or has coefficients different from -1 and 1? |
5001 | | */ |
5002 | | static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap) |
5003 | 16.2k | { |
5004 | 16.2k | int i; |
5005 | 16.2k | unsigned total; |
5006 | 16.2k | |
5007 | 16.2k | total = isl_basic_map_dim(bmap, isl_dim_all); |
5008 | 16.2k | |
5009 | 34.4k | for (i = 0; i < bmap->n_eq; ++i18.1k ) { |
5010 | 25.4k | int j, k; |
5011 | 25.4k | |
5012 | 25.4k | j = isl_seq_first_non_zero(bmap->eq[i] + 1, total); |
5013 | 25.4k | if (j < 0) |
5014 | 0 | continue; |
5015 | 25.4k | if (!isl_int_is_one(bmap->eq[i][1 + j]) && |
5016 | 25.4k | !12.4k isl_int_is_negone12.4k (bmap->eq[i][1 + j])) |
5017 | 25.4k | return 16.31k ; |
5018 | 19.1k | |
5019 | 19.1k | j += 1; |
5020 | 19.1k | k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j); |
5021 | 19.1k | if (k < 0) |
5022 | 12.7k | continue; |
5023 | 6.36k | j += k; |
5024 | 6.36k | if (!isl_int_is_one(bmap->eq[i][1 + j]) && |
5025 | 6.36k | !882 isl_int_is_negone882 (bmap->eq[i][1 + j])) |
5026 | 6.36k | return 1634 ; |
5027 | 5.73k | |
5028 | 5.73k | j += 1; |
5029 | 5.73k | k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j); |
5030 | 5.73k | if (k >= 0) |
5031 | 328 | return 1; |
5032 | 5.73k | } |
5033 | 16.2k | |
5034 | 16.2k | return 09.01k ; |
5035 | 16.2k | } |
5036 | | |
5037 | | /* Remove any common factor g from the constraint coefficients in "v". |
5038 | | * The constant term is stored in the first position and is replaced |
5039 | | * by floor(c/g). If any common factor is removed and if this results |
5040 | | * in a tightening of the constraint, then set *tightened. |
5041 | | */ |
5042 | | static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v, |
5043 | | int *tightened) |
5044 | 72.6k | { |
5045 | 72.6k | isl_ctx *ctx; |
5046 | 72.6k | |
5047 | 72.6k | if (!v) |
5048 | 0 | return NULL; |
5049 | 72.6k | ctx = isl_vec_get_ctx(v); |
5050 | 72.6k | isl_seq_gcd(v->el + 1, v->size - 1, &ctx->normalize_gcd); |
5051 | 72.6k | if (isl_int_is_zero(ctx->normalize_gcd)) |
5052 | 72.6k | return v0 ; |
5053 | 72.6k | if (isl_int_is_one(ctx->normalize_gcd)) |
5054 | 72.6k | return v70.8k ; |
5055 | 1.77k | v = isl_vec_cow(v); |
5056 | 1.77k | if (!v) |
5057 | 0 | return NULL; |
5058 | 1.77k | if (tightened && !isl_int_is_divisible_by(v->el[0], ctx->normalize_gcd)) |
5059 | 1.77k | *tightened = 1720 ; |
5060 | 1.77k | isl_int_fdiv_q(v->el[0], v->el[0], ctx->normalize_gcd); |
5061 | 1.77k | isl_seq_scale_down(v->el + 1, v->el + 1, ctx->normalize_gcd, |
5062 | 1.77k | v->size - 1); |
5063 | 1.77k | return v; |
5064 | 1.77k | } |
5065 | | |
5066 | | /* If "bmap" is an integer set that satisfies any equality involving |
5067 | | * more than 2 variables and/or has coefficients different from -1 and 1, |
5068 | | * then use variable compression to reduce the coefficients by removing |
5069 | | * any (hidden) common factor. |
5070 | | * In particular, apply the variable compression to each constraint, |
5071 | | * factor out any common factor in the non-constant coefficients and |
5072 | | * then apply the inverse of the compression. |
5073 | | * At the end, we mark the basic map as having reduced constants. |
5074 | | * If this flag is still set on the next invocation of this function, |
5075 | | * then we skip the computation. |
5076 | | * |
5077 | | * Removing a common factor may result in a tightening of some of |
5078 | | * the constraints. If this happens, then we may end up with two |
5079 | | * opposite inequalities that can be replaced by an equality. |
5080 | | * We therefore call isl_basic_map_detect_inequality_pairs, |
5081 | | * which checks for such pairs of inequalities as well as eliminate_divs_eq |
5082 | | * and isl_basic_map_gauss if such a pair was found. |
5083 | | * |
5084 | | * Note that this function may leave the result in an inconsistent state. |
5085 | | * In particular, the constraints may not be gaussed. |
5086 | | * Unfortunately, isl_map_coalesce actually depends on this inconsistent state |
5087 | | * for some of the test cases to pass successfully. |
5088 | | * Any potential modification of the representation is therefore only |
5089 | | * performed on a single copy of the basic map. |
5090 | | */ |
5091 | | __isl_give isl_basic_map *isl_basic_map_reduce_coefficients( |
5092 | | __isl_take isl_basic_map *bmap) |
5093 | 67.6k | { |
5094 | 67.6k | unsigned total; |
5095 | 67.6k | isl_ctx *ctx; |
5096 | 67.6k | isl_vec *v; |
5097 | 67.6k | isl_mat *eq, *T, *T2; |
5098 | 67.6k | int i; |
5099 | 67.6k | int tightened; |
5100 | 67.6k | |
5101 | 67.6k | if (!bmap) |
5102 | 0 | return NULL; |
5103 | 67.6k | if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS)) |
5104 | 67.6k | return bmap124 ; |
5105 | 67.5k | if (isl_basic_map_is_rational(bmap)) |
5106 | 24.5k | return bmap; |
5107 | 43.0k | if (bmap->n_eq == 0) |
5108 | 26.7k | return bmap; |
5109 | 16.2k | if (!has_multiple_var_equality(bmap)) |
5110 | 9.01k | return bmap; |
5111 | 7.27k | |
5112 | 7.27k | total = isl_basic_map_dim(bmap, isl_dim_all); |
5113 | 7.27k | ctx = isl_basic_map_get_ctx(bmap); |
5114 | 7.27k | v = isl_vec_alloc(ctx, 1 + total); |
5115 | 7.27k | if (!v) |
5116 | 0 | return isl_basic_map_free(bmap); |
5117 | 7.27k | |
5118 | 7.27k | eq = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total); |
5119 | 7.27k | T = isl_mat_variable_compression(eq, &T2); |
5120 | 7.27k | if (!T || !T2) |
5121 | 0 | goto error; |
5122 | 7.27k | if (T->n_col == 0) { |
5123 | 1 | isl_mat_free(T); |
5124 | 1 | isl_mat_free(T2); |
5125 | 1 | isl_vec_free(v); |
5126 | 1 | return isl_basic_map_set_to_empty(bmap); |
5127 | 1 | } |
5128 | 7.27k | |
5129 | 7.27k | bmap = isl_basic_map_cow(bmap); |
5130 | 7.27k | if (!bmap) |
5131 | 0 | goto error; |
5132 | 7.27k | |
5133 | 7.27k | tightened = 0; |
5134 | 79.8k | for (i = 0; i < bmap->n_ineq; ++i72.6k ) { |
5135 | 72.6k | isl_seq_cpy(v->el, bmap->ineq[i], 1 + total); |
5136 | 72.6k | v = isl_vec_mat_product(v, isl_mat_copy(T)); |
5137 | 72.6k | v = normalize_constraint(v, &tightened); |
5138 | 72.6k | v = isl_vec_mat_product(v, isl_mat_copy(T2)); |
5139 | 72.6k | if (!v) |
5140 | 0 | goto error; |
5141 | 72.6k | isl_seq_cpy(bmap->ineq[i], v->el, 1 + total); |
5142 | 72.6k | } |
5143 | 7.27k | |
5144 | 7.27k | isl_mat_free(T); |
5145 | 7.27k | isl_mat_free(T2); |
5146 | 7.27k | isl_vec_free(v); |
5147 | 7.27k | |
5148 | 7.27k | ISL_F_SET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS); |
5149 | 7.27k | |
5150 | 7.27k | if (tightened) { |
5151 | 471 | int progress = 0; |
5152 | 471 | |
5153 | 471 | bmap = isl_basic_map_detect_inequality_pairs(bmap, &progress); |
5154 | 471 | if (progress) { |
5155 | 61 | bmap = eliminate_divs_eq(bmap, &progress); |
5156 | 61 | bmap = isl_basic_map_gauss(bmap, NULL); |
5157 | 61 | } |
5158 | 471 | } |
5159 | 7.27k | |
5160 | 7.27k | return bmap; |
5161 | 0 | error: |
5162 | 0 | isl_mat_free(T); |
5163 | 0 | isl_mat_free(T2); |
5164 | 0 | isl_vec_free(v); |
5165 | 0 | return isl_basic_map_free(bmap); |
5166 | 7.27k | } |
5167 | | |
5168 | | /* Shift the integer division at position "div" of "bmap" |
5169 | | * by "shift" times the variable at position "pos". |
5170 | | * "pos" is as determined by isl_basic_map_offset, i.e., pos == 0 |
5171 | | * corresponds to the constant term. |
5172 | | * |
5173 | | * That is, if the integer division has the form |
5174 | | * |
5175 | | * floor(f(x)/d) |
5176 | | * |
5177 | | * then replace it by |
5178 | | * |
5179 | | * floor((f(x) + shift * d * x_pos)/d) - shift * x_pos |
5180 | | */ |
5181 | | __isl_give isl_basic_map *isl_basic_map_shift_div( |
5182 | | __isl_take isl_basic_map *bmap, int div, int pos, isl_int shift) |
5183 | 17.7k | { |
5184 | 17.7k | int i; |
5185 | 17.7k | unsigned total; |
5186 | 17.7k | |
5187 | 17.7k | if (isl_int_is_zero(shift)) |
5188 | 17.7k | return bmap91 ; |
5189 | 17.6k | if (!bmap) |
5190 | 0 | return NULL; |
5191 | 17.6k | |
5192 | 17.6k | total = isl_basic_map_dim(bmap, isl_dim_all); |
5193 | 17.6k | total -= isl_basic_map_dim(bmap, isl_dim_div); |
5194 | 17.6k | |
5195 | 17.6k | isl_int_addmul(bmap->div[div][1 + pos], shift, bmap->div[div][0]); |
5196 | 17.6k | |
5197 | 67.0k | for (i = 0; i < bmap->n_eq; ++i49.4k ) { |
5198 | 49.4k | if (isl_int_is_zero(bmap->eq[i][1 + total + div])) |
5199 | 49.4k | continue34.4k ; |
5200 | 14.9k | isl_int_submul(bmap->eq[i][pos], |
5201 | 14.9k | shift, bmap->eq[i][1 + total + div]); |
5202 | 14.9k | } |
5203 | 138k | for (i = 0; i < bmap->n_ineq; ++i120k ) { |
5204 | 120k | if (isl_int_is_zero(bmap->ineq[i][1 + total + div])) |
5205 | 120k | continue106k ; |
5206 | 14.1k | isl_int_submul(bmap->ineq[i][pos], |
5207 | 14.1k | shift, bmap->ineq[i][1 + total + div]); |
5208 | 14.1k | } |
5209 | 58.4k | for (i = 0; i < bmap->n_div; ++i40.7k ) { |
5210 | 40.7k | if (isl_int_is_zero(bmap->div[i][0])) |
5211 | 40.7k | continue2.99k ; |
5212 | 37.7k | if (isl_int_is_zero(bmap->div[i][1 + 1 + total + div])) |
5213 | 37.7k | continue36.8k ; |
5214 | 910 | isl_int_submul(bmap->div[i][1 + pos], |
5215 | 910 | shift, bmap->div[i][1 + 1 + total + div]); |
5216 | 910 | } |
5217 | 17.6k | |
5218 | 17.6k | return bmap; |
5219 | 17.6k | } |