93f12e8267af26e0561fbed4425d923fd7b4111c
[platform/upstream/isl.git] / isl_dim.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  *
5  * Use of this software is governed by the GNU LGPLv2.1 license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
11  */
12
13 #include <stdlib.h>
14 #include <isl_dim_private.h>
15 #include <isl_id_private.h>
16 #include <isl_reordering.h>
17
18 isl_ctx *isl_dim_get_ctx(__isl_keep isl_dim *dim)
19 {
20         return dim ? dim->ctx : NULL;
21 }
22
23 struct isl_dim *isl_dim_alloc(struct isl_ctx *ctx,
24                         unsigned nparam, unsigned n_in, unsigned n_out)
25 {
26         struct isl_dim *dim;
27
28         dim = isl_alloc_type(ctx, struct isl_dim);
29         if (!dim)
30                 return NULL;
31
32         dim->ctx = ctx;
33         isl_ctx_ref(ctx);
34         dim->ref = 1;
35         dim->nparam = nparam;
36         dim->n_in = n_in;
37         dim->n_out = n_out;
38
39         dim->tuple_id[0] = NULL;
40         dim->tuple_id[1] = NULL;
41
42         dim->nested[0] = NULL;
43         dim->nested[1] = NULL;
44
45         dim->n_id = 0;
46         dim->ids = NULL;
47
48         return dim;
49 }
50
51 struct isl_dim *isl_dim_set_alloc(struct isl_ctx *ctx,
52                         unsigned nparam, unsigned dim)
53 {
54         return isl_dim_alloc(ctx, nparam, 0, dim);
55 }
56
57 static unsigned global_pos(struct isl_dim *dim,
58                                  enum isl_dim_type type, unsigned pos)
59 {
60         struct isl_ctx *ctx = dim->ctx;
61
62         switch (type) {
63         case isl_dim_param:
64                 isl_assert(ctx, pos < dim->nparam, return isl_dim_total(dim));
65                 return pos;
66         case isl_dim_in:
67                 isl_assert(ctx, pos < dim->n_in, return isl_dim_total(dim));
68                 return pos + dim->nparam;
69         case isl_dim_out:
70                 isl_assert(ctx, pos < dim->n_out, return isl_dim_total(dim));
71                 return pos + dim->nparam + dim->n_in;
72         default:
73                 isl_assert(ctx, 0, return isl_dim_total(dim));
74         }
75         return isl_dim_total(dim);
76 }
77
78 /* Extend length of ids array to the total number of dimensions.
79  */
80 static __isl_give isl_dim *extend_ids(__isl_take isl_dim *dim)
81 {
82         isl_id **ids;
83         int i;
84
85         if (isl_dim_total(dim) <= dim->n_id)
86                 return dim;
87
88         if (!dim->ids) {
89                 dim->ids = isl_calloc_array(dim->ctx,
90                                 isl_id *, isl_dim_total(dim));
91                 if (!dim->ids)
92                         goto error;
93         } else {
94                 ids = isl_realloc_array(dim->ctx, dim->ids,
95                                 isl_id *, isl_dim_total(dim));
96                 if (!ids)
97                         goto error;
98                 dim->ids = ids;
99                 for (i = dim->n_id; i < isl_dim_total(dim); ++i)
100                         dim->ids[i] = NULL;
101         }
102
103         dim->n_id = isl_dim_total(dim);
104
105         return dim;
106 error:
107         isl_dim_free(dim);
108         return NULL;
109 }
110
111 static __isl_give isl_dim *set_id(__isl_take isl_dim *dim,
112         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
113 {
114         dim = isl_dim_cow(dim);
115
116         if (!dim)
117                 goto error;
118
119         pos = global_pos(dim, type, pos);
120         if (pos == isl_dim_total(dim))
121                 goto error;
122
123         if (pos >= dim->n_id) {
124                 if (!id)
125                         return dim;
126                 dim = extend_ids(dim);
127                 if (!dim)
128                         goto error;
129         }
130
131         dim->ids[pos] = id;
132
133         return dim;
134 error:
135         isl_id_free(id);
136         isl_dim_free(dim);
137         return NULL;
138 }
139
140 static __isl_keep isl_id *get_id(__isl_keep isl_dim *dim,
141                                  enum isl_dim_type type, unsigned pos)
142 {
143         if (!dim)
144                 return NULL;
145
146         pos = global_pos(dim, type, pos);
147         if (pos == isl_dim_total(dim))
148                 return NULL;
149         if (pos >= dim->n_id)
150                 return NULL;
151         return dim->ids[pos];
152 }
153
154 static unsigned offset(struct isl_dim *dim, enum isl_dim_type type)
155 {
156         switch (type) {
157         case isl_dim_param:     return 0;
158         case isl_dim_in:        return dim->nparam;
159         case isl_dim_out:       return dim->nparam + dim->n_in;
160         default:                return 0;
161         }
162 }
163
164 static unsigned n(struct isl_dim *dim, enum isl_dim_type type)
165 {
166         switch (type) {
167         case isl_dim_param:     return dim->nparam;
168         case isl_dim_in:        return dim->n_in;
169         case isl_dim_out:       return dim->n_out;
170         case isl_dim_all:       return dim->nparam + dim->n_in + dim->n_out;
171         default:                return 0;
172         }
173 }
174
175 unsigned isl_dim_size(struct isl_dim *dim, enum isl_dim_type type)
176 {
177         if (!dim)
178                 return 0;
179         return n(dim, type);
180 }
181
182 unsigned isl_dim_offset(__isl_keep isl_dim *dim, enum isl_dim_type type)
183 {
184         if (!dim)
185                 return 0;
186         return offset(dim, type);
187 }
188
189 static __isl_give isl_dim *copy_ids(__isl_take isl_dim *dst,
190         enum isl_dim_type dst_type, unsigned offset, __isl_keep isl_dim *src,
191         enum isl_dim_type src_type)
192 {
193         int i;
194         isl_id *id;
195
196         if (!dst)
197                 return NULL;
198
199         for (i = 0; i < n(src, src_type); ++i) {
200                 id = get_id(src, src_type, i);
201                 if (!id)
202                         continue;
203                 dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
204                 if (!dst)
205                         return NULL;
206         }
207         return dst;
208 }
209
210 struct isl_dim *isl_dim_dup(struct isl_dim *dim)
211 {
212         struct isl_dim *dup;
213         if (!dim)
214                 return NULL;
215         dup = isl_dim_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
216         if (dim->tuple_id[0] &&
217             !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
218                 goto error;
219         if (dim->tuple_id[1] &&
220             !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
221                 goto error;
222         if (dim->nested[0] && !(dup->nested[0] = isl_dim_copy(dim->nested[0])))
223                 goto error;
224         if (dim->nested[1] && !(dup->nested[1] = isl_dim_copy(dim->nested[1])))
225                 goto error;
226         if (!dim->ids)
227                 return dup;
228         dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
229         dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
230         dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
231         return dup;
232 error:
233         isl_dim_free(dup);
234         return NULL;
235 }
236
237 struct isl_dim *isl_dim_cow(struct isl_dim *dim)
238 {
239         if (!dim)
240                 return NULL;
241
242         if (dim->ref == 1)
243                 return dim;
244         dim->ref--;
245         return isl_dim_dup(dim);
246 }
247
248 struct isl_dim *isl_dim_copy(struct isl_dim *dim)
249 {
250         if (!dim)
251                 return NULL;
252
253         dim->ref++;
254         return dim;
255 }
256
257 void isl_dim_free(struct isl_dim *dim)
258 {
259         int i;
260
261         if (!dim)
262                 return;
263
264         if (--dim->ref > 0)
265                 return;
266
267         isl_id_free(dim->tuple_id[0]);
268         isl_id_free(dim->tuple_id[1]);
269
270         isl_dim_free(dim->nested[0]);
271         isl_dim_free(dim->nested[1]);
272
273         for (i = 0; i < dim->n_id; ++i)
274                 isl_id_free(dim->ids[i]);
275         free(dim->ids);
276         isl_ctx_deref(dim->ctx);
277         
278         free(dim);
279 }
280
281 static int name_ok(isl_ctx *ctx, const char *s)
282 {
283         char *p;
284         long dummy;
285
286         dummy = strtol(s, &p, 0);
287         if (p != s)
288                 isl_die(ctx, isl_error_invalid, "name looks like a number",
289                         return 0);
290
291         return 1;
292 }
293
294 int isl_dim_has_tuple_id(__isl_keep isl_dim *dim, enum isl_dim_type type)
295 {
296         if (!dim)
297                 return -1;
298         if (type != isl_dim_in && type != isl_dim_out)
299                 isl_die(dim->ctx, isl_error_invalid,
300                         "only input, output and set tuples can have ids",
301                         return -1);
302         return dim->tuple_id[type - isl_dim_in] != NULL;
303 }
304
305 __isl_give isl_id *isl_dim_get_tuple_id(__isl_keep isl_dim *dim,
306         enum isl_dim_type type)
307 {
308         if (!dim)
309                 return NULL;
310         if (type != isl_dim_in && type != isl_dim_out)
311                 return NULL;
312         return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
313 }
314
315 __isl_give isl_dim *isl_dim_set_tuple_id(__isl_take isl_dim *dim,
316         enum isl_dim_type type, __isl_take isl_id *id)
317 {
318         dim = isl_dim_cow(dim);
319         if (!dim || !id)
320                 goto error;
321         if (type != isl_dim_in && type != isl_dim_out)
322                 isl_die(dim->ctx, isl_error_invalid,
323                         "only input, output and set tuples can have names",
324                         goto error);
325
326         isl_id_free(dim->tuple_id[type - isl_dim_in]);
327         dim->tuple_id[type - isl_dim_in] = id;
328
329         return dim;
330 error:
331         isl_id_free(id);
332         isl_dim_free(dim);
333         return NULL;
334 }
335
336 __isl_give isl_dim *isl_dim_reset_tuple_id(__isl_take isl_dim *dim,
337         enum isl_dim_type type)
338 {
339         dim = isl_dim_cow(dim);
340         if (!dim)
341                 return NULL;
342         if (type != isl_dim_in && type != isl_dim_out)
343                 isl_die(dim->ctx, isl_error_invalid,
344                         "only input, output and set tuples can have names",
345                         goto error);
346
347         isl_id_free(dim->tuple_id[type - isl_dim_in]);
348         dim->tuple_id[type - isl_dim_in] = NULL;
349
350         return dim;
351 error:
352         isl_dim_free(dim);
353         return NULL;
354 }
355
356 __isl_give isl_dim *isl_dim_set_dim_id(__isl_take isl_dim *dim,
357         enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
358 {
359         dim = isl_dim_cow(dim);
360         if (!dim || !id)
361                 goto error;
362         isl_id_free(get_id(dim, type, pos));
363         return set_id(dim, type, pos, id);
364 error:
365         isl_id_free(id);
366         isl_dim_free(dim);
367         return NULL;
368 }
369
370 int isl_dim_has_dim_id(__isl_keep isl_dim *dim,
371         enum isl_dim_type type, unsigned pos)
372 {
373         if (!dim)
374                 return -1;
375         return get_id(dim, type, pos) != NULL;
376 }
377
378 __isl_give isl_id *isl_dim_get_dim_id(__isl_keep isl_dim *dim,
379         enum isl_dim_type type, unsigned pos)
380 {
381         if (!dim)
382                 return NULL;
383         if (!get_id(dim, type, pos))
384                 isl_die(dim->ctx, isl_error_invalid,
385                         "dim has no id", return NULL);
386         return isl_id_copy(get_id(dim, type, pos));
387 }
388
389 __isl_give isl_dim *isl_dim_set_tuple_name(__isl_take isl_dim *dim,
390         enum isl_dim_type type, const char *s)
391 {
392         isl_id *id;
393
394         if (!dim)
395                 return NULL;
396
397         if (!s)
398                 return isl_dim_reset_tuple_id(dim, type);
399
400         if (!name_ok(dim->ctx, s))
401                 goto error;
402
403         id = isl_id_alloc(dim->ctx, s, NULL);
404         return isl_dim_set_tuple_id(dim, type, id);
405 error:
406         isl_dim_free(dim);
407         return NULL;
408 }
409
410 const char *isl_dim_get_tuple_name(__isl_keep isl_dim *dim,
411          enum isl_dim_type type)
412 {
413         isl_id *id;
414         if (!dim)
415                 return NULL;
416         if (type != isl_dim_in && type != isl_dim_out)
417                 return NULL;
418         id = dim->tuple_id[type - isl_dim_in];
419         return id ? id->name : NULL;
420 }
421
422 struct isl_dim *isl_dim_set_name(struct isl_dim *dim,
423                                  enum isl_dim_type type, unsigned pos,
424                                  const char *s)
425 {
426         isl_id *id;
427
428         if (!dim)
429                 return NULL;
430         if (!name_ok(dim->ctx, s))
431                 goto error;
432         id = isl_id_alloc(dim->ctx, s, NULL);
433         return isl_dim_set_dim_id(dim, type, pos, id);
434 error:
435         isl_dim_free(dim);
436         return NULL;
437 }
438
439 const char *isl_dim_get_name(struct isl_dim *dim,
440                                  enum isl_dim_type type, unsigned pos)
441 {
442         isl_id *id = get_id(dim, type, pos);
443         return id ? id->name : NULL;
444 }
445
446 int isl_dim_find_dim_by_id(__isl_keep isl_dim *dim, enum isl_dim_type type,
447         __isl_keep isl_id *id)
448 {
449         int i;
450         int offset;
451         int n;
452
453         if (!dim || !id)
454                 return -1;
455
456         offset = isl_dim_offset(dim, type);
457         n = isl_dim_size(dim, type);
458         for (i = 0; i < n && offset + i < dim->n_id; ++i)
459                 if (dim->ids[offset + i] == id)
460                         return i;
461
462         return -1;
463 }
464
465 static __isl_keep isl_id *tuple_id(__isl_keep isl_dim *dim,
466         enum isl_dim_type type)
467 {
468         if (!dim)
469                 return NULL;
470         if (type == isl_dim_in)
471                 return dim->tuple_id[0];
472         if (type == isl_dim_out)
473                 return dim->tuple_id[1];
474         return NULL;
475 }
476
477 static __isl_keep isl_dim *nested(__isl_keep isl_dim *dim,
478         enum isl_dim_type type)
479 {
480         if (!dim)
481                 return NULL;
482         if (type == isl_dim_in)
483                 return dim->nested[0];
484         if (type == isl_dim_out)
485                 return dim->nested[1];
486         return NULL;
487 }
488
489 int isl_dim_tuple_match(__isl_keep isl_dim *dim1, enum isl_dim_type dim1_type,
490                         __isl_keep isl_dim *dim2, enum isl_dim_type dim2_type)
491 {
492         isl_id *id1, *id2;
493         isl_dim *nested1, *nested2;
494
495         if (!dim1 || !dim2)
496                 return -1;
497
498         if (n(dim1, dim1_type) != n(dim2, dim2_type))
499                 return 0;
500         id1 = tuple_id(dim1, dim1_type);
501         id2 = tuple_id(dim2, dim2_type);
502         if (!id1 ^ !id2)
503                 return 0;
504         if (id1 && id1 != id2)
505                 return 0;
506         nested1 = nested(dim1, dim1_type);
507         nested2 = nested(dim2, dim2_type);
508         if (!nested1 ^ !nested2)
509                 return 0;
510         if (nested1 && !isl_dim_equal(nested1, nested2))
511                 return 0;
512         return 1;
513 }
514
515 static int match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
516                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
517 {
518         int i;
519
520         if (!isl_dim_tuple_match(dim1, dim1_type, dim2, dim2_type))
521                 return 0;
522
523         if (!dim1->ids && !dim2->ids)
524                 return 1;
525
526         for (i = 0; i < n(dim1, dim1_type); ++i) {
527                 if (get_id(dim1, dim1_type, i) != get_id(dim2, dim2_type, i))
528                         return 0;
529         }
530         return 1;
531 }
532
533 int isl_dim_match(struct isl_dim *dim1, enum isl_dim_type dim1_type,
534                 struct isl_dim *dim2, enum isl_dim_type dim2_type)
535 {
536         return match(dim1, dim1_type, dim2, dim2_type);
537 }
538
539 static void get_ids(struct isl_dim *dim, enum isl_dim_type type,
540         unsigned first, unsigned n, __isl_keep isl_id **ids)
541 {
542         int i;
543
544         for (i = 0; i < n ; ++i)
545                 ids[i] = get_id(dim, type, first + i);
546 }
547
548 struct isl_dim *isl_dim_extend(struct isl_dim *dim,
549                         unsigned nparam, unsigned n_in, unsigned n_out)
550 {
551         isl_id **ids = NULL;
552
553         if (!dim)
554                 return NULL;
555         if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out)
556                 return dim;
557
558         isl_assert(dim->ctx, dim->nparam <= nparam, goto error);
559         isl_assert(dim->ctx, dim->n_in <= n_in, goto error);
560         isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
561
562         dim = isl_dim_cow(dim);
563
564         if (dim->ids) {
565                 ids = isl_calloc_array(dim->ctx, isl_id *,
566                                          nparam + n_in + n_out);
567                 if (!ids)
568                         goto error;
569                 get_ids(dim, isl_dim_param, 0, dim->nparam, ids);
570                 get_ids(dim, isl_dim_in, 0, dim->n_in, ids + nparam);
571                 get_ids(dim, isl_dim_out, 0, dim->n_out, ids + nparam + n_in);
572                 free(dim->ids);
573                 dim->ids = ids;
574                 dim->n_id = nparam + n_in + n_out;
575         }
576         dim->nparam = nparam;
577         dim->n_in = n_in;
578         dim->n_out = n_out;
579
580         return dim;
581 error:
582         free(ids);
583         isl_dim_free(dim);
584         return NULL;
585 }
586
587 struct isl_dim *isl_dim_add(struct isl_dim *dim, enum isl_dim_type type,
588         unsigned n)
589 {
590         if (!dim)
591                 return NULL;
592         dim = isl_dim_reset(dim, type);
593         switch (type) {
594         case isl_dim_param:
595                 dim = isl_dim_extend(dim,
596                                         dim->nparam + n, dim->n_in, dim->n_out);
597                 if (dim && dim->nested[0] &&
598                     !(dim->nested[0] = isl_dim_add(dim->nested[0],
599                                                     isl_dim_param, n)))
600                         goto error;
601                 if (dim && dim->nested[1] &&
602                     !(dim->nested[1] = isl_dim_add(dim->nested[1],
603                                                     isl_dim_param, n)))
604                         goto error;
605                 return dim;
606         case isl_dim_in:
607                 return isl_dim_extend(dim,
608                                         dim->nparam, dim->n_in + n, dim->n_out);
609         case isl_dim_out:
610                 return isl_dim_extend(dim,
611                                         dim->nparam, dim->n_in, dim->n_out + n);
612         default:
613                 isl_die(dim->ctx, isl_error_invalid,
614                         "cannot add dimensions of specified type", goto error);
615         }
616 error:
617         isl_dim_free(dim);
618         return NULL;
619 }
620
621 static int valid_dim_type(enum isl_dim_type type)
622 {
623         switch (type) {
624         case isl_dim_param:
625         case isl_dim_in:
626         case isl_dim_out:
627                 return 1;
628         default:
629                 return 0;
630         }
631 }
632
633 __isl_give isl_dim *isl_dim_insert(__isl_take isl_dim *dim,
634         enum isl_dim_type type, unsigned pos, unsigned n)
635 {
636         isl_id **ids = NULL;
637
638         if (!dim)
639                 return NULL;
640         if (n == 0)
641                 return isl_dim_reset(dim, type);
642
643         if (!valid_dim_type(type))
644                 isl_die(dim->ctx, isl_error_invalid,
645                         "cannot insert dimensions of specified type",
646                         goto error);
647
648         isl_assert(dim->ctx, pos <= isl_dim_size(dim, type), goto error);
649
650         dim = isl_dim_cow(dim);
651         if (!dim)
652                 return NULL;
653
654         if (dim->ids) {
655                 enum isl_dim_type t;
656                 int off;
657                 int s[3];
658                 int *size = s - isl_dim_param;
659                 ids = isl_calloc_array(dim->ctx, isl_id *,
660                                      dim->nparam + dim->n_in + dim->n_out + n);
661                 if (!ids)
662                         goto error;
663                 off = 0;
664                 size[isl_dim_param] = dim->nparam;
665                 size[isl_dim_in] = dim->n_in;
666                 size[isl_dim_out] = dim->n_out;
667                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
668                         if (t != type) {
669                                 get_ids(dim, t, 0, size[t], ids + off);
670                                 off += size[t];
671                         } else {
672                                 get_ids(dim, t, 0, pos, ids + off);
673                                 off += pos + n;
674                                 get_ids(dim, t, pos, size[t] - pos, ids + off);
675                                 off += size[t] - pos;
676                         }
677                 }
678                 free(dim->ids);
679                 dim->ids = ids;
680                 dim->n_id = dim->nparam + dim->n_in + dim->n_out + n;
681         }
682         switch (type) {
683         case isl_dim_param:     dim->nparam += n; break;
684         case isl_dim_in:        dim->n_in += n; break;
685         case isl_dim_out:       dim->n_out += n; break;
686         default:                ;
687         }
688         dim = isl_dim_reset(dim, type);
689
690         return dim;
691 error:
692         isl_dim_free(dim);
693         return NULL;
694 }
695
696 __isl_give isl_dim *isl_dim_move(__isl_take isl_dim *dim,
697         enum isl_dim_type dst_type, unsigned dst_pos,
698         enum isl_dim_type src_type, unsigned src_pos, unsigned n)
699 {
700         int i;
701
702         if (!dim)
703                 return NULL;
704         if (n == 0)
705                 return dim;
706
707         isl_assert(dim->ctx, src_pos + n <= isl_dim_size(dim, src_type),
708                 goto error);
709
710         if (dst_type == src_type && dst_pos == src_pos)
711                 return dim;
712
713         isl_assert(dim->ctx, dst_type != src_type, goto error);
714
715         dim = isl_dim_reset(dim, src_type);
716         dim = isl_dim_reset(dim, dst_type);
717
718         dim = isl_dim_cow(dim);
719         if (!dim)
720                 return NULL;
721
722         if (dim->ids) {
723                 isl_id **ids;
724                 enum isl_dim_type t;
725                 int off;
726                 int s[3];
727                 int *size = s - isl_dim_param;
728                 ids = isl_calloc_array(dim->ctx, isl_id *,
729                                          dim->nparam + dim->n_in + dim->n_out);
730                 if (!ids)
731                         goto error;
732                 off = 0;
733                 size[isl_dim_param] = dim->nparam;
734                 size[isl_dim_in] = dim->n_in;
735                 size[isl_dim_out] = dim->n_out;
736                 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
737                         if (t == dst_type) {
738                                 get_ids(dim, t, 0, dst_pos, ids + off);
739                                 off += dst_pos;
740                                 get_ids(dim, src_type, src_pos, n, ids + off);
741                                 off += n;
742                                 get_ids(dim, t, dst_pos, size[t] - dst_pos,
743                                                 ids + off);
744                                 off += size[t] - dst_pos;
745                         } else if (t == src_type) {
746                                 get_ids(dim, t, 0, src_pos, ids + off);
747                                 off += src_pos;
748                                 get_ids(dim, t, src_pos + n,
749                                             size[t] - src_pos - n, ids + off);
750                                 off += size[t] - src_pos - n;
751                         } else {
752                                 get_ids(dim, t, 0, size[t], ids + off);
753                                 off += size[t];
754                         }
755                 }
756                 free(dim->ids);
757                 dim->ids = ids;
758                 dim->n_id = dim->nparam + dim->n_in + dim->n_out;
759         }
760
761         switch (dst_type) {
762         case isl_dim_param:     dim->nparam += n; break;
763         case isl_dim_in:        dim->n_in += n; break;
764         case isl_dim_out:       dim->n_out += n; break;
765         default:                ;
766         }
767
768         switch (src_type) {
769         case isl_dim_param:     dim->nparam -= n; break;
770         case isl_dim_in:        dim->n_in -= n; break;
771         case isl_dim_out:       dim->n_out -= n; break;
772         default:                ;
773         }
774
775         if (dst_type != isl_dim_param && src_type != isl_dim_param)
776                 return dim;
777
778         for (i = 0; i < 2; ++i) {
779                 if (!dim->nested[i])
780                         continue;
781                 dim->nested[i] = isl_dim_replace(dim->nested[i],
782                                                  isl_dim_param, dim);
783                 if (!dim->nested[i])
784                         goto error;
785         }
786
787         return dim;
788 error:
789         isl_dim_free(dim);
790         return NULL;
791 }
792
793 struct isl_dim *isl_dim_join(struct isl_dim *left, struct isl_dim *right)
794 {
795         struct isl_dim *dim;
796
797         if (!left || !right)
798                 goto error;
799
800         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
801                         goto error);
802         isl_assert(left->ctx,
803                 isl_dim_tuple_match(left, isl_dim_out, right, isl_dim_in),
804                 goto error);
805
806         dim = isl_dim_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
807         if (!dim)
808                 goto error;
809
810         dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
811         dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
812         dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
813
814         if (dim && left->tuple_id[0] &&
815             !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
816                 goto error;
817         if (dim && right->tuple_id[1] &&
818             !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
819                 goto error;
820         if (dim && left->nested[0] &&
821             !(dim->nested[0] = isl_dim_copy(left->nested[0])))
822                 goto error;
823         if (dim && right->nested[1] &&
824             !(dim->nested[1] = isl_dim_copy(right->nested[1])))
825                 goto error;
826
827         isl_dim_free(left);
828         isl_dim_free(right);
829
830         return dim;
831 error:
832         isl_dim_free(left);
833         isl_dim_free(right);
834         return NULL;
835 }
836
837 struct isl_dim *isl_dim_product(struct isl_dim *left, struct isl_dim *right)
838 {
839         isl_dim *dom1, *dom2, *nest1, *nest2;
840
841         if (!left || !right)
842                 goto error;
843
844         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
845                         goto error);
846
847         dom1 = isl_dim_domain(isl_dim_copy(left));
848         dom2 = isl_dim_domain(isl_dim_copy(right));
849         nest1 = isl_dim_wrap(isl_dim_join(isl_dim_reverse(dom1), dom2));
850
851         dom1 = isl_dim_range(left);
852         dom2 = isl_dim_range(right);
853         nest2 = isl_dim_wrap(isl_dim_join(isl_dim_reverse(dom1), dom2));
854
855         return isl_dim_join(isl_dim_reverse(nest1), nest2);
856 error:
857         isl_dim_free(left);
858         isl_dim_free(right);
859         return NULL;
860 }
861
862 __isl_give isl_dim *isl_dim_range_product(__isl_take isl_dim *left,
863         __isl_take isl_dim *right)
864 {
865         isl_dim *dom, *ran1, *ran2, *nest;
866
867         if (!left || !right)
868                 goto error;
869
870         isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
871                         goto error);
872         if (!isl_dim_tuple_match(left, isl_dim_in, right, isl_dim_in))
873                 isl_die(left->ctx, isl_error_invalid,
874                         "domains need to match", goto error);
875
876         dom = isl_dim_domain(isl_dim_copy(left));
877
878         ran1 = isl_dim_range(left);
879         ran2 = isl_dim_range(right);
880         nest = isl_dim_wrap(isl_dim_join(isl_dim_reverse(ran1), ran2));
881
882         return isl_dim_join(isl_dim_reverse(dom), nest);
883 error:
884         isl_dim_free(left);
885         isl_dim_free(right);
886         return NULL;
887 }
888
889 __isl_give isl_dim *isl_dim_map_from_set(__isl_take isl_dim *dim)
890 {
891         isl_id **ids = NULL;
892
893         if (!dim)
894                 return NULL;
895         isl_assert(dim->ctx, dim->n_in == 0, goto error);
896         if (dim->n_out == 0 && !isl_dim_is_named_or_nested(dim, isl_dim_out))
897                 return dim;
898         dim = isl_dim_cow(dim);
899         if (!dim)
900                 return NULL;
901         if (dim->ids) {
902                 ids = isl_calloc_array(dim->ctx, isl_id *,
903                                         dim->nparam + dim->n_out + dim->n_out);
904                 if (!ids)
905                         goto error;
906                 get_ids(dim, isl_dim_param, 0, dim->nparam, ids);
907                 get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->nparam);
908         }
909         dim->n_in = dim->n_out;
910         if (ids) {
911                 free(dim->ids);
912                 dim->ids = ids;
913                 dim->n_id = dim->nparam + dim->n_out + dim->n_out;
914                 dim = copy_ids(dim, isl_dim_out, 0, dim, isl_dim_in);
915         }
916         isl_id_free(dim->tuple_id[0]);
917         dim->tuple_id[0] = isl_id_copy(dim->tuple_id[1]);
918         isl_dim_free(dim->nested[0]);
919         dim->nested[0] = isl_dim_copy(dim->nested[1]);
920         return dim;
921 error:
922         isl_dim_free(dim);
923         return NULL;
924 }
925
926 static __isl_give isl_dim *set_ids(struct isl_dim *dim, enum isl_dim_type type,
927         unsigned first, unsigned n, __isl_take isl_id **ids)
928 {
929         int i;
930
931         for (i = 0; i < n ; ++i)
932                 dim = set_id(dim, type, first + i, ids[i]);
933
934         return dim;
935 }
936
937 struct isl_dim *isl_dim_reverse(struct isl_dim *dim)
938 {
939         unsigned t;
940         isl_dim *nested;
941         isl_id **ids = NULL;
942         isl_id *id;
943
944         if (!dim)
945                 return NULL;
946         if (match(dim, isl_dim_in, dim, isl_dim_out))
947                 return dim;
948
949         dim = isl_dim_cow(dim);
950         if (!dim)
951                 return NULL;
952
953         id = dim->tuple_id[0];
954         dim->tuple_id[0] = dim->tuple_id[1];
955         dim->tuple_id[1] = id;
956
957         nested = dim->nested[0];
958         dim->nested[0] = dim->nested[1];
959         dim->nested[1] = nested;
960
961         if (dim->ids) {
962                 ids = isl_alloc_array(dim->ctx, isl_id *,
963                                         dim->n_in + dim->n_out);
964                 if (!ids)
965                         goto error;
966                 get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
967                 get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
968         }
969
970         t = dim->n_in;
971         dim->n_in = dim->n_out;
972         dim->n_out = t;
973
974         if (dim->ids) {
975                 dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
976                 dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
977                 free(ids);
978         }
979
980         return dim;
981 error:
982         free(ids);
983         isl_dim_free(dim);
984         return NULL;
985 }
986
987 struct isl_dim *isl_dim_drop(struct isl_dim *dim, enum isl_dim_type type,
988                 unsigned first, unsigned num)
989 {
990         int i;
991
992         if (!dim)
993                 return NULL;
994
995         if (num == 0)
996                 return isl_dim_reset(dim, type);
997
998         if (!valid_dim_type(type))
999                 isl_die(dim->ctx, isl_error_invalid,
1000                         "cannot drop dimensions of specified type", goto error);
1001
1002         isl_assert(dim->ctx, first + num <= n(dim, type), goto error);
1003         dim = isl_dim_cow(dim);
1004         if (!dim)
1005                 goto error;
1006         if (dim->ids) {
1007                 dim = extend_ids(dim);
1008                 if (!dim)
1009                         goto error;
1010                 for (i = 0; i < num; ++i)
1011                         isl_id_free(get_id(dim, type, first + i));
1012                 for (i = first+num; i < n(dim, type); ++i)
1013                         set_id(dim, type, i - num, get_id(dim, type, i));
1014                 switch (type) {
1015                 case isl_dim_param:
1016                         get_ids(dim, isl_dim_in, 0, dim->n_in,
1017                                 dim->ids + offset(dim, isl_dim_in) - num);
1018                 case isl_dim_in:
1019                         get_ids(dim, isl_dim_out, 0, dim->n_out,
1020                                 dim->ids + offset(dim, isl_dim_out) - num);
1021                 default:
1022                         ;
1023                 }
1024                 dim->n_id -= num;
1025         }
1026         switch (type) {
1027         case isl_dim_param:     dim->nparam -= num; break;
1028         case isl_dim_in:        dim->n_in -= num; break;
1029         case isl_dim_out:       dim->n_out -= num; break;
1030         default:                ;
1031         }
1032         dim = isl_dim_reset(dim, type);
1033         if (type == isl_dim_param) {
1034                 if (dim && dim->nested[0] &&
1035                     !(dim->nested[0] = isl_dim_drop(dim->nested[0],
1036                                                     isl_dim_param, first, num)))
1037                         goto error;
1038                 if (dim && dim->nested[1] &&
1039                     !(dim->nested[1] = isl_dim_drop(dim->nested[1],
1040                                                     isl_dim_param, first, num)))
1041                         goto error;
1042         }
1043         return dim;
1044 error:
1045         isl_dim_free(dim);
1046         return NULL;
1047 }
1048
1049 struct isl_dim *isl_dim_drop_inputs(struct isl_dim *dim,
1050                 unsigned first, unsigned n)
1051 {
1052         if (!dim)
1053                 return NULL;
1054         return isl_dim_drop(dim, isl_dim_in, first, n);
1055 }
1056
1057 struct isl_dim *isl_dim_drop_outputs(struct isl_dim *dim,
1058                 unsigned first, unsigned n)
1059 {
1060         if (!dim)
1061                 return NULL;
1062         return isl_dim_drop(dim, isl_dim_out, first, n);
1063 }
1064
1065 struct isl_dim *isl_dim_domain(struct isl_dim *dim)
1066 {
1067         if (!dim)
1068                 return NULL;
1069         dim = isl_dim_drop_outputs(dim, 0, dim->n_out);
1070         return isl_dim_reverse(dim);
1071 }
1072
1073 __isl_give isl_dim *isl_dim_from_domain(__isl_take isl_dim *dim)
1074 {
1075         return isl_dim_reverse(dim);
1076 }
1077
1078 struct isl_dim *isl_dim_range(struct isl_dim *dim)
1079 {
1080         if (!dim)
1081                 return NULL;
1082         return isl_dim_drop_inputs(dim, 0, dim->n_in);
1083 }
1084
1085 __isl_give isl_dim *isl_dim_from_range(__isl_take isl_dim *dim)
1086 {
1087         return dim;
1088 }
1089
1090 __isl_give isl_dim *isl_dim_as_set_dim(__isl_take isl_dim *dim)
1091 {
1092         dim = isl_dim_cow(dim);
1093         if (!dim)
1094                 return NULL;
1095
1096         dim->n_out += dim->n_in;
1097         dim->n_in = 0;
1098         dim = isl_dim_reset(dim, isl_dim_in);
1099         dim = isl_dim_reset(dim, isl_dim_out);
1100
1101         return dim;
1102 }
1103
1104 struct isl_dim *isl_dim_underlying(struct isl_dim *dim, unsigned n_div)
1105 {
1106         int i;
1107
1108         if (!dim)
1109                 return NULL;
1110         if (n_div == 0 &&
1111             dim->nparam == 0 && dim->n_in == 0 && dim->n_id == 0)
1112                 return isl_dim_reset(isl_dim_reset(dim, isl_dim_in), isl_dim_out);
1113         dim = isl_dim_cow(dim);
1114         if (!dim)
1115                 return NULL;
1116         dim->n_out += dim->nparam + dim->n_in + n_div;
1117         dim->nparam = 0;
1118         dim->n_in = 0;
1119
1120         for (i = 0; i < dim->n_id; ++i)
1121                 isl_id_free(get_id(dim, isl_dim_out, i));
1122         dim->n_id = 0;
1123         dim = isl_dim_reset(dim, isl_dim_in);
1124         dim = isl_dim_reset(dim, isl_dim_out);
1125
1126         return dim;
1127 }
1128
1129 unsigned isl_dim_total(struct isl_dim *dim)
1130 {
1131         return dim ? dim->nparam + dim->n_in + dim->n_out : 0;
1132 }
1133
1134 int isl_dim_equal(struct isl_dim *dim1, struct isl_dim *dim2)
1135 {
1136         if (!dim1 || !dim2)
1137                 return -1;
1138         return match(dim1, isl_dim_param, dim2, isl_dim_param) &&
1139                isl_dim_tuple_match(dim1, isl_dim_in, dim2, isl_dim_in) &&
1140                isl_dim_tuple_match(dim1, isl_dim_out, dim2, isl_dim_out);
1141 }
1142
1143 int isl_dim_compatible(struct isl_dim *dim1, struct isl_dim *dim2)
1144 {
1145         return dim1->nparam == dim2->nparam &&
1146                dim1->n_in + dim1->n_out == dim2->n_in + dim2->n_out;
1147 }
1148
1149 static uint32_t isl_hash_dim(uint32_t hash, __isl_keep isl_dim *dim)
1150 {
1151         int i;
1152         isl_id *id;
1153
1154         if (!dim)
1155                 return hash;
1156
1157         hash = isl_hash_builtin(hash, dim->nparam);
1158         hash = isl_hash_builtin(hash, dim->n_in);
1159         hash = isl_hash_builtin(hash, dim->n_out);
1160
1161         for (i = 0; i < dim->nparam; ++i) {
1162                 id = get_id(dim, isl_dim_param, i);
1163                 hash = isl_hash_id(hash, id);
1164         }
1165
1166         id = tuple_id(dim, isl_dim_in);
1167         hash = isl_hash_id(hash, id);
1168         id = tuple_id(dim, isl_dim_out);
1169         hash = isl_hash_id(hash, id);
1170
1171         hash = isl_hash_dim(hash, dim->nested[0]);
1172         hash = isl_hash_dim(hash, dim->nested[1]);
1173
1174         return hash;
1175 }
1176
1177 uint32_t isl_dim_get_hash(__isl_keep isl_dim *dim)
1178 {
1179         uint32_t hash;
1180
1181         if (!dim)
1182                 return 0;
1183
1184         hash = isl_hash_init();
1185         hash = isl_hash_dim(hash, dim);
1186
1187         return hash;
1188 }
1189
1190 int isl_dim_is_wrapping(__isl_keep isl_dim *dim)
1191 {
1192         if (!dim)
1193                 return -1;
1194
1195         if (dim->n_in != 0 || dim->tuple_id[0] || dim->nested[0])
1196                 return 0;
1197
1198         return dim->nested[1] != NULL;
1199 }
1200
1201 __isl_give isl_dim *isl_dim_wrap(__isl_take isl_dim *dim)
1202 {
1203         isl_dim *wrap;
1204
1205         if (!dim)
1206                 return NULL;
1207
1208         wrap = isl_dim_alloc(dim->ctx, dim->nparam, 0, dim->n_in + dim->n_out);
1209
1210         wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
1211         wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
1212         wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
1213
1214         if (!wrap)
1215                 goto error;
1216
1217         wrap->nested[1] = dim;
1218
1219         return wrap;
1220 error:
1221         isl_dim_free(dim);
1222         return NULL;
1223 }
1224
1225 __isl_give isl_dim *isl_dim_unwrap(__isl_take isl_dim *dim)
1226 {
1227         isl_dim *unwrap;
1228
1229         if (!dim)
1230                 return NULL;
1231
1232         if (!isl_dim_is_wrapping(dim))
1233                 isl_die(dim->ctx, isl_error_invalid, "not a wrapping dim",
1234                         goto error);
1235
1236         unwrap = isl_dim_copy(dim->nested[1]);
1237         isl_dim_free(dim);
1238
1239         return unwrap;
1240 error:
1241         isl_dim_free(dim);
1242         return NULL;
1243 }
1244
1245 int isl_dim_is_named_or_nested(__isl_keep isl_dim *dim, enum isl_dim_type type)
1246 {
1247         if (type != isl_dim_in && type != isl_dim_out)
1248                 return 0;
1249         if (!dim)
1250                 return -1;
1251         if (dim->tuple_id[type - isl_dim_in])
1252                 return 1;
1253         if (dim->nested[type - isl_dim_in])
1254                 return 1;
1255         return 0;
1256 }
1257
1258 int isl_dim_may_be_set(__isl_keep isl_dim *dim)
1259 {
1260         if (!dim)
1261                 return -1;
1262         if (isl_dim_size(dim, isl_dim_in) != 0)
1263                 return 0;
1264         if (isl_dim_is_named_or_nested(dim, isl_dim_in))
1265                 return 0;
1266         return 1;
1267 }
1268
1269 __isl_give isl_dim *isl_dim_reset(__isl_take isl_dim *dim,
1270         enum isl_dim_type type)
1271 {
1272         if (!isl_dim_is_named_or_nested(dim, type))
1273                 return dim;
1274
1275         dim = isl_dim_cow(dim);
1276         if (!dim)
1277                 return NULL;
1278
1279         isl_id_free(dim->tuple_id[type - isl_dim_in]);
1280         dim->tuple_id[type - isl_dim_in] = NULL;
1281         isl_dim_free(dim->nested[type - isl_dim_in]);
1282         dim->nested[type - isl_dim_in] = NULL;
1283
1284         return dim;
1285 }
1286
1287 __isl_give isl_dim *isl_dim_flatten(__isl_take isl_dim *dim)
1288 {
1289         if (!dim)
1290                 return NULL;
1291         if (!dim->nested[0] && !dim->nested[1])
1292                 return dim;
1293
1294         if (dim->nested[0])
1295                 dim = isl_dim_reset(dim, isl_dim_in);
1296         if (dim && dim->nested[1])
1297                 dim = isl_dim_reset(dim, isl_dim_out);
1298
1299         return dim;
1300 }
1301
1302 __isl_give isl_dim *isl_dim_flatten_range(__isl_take isl_dim *dim)
1303 {
1304         if (!dim)
1305                 return NULL;
1306         if (!dim->nested[1])
1307                 return dim;
1308
1309         return isl_dim_reset(dim, isl_dim_out);
1310 }
1311
1312 /* Replace the dimensions of the given type of dst by those of src.
1313  */
1314 __isl_give isl_dim *isl_dim_replace(__isl_take isl_dim *dst,
1315         enum isl_dim_type type, __isl_keep isl_dim *src)
1316 {
1317         dst = isl_dim_cow(dst);
1318
1319         if (!dst || !src)
1320                 goto error;
1321
1322         dst = isl_dim_drop(dst, type, 0, isl_dim_size(dst, type));
1323         dst = isl_dim_add(dst, type, isl_dim_size(src, type));
1324         dst = copy_ids(dst, type, 0, src, type);
1325
1326         if (dst && type == isl_dim_param) {
1327                 int i;
1328                 for (i = 0; i <= 1; ++i) {
1329                         if (!dst->nested[i])
1330                                 continue;
1331                         dst->nested[i] = isl_dim_replace(dst->nested[i],
1332                                                          type, src);
1333                         if (!dst->nested[i])
1334                                 goto error;
1335                 }
1336         }
1337
1338         return dst;
1339 error:
1340         isl_dim_free(dst);
1341         return NULL;
1342 }
1343
1344 /* Given a dimension specification "dim" of a set, create a dimension
1345  * specification for the lift of the set.  In particular, the result
1346  * is of the form [dim -> local[..]], with n_local variables in the
1347  * range of the wrapped map.
1348  */
1349 __isl_give isl_dim *isl_dim_lift(__isl_take isl_dim *dim, unsigned n_local)
1350 {
1351         isl_dim *local_dim;
1352
1353         if (!dim)
1354                 return NULL;
1355
1356         local_dim = isl_dim_dup(dim);
1357         local_dim = isl_dim_drop(local_dim, isl_dim_set, 0, dim->n_out);
1358         local_dim = isl_dim_add(local_dim, isl_dim_set, n_local);
1359         local_dim = isl_dim_set_tuple_name(local_dim, isl_dim_set, "local");
1360         dim = isl_dim_join(isl_dim_from_domain(dim),
1361                             isl_dim_from_range(local_dim));
1362         dim = isl_dim_wrap(dim);
1363         dim = isl_dim_set_tuple_name(dim, isl_dim_set, "lifted");
1364
1365         return dim;
1366 }
1367
1368 int isl_dim_can_zip(__isl_keep isl_dim *dim)
1369 {
1370         if (!dim)
1371                 return -1;
1372
1373         return dim->nested[0] && dim->nested[1];
1374 }
1375
1376 __isl_give isl_dim *isl_dim_zip(__isl_take isl_dim *dim)
1377 {
1378         isl_dim *dom, *ran;
1379         isl_dim *dom_dom, *dom_ran, *ran_dom, *ran_ran;
1380
1381         if (!isl_dim_can_zip(dim))
1382                 isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
1383                         goto error);
1384
1385         if (!dim)
1386                 return 0;
1387         dom = isl_dim_unwrap(isl_dim_domain(isl_dim_copy(dim)));
1388         ran = isl_dim_unwrap(isl_dim_range(dim));
1389         dom_dom = isl_dim_domain(isl_dim_copy(dom));
1390         dom_ran = isl_dim_range(dom);
1391         ran_dom = isl_dim_domain(isl_dim_copy(ran));
1392         ran_ran = isl_dim_range(ran);
1393         dom = isl_dim_join(isl_dim_from_domain(dom_dom),
1394                            isl_dim_from_range(ran_dom));
1395         ran = isl_dim_join(isl_dim_from_domain(dom_ran),
1396                            isl_dim_from_range(ran_ran));
1397         return isl_dim_join(isl_dim_from_domain(isl_dim_wrap(dom)),
1398                             isl_dim_from_range(isl_dim_wrap(ran)));
1399 error:
1400         isl_dim_free(dim);
1401         return NULL;
1402 }
1403
1404 int isl_dim_has_named_params(__isl_keep isl_dim *dim)
1405 {
1406         int i;
1407         unsigned off;
1408
1409         if (!dim)
1410                 return -1;
1411         if (dim->nparam == 0)
1412                 return 1;
1413         off = isl_dim_offset(dim, isl_dim_param);
1414         if (off + dim->nparam > dim->n_id)
1415                 return 0;
1416         for (i = 0; i < dim->nparam; ++i)
1417                 if (!dim->ids[off + i])
1418                         return 0;
1419         return 1;
1420 }
1421
1422 /* Align the initial parameters of dim1 to match the order in dim2.
1423  */
1424 __isl_give isl_dim *isl_dim_align_params(__isl_take isl_dim *dim1,
1425         __isl_take isl_dim *dim2)
1426 {
1427         isl_reordering *exp;
1428
1429         if (!isl_dim_has_named_params(dim1) || !isl_dim_has_named_params(dim2))
1430                 isl_die(isl_dim_get_ctx(dim1), isl_error_invalid,
1431                         "parameter alignment requires named parameters",
1432                         goto error);
1433
1434         exp = isl_parameter_alignment_reordering(dim1, dim2);
1435         isl_dim_free(dim1);
1436         isl_dim_free(dim2);
1437         if (!exp)
1438                 return NULL;
1439         dim1 = isl_dim_copy(exp->dim);
1440         isl_reordering_free(exp);
1441         return dim1;
1442 error:
1443         isl_dim_free(dim1);
1444         isl_dim_free(dim2);
1445         return NULL;
1446 }