+/* Given a pair of divs div1 and div2 such that, expect for the lower bound l
+ * and the upper bound u, div1 always occurs together with div2 in the form
+ * (div1 + m div2), where m is the constant range on the variable div1
+ * allowed by l and u, replace the pair div1 and div2 by a single
+ * div that is equal to div1 + m div2.
+ *
+ * The new div will appear in the location that contains div2.
+ * We need to modify all constraints that contain
+ * div2 = (div - div1) / m
+ * (If a constraint does not contain div2, it will also not contain div1.)
+ * If the constraint also contains div1, then we know they appear
+ * as f (div1 + m div2) and we can simply replace (div1 + m div2) by div,
+ * i.e., the coefficient of div is f.
+ *
+ * Otherwise, we first need to introduce div1 into the constraint.
+ * Let the l be
+ *
+ * div1 + f >=0
+ *
+ * and u
+ *
+ * -div1 + f' >= 0
+ *
+ * A lower bound on div2
+ *
+ * n div2 + t >= 0
+ *
+ * can be replaced by
+ *
+ * (n * (m div 2 + div1) + m t + n f)/g >= 0
+ *
+ * with g = gcd(m,n).
+ * An upper bound
+ *
+ * -n div2 + t >= 0
+ *
+ * can be replaced by
+ *
+ * (-n * (m div2 + div1) + m t + n f')/g >= 0
+ *
+ * These constraint are those that we would obtain from eliminating
+ * div1 using Fourier-Motzkin.
+ *
+ * After all constraints have been modified, we drop the lower and upper
+ * bound and then drop div1.
+ */
+static struct isl_basic_map *coalesce_divs(struct isl_basic_map *bmap,
+ unsigned div1, unsigned div2, unsigned l, unsigned u)
+{
+ isl_int a;
+ isl_int b;
+ isl_int m;
+ unsigned dim, total;
+ int i;
+
+ dim = isl_dim_total(bmap->dim);
+ total = 1 + dim + bmap->n_div;
+
+ isl_int_init(a);
+ isl_int_init(b);
+ isl_int_init(m);
+ isl_int_add(m, bmap->ineq[l][0], bmap->ineq[u][0]);
+ isl_int_add_ui(m, m, 1);
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (i == l || i == u)
+ continue;
+ if (isl_int_is_zero(bmap->ineq[i][1 + dim + div2]))
+ continue;
+ if (isl_int_is_zero(bmap->ineq[i][1 + dim + div1])) {
+ isl_int_gcd(b, m, bmap->ineq[i][1 + dim + div2]);
+ isl_int_divexact(a, m, b);
+ isl_int_divexact(b, bmap->ineq[i][1 + dim + div2], b);
+ if (isl_int_is_pos(b)) {
+ isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
+ b, bmap->ineq[l], total);
+ } else {
+ isl_int_neg(b, b);
+ isl_seq_combine(bmap->ineq[i], a, bmap->ineq[i],
+ b, bmap->ineq[u], total);
+ }
+ }
+ isl_int_set(bmap->ineq[i][1 + dim + div2],
+ bmap->ineq[i][1 + dim + div1]);
+ isl_int_set_si(bmap->ineq[i][1 + dim + div1], 0);
+ }
+
+ isl_int_clear(a);
+ isl_int_clear(b);
+ isl_int_clear(m);
+ if (l > u) {
+ isl_basic_map_drop_inequality(bmap, l);
+ isl_basic_map_drop_inequality(bmap, u);
+ } else {
+ isl_basic_map_drop_inequality(bmap, u);
+ isl_basic_map_drop_inequality(bmap, l);
+ }
+ bmap = isl_basic_map_drop_div(bmap, div1);
+ return bmap;
+}
+
+/* First check if we can coalesce any pair of divs and
+ * then continue with dropping more redundant divs.
+ *
+ * We loop over all pairs of lower and upper bounds on a div
+ * with coefficient 1 and -1, respectively, check if there
+ * is any other div "c" with which we can coalesce the div
+ * and if so, perform the coalescing.
+ */
+static struct isl_basic_map *coalesce_or_drop_more_redundant_divs(
+ struct isl_basic_map *bmap, int *pairs, int n)
+{
+ int i, l, u;
+ unsigned dim;
+
+ dim = isl_dim_total(bmap->dim);
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (!pairs[i])
+ continue;
+ for (l = 0; l < bmap->n_ineq; ++l) {
+ if (!isl_int_is_one(bmap->ineq[l][1 + dim + i]))
+ continue;
+ for (u = 0; u < bmap->n_ineq; ++u) {
+ int c;
+
+ if (!isl_int_is_negone(bmap->ineq[u][1+dim+i]))
+ continue;
+ c = div_find_coalesce(bmap, pairs, i, l, u);
+ if (c < 0)
+ continue;
+ free(pairs);
+ bmap = coalesce_divs(bmap, i, c, l, u);
+ return isl_basic_map_drop_redundant_divs(bmap);
+ }
+ }
+ }
+
+ return drop_more_redundant_divs(bmap, pairs, n);
+}
+