Update isl to isl-0.17.1-191-g540b2fd
authorTobias Grosser <tobias@grosser.es>
Wed, 20 Jul 2016 16:53:07 +0000 (16:53 +0000)
committerTobias Grosser <tobias@grosser.es>
Wed, 20 Jul 2016 16:53:07 +0000 (16:53 +0000)
This update resolves a bug in computing lexicographic minima/maxima.

llvm-svn: 276138

polly/lib/External/isl/GIT_HEAD_ID
polly/lib/External/isl/doc/manual.pdf
polly/lib/External/isl/isl_map.c
polly/lib/External/isl/isl_map_private.h
polly/lib/External/isl/isl_map_simplify.c
polly/lib/External/isl/isl_map_subtract.c
polly/lib/External/isl/isl_tab.c
polly/lib/External/isl/isl_tab.h
polly/lib/External/isl/isl_tab_pip.c
polly/lib/External/isl/isl_test.c

index 9c1df79..addfca4 100644 (file)
@@ -1 +1 @@
-isl-0.17.1-171-g233f589
+isl-0.17.1-191-g540b2fd
index 62973b5..74af403 100644 (file)
Binary files a/polly/lib/External/isl/doc/manual.pdf and b/polly/lib/External/isl/doc/manual.pdf differ
index a1358d3..ddff7c6 100644 (file)
@@ -1425,6 +1425,43 @@ int isl_basic_set_alloc_div(struct isl_basic_set *bset)
        return isl_basic_map_alloc_div((struct isl_basic_map *)bset);
 }
 
+/* Insert an extra integer division, prescribed by "div", to "bmap"
+ * at (integer division) position "pos".
+ *
+ * The integer division is first added at the end and then moved
+ * into the right position.
+ */
+__isl_give isl_basic_map *isl_basic_map_insert_div(
+       __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
+{
+       int i, k, n_div;
+
+       bmap = isl_basic_map_cow(bmap);
+       if (!bmap || !div)
+               return isl_basic_map_free(bmap);
+
+       if (div->size != 1 + 1 + isl_basic_map_dim(bmap, isl_dim_all))
+               isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+                       "unexpected size", return isl_basic_map_free(bmap));
+       n_div = isl_basic_map_dim(bmap, isl_dim_div);
+       if (pos < 0 || pos > n_div)
+               isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+                       "invalid position", return isl_basic_map_free(bmap));
+
+       bmap = isl_basic_map_extend_space(bmap,
+                                       isl_basic_map_get_space(bmap), 1, 0, 2);
+       k = isl_basic_map_alloc_div(bmap);
+       if (k < 0)
+               return isl_basic_map_free(bmap);
+       isl_seq_cpy(bmap->div[k], div->el, div->size);
+       isl_int_set_si(bmap->div[k][div->size], 0);
+
+       for (i = k; i > pos; --i)
+               isl_basic_map_swap_div(bmap, i, i - 1);
+
+       return bmap;
+}
+
 int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
 {
        if (!bmap)
@@ -6918,6 +6955,17 @@ int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
        return bmap->n_div;
 }
 
+/* Return the position of the first local variable that does not
+ * have an explicit representation.
+ * Return the total number of local variables if they all have
+ * an explicit representation.
+ * Return -1 on error.
+ */
+int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
+{
+       return isl_basic_map_first_unknown_div(bset);
+}
+
 /* Does "bmap" have an explicit representation for all local variables?
  */
 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
index 679df01..69a9589 100644 (file)
@@ -231,9 +231,13 @@ int isl_basic_set_alloc_inequality(struct isl_basic_set *bset);
 int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap);
 int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n);
 int isl_basic_map_alloc_div(struct isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_insert_div(
+       __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div);
 int isl_basic_set_alloc_div(struct isl_basic_set *bset);
 int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n);
 int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_drop_div(
+       __isl_take isl_basic_map *bmap, unsigned div);
 void isl_basic_map_inequality_to_equality(
                struct isl_basic_map *bmap, unsigned pos);
 int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos);
@@ -427,6 +431,7 @@ isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
        int div);
 isl_bool isl_basic_set_div_is_known(__isl_keep isl_basic_set *bset, int div);
 isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div);
+int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset);
 int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap);
 isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap);
 isl_bool isl_map_divs_known(__isl_keep isl_map *map);
index dbd81b5..c928a14 100644 (file)
@@ -269,8 +269,8 @@ struct isl_map *isl_map_drop_inputs(
 /*
  * We don't cow, as the div is assumed to be redundant.
  */
-static struct isl_basic_map *isl_basic_map_drop_div(
-               struct isl_basic_map *bmap, unsigned div)
+__isl_give isl_basic_map *isl_basic_map_drop_div(
+       __isl_take isl_basic_map *bmap, unsigned div)
 {
        int i;
        unsigned pos;
index 036737e..fe8dfae 100644 (file)
@@ -193,7 +193,7 @@ static int tab_add_divs(struct isl_tab *tab, __isl_keep isl_basic_map *bmap,
                (*div_map)[i] = j;
                if (j == tab->bmap->n_div) {
                        vec->size = 2 + dim + tab->bmap->n_div;
-                       if (isl_tab_add_div(tab, vec, NULL, NULL) < 0)
+                       if (isl_tab_add_div(tab, vec) < 0)
                                goto error;
                }
        }
index d077401..4985f49 100644 (file)
@@ -2287,8 +2287,10 @@ static int div_is_nonneg(struct isl_tab *tab, __isl_keep isl_vec *div)
        return 1;
 }
 
-/* Add an extra div, prescribed by "div" to the tableau and
+/* Insert an extra div, prescribed by "div", to the tableau and
  * the associated bmap (which is assumed to be non-NULL).
+ * The extra integer division is inserted at (tableau) position "pos".
+ * Return "pos" or -1 if an error occurred.
  *
  * If add_ineq is not NULL, then this function is used instead
  * of isl_tab_add_ineq to add the div constraints.
@@ -2296,17 +2298,26 @@ static int div_is_nonneg(struct isl_tab *tab, __isl_keep isl_vec *div)
  * wants to perform some extra processing when an inequality
  * is added to the tableau.
  */
-int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
+int isl_tab_insert_div(struct isl_tab *tab, int pos, __isl_keep isl_vec *div,
        int (*add_ineq)(void *user, isl_int *), void *user)
 {
        int r;
-       int k;
        int nonneg;
+       int n_div, o_div;
 
        if (!tab || !div)
                return -1;
 
+       if (div->size != 1 + 1 + tab->n_var)
+               isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
+                       "unexpected size", return -1);
+
        isl_assert(tab->mat->ctx, tab->bmap, return -1);
+       n_div = isl_basic_map_dim(tab->bmap, isl_dim_div);
+       o_div = tab->n_var - n_div;
+       if (pos < o_div || pos > tab->n_var)
+               isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
+                       "invalid position", return -1);
 
        nonneg = div_is_nonneg(tab, div);
 
@@ -2314,28 +2325,35 @@ int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
                return -1;
        if (isl_tab_extend_vars(tab, 1) < 0)
                return -1;
-       r = isl_tab_allocate_var(tab);
+       r = isl_tab_insert_var(tab, pos);
        if (r < 0)
                return -1;
 
        if (nonneg)
                tab->var[r].is_nonneg = 1;
 
-       tab->bmap = isl_basic_map_extend_space(tab->bmap,
-               isl_basic_map_get_space(tab->bmap), 1, 0, 2);
-       k = isl_basic_map_alloc_div(tab->bmap);
-       if (k < 0)
+       tab->bmap = isl_basic_map_insert_div(tab->bmap, pos - o_div, div);
+       if (!tab->bmap)
                return -1;
-       isl_seq_cpy(tab->bmap->div[k], div->el, div->size);
-       if (isl_tab_push(tab, isl_tab_undo_bmap_div) < 0)
+       if (isl_tab_push_var(tab, isl_tab_undo_bmap_div, &tab->var[r]) < 0)
                return -1;
 
-       if (add_div_constraints(tab, k, add_ineq, user) < 0)
+       if (add_div_constraints(tab, pos - o_div, add_ineq, user) < 0)
                return -1;
 
        return r;
 }
 
+/* Add an extra div, prescribed by "div", to the tableau and
+ * the associated bmap (which is assumed to be non-NULL).
+ */
+int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div)
+{
+       if (!tab)
+               return -1;
+       return isl_tab_insert_div(tab, tab->n_var, div, NULL, NULL);
+}
+
 /* If "track" is set, then we want to keep track of all constraints in tab
  * in its bmap field.  This field is initialized from a copy of "bmap",
  * so we need to make sure that all constraints in "bmap" also appear
@@ -3408,6 +3426,25 @@ static int perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
        return 0;
 }
 
+/* Undo the addition of an integer division to the basic map representation
+ * of "tab" in position "pos".
+ */
+static isl_stat drop_bmap_div(struct isl_tab *tab, int pos)
+{
+       int off;
+
+       off = tab->n_var - isl_basic_map_dim(tab->bmap, isl_dim_div);
+       if (isl_basic_map_drop_div(tab->bmap, pos - off) < 0)
+               return isl_stat_error;
+       if (tab->samples) {
+               tab->samples = isl_mat_drop_cols(tab->samples, 1 + pos, 1);
+               if (!tab->samples)
+                       return isl_stat_error;
+       }
+
+       return isl_stat_ok;
+}
+
 /* Restore the tableau to the state where the basic variables
  * are those in "col_var".
  * We first construct a list of variables that are currently in
@@ -3509,11 +3546,7 @@ static int perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
        case isl_tab_undo_bmap_ineq:
                return isl_basic_map_free_inequality(tab->bmap, 1);
        case isl_tab_undo_bmap_div:
-               if (isl_basic_map_free_div(tab->bmap, 1) < 0)
-                       return -1;
-               if (tab->samples)
-                       tab->samples->n_col--;
-               break;
+               return drop_bmap_div(tab, undo->u.var_index);
        case isl_tab_undo_saved_basis:
                if (restore_basis(tab, undo->u.col_var) < 0)
                        return -1;
index d97ab50..afb50a6 100644 (file)
@@ -320,8 +320,9 @@ struct isl_tab *isl_tab_detect_equalities(struct isl_tab *tab,
 int isl_tab_push_callback(struct isl_tab *tab,
        struct isl_tab_callback *callback) WARN_UNUSED;
 
-int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
+int isl_tab_insert_div(struct isl_tab *tab, int pos, __isl_keep isl_vec *div,
        int (*add_ineq)(void *user, isl_int *), void *user);
+int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div);
 
 int isl_tab_shift_var(struct isl_tab *tab, int pos, isl_int shift) WARN_UNUSED;
 
index ab86799..0cebe77 100644 (file)
@@ -91,8 +91,9 @@ struct isl_context_op {
        /* return index of a div that corresponds to "div" */
        int (*get_div)(struct isl_context *context, struct isl_tab *tab,
                        struct isl_vec *div);
-       /* add div "div" to context and return non-negativity */
-       int (*add_div)(struct isl_context *context, struct isl_vec *div);
+       /* insert div "div" to context at "pos" and return non-negativity */
+       isl_bool (*insert_div)(struct isl_context *context, int pos,
+               __isl_keep isl_vec *div);
        int (*detect_equalities)(struct isl_context *context,
                        struct isl_tab *tab);
        /* return row index of "best" split */
@@ -110,11 +111,17 @@ struct isl_context_op {
        /* invalidate context */
        void (*invalidate)(struct isl_context *context);
        /* free context */
-       void (*free)(struct isl_context *context);
+       __isl_null struct isl_context *(*free)(struct isl_context *context);
 };
 
+/* Shared parts of context representation.
+ *
+ * "n_unknown" is the number of final unknown integer divisions
+ * in the input domain.
+ */
 struct isl_context {
        struct isl_context_op *op;
+       int n_unknown;
 };
 
 struct isl_context_lex {
@@ -1860,10 +1867,11 @@ static int tab_has_valid_sample(struct isl_tab *tab, isl_int *ineq, int eq)
        return i < tab->n_sample;
 }
 
-/* Add a div specified by "div" to the tableau "tab" and return
- * 1 if the div is obviously non-negative.
+/* Insert a div specified by "div" to the tableau "tab" at position "pos" and
+ * return isl_bool_true if the div is obviously non-negative.
  */
-static int context_tab_add_div(struct isl_tab *tab, struct isl_vec *div,
+static isl_bool context_tab_insert_div(struct isl_tab *tab, int pos,
+       __isl_keep isl_vec *div,
        int (*add_ineq)(void *user, isl_int *), void *user)
 {
        int i;
@@ -1871,9 +1879,9 @@ static int context_tab_add_div(struct isl_tab *tab, struct isl_vec *div,
        struct isl_mat *samples;
        int nonneg;
 
-       r = isl_tab_add_div(tab, div, add_ineq, user);
+       r = isl_tab_insert_div(tab, pos, div, add_ineq, user);
        if (r < 0)
-               return -1;
+               return isl_bool_error;
        nonneg = tab->var[r].is_nonneg;
        tab->var[r].frozen = 1;
 
@@ -1881,13 +1889,17 @@ static int context_tab_add_div(struct isl_tab *tab, struct isl_vec *div,
                        tab->n_sample, 1 + tab->n_var);
        tab->samples = samples;
        if (!samples)
-               return -1;
+               return isl_bool_error;
        for (i = tab->n_outside; i < samples->n_row; ++i) {
                isl_seq_inner_product(div->el + 1, samples->row[i],
                        div->size - 1, &samples->row[i][samples->n_col - 1]);
                isl_int_fdiv_q(samples->row[i][samples->n_col - 1],
                               samples->row[i][samples->n_col - 1], div->el[0]);
        }
+       tab->samples = isl_mat_move_cols(tab->samples, 1 + pos,
+                                       1 + tab->n_var - 1, 1);
+       if (!tab->samples)
+               return isl_bool_error;
 
        return nonneg;
 }
@@ -1897,22 +1909,34 @@ static int context_tab_add_div(struct isl_tab *tab, struct isl_vec *div,
  * need to add an extra div.  In the context tableau, we also
  * need to express the meaning of the div.
  * Return the index of the div or -1 if anything went wrong.
+ *
+ * The new integer division is added before any unknown integer
+ * divisions in the context to ensure that it does not get
+ * equated to some linear combination involving unknown integer
+ * divisions.
  */
 static int add_div(struct isl_tab *tab, struct isl_context *context,
-       struct isl_vec *div)
+       __isl_keep isl_vec *div)
 {
        int r;
-       int nonneg;
+       int pos;
+       isl_bool nonneg;
+       struct isl_tab *context_tab = context->op->peek_tab(context);
+
+       if (!tab || !context_tab)
+               goto error;
 
-       if ((nonneg = context->op->add_div(context, div)) < 0)
+       pos = context_tab->n_var - context->n_unknown;
+       if ((nonneg = context->op->insert_div(context, pos, div)) < 0)
                goto error;
 
        if (!context->op->is_ok(context))
                goto error;
 
+       pos = tab->n_var - context->n_unknown;
        if (isl_tab_extend_vars(tab, 1) < 0)
                goto error;
-       r = isl_tab_allocate_var(tab);
+       r = isl_tab_insert_var(tab, pos);
        if (r < 0)
                goto error;
        if (nonneg)
@@ -1920,7 +1944,7 @@ static int add_div(struct isl_tab *tab, struct isl_context *context,
        tab->var[r].frozen = 1;
        tab->n_div++;
 
-       return tab->n_div - 1;
+       return tab->n_div - 1 - context->n_unknown;
 error:
        context->op->invalidate(context);
        return -1;
@@ -2002,7 +2026,7 @@ static int add_parametric_cut(struct isl_tab *tab, int row,
        if (!div)
                return -1;
 
-       n = tab->n_div;
+       n = tab->n_div - context->n_unknown;
        d = context->op->get_div(context, tab, div);
        isl_vec_free(div);
        if (d < 0)
@@ -2395,24 +2419,25 @@ static int context_lex_get_div(struct isl_context *context, struct isl_tab *tab,
        return get_div(tab, context, div);
 }
 
-/* Add a div specified by "div" to the context tableau and return
- * 1 if the div is obviously non-negative.
- * context_tab_add_div will always return 1, because all variables
+/* Insert a div specified by "div" to the context tableau at position "pos" and
+ * return isl_bool_true if the div is obviously non-negative.
+ * context_tab_add_div will always return isl_bool_true, because all variables
  * in a isl_context_lex tableau are non-negative.
  * However, if we are using a big parameter in the context, then this only
  * reflects the non-negativity of the variable used to _encode_ the
  * div, i.e., div' = M + div, so we can't draw any conclusions.
  */
-static int context_lex_add_div(struct isl_context *context, struct isl_vec *div)
+static isl_bool context_lex_insert_div(struct isl_context *context, int pos,
+       __isl_keep isl_vec *div)
 {
        struct isl_context_lex *clex = (struct isl_context_lex *)context;
-       int nonneg;
-       nonneg = context_tab_add_div(clex->tab, div,
+       isl_bool nonneg;
+       nonneg = context_tab_insert_div(clex->tab, pos, div,
                                        context_lex_add_ineq_wrap, context);
        if (nonneg < 0)
-               return -1;
+               return isl_bool_error;
        if (clex->tab->M)
-               return 0;
+               return isl_bool_false;
        return nonneg;
 }
 
@@ -2571,11 +2596,14 @@ static void context_lex_invalidate(struct isl_context *context)
        clex->tab = NULL;
 }
 
-static void context_lex_free(struct isl_context *context)
+static __isl_null struct isl_context *context_lex_free(
+       struct isl_context *context)
 {
        struct isl_context_lex *clex = (struct isl_context_lex *)context;
        isl_tab_free(clex->tab);
        free(clex);
+
+       return NULL;
 }
 
 struct isl_context_op isl_context_lex_op = {
@@ -2587,7 +2615,7 @@ struct isl_context_op isl_context_lex_op = {
        context_lex_ineq_sign,
        context_lex_test_ineq,
        context_lex_get_div,
-       context_lex_add_div,
+       context_lex_insert_div,
        context_lex_detect_equalities,
        context_lex_best_split,
        context_lex_is_empty,
@@ -3199,29 +3227,32 @@ static int context_gbr_get_div(struct isl_context *context, struct isl_tab *tab,
        return get_div(tab, context, div);
 }
 
-static int context_gbr_add_div(struct isl_context *context, struct isl_vec *div)
+static isl_bool context_gbr_insert_div(struct isl_context *context, int pos,
+       __isl_keep isl_vec *div)
 {
        struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
        if (cgbr->cone) {
-               int k;
+               int r, n_div, o_div;
+
+               n_div = isl_basic_map_dim(cgbr->cone->bmap, isl_dim_div);
+               o_div = cgbr->cone->n_var - n_div;
 
                if (isl_tab_extend_cons(cgbr->cone, 3) < 0)
-                       return -1;
+                       return isl_bool_error;
                if (isl_tab_extend_vars(cgbr->cone, 1) < 0)
-                       return -1;
-               if (isl_tab_allocate_var(cgbr->cone) <0)
-                       return -1;
-
-               cgbr->cone->bmap = isl_basic_map_extend_space(cgbr->cone->bmap,
-                       isl_basic_map_get_space(cgbr->cone->bmap), 1, 0, 2);
-               k = isl_basic_map_alloc_div(cgbr->cone->bmap);
-               if (k < 0)
-                       return -1;
-               isl_seq_cpy(cgbr->cone->bmap->div[k], div->el, div->size);
-               if (isl_tab_push(cgbr->cone, isl_tab_undo_bmap_div) < 0)
-                       return -1;
+                       return isl_bool_error;
+               if ((r = isl_tab_insert_var(cgbr->cone, pos)) <0)
+                       return isl_bool_error;
+
+               cgbr->cone->bmap = isl_basic_map_insert_div(cgbr->cone->bmap,
+                                                   r - o_div, div);
+               if (!cgbr->cone->bmap)
+                       return isl_bool_error;
+               if (isl_tab_push_var(cgbr->cone, isl_tab_undo_bmap_div,
+                                   &cgbr->cone->var[r]) < 0)
+                       return isl_bool_error;
        }
-       return context_tab_add_div(cgbr->tab, div,
+       return context_tab_insert_div(cgbr->tab, pos, div,
                                        context_gbr_add_ineq_wrap, context);
 }
 
@@ -3340,13 +3371,16 @@ static void context_gbr_invalidate(struct isl_context *context)
        cgbr->tab = NULL;
 }
 
-static void context_gbr_free(struct isl_context *context)
+static __isl_null struct isl_context *context_gbr_free(
+       struct isl_context *context)
 {
        struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
        isl_tab_free(cgbr->tab);
        isl_tab_free(cgbr->shifted);
        isl_tab_free(cgbr->cone);
        free(cgbr);
+
+       return NULL;
 }
 
 struct isl_context_op isl_context_gbr_op = {
@@ -3358,7 +3392,7 @@ struct isl_context_op isl_context_gbr_op = {
        context_gbr_ineq_sign,
        context_gbr_test_ineq,
        context_gbr_get_div,
-       context_gbr_add_div,
+       context_gbr_insert_div,
        context_gbr_detect_equalities,
        context_gbr_best_split,
        context_gbr_is_empty,
@@ -3397,15 +3431,34 @@ error:
        return NULL;
 }
 
+/* Allocate a context corresponding to "dom".
+ * The representation specific fields are initialized by
+ * isl_context_lex_alloc or isl_context_gbr_alloc.
+ * The shared "n_unknown" field is initialized to the number
+ * of final unknown integer divisions in "dom".
+ */
 static struct isl_context *isl_context_alloc(__isl_keep isl_basic_set *dom)
 {
+       struct isl_context *context;
+       int first;
+
        if (!dom)
                return NULL;
 
        if (dom->ctx->opt->context == ISL_CONTEXT_LEXMIN)
-               return isl_context_lex_alloc(dom);
+               context = isl_context_lex_alloc(dom);
        else
-               return isl_context_gbr_alloc(dom);
+               context = isl_context_gbr_alloc(dom);
+
+       if (!context)
+               return NULL;
+
+       first = isl_basic_set_first_unknown_div(dom);
+       if (first < 0)
+               return context->op->free(context);
+       context->n_unknown = isl_basic_set_dim(dom, isl_dim_div) - first;
+
+       return context;
 }
 
 /* Construct an isl_sol_map structure for accumulating the solution.
@@ -5302,110 +5355,6 @@ error:
        sol->sol.error = 1;
 }
 
-/* Return the equality constraint in "bset" that defines existentially
- * quantified variable "pos" in terms of earlier dimensions.
- * The equality constraint is guaranteed to exist by the caller.
- * If "c" is not NULL, then it is the result of a previous call
- * to this function for the same variable, so simply return the input "c"
- * in that case.
- */
-static __isl_give isl_constraint *get_equality(__isl_keep isl_basic_set *bset,
-       int pos, __isl_take isl_constraint *c)
-{
-       int r;
-
-       if (c)
-               return c;
-       r = isl_basic_set_has_defining_equality(bset, isl_dim_div, pos, &c);
-       if (r < 0)
-               return NULL;
-       if (!r)
-               isl_die(isl_basic_set_get_ctx(bset), isl_error_internal,
-                       "unexpected missing equality", return NULL);
-       return c;
-}
-
-/* Given a set "dom", of which only the first "n_known" existentially
- * quantified variables have a known explicit representation, and
- * a matrix "M", the rows of which are defined in terms of the dimensions
- * of "dom", eliminate all references to the existentially quantified
- * variables without a known explicit representation from "M"
- * by exploiting the equality constraints of "dom".
- *
- * In particular, for each of those existentially quantified variables,
- * if there are non-zero entries in the corresponding column of "M",
- * then look for an equality constraint of "dom" that defines that variable
- * in terms of earlier variables and use it to clear the entries.
- *
- * In particular, if the equality is of the form
- *
- *     f() + a alpha = 0
- *
- * while the matrix entry is b/d (with d the global denominator of "M"),
- * then first scale the matrix such that the entry becomes b'/d' with
- * b' a multiple of a.  Do this by multiplying the entire matrix
- * by abs(a/gcd(a,b)).  Then subtract the equality multiplied by b'/a
- * from the row of "M" to clear the entry.
- */
-static __isl_give isl_mat *eliminate_unknown_divs(__isl_take isl_mat *M,
-       __isl_keep isl_basic_set *dom, int n_known)
-{
-       int i, j, n_div, off;
-       isl_int t;
-       isl_constraint *c = NULL;
-
-       if (!M)
-               return NULL;
-
-       n_div = isl_basic_set_dim(dom, isl_dim_div);
-       off = M->n_col - n_div;
-
-       isl_int_init(t);
-       for (i = n_div - 1; i >= n_known; --i) {
-               for (j = 1; j < M->n_row; ++j) {
-                       if (isl_int_is_zero(M->row[j][off + i]))
-                               continue;
-                       c = get_equality(dom, i, c);
-                       if (!c)
-                               goto error;
-                       isl_int_gcd(t, M->row[j][off + i], c->v->el[off + i]);
-                       isl_int_divexact(t, c->v->el[off + i], t);
-                       isl_int_abs(t, t);
-                       M = isl_mat_scale(M, t);
-                       M = isl_mat_cow(M);
-                       if (!M)
-                               goto error;
-                       isl_int_divexact(t,
-                                       M->row[j][off + i], c->v->el[off + i]);
-                       isl_seq_submul(M->row[j], t, c->v->el, M->n_col);
-               }
-               c = isl_constraint_free(c);
-       }
-       isl_int_clear(t);
-
-       return M;
-error:
-       isl_int_clear(t);
-       isl_constraint_free(c);
-       isl_mat_free(M);
-       return NULL;
-}
-
-/* Return the index of the last known div of "bset" after "start" and
- * up to (but not including) "end".
- * Return "start" if there is no such known div.
- */
-static int last_known_div_after(__isl_keep isl_basic_set *bset,
-       int start, int end)
-{
-       for (end = end - 1; end > start; --end) {
-               if (isl_basic_set_div_is_known(bset, end))
-                       return end;
-       }
-
-       return start;
-}
-
 /* Set the affine expressions in "ma" according to the rows in "M", which
  * are defined over the local space "ls".
  * The matrix "M" may have extra (zero) columns beyond the number
@@ -5418,6 +5367,9 @@ static __isl_give isl_multi_aff *set_from_affine_matrix(
        int i, dim;
        isl_aff *aff;
 
+       if (!ma || !ls || !M)
+               goto error;
+
        dim = isl_local_space_dim(ls, isl_dim_all);
        for (i = 1; i < M->n_row; ++i) {
                aff = isl_aff_alloc(isl_local_space_copy(ls));
@@ -5432,6 +5384,11 @@ static __isl_give isl_multi_aff *set_from_affine_matrix(
        isl_mat_free(M);
 
        return ma;
+error:
+       isl_local_space_free(ls);
+       isl_mat_free(M);
+       isl_multi_aff_free(ma);
+       return NULL;
 }
 
 /* Given a basic map "dom" that represents the context and an affine
@@ -5443,21 +5400,13 @@ static __isl_give isl_multi_aff *set_from_affine_matrix(
  * existentially quantified variables, in which case they also appear
  * in "dom".  These need to be removed before creating the affine
  * expression because an affine expression cannot be defined in terms
- * of existentially quantified variables without a known representation.
- * In particular, they are first moved to the end in both "dom" and "M" and
- * then ignored in "M".  In principle, the final columns of "M"
- * (i.e., those that will be ignored) should be zero at this stage
+ * Since newly added integer divisions are inserted before these
+ * existentially quantified variables, they are still in the final
+ * positions and the corresponding final columns "M" are zero
  * because align_context_divs adds the existentially quantified
- * variables of the context to the main tableau without any constraints.
- * The computed minimal value can therefore not depend on these variables.
- * However, additional integer divisions that get added for parametric cuts
- * get added to the end and they may happen to be equal to some affine
- * expression involving the original existentially quantified variables.
- * These equality constraints are then propagated to the main tableau
- * such that the computed minimum can in fact depend on those existentially
- * quantified variables.  This dependence can however be removed again
- * by exploiting the equality constraints in "dom".
- * eliminate_unknown_divs takes care of this.
+ * variables of the context to the main tableau without any constraints and
+ * any equality constraints that are added later on can only serve
+ * to eliminate these existentially quantified variables.
  */
 static void sol_pma_add(struct isl_sol_pma *sol,
        __isl_take isl_basic_set *dom, __isl_take isl_mat *M)
@@ -5465,23 +5414,10 @@ static void sol_pma_add(struct isl_sol_pma *sol,
        isl_local_space *ls;
        isl_multi_aff *maff;
        isl_pw_multi_aff *pma;
-       int n_div, n_known, end, off;
+       int n_div, n_known;
 
        n_div = isl_basic_set_dim(dom, isl_dim_div);
-       off = M->n_col - n_div;
-       end = n_div;
-       for (n_known = 0; n_known < end; ++n_known) {
-               if (isl_basic_set_div_is_known(dom, n_known))
-                       continue;
-               end = last_known_div_after(dom, n_known, end);
-               if (end == n_known)
-                       break;
-               isl_basic_set_swap_div(dom, n_known, end);
-               M = isl_mat_swap_cols(M, off + n_known, off + end);
-       }
-       dom = isl_basic_set_gauss(dom, NULL);
-       if (n_known < n_div)
-               M = eliminate_unknown_divs(M, dom, n_known);
+       n_known = n_div - sol->sol.context->n_unknown;
 
        maff = isl_multi_aff_alloc(isl_pw_multi_aff_get_space(sol->pma));
        ls = isl_basic_set_get_local_space(dom);
index 42964d8..1eda6e0 100644 (file)
@@ -2297,6 +2297,11 @@ struct {
                "247j >= 62738 - i and 509j <= 129795 + i and "
                "742j >= 188724 - i; "
            "[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
+       { "{ [a] -> [b] : 0 <= b <= 255 and -509 + a <= 512b < a and "
+                       "16*floor((8 + b)/16) <= 7 + b; "
+           "[a] -> [1] }",
+         "{ [a] -> [b = 1] : a >= 510 or a <= 0; "
+           "[a] -> [b = 0] : 0 < a <= 509 }" },
 };
 
 static int test_lexmin(struct isl_ctx *ctx)