isl_map_gist: ensure divs of map are known
[platform/upstream/isl.git] / isl_map.c
index 3c9aeb5..281a92b 100644 (file)
--- a/isl_map.c
+++ b/isl_map.c
@@ -250,32 +250,30 @@ struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
        return (struct isl_basic_set *)bmap;
 }
 
-struct isl_basic_set *isl_basic_set_alloc_dim(struct isl_ctx *ctx,
-               struct isl_dim *dim, unsigned extra,
-               unsigned n_eq, unsigned n_ineq)
+struct isl_basic_set *isl_basic_set_alloc_dim(struct isl_dim *dim,
+               unsigned extra, unsigned n_eq, unsigned n_ineq)
 {
        struct isl_basic_map *bmap;
        if (!dim)
                return NULL;
-       isl_assert(ctx, dim->n_in == 0, return NULL);
-       bmap = isl_basic_map_alloc_dim(ctx, dim, extra, n_eq, n_ineq);
+       isl_assert(dim->ctx, dim->n_in == 0, return NULL);
+       bmap = isl_basic_map_alloc_dim(dim, extra, n_eq, n_ineq);
        return (struct isl_basic_set *)bmap;
 }
 
-struct isl_basic_map *isl_basic_map_alloc_dim(struct isl_ctx *ctx,
-               struct isl_dim *dim, unsigned extra,
-               unsigned n_eq, unsigned n_ineq)
+struct isl_basic_map *isl_basic_map_alloc_dim(struct isl_dim *dim,
+               unsigned extra, unsigned n_eq, unsigned n_ineq)
 {
        struct isl_basic_map *bmap;
 
        if (!dim)
                return NULL;
-       bmap = isl_alloc_type(ctx, struct isl_basic_map);
+       bmap = isl_alloc_type(dim->ctx, struct isl_basic_map);
        if (!bmap)
                goto error;
        bmap->dim = dim;
 
-       return basic_map_init(ctx, bmap, extra, n_eq, n_ineq);
+       return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
 error:
        isl_dim_free(dim);
        return NULL;
@@ -292,7 +290,7 @@ struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
        if (!dim)
                return NULL;
 
-       bmap = isl_basic_map_alloc_dim(ctx, dim, extra, n_eq, n_ineq);
+       bmap = isl_basic_map_alloc_dim(dim, extra, n_eq, n_ineq);
        return bmap;
 }
 
@@ -325,7 +323,7 @@ struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
 
        if (!bmap)
                return NULL;
-       dup = isl_basic_map_alloc_dim(bmap->ctx, isl_dim_copy(bmap->dim),
+       dup = isl_basic_map_alloc_dim(isl_dim_copy(bmap->dim),
                        bmap->n_div, bmap->n_eq, bmap->n_ineq);
        if (!dup)
                return NULL;
@@ -756,7 +754,7 @@ struct isl_basic_map *isl_basic_map_extend_dim(struct isl_basic_map *base,
        n_eq += base->n_eq;
        n_ineq += base->n_ineq;
 
-       ext = isl_basic_map_alloc_dim(base->ctx, dim, extra, n_eq, n_ineq);
+       ext = isl_basic_map_alloc_dim(dim, extra, n_eq, n_ineq);
        dim = NULL;
        if (!ext)
                goto error;
@@ -940,6 +938,13 @@ static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
        isl_seq_clr(c + rem, n);
 }
 
+/* Drop n dimensions starting at first.
+ *
+ * In principle, this frees up some extra variables as the number
+ * of columns remains constant, but we would have to extend
+ * the div array too as the number of rows in this array is assumed
+ * to be equal to extra.
+ */
 struct isl_basic_set *isl_basic_set_drop_dims(
                struct isl_basic_set *bset, unsigned first, unsigned n)
 {
@@ -972,7 +977,6 @@ struct isl_basic_set *isl_basic_set_drop_dims(
        bset->dim = isl_dim_drop_outputs(bset->dim, first, n);
        if (!bset->dim)
                goto error;
-       bset->extra += n;
 
        F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
        bset = isl_basic_set_simplify(bset);
@@ -1014,6 +1018,13 @@ error:
        return NULL;
 }
 
+/* Drop n input dimensions starting at first.
+ *
+ * In principle, this frees up some extra variables as the number
+ * of columns remains constant, but we would have to extend
+ * the div array too as the number of rows in this array is assumed
+ * to be equal to extra.
+ */
 struct isl_basic_map *isl_basic_map_drop_inputs(
                struct isl_basic_map *bmap, unsigned first, unsigned n)
 {
@@ -1052,7 +1063,6 @@ struct isl_basic_map *isl_basic_map_drop_inputs(
        bmap->dim = isl_dim_drop_inputs(bmap->dim, first, n);
        if (!bmap->dim)
                goto error;
-       bmap->extra += n;
 
        F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
        bmap = isl_basic_map_simplify(bmap);
@@ -1736,11 +1746,32 @@ static struct isl_basic_map *normalize_constraints(struct isl_basic_map *bmap)
 }
 
 
+/* Remove any div that is defined in terms of the given variable.
+ */
+static struct isl_basic_map *remove_dependent_vars(struct isl_basic_map *bmap,
+                                                                       int pos)
+{
+       int i;
+       unsigned dim = isl_dim_total(bmap->dim);
+
+       for (i = 0; i < bmap->n_div; ++i) {
+               if (isl_int_is_zero(bmap->div[i][0]))
+                       continue;
+               if (isl_int_is_zero(bmap->div[i][1+1+pos]))
+                       continue;
+               bmap = isl_basic_map_eliminate_vars(bmap, dim + i, 1);
+               if (!bmap)
+                       return NULL;
+       }
+       return bmap;
+}
+
+
 /* Eliminate the specified variables from the constraints using
  * Fourier-Motzkin.  The variables themselves are not removed.
  */
 struct isl_basic_map *isl_basic_map_eliminate_vars(
-       struct isl_basic_map *bmap, int pos, unsigned n)
+       struct isl_basic_map *bmap, unsigned pos, unsigned n)
 {
        int d;
        int i, j, k;
@@ -1753,10 +1784,13 @@ struct isl_basic_map *isl_basic_map_eliminate_vars(
        total = isl_basic_map_total_dim(bmap);
 
        bmap = isl_basic_map_cow(bmap);
-       for (d = pos + n - 1; d >= pos; --d) {
+       for (d = pos + n - 1; d >= 0 && d >= pos; --d) {
                int n_lower, n_upper;
+               bmap = remove_dependent_vars(bmap, d);
                if (!bmap)
                        return NULL;
+               if (d >= total - bmap->n_div)
+                       isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total);
                for (i = 0; i < bmap->n_eq; ++i) {
                        if (isl_int_is_zero(bmap->eq[i][1+d]))
                                continue;
@@ -2159,23 +2193,22 @@ int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
        return 0;
 }
 
-struct isl_set *isl_set_alloc_dim(struct isl_ctx *ctx,
-               struct isl_dim *dim, int n, unsigned flags)
+struct isl_set *isl_set_alloc_dim(struct isl_dim *dim, int n, unsigned flags)
 {
        struct isl_set *set;
 
        if (!dim)
                return NULL;
-       isl_assert(ctx, dim->n_in == 0, return NULL);
-       isl_assert(ctx, n >= 0, return NULL);
-       set = isl_alloc(ctx, struct isl_set,
+       isl_assert(dim->ctx, dim->n_in == 0, return NULL);
+       isl_assert(dim->ctx, n >= 0, return NULL);
+       set = isl_alloc(dim->ctx, struct isl_set,
                        sizeof(struct isl_set) +
                        n * sizeof(struct isl_basic_set *));
        if (!set)
                goto error;
 
-       set->ctx = ctx;
-       isl_ctx_ref(ctx);
+       set->ctx = dim->ctx;
+       isl_ctx_ref(set->ctx);
        set->ref = 1;
        set->size = n;
        set->n = 0;
@@ -2197,7 +2230,7 @@ struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
        if (!dims)
                return NULL;
 
-       set = isl_set_alloc_dim(ctx, dims, n, flags);
+       set = isl_set_alloc_dim(dims, n, flags);
        return set;
 }
 
@@ -2209,8 +2242,7 @@ struct isl_set *isl_set_dup(struct isl_set *set)
        if (!set)
                return NULL;
 
-       dup = isl_set_alloc_dim(set->ctx, isl_dim_copy(set->dim),
-                               set->n, set->flags);
+       dup = isl_set_alloc_dim(isl_dim_copy(set->dim), set->n, set->flags);
        if (!dup)
                return NULL;
        for (i = 0; i < set->n; ++i)
@@ -2225,8 +2257,7 @@ struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
        if (!bset)
                return NULL;
 
-       set = isl_set_alloc_dim(bset->ctx, isl_dim_copy(bset->dim),
-                               1, ISL_MAP_DISJOINT);
+       set = isl_set_alloc_dim(isl_dim_copy(bset->dim), 1, ISL_MAP_DISJOINT);
        if (!set) {
                isl_basic_set_free(bset);
                return NULL;
@@ -2241,8 +2272,7 @@ struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
        if (!bmap)
                return NULL;
 
-       map = isl_map_alloc_dim(bmap->ctx, isl_dim_copy(bmap->dim),
-                               1, ISL_MAP_DISJOINT);
+       map = isl_map_alloc_dim(isl_dim_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
        if (!map) {
                isl_basic_map_free(bmap);
                return NULL;
@@ -2423,7 +2453,7 @@ struct isl_map *isl_map_intersect(struct isl_map *map1, struct isl_map *map2)
            F_ISSET(map2, ISL_MAP_DISJOINT))
                FL_SET(flags, ISL_MAP_DISJOINT);
 
-       result = isl_map_alloc_dim(map1->ctx, isl_dim_copy(map1->dim),
+       result = isl_map_alloc_dim(isl_dim_copy(map1->dim),
                                map1->n * map2->n, flags);
        if (!result)
                goto error;
@@ -2572,7 +2602,7 @@ struct isl_basic_map *isl_basic_map_apply_range(
        isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
        isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
 
-       bmap = isl_basic_map_alloc_dim(bmap1->ctx, dim_result,
+       bmap = isl_basic_map_alloc_dim(dim_result,
                        bmap1->n_div + bmap2->n_div + n,
                        bmap1->n_eq + bmap2->n_eq,
                        bmap1->n_ineq + bmap2->n_ineq);
@@ -2834,11 +2864,13 @@ struct isl_basic_map *isl_basic_map_overlying_set(
        struct isl_basic_map *bmap;
        struct isl_ctx *ctx;
        unsigned total;
-       int i, k;
+       int i;
 
        if (!bset || !like)
                goto error;
        ctx = bset->ctx;
+       isl_assert(ctx, bset->n_div == 0, goto error);
+       isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
        isl_assert(ctx, bset->dim->n_out == isl_basic_map_total_dim(like),
                        goto error);
        if (isl_dim_equal(bset->dim, like->dim) && like->n_div == 0) {
@@ -2854,6 +2886,7 @@ struct isl_basic_map *isl_basic_map_overlying_set(
        bmap->dim = isl_dim_copy(like->dim);
        if (!bmap->dim)
                goto error;
+       bmap->n_div = like->n_div;
        bmap->extra += like->n_div;
        if (bmap->extra) {
                unsigned ltotal;
@@ -2868,17 +2901,17 @@ struct isl_basic_map *isl_basic_map_overlying_set(
                                                bmap->extra);
                if (!bmap->div)
                        goto error;
+               for (i = 0; i < bmap->extra; ++i)
+                       bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
+               for (i = 0; i < like->n_div; ++i) {
+                       isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
+                       isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
+               }
                bmap = isl_basic_map_extend_constraints(bmap, 
                                                        0, 2 * like->n_div);
-               for (i = 0; i < like->n_div; ++i) {
-                       k = isl_basic_map_alloc_div(bmap);
-                       if (k < 0)
-                               goto error;
-                       isl_seq_cpy(bmap->div[k], like->div[i], 1 + 1 + ltotal);
-                       isl_seq_clr(bmap->div[k]+1+1+ltotal, total - ltotal);
-                       if (add_div_constraints(bmap, k) < 0)
+               for (i = 0; i < like->n_div; ++i)
+                       if (add_div_constraints(bmap, i) < 0)
                                goto error;
-               }
        }
        isl_basic_map_free(like);
        bmap = isl_basic_map_finalize(bmap);
@@ -2934,7 +2967,6 @@ struct isl_set *isl_map_underlying_set(struct isl_map *map)
 {
        int i;
 
-       map = isl_map_align_divs(map);
        map = isl_map_cow(map);
        if (!map)
                return NULL;
@@ -2942,6 +2974,9 @@ struct isl_set *isl_map_underlying_set(struct isl_map *map)
        if (!map->dim)
                goto error;
 
+       for (i = 1; i < map->n; ++i)
+               isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
+                               goto error);
        for (i = 0; i < map->n; ++i) {
                map->p[i] = (struct isl_basic_map *)
                                isl_basic_map_underlying_set(map->p[i]);
@@ -3063,22 +3098,21 @@ error:
        return NULL;
 }
 
-struct isl_map *isl_map_alloc_dim(struct isl_ctx *ctx,
-               struct isl_dim *dim, int n, unsigned flags)
+struct isl_map *isl_map_alloc_dim(struct isl_dim *dim, int n, unsigned flags)
 {
        struct isl_map *map;
 
        if (!dim)
                return NULL;
-       isl_assert(ctx, n >= 0, return NULL);
-       map = isl_alloc(ctx, struct isl_map,
+       isl_assert(dim->ctx, n >= 0, return NULL);
+       map = isl_alloc(dim->ctx, struct isl_map,
                        sizeof(struct isl_map) +
                        n * sizeof(struct isl_basic_map *));
        if (!map)
                goto error;
 
-       map->ctx = ctx;
-       isl_ctx_ref(ctx);
+       map->ctx = dim->ctx;
+       isl_ctx_ref(map->ctx);
        map->ref = 1;
        map->size = n;
        map->n = 0;
@@ -3101,7 +3135,7 @@ struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
        if (!dims)
                return NULL;
 
-       map = isl_map_alloc_dim(ctx, dims, n, flags);
+       map = isl_map_alloc_dim(dims, n, flags);
        return map;
 }
 
@@ -3114,11 +3148,10 @@ struct isl_basic_map *isl_basic_map_empty(struct isl_ctx *ctx,
        return bmap;
 }
 
-struct isl_basic_set *isl_basic_set_empty(struct isl_ctx *ctx,
-               unsigned nparam, unsigned dim)
+struct isl_basic_set *isl_basic_set_empty(struct isl_dim *dim)
 {
        struct isl_basic_set *bset;
-       bset = isl_basic_set_alloc(ctx, nparam, dim, 0, 1, 0);
+       bset = isl_basic_set_alloc_dim(dim, 0, 1, 0);
        bset = isl_basic_set_set_to_empty(bset);
        return bset;
 }
@@ -3128,8 +3161,7 @@ struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model)
        struct isl_basic_map *bmap;
        if (!model)
                return NULL;
-       bmap = isl_basic_map_alloc_dim(model->ctx, isl_dim_copy(model->dim),
-                                       0, 1, 0);
+       bmap = isl_basic_map_alloc_dim(isl_dim_copy(model->dim), 0, 1, 0);
        bmap = isl_basic_map_set_to_empty(bmap);
        return bmap;
 }
@@ -3139,8 +3171,7 @@ struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model)
        struct isl_basic_map *bmap;
        if (!model)
                return NULL;
-       bmap = isl_basic_map_alloc_dim(model->ctx, isl_dim_copy(model->dim),
-                                       0, 1, 0);
+       bmap = isl_basic_map_alloc_dim(isl_dim_copy(model->dim), 0, 1, 0);
        bmap = isl_basic_map_set_to_empty(bmap);
        return bmap;
 }
@@ -3150,25 +3181,22 @@ struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model)
        struct isl_basic_set *bset;
        if (!model)
                return NULL;
-       bset = isl_basic_set_alloc_dim(model->ctx, isl_dim_copy(model->dim),
-                                       0, 1, 0);
+       bset = isl_basic_set_alloc_dim(isl_dim_copy(model->dim), 0, 1, 0);
        bset = isl_basic_set_set_to_empty(bset);
        return bset;
 }
 
-struct isl_basic_map *isl_basic_map_universe(struct isl_ctx *ctx,
-               unsigned nparam, unsigned in, unsigned out)
+struct isl_basic_map *isl_basic_map_universe(struct isl_dim *dim)
 {
        struct isl_basic_map *bmap;
-       bmap = isl_basic_map_alloc(ctx, nparam, in, out, 0, 0, 0);
+       bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
        return bmap;
 }
 
-struct isl_basic_set *isl_basic_set_universe(struct isl_ctx *ctx,
-               unsigned nparam, unsigned dim)
+struct isl_basic_set *isl_basic_set_universe(struct isl_dim *dim)
 {
        struct isl_basic_set *bset;
-       bset = isl_basic_set_alloc(ctx, nparam, dim, 0, 0, 0);
+       bset = isl_basic_set_alloc_dim(dim, 0, 0, 0);
        return bset;
 }
 
@@ -3176,8 +3204,7 @@ struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model)
 {
        if (!model)
                return NULL;
-       return isl_basic_set_alloc_dim(model->ctx, isl_dim_copy(model->dim),
-                                       0, 0, 0);
+       return isl_basic_set_alloc_dim(isl_dim_copy(model->dim), 0, 0, 0);
 }
 
 struct isl_map *isl_map_empty(struct isl_ctx *ctx,
@@ -3190,20 +3217,29 @@ struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model)
 {
        if (!model)
                return NULL;
-       return isl_map_alloc_dim(model->ctx, isl_dim_copy(model->dim),
-                                       0, ISL_MAP_DISJOINT);
+       return isl_map_alloc_dim(isl_dim_copy(model->dim), 0, ISL_MAP_DISJOINT);
 }
 
-struct isl_set *isl_set_empty(struct isl_ctx *ctx, struct isl_dim *dim)
+struct isl_set *isl_set_empty(struct isl_dim *dim)
 {
-       return isl_set_alloc_dim(ctx, dim, 0, ISL_MAP_DISJOINT);
+       return isl_set_alloc_dim(dim, 0, ISL_MAP_DISJOINT);
 }
 
 struct isl_set *isl_set_empty_like(struct isl_set *model)
 {
        if (!model)
                return NULL;
-       return isl_set_empty(model->ctx, isl_dim_copy(model->dim));
+       return isl_set_empty(isl_dim_copy(model->dim));
+}
+
+struct isl_set *isl_set_universe(struct isl_dim *dim)
+{
+       struct isl_set *set;
+       if (!dim)
+               return NULL;
+       set = isl_set_alloc_dim(isl_dim_copy(dim), 1, ISL_MAP_DISJOINT);
+       set = isl_set_add(set, isl_basic_set_universe(dim));
+       return set;
 }
 
 struct isl_map *isl_map_dup(struct isl_map *map)
@@ -3213,8 +3249,7 @@ struct isl_map *isl_map_dup(struct isl_map *map)
 
        if (!map)
                return NULL;
-       dup = isl_map_alloc_dim(map->ctx, isl_dim_copy(map->dim),
-                               map->n, map->flags);
+       dup = isl_map_alloc_dim(isl_dim_copy(map->dim), map->n, map->flags);
        for (i = 0; i < map->n; ++i)
                dup = isl_map_add(dup, isl_basic_map_copy(map->p[i]));
        return dup;
@@ -3460,13 +3495,15 @@ struct isl_set *isl_basic_set_lexmin(struct isl_basic_set *bset)
        struct isl_basic_map *bmap = NULL;
        struct isl_basic_set *dom = NULL;
        struct isl_map *min;
+       struct isl_dim *param_dim;
 
        if (!bset)
                goto error;
        bmap = isl_basic_map_from_basic_set(bset, isl_dim_copy(bset->dim));
        if (!bmap)
                goto error;
-       dom = isl_basic_set_universe(bmap->ctx, isl_basic_map_n_param(bmap), 0);
+       param_dim = isl_dim_domain(isl_dim_copy(bmap->dim));
+       dom = isl_basic_set_universe(param_dim);
        if (!dom)
                goto error;
        min = isl_basic_map_lexmin(bmap, dom, NULL);
@@ -3478,11 +3515,22 @@ error:
 
 struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
 {
+       int i;
+       unsigned off;
+
        if (!bmap)
                return NULL;
-       if (bmap->n_div == 0)
-               return isl_map_from_basic_map(bmap);
-       return isl_pip_basic_map_compute_divs(bmap);
+       off = isl_dim_total(bmap->dim);
+       for (i = 0; i < bmap->n_div; ++i) {
+               if (isl_int_is_zero(bmap->div[i][0]))
+                       return isl_pip_basic_map_compute_divs(bmap);
+               isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]),
+                               goto error);
+       }
+       return isl_map_from_basic_map(bmap);
+error:
+       isl_basic_map_free(bmap);
+       return NULL;
 }
 
 struct isl_map *isl_map_compute_divs(struct isl_map *map)
@@ -3533,8 +3581,7 @@ struct isl_set *isl_map_domain(struct isl_map *map)
                return NULL;
 
        set = (struct isl_set *)map;
-       set->dim = isl_dim_drop_outputs(set->dim, 0, set->dim->n_out);
-       set->dim = isl_dim_reverse(set->dim);
+       set->dim = isl_dim_domain(set->dim);
        if (!set->dim)
                goto error;
        for (i = 0; i < map->n; ++i) {
@@ -3575,7 +3622,7 @@ struct isl_map *isl_map_union_disjoint(
            F_ISSET(map2, ISL_MAP_DISJOINT))
                FL_SET(flags, ISL_MAP_DISJOINT);
 
-       map = isl_map_alloc_dim(map1->ctx, isl_dim_copy(map1->dim),
+       map = isl_map_alloc_dim(isl_dim_copy(map1->dim),
                                map1->n + map2->n, flags);
        if (!map)
                goto error;
@@ -3639,7 +3686,7 @@ struct isl_map *isl_map_intersect_range(
            F_ISSET(set, ISL_MAP_DISJOINT))
                FL_SET(flags, ISL_MAP_DISJOINT);
 
-       result = isl_map_alloc_dim(map->ctx, isl_dim_copy(map->dim),
+       result = isl_map_alloc_dim(isl_dim_copy(map->dim),
                                        map->n * set->n, flags);
        if (!result)
                goto error;
@@ -3698,7 +3745,7 @@ struct isl_map *isl_map_apply_range(
        dim_result = isl_dim_join(isl_dim_copy(map1->dim),
                                  isl_dim_copy(map2->dim));
 
-       result = isl_map_alloc_dim(map1->ctx, dim_result, map1->n * map2->n, 0);
+       result = isl_map_alloc_dim(dim_result, map1->n * map2->n, 0);
        if (!result)
                goto error;
        for (i = 0; i < map1->n; ++i)
@@ -3914,7 +3961,7 @@ static struct isl_basic_map *basic_map_identity(struct isl_dim *dims)
 
        nparam = dims->nparam;
        dim = dims->n_out;
-       bmap = isl_basic_map_alloc_dim(dims->ctx, dims, 0, dim, 0);
+       bmap = isl_basic_map_alloc_dim(dims, 0, dim, 0);
        if (!bmap)
                goto error;
 
@@ -3951,7 +3998,7 @@ struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model)
 
 static struct isl_map *map_identity(struct isl_dim *dim)
 {
-       struct isl_map *map = isl_map_alloc_dim(dim->ctx, dim, 1, ISL_MAP_DISJOINT);
+       struct isl_map *map = isl_map_alloc_dim(dim, 1, ISL_MAP_DISJOINT);
        return isl_map_add(map, basic_map_identity(isl_dim_copy(dim)));
 }
 
@@ -4193,7 +4240,7 @@ struct isl_map *isl_basic_map_union(
 
        isl_assert(map1->ctx, isl_dim_equal(bmap1->dim, bmap2->dim), goto error);
 
-       map = isl_map_alloc_dim(bmap1->ctx, isl_dim_copy(bmap1->dim), 2, 0);
+       map = isl_map_alloc_dim(isl_dim_copy(bmap1->dim), 2, 0);
        if (!map)
                goto error;
        map = isl_map_add(map, bmap1);
@@ -4231,17 +4278,24 @@ static struct isl_basic_map *order_divs(struct isl_basic_map *bmap)
        return bmap;
 }
 
+/* Look for a div in dst that corresponds to the div "div" in src.
+ * The divs before "div" in src and dst are assumed to be the same.
+ * 
+ * Returns -1 if no corresponding div was found and the position
+ * of the corresponding div in dst otherwise.
+ */
 static int find_div(struct isl_basic_map *dst,
                        struct isl_basic_map *src, unsigned div)
 {
        int i;
 
-       unsigned total = isl_basic_map_total_dim(src);
+       unsigned total = isl_dim_total(src->dim);
 
-       for (i = 0; i < dst->n_div; ++i)
-               if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total) &&
-                   isl_seq_first_non_zero(dst->div[i]+1+1+total,
-                                               dst->n_div - src->n_div) == -1)
+       isl_assert(dst->ctx, div <= dst->n_div, return -1);
+       for (i = div; i < dst->n_div; ++i)
+               if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
+                   isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
+                                               dst->n_div - div) == -1)
                        return i;
        return -1;
 }
@@ -4250,7 +4304,7 @@ struct isl_basic_map *isl_basic_map_align_divs(
                struct isl_basic_map *dst, struct isl_basic_map *src)
 {
        int i;
-       unsigned total = isl_basic_map_total_dim(src);
+       unsigned total = isl_dim_total(src->dim);
 
        if (!dst || !src)
                goto error;
@@ -4269,9 +4323,8 @@ struct isl_basic_map *isl_basic_map_align_divs(
                        j = isl_basic_map_alloc_div(dst);
                        if (j < 0)
                                goto error;
-                       isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
-                       isl_seq_clr(dst->div[j]+1+1+total,
-                                                   dst->n_div - src->n_div);
+                       isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
+                       isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
                        if (add_div_constraints(dst, j) < 0)
                                goto error;
                }
@@ -4366,7 +4419,7 @@ static struct isl_map *subtract(struct isl_map *map, struct isl_basic_map *bmap)
                FL_SET(flags, ISL_MAP_DISJOINT);
 
        max = map->n * (2 * bmap->n_eq + bmap->n_ineq);
-       rest = isl_map_alloc_dim(map->ctx, isl_dim_copy(map->dim), max, flags);
+       rest = isl_map_alloc_dim(isl_dim_copy(map->dim), max, flags);
        if (!rest)
                goto error;
 
@@ -4592,6 +4645,7 @@ int isl_basic_set_compare_at(struct isl_basic_set *bset1,
        bmap1 = isl_basic_map_extend(bmap1, nparam,
                        pos, (dim1 - pos) + (dim2 - pos),
                        bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
+       bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos);
        if (!bmap1)
                goto error;
        total = isl_basic_map_total_dim(bmap1);
@@ -4602,7 +4656,6 @@ int isl_basic_set_compare_at(struct isl_basic_set *bset1,
        isl_int_set_si(obj->block.data[nparam+pos+(dim1-pos)], -1);
        if (!obj)
                goto error;
-       bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos);
        isl_int_init(num);
        isl_int_init(den);
        res = isl_solve_lp(bmap1, 0, obj->block.data, ctx->one, &num, &den);
@@ -4952,6 +5005,9 @@ error:
        return NULL;
 }
 
+/*
+ * Assumes context has no implicit divs.
+ */
 struct isl_map *isl_map_gist(struct isl_map *map, struct isl_basic_map *context)
 {
        int i;
@@ -4960,6 +5016,7 @@ struct isl_map *isl_map_gist(struct isl_map *map, struct isl_basic_map *context)
        if (!map || !context)
                return NULL;
        isl_assert(map->ctx, isl_dim_equal(map->dim, context->dim), goto error);
+       map = isl_map_compute_divs(map);
        for (i = 0; i < map->n; ++i)
                context = isl_basic_map_align_divs(context, map->p[i]);
        for (i = 0; i < map->n; ++i) {