[polly] r228193 - Import isl(+imath) as an external library into Polly

Tobias Grosser tobias at grosser.es
Wed Feb 4 12:55:55 PST 2015


Added: polly/trunk/lib/External/isl/isl_tab_pip.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tab_pip.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_tab_pip.c (added)
+++ polly/trunk/lib/External/isl/isl_tab_pip.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5681 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010      INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
+ */
+
+#include <isl_ctx_private.h>
+#include "isl_map_private.h"
+#include <isl_seq.h>
+#include "isl_tab.h"
+#include "isl_sample.h"
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_aff_private.h>
+#include <isl_options_private.h>
+#include <isl_config.h>
+
+/*
+ * The implementation of parametric integer linear programming in this file
+ * was inspired by the paper "Parametric Integer Programming" and the
+ * report "Solving systems of affine (in)equalities" by Paul Feautrier
+ * (and others).
+ *
+ * The strategy used for obtaining a feasible solution is different
+ * from the one used in isl_tab.c.  In particular, in isl_tab.c,
+ * upon finding a constraint that is not yet satisfied, we pivot
+ * in a row that increases the constant term of the row holding the
+ * constraint, making sure the sample solution remains feasible
+ * for all the constraints it already satisfied.
+ * Here, we always pivot in the row holding the constraint,
+ * choosing a column that induces the lexicographically smallest
+ * increment to the sample solution.
+ *
+ * By starting out from a sample value that is lexicographically
+ * smaller than any integer point in the problem space, the first
+ * feasible integer sample point we find will also be the lexicographically
+ * smallest.  If all variables can be assumed to be non-negative,
+ * then the initial sample value may be chosen equal to zero.
+ * However, we will not make this assumption.  Instead, we apply
+ * the "big parameter" trick.  Any variable x is then not directly
+ * used in the tableau, but instead it is represented by another
+ * variable x' = M + x, where M is an arbitrarily large (positive)
+ * value.  x' is therefore always non-negative, whatever the value of x.
+ * Taking as initial sample value x' = 0 corresponds to x = -M,
+ * which is always smaller than any possible value of x.
+ *
+ * The big parameter trick is used in the main tableau and
+ * also in the context tableau if isl_context_lex is used.
+ * In this case, each tableaus has its own big parameter.
+ * Before doing any real work, we check if all the parameters
+ * happen to be non-negative.  If so, we drop the column corresponding
+ * to M from the initial context tableau.
+ * If isl_context_gbr is used, then the big parameter trick is only
+ * used in the main tableau.
+ */
+
+struct isl_context;
+struct isl_context_op {
+	/* detect nonnegative parameters in context and mark them in tab */
+	struct isl_tab *(*detect_nonnegative_parameters)(
+			struct isl_context *context, struct isl_tab *tab);
+	/* return temporary reference to basic set representation of context */
+	struct isl_basic_set *(*peek_basic_set)(struct isl_context *context);
+	/* return temporary reference to tableau representation of context */
+	struct isl_tab *(*peek_tab)(struct isl_context *context);
+	/* add equality; check is 1 if eq may not be valid;
+	 * update is 1 if we may want to call ineq_sign on context later.
+	 */
+	void (*add_eq)(struct isl_context *context, isl_int *eq,
+			int check, int update);
+	/* add inequality; check is 1 if ineq may not be valid;
+	 * update is 1 if we may want to call ineq_sign on context later.
+	 */
+	void (*add_ineq)(struct isl_context *context, isl_int *ineq,
+			int check, int update);
+	/* check sign of ineq based on previous information.
+	 * strict is 1 if saturation should be treated as a positive sign.
+	 */
+	enum isl_tab_row_sign (*ineq_sign)(struct isl_context *context,
+			isl_int *ineq, int strict);
+	/* check if inequality maintains feasibility */
+	int (*test_ineq)(struct isl_context *context, isl_int *ineq);
+	/* 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);
+	int (*detect_equalities)(struct isl_context *context,
+			struct isl_tab *tab);
+	/* return row index of "best" split */
+	int (*best_split)(struct isl_context *context, struct isl_tab *tab);
+	/* check if context has already been determined to be empty */
+	int (*is_empty)(struct isl_context *context);
+	/* check if context is still usable */
+	int (*is_ok)(struct isl_context *context);
+	/* save a copy/snapshot of context */
+	void *(*save)(struct isl_context *context);
+	/* restore saved context */
+	void (*restore)(struct isl_context *context, void *);
+	/* discard saved context */
+	void (*discard)(void *);
+	/* invalidate context */
+	void (*invalidate)(struct isl_context *context);
+	/* free context */
+	void (*free)(struct isl_context *context);
+};
+
+struct isl_context {
+	struct isl_context_op *op;
+};
+
+struct isl_context_lex {
+	struct isl_context context;
+	struct isl_tab *tab;
+};
+
+/* A stack (linked list) of solutions of subtrees of the search space.
+ *
+ * "M" describes the solution in terms of the dimensions of "dom".
+ * The number of columns of "M" is one more than the total number
+ * of dimensions of "dom".
+ *
+ * If "M" is NULL, then there is no solution on "dom".
+ */
+struct isl_partial_sol {
+	int level;
+	struct isl_basic_set *dom;
+	struct isl_mat *M;
+
+	struct isl_partial_sol *next;
+};
+
+struct isl_sol;
+struct isl_sol_callback {
+	struct isl_tab_callback callback;
+	struct isl_sol *sol;
+};
+
+/* isl_sol is an interface for constructing a solution to
+ * a parametric integer linear programming problem.
+ * Every time the algorithm reaches a state where a solution
+ * can be read off from the tableau (including cases where the tableau
+ * is empty), the function "add" is called on the isl_sol passed
+ * to find_solutions_main.
+ *
+ * The context tableau is owned by isl_sol and is updated incrementally.
+ *
+ * There are currently two implementations of this interface,
+ * isl_sol_map, which simply collects the solutions in an isl_map
+ * and (optionally) the parts of the context where there is no solution
+ * in an isl_set, and
+ * isl_sol_for, which calls a user-defined function for each part of
+ * the solution.
+ */
+struct isl_sol {
+	int error;
+	int rational;
+	int level;
+	int max;
+	int n_out;
+	struct isl_context *context;
+	struct isl_partial_sol *partial;
+	void (*add)(struct isl_sol *sol,
+			    struct isl_basic_set *dom, struct isl_mat *M);
+	void (*add_empty)(struct isl_sol *sol, struct isl_basic_set *bset);
+	void (*free)(struct isl_sol *sol);
+	struct isl_sol_callback	dec_level;
+};
+
+static void sol_free(struct isl_sol *sol)
+{
+	struct isl_partial_sol *partial, *next;
+	if (!sol)
+		return;
+	for (partial = sol->partial; partial; partial = next) {
+		next = partial->next;
+		isl_basic_set_free(partial->dom);
+		isl_mat_free(partial->M);
+		free(partial);
+	}
+	sol->free(sol);
+}
+
+/* Push a partial solution represented by a domain and mapping M
+ * onto the stack of partial solutions.
+ */
+static void sol_push_sol(struct isl_sol *sol,
+	struct isl_basic_set *dom, struct isl_mat *M)
+{
+	struct isl_partial_sol *partial;
+
+	if (sol->error || !dom)
+		goto error;
+
+	partial = isl_alloc_type(dom->ctx, struct isl_partial_sol);
+	if (!partial)
+		goto error;
+
+	partial->level = sol->level;
+	partial->dom = dom;
+	partial->M = M;
+	partial->next = sol->partial;
+
+	sol->partial = partial;
+
+	return;
+error:
+	isl_basic_set_free(dom);
+	isl_mat_free(M);
+	sol->error = 1;
+}
+
+/* Pop one partial solution from the partial solution stack and
+ * pass it on to sol->add or sol->add_empty.
+ */
+static void sol_pop_one(struct isl_sol *sol)
+{
+	struct isl_partial_sol *partial;
+
+	partial = sol->partial;
+	sol->partial = partial->next;
+
+	if (partial->M)
+		sol->add(sol, partial->dom, partial->M);
+	else
+		sol->add_empty(sol, partial->dom);
+	free(partial);
+}
+
+/* Return a fresh copy of the domain represented by the context tableau.
+ */
+static struct isl_basic_set *sol_domain(struct isl_sol *sol)
+{
+	struct isl_basic_set *bset;
+
+	if (sol->error)
+		return NULL;
+
+	bset = isl_basic_set_dup(sol->context->op->peek_basic_set(sol->context));
+	bset = isl_basic_set_update_from_tab(bset,
+			sol->context->op->peek_tab(sol->context));
+
+	return bset;
+}
+
+/* Check whether two partial solutions have the same mapping, where n_div
+ * is the number of divs that the two partial solutions have in common.
+ */
+static int same_solution(struct isl_partial_sol *s1, struct isl_partial_sol *s2,
+	unsigned n_div)
+{
+	int i;
+	unsigned dim;
+
+	if (!s1->M != !s2->M)
+		return 0;
+	if (!s1->M)
+		return 1;
+
+	dim = isl_basic_set_total_dim(s1->dom) - s1->dom->n_div;
+
+	for (i = 0; i < s1->M->n_row; ++i) {
+		if (isl_seq_first_non_zero(s1->M->row[i]+1+dim+n_div,
+					    s1->M->n_col-1-dim-n_div) != -1)
+			return 0;
+		if (isl_seq_first_non_zero(s2->M->row[i]+1+dim+n_div,
+					    s2->M->n_col-1-dim-n_div) != -1)
+			return 0;
+		if (!isl_seq_eq(s1->M->row[i], s2->M->row[i], 1+dim+n_div))
+			return 0;
+	}
+	return 1;
+}
+
+/* Pop all solutions from the partial solution stack that were pushed onto
+ * the stack at levels that are deeper than the current level.
+ * If the two topmost elements on the stack have the same level
+ * and represent the same solution, then their domains are combined.
+ * This combined domain is the same as the current context domain
+ * as sol_pop is called each time we move back to a higher level.
+ */
+static void sol_pop(struct isl_sol *sol)
+{
+	struct isl_partial_sol *partial;
+	unsigned n_div;
+
+	if (sol->error)
+		return;
+
+	if (sol->level == 0) {
+		for (partial = sol->partial; partial; partial = sol->partial)
+			sol_pop_one(sol);
+		return;
+	}
+
+	partial = sol->partial;
+	if (!partial)
+		return;
+
+	if (partial->level <= sol->level)
+		return;
+
+	if (partial->next && partial->next->level == partial->level) {
+		n_div = isl_basic_set_dim(
+				sol->context->op->peek_basic_set(sol->context),
+				isl_dim_div);
+
+		if (!same_solution(partial, partial->next, n_div)) {
+			sol_pop_one(sol);
+			sol_pop_one(sol);
+		} else {
+			struct isl_basic_set *bset;
+			isl_mat *M;
+			unsigned n;
+
+			n = isl_basic_set_dim(partial->next->dom, isl_dim_div);
+			n -= n_div;
+			bset = sol_domain(sol);
+			isl_basic_set_free(partial->next->dom);
+			partial->next->dom = bset;
+			M = partial->next->M;
+			if (M) {
+				M = isl_mat_drop_cols(M, M->n_col - n, n);
+				partial->next->M = M;
+				if (!M)
+					goto error;
+			}
+			partial->next->level = sol->level;
+
+			if (!bset)
+				goto error;
+
+			sol->partial = partial->next;
+			isl_basic_set_free(partial->dom);
+			isl_mat_free(partial->M);
+			free(partial);
+		}
+	} else
+		sol_pop_one(sol);
+
+	if (0)
+error:		sol->error = 1;
+}
+
+static void sol_dec_level(struct isl_sol *sol)
+{
+	if (sol->error)
+		return;
+
+	sol->level--;
+
+	sol_pop(sol);
+}
+
+static int sol_dec_level_wrap(struct isl_tab_callback *cb)
+{
+	struct isl_sol_callback *callback = (struct isl_sol_callback *)cb;
+
+	sol_dec_level(callback->sol);
+
+	return callback->sol->error ? -1 : 0;
+}
+
+/* Move down to next level and push callback onto context tableau
+ * to decrease the level again when it gets rolled back across
+ * the current state.  That is, dec_level will be called with
+ * the context tableau in the same state as it is when inc_level
+ * is called.
+ */
+static void sol_inc_level(struct isl_sol *sol)
+{
+	struct isl_tab *tab;
+
+	if (sol->error)
+		return;
+
+	sol->level++;
+	tab = sol->context->op->peek_tab(sol->context);
+	if (isl_tab_push_callback(tab, &sol->dec_level.callback) < 0)
+		sol->error = 1;
+}
+
+static void scale_rows(struct isl_mat *mat, isl_int m, int n_row)
+{
+	int i;
+
+	if (isl_int_is_one(m))
+		return;
+
+	for (i = 0; i < n_row; ++i)
+		isl_seq_scale(mat->row[i], mat->row[i], m, mat->n_col);
+}
+
+/* Add the solution identified by the tableau and the context tableau.
+ *
+ * The layout of the variables is as follows.
+ *	tab->n_var is equal to the total number of variables in the input
+ *			map (including divs that were copied from the context)
+ *			+ the number of extra divs constructed
+ *      Of these, the first tab->n_param and the last tab->n_div variables
+ *	correspond to the variables in the context, i.e.,
+ *		tab->n_param + tab->n_div = context_tab->n_var
+ *	tab->n_param is equal to the number of parameters and input
+ *			dimensions in the input map
+ *	tab->n_div is equal to the number of divs in the context
+ *
+ * If there is no solution, then call add_empty with a basic set
+ * that corresponds to the context tableau.  (If add_empty is NULL,
+ * then do nothing).
+ *
+ * If there is a solution, then first construct a matrix that maps
+ * all dimensions of the context to the output variables, i.e.,
+ * the output dimensions in the input map.
+ * The divs in the input map (if any) that do not correspond to any
+ * div in the context do not appear in the solution.
+ * The algorithm will make sure that they have an integer value,
+ * but these values themselves are of no interest.
+ * We have to be careful not to drop or rearrange any divs in the
+ * context because that would change the meaning of the matrix.
+ *
+ * To extract the value of the output variables, it should be noted
+ * that we always use a big parameter M in the main tableau and so
+ * the variable stored in this tableau is not an output variable x itself, but
+ *	x' = M + x (in case of minimization)
+ * or
+ *	x' = M - x (in case of maximization)
+ * If x' appears in a column, then its optimal value is zero,
+ * which means that the optimal value of x is an unbounded number
+ * (-M for minimization and M for maximization).
+ * We currently assume that the output dimensions in the original map
+ * are bounded, so this cannot occur.
+ * Similarly, when x' appears in a row, then the coefficient of M in that
+ * row is necessarily 1.
+ * If the row in the tableau represents
+ *	d x' = c + d M + e(y)
+ * then, in case of minimization, the corresponding row in the matrix
+ * will be
+ *	a c + a e(y)
+ * with a d = m, the (updated) common denominator of the matrix.
+ * In case of maximization, the row will be
+ *	-a c - a e(y)
+ */
+static void sol_add(struct isl_sol *sol, struct isl_tab *tab)
+{
+	struct isl_basic_set *bset = NULL;
+	struct isl_mat *mat = NULL;
+	unsigned off;
+	int row;
+	isl_int m;
+
+	if (sol->error || !tab)
+		goto error;
+
+	if (tab->empty && !sol->add_empty)
+		return;
+	if (sol->context->op->is_empty(sol->context))
+		return;
+
+	bset = sol_domain(sol);
+
+	if (tab->empty) {
+		sol_push_sol(sol, bset, NULL);
+		return;
+	}
+
+	off = 2 + tab->M;
+
+	mat = isl_mat_alloc(tab->mat->ctx, 1 + sol->n_out,
+					    1 + tab->n_param + tab->n_div);
+	if (!mat)
+		goto error;
+
+	isl_int_init(m);
+
+	isl_seq_clr(mat->row[0] + 1, mat->n_col - 1);
+	isl_int_set_si(mat->row[0][0], 1);
+	for (row = 0; row < sol->n_out; ++row) {
+		int i = tab->n_param + row;
+		int r, j;
+
+		isl_seq_clr(mat->row[1 + row], mat->n_col);
+		if (!tab->var[i].is_row) {
+			if (tab->M)
+				isl_die(mat->ctx, isl_error_invalid,
+					"unbounded optimum", goto error2);
+			continue;
+		}
+
+		r = tab->var[i].index;
+		if (tab->M &&
+		    isl_int_ne(tab->mat->row[r][2], tab->mat->row[r][0]))
+			isl_die(mat->ctx, isl_error_invalid,
+				"unbounded optimum", goto error2);
+		isl_int_gcd(m, mat->row[0][0], tab->mat->row[r][0]);
+		isl_int_divexact(m, tab->mat->row[r][0], m);
+		scale_rows(mat, m, 1 + row);
+		isl_int_divexact(m, mat->row[0][0], tab->mat->row[r][0]);
+		isl_int_mul(mat->row[1 + row][0], m, tab->mat->row[r][1]);
+		for (j = 0; j < tab->n_param; ++j) {
+			int col;
+			if (tab->var[j].is_row)
+				continue;
+			col = tab->var[j].index;
+			isl_int_mul(mat->row[1 + row][1 + j], m,
+				    tab->mat->row[r][off + col]);
+		}
+		for (j = 0; j < tab->n_div; ++j) {
+			int col;
+			if (tab->var[tab->n_var - tab->n_div+j].is_row)
+				continue;
+			col = tab->var[tab->n_var - tab->n_div+j].index;
+			isl_int_mul(mat->row[1 + row][1 + tab->n_param + j], m,
+				    tab->mat->row[r][off + col]);
+		}
+		if (sol->max)
+			isl_seq_neg(mat->row[1 + row], mat->row[1 + row],
+				    mat->n_col);
+	}
+
+	isl_int_clear(m);
+
+	sol_push_sol(sol, bset, mat);
+	return;
+error2:
+	isl_int_clear(m);
+error:
+	isl_basic_set_free(bset);
+	isl_mat_free(mat);
+	sol->error = 1;
+}
+
+struct isl_sol_map {
+	struct isl_sol	sol;
+	struct isl_map	*map;
+	struct isl_set	*empty;
+};
+
+static void sol_map_free(struct isl_sol_map *sol_map)
+{
+	if (!sol_map)
+		return;
+	if (sol_map->sol.context)
+		sol_map->sol.context->op->free(sol_map->sol.context);
+	isl_map_free(sol_map->map);
+	isl_set_free(sol_map->empty);
+	free(sol_map);
+}
+
+static void sol_map_free_wrap(struct isl_sol *sol)
+{
+	sol_map_free((struct isl_sol_map *)sol);
+}
+
+/* This function is called for parts of the context where there is
+ * no solution, with "bset" corresponding to the context tableau.
+ * Simply add the basic set to the set "empty".
+ */
+static void sol_map_add_empty(struct isl_sol_map *sol,
+	struct isl_basic_set *bset)
+{
+	if (!bset)
+		goto error;
+	isl_assert(bset->ctx, sol->empty, goto error);
+
+	sol->empty = isl_set_grow(sol->empty, 1);
+	bset = isl_basic_set_simplify(bset);
+	bset = isl_basic_set_finalize(bset);
+	sol->empty = isl_set_add_basic_set(sol->empty, isl_basic_set_copy(bset));
+	if (!sol->empty)
+		goto error;
+	isl_basic_set_free(bset);
+	return;
+error:
+	isl_basic_set_free(bset);
+	sol->sol.error = 1;
+}
+
+static void sol_map_add_empty_wrap(struct isl_sol *sol,
+	struct isl_basic_set *bset)
+{
+	sol_map_add_empty((struct isl_sol_map *)sol, bset);
+}
+
+/* Given a basic map "dom" that represents the context and an affine
+ * matrix "M" that maps the dimensions of the context to the
+ * output variables, construct a basic map with the same parameters
+ * and divs as the context, the dimensions of the context as input
+ * dimensions and a number of output dimensions that is equal to
+ * the number of output dimensions in the input map.
+ *
+ * The constraints and divs of the context are simply copied
+ * from "dom".  For each row
+ *	x = c + e(y)
+ * an equality
+ *	c + e(y) - d x = 0
+ * is added, with d the common denominator of M.
+ */
+static void sol_map_add(struct isl_sol_map *sol,
+	struct isl_basic_set *dom, struct isl_mat *M)
+{
+	int i;
+	struct isl_basic_map *bmap = NULL;
+	unsigned n_eq;
+	unsigned n_ineq;
+	unsigned nparam;
+	unsigned total;
+	unsigned n_div;
+	unsigned n_out;
+
+	if (sol->sol.error || !dom || !M)
+		goto error;
+
+	n_out = sol->sol.n_out;
+	n_eq = dom->n_eq + n_out;
+	n_ineq = dom->n_ineq;
+	n_div = dom->n_div;
+	nparam = isl_basic_set_total_dim(dom) - n_div;
+	total = isl_map_dim(sol->map, isl_dim_all);
+	bmap = isl_basic_map_alloc_space(isl_map_get_space(sol->map),
+					n_div, n_eq, 2 * n_div + n_ineq);
+	if (!bmap)
+		goto error;
+	if (sol->sol.rational)
+		ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
+	for (i = 0; i < dom->n_div; ++i) {
+		int k = isl_basic_map_alloc_div(bmap);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bmap->div[k], dom->div[i], 1 + 1 + nparam);
+		isl_seq_clr(bmap->div[k] + 1 + 1 + nparam, total - nparam);
+		isl_seq_cpy(bmap->div[k] + 1 + 1 + total,
+			    dom->div[i] + 1 + 1 + nparam, i);
+	}
+	for (i = 0; i < dom->n_eq; ++i) {
+		int k = isl_basic_map_alloc_equality(bmap);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bmap->eq[k], dom->eq[i], 1 + nparam);
+		isl_seq_clr(bmap->eq[k] + 1 + nparam, total - nparam);
+		isl_seq_cpy(bmap->eq[k] + 1 + total,
+			    dom->eq[i] + 1 + nparam, n_div);
+	}
+	for (i = 0; i < dom->n_ineq; ++i) {
+		int k = isl_basic_map_alloc_inequality(bmap);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bmap->ineq[k], dom->ineq[i], 1 + nparam);
+		isl_seq_clr(bmap->ineq[k] + 1 + nparam, total - nparam);
+		isl_seq_cpy(bmap->ineq[k] + 1 + total,
+			dom->ineq[i] + 1 + nparam, n_div);
+	}
+	for (i = 0; i < M->n_row - 1; ++i) {
+		int k = isl_basic_map_alloc_equality(bmap);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bmap->eq[k], M->row[1 + i], 1 + nparam);
+		isl_seq_clr(bmap->eq[k] + 1 + nparam, n_out);
+		isl_int_neg(bmap->eq[k][1 + nparam + i], M->row[0][0]);
+		isl_seq_cpy(bmap->eq[k] + 1 + nparam + n_out,
+			    M->row[1 + i] + 1 + nparam, n_div);
+	}
+	bmap = isl_basic_map_simplify(bmap);
+	bmap = isl_basic_map_finalize(bmap);
+	sol->map = isl_map_grow(sol->map, 1);
+	sol->map = isl_map_add_basic_map(sol->map, bmap);
+	isl_basic_set_free(dom);
+	isl_mat_free(M);
+	if (!sol->map)
+		sol->sol.error = 1;
+	return;
+error:
+	isl_basic_set_free(dom);
+	isl_mat_free(M);
+	isl_basic_map_free(bmap);
+	sol->sol.error = 1;
+}
+
+static void sol_map_add_wrap(struct isl_sol *sol,
+	struct isl_basic_set *dom, struct isl_mat *M)
+{
+	sol_map_add((struct isl_sol_map *)sol, dom, M);
+}
+
+
+/* Store the "parametric constant" of row "row" of tableau "tab" in "line",
+ * i.e., the constant term and the coefficients of all variables that
+ * appear in the context tableau.
+ * Note that the coefficient of the big parameter M is NOT copied.
+ * The context tableau may not have a big parameter and even when it
+ * does, it is a different big parameter.
+ */
+static void get_row_parameter_line(struct isl_tab *tab, int row, isl_int *line)
+{
+	int i;
+	unsigned off = 2 + tab->M;
+
+	isl_int_set(line[0], tab->mat->row[row][1]);
+	for (i = 0; i < tab->n_param; ++i) {
+		if (tab->var[i].is_row)
+			isl_int_set_si(line[1 + i], 0);
+		else {
+			int col = tab->var[i].index;
+			isl_int_set(line[1 + i], tab->mat->row[row][off + col]);
+		}
+	}
+	for (i = 0; i < tab->n_div; ++i) {
+		if (tab->var[tab->n_var - tab->n_div + i].is_row)
+			isl_int_set_si(line[1 + tab->n_param + i], 0);
+		else {
+			int col = tab->var[tab->n_var - tab->n_div + i].index;
+			isl_int_set(line[1 + tab->n_param + i],
+				    tab->mat->row[row][off + col]);
+		}
+	}
+}
+
+/* Check if rows "row1" and "row2" have identical "parametric constants",
+ * as explained above.
+ * In this case, we also insist that the coefficients of the big parameter
+ * be the same as the values of the constants will only be the same
+ * if these coefficients are also the same.
+ */
+static int identical_parameter_line(struct isl_tab *tab, int row1, int row2)
+{
+	int i;
+	unsigned off = 2 + tab->M;
+
+	if (isl_int_ne(tab->mat->row[row1][1], tab->mat->row[row2][1]))
+		return 0;
+
+	if (tab->M && isl_int_ne(tab->mat->row[row1][2],
+				 tab->mat->row[row2][2]))
+		return 0;
+
+	for (i = 0; i < tab->n_param + tab->n_div; ++i) {
+		int pos = i < tab->n_param ? i :
+			tab->n_var - tab->n_div + i - tab->n_param;
+		int col;
+
+		if (tab->var[pos].is_row)
+			continue;
+		col = tab->var[pos].index;
+		if (isl_int_ne(tab->mat->row[row1][off + col],
+			       tab->mat->row[row2][off + col]))
+			return 0;
+	}
+	return 1;
+}
+
+/* Return an inequality that expresses that the "parametric constant"
+ * should be non-negative.
+ * This function is only called when the coefficient of the big parameter
+ * is equal to zero.
+ */
+static struct isl_vec *get_row_parameter_ineq(struct isl_tab *tab, int row)
+{
+	struct isl_vec *ineq;
+
+	ineq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_param + tab->n_div);
+	if (!ineq)
+		return NULL;
+
+	get_row_parameter_line(tab, row, ineq->el);
+	if (ineq)
+		ineq = isl_vec_normalize(ineq);
+
+	return ineq;
+}
+
+/* Normalize a div expression of the form
+ *
+ *	[(g*f(x) + c)/(g * m)]
+ *
+ * with c the constant term and f(x) the remaining coefficients, to
+ *
+ *	[(f(x) + [c/g])/m]
+ */
+static void normalize_div(__isl_keep isl_vec *div)
+{
+	isl_ctx *ctx = isl_vec_get_ctx(div);
+	int len = div->size - 2;
+
+	isl_seq_gcd(div->el + 2, len, &ctx->normalize_gcd);
+	isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, div->el[0]);
+
+	if (isl_int_is_one(ctx->normalize_gcd))
+		return;
+
+	isl_int_divexact(div->el[0], div->el[0], ctx->normalize_gcd);
+	isl_int_fdiv_q(div->el[1], div->el[1], ctx->normalize_gcd);
+	isl_seq_scale_down(div->el + 2, div->el + 2, ctx->normalize_gcd, len);
+}
+
+/* Return a integer division for use in a parametric cut based on the given row.
+ * In particular, let the parametric constant of the row be
+ *
+ *		\sum_i a_i y_i
+ *
+ * where y_0 = 1, but none of the y_i corresponds to the big parameter M.
+ * The div returned is equal to
+ *
+ *		floor(\sum_i {-a_i} y_i) = floor((\sum_i (-a_i mod d) y_i)/d)
+ */
+static struct isl_vec *get_row_parameter_div(struct isl_tab *tab, int row)
+{
+	struct isl_vec *div;
+
+	div = isl_vec_alloc(tab->mat->ctx, 1 + 1 + tab->n_param + tab->n_div);
+	if (!div)
+		return NULL;
+
+	isl_int_set(div->el[0], tab->mat->row[row][0]);
+	get_row_parameter_line(tab, row, div->el + 1);
+	isl_seq_neg(div->el + 1, div->el + 1, div->size - 1);
+	normalize_div(div);
+	isl_seq_fdiv_r(div->el + 1, div->el + 1, div->el[0], div->size - 1);
+
+	return div;
+}
+
+/* Return a integer division for use in transferring an integrality constraint
+ * to the context.
+ * In particular, let the parametric constant of the row be
+ *
+ *		\sum_i a_i y_i
+ *
+ * where y_0 = 1, but none of the y_i corresponds to the big parameter M.
+ * The the returned div is equal to
+ *
+ *		floor(\sum_i {a_i} y_i) = floor((\sum_i (a_i mod d) y_i)/d)
+ */
+static struct isl_vec *get_row_split_div(struct isl_tab *tab, int row)
+{
+	struct isl_vec *div;
+
+	div = isl_vec_alloc(tab->mat->ctx, 1 + 1 + tab->n_param + tab->n_div);
+	if (!div)
+		return NULL;
+
+	isl_int_set(div->el[0], tab->mat->row[row][0]);
+	get_row_parameter_line(tab, row, div->el + 1);
+	normalize_div(div);
+	isl_seq_fdiv_r(div->el + 1, div->el + 1, div->el[0], div->size - 1);
+
+	return div;
+}
+
+/* Construct and return an inequality that expresses an upper bound
+ * on the given div.
+ * In particular, if the div is given by
+ *
+ *	d = floor(e/m)
+ *
+ * then the inequality expresses
+ *
+ *	m d <= e
+ */
+static struct isl_vec *ineq_for_div(struct isl_basic_set *bset, unsigned div)
+{
+	unsigned total;
+	unsigned div_pos;
+	struct isl_vec *ineq;
+
+	if (!bset)
+		return NULL;
+
+	total = isl_basic_set_total_dim(bset);
+	div_pos = 1 + total - bset->n_div + div;
+
+	ineq = isl_vec_alloc(bset->ctx, 1 + total);
+	if (!ineq)
+		return NULL;
+
+	isl_seq_cpy(ineq->el, bset->div[div] + 1, 1 + total);
+	isl_int_neg(ineq->el[div_pos], bset->div[div][0]);
+	return ineq;
+}
+
+/* Given a row in the tableau and a div that was created
+ * using get_row_split_div and that has been constrained to equality, i.e.,
+ *
+ *		d = floor(\sum_i {a_i} y_i) = \sum_i {a_i} y_i
+ *
+ * replace the expression "\sum_i {a_i} y_i" in the row by d,
+ * i.e., we subtract "\sum_i {a_i} y_i" and add 1 d.
+ * The coefficients of the non-parameters in the tableau have been
+ * verified to be integral.  We can therefore simply replace coefficient b
+ * by floor(b).  For the coefficients of the parameters we have
+ * floor(a_i) = a_i - {a_i}, while for the other coefficients, we have
+ * floor(b) = b.
+ */
+static struct isl_tab *set_row_cst_to_div(struct isl_tab *tab, int row, int div)
+{
+	isl_seq_fdiv_q(tab->mat->row[row] + 1, tab->mat->row[row] + 1,
+			tab->mat->row[row][0], 1 + tab->M + tab->n_col);
+
+	isl_int_set_si(tab->mat->row[row][0], 1);
+
+	if (tab->var[tab->n_var - tab->n_div + div].is_row) {
+		int drow = tab->var[tab->n_var - tab->n_div + div].index;
+
+		isl_assert(tab->mat->ctx,
+			isl_int_is_one(tab->mat->row[drow][0]), goto error);
+		isl_seq_combine(tab->mat->row[row] + 1,
+			tab->mat->ctx->one, tab->mat->row[row] + 1,
+			tab->mat->ctx->one, tab->mat->row[drow] + 1,
+			1 + tab->M + tab->n_col);
+	} else {
+		int dcol = tab->var[tab->n_var - tab->n_div + div].index;
+
+		isl_int_add_ui(tab->mat->row[row][2 + tab->M + dcol],
+				tab->mat->row[row][2 + tab->M + dcol], 1);
+	}
+
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Check if the (parametric) constant of the given row is obviously
+ * negative, meaning that we don't need to consult the context tableau.
+ * If there is a big parameter and its coefficient is non-zero,
+ * then this coefficient determines the outcome.
+ * Otherwise, we check whether the constant is negative and
+ * all non-zero coefficients of parameters are negative and
+ * belong to non-negative parameters.
+ */
+static int is_obviously_neg(struct isl_tab *tab, int row)
+{
+	int i;
+	int col;
+	unsigned off = 2 + tab->M;
+
+	if (tab->M) {
+		if (isl_int_is_pos(tab->mat->row[row][2]))
+			return 0;
+		if (isl_int_is_neg(tab->mat->row[row][2]))
+			return 1;
+	}
+
+	if (isl_int_is_nonneg(tab->mat->row[row][1]))
+		return 0;
+	for (i = 0; i < tab->n_param; ++i) {
+		/* Eliminated parameter */
+		if (tab->var[i].is_row)
+			continue;
+		col = tab->var[i].index;
+		if (isl_int_is_zero(tab->mat->row[row][off + col]))
+			continue;
+		if (!tab->var[i].is_nonneg)
+			return 0;
+		if (isl_int_is_pos(tab->mat->row[row][off + col]))
+			return 0;
+	}
+	for (i = 0; i < tab->n_div; ++i) {
+		if (tab->var[tab->n_var - tab->n_div + i].is_row)
+			continue;
+		col = tab->var[tab->n_var - tab->n_div + i].index;
+		if (isl_int_is_zero(tab->mat->row[row][off + col]))
+			continue;
+		if (!tab->var[tab->n_var - tab->n_div + i].is_nonneg)
+			return 0;
+		if (isl_int_is_pos(tab->mat->row[row][off + col]))
+			return 0;
+	}
+	return 1;
+}
+
+/* Check if the (parametric) constant of the given row is obviously
+ * non-negative, meaning that we don't need to consult the context tableau.
+ * If there is a big parameter and its coefficient is non-zero,
+ * then this coefficient determines the outcome.
+ * Otherwise, we check whether the constant is non-negative and
+ * all non-zero coefficients of parameters are positive and
+ * belong to non-negative parameters.
+ */
+static int is_obviously_nonneg(struct isl_tab *tab, int row)
+{
+	int i;
+	int col;
+	unsigned off = 2 + tab->M;
+
+	if (tab->M) {
+		if (isl_int_is_pos(tab->mat->row[row][2]))
+			return 1;
+		if (isl_int_is_neg(tab->mat->row[row][2]))
+			return 0;
+	}
+
+	if (isl_int_is_neg(tab->mat->row[row][1]))
+		return 0;
+	for (i = 0; i < tab->n_param; ++i) {
+		/* Eliminated parameter */
+		if (tab->var[i].is_row)
+			continue;
+		col = tab->var[i].index;
+		if (isl_int_is_zero(tab->mat->row[row][off + col]))
+			continue;
+		if (!tab->var[i].is_nonneg)
+			return 0;
+		if (isl_int_is_neg(tab->mat->row[row][off + col]))
+			return 0;
+	}
+	for (i = 0; i < tab->n_div; ++i) {
+		if (tab->var[tab->n_var - tab->n_div + i].is_row)
+			continue;
+		col = tab->var[tab->n_var - tab->n_div + i].index;
+		if (isl_int_is_zero(tab->mat->row[row][off + col]))
+			continue;
+		if (!tab->var[tab->n_var - tab->n_div + i].is_nonneg)
+			return 0;
+		if (isl_int_is_neg(tab->mat->row[row][off + col]))
+			return 0;
+	}
+	return 1;
+}
+
+/* Given a row r and two columns, return the column that would
+ * lead to the lexicographically smallest increment in the sample
+ * solution when leaving the basis in favor of the row.
+ * Pivoting with column c will increment the sample value by a non-negative
+ * constant times a_{V,c}/a_{r,c}, with a_{V,c} the elements of column c
+ * corresponding to the non-parametric variables.
+ * If variable v appears in a column c_v, the a_{v,c} = 1 iff c = c_v,
+ * with all other entries in this virtual row equal to zero.
+ * If variable v appears in a row, then a_{v,c} is the element in column c
+ * of that row.
+ *
+ * Let v be the first variable with a_{v,c1}/a_{r,c1} != a_{v,c2}/a_{r,c2}.
+ * Then if a_{v,c1}/a_{r,c1} < a_{v,c2}/a_{r,c2}, i.e.,
+ * a_{v,c2} a_{r,c1} - a_{v,c1} a_{r,c2} > 0, c1 results in the minimal
+ * increment.  Otherwise, it's c2.
+ */
+static int lexmin_col_pair(struct isl_tab *tab,
+	int row, int col1, int col2, isl_int tmp)
+{
+	int i;
+	isl_int *tr;
+
+	tr = tab->mat->row[row] + 2 + tab->M;
+
+	for (i = tab->n_param; i < tab->n_var - tab->n_div; ++i) {
+		int s1, s2;
+		isl_int *r;
+
+		if (!tab->var[i].is_row) {
+			if (tab->var[i].index == col1)
+				return col2;
+			if (tab->var[i].index == col2)
+				return col1;
+			continue;
+		}
+
+		if (tab->var[i].index == row)
+			continue;
+
+		r = tab->mat->row[tab->var[i].index] + 2 + tab->M;
+		s1 = isl_int_sgn(r[col1]);
+		s2 = isl_int_sgn(r[col2]);
+		if (s1 == 0 && s2 == 0)
+			continue;
+		if (s1 < s2)
+			return col1;
+		if (s2 < s1)
+			return col2;
+
+		isl_int_mul(tmp, r[col2], tr[col1]);
+		isl_int_submul(tmp, r[col1], tr[col2]);
+		if (isl_int_is_pos(tmp))
+			return col1;
+		if (isl_int_is_neg(tmp))
+			return col2;
+	}
+	return -1;
+}
+
+/* Given a row in the tableau, find and return the column that would
+ * result in the lexicographically smallest, but positive, increment
+ * in the sample point.
+ * If there is no such column, then return tab->n_col.
+ * If anything goes wrong, return -1.
+ */
+static int lexmin_pivot_col(struct isl_tab *tab, int row)
+{
+	int j;
+	int col = tab->n_col;
+	isl_int *tr;
+	isl_int tmp;
+
+	tr = tab->mat->row[row] + 2 + tab->M;
+
+	isl_int_init(tmp);
+
+	for (j = tab->n_dead; j < tab->n_col; ++j) {
+		if (tab->col_var[j] >= 0 &&
+		    (tab->col_var[j] < tab->n_param  ||
+		    tab->col_var[j] >= tab->n_var - tab->n_div))
+			continue;
+
+		if (!isl_int_is_pos(tr[j]))
+			continue;
+
+		if (col == tab->n_col)
+			col = j;
+		else
+			col = lexmin_col_pair(tab, row, col, j, tmp);
+		isl_assert(tab->mat->ctx, col >= 0, goto error);
+	}
+
+	isl_int_clear(tmp);
+	return col;
+error:
+	isl_int_clear(tmp);
+	return -1;
+}
+
+/* Return the first known violated constraint, i.e., a non-negative
+ * constraint that currently has an either obviously negative value
+ * or a previously determined to be negative value.
+ *
+ * If any constraint has a negative coefficient for the big parameter,
+ * if any, then we return one of these first.
+ */
+static int first_neg(struct isl_tab *tab)
+{
+	int row;
+
+	if (tab->M)
+		for (row = tab->n_redundant; row < tab->n_row; ++row) {
+			if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+				continue;
+			if (!isl_int_is_neg(tab->mat->row[row][2]))
+				continue;
+			if (tab->row_sign)
+				tab->row_sign[row] = isl_tab_row_neg;
+			return row;
+		}
+	for (row = tab->n_redundant; row < tab->n_row; ++row) {
+		if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+			continue;
+		if (tab->row_sign) {
+			if (tab->row_sign[row] == 0 &&
+			    is_obviously_neg(tab, row))
+				tab->row_sign[row] = isl_tab_row_neg;
+			if (tab->row_sign[row] != isl_tab_row_neg)
+				continue;
+		} else if (!is_obviously_neg(tab, row))
+			continue;
+		return row;
+	}
+	return -1;
+}
+
+/* Check whether the invariant that all columns are lexico-positive
+ * is satisfied.  This function is not called from the current code
+ * but is useful during debugging.
+ */
+static void check_lexpos(struct isl_tab *tab) __attribute__ ((unused));
+static void check_lexpos(struct isl_tab *tab)
+{
+	unsigned off = 2 + tab->M;
+	int col;
+	int var;
+	int row;
+
+	for (col = tab->n_dead; col < tab->n_col; ++col) {
+		if (tab->col_var[col] >= 0 &&
+		    (tab->col_var[col] < tab->n_param ||
+		     tab->col_var[col] >= tab->n_var - tab->n_div))
+			continue;
+		for (var = tab->n_param; var < tab->n_var - tab->n_div; ++var) {
+			if (!tab->var[var].is_row) {
+				if (tab->var[var].index == col)
+					break;
+				else
+					continue;
+			}
+			row = tab->var[var].index;
+			if (isl_int_is_zero(tab->mat->row[row][off + col]))
+				continue;
+			if (isl_int_is_pos(tab->mat->row[row][off + col]))
+				break;
+			fprintf(stderr, "lexneg column %d (row %d)\n",
+				col, row);
+		}
+		if (var >= tab->n_var - tab->n_div)
+			fprintf(stderr, "zero column %d\n", col);
+	}
+}
+
+/* Report to the caller that the given constraint is part of an encountered
+ * conflict.
+ */
+static int report_conflicting_constraint(struct isl_tab *tab, int con)
+{
+	return tab->conflict(con, tab->conflict_user);
+}
+
+/* Given a conflicting row in the tableau, report all constraints
+ * involved in the row to the caller.  That is, the row itself
+ * (if it represents a constraint) and all constraint columns with
+ * non-zero (and therefore negative) coefficients.
+ */
+static int report_conflict(struct isl_tab *tab, int row)
+{
+	int j;
+	isl_int *tr;
+
+	if (!tab->conflict)
+		return 0;
+
+	if (tab->row_var[row] < 0 &&
+	    report_conflicting_constraint(tab, ~tab->row_var[row]) < 0)
+		return -1;
+
+	tr = tab->mat->row[row] + 2 + tab->M;
+
+	for (j = tab->n_dead; j < tab->n_col; ++j) {
+		if (tab->col_var[j] >= 0 &&
+		    (tab->col_var[j] < tab->n_param  ||
+		    tab->col_var[j] >= tab->n_var - tab->n_div))
+			continue;
+
+		if (!isl_int_is_neg(tr[j]))
+			continue;
+
+		if (tab->col_var[j] < 0 &&
+		    report_conflicting_constraint(tab, ~tab->col_var[j]) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* Resolve all known or obviously violated constraints through pivoting.
+ * In particular, as long as we can find any violated constraint, we
+ * look for a pivoting column that would result in the lexicographically
+ * smallest increment in the sample point.  If there is no such column
+ * then the tableau is infeasible.
+ */
+static int restore_lexmin(struct isl_tab *tab) WARN_UNUSED;
+static int restore_lexmin(struct isl_tab *tab)
+{
+	int row, col;
+
+	if (!tab)
+		return -1;
+	if (tab->empty)
+		return 0;
+	while ((row = first_neg(tab)) != -1) {
+		col = lexmin_pivot_col(tab, row);
+		if (col >= tab->n_col) {
+			if (report_conflict(tab, row) < 0)
+				return -1;
+			if (isl_tab_mark_empty(tab) < 0)
+				return -1;
+			return 0;
+		}
+		if (col < 0)
+			return -1;
+		if (isl_tab_pivot(tab, row, col) < 0)
+			return -1;
+	}
+	return 0;
+}
+
+/* Given a row that represents an equality, look for an appropriate
+ * pivoting column.
+ * In particular, if there are any non-zero coefficients among
+ * the non-parameter variables, then we take the last of these
+ * variables.  Eliminating this variable in terms of the other
+ * variables and/or parameters does not influence the property
+ * that all column in the initial tableau are lexicographically
+ * positive.  The row corresponding to the eliminated variable
+ * will only have non-zero entries below the diagonal of the
+ * initial tableau.  That is, we transform
+ *
+ *		I				I
+ *		  1		into		a
+ *		    I				  I
+ *
+ * If there is no such non-parameter variable, then we are dealing with
+ * pure parameter equality and we pick any parameter with coefficient 1 or -1
+ * for elimination.  This will ensure that the eliminated parameter
+ * always has an integer value whenever all the other parameters are integral.
+ * If there is no such parameter then we return -1.
+ */
+static int last_var_col_or_int_par_col(struct isl_tab *tab, int row)
+{
+	unsigned off = 2 + tab->M;
+	int i;
+
+	for (i = tab->n_var - tab->n_div - 1; i >= 0 && i >= tab->n_param; --i) {
+		int col;
+		if (tab->var[i].is_row)
+			continue;
+		col = tab->var[i].index;
+		if (col <= tab->n_dead)
+			continue;
+		if (!isl_int_is_zero(tab->mat->row[row][off + col]))
+			return col;
+	}
+	for (i = tab->n_dead; i < tab->n_col; ++i) {
+		if (isl_int_is_one(tab->mat->row[row][off + i]))
+			return i;
+		if (isl_int_is_negone(tab->mat->row[row][off + i]))
+			return i;
+	}
+	return -1;
+}
+
+/* Add an equality that is known to be valid to the tableau.
+ * We first check if we can eliminate a variable or a parameter.
+ * If not, we add the equality as two inequalities.
+ * In this case, the equality was a pure parameter equality and there
+ * is no need to resolve any constraint violations.
+ */
+static struct isl_tab *add_lexmin_valid_eq(struct isl_tab *tab, isl_int *eq)
+{
+	int i;
+	int r;
+
+	if (!tab)
+		return NULL;
+	r = isl_tab_add_row(tab, eq);
+	if (r < 0)
+		goto error;
+
+	r = tab->con[r].index;
+	i = last_var_col_or_int_par_col(tab, r);
+	if (i < 0) {
+		tab->con[r].is_nonneg = 1;
+		if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+			goto error;
+		isl_seq_neg(eq, eq, 1 + tab->n_var);
+		r = isl_tab_add_row(tab, eq);
+		if (r < 0)
+			goto error;
+		tab->con[r].is_nonneg = 1;
+		if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+			goto error;
+	} else {
+		if (isl_tab_pivot(tab, r, i) < 0)
+			goto error;
+		if (isl_tab_kill_col(tab, i) < 0)
+			goto error;
+		tab->n_eq++;
+	}
+
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Check if the given row is a pure constant.
+ */
+static int is_constant(struct isl_tab *tab, int row)
+{
+	unsigned off = 2 + tab->M;
+
+	return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
+					tab->n_col - tab->n_dead) == -1;
+}
+
+/* Add an equality that may or may not be valid to the tableau.
+ * If the resulting row is a pure constant, then it must be zero.
+ * Otherwise, the resulting tableau is empty.
+ *
+ * If the row is not a pure constant, then we add two inequalities,
+ * each time checking that they can be satisfied.
+ * In the end we try to use one of the two constraints to eliminate
+ * a column.
+ */
+static int add_lexmin_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
+static int add_lexmin_eq(struct isl_tab *tab, isl_int *eq)
+{
+	int r1, r2;
+	int row;
+	struct isl_tab_undo *snap;
+
+	if (!tab)
+		return -1;
+	snap = isl_tab_snap(tab);
+	r1 = isl_tab_add_row(tab, eq);
+	if (r1 < 0)
+		return -1;
+	tab->con[r1].is_nonneg = 1;
+	if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r1]) < 0)
+		return -1;
+
+	row = tab->con[r1].index;
+	if (is_constant(tab, row)) {
+		if (!isl_int_is_zero(tab->mat->row[row][1]) ||
+		    (tab->M && !isl_int_is_zero(tab->mat->row[row][2]))) {
+			if (isl_tab_mark_empty(tab) < 0)
+				return -1;
+			return 0;
+		}
+		if (isl_tab_rollback(tab, snap) < 0)
+			return -1;
+		return 0;
+	}
+
+	if (restore_lexmin(tab) < 0)
+		return -1;
+	if (tab->empty)
+		return 0;
+
+	isl_seq_neg(eq, eq, 1 + tab->n_var);
+
+	r2 = isl_tab_add_row(tab, eq);
+	if (r2 < 0)
+		return -1;
+	tab->con[r2].is_nonneg = 1;
+	if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r2]) < 0)
+		return -1;
+
+	if (restore_lexmin(tab) < 0)
+		return -1;
+	if (tab->empty)
+		return 0;
+
+	if (!tab->con[r1].is_row) {
+		if (isl_tab_kill_col(tab, tab->con[r1].index) < 0)
+			return -1;
+	} else if (!tab->con[r2].is_row) {
+		if (isl_tab_kill_col(tab, tab->con[r2].index) < 0)
+			return -1;
+	}
+
+	if (tab->bmap) {
+		tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
+		if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+			return -1;
+		isl_seq_neg(eq, eq, 1 + tab->n_var);
+		tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
+		isl_seq_neg(eq, eq, 1 + tab->n_var);
+		if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+			return -1;
+		if (!tab->bmap)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* Add an inequality to the tableau, resolving violations using
+ * restore_lexmin.
+ */
+static struct isl_tab *add_lexmin_ineq(struct isl_tab *tab, isl_int *ineq)
+{
+	int r;
+
+	if (!tab)
+		return NULL;
+	if (tab->bmap) {
+		tab->bmap = isl_basic_map_add_ineq(tab->bmap, ineq);
+		if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+			goto error;
+		if (!tab->bmap)
+			goto error;
+	}
+	r = isl_tab_add_row(tab, ineq);
+	if (r < 0)
+		goto error;
+	tab->con[r].is_nonneg = 1;
+	if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+		goto error;
+	if (isl_tab_row_is_redundant(tab, tab->con[r].index)) {
+		if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
+			goto error;
+		return tab;
+	}
+
+	if (restore_lexmin(tab) < 0)
+		goto error;
+	if (!tab->empty && tab->con[r].is_row &&
+		 isl_tab_row_is_redundant(tab, tab->con[r].index))
+		if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
+			goto error;
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Check if the coefficients of the parameters are all integral.
+ */
+static int integer_parameter(struct isl_tab *tab, int row)
+{
+	int i;
+	int col;
+	unsigned off = 2 + tab->M;
+
+	for (i = 0; i < tab->n_param; ++i) {
+		/* Eliminated parameter */
+		if (tab->var[i].is_row)
+			continue;
+		col = tab->var[i].index;
+		if (!isl_int_is_divisible_by(tab->mat->row[row][off + col],
+						tab->mat->row[row][0]))
+			return 0;
+	}
+	for (i = 0; i < tab->n_div; ++i) {
+		if (tab->var[tab->n_var - tab->n_div + i].is_row)
+			continue;
+		col = tab->var[tab->n_var - tab->n_div + i].index;
+		if (!isl_int_is_divisible_by(tab->mat->row[row][off + col],
+						tab->mat->row[row][0]))
+			return 0;
+	}
+	return 1;
+}
+
+/* Check if the coefficients of the non-parameter variables are all integral.
+ */
+static int integer_variable(struct isl_tab *tab, int row)
+{
+	int i;
+	unsigned off = 2 + tab->M;
+
+	for (i = tab->n_dead; i < tab->n_col; ++i) {
+		if (tab->col_var[i] >= 0 &&
+		    (tab->col_var[i] < tab->n_param ||
+		     tab->col_var[i] >= tab->n_var - tab->n_div))
+			continue;
+		if (!isl_int_is_divisible_by(tab->mat->row[row][off + i],
+						tab->mat->row[row][0]))
+			return 0;
+	}
+	return 1;
+}
+
+/* Check if the constant term is integral.
+ */
+static int integer_constant(struct isl_tab *tab, int row)
+{
+	return isl_int_is_divisible_by(tab->mat->row[row][1],
+					tab->mat->row[row][0]);
+}
+
+#define I_CST	1 << 0
+#define I_PAR	1 << 1
+#define I_VAR	1 << 2
+
+/* Check for next (non-parameter) variable after "var" (first if var == -1)
+ * that is non-integer and therefore requires a cut and return
+ * the index of the variable.
+ * For parametric tableaus, there are three parts in a row,
+ * the constant, the coefficients of the parameters and the rest.
+ * For each part, we check whether the coefficients in that part
+ * are all integral and if so, set the corresponding flag in *f.
+ * If the constant and the parameter part are integral, then the
+ * current sample value is integral and no cut is required
+ * (irrespective of whether the variable part is integral).
+ */
+static int next_non_integer_var(struct isl_tab *tab, int var, int *f)
+{
+	var = var < 0 ? tab->n_param : var + 1;
+
+	for (; var < tab->n_var - tab->n_div; ++var) {
+		int flags = 0;
+		int row;
+		if (!tab->var[var].is_row)
+			continue;
+		row = tab->var[var].index;
+		if (integer_constant(tab, row))
+			ISL_FL_SET(flags, I_CST);
+		if (integer_parameter(tab, row))
+			ISL_FL_SET(flags, I_PAR);
+		if (ISL_FL_ISSET(flags, I_CST) && ISL_FL_ISSET(flags, I_PAR))
+			continue;
+		if (integer_variable(tab, row))
+			ISL_FL_SET(flags, I_VAR);
+		*f = flags;
+		return var;
+	}
+	return -1;
+}
+
+/* Check for first (non-parameter) variable that is non-integer and
+ * therefore requires a cut and return the corresponding row.
+ * For parametric tableaus, there are three parts in a row,
+ * the constant, the coefficients of the parameters and the rest.
+ * For each part, we check whether the coefficients in that part
+ * are all integral and if so, set the corresponding flag in *f.
+ * If the constant and the parameter part are integral, then the
+ * current sample value is integral and no cut is required
+ * (irrespective of whether the variable part is integral).
+ */
+static int first_non_integer_row(struct isl_tab *tab, int *f)
+{
+	int var = next_non_integer_var(tab, -1, f);
+
+	return var < 0 ? -1 : tab->var[var].index;
+}
+
+/* Add a (non-parametric) cut to cut away the non-integral sample
+ * value of the given row.
+ *
+ * If the row is given by
+ *
+ *	m r = f + \sum_i a_i y_i
+ *
+ * then the cut is
+ *
+ *	c = - {-f/m} + \sum_i {a_i/m} y_i >= 0
+ *
+ * The big parameter, if any, is ignored, since it is assumed to be big
+ * enough to be divisible by any integer.
+ * If the tableau is actually a parametric tableau, then this function
+ * is only called when all coefficients of the parameters are integral.
+ * The cut therefore has zero coefficients for the parameters.
+ *
+ * The current value is known to be negative, so row_sign, if it
+ * exists, is set accordingly.
+ *
+ * Return the row of the cut or -1.
+ */
+static int add_cut(struct isl_tab *tab, int row)
+{
+	int i;
+	int r;
+	isl_int *r_row;
+	unsigned off = 2 + tab->M;
+
+	if (isl_tab_extend_cons(tab, 1) < 0)
+		return -1;
+	r = isl_tab_allocate_con(tab);
+	if (r < 0)
+		return -1;
+
+	r_row = tab->mat->row[tab->con[r].index];
+	isl_int_set(r_row[0], tab->mat->row[row][0]);
+	isl_int_neg(r_row[1], tab->mat->row[row][1]);
+	isl_int_fdiv_r(r_row[1], r_row[1], tab->mat->row[row][0]);
+	isl_int_neg(r_row[1], r_row[1]);
+	if (tab->M)
+		isl_int_set_si(r_row[2], 0);
+	for (i = 0; i < tab->n_col; ++i)
+		isl_int_fdiv_r(r_row[off + i],
+			tab->mat->row[row][off + i], tab->mat->row[row][0]);
+
+	tab->con[r].is_nonneg = 1;
+	if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+		return -1;
+	if (tab->row_sign)
+		tab->row_sign[tab->con[r].index] = isl_tab_row_neg;
+
+	return tab->con[r].index;
+}
+
+#define CUT_ALL 1
+#define CUT_ONE 0
+
+/* Given a non-parametric tableau, add cuts until an integer
+ * sample point is obtained or until the tableau is determined
+ * to be integer infeasible.
+ * As long as there is any non-integer value in the sample point,
+ * we add appropriate cuts, if possible, for each of these
+ * non-integer values and then resolve the violated
+ * cut constraints using restore_lexmin.
+ * If one of the corresponding rows is equal to an integral
+ * combination of variables/constraints plus a non-integral constant,
+ * then there is no way to obtain an integer point and we return
+ * a tableau that is marked empty.
+ * The parameter cutting_strategy controls the strategy used when adding cuts
+ * to remove non-integer points. CUT_ALL adds all possible cuts
+ * before continuing the search. CUT_ONE adds only one cut at a time.
+ */
+static struct isl_tab *cut_to_integer_lexmin(struct isl_tab *tab,
+	int cutting_strategy)
+{
+	int var;
+	int row;
+	int flags;
+
+	if (!tab)
+		return NULL;
+	if (tab->empty)
+		return tab;
+
+	while ((var = next_non_integer_var(tab, -1, &flags)) != -1) {
+		do {
+			if (ISL_FL_ISSET(flags, I_VAR)) {
+				if (isl_tab_mark_empty(tab) < 0)
+					goto error;
+				return tab;
+			}
+			row = tab->var[var].index;
+			row = add_cut(tab, row);
+			if (row < 0)
+				goto error;
+			if (cutting_strategy == CUT_ONE)
+				break;
+		} while ((var = next_non_integer_var(tab, var, &flags)) != -1);
+		if (restore_lexmin(tab) < 0)
+			goto error;
+		if (tab->empty)
+			break;
+	}
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Check whether all the currently active samples also satisfy the inequality
+ * "ineq" (treated as an equality if eq is set).
+ * Remove those samples that do not.
+ */
+static struct isl_tab *check_samples(struct isl_tab *tab, isl_int *ineq, int eq)
+{
+	int i;
+	isl_int v;
+
+	if (!tab)
+		return NULL;
+
+	isl_assert(tab->mat->ctx, tab->bmap, goto error);
+	isl_assert(tab->mat->ctx, tab->samples, goto error);
+	isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, goto error);
+
+	isl_int_init(v);
+	for (i = tab->n_outside; i < tab->n_sample; ++i) {
+		int sgn;
+		isl_seq_inner_product(ineq, tab->samples->row[i],
+					1 + tab->n_var, &v);
+		sgn = isl_int_sgn(v);
+		if (eq ? (sgn == 0) : (sgn >= 0))
+			continue;
+		tab = isl_tab_drop_sample(tab, i);
+		if (!tab)
+			break;
+	}
+	isl_int_clear(v);
+
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Check whether the sample value of the tableau is finite,
+ * i.e., either the tableau does not use a big parameter, or
+ * all values of the variables are equal to the big parameter plus
+ * some constant.  This constant is the actual sample value.
+ */
+static int sample_is_finite(struct isl_tab *tab)
+{
+	int i;
+
+	if (!tab->M)
+		return 1;
+
+	for (i = 0; i < tab->n_var; ++i) {
+		int row;
+		if (!tab->var[i].is_row)
+			return 0;
+		row = tab->var[i].index;
+		if (isl_int_ne(tab->mat->row[row][0], tab->mat->row[row][2]))
+			return 0;
+	}
+	return 1;
+}
+
+/* Check if the context tableau of sol has any integer points.
+ * Leave tab in empty state if no integer point can be found.
+ * If an integer point can be found and if moreover it is finite,
+ * then it is added to the list of sample values.
+ *
+ * This function is only called when none of the currently active sample
+ * values satisfies the most recently added constraint.
+ */
+static struct isl_tab *check_integer_feasible(struct isl_tab *tab)
+{
+	struct isl_tab_undo *snap;
+
+	if (!tab)
+		return NULL;
+
+	snap = isl_tab_snap(tab);
+	if (isl_tab_push_basis(tab) < 0)
+		goto error;
+
+	tab = cut_to_integer_lexmin(tab, CUT_ALL);
+	if (!tab)
+		goto error;
+
+	if (!tab->empty && sample_is_finite(tab)) {
+		struct isl_vec *sample;
+
+		sample = isl_tab_get_sample_value(tab);
+
+		if (isl_tab_add_sample(tab, sample) < 0)
+			goto error;
+	}
+
+	if (!tab->empty && isl_tab_rollback(tab, snap) < 0)
+		goto error;
+
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Check if any of the currently active sample values satisfies
+ * the inequality "ineq" (an equality if eq is set).
+ */
+static int tab_has_valid_sample(struct isl_tab *tab, isl_int *ineq, int eq)
+{
+	int i;
+	isl_int v;
+
+	if (!tab)
+		return -1;
+
+	isl_assert(tab->mat->ctx, tab->bmap, return -1);
+	isl_assert(tab->mat->ctx, tab->samples, return -1);
+	isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, return -1);
+
+	isl_int_init(v);
+	for (i = tab->n_outside; i < tab->n_sample; ++i) {
+		int sgn;
+		isl_seq_inner_product(ineq, tab->samples->row[i],
+					1 + tab->n_var, &v);
+		sgn = isl_int_sgn(v);
+		if (eq ? (sgn == 0) : (sgn >= 0))
+			break;
+	}
+	isl_int_clear(v);
+
+	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.
+ */
+static int context_tab_add_div(struct isl_tab *tab, struct isl_vec *div,
+	int (*add_ineq)(void *user, isl_int *), void *user)
+{
+	int i;
+	int r;
+	struct isl_mat *samples;
+	int nonneg;
+
+	r = isl_tab_add_div(tab, div, add_ineq, user);
+	if (r < 0)
+		return -1;
+	nonneg = tab->var[r].is_nonneg;
+	tab->var[r].frozen = 1;
+
+	samples = isl_mat_extend(tab->samples,
+			tab->n_sample, 1 + tab->n_var);
+	tab->samples = samples;
+	if (!samples)
+		return -1;
+	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]);
+	}
+
+	return nonneg;
+}
+
+/* Add a div specified by "div" to both the main tableau and
+ * the context tableau.  In case of the main tableau, we only
+ * 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.
+ */
+static int add_div(struct isl_tab *tab, struct isl_context *context,
+	struct isl_vec *div)
+{
+	int r;
+	int nonneg;
+
+	if ((nonneg = context->op->add_div(context, div)) < 0)
+		goto error;
+
+	if (!context->op->is_ok(context))
+		goto error;
+
+	if (isl_tab_extend_vars(tab, 1) < 0)
+		goto error;
+	r = isl_tab_allocate_var(tab);
+	if (r < 0)
+		goto error;
+	if (nonneg)
+		tab->var[r].is_nonneg = 1;
+	tab->var[r].frozen = 1;
+	tab->n_div++;
+
+	return tab->n_div - 1;
+error:
+	context->op->invalidate(context);
+	return -1;
+}
+
+static int find_div(struct isl_tab *tab, isl_int *div, isl_int denom)
+{
+	int i;
+	unsigned total = isl_basic_map_total_dim(tab->bmap);
+
+	for (i = 0; i < tab->bmap->n_div; ++i) {
+		if (isl_int_ne(tab->bmap->div[i][0], denom))
+			continue;
+		if (!isl_seq_eq(tab->bmap->div[i] + 1, div, 1 + total))
+			continue;
+		return i;
+	}
+	return -1;
+}
+
+/* Return the index of a div that corresponds to "div".
+ * We first check if we already have such a div and if not, we create one.
+ */
+static int get_div(struct isl_tab *tab, struct isl_context *context,
+	struct isl_vec *div)
+{
+	int d;
+	struct isl_tab *context_tab = context->op->peek_tab(context);
+
+	if (!context_tab)
+		return -1;
+
+	d = find_div(context_tab, div->el + 1, div->el[0]);
+	if (d != -1)
+		return d;
+
+	return add_div(tab, context, div);
+}
+
+/* Add a parametric cut to cut away the non-integral sample value
+ * of the give row.
+ * Let a_i be the coefficients of the constant term and the parameters
+ * and let b_i be the coefficients of the variables or constraints
+ * in basis of the tableau.
+ * Let q be the div q = floor(\sum_i {-a_i} y_i).
+ *
+ * The cut is expressed as
+ *
+ *	c = \sum_i -{-a_i} y_i + \sum_i {b_i} x_i + q >= 0
+ *
+ * If q did not already exist in the context tableau, then it is added first.
+ * If q is in a column of the main tableau then the "+ q" can be accomplished
+ * by setting the corresponding entry to the denominator of the constraint.
+ * If q happens to be in a row of the main tableau, then the corresponding
+ * row needs to be added instead (taking care of the denominators).
+ * Note that this is very unlikely, but perhaps not entirely impossible.
+ *
+ * The current value of the cut is known to be negative (or at least
+ * non-positive), so row_sign is set accordingly.
+ *
+ * Return the row of the cut or -1.
+ */
+static int add_parametric_cut(struct isl_tab *tab, int row,
+	struct isl_context *context)
+{
+	struct isl_vec *div;
+	int d;
+	int i;
+	int r;
+	isl_int *r_row;
+	int col;
+	int n;
+	unsigned off = 2 + tab->M;
+
+	if (!context)
+		return -1;
+
+	div = get_row_parameter_div(tab, row);
+	if (!div)
+		return -1;
+
+	n = tab->n_div;
+	d = context->op->get_div(context, tab, div);
+	isl_vec_free(div);
+	if (d < 0)
+		return -1;
+
+	if (isl_tab_extend_cons(tab, 1) < 0)
+		return -1;
+	r = isl_tab_allocate_con(tab);
+	if (r < 0)
+		return -1;
+
+	r_row = tab->mat->row[tab->con[r].index];
+	isl_int_set(r_row[0], tab->mat->row[row][0]);
+	isl_int_neg(r_row[1], tab->mat->row[row][1]);
+	isl_int_fdiv_r(r_row[1], r_row[1], tab->mat->row[row][0]);
+	isl_int_neg(r_row[1], r_row[1]);
+	if (tab->M)
+		isl_int_set_si(r_row[2], 0);
+	for (i = 0; i < tab->n_param; ++i) {
+		if (tab->var[i].is_row)
+			continue;
+		col = tab->var[i].index;
+		isl_int_neg(r_row[off + col], tab->mat->row[row][off + col]);
+		isl_int_fdiv_r(r_row[off + col], r_row[off + col],
+				tab->mat->row[row][0]);
+		isl_int_neg(r_row[off + col], r_row[off + col]);
+	}
+	for (i = 0; i < tab->n_div; ++i) {
+		if (tab->var[tab->n_var - tab->n_div + i].is_row)
+			continue;
+		col = tab->var[tab->n_var - tab->n_div + i].index;
+		isl_int_neg(r_row[off + col], tab->mat->row[row][off + col]);
+		isl_int_fdiv_r(r_row[off + col], r_row[off + col],
+				tab->mat->row[row][0]);
+		isl_int_neg(r_row[off + col], r_row[off + col]);
+	}
+	for (i = 0; i < tab->n_col; ++i) {
+		if (tab->col_var[i] >= 0 &&
+		    (tab->col_var[i] < tab->n_param ||
+		     tab->col_var[i] >= tab->n_var - tab->n_div))
+			continue;
+		isl_int_fdiv_r(r_row[off + i],
+			tab->mat->row[row][off + i], tab->mat->row[row][0]);
+	}
+	if (tab->var[tab->n_var - tab->n_div + d].is_row) {
+		isl_int gcd;
+		int d_row = tab->var[tab->n_var - tab->n_div + d].index;
+		isl_int_init(gcd);
+		isl_int_gcd(gcd, tab->mat->row[d_row][0], r_row[0]);
+		isl_int_divexact(r_row[0], r_row[0], gcd);
+		isl_int_divexact(gcd, tab->mat->row[d_row][0], gcd);
+		isl_seq_combine(r_row + 1, gcd, r_row + 1,
+				r_row[0], tab->mat->row[d_row] + 1,
+				off - 1 + tab->n_col);
+		isl_int_mul(r_row[0], r_row[0], tab->mat->row[d_row][0]);
+		isl_int_clear(gcd);
+	} else {
+		col = tab->var[tab->n_var - tab->n_div + d].index;
+		isl_int_set(r_row[off + col], tab->mat->row[row][0]);
+	}
+
+	tab->con[r].is_nonneg = 1;
+	if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+		return -1;
+	if (tab->row_sign)
+		tab->row_sign[tab->con[r].index] = isl_tab_row_neg;
+
+	row = tab->con[r].index;
+
+	if (d >= n && context->op->detect_equalities(context, tab) < 0)
+		return -1;
+
+	return row;
+}
+
+/* Construct a tableau for bmap that can be used for computing
+ * the lexicographic minimum (or maximum) of bmap.
+ * If not NULL, then dom is the domain where the minimum
+ * should be computed.  In this case, we set up a parametric
+ * tableau with row signs (initialized to "unknown").
+ * If M is set, then the tableau will use a big parameter.
+ * If max is set, then a maximum should be computed instead of a minimum.
+ * This means that for each variable x, the tableau will contain the variable
+ * x' = M - x, rather than x' = M + x.  This in turn means that the coefficient
+ * of the variables in all constraints are negated prior to adding them
+ * to the tableau.
+ */
+static struct isl_tab *tab_for_lexmin(struct isl_basic_map *bmap,
+	struct isl_basic_set *dom, unsigned M, int max)
+{
+	int i;
+	struct isl_tab *tab;
+	unsigned n_var;
+	unsigned o_var;
+
+	tab = isl_tab_alloc(bmap->ctx, 2 * bmap->n_eq + bmap->n_ineq + 1,
+			    isl_basic_map_total_dim(bmap), M);
+	if (!tab)
+		return NULL;
+
+	tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+	if (dom) {
+		tab->n_param = isl_basic_set_total_dim(dom) - dom->n_div;
+		tab->n_div = dom->n_div;
+		tab->row_sign = isl_calloc_array(bmap->ctx,
+					enum isl_tab_row_sign, tab->mat->n_row);
+		if (tab->mat->n_row && !tab->row_sign)
+			goto error;
+	}
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) {
+		if (isl_tab_mark_empty(tab) < 0)
+			goto error;
+		return tab;
+	}
+
+	for (i = tab->n_param; i < tab->n_var - tab->n_div; ++i) {
+		tab->var[i].is_nonneg = 1;
+		tab->var[i].frozen = 1;
+	}
+	o_var = 1 + tab->n_param;
+	n_var = tab->n_var - tab->n_param - tab->n_div;
+	for (i = 0; i < bmap->n_eq; ++i) {
+		if (max)
+			isl_seq_neg(bmap->eq[i] + o_var,
+				    bmap->eq[i] + o_var, n_var);
+		tab = add_lexmin_valid_eq(tab, bmap->eq[i]);
+		if (max)
+			isl_seq_neg(bmap->eq[i] + o_var,
+				    bmap->eq[i] + o_var, n_var);
+		if (!tab || tab->empty)
+			return tab;
+	}
+	if (bmap->n_eq && restore_lexmin(tab) < 0)
+		goto error;
+	for (i = 0; i < bmap->n_ineq; ++i) {
+		if (max)
+			isl_seq_neg(bmap->ineq[i] + o_var,
+				    bmap->ineq[i] + o_var, n_var);
+		tab = add_lexmin_ineq(tab, bmap->ineq[i]);
+		if (max)
+			isl_seq_neg(bmap->ineq[i] + o_var,
+				    bmap->ineq[i] + o_var, n_var);
+		if (!tab || tab->empty)
+			return tab;
+	}
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Given a main tableau where more than one row requires a split,
+ * determine and return the "best" row to split on.
+ *
+ * Given two rows in the main tableau, if the inequality corresponding
+ * to the first row is redundant with respect to that of the second row
+ * in the current tableau, then it is better to split on the second row,
+ * since in the positive part, both row will be positive.
+ * (In the negative part a pivot will have to be performed and just about
+ * anything can happen to the sign of the other row.)
+ *
+ * As a simple heuristic, we therefore select the row that makes the most
+ * of the other rows redundant.
+ *
+ * Perhaps it would also be useful to look at the number of constraints
+ * that conflict with any given constraint.
+ *
+ * best is the best row so far (-1 when we have not found any row yet).
+ * best_r is the number of other rows made redundant by row best.
+ * When best is still -1, bset_r is meaningless, but it is initialized
+ * to some arbitrary value (0) anyway.  Without this redundant initialization
+ * valgrind may warn about uninitialized memory accesses when isl
+ * is compiled with some versions of gcc.
+ */
+static int best_split(struct isl_tab *tab, struct isl_tab *context_tab)
+{
+	struct isl_tab_undo *snap;
+	int split;
+	int row;
+	int best = -1;
+	int best_r = 0;
+
+	if (isl_tab_extend_cons(context_tab, 2) < 0)
+		return -1;
+
+	snap = isl_tab_snap(context_tab);
+
+	for (split = tab->n_redundant; split < tab->n_row; ++split) {
+		struct isl_tab_undo *snap2;
+		struct isl_vec *ineq = NULL;
+		int r = 0;
+		int ok;
+
+		if (!isl_tab_var_from_row(tab, split)->is_nonneg)
+			continue;
+		if (tab->row_sign[split] != isl_tab_row_any)
+			continue;
+
+		ineq = get_row_parameter_ineq(tab, split);
+		if (!ineq)
+			return -1;
+		ok = isl_tab_add_ineq(context_tab, ineq->el) >= 0;
+		isl_vec_free(ineq);
+		if (!ok)
+			return -1;
+
+		snap2 = isl_tab_snap(context_tab);
+
+		for (row = tab->n_redundant; row < tab->n_row; ++row) {
+			struct isl_tab_var *var;
+
+			if (row == split)
+				continue;
+			if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+				continue;
+			if (tab->row_sign[row] != isl_tab_row_any)
+				continue;
+
+			ineq = get_row_parameter_ineq(tab, row);
+			if (!ineq)
+				return -1;
+			ok = isl_tab_add_ineq(context_tab, ineq->el) >= 0;
+			isl_vec_free(ineq);
+			if (!ok)
+				return -1;
+			var = &context_tab->con[context_tab->n_con - 1];
+			if (!context_tab->empty &&
+			    !isl_tab_min_at_most_neg_one(context_tab, var))
+				r++;
+			if (isl_tab_rollback(context_tab, snap2) < 0)
+				return -1;
+		}
+		if (best == -1 || r > best_r) {
+			best = split;
+			best_r = r;
+		}
+		if (isl_tab_rollback(context_tab, snap) < 0)
+			return -1;
+	}
+
+	return best;
+}
+
+static struct isl_basic_set *context_lex_peek_basic_set(
+	struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	if (!clex->tab)
+		return NULL;
+	return isl_tab_peek_bset(clex->tab);
+}
+
+static struct isl_tab *context_lex_peek_tab(struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	return clex->tab;
+}
+
+static void context_lex_add_eq(struct isl_context *context, isl_int *eq,
+		int check, int update)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	if (isl_tab_extend_cons(clex->tab, 2) < 0)
+		goto error;
+	if (add_lexmin_eq(clex->tab, eq) < 0)
+		goto error;
+	if (check) {
+		int v = tab_has_valid_sample(clex->tab, eq, 1);
+		if (v < 0)
+			goto error;
+		if (!v)
+			clex->tab = check_integer_feasible(clex->tab);
+	}
+	if (update)
+		clex->tab = check_samples(clex->tab, eq, 1);
+	return;
+error:
+	isl_tab_free(clex->tab);
+	clex->tab = NULL;
+}
+
+static void context_lex_add_ineq(struct isl_context *context, isl_int *ineq,
+		int check, int update)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	if (isl_tab_extend_cons(clex->tab, 1) < 0)
+		goto error;
+	clex->tab = add_lexmin_ineq(clex->tab, ineq);
+	if (check) {
+		int v = tab_has_valid_sample(clex->tab, ineq, 0);
+		if (v < 0)
+			goto error;
+		if (!v)
+			clex->tab = check_integer_feasible(clex->tab);
+	}
+	if (update)
+		clex->tab = check_samples(clex->tab, ineq, 0);
+	return;
+error:
+	isl_tab_free(clex->tab);
+	clex->tab = NULL;
+}
+
+static int context_lex_add_ineq_wrap(void *user, isl_int *ineq)
+{
+	struct isl_context *context = (struct isl_context *)user;
+	context_lex_add_ineq(context, ineq, 0, 0);
+	return context->op->is_ok(context) ? 0 : -1;
+}
+
+/* Check which signs can be obtained by "ineq" on all the currently
+ * active sample values.  See row_sign for more information.
+ */
+static enum isl_tab_row_sign tab_ineq_sign(struct isl_tab *tab, isl_int *ineq,
+	int strict)
+{
+	int i;
+	int sgn;
+	isl_int tmp;
+	enum isl_tab_row_sign res = isl_tab_row_unknown;
+
+	isl_assert(tab->mat->ctx, tab->samples, return isl_tab_row_unknown);
+	isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var,
+			return isl_tab_row_unknown);
+
+	isl_int_init(tmp);
+	for (i = tab->n_outside; i < tab->n_sample; ++i) {
+		isl_seq_inner_product(tab->samples->row[i], ineq,
+					1 + tab->n_var, &tmp);
+		sgn = isl_int_sgn(tmp);
+		if (sgn > 0 || (sgn == 0 && strict)) {
+			if (res == isl_tab_row_unknown)
+				res = isl_tab_row_pos;
+			if (res == isl_tab_row_neg)
+				res = isl_tab_row_any;
+		}
+		if (sgn < 0) {
+			if (res == isl_tab_row_unknown)
+				res = isl_tab_row_neg;
+			if (res == isl_tab_row_pos)
+				res = isl_tab_row_any;
+		}
+		if (res == isl_tab_row_any)
+			break;
+	}
+	isl_int_clear(tmp);
+
+	return res;
+}
+
+static enum isl_tab_row_sign context_lex_ineq_sign(struct isl_context *context,
+			isl_int *ineq, int strict)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	return tab_ineq_sign(clex->tab, ineq, strict);
+}
+
+/* Check whether "ineq" can be added to the tableau without rendering
+ * it infeasible.
+ */
+static int context_lex_test_ineq(struct isl_context *context, isl_int *ineq)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	struct isl_tab_undo *snap;
+	int feasible;
+
+	if (!clex->tab)
+		return -1;
+
+	if (isl_tab_extend_cons(clex->tab, 1) < 0)
+		return -1;
+
+	snap = isl_tab_snap(clex->tab);
+	if (isl_tab_push_basis(clex->tab) < 0)
+		return -1;
+	clex->tab = add_lexmin_ineq(clex->tab, ineq);
+	clex->tab = check_integer_feasible(clex->tab);
+	if (!clex->tab)
+		return -1;
+	feasible = !clex->tab->empty;
+	if (isl_tab_rollback(clex->tab, snap) < 0)
+		return -1;
+
+	return feasible;
+}
+
+static int context_lex_get_div(struct isl_context *context, struct isl_tab *tab,
+		struct isl_vec *div)
+{
+	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
+ * 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)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	int nonneg;
+	nonneg = context_tab_add_div(clex->tab, div,
+					context_lex_add_ineq_wrap, context);
+	if (nonneg < 0)
+		return -1;
+	if (clex->tab->M)
+		return 0;
+	return nonneg;
+}
+
+static int context_lex_detect_equalities(struct isl_context *context,
+		struct isl_tab *tab)
+{
+	return 0;
+}
+
+static int context_lex_best_split(struct isl_context *context,
+		struct isl_tab *tab)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	struct isl_tab_undo *snap;
+	int r;
+
+	snap = isl_tab_snap(clex->tab);
+	if (isl_tab_push_basis(clex->tab) < 0)
+		return -1;
+	r = best_split(tab, clex->tab);
+
+	if (r >= 0 && isl_tab_rollback(clex->tab, snap) < 0)
+		return -1;
+
+	return r;
+}
+
+static int context_lex_is_empty(struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	if (!clex->tab)
+		return -1;
+	return clex->tab->empty;
+}
+
+static void *context_lex_save(struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	struct isl_tab_undo *snap;
+
+	snap = isl_tab_snap(clex->tab);
+	if (isl_tab_push_basis(clex->tab) < 0)
+		return NULL;
+	if (isl_tab_save_samples(clex->tab) < 0)
+		return NULL;
+
+	return snap;
+}
+
+static void context_lex_restore(struct isl_context *context, void *save)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	if (isl_tab_rollback(clex->tab, (struct isl_tab_undo *)save) < 0) {
+		isl_tab_free(clex->tab);
+		clex->tab = NULL;
+	}
+}
+
+static void context_lex_discard(void *save)
+{
+}
+
+static int context_lex_is_ok(struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	return !!clex->tab;
+}
+
+/* For each variable in the context tableau, check if the variable can
+ * only attain non-negative values.  If so, mark the parameter as non-negative
+ * in the main tableau.  This allows for a more direct identification of some
+ * cases of violated constraints.
+ */
+static struct isl_tab *tab_detect_nonnegative_parameters(struct isl_tab *tab,
+	struct isl_tab *context_tab)
+{
+	int i;
+	struct isl_tab_undo *snap;
+	struct isl_vec *ineq = NULL;
+	struct isl_tab_var *var;
+	int n;
+
+	if (context_tab->n_var == 0)
+		return tab;
+
+	ineq = isl_vec_alloc(tab->mat->ctx, 1 + context_tab->n_var);
+	if (!ineq)
+		goto error;
+
+	if (isl_tab_extend_cons(context_tab, 1) < 0)
+		goto error;
+
+	snap = isl_tab_snap(context_tab);
+
+	n = 0;
+	isl_seq_clr(ineq->el, ineq->size);
+	for (i = 0; i < context_tab->n_var; ++i) {
+		isl_int_set_si(ineq->el[1 + i], 1);
+		if (isl_tab_add_ineq(context_tab, ineq->el) < 0)
+			goto error;
+		var = &context_tab->con[context_tab->n_con - 1];
+		if (!context_tab->empty &&
+		    !isl_tab_min_at_most_neg_one(context_tab, var)) {
+			int j = i;
+			if (i >= tab->n_param)
+				j = i - tab->n_param + tab->n_var - tab->n_div;
+			tab->var[j].is_nonneg = 1;
+			n++;
+		}
+		isl_int_set_si(ineq->el[1 + i], 0);
+		if (isl_tab_rollback(context_tab, snap) < 0)
+			goto error;
+	}
+
+	if (context_tab->M && n == context_tab->n_var) {
+		context_tab->mat = isl_mat_drop_cols(context_tab->mat, 2, 1);
+		context_tab->M = 0;
+	}
+
+	isl_vec_free(ineq);
+	return tab;
+error:
+	isl_vec_free(ineq);
+	isl_tab_free(tab);
+	return NULL;
+}
+
+static struct isl_tab *context_lex_detect_nonnegative_parameters(
+	struct isl_context *context, struct isl_tab *tab)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	struct isl_tab_undo *snap;
+
+	if (!tab)
+		return NULL;
+
+	snap = isl_tab_snap(clex->tab);
+	if (isl_tab_push_basis(clex->tab) < 0)
+		goto error;
+
+	tab = tab_detect_nonnegative_parameters(tab, clex->tab);
+
+	if (isl_tab_rollback(clex->tab, snap) < 0)
+		goto error;
+
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+static void context_lex_invalidate(struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	isl_tab_free(clex->tab);
+	clex->tab = NULL;
+}
+
+static void context_lex_free(struct isl_context *context)
+{
+	struct isl_context_lex *clex = (struct isl_context_lex *)context;
+	isl_tab_free(clex->tab);
+	free(clex);
+}
+
+struct isl_context_op isl_context_lex_op = {
+	context_lex_detect_nonnegative_parameters,
+	context_lex_peek_basic_set,
+	context_lex_peek_tab,
+	context_lex_add_eq,
+	context_lex_add_ineq,
+	context_lex_ineq_sign,
+	context_lex_test_ineq,
+	context_lex_get_div,
+	context_lex_add_div,
+	context_lex_detect_equalities,
+	context_lex_best_split,
+	context_lex_is_empty,
+	context_lex_is_ok,
+	context_lex_save,
+	context_lex_restore,
+	context_lex_discard,
+	context_lex_invalidate,
+	context_lex_free,
+};
+
+static struct isl_tab *context_tab_for_lexmin(struct isl_basic_set *bset)
+{
+	struct isl_tab *tab;
+
+	if (!bset)
+		return NULL;
+	tab = tab_for_lexmin((struct isl_basic_map *)bset, NULL, 1, 0);
+	if (!tab)
+		goto error;
+	if (isl_tab_track_bset(tab, bset) < 0)
+		goto error;
+	tab = isl_tab_init_samples(tab);
+	return tab;
+error:
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+static struct isl_context *isl_context_lex_alloc(struct isl_basic_set *dom)
+{
+	struct isl_context_lex *clex;
+
+	if (!dom)
+		return NULL;
+
+	clex = isl_alloc_type(dom->ctx, struct isl_context_lex);
+	if (!clex)
+		return NULL;
+
+	clex->context.op = &isl_context_lex_op;
+
+	clex->tab = context_tab_for_lexmin(isl_basic_set_copy(dom));
+	if (restore_lexmin(clex->tab) < 0)
+		goto error;
+	clex->tab = check_integer_feasible(clex->tab);
+	if (!clex->tab)
+		goto error;
+
+	return &clex->context;
+error:
+	clex->context.op->free(&clex->context);
+	return NULL;
+}
+
+/* Representation of the context when using generalized basis reduction.
+ *
+ * "shifted" contains the offsets of the unit hypercubes that lie inside the
+ * context.  Any rational point in "shifted" can therefore be rounded
+ * up to an integer point in the context.
+ * If the context is constrained by any equality, then "shifted" is not used
+ * as it would be empty.
+ */
+struct isl_context_gbr {
+	struct isl_context context;
+	struct isl_tab *tab;
+	struct isl_tab *shifted;
+	struct isl_tab *cone;
+};
+
+static struct isl_tab *context_gbr_detect_nonnegative_parameters(
+	struct isl_context *context, struct isl_tab *tab)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	if (!tab)
+		return NULL;
+	return tab_detect_nonnegative_parameters(tab, cgbr->tab);
+}
+
+static struct isl_basic_set *context_gbr_peek_basic_set(
+	struct isl_context *context)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	if (!cgbr->tab)
+		return NULL;
+	return isl_tab_peek_bset(cgbr->tab);
+}
+
+static struct isl_tab *context_gbr_peek_tab(struct isl_context *context)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	return cgbr->tab;
+}
+
+/* Initialize the "shifted" tableau of the context, which
+ * contains the constraints of the original tableau shifted
+ * by the sum of all negative coefficients.  This ensures
+ * that any rational point in the shifted tableau can
+ * be rounded up to yield an integer point in the original tableau.
+ */
+static void gbr_init_shifted(struct isl_context_gbr *cgbr)
+{
+	int i, j;
+	struct isl_vec *cst;
+	struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab);
+	unsigned dim = isl_basic_set_total_dim(bset);
+
+	cst = isl_vec_alloc(cgbr->tab->mat->ctx, bset->n_ineq);
+	if (!cst)
+		return;
+
+	for (i = 0; i < bset->n_ineq; ++i) {
+		isl_int_set(cst->el[i], bset->ineq[i][0]);
+		for (j = 0; j < dim; ++j) {
+			if (!isl_int_is_neg(bset->ineq[i][1 + j]))
+				continue;
+			isl_int_add(bset->ineq[i][0], bset->ineq[i][0],
+				    bset->ineq[i][1 + j]);
+		}
+	}
+
+	cgbr->shifted = isl_tab_from_basic_set(bset, 0);
+
+	for (i = 0; i < bset->n_ineq; ++i)
+		isl_int_set(bset->ineq[i][0], cst->el[i]);
+
+	isl_vec_free(cst);
+}
+
+/* Check if the shifted tableau is non-empty, and if so
+ * use the sample point to construct an integer point
+ * of the context tableau.
+ */
+static struct isl_vec *gbr_get_shifted_sample(struct isl_context_gbr *cgbr)
+{
+	struct isl_vec *sample;
+
+	if (!cgbr->shifted)
+		gbr_init_shifted(cgbr);
+	if (!cgbr->shifted)
+		return NULL;
+	if (cgbr->shifted->empty)
+		return isl_vec_alloc(cgbr->tab->mat->ctx, 0);
+
+	sample = isl_tab_get_sample_value(cgbr->shifted);
+	sample = isl_vec_ceil(sample);
+
+	return sample;
+}
+
+static struct isl_basic_set *drop_constant_terms(struct isl_basic_set *bset)
+{
+	int i;
+
+	if (!bset)
+		return NULL;
+
+	for (i = 0; i < bset->n_eq; ++i)
+		isl_int_set_si(bset->eq[i][0], 0);
+
+	for (i = 0; i < bset->n_ineq; ++i)
+		isl_int_set_si(bset->ineq[i][0], 0);
+
+	return bset;
+}
+
+static int use_shifted(struct isl_context_gbr *cgbr)
+{
+	if (!cgbr->tab)
+		return 0;
+	return cgbr->tab->bmap->n_eq == 0 && cgbr->tab->bmap->n_div == 0;
+}
+
+static struct isl_vec *gbr_get_sample(struct isl_context_gbr *cgbr)
+{
+	struct isl_basic_set *bset;
+	struct isl_basic_set *cone;
+
+	if (isl_tab_sample_is_integer(cgbr->tab))
+		return isl_tab_get_sample_value(cgbr->tab);
+
+	if (use_shifted(cgbr)) {
+		struct isl_vec *sample;
+
+		sample = gbr_get_shifted_sample(cgbr);
+		if (!sample || sample->size > 0)
+			return sample;
+
+		isl_vec_free(sample);
+	}
+
+	if (!cgbr->cone) {
+		bset = isl_tab_peek_bset(cgbr->tab);
+		cgbr->cone = isl_tab_from_recession_cone(bset, 0);
+		if (!cgbr->cone)
+			return NULL;
+		if (isl_tab_track_bset(cgbr->cone,
+					isl_basic_set_copy(bset)) < 0)
+			return NULL;
+	}
+	if (isl_tab_detect_implicit_equalities(cgbr->cone) < 0)
+		return NULL;
+
+	if (cgbr->cone->n_dead == cgbr->cone->n_col) {
+		struct isl_vec *sample;
+		struct isl_tab_undo *snap;
+
+		if (cgbr->tab->basis) {
+			if (cgbr->tab->basis->n_col != 1 + cgbr->tab->n_var) {
+				isl_mat_free(cgbr->tab->basis);
+				cgbr->tab->basis = NULL;
+			}
+			cgbr->tab->n_zero = 0;
+			cgbr->tab->n_unbounded = 0;
+		}
+
+		snap = isl_tab_snap(cgbr->tab);
+
+		sample = isl_tab_sample(cgbr->tab);
+
+		if (isl_tab_rollback(cgbr->tab, snap) < 0) {
+			isl_vec_free(sample);
+			return NULL;
+		}
+
+		return sample;
+	}
+
+	cone = isl_basic_set_dup(isl_tab_peek_bset(cgbr->cone));
+	cone = drop_constant_terms(cone);
+	cone = isl_basic_set_update_from_tab(cone, cgbr->cone);
+	cone = isl_basic_set_underlying_set(cone);
+	cone = isl_basic_set_gauss(cone, NULL);
+
+	bset = isl_basic_set_dup(isl_tab_peek_bset(cgbr->tab));
+	bset = isl_basic_set_update_from_tab(bset, cgbr->tab);
+	bset = isl_basic_set_underlying_set(bset);
+	bset = isl_basic_set_gauss(bset, NULL);
+
+	return isl_basic_set_sample_with_cone(bset, cone);
+}
+
+static void check_gbr_integer_feasible(struct isl_context_gbr *cgbr)
+{
+	struct isl_vec *sample;
+
+	if (!cgbr->tab)
+		return;
+
+	if (cgbr->tab->empty)
+		return;
+
+	sample = gbr_get_sample(cgbr);
+	if (!sample)
+		goto error;
+
+	if (sample->size == 0) {
+		isl_vec_free(sample);
+		if (isl_tab_mark_empty(cgbr->tab) < 0)
+			goto error;
+		return;
+	}
+
+	if (isl_tab_add_sample(cgbr->tab, sample) < 0)
+		goto error;
+
+	return;
+error:
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+}
+
+static struct isl_tab *add_gbr_eq(struct isl_tab *tab, isl_int *eq)
+{
+	if (!tab)
+		return NULL;
+
+	if (isl_tab_extend_cons(tab, 2) < 0)
+		goto error;
+
+	if (isl_tab_add_eq(tab, eq) < 0)
+		goto error;
+
+	return tab;
+error:
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Add the equality described by "eq" to the context.
+ * If "check" is set, then we check if the context is empty after
+ * adding the equality.
+ * If "update" is set, then we check if the samples are still valid.
+ *
+ * We do not explicitly add shifted copies of the equality to
+ * cgbr->shifted since they would conflict with each other.
+ * Instead, we directly mark cgbr->shifted empty.
+ */
+static void context_gbr_add_eq(struct isl_context *context, isl_int *eq,
+		int check, int update)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+
+	cgbr->tab = add_gbr_eq(cgbr->tab, eq);
+
+	if (cgbr->shifted && !cgbr->shifted->empty && use_shifted(cgbr)) {
+		if (isl_tab_mark_empty(cgbr->shifted) < 0)
+			goto error;
+	}
+
+	if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead) {
+		if (isl_tab_extend_cons(cgbr->cone, 2) < 0)
+			goto error;
+		if (isl_tab_add_eq(cgbr->cone, eq) < 0)
+			goto error;
+	}
+
+	if (check) {
+		int v = tab_has_valid_sample(cgbr->tab, eq, 1);
+		if (v < 0)
+			goto error;
+		if (!v)
+			check_gbr_integer_feasible(cgbr);
+	}
+	if (update)
+		cgbr->tab = check_samples(cgbr->tab, eq, 1);
+	return;
+error:
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+}
+
+static void add_gbr_ineq(struct isl_context_gbr *cgbr, isl_int *ineq)
+{
+	if (!cgbr->tab)
+		return;
+
+	if (isl_tab_extend_cons(cgbr->tab, 1) < 0)
+		goto error;
+
+	if (isl_tab_add_ineq(cgbr->tab, ineq) < 0)
+		goto error;
+
+	if (cgbr->shifted && !cgbr->shifted->empty && use_shifted(cgbr)) {
+		int i;
+		unsigned dim;
+		dim = isl_basic_map_total_dim(cgbr->tab->bmap);
+
+		if (isl_tab_extend_cons(cgbr->shifted, 1) < 0)
+			goto error;
+
+		for (i = 0; i < dim; ++i) {
+			if (!isl_int_is_neg(ineq[1 + i]))
+				continue;
+			isl_int_add(ineq[0], ineq[0], ineq[1 + i]);
+		}
+
+		if (isl_tab_add_ineq(cgbr->shifted, ineq) < 0)
+			goto error;
+
+		for (i = 0; i < dim; ++i) {
+			if (!isl_int_is_neg(ineq[1 + i]))
+				continue;
+			isl_int_sub(ineq[0], ineq[0], ineq[1 + i]);
+		}
+	}
+
+	if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead) {
+		if (isl_tab_extend_cons(cgbr->cone, 1) < 0)
+			goto error;
+		if (isl_tab_add_ineq(cgbr->cone, ineq) < 0)
+			goto error;
+	}
+
+	return;
+error:
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+}
+
+static void context_gbr_add_ineq(struct isl_context *context, isl_int *ineq,
+		int check, int update)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+
+	add_gbr_ineq(cgbr, ineq);
+	if (!cgbr->tab)
+		return;
+
+	if (check) {
+		int v = tab_has_valid_sample(cgbr->tab, ineq, 0);
+		if (v < 0)
+			goto error;
+		if (!v)
+			check_gbr_integer_feasible(cgbr);
+	}
+	if (update)
+		cgbr->tab = check_samples(cgbr->tab, ineq, 0);
+	return;
+error:
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+}
+
+static int context_gbr_add_ineq_wrap(void *user, isl_int *ineq)
+{
+	struct isl_context *context = (struct isl_context *)user;
+	context_gbr_add_ineq(context, ineq, 0, 0);
+	return context->op->is_ok(context) ? 0 : -1;
+}
+
+static enum isl_tab_row_sign context_gbr_ineq_sign(struct isl_context *context,
+			isl_int *ineq, int strict)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	return tab_ineq_sign(cgbr->tab, ineq, strict);
+}
+
+/* Check whether "ineq" can be added to the tableau without rendering
+ * it infeasible.
+ */
+static int context_gbr_test_ineq(struct isl_context *context, isl_int *ineq)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	struct isl_tab_undo *snap;
+	struct isl_tab_undo *shifted_snap = NULL;
+	struct isl_tab_undo *cone_snap = NULL;
+	int feasible;
+
+	if (!cgbr->tab)
+		return -1;
+
+	if (isl_tab_extend_cons(cgbr->tab, 1) < 0)
+		return -1;
+
+	snap = isl_tab_snap(cgbr->tab);
+	if (cgbr->shifted)
+		shifted_snap = isl_tab_snap(cgbr->shifted);
+	if (cgbr->cone)
+		cone_snap = isl_tab_snap(cgbr->cone);
+	add_gbr_ineq(cgbr, ineq);
+	check_gbr_integer_feasible(cgbr);
+	if (!cgbr->tab)
+		return -1;
+	feasible = !cgbr->tab->empty;
+	if (isl_tab_rollback(cgbr->tab, snap) < 0)
+		return -1;
+	if (shifted_snap) {
+		if (isl_tab_rollback(cgbr->shifted, shifted_snap))
+			return -1;
+	} else if (cgbr->shifted) {
+		isl_tab_free(cgbr->shifted);
+		cgbr->shifted = NULL;
+	}
+	if (cone_snap) {
+		if (isl_tab_rollback(cgbr->cone, cone_snap))
+			return -1;
+	} else if (cgbr->cone) {
+		isl_tab_free(cgbr->cone);
+		cgbr->cone = NULL;
+	}
+
+	return feasible;
+}
+
+/* Return the column of the last of the variables associated to
+ * a column that has a non-zero coefficient.
+ * This function is called in a context where only coefficients
+ * of parameters or divs can be non-zero.
+ */
+static int last_non_zero_var_col(struct isl_tab *tab, isl_int *p)
+{
+	int i;
+	int col;
+
+	if (tab->n_var == 0)
+		return -1;
+
+	for (i = tab->n_var - 1; i >= 0; --i) {
+		if (i >= tab->n_param && i < tab->n_var - tab->n_div)
+			continue;
+		if (tab->var[i].is_row)
+			continue;
+		col = tab->var[i].index;
+		if (!isl_int_is_zero(p[col]))
+			return col;
+	}
+
+	return -1;
+}
+
+/* Look through all the recently added equalities in the context
+ * to see if we can propagate any of them to the main tableau.
+ *
+ * The newly added equalities in the context are encoded as pairs
+ * of inequalities starting at inequality "first".
+ *
+ * We tentatively add each of these equalities to the main tableau
+ * and if this happens to result in a row with a final coefficient
+ * that is one or negative one, we use it to kill a column
+ * in the main tableau.  Otherwise, we discard the tentatively
+ * added row.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+static int propagate_equalities(struct isl_context_gbr *cgbr,
+	struct isl_tab *tab, unsigned first)
+{
+	int i;
+	struct isl_vec *eq = NULL;
+
+	eq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+	if (!eq)
+		goto error;
+
+	if (isl_tab_extend_cons(tab, (cgbr->tab->bmap->n_ineq - first)/2) < 0)
+		goto error;
+
+	isl_seq_clr(eq->el + 1 + tab->n_param,
+		    tab->n_var - tab->n_param - tab->n_div);
+	for (i = first; i < cgbr->tab->bmap->n_ineq; i += 2) {
+		int j;
+		int r;
+		struct isl_tab_undo *snap;
+		snap = isl_tab_snap(tab);
+
+		isl_seq_cpy(eq->el, cgbr->tab->bmap->ineq[i], 1 + tab->n_param);
+		isl_seq_cpy(eq->el + 1 + tab->n_var - tab->n_div,
+			    cgbr->tab->bmap->ineq[i] + 1 + tab->n_param,
+			    tab->n_div);
+
+		r = isl_tab_add_row(tab, eq->el);
+		if (r < 0)
+			goto error;
+		r = tab->con[r].index;
+		j = last_non_zero_var_col(tab, tab->mat->row[r] + 2 + tab->M);
+		if (j < 0 || j < tab->n_dead ||
+		    !isl_int_is_one(tab->mat->row[r][0]) ||
+		    (!isl_int_is_one(tab->mat->row[r][2 + tab->M + j]) &&
+		     !isl_int_is_negone(tab->mat->row[r][2 + tab->M + j]))) {
+			if (isl_tab_rollback(tab, snap) < 0)
+				goto error;
+			continue;
+		}
+		if (isl_tab_pivot(tab, r, j) < 0)
+			goto error;
+		if (isl_tab_kill_col(tab, j) < 0)
+			goto error;
+
+		if (restore_lexmin(tab) < 0)
+			goto error;
+	}
+
+	isl_vec_free(eq);
+
+	return 0;
+error:
+	isl_vec_free(eq);
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+	return -1;
+}
+
+static int context_gbr_detect_equalities(struct isl_context *context,
+	struct isl_tab *tab)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	struct isl_ctx *ctx;
+	unsigned n_ineq;
+
+	ctx = cgbr->tab->mat->ctx;
+
+	if (!cgbr->cone) {
+		struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab);
+		cgbr->cone = isl_tab_from_recession_cone(bset, 0);
+		if (!cgbr->cone)
+			goto error;
+		if (isl_tab_track_bset(cgbr->cone,
+					isl_basic_set_copy(bset)) < 0)
+			goto error;
+	}
+	if (isl_tab_detect_implicit_equalities(cgbr->cone) < 0)
+		goto error;
+
+	n_ineq = cgbr->tab->bmap->n_ineq;
+	cgbr->tab = isl_tab_detect_equalities(cgbr->tab, cgbr->cone);
+	if (!cgbr->tab)
+		return -1;
+	if (cgbr->tab->bmap->n_ineq > n_ineq &&
+	    propagate_equalities(cgbr, tab, n_ineq) < 0)
+		return -1;
+
+	return 0;
+error:
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+	return -1;
+}
+
+static int context_gbr_get_div(struct isl_context *context, struct isl_tab *tab,
+		struct isl_vec *div)
+{
+	return get_div(tab, context, div);
+}
+
+static int context_gbr_add_div(struct isl_context *context, struct isl_vec *div)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	if (cgbr->cone) {
+		int k;
+
+		if (isl_tab_extend_cons(cgbr->cone, 3) < 0)
+			return -1;
+		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 context_tab_add_div(cgbr->tab, div,
+					context_gbr_add_ineq_wrap, context);
+}
+
+static int context_gbr_best_split(struct isl_context *context,
+		struct isl_tab *tab)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	struct isl_tab_undo *snap;
+	int r;
+
+	snap = isl_tab_snap(cgbr->tab);
+	r = best_split(tab, cgbr->tab);
+
+	if (r >= 0 && isl_tab_rollback(cgbr->tab, snap) < 0)
+		return -1;
+
+	return r;
+}
+
+static int context_gbr_is_empty(struct isl_context *context)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	if (!cgbr->tab)
+		return -1;
+	return cgbr->tab->empty;
+}
+
+struct isl_gbr_tab_undo {
+	struct isl_tab_undo *tab_snap;
+	struct isl_tab_undo *shifted_snap;
+	struct isl_tab_undo *cone_snap;
+};
+
+static void *context_gbr_save(struct isl_context *context)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	struct isl_gbr_tab_undo *snap;
+
+	if (!cgbr->tab)
+		return NULL;
+
+	snap = isl_alloc_type(cgbr->tab->mat->ctx, struct isl_gbr_tab_undo);
+	if (!snap)
+		return NULL;
+
+	snap->tab_snap = isl_tab_snap(cgbr->tab);
+	if (isl_tab_save_samples(cgbr->tab) < 0)
+		goto error;
+
+	if (cgbr->shifted)
+		snap->shifted_snap = isl_tab_snap(cgbr->shifted);
+	else
+		snap->shifted_snap = NULL;
+
+	if (cgbr->cone)
+		snap->cone_snap = isl_tab_snap(cgbr->cone);
+	else
+		snap->cone_snap = NULL;
+
+	return snap;
+error:
+	free(snap);
+	return NULL;
+}
+
+static void context_gbr_restore(struct isl_context *context, void *save)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	struct isl_gbr_tab_undo *snap = (struct isl_gbr_tab_undo *)save;
+	if (!snap)
+		goto error;
+	if (isl_tab_rollback(cgbr->tab, snap->tab_snap) < 0) {
+		isl_tab_free(cgbr->tab);
+		cgbr->tab = NULL;
+	}
+
+	if (snap->shifted_snap) {
+		if (isl_tab_rollback(cgbr->shifted, snap->shifted_snap) < 0)
+			goto error;
+	} else if (cgbr->shifted) {
+		isl_tab_free(cgbr->shifted);
+		cgbr->shifted = NULL;
+	}
+
+	if (snap->cone_snap) {
+		if (isl_tab_rollback(cgbr->cone, snap->cone_snap) < 0)
+			goto error;
+	} else if (cgbr->cone) {
+		isl_tab_free(cgbr->cone);
+		cgbr->cone = NULL;
+	}
+
+	free(snap);
+
+	return;
+error:
+	free(snap);
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+}
+
+static void context_gbr_discard(void *save)
+{
+	struct isl_gbr_tab_undo *snap = (struct isl_gbr_tab_undo *)save;
+	free(snap);
+}
+
+static int context_gbr_is_ok(struct isl_context *context)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	return !!cgbr->tab;
+}
+
+static void context_gbr_invalidate(struct isl_context *context)
+{
+	struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+	isl_tab_free(cgbr->tab);
+	cgbr->tab = NULL;
+}
+
+static void 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);
+}
+
+struct isl_context_op isl_context_gbr_op = {
+	context_gbr_detect_nonnegative_parameters,
+	context_gbr_peek_basic_set,
+	context_gbr_peek_tab,
+	context_gbr_add_eq,
+	context_gbr_add_ineq,
+	context_gbr_ineq_sign,
+	context_gbr_test_ineq,
+	context_gbr_get_div,
+	context_gbr_add_div,
+	context_gbr_detect_equalities,
+	context_gbr_best_split,
+	context_gbr_is_empty,
+	context_gbr_is_ok,
+	context_gbr_save,
+	context_gbr_restore,
+	context_gbr_discard,
+	context_gbr_invalidate,
+	context_gbr_free,
+};
+
+static struct isl_context *isl_context_gbr_alloc(struct isl_basic_set *dom)
+{
+	struct isl_context_gbr *cgbr;
+
+	if (!dom)
+		return NULL;
+
+	cgbr = isl_calloc_type(dom->ctx, struct isl_context_gbr);
+	if (!cgbr)
+		return NULL;
+
+	cgbr->context.op = &isl_context_gbr_op;
+
+	cgbr->shifted = NULL;
+	cgbr->cone = NULL;
+	cgbr->tab = isl_tab_from_basic_set(dom, 1);
+	cgbr->tab = isl_tab_init_samples(cgbr->tab);
+	if (!cgbr->tab)
+		goto error;
+	check_gbr_integer_feasible(cgbr);
+
+	return &cgbr->context;
+error:
+	cgbr->context.op->free(&cgbr->context);
+	return NULL;
+}
+
+static struct isl_context *isl_context_alloc(struct isl_basic_set *dom)
+{
+	if (!dom)
+		return NULL;
+
+	if (dom->ctx->opt->context == ISL_CONTEXT_LEXMIN)
+		return isl_context_lex_alloc(dom);
+	else
+		return isl_context_gbr_alloc(dom);
+}
+
+/* Construct an isl_sol_map structure for accumulating the solution.
+ * If track_empty is set, then we also keep track of the parts
+ * of the context where there is no solution.
+ * If max is set, then we are solving a maximization, rather than
+ * a minimization problem, which means that the variables in the
+ * tableau have value "M - x" rather than "M + x".
+ */
+static struct isl_sol *sol_map_init(struct isl_basic_map *bmap,
+	struct isl_basic_set *dom, int track_empty, int max)
+{
+	struct isl_sol_map *sol_map = NULL;
+
+	if (!bmap)
+		goto error;
+
+	sol_map = isl_calloc_type(bmap->ctx, struct isl_sol_map);
+	if (!sol_map)
+		goto error;
+
+	sol_map->sol.rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+	sol_map->sol.dec_level.callback.run = &sol_dec_level_wrap;
+	sol_map->sol.dec_level.sol = &sol_map->sol;
+	sol_map->sol.max = max;
+	sol_map->sol.n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	sol_map->sol.add = &sol_map_add_wrap;
+	sol_map->sol.add_empty = track_empty ? &sol_map_add_empty_wrap : NULL;
+	sol_map->sol.free = &sol_map_free_wrap;
+	sol_map->map = isl_map_alloc_space(isl_basic_map_get_space(bmap), 1,
+					    ISL_MAP_DISJOINT);
+	if (!sol_map->map)
+		goto error;
+
+	sol_map->sol.context = isl_context_alloc(dom);
+	if (!sol_map->sol.context)
+		goto error;
+
+	if (track_empty) {
+		sol_map->empty = isl_set_alloc_space(isl_basic_set_get_space(dom),
+							1, ISL_SET_DISJOINT);
+		if (!sol_map->empty)
+			goto error;
+	}
+
+	isl_basic_set_free(dom);
+	return &sol_map->sol;
+error:
+	isl_basic_set_free(dom);
+	sol_map_free(sol_map);
+	return NULL;
+}
+
+/* Check whether all coefficients of (non-parameter) variables
+ * are non-positive, meaning that no pivots can be performed on the row.
+ */
+static int is_critical(struct isl_tab *tab, int row)
+{
+	int j;
+	unsigned off = 2 + tab->M;
+
+	for (j = tab->n_dead; j < tab->n_col; ++j) {
+		if (tab->col_var[j] >= 0 &&
+		    (tab->col_var[j] < tab->n_param  ||
+		    tab->col_var[j] >= tab->n_var - tab->n_div))
+			continue;
+
+		if (isl_int_is_pos(tab->mat->row[row][off + j]))
+			return 0;
+	}
+
+	return 1;
+}
+
+/* Check whether the inequality represented by vec is strict over the integers,
+ * i.e., there are no integer values satisfying the constraint with
+ * equality.  This happens if the gcd of the coefficients is not a divisor
+ * of the constant term.  If so, scale the constraint down by the gcd
+ * of the coefficients.
+ */
+static int is_strict(struct isl_vec *vec)
+{
+	isl_int gcd;
+	int strict = 0;
+
+	isl_int_init(gcd);
+	isl_seq_gcd(vec->el + 1, vec->size - 1, &gcd);
+	if (!isl_int_is_one(gcd)) {
+		strict = !isl_int_is_divisible_by(vec->el[0], gcd);
+		isl_int_fdiv_q(vec->el[0], vec->el[0], gcd);
+		isl_seq_scale_down(vec->el + 1, vec->el + 1, gcd, vec->size-1);
+	}
+	isl_int_clear(gcd);
+
+	return strict;
+}
+
+/* Determine the sign of the given row of the main tableau.
+ * The result is one of
+ *	isl_tab_row_pos: always non-negative; no pivot needed
+ *	isl_tab_row_neg: always non-positive; pivot
+ *	isl_tab_row_any: can be both positive and negative; split
+ *
+ * We first handle some simple cases
+ *	- the row sign may be known already
+ *	- the row may be obviously non-negative
+ *	- the parametric constant may be equal to that of another row
+ *	  for which we know the sign.  This sign will be either "pos" or
+ *	  "any".  If it had been "neg" then we would have pivoted before.
+ *
+ * If none of these cases hold, we check the value of the row for each
+ * of the currently active samples.  Based on the signs of these values
+ * we make an initial determination of the sign of the row.
+ *
+ *	all zero			->	unk(nown)
+ *	all non-negative		->	pos
+ *	all non-positive		->	neg
+ *	both negative and positive	->	all
+ *
+ * If we end up with "all", we are done.
+ * Otherwise, we perform a check for positive and/or negative
+ * values as follows.
+ *
+ *	samples	       neg	       unk	       pos
+ *	<0 ?			    Y        N	    Y        N
+ *					    pos    any      pos
+ *	>0 ?	     Y      N	 Y     N
+ *		    any    neg  any   neg
+ *
+ * There is no special sign for "zero", because we can usually treat zero
+ * as either non-negative or non-positive, whatever works out best.
+ * However, if the row is "critical", meaning that pivoting is impossible
+ * then we don't want to limp zero with the non-positive case, because
+ * then we we would lose the solution for those values of the parameters
+ * where the value of the row is zero.  Instead, we treat 0 as non-negative
+ * ensuring a split if the row can attain both zero and negative values.
+ * The same happens when the original constraint was one that could not
+ * be satisfied with equality by any integer values of the parameters.
+ * In this case, we normalize the constraint, but then a value of zero
+ * for the normalized constraint is actually a positive value for the
+ * original constraint, so again we need to treat zero as non-negative.
+ * In both these cases, we have the following decision tree instead:
+ *
+ *	all non-negative		->	pos
+ *	all negative			->	neg
+ *	both negative and non-negative	->	all
+ *
+ *	samples	       neg	          	       pos
+ *	<0 ?			             	    Y        N
+ *					           any      pos
+ *	>=0 ?	     Y      N
+ *		    any    neg
+ */
+static enum isl_tab_row_sign row_sign(struct isl_tab *tab,
+	struct isl_sol *sol, int row)
+{
+	struct isl_vec *ineq = NULL;
+	enum isl_tab_row_sign res = isl_tab_row_unknown;
+	int critical;
+	int strict;
+	int row2;
+
+	if (tab->row_sign[row] != isl_tab_row_unknown)
+		return tab->row_sign[row];
+	if (is_obviously_nonneg(tab, row))
+		return isl_tab_row_pos;
+	for (row2 = tab->n_redundant; row2 < tab->n_row; ++row2) {
+		if (tab->row_sign[row2] == isl_tab_row_unknown)
+			continue;
+		if (identical_parameter_line(tab, row, row2))
+			return tab->row_sign[row2];
+	}
+
+	critical = is_critical(tab, row);
+
+	ineq = get_row_parameter_ineq(tab, row);
+	if (!ineq)
+		goto error;
+
+	strict = is_strict(ineq);
+
+	res = sol->context->op->ineq_sign(sol->context, ineq->el,
+					  critical || strict);
+
+	if (res == isl_tab_row_unknown || res == isl_tab_row_pos) {
+		/* test for negative values */
+		int feasible;
+		isl_seq_neg(ineq->el, ineq->el, ineq->size);
+		isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+		feasible = sol->context->op->test_ineq(sol->context, ineq->el);
+		if (feasible < 0)
+			goto error;
+		if (!feasible)
+			res = isl_tab_row_pos;
+		else
+			res = (res == isl_tab_row_unknown) ? isl_tab_row_neg
+							   : isl_tab_row_any;
+		if (res == isl_tab_row_neg) {
+			isl_seq_neg(ineq->el, ineq->el, ineq->size);
+			isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+		}
+	}
+
+	if (res == isl_tab_row_neg) {
+		/* test for positive values */
+		int feasible;
+		if (!critical && !strict)
+			isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+		feasible = sol->context->op->test_ineq(sol->context, ineq->el);
+		if (feasible < 0)
+			goto error;
+		if (feasible)
+			res = isl_tab_row_any;
+	}
+
+	isl_vec_free(ineq);
+	return res;
+error:
+	isl_vec_free(ineq);
+	return isl_tab_row_unknown;
+}
+
+static void find_solutions(struct isl_sol *sol, struct isl_tab *tab);
+
+/* Find solutions for values of the parameters that satisfy the given
+ * inequality.
+ *
+ * We currently take a snapshot of the context tableau that is reset
+ * when we return from this function, while we make a copy of the main
+ * tableau, leaving the original main tableau untouched.
+ * These are fairly arbitrary choices.  Making a copy also of the context
+ * tableau would obviate the need to undo any changes made to it later,
+ * while taking a snapshot of the main tableau could reduce memory usage.
+ * If we were to switch to taking a snapshot of the main tableau,
+ * we would have to keep in mind that we need to save the row signs
+ * and that we need to do this before saving the current basis
+ * such that the basis has been restore before we restore the row signs.
+ */
+static void find_in_pos(struct isl_sol *sol, struct isl_tab *tab, isl_int *ineq)
+{
+	void *saved;
+
+	if (!sol->context)
+		goto error;
+	saved = sol->context->op->save(sol->context);
+
+	tab = isl_tab_dup(tab);
+	if (!tab)
+		goto error;
+
+	sol->context->op->add_ineq(sol->context, ineq, 0, 1);
+
+	find_solutions(sol, tab);
+
+	if (!sol->error)
+		sol->context->op->restore(sol->context, saved);
+	else
+		sol->context->op->discard(saved);
+	return;
+error:
+	sol->error = 1;
+}
+
+/* Record the absence of solutions for those values of the parameters
+ * that do not satisfy the given inequality with equality.
+ */
+static void no_sol_in_strict(struct isl_sol *sol,
+	struct isl_tab *tab, struct isl_vec *ineq)
+{
+	int empty;
+	void *saved;
+
+	if (!sol->context || sol->error)
+		goto error;
+	saved = sol->context->op->save(sol->context);
+
+	isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+	sol->context->op->add_ineq(sol->context, ineq->el, 1, 0);
+	if (!sol->context)
+		goto error;
+
+	empty = tab->empty;
+	tab->empty = 1;
+	sol_add(sol, tab);
+	tab->empty = empty;
+
+	isl_int_add_ui(ineq->el[0], ineq->el[0], 1);
+
+	sol->context->op->restore(sol->context, saved);
+	return;
+error:
+	sol->error = 1;
+}
+
+/* Compute the lexicographic minimum of the set represented by the main
+ * tableau "tab" within the context "sol->context_tab".
+ * On entry the sample value of the main tableau is lexicographically
+ * less than or equal to this lexicographic minimum.
+ * Pivots are performed until a feasible point is found, which is then
+ * necessarily equal to the minimum, or until the tableau is found to
+ * be infeasible.  Some pivots may need to be performed for only some
+ * feasible values of the context tableau.  If so, the context tableau
+ * is split into a part where the pivot is needed and a part where it is not.
+ *
+ * Whenever we enter the main loop, the main tableau is such that no
+ * "obvious" pivots need to be performed on it, where "obvious" means
+ * that the given row can be seen to be negative without looking at
+ * the context tableau.  In particular, for non-parametric problems,
+ * no pivots need to be performed on the main tableau.
+ * The caller of find_solutions is responsible for making this property
+ * hold prior to the first iteration of the loop, while restore_lexmin
+ * is called before every other iteration.
+ *
+ * Inside the main loop, we first examine the signs of the rows of
+ * the main tableau within the context of the context tableau.
+ * If we find a row that is always non-positive for all values of
+ * the parameters satisfying the context tableau and negative for at
+ * least one value of the parameters, we perform the appropriate pivot
+ * and start over.  An exception is the case where no pivot can be
+ * performed on the row.  In this case, we require that the sign of
+ * the row is negative for all values of the parameters (rather than just
+ * non-positive).  This special case is handled inside row_sign, which
+ * will say that the row can have any sign if it determines that it can
+ * attain both negative and zero values.
+ *
+ * If we can't find a row that always requires a pivot, but we can find
+ * one or more rows that require a pivot for some values of the parameters
+ * (i.e., the row can attain both positive and negative signs), then we split
+ * the context tableau into two parts, one where we force the sign to be
+ * non-negative and one where we force is to be negative.
+ * The non-negative part is handled by a recursive call (through find_in_pos).
+ * Upon returning from this call, we continue with the negative part and
+ * perform the required pivot.
+ *
+ * If no such rows can be found, all rows are non-negative and we have
+ * found a (rational) feasible point.  If we only wanted a rational point
+ * then we are done.
+ * Otherwise, we check if all values of the sample point of the tableau
+ * are integral for the variables.  If so, we have found the minimal
+ * integral point and we are done.
+ * If the sample point is not integral, then we need to make a distinction
+ * based on whether the constant term is non-integral or the coefficients
+ * of the parameters.  Furthermore, in order to decide how to handle
+ * the non-integrality, we also need to know whether the coefficients
+ * of the other columns in the tableau are integral.  This leads
+ * to the following table.  The first two rows do not correspond
+ * to a non-integral sample point and are only mentioned for completeness.
+ *
+ *	constant	parameters	other
+ *
+ *	int		int		int	|
+ *	int		int		rat	| -> no problem
+ *
+ *	rat		int		int	  -> fail
+ *
+ *	rat		int		rat	  -> cut
+ *
+ *	int		rat		rat	|
+ *	rat		rat		rat	| -> parametric cut
+ *
+ *	int		rat		int	|
+ *	rat		rat		int	| -> split context
+ *
+ * If the parametric constant is completely integral, then there is nothing
+ * to be done.  If the constant term is non-integral, but all the other
+ * coefficient are integral, then there is nothing that can be done
+ * and the tableau has no integral solution.
+ * If, on the other hand, one or more of the other columns have rational
+ * coefficients, but the parameter coefficients are all integral, then
+ * we can perform a regular (non-parametric) cut.
+ * Finally, if there is any parameter coefficient that is non-integral,
+ * then we need to involve the context tableau.  There are two cases here.
+ * If at least one other column has a rational coefficient, then we
+ * can perform a parametric cut in the main tableau by adding a new
+ * integer division in the context tableau.
+ * If all other columns have integral coefficients, then we need to
+ * enforce that the rational combination of parameters (c + \sum a_i y_i)/m
+ * is always integral.  We do this by introducing an integer division
+ * q = floor((c + \sum a_i y_i)/m) and stipulating that its argument should
+ * always be integral in the context tableau, i.e., m q = c + \sum a_i y_i.
+ * Since q is expressed in the tableau as
+ *	c + \sum a_i y_i - m q >= 0
+ *	-c - \sum a_i y_i + m q + m - 1 >= 0
+ * it is sufficient to add the inequality
+ *	-c - \sum a_i y_i + m q >= 0
+ * In the part of the context where this inequality does not hold, the
+ * main tableau is marked as being empty.
+ */
+static void find_solutions(struct isl_sol *sol, struct isl_tab *tab)
+{
+	struct isl_context *context;
+	int r;
+
+	if (!tab || sol->error)
+		goto error;
+
+	context = sol->context;
+
+	if (tab->empty)
+		goto done;
+	if (context->op->is_empty(context))
+		goto done;
+
+	for (r = 0; r >= 0 && tab && !tab->empty; r = restore_lexmin(tab)) {
+		int flags;
+		int row;
+		enum isl_tab_row_sign sgn;
+		int split = -1;
+		int n_split = 0;
+
+		for (row = tab->n_redundant; row < tab->n_row; ++row) {
+			if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+				continue;
+			sgn = row_sign(tab, sol, row);
+			if (!sgn)
+				goto error;
+			tab->row_sign[row] = sgn;
+			if (sgn == isl_tab_row_any)
+				n_split++;
+			if (sgn == isl_tab_row_any && split == -1)
+				split = row;
+			if (sgn == isl_tab_row_neg)
+				break;
+		}
+		if (row < tab->n_row)
+			continue;
+		if (split != -1) {
+			struct isl_vec *ineq;
+			if (n_split != 1)
+				split = context->op->best_split(context, tab);
+			if (split < 0)
+				goto error;
+			ineq = get_row_parameter_ineq(tab, split);
+			if (!ineq)
+				goto error;
+			is_strict(ineq);
+			for (row = tab->n_redundant; row < tab->n_row; ++row) {
+				if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+					continue;
+				if (tab->row_sign[row] == isl_tab_row_any)
+					tab->row_sign[row] = isl_tab_row_unknown;
+			}
+			tab->row_sign[split] = isl_tab_row_pos;
+			sol_inc_level(sol);
+			find_in_pos(sol, tab, ineq->el);
+			tab->row_sign[split] = isl_tab_row_neg;
+			row = split;
+			isl_seq_neg(ineq->el, ineq->el, ineq->size);
+			isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+			if (!sol->error)
+				context->op->add_ineq(context, ineq->el, 0, 1);
+			isl_vec_free(ineq);
+			if (sol->error)
+				goto error;
+			continue;
+		}
+		if (tab->rational)
+			break;
+		row = first_non_integer_row(tab, &flags);
+		if (row < 0)
+			break;
+		if (ISL_FL_ISSET(flags, I_PAR)) {
+			if (ISL_FL_ISSET(flags, I_VAR)) {
+				if (isl_tab_mark_empty(tab) < 0)
+					goto error;
+				break;
+			}
+			row = add_cut(tab, row);
+		} else if (ISL_FL_ISSET(flags, I_VAR)) {
+			struct isl_vec *div;
+			struct isl_vec *ineq;
+			int d;
+			div = get_row_split_div(tab, row);
+			if (!div)
+				goto error;
+			d = context->op->get_div(context, tab, div);
+			isl_vec_free(div);
+			if (d < 0)
+				goto error;
+			ineq = ineq_for_div(context->op->peek_basic_set(context), d);
+			if (!ineq)
+				goto error;
+			sol_inc_level(sol);
+			no_sol_in_strict(sol, tab, ineq);
+			isl_seq_neg(ineq->el, ineq->el, ineq->size);
+			context->op->add_ineq(context, ineq->el, 1, 1);
+			isl_vec_free(ineq);
+			if (sol->error || !context->op->is_ok(context))
+				goto error;
+			tab = set_row_cst_to_div(tab, row, d);
+			if (context->op->is_empty(context))
+				break;
+		} else
+			row = add_parametric_cut(tab, row, context);
+		if (row < 0)
+			goto error;
+	}
+	if (r < 0)
+		goto error;
+done:
+	sol_add(sol, tab);
+	isl_tab_free(tab);
+	return;
+error:
+	isl_tab_free(tab);
+	sol->error = 1;
+}
+
+/* Does "sol" contain a pair of partial solutions that could potentially
+ * be merged?
+ *
+ * We currently only check that "sol" is not in an error state
+ * and that there are at least two partial solutions of which the final two
+ * are defined at the same level.
+ */
+static int sol_has_mergeable_solutions(struct isl_sol *sol)
+{
+	if (sol->error)
+		return 0;
+	if (!sol->partial)
+		return 0;
+	if (!sol->partial->next)
+		return 0;
+	return sol->partial->level == sol->partial->next->level;
+}
+
+/* Compute the lexicographic minimum of the set represented by the main
+ * tableau "tab" within the context "sol->context_tab".
+ *
+ * As a preprocessing step, we first transfer all the purely parametric
+ * equalities from the main tableau to the context tableau, i.e.,
+ * parameters that have been pivoted to a row.
+ * These equalities are ignored by the main algorithm, because the
+ * corresponding rows may not be marked as being non-negative.
+ * In parts of the context where the added equality does not hold,
+ * the main tableau is marked as being empty.
+ *
+ * Before we embark on the actual computation, we save a copy
+ * of the context.  When we return, we check if there are any
+ * partial solutions that can potentially be merged.  If so,
+ * we perform a rollback to the initial state of the context.
+ * The merging of partial solutions happens inside calls to
+ * sol_dec_level that are pushed onto the undo stack of the context.
+ * If there are no partial solutions that can potentially be merged
+ * then the rollback is skipped as it would just be wasted effort.
+ */
+static void find_solutions_main(struct isl_sol *sol, struct isl_tab *tab)
+{
+	int row;
+	void *saved;
+
+	if (!tab)
+		goto error;
+
+	sol->level = 0;
+
+	for (row = tab->n_redundant; row < tab->n_row; ++row) {
+		int p;
+		struct isl_vec *eq;
+
+		if (tab->row_var[row] < 0)
+			continue;
+		if (tab->row_var[row] >= tab->n_param &&
+		    tab->row_var[row] < tab->n_var - tab->n_div)
+			continue;
+		if (tab->row_var[row] < tab->n_param)
+			p = tab->row_var[row];
+		else
+			p = tab->row_var[row]
+				+ tab->n_param - (tab->n_var - tab->n_div);
+
+		eq = isl_vec_alloc(tab->mat->ctx, 1+tab->n_param+tab->n_div);
+		if (!eq)
+			goto error;
+		get_row_parameter_line(tab, row, eq->el);
+		isl_int_neg(eq->el[1 + p], tab->mat->row[row][0]);
+		eq = isl_vec_normalize(eq);
+
+		sol_inc_level(sol);
+		no_sol_in_strict(sol, tab, eq);
+
+		isl_seq_neg(eq->el, eq->el, eq->size);
+		sol_inc_level(sol);
+		no_sol_in_strict(sol, tab, eq);
+		isl_seq_neg(eq->el, eq->el, eq->size);
+
+		sol->context->op->add_eq(sol->context, eq->el, 1, 1);
+
+		isl_vec_free(eq);
+
+		if (isl_tab_mark_redundant(tab, row) < 0)
+			goto error;
+
+		if (sol->context->op->is_empty(sol->context))
+			break;
+
+		row = tab->n_redundant - 1;
+	}
+
+	saved = sol->context->op->save(sol->context);
+
+	find_solutions(sol, tab);
+
+	if (sol_has_mergeable_solutions(sol))
+		sol->context->op->restore(sol->context, saved);
+	else
+		sol->context->op->discard(saved);
+
+	sol->level = 0;
+	sol_pop(sol);
+
+	return;
+error:
+	isl_tab_free(tab);
+	sol->error = 1;
+}
+
+/* Check if integer division "div" of "dom" also occurs in "bmap".
+ * If so, return its position within the divs.
+ * If not, return -1.
+ */
+static int find_context_div(struct isl_basic_map *bmap,
+	struct isl_basic_set *dom, unsigned div)
+{
+	int i;
+	unsigned b_dim = isl_space_dim(bmap->dim, isl_dim_all);
+	unsigned d_dim = isl_space_dim(dom->dim, isl_dim_all);
+
+	if (isl_int_is_zero(dom->div[div][0]))
+		return -1;
+	if (isl_seq_first_non_zero(dom->div[div] + 2 + d_dim, dom->n_div) != -1)
+		return -1;
+
+	for (i = 0; i < bmap->n_div; ++i) {
+		if (isl_int_is_zero(bmap->div[i][0]))
+			continue;
+		if (isl_seq_first_non_zero(bmap->div[i] + 2 + d_dim,
+					   (b_dim - d_dim) + bmap->n_div) != -1)
+			continue;
+		if (isl_seq_eq(bmap->div[i], dom->div[div], 2 + d_dim))
+			return i;
+	}
+	return -1;
+}
+
+/* The correspondence between the variables in the main tableau,
+ * the context tableau, and the input map and domain is as follows.
+ * The first n_param and the last n_div variables of the main tableau
+ * form the variables of the context tableau.
+ * In the basic map, these n_param variables correspond to the
+ * parameters and the input dimensions.  In the domain, they correspond
+ * to the parameters and the set dimensions.
+ * The n_div variables correspond to the integer divisions in the domain.
+ * To ensure that everything lines up, we may need to copy some of the
+ * integer divisions of the domain to the map.  These have to be placed
+ * in the same order as those in the context and they have to be placed
+ * after any other integer divisions that the map may have.
+ * This function performs the required reordering.
+ */
+static struct isl_basic_map *align_context_divs(struct isl_basic_map *bmap,
+	struct isl_basic_set *dom)
+{
+	int i;
+	int common = 0;
+	int other;
+
+	for (i = 0; i < dom->n_div; ++i)
+		if (find_context_div(bmap, dom, i) != -1)
+			common++;
+	other = bmap->n_div - common;
+	if (dom->n_div - common > 0) {
+		bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+				dom->n_div - common, 0, 0);
+		if (!bmap)
+			return NULL;
+	}
+	for (i = 0; i < dom->n_div; ++i) {
+		int pos = find_context_div(bmap, dom, i);
+		if (pos < 0) {
+			pos = isl_basic_map_alloc_div(bmap);
+			if (pos < 0)
+				goto error;
+			isl_int_set_si(bmap->div[pos][0], 0);
+		}
+		if (pos != other + i)
+			isl_basic_map_swap_div(bmap, pos, other + i);
+	}
+	return bmap;
+error:
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Base case of isl_tab_basic_map_partial_lexopt, after removing
+ * some obvious symmetries.
+ *
+ * We make sure the divs in the domain are properly ordered,
+ * because they will be added one by one in the given order
+ * during the construction of the solution map.
+ */
+static struct isl_sol *basic_map_partial_lexopt_base(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max,
+	struct isl_sol *(*init)(__isl_keep isl_basic_map *bmap,
+		    __isl_take isl_basic_set *dom, int track_empty, int max))
+{
+	struct isl_tab *tab;
+	struct isl_sol *sol = NULL;
+	struct isl_context *context;
+
+	if (dom->n_div) {
+		dom = isl_basic_set_order_divs(dom);
+		bmap = align_context_divs(bmap, dom);
+	}
+	sol = init(bmap, dom, !!empty, max);
+	if (!sol)
+		goto error;
+
+	context = sol->context;
+	if (isl_basic_set_plain_is_empty(context->op->peek_basic_set(context)))
+		/* nothing */;
+	else if (isl_basic_map_plain_is_empty(bmap)) {
+		if (sol->add_empty)
+			sol->add_empty(sol,
+		    isl_basic_set_copy(context->op->peek_basic_set(context)));
+	} else {
+		tab = tab_for_lexmin(bmap,
+				    context->op->peek_basic_set(context), 1, max);
+		tab = context->op->detect_nonnegative_parameters(context, tab);
+		find_solutions_main(sol, tab);
+	}
+	if (sol->error)
+		goto error;
+
+	isl_basic_map_free(bmap);
+	return sol;
+error:
+	sol_free(sol);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Base case of isl_tab_basic_map_partial_lexopt, after removing
+ * some obvious symmetries.
+ *
+ * We call basic_map_partial_lexopt_base and extract the results.
+ */
+static __isl_give isl_map *basic_map_partial_lexopt_base_map(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max)
+{
+	isl_map *result = NULL;
+	struct isl_sol *sol;
+	struct isl_sol_map *sol_map;
+
+	sol = basic_map_partial_lexopt_base(bmap, dom, empty, max,
+					    &sol_map_init);
+	if (!sol)
+		return NULL;
+	sol_map = (struct isl_sol_map *) sol;
+
+	result = isl_map_copy(sol_map->map);
+	if (empty)
+		*empty = isl_set_copy(sol_map->empty);
+	sol_free(&sol_map->sol);
+	return result;
+}
+
+/* Structure used during detection of parallel constraints.
+ * n_in: number of "input" variables: isl_dim_param + isl_dim_in
+ * n_out: number of "output" variables: isl_dim_out + isl_dim_div
+ * val: the coefficients of the output variables
+ */
+struct isl_constraint_equal_info {
+	isl_basic_map *bmap;
+	unsigned n_in;
+	unsigned n_out;
+	isl_int *val;
+};
+
+/* Check whether the coefficients of the output variables
+ * of the constraint in "entry" are equal to info->val.
+ */
+static int constraint_equal(const void *entry, const void *val)
+{
+	isl_int **row = (isl_int **)entry;
+	const struct isl_constraint_equal_info *info = val;
+
+	return isl_seq_eq((*row) + 1 + info->n_in, info->val, info->n_out);
+}
+
+/* Check whether "bmap" has a pair of constraints that have
+ * the same coefficients for the output variables.
+ * Note that the coefficients of the existentially quantified
+ * variables need to be zero since the existentially quantified
+ * of the result are usually not the same as those of the input.
+ * the isl_dim_out and isl_dim_div dimensions.
+ * If so, return 1 and return the row indices of the two constraints
+ * in *first and *second.
+ */
+static int parallel_constraints(__isl_keep isl_basic_map *bmap,
+	int *first, int *second)
+{
+	int i;
+	isl_ctx *ctx = isl_basic_map_get_ctx(bmap);
+	struct isl_hash_table *table = NULL;
+	struct isl_hash_table_entry *entry;
+	struct isl_constraint_equal_info info;
+	unsigned n_out;
+	unsigned n_div;
+
+	ctx = isl_basic_map_get_ctx(bmap);
+	table = isl_hash_table_alloc(ctx, bmap->n_ineq);
+	if (!table)
+		goto error;
+
+	info.n_in = isl_basic_map_dim(bmap, isl_dim_param) +
+		    isl_basic_map_dim(bmap, isl_dim_in);
+	info.bmap = bmap;
+	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	info.n_out = n_out + n_div;
+	for (i = 0; i < bmap->n_ineq; ++i) {
+		uint32_t hash;
+
+		info.val = bmap->ineq[i] + 1 + info.n_in;
+		if (isl_seq_first_non_zero(info.val, n_out) < 0)
+			continue;
+		if (isl_seq_first_non_zero(info.val + n_out, n_div) >= 0)
+			continue;
+		hash = isl_seq_get_hash(info.val, info.n_out);
+		entry = isl_hash_table_find(ctx, table, hash,
+					    constraint_equal, &info, 1);
+		if (!entry)
+			goto error;
+		if (entry->data)
+			break;
+		entry->data = &bmap->ineq[i];
+	}
+
+	if (i < bmap->n_ineq) {
+		*first = ((isl_int **)entry->data) - bmap->ineq; 
+		*second = i;
+	}
+
+	isl_hash_table_free(ctx, table);
+
+	return i < bmap->n_ineq;
+error:
+	isl_hash_table_free(ctx, table);
+	return -1;
+}
+
+/* Given a set of upper bounds in "var", add constraints to "bset"
+ * that make the i-th bound smallest.
+ *
+ * In particular, if there are n bounds b_i, then add the constraints
+ *
+ *	b_i <= b_j	for j > i
+ *	b_i <  b_j	for j < i
+ */
+static __isl_give isl_basic_set *select_minimum(__isl_take isl_basic_set *bset,
+	__isl_keep isl_mat *var, int i)
+{
+	isl_ctx *ctx;
+	int j, k;
+
+	ctx = isl_mat_get_ctx(var);
+
+	for (j = 0; j < var->n_row; ++j) {
+		if (j == i)
+			continue;
+		k = isl_basic_set_alloc_inequality(bset);
+		if (k < 0)
+			goto error;
+		isl_seq_combine(bset->ineq[k], ctx->one, var->row[j],
+				ctx->negone, var->row[i], var->n_col);
+		isl_int_set_si(bset->ineq[k][var->n_col], 0);
+		if (j < i)
+			isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
+	}
+
+	bset = isl_basic_set_finalize(bset);
+
+	return bset;
+error:
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+/* Given a set of upper bounds on the last "input" variable m,
+ * construct a set that assigns the minimal upper bound to m, i.e.,
+ * construct a set that divides the space into cells where one
+ * of the upper bounds is smaller than all the others and assign
+ * this upper bound to m.
+ *
+ * In particular, if there are n bounds b_i, then the result
+ * consists of n basic sets, each one of the form
+ *
+ *	m = b_i
+ *	b_i <= b_j	for j > i
+ *	b_i <  b_j	for j < i
+ */
+static __isl_give isl_set *set_minimum(__isl_take isl_space *dim,
+	__isl_take isl_mat *var)
+{
+	int i, k;
+	isl_basic_set *bset = NULL;
+	isl_ctx *ctx;
+	isl_set *set = NULL;
+
+	if (!dim || !var)
+		goto error;
+
+	ctx = isl_space_get_ctx(dim);
+	set = isl_set_alloc_space(isl_space_copy(dim),
+				var->n_row, ISL_SET_DISJOINT);
+
+	for (i = 0; i < var->n_row; ++i) {
+		bset = isl_basic_set_alloc_space(isl_space_copy(dim), 0,
+					       1, var->n_row - 1);
+		k = isl_basic_set_alloc_equality(bset);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bset->eq[k], var->row[i], var->n_col);
+		isl_int_set_si(bset->eq[k][var->n_col], -1);
+		bset = select_minimum(bset, var, i);
+		set = isl_set_add_basic_set(set, bset);
+	}
+
+	isl_space_free(dim);
+	isl_mat_free(var);
+	return set;
+error:
+	isl_basic_set_free(bset);
+	isl_set_free(set);
+	isl_space_free(dim);
+	isl_mat_free(var);
+	return NULL;
+}
+
+/* Given that the last input variable of "bmap" represents the minimum
+ * of the bounds in "cst", check whether we need to split the domain
+ * based on which bound attains the minimum.
+ *
+ * A split is needed when the minimum appears in an integer division
+ * or in an equality.  Otherwise, it is only needed if it appears in
+ * an upper bound that is different from the upper bounds on which it
+ * is defined.
+ */
+static int need_split_basic_map(__isl_keep isl_basic_map *bmap,
+	__isl_keep isl_mat *cst)
+{
+	int i, j;
+	unsigned total;
+	unsigned pos;
+
+	pos = cst->n_col - 1;
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+
+	for (i = 0; i < bmap->n_div; ++i)
+		if (!isl_int_is_zero(bmap->div[i][2 + pos]))
+			return 1;
+
+	for (i = 0; i < bmap->n_eq; ++i)
+		if (!isl_int_is_zero(bmap->eq[i][1 + pos]))
+			return 1;
+
+	for (i = 0; i < bmap->n_ineq; ++i) {
+		if (isl_int_is_nonneg(bmap->ineq[i][1 + pos]))
+			continue;
+		if (!isl_int_is_negone(bmap->ineq[i][1 + pos]))
+			return 1;
+		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + pos + 1,
+					   total - pos - 1) >= 0)
+			return 1;
+
+		for (j = 0; j < cst->n_row; ++j)
+			if (isl_seq_eq(bmap->ineq[i], cst->row[j], cst->n_col))
+				break;
+		if (j >= cst->n_row)
+			return 1;
+	}
+
+	return 0;
+}
+
+/* Given that the last set variable of "bset" represents the minimum
+ * of the bounds in "cst", check whether we need to split the domain
+ * based on which bound attains the minimum.
+ *
+ * We simply call need_split_basic_map here.  This is safe because
+ * the position of the minimum is computed from "cst" and not
+ * from "bmap".
+ */
+static int need_split_basic_set(__isl_keep isl_basic_set *bset,
+	__isl_keep isl_mat *cst)
+{
+	return need_split_basic_map((isl_basic_map *)bset, cst);
+}
+
+/* Given that the last set variable of "set" represents the minimum
+ * of the bounds in "cst", check whether we need to split the domain
+ * based on which bound attains the minimum.
+ */
+static int need_split_set(__isl_keep isl_set *set, __isl_keep isl_mat *cst)
+{
+	int i;
+
+	for (i = 0; i < set->n; ++i)
+		if (need_split_basic_set(set->p[i], cst))
+			return 1;
+
+	return 0;
+}
+
+/* Given a set of which the last set variable is the minimum
+ * of the bounds in "cst", split each basic set in the set
+ * in pieces where one of the bounds is (strictly) smaller than the others.
+ * This subdivision is given in "min_expr".
+ * The variable is subsequently projected out.
+ *
+ * We only do the split when it is needed.
+ * For example if the last input variable m = min(a,b) and the only
+ * constraints in the given basic set are lower bounds on m,
+ * i.e., l <= m = min(a,b), then we can simply project out m
+ * to obtain l <= a and l <= b, without having to split on whether
+ * m is equal to a or b.
+ */
+static __isl_give isl_set *split(__isl_take isl_set *empty,
+	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+	int n_in;
+	int i;
+	isl_space *dim;
+	isl_set *res;
+
+	if (!empty || !min_expr || !cst)
+		goto error;
+
+	n_in = isl_set_dim(empty, isl_dim_set);
+	dim = isl_set_get_space(empty);
+	dim = isl_space_drop_dims(dim, isl_dim_set, n_in - 1, 1);
+	res = isl_set_empty(dim);
+
+	for (i = 0; i < empty->n; ++i) {
+		isl_set *set;
+
+		set = isl_set_from_basic_set(isl_basic_set_copy(empty->p[i]));
+		if (need_split_basic_set(empty->p[i], cst))
+			set = isl_set_intersect(set, isl_set_copy(min_expr));
+		set = isl_set_remove_dims(set, isl_dim_set, n_in - 1, 1);
+
+		res = isl_set_union_disjoint(res, set);
+	}
+
+	isl_set_free(empty);
+	isl_set_free(min_expr);
+	isl_mat_free(cst);
+	return res;
+error:
+	isl_set_free(empty);
+	isl_set_free(min_expr);
+	isl_mat_free(cst);
+	return NULL;
+}
+
+/* Given a map of which the last input variable is the minimum
+ * of the bounds in "cst", split each basic set in the set
+ * in pieces where one of the bounds is (strictly) smaller than the others.
+ * This subdivision is given in "min_expr".
+ * The variable is subsequently projected out.
+ *
+ * The implementation is essentially the same as that of "split".
+ */
+static __isl_give isl_map *split_domain(__isl_take isl_map *opt,
+	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+	int n_in;
+	int i;
+	isl_space *dim;
+	isl_map *res;
+
+	if (!opt || !min_expr || !cst)
+		goto error;
+
+	n_in = isl_map_dim(opt, isl_dim_in);
+	dim = isl_map_get_space(opt);
+	dim = isl_space_drop_dims(dim, isl_dim_in, n_in - 1, 1);
+	res = isl_map_empty(dim);
+
+	for (i = 0; i < opt->n; ++i) {
+		isl_map *map;
+
+		map = isl_map_from_basic_map(isl_basic_map_copy(opt->p[i]));
+		if (need_split_basic_map(opt->p[i], cst))
+			map = isl_map_intersect_domain(map,
+						       isl_set_copy(min_expr));
+		map = isl_map_remove_dims(map, isl_dim_in, n_in - 1, 1);
+
+		res = isl_map_union_disjoint(res, map);
+	}
+
+	isl_map_free(opt);
+	isl_set_free(min_expr);
+	isl_mat_free(cst);
+	return res;
+error:
+	isl_map_free(opt);
+	isl_set_free(min_expr);
+	isl_mat_free(cst);
+	return NULL;
+}
+
+static __isl_give isl_map *basic_map_partial_lexopt(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max);
+
+union isl_lex_res {
+	void *p;
+	isl_map *map;
+	isl_pw_multi_aff *pma;
+};
+
+/* This function is called from basic_map_partial_lexopt_symm.
+ * The last variable of "bmap" and "dom" corresponds to the minimum
+ * of the bounds in "cst".  "map_space" is the space of the original
+ * input relation (of basic_map_partial_lexopt_symm) and "set_space"
+ * is the space of the original domain.
+ *
+ * We recursively call basic_map_partial_lexopt and then plug in
+ * the definition of the minimum in the result.
+ */
+static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_map_core(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max, __isl_take isl_mat *cst,
+	__isl_take isl_space *map_space, __isl_take isl_space *set_space)
+{
+	isl_map *opt;
+	isl_set *min_expr;
+	union isl_lex_res res;
+
+	min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst));
+
+	opt = basic_map_partial_lexopt(bmap, dom, empty, max);
+
+	if (empty) {
+		*empty = split(*empty,
+			       isl_set_copy(min_expr), isl_mat_copy(cst));
+		*empty = isl_set_reset_space(*empty, set_space);
+	}
+
+	opt = split_domain(opt, min_expr, cst);
+	opt = isl_map_reset_space(opt, map_space);
+
+	res.map = opt;
+	return res;
+}
+
+/* Given a basic map with at least two parallel constraints (as found
+ * by the function parallel_constraints), first look for more constraints
+ * parallel to the two constraint and replace the found list of parallel
+ * constraints by a single constraint with as "input" part the minimum
+ * of the input parts of the list of constraints.  Then, recursively call
+ * basic_map_partial_lexopt (possibly finding more parallel constraints)
+ * and plug in the definition of the minimum in the result.
+ *
+ * More specifically, given a set of constraints
+ *
+ *	a x + b_i(p) >= 0
+ *
+ * Replace this set by a single constraint
+ *
+ *	a x + u >= 0
+ *
+ * with u a new parameter with constraints
+ *
+ *	u <= b_i(p)
+ *
+ * Any solution to the new system is also a solution for the original system
+ * since
+ *
+ *	a x >= -u >= -b_i(p)
+ *
+ * Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
+ * therefore be plugged into the solution.
+ */
+static union isl_lex_res basic_map_partial_lexopt_symm(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max, int first, int second,
+	__isl_give union isl_lex_res (*core)(__isl_take isl_basic_map *bmap,
+					    __isl_take isl_basic_set *dom,
+					    __isl_give isl_set **empty,
+					    int max, __isl_take isl_mat *cst,
+					    __isl_take isl_space *map_space,
+					    __isl_take isl_space *set_space))
+{
+	int i, n, k;
+	int *list = NULL;
+	unsigned n_in, n_out, n_div;
+	isl_ctx *ctx;
+	isl_vec *var = NULL;
+	isl_mat *cst = NULL;
+	isl_space *map_space, *set_space;
+	union isl_lex_res res;
+
+	map_space = isl_basic_map_get_space(bmap);
+	set_space = empty ? isl_basic_set_get_space(dom) : NULL;
+
+	n_in = isl_basic_map_dim(bmap, isl_dim_param) +
+	       isl_basic_map_dim(bmap, isl_dim_in);
+	n_out = isl_basic_map_dim(bmap, isl_dim_all) - n_in;
+
+	ctx = isl_basic_map_get_ctx(bmap);
+	list = isl_alloc_array(ctx, int, bmap->n_ineq);
+	var = isl_vec_alloc(ctx, n_out);
+	if ((bmap->n_ineq && !list) || (n_out && !var))
+		goto error;
+
+	list[0] = first;
+	list[1] = second;
+	isl_seq_cpy(var->el, bmap->ineq[first] + 1 + n_in, n_out);
+	for (i = second + 1, n = 2; i < bmap->n_ineq; ++i) {
+		if (isl_seq_eq(var->el, bmap->ineq[i] + 1 + n_in, n_out))
+			list[n++] = i;
+	}
+
+	cst = isl_mat_alloc(ctx, n, 1 + n_in);
+	if (!cst)
+		goto error;
+
+	for (i = 0; i < n; ++i)
+		isl_seq_cpy(cst->row[i], bmap->ineq[list[i]], 1 + n_in);
+
+	bmap = isl_basic_map_cow(bmap);
+	if (!bmap)
+		goto error;
+	for (i = n - 1; i >= 0; --i)
+		if (isl_basic_map_drop_inequality(bmap, list[i]) < 0)
+			goto error;
+
+	bmap = isl_basic_map_add(bmap, isl_dim_in, 1);
+	bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
+	k = isl_basic_map_alloc_inequality(bmap);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(bmap->ineq[k], 1 + n_in);
+	isl_int_set_si(bmap->ineq[k][1 + n_in], 1);
+	isl_seq_cpy(bmap->ineq[k] + 1 + n_in + 1, var->el, n_out);
+	bmap = isl_basic_map_finalize(bmap);
+
+	n_div = isl_basic_set_dim(dom, isl_dim_div);
+	dom = isl_basic_set_add_dims(dom, isl_dim_set, 1);
+	dom = isl_basic_set_extend_constraints(dom, 0, n);
+	for (i = 0; i < n; ++i) {
+		k = isl_basic_set_alloc_inequality(dom);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(dom->ineq[k], cst->row[i], 1 + n_in);
+		isl_int_set_si(dom->ineq[k][1 + n_in], -1);
+		isl_seq_clr(dom->ineq[k] + 1 + n_in + 1, n_div);
+	}
+
+	isl_vec_free(var);
+	free(list);
+
+	return core(bmap, dom, empty, max, cst, map_space, set_space);
+error:
+	isl_space_free(map_space);
+	isl_space_free(set_space);
+	isl_mat_free(cst);
+	isl_vec_free(var);
+	free(list);
+	isl_basic_set_free(dom);
+	isl_basic_map_free(bmap);
+	res.p = NULL;
+	return res;
+}
+
+static __isl_give isl_map *basic_map_partial_lexopt_symm_map(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max, int first, int second)
+{
+	return basic_map_partial_lexopt_symm(bmap, dom, empty, max,
+		    first, second, &basic_map_partial_lexopt_symm_map_core).map;
+}
+
+/* Recursive part of isl_tab_basic_map_partial_lexopt, after detecting
+ * equalities and removing redundant constraints.
+ *
+ * We first check if there are any parallel constraints (left).
+ * If not, we are in the base case.
+ * If there are parallel constraints, we replace them by a single
+ * constraint in basic_map_partial_lexopt_symm and then call
+ * this function recursively to look for more parallel constraints.
+ */
+static __isl_give isl_map *basic_map_partial_lexopt(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max)
+{
+	int par = 0;
+	int first, second;
+
+	if (!bmap)
+		goto error;
+
+	if (bmap->ctx->opt->pip_symmetry)
+		par = parallel_constraints(bmap, &first, &second);
+	if (par < 0)
+		goto error;
+	if (!par)
+		return basic_map_partial_lexopt_base_map(bmap, dom, empty, max);
+	
+	return basic_map_partial_lexopt_symm_map(bmap, dom, empty, max,
+						 first, second);
+error:
+	isl_basic_set_free(dom);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Compute the lexicographic minimum (or maximum if "max" is set)
+ * of "bmap" over the domain "dom" and return the result as a map.
+ * If "empty" is not NULL, then *empty is assigned a set that
+ * contains those parts of the domain where there is no solution.
+ * If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
+ * then we compute the rational optimum.  Otherwise, we compute
+ * the integral optimum.
+ *
+ * We perform some preprocessing.  As the PILP solver does not
+ * handle implicit equalities very well, we first make sure all
+ * the equalities are explicitly available.
+ *
+ * We also add context constraints to the basic map and remove
+ * redundant constraints.  This is only needed because of the
+ * way we handle simple symmetries.  In particular, we currently look
+ * for symmetries on the constraints, before we set up the main tableau.
+ * It is then no good to look for symmetries on possibly redundant constraints.
+ */
+struct isl_map *isl_tab_basic_map_partial_lexopt(
+		struct isl_basic_map *bmap, struct isl_basic_set *dom,
+		struct isl_set **empty, int max)
+{
+	if (empty)
+		*empty = NULL;
+	if (!bmap || !dom)
+		goto error;
+
+	isl_assert(bmap->ctx,
+	    isl_basic_map_compatible_domain(bmap, dom), goto error);
+
+	if (isl_basic_set_dim(dom, isl_dim_all) == 0)
+		return basic_map_partial_lexopt(bmap, dom, empty, max);
+
+	bmap = isl_basic_map_intersect_domain(bmap, isl_basic_set_copy(dom));
+	bmap = isl_basic_map_detect_equalities(bmap);
+	bmap = isl_basic_map_remove_redundancies(bmap);
+
+	return basic_map_partial_lexopt(bmap, dom, empty, max);
+error:
+	isl_basic_set_free(dom);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+struct isl_sol_for {
+	struct isl_sol	sol;
+	int		(*fn)(__isl_take isl_basic_set *dom,
+				__isl_take isl_aff_list *list, void *user);
+	void		*user;
+};
+
+static void sol_for_free(struct isl_sol_for *sol_for)
+{
+	if (!sol_for)
+		return;
+	if (sol_for->sol.context)
+		sol_for->sol.context->op->free(sol_for->sol.context);
+	free(sol_for);
+}
+
+static void sol_for_free_wrap(struct isl_sol *sol)
+{
+	sol_for_free((struct isl_sol_for *)sol);
+}
+
+/* Add the solution identified by the tableau and the context tableau.
+ *
+ * See documentation of sol_add for more details.
+ *
+ * Instead of constructing a basic map, this function calls a user
+ * defined function with the current context as a basic set and
+ * a list of affine expressions representing the relation between
+ * the input and output.  The space over which the affine expressions
+ * are defined is the same as that of the domain.  The number of
+ * affine expressions in the list is equal to the number of output variables.
+ */
+static void sol_for_add(struct isl_sol_for *sol,
+	struct isl_basic_set *dom, struct isl_mat *M)
+{
+	int i;
+	isl_ctx *ctx;
+	isl_local_space *ls;
+	isl_aff *aff;
+	isl_aff_list *list;
+
+	if (sol->sol.error || !dom || !M)
+		goto error;
+
+	ctx = isl_basic_set_get_ctx(dom);
+	ls = isl_basic_set_get_local_space(dom);
+	list = isl_aff_list_alloc(ctx, M->n_row - 1);
+	for (i = 1; i < M->n_row; ++i) {
+		aff = isl_aff_alloc(isl_local_space_copy(ls));
+		if (aff) {
+			isl_int_set(aff->v->el[0], M->row[0][0]);
+			isl_seq_cpy(aff->v->el + 1, M->row[i], M->n_col);
+		}
+		aff = isl_aff_normalize(aff);
+		list = isl_aff_list_add(list, aff);
+	}
+	isl_local_space_free(ls);
+
+	dom = isl_basic_set_finalize(dom);
+
+	if (sol->fn(isl_basic_set_copy(dom), list, sol->user) < 0)
+		goto error;
+
+	isl_basic_set_free(dom);
+	isl_mat_free(M);
+	return;
+error:
+	isl_basic_set_free(dom);
+	isl_mat_free(M);
+	sol->sol.error = 1;
+}
+
+static void sol_for_add_wrap(struct isl_sol *sol,
+	struct isl_basic_set *dom, struct isl_mat *M)
+{
+	sol_for_add((struct isl_sol_for *)sol, dom, M);
+}
+
+static struct isl_sol_for *sol_for_init(struct isl_basic_map *bmap, int max,
+	int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+		  void *user),
+	void *user)
+{
+	struct isl_sol_for *sol_for = NULL;
+	isl_space *dom_dim;
+	struct isl_basic_set *dom = NULL;
+
+	sol_for = isl_calloc_type(bmap->ctx, struct isl_sol_for);
+	if (!sol_for)
+		goto error;
+
+	dom_dim = isl_space_domain(isl_space_copy(bmap->dim));
+	dom = isl_basic_set_universe(dom_dim);
+
+	sol_for->sol.rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+	sol_for->sol.dec_level.callback.run = &sol_dec_level_wrap;
+	sol_for->sol.dec_level.sol = &sol_for->sol;
+	sol_for->fn = fn;
+	sol_for->user = user;
+	sol_for->sol.max = max;
+	sol_for->sol.n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	sol_for->sol.add = &sol_for_add_wrap;
+	sol_for->sol.add_empty = NULL;
+	sol_for->sol.free = &sol_for_free_wrap;
+
+	sol_for->sol.context = isl_context_alloc(dom);
+	if (!sol_for->sol.context)
+		goto error;
+
+	isl_basic_set_free(dom);
+	return sol_for;
+error:
+	isl_basic_set_free(dom);
+	sol_for_free(sol_for);
+	return NULL;
+}
+
+static void sol_for_find_solutions(struct isl_sol_for *sol_for,
+	struct isl_tab *tab)
+{
+	find_solutions_main(&sol_for->sol, tab);
+}
+
+int isl_basic_map_foreach_lexopt(__isl_keep isl_basic_map *bmap, int max,
+	int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+		  void *user),
+	void *user)
+{
+	struct isl_sol_for *sol_for = NULL;
+
+	bmap = isl_basic_map_copy(bmap);
+	bmap = isl_basic_map_detect_equalities(bmap);
+	if (!bmap)
+		return -1;
+
+	sol_for = sol_for_init(bmap, max, fn, user);
+	if (!sol_for)
+		goto error;
+
+	if (isl_basic_map_plain_is_empty(bmap))
+		/* nothing */;
+	else {
+		struct isl_tab *tab;
+		struct isl_context *context = sol_for->sol.context;
+		tab = tab_for_lexmin(bmap,
+				context->op->peek_basic_set(context), 1, max);
+		tab = context->op->detect_nonnegative_parameters(context, tab);
+		sol_for_find_solutions(sol_for, tab);
+		if (sol_for->sol.error)
+			goto error;
+	}
+
+	sol_free(&sol_for->sol);
+	isl_basic_map_free(bmap);
+	return 0;
+error:
+	sol_free(&sol_for->sol);
+	isl_basic_map_free(bmap);
+	return -1;
+}
+
+int isl_basic_set_foreach_lexopt(__isl_keep isl_basic_set *bset, int max,
+	int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+		  void *user),
+	void *user)
+{
+	return isl_basic_map_foreach_lexopt(bset, max, fn, user);
+}
+
+/* Check if the given sequence of len variables starting at pos
+ * represents a trivial (i.e., zero) solution.
+ * The variables are assumed to be non-negative and to come in pairs,
+ * with each pair representing a variable of unrestricted sign.
+ * The solution is trivial if each such pair in the sequence consists
+ * of two identical values, meaning that the variable being represented
+ * has value zero.
+ */
+static int region_is_trivial(struct isl_tab *tab, int pos, int len)
+{
+	int i;
+
+	if (len == 0)
+		return 0;
+
+	for (i = 0; i < len; i +=  2) {
+		int neg_row;
+		int pos_row;
+
+		neg_row = tab->var[pos + i].is_row ?
+				tab->var[pos + i].index : -1;
+		pos_row = tab->var[pos + i + 1].is_row ?
+				tab->var[pos + i + 1].index : -1;
+
+		if ((neg_row < 0 ||
+		     isl_int_is_zero(tab->mat->row[neg_row][1])) &&
+		    (pos_row < 0 ||
+		     isl_int_is_zero(tab->mat->row[pos_row][1])))
+			continue;
+
+		if (neg_row < 0 || pos_row < 0)
+			return 0;
+		if (isl_int_ne(tab->mat->row[neg_row][1],
+			       tab->mat->row[pos_row][1]))
+			return 0;
+	}
+
+	return 1;
+}
+
+/* Return the index of the first trivial region or -1 if all regions
+ * are non-trivial.
+ */
+static int first_trivial_region(struct isl_tab *tab,
+	int n_region, struct isl_region *region)
+{
+	int i;
+
+	for (i = 0; i < n_region; ++i) {
+		if (region_is_trivial(tab, region[i].pos, region[i].len))
+			return i;
+	}
+
+	return -1;
+}
+
+/* Check if the solution is optimal, i.e., whether the first
+ * n_op entries are zero.
+ */
+static int is_optimal(__isl_keep isl_vec *sol, int n_op)
+{
+	int i;
+
+	for (i = 0; i < n_op; ++i)
+		if (!isl_int_is_zero(sol->el[1 + i]))
+			return 0;
+	return 1;
+}
+
+/* Add constraints to "tab" that ensure that any solution is significantly
+ * better that that represented by "sol".  That is, find the first
+ * relevant (within first n_op) non-zero coefficient and force it (along
+ * with all previous coefficients) to be zero.
+ * If the solution is already optimal (all relevant coefficients are zero),
+ * then just mark the table as empty.
+ */
+static int force_better_solution(struct isl_tab *tab,
+	__isl_keep isl_vec *sol, int n_op)
+{
+	int i;
+	isl_ctx *ctx;
+	isl_vec *v = NULL;
+
+	if (!sol)
+		return -1;
+
+	for (i = 0; i < n_op; ++i)
+		if (!isl_int_is_zero(sol->el[1 + i]))
+			break;
+
+	if (i == n_op) {
+		if (isl_tab_mark_empty(tab) < 0)
+			return -1;
+		return 0;
+	}
+
+	ctx = isl_vec_get_ctx(sol);
+	v = isl_vec_alloc(ctx, 1 + tab->n_var);
+	if (!v)
+		return -1;
+
+	for (; i >= 0; --i) {
+		v = isl_vec_clr(v);
+		isl_int_set_si(v->el[1 + i], -1);
+		if (add_lexmin_eq(tab, v->el) < 0)
+			goto error;
+	}
+
+	isl_vec_free(v);
+	return 0;
+error:
+	isl_vec_free(v);
+	return -1;
+}
+
+struct isl_trivial {
+	int update;
+	int region;
+	int side;
+	struct isl_tab_undo *snap;
+};
+
+/* Return the lexicographically smallest non-trivial solution of the
+ * given ILP problem.
+ *
+ * All variables are assumed to be non-negative.
+ *
+ * n_op is the number of initial coordinates to optimize.
+ * That is, once a solution has been found, we will only continue looking
+ * for solution that result in significantly better values for those
+ * initial coordinates.  That is, we only continue looking for solutions
+ * that increase the number of initial zeros in this sequence.
+ *
+ * A solution is non-trivial, if it is non-trivial on each of the
+ * specified regions.  Each region represents a sequence of pairs
+ * of variables.  A solution is non-trivial on such a region if
+ * at least one of these pairs consists of different values, i.e.,
+ * such that the non-negative variable represented by the pair is non-zero.
+ *
+ * Whenever a conflict is encountered, all constraints involved are
+ * reported to the caller through a call to "conflict".
+ *
+ * We perform a simple branch-and-bound backtracking search.
+ * Each level in the search represents initially trivial region that is forced
+ * to be non-trivial.
+ * At each level we consider n cases, where n is the length of the region.
+ * In terms of the n/2 variables of unrestricted signs being encoded by
+ * the region, we consider the cases
+ *	x_0 >= 1
+ *	x_0 <= -1
+ *	x_0 = 0 and x_1 >= 1
+ *	x_0 = 0 and x_1 <= -1
+ *	x_0 = 0 and x_1 = 0 and x_2 >= 1
+ *	x_0 = 0 and x_1 = 0 and x_2 <= -1
+ *	...
+ * The cases are considered in this order, assuming that each pair
+ * x_i_a x_i_b represents the value x_i_b - x_i_a.
+ * That is, x_0 >= 1 is enforced by adding the constraint
+ *	x_0_b - x_0_a >= 1
+ */
+__isl_give isl_vec *isl_tab_basic_set_non_trivial_lexmin(
+	__isl_take isl_basic_set *bset, int n_op, int n_region,
+	struct isl_region *region,
+	int (*conflict)(int con, void *user), void *user)
+{
+	int i, j;
+	int r;
+	isl_ctx *ctx;
+	isl_vec *v = NULL;
+	isl_vec *sol = NULL;
+	struct isl_tab *tab;
+	struct isl_trivial *triv = NULL;
+	int level, init;
+
+	if (!bset)
+		return NULL;
+
+	ctx = isl_basic_set_get_ctx(bset);
+	sol = isl_vec_alloc(ctx, 0);
+
+	tab = tab_for_lexmin(bset, NULL, 0, 0);
+	if (!tab)
+		goto error;
+	tab->conflict = conflict;
+	tab->conflict_user = user;
+
+	v = isl_vec_alloc(ctx, 1 + tab->n_var);
+	triv = isl_calloc_array(ctx, struct isl_trivial, n_region);
+	if (!v || (n_region && !triv))
+		goto error;
+
+	level = 0;
+	init = 1;
+
+	while (level >= 0) {
+		int side, base;
+
+		if (init) {
+			tab = cut_to_integer_lexmin(tab, CUT_ONE);
+			if (!tab)
+				goto error;
+			if (tab->empty)
+				goto backtrack;
+			r = first_trivial_region(tab, n_region, region);
+			if (r < 0) {
+				for (i = 0; i < level; ++i)
+					triv[i].update = 1;
+				isl_vec_free(sol);
+				sol = isl_tab_get_sample_value(tab);
+				if (!sol)
+					goto error;
+				if (is_optimal(sol, n_op))
+					break;
+				goto backtrack;
+			}
+			if (level >= n_region)
+				isl_die(ctx, isl_error_internal,
+					"nesting level too deep", goto error);
+			if (isl_tab_extend_cons(tab,
+					    2 * region[r].len + 2 * n_op) < 0)
+				goto error;
+			triv[level].region = r;
+			triv[level].side = 0;
+		}
+
+		r = triv[level].region;
+		side = triv[level].side;
+		base = 2 * (side/2);
+
+		if (side >= region[r].len) {
+backtrack:
+			level--;
+			init = 0;
+			if (level >= 0)
+				if (isl_tab_rollback(tab, triv[level].snap) < 0)
+					goto error;
+			continue;
+		}
+
+		if (triv[level].update) {
+			if (force_better_solution(tab, sol, n_op) < 0)
+				goto error;
+			triv[level].update = 0;
+		}
+
+		if (side == base && base >= 2) {
+			for (j = base - 2; j < base; ++j) {
+				v = isl_vec_clr(v);
+				isl_int_set_si(v->el[1 + region[r].pos + j], 1);
+				if (add_lexmin_eq(tab, v->el) < 0)
+					goto error;
+			}
+		}
+
+		triv[level].snap = isl_tab_snap(tab);
+		if (isl_tab_push_basis(tab) < 0)
+			goto error;
+
+		v = isl_vec_clr(v);
+		isl_int_set_si(v->el[0], -1);
+		isl_int_set_si(v->el[1 + region[r].pos + side], -1);
+		isl_int_set_si(v->el[1 + region[r].pos + (side ^ 1)], 1);
+		tab = add_lexmin_ineq(tab, v->el);
+
+		triv[level].side++;
+		level++;
+		init = 1;
+	}
+
+	free(triv);
+	isl_vec_free(v);
+	isl_tab_free(tab);
+	isl_basic_set_free(bset);
+
+	return sol;
+error:
+	free(triv);
+	isl_vec_free(v);
+	isl_tab_free(tab);
+	isl_basic_set_free(bset);
+	isl_vec_free(sol);
+	return NULL;
+}
+
+/* Return the lexicographically smallest rational point in "bset",
+ * assuming that all variables are non-negative.
+ * If "bset" is empty, then return a zero-length vector.
+ */
+__isl_give isl_vec *isl_tab_basic_set_non_neg_lexmin(
+	__isl_take isl_basic_set *bset)
+{
+	struct isl_tab *tab;
+	isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+	isl_vec *sol;
+
+	if (!bset)
+		return NULL;
+
+	tab = tab_for_lexmin(bset, NULL, 0, 0);
+	if (!tab)
+		goto error;
+	if (tab->empty)
+		sol = isl_vec_alloc(ctx, 0);
+	else
+		sol = isl_tab_get_sample_value(tab);
+	isl_tab_free(tab);
+	isl_basic_set_free(bset);
+	return sol;
+error:
+	isl_tab_free(tab);
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+struct isl_sol_pma {
+	struct isl_sol	sol;
+	isl_pw_multi_aff *pma;
+	isl_set *empty;
+};
+
+static void sol_pma_free(struct isl_sol_pma *sol_pma)
+{
+	if (!sol_pma)
+		return;
+	if (sol_pma->sol.context)
+		sol_pma->sol.context->op->free(sol_pma->sol.context);
+	isl_pw_multi_aff_free(sol_pma->pma);
+	isl_set_free(sol_pma->empty);
+	free(sol_pma);
+}
+
+/* This function is called for parts of the context where there is
+ * no solution, with "bset" corresponding to the context tableau.
+ * Simply add the basic set to the set "empty".
+ */
+static void sol_pma_add_empty(struct isl_sol_pma *sol,
+	__isl_take isl_basic_set *bset)
+{
+	if (!bset)
+		goto error;
+	isl_assert(bset->ctx, sol->empty, goto error);
+
+	sol->empty = isl_set_grow(sol->empty, 1);
+	bset = isl_basic_set_simplify(bset);
+	bset = isl_basic_set_finalize(bset);
+	sol->empty = isl_set_add_basic_set(sol->empty, bset);
+	if (!sol->empty)
+		sol->sol.error = 1;
+	return;
+error:
+	isl_basic_set_free(bset);
+	sol->sol.error = 1;
+}
+
+/* Given a basic map "dom" that represents the context and an affine
+ * matrix "M" that maps the dimensions of the context to the
+ * output variables, construct an isl_pw_multi_aff with a single
+ * cell corresponding to "dom" and affine expressions copied from "M".
+ */
+static void sol_pma_add(struct isl_sol_pma *sol,
+	__isl_take isl_basic_set *dom, __isl_take isl_mat *M)
+{
+	int i;
+	isl_local_space *ls;
+	isl_aff *aff;
+	isl_multi_aff *maff;
+	isl_pw_multi_aff *pma;
+
+	maff = isl_multi_aff_alloc(isl_pw_multi_aff_get_space(sol->pma));
+	ls = isl_basic_set_get_local_space(dom);
+	for (i = 1; i < M->n_row; ++i) {
+		aff = isl_aff_alloc(isl_local_space_copy(ls));
+		if (aff) {
+			isl_int_set(aff->v->el[0], M->row[0][0]);
+			isl_seq_cpy(aff->v->el + 1, M->row[i], M->n_col);
+		}
+		aff = isl_aff_normalize(aff);
+		maff = isl_multi_aff_set_aff(maff, i - 1, aff);
+	}
+	isl_local_space_free(ls);
+	isl_mat_free(M);
+	dom = isl_basic_set_simplify(dom);
+	dom = isl_basic_set_finalize(dom);
+	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(dom), maff);
+	sol->pma = isl_pw_multi_aff_add_disjoint(sol->pma, pma);
+	if (!sol->pma)
+		sol->sol.error = 1;
+}
+
+static void sol_pma_free_wrap(struct isl_sol *sol)
+{
+	sol_pma_free((struct isl_sol_pma *)sol);
+}
+
+static void sol_pma_add_empty_wrap(struct isl_sol *sol,
+	__isl_take isl_basic_set *bset)
+{
+	sol_pma_add_empty((struct isl_sol_pma *)sol, bset);
+}
+
+static void sol_pma_add_wrap(struct isl_sol *sol,
+	__isl_take isl_basic_set *dom, __isl_take isl_mat *M)
+{
+	sol_pma_add((struct isl_sol_pma *)sol, dom, M);
+}
+
+/* Construct an isl_sol_pma structure for accumulating the solution.
+ * If track_empty is set, then we also keep track of the parts
+ * of the context where there is no solution.
+ * If max is set, then we are solving a maximization, rather than
+ * a minimization problem, which means that the variables in the
+ * tableau have value "M - x" rather than "M + x".
+ */
+static struct isl_sol *sol_pma_init(__isl_keep isl_basic_map *bmap,
+	__isl_take isl_basic_set *dom, int track_empty, int max)
+{
+	struct isl_sol_pma *sol_pma = NULL;
+
+	if (!bmap)
+		goto error;
+
+	sol_pma = isl_calloc_type(bmap->ctx, struct isl_sol_pma);
+	if (!sol_pma)
+		goto error;
+
+	sol_pma->sol.rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+	sol_pma->sol.dec_level.callback.run = &sol_dec_level_wrap;
+	sol_pma->sol.dec_level.sol = &sol_pma->sol;
+	sol_pma->sol.max = max;
+	sol_pma->sol.n_out = isl_basic_map_dim(bmap, isl_dim_out);
+	sol_pma->sol.add = &sol_pma_add_wrap;
+	sol_pma->sol.add_empty = track_empty ? &sol_pma_add_empty_wrap : NULL;
+	sol_pma->sol.free = &sol_pma_free_wrap;
+	sol_pma->pma = isl_pw_multi_aff_empty(isl_basic_map_get_space(bmap));
+	if (!sol_pma->pma)
+		goto error;
+
+	sol_pma->sol.context = isl_context_alloc(dom);
+	if (!sol_pma->sol.context)
+		goto error;
+
+	if (track_empty) {
+		sol_pma->empty = isl_set_alloc_space(isl_basic_set_get_space(dom),
+							1, ISL_SET_DISJOINT);
+		if (!sol_pma->empty)
+			goto error;
+	}
+
+	isl_basic_set_free(dom);
+	return &sol_pma->sol;
+error:
+	isl_basic_set_free(dom);
+	sol_pma_free(sol_pma);
+	return NULL;
+}
+
+/* Base case of isl_tab_basic_map_partial_lexopt, after removing
+ * some obvious symmetries.
+ *
+ * We call basic_map_partial_lexopt_base and extract the results.
+ */
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_base_pma(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max)
+{
+	isl_pw_multi_aff *result = NULL;
+	struct isl_sol *sol;
+	struct isl_sol_pma *sol_pma;
+
+	sol = basic_map_partial_lexopt_base(bmap, dom, empty, max,
+					    &sol_pma_init);
+	if (!sol)
+		return NULL;
+	sol_pma = (struct isl_sol_pma *) sol;
+
+	result = isl_pw_multi_aff_copy(sol_pma->pma);
+	if (empty)
+		*empty = isl_set_copy(sol_pma->empty);
+	sol_free(&sol_pma->sol);
+	return result;
+}
+
+/* Given that the last input variable of "maff" represents the minimum
+ * of some bounds, check whether we need to plug in the expression
+ * of the minimum.
+ *
+ * In particular, check if the last input variable appears in any
+ * of the expressions in "maff".
+ */
+static int need_substitution(__isl_keep isl_multi_aff *maff)
+{
+	int i;
+	unsigned pos;
+
+	pos = isl_multi_aff_dim(maff, isl_dim_in) - 1;
+
+	for (i = 0; i < maff->n; ++i)
+		if (isl_aff_involves_dims(maff->p[i], isl_dim_in, pos, 1))
+			return 1;
+
+	return 0;
+}
+
+/* Given a set of upper bounds on the last "input" variable m,
+ * construct a piecewise affine expression that selects
+ * the minimal upper bound to m, i.e.,
+ * divide the space into cells where one
+ * of the upper bounds is smaller than all the others and select
+ * this upper bound on that cell.
+ *
+ * In particular, if there are n bounds b_i, then the result
+ * consists of n cell, each one of the form
+ *
+ *	b_i <= b_j	for j > i
+ *	b_i <  b_j	for j < i
+ *
+ * The affine expression on this cell is
+ *
+ *	b_i
+ */
+static __isl_give isl_pw_aff *set_minimum_pa(__isl_take isl_space *space,
+	__isl_take isl_mat *var)
+{
+	int i;
+	isl_aff *aff = NULL;
+	isl_basic_set *bset = NULL;
+	isl_ctx *ctx;
+	isl_pw_aff *paff = NULL;
+	isl_space *pw_space;
+	isl_local_space *ls = NULL;
+
+	if (!space || !var)
+		goto error;
+
+	ctx = isl_space_get_ctx(space);
+	ls = isl_local_space_from_space(isl_space_copy(space));
+	pw_space = isl_space_copy(space);
+	pw_space = isl_space_from_domain(pw_space);
+	pw_space = isl_space_add_dims(pw_space, isl_dim_out, 1);
+	paff = isl_pw_aff_alloc_size(pw_space, var->n_row);
+
+	for (i = 0; i < var->n_row; ++i) {
+		isl_pw_aff *paff_i;
+
+		aff = isl_aff_alloc(isl_local_space_copy(ls));
+		bset = isl_basic_set_alloc_space(isl_space_copy(space), 0,
+					       0, var->n_row - 1);
+		if (!aff || !bset)
+			goto error;
+		isl_int_set_si(aff->v->el[0], 1);
+		isl_seq_cpy(aff->v->el + 1, var->row[i], var->n_col);
+		isl_int_set_si(aff->v->el[1 + var->n_col], 0);
+		bset = select_minimum(bset, var, i);
+		paff_i = isl_pw_aff_alloc(isl_set_from_basic_set(bset), aff);
+		paff = isl_pw_aff_add_disjoint(paff, paff_i);
+	}
+
+	isl_local_space_free(ls);
+	isl_space_free(space);
+	isl_mat_free(var);
+	return paff;
+error:
+	isl_aff_free(aff);
+	isl_basic_set_free(bset);
+	isl_pw_aff_free(paff);
+	isl_local_space_free(ls);
+	isl_space_free(space);
+	isl_mat_free(var);
+	return NULL;
+}
+
+/* Given a piecewise multi-affine expression of which the last input variable
+ * is the minimum of the bounds in "cst", plug in the value of the minimum.
+ * This minimum expression is given in "min_expr_pa".
+ * The set "min_expr" contains the same information, but in the form of a set.
+ * The variable is subsequently projected out.
+ *
+ * The implementation is similar to those of "split" and "split_domain".
+ * If the variable appears in a given expression, then minimum expression
+ * is plugged in.  Otherwise, if the variable appears in the constraints
+ * and a split is required, then the domain is split.  Otherwise, no split
+ * is performed.
+ */
+static __isl_give isl_pw_multi_aff *split_domain_pma(
+	__isl_take isl_pw_multi_aff *opt, __isl_take isl_pw_aff *min_expr_pa,
+	__isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+	int n_in;
+	int i;
+	isl_space *space;
+	isl_pw_multi_aff *res;
+
+	if (!opt || !min_expr || !cst)
+		goto error;
+
+	n_in = isl_pw_multi_aff_dim(opt, isl_dim_in);
+	space = isl_pw_multi_aff_get_space(opt);
+	space = isl_space_drop_dims(space, isl_dim_in, n_in - 1, 1);
+	res = isl_pw_multi_aff_empty(space);
+
+	for (i = 0; i < opt->n; ++i) {
+		isl_pw_multi_aff *pma;
+
+		pma = isl_pw_multi_aff_alloc(isl_set_copy(opt->p[i].set),
+					 isl_multi_aff_copy(opt->p[i].maff));
+		if (need_substitution(opt->p[i].maff))
+			pma = isl_pw_multi_aff_substitute(pma,
+					isl_dim_in, n_in - 1, min_expr_pa);
+		else if (need_split_set(opt->p[i].set, cst))
+			pma = isl_pw_multi_aff_intersect_domain(pma,
+						       isl_set_copy(min_expr));
+		pma = isl_pw_multi_aff_project_out(pma,
+						    isl_dim_in, n_in - 1, 1);
+
+		res = isl_pw_multi_aff_add_disjoint(res, pma);
+	}
+
+	isl_pw_multi_aff_free(opt);
+	isl_pw_aff_free(min_expr_pa);
+	isl_set_free(min_expr);
+	isl_mat_free(cst);
+	return res;
+error:
+	isl_pw_multi_aff_free(opt);
+	isl_pw_aff_free(min_expr_pa);
+	isl_set_free(min_expr);
+	isl_mat_free(cst);
+	return NULL;
+}
+
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max);
+
+/* This function is called from basic_map_partial_lexopt_symm.
+ * The last variable of "bmap" and "dom" corresponds to the minimum
+ * of the bounds in "cst".  "map_space" is the space of the original
+ * input relation (of basic_map_partial_lexopt_symm) and "set_space"
+ * is the space of the original domain.
+ *
+ * We recursively call basic_map_partial_lexopt and then plug in
+ * the definition of the minimum in the result.
+ */
+static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_pma_core(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max, __isl_take isl_mat *cst,
+	__isl_take isl_space *map_space, __isl_take isl_space *set_space)
+{
+	isl_pw_multi_aff *opt;
+	isl_pw_aff *min_expr_pa;
+	isl_set *min_expr;
+	union isl_lex_res res;
+
+	min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst));
+	min_expr_pa = set_minimum_pa(isl_basic_set_get_space(dom),
+					isl_mat_copy(cst));
+
+	opt = basic_map_partial_lexopt_pma(bmap, dom, empty, max);
+
+	if (empty) {
+		*empty = split(*empty,
+			       isl_set_copy(min_expr), isl_mat_copy(cst));
+		*empty = isl_set_reset_space(*empty, set_space);
+	}
+
+	opt = split_domain_pma(opt, min_expr_pa, min_expr, cst);
+	opt = isl_pw_multi_aff_reset_space(opt, map_space);
+
+	res.pma = opt;
+	return res;
+}
+
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_symm_pma(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max, int first, int second)
+{
+	return basic_map_partial_lexopt_symm(bmap, dom, empty, max,
+		    first, second, &basic_map_partial_lexopt_symm_pma_core).pma;
+}
+
+/* Recursive part of isl_basic_map_partial_lexopt_pw_multi_aff, after detecting
+ * equalities and removing redundant constraints.
+ *
+ * We first check if there are any parallel constraints (left).
+ * If not, we are in the base case.
+ * If there are parallel constraints, we replace them by a single
+ * constraint in basic_map_partial_lexopt_symm_pma and then call
+ * this function recursively to look for more parallel constraints.
+ */
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max)
+{
+	int par = 0;
+	int first, second;
+
+	if (!bmap)
+		goto error;
+
+	if (bmap->ctx->opt->pip_symmetry)
+		par = parallel_constraints(bmap, &first, &second);
+	if (par < 0)
+		goto error;
+	if (!par)
+		return basic_map_partial_lexopt_base_pma(bmap, dom, empty, max);
+	
+	return basic_map_partial_lexopt_symm_pma(bmap, dom, empty, max,
+						 first, second);
+error:
+	isl_basic_set_free(dom);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Compute the lexicographic minimum (or maximum if "max" is set)
+ * of "bmap" over the domain "dom" and return the result as a piecewise
+ * multi-affine expression.
+ * If "empty" is not NULL, then *empty is assigned a set that
+ * contains those parts of the domain where there is no solution.
+ * If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
+ * then we compute the rational optimum.  Otherwise, we compute
+ * the integral optimum.
+ *
+ * We perform some preprocessing.  As the PILP solver does not
+ * handle implicit equalities very well, we first make sure all
+ * the equalities are explicitly available.
+ *
+ * We also add context constraints to the basic map and remove
+ * redundant constraints.  This is only needed because of the
+ * way we handle simple symmetries.  In particular, we currently look
+ * for symmetries on the constraints, before we set up the main tableau.
+ * It is then no good to look for symmetries on possibly redundant constraints.
+ */
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexopt_pw_multi_aff(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty, int max)
+{
+	if (empty)
+		*empty = NULL;
+	if (!bmap || !dom)
+		goto error;
+
+	isl_assert(bmap->ctx,
+	    isl_basic_map_compatible_domain(bmap, dom), goto error);
+
+	if (isl_basic_set_dim(dom, isl_dim_all) == 0)
+		return basic_map_partial_lexopt_pma(bmap, dom, empty, max);
+
+	bmap = isl_basic_map_intersect_domain(bmap, isl_basic_set_copy(dom));
+	bmap = isl_basic_map_detect_equalities(bmap);
+	bmap = isl_basic_map_remove_redundancies(bmap);
+
+	return basic_map_partial_lexopt_pma(bmap, dom, empty, max);
+error:
+	isl_basic_set_free(dom);
+	isl_basic_map_free(bmap);
+	return NULL;
+}

Added: polly/trunk/lib/External/isl/isl_tarjan.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tarjan.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_tarjan.c (added)
+++ polly/trunk/lib/External/isl/isl_tarjan.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2010-2011 INRIA Saclay
+ * Copyright 2012      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France
+ * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+#include <stdlib.h>
+#include <isl/ctx.h>
+#include <isl_tarjan.h>
+
+void isl_tarjan_graph_free(struct isl_tarjan_graph *g)
+{
+	if (!g)
+		return;
+	free(g->node);
+	free(g->stack);
+	free(g->order);
+	free(g);
+}
+
+static struct isl_tarjan_graph *isl_tarjan_graph_alloc(isl_ctx *ctx, int len)
+{
+	struct isl_tarjan_graph *g;
+	int i;
+
+	g = isl_calloc_type(ctx, struct isl_tarjan_graph);
+	if (!g)
+		return NULL;
+	g->len = len;
+	g->node = isl_alloc_array(ctx, struct isl_tarjan_node, len);
+	if (len && !g->node)
+		goto error;
+	for (i = 0; i < len; ++i)
+		g->node[i].index = -1;
+	g->stack = isl_alloc_array(ctx, int, len);
+	if (len && !g->stack)
+		goto error;
+	g->order = isl_alloc_array(ctx, int, 2 * len);
+	if (len && !g->order)
+		goto error;
+
+	g->sp = 0;
+	g->index = 0;
+	g->op = 0;
+
+	return g;
+error:
+	isl_tarjan_graph_free(g);
+	return NULL;
+}
+
+/* Perform Tarjan's algorithm for computing the strongly connected components
+ * in the graph with g->len nodes and with edges defined by "follows".
+ */
+static int isl_tarjan_components(struct isl_tarjan_graph *g, int i,
+	int (*follows)(int i, int j, void *user), void *user)
+{
+	int j;
+
+	g->node[i].index = g->index;
+	g->node[i].min_index = g->index;
+	g->node[i].on_stack = 1;
+	g->index++;
+	g->stack[g->sp++] = i;
+
+	for (j = g->len - 1; j >= 0; --j) {
+		int f;
+
+		if (j == i)
+			continue;
+		if (g->node[j].index >= 0 &&
+			(!g->node[j].on_stack ||
+			 g->node[j].index > g->node[i].min_index))
+			continue;
+
+		f = follows(i, j, user);
+		if (f < 0)
+			return -1;
+		if (!f)
+			continue;
+
+		if (g->node[j].index < 0) {
+			isl_tarjan_components(g, j, follows, user);
+			if (g->node[j].min_index < g->node[i].min_index)
+				g->node[i].min_index = g->node[j].min_index;
+		} else if (g->node[j].index < g->node[i].min_index)
+			g->node[i].min_index = g->node[j].index;
+	}
+
+	if (g->node[i].index != g->node[i].min_index)
+		return 0;
+
+	do {
+		j = g->stack[--g->sp];
+		g->node[j].on_stack = 0;
+		g->order[g->op++] = j;
+	} while (j != i);
+	g->order[g->op++] = -1;
+
+	return 0;
+}
+
+/* Decompose the graph with "len" nodes and edges defined by "follows"
+ * into strongly connected components (SCCs).
+ * follows(i, j, user) should return 1 if "i" follows "j" and 0 otherwise.
+ * It should return -1 on error.
+ *
+ * If SCC a contains a node i that follows a node j in another SCC b
+ * (i.e., follows(i, j, user) returns 1), then SCC a will appear after SCC b
+ * in the result.
+ */
+struct isl_tarjan_graph *isl_tarjan_graph_init(isl_ctx *ctx, int len,
+	int (*follows)(int i, int j, void *user), void *user)
+{
+	int i;
+	struct isl_tarjan_graph *g = NULL;
+
+	g = isl_tarjan_graph_alloc(ctx, len);
+	if (!g)
+		return NULL;
+	for (i = len - 1; i >= 0; --i) {
+		if (g->node[i].index >= 0)
+			continue;
+		if (isl_tarjan_components(g, i, follows, user) < 0)
+			goto error;
+	}
+
+	return g;
+error:
+	isl_tarjan_graph_free(g);
+	return NULL;
+}

Added: polly/trunk/lib/External/isl/isl_tarjan.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tarjan.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_tarjan.h (added)
+++ polly/trunk/lib/External/isl/isl_tarjan.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,40 @@
+#ifndef ISL_TARJAN_H
+#define ISL_TARJAN_H
+
+/* Structure for representing the nodes in the graph being traversed
+ * using Tarjan's algorithm.
+ * index represents the order in which nodes are visited.
+ * min_index is the index of the root of a (sub)component.
+ * on_stack indicates whether the node is currently on the stack.
+ */
+struct isl_tarjan_node {
+	int index;
+	int min_index;
+	int on_stack;
+};
+
+/* Structure for representing the graph being traversed
+ * using Tarjan's algorithm.
+ * len is the number of nodes
+ * node is an array of nodes
+ * stack contains the nodes on the path from the root to the current node
+ * sp is the stack pointer
+ * index is the index of the last node visited
+ * order contains the elements of the components separated by -1
+ * op represents the current position in order
+ */
+struct isl_tarjan_graph {
+	int len;
+	struct isl_tarjan_node *node;
+	int *stack;
+	int sp;
+	int index;
+	int *order;
+	int op;
+};
+
+struct isl_tarjan_graph *isl_tarjan_graph_init(isl_ctx *ctx, int len,
+	int (*follows)(int i, int j, void *user), void *user);
+void isl_tarjan_graph_free(struct isl_tarjan_graph *g);
+
+#endif

Added: polly/trunk/lib/External/isl/isl_test.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_test.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_test.c (added)
+++ polly/trunk/lib/External/isl/isl_test.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5176 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010      INRIA Saclay
+ * Copyright 2012-2013 Ecole Normale Superieure
+ * Copyright 2014      INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <limits.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_aff_private.h>
+#include <isl/set.h>
+#include <isl/flow.h>
+#include <isl_constraint_private.h>
+#include <isl/polynomial.h>
+#include <isl/union_map.h>
+#include <isl_factorization.h>
+#include <isl/schedule.h>
+#include <isl_options_private.h>
+#include <isl/vertices.h>
+#include <isl/ast_build.h>
+#include <isl/val.h>
+#include <isl/ilp.h>
+#include <isl_ast_build_expr.h>
+#include <isl/options.h>
+
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
+
+static char *srcdir;
+
+static char *get_filename(isl_ctx *ctx, const char *name, const char *suffix) {
+	char *filename;
+	int length;
+	char *pattern = "%s/test_inputs/%s.%s";
+
+	length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name)
+		+ strlen(suffix) + 1;
+	filename = isl_alloc_array(ctx, char, length);
+
+	if (!filename)
+		return NULL;
+
+	sprintf(filename, pattern, srcdir, name, suffix);
+
+	return filename;
+}
+
+void test_parse_map(isl_ctx *ctx, const char *str)
+{
+	isl_map *map;
+
+	map = isl_map_read_from_str(ctx, str);
+	assert(map);
+	isl_map_free(map);
+}
+
+int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2)
+{
+	isl_map *map, *map2;
+	int equal;
+
+	map = isl_map_read_from_str(ctx, str);
+	map2 = isl_map_read_from_str(ctx, str2);
+	equal = isl_map_is_equal(map, map2);
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "maps not equal",
+			return -1);
+
+	return 0;
+}
+
+void test_parse_pwqp(isl_ctx *ctx, const char *str)
+{
+	isl_pw_qpolynomial *pwqp;
+
+	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+	assert(pwqp);
+	isl_pw_qpolynomial_free(pwqp);
+}
+
+static void test_parse_pwaff(isl_ctx *ctx, const char *str)
+{
+	isl_pw_aff *pwaff;
+
+	pwaff = isl_pw_aff_read_from_str(ctx, str);
+	assert(pwaff);
+	isl_pw_aff_free(pwaff);
+}
+
+int test_parse(struct isl_ctx *ctx)
+{
+	isl_map *map, *map2;
+	const char *str, *str2;
+
+	str = "{ [i] -> [-i] }";
+	map = isl_map_read_from_str(ctx, str);
+	assert(map);
+	isl_map_free(map);
+
+	str = "{ A[i] -> L[([i/3])] }";
+	map = isl_map_read_from_str(ctx, str);
+	assert(map);
+	isl_map_free(map);
+
+	test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
+	test_parse_map(ctx, "{ [p1, y1, y2] -> [2, y1, y2] : "
+				"p1 = 1 && (y1 <= y2 || y2 = 0) }");
+
+	str = "{ [x,y]  : [([x/2]+y)/3] >= 1 }";
+	str2 = "{ [x, y] : 2y >= 6 - x }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{ [x,y] : x <= min(y, 2*y+3) }",
+				      "{ [x,y] : x <= y, 2*y + 3 }") < 0)
+		return -1;
+	str = "{ [x, y] : (y <= x and y >= -3) or (2y <= -3 + x and y <= -4) }";
+	if (test_parse_map_equal(ctx, "{ [x,y] : x >= min(y, 2*y+3) }",
+					str) < 0)
+		return -1;
+
+	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
+	map = isl_map_read_from_str(ctx, str);
+	str = "{ [new, old] -> [o0, o1] : "
+	       "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
+	       "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
+	       "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
+	map = isl_map_read_from_str(ctx, str);
+	str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "[n] -> { [c1] : c1>=0 and c1<=floord(n-4,3) }";
+	str2 = "[n] -> { [c1] : c1 >= 0 and 3c1 <= -4 + n }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [i,j] -> [i] : i < j; [i,j] -> [j] : j <= i }";
+	str2 = "{ [i,j] -> [min(i,j)] }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [i,j] : i != j }";
+	str2 = "{ [i,j] : i < j or i > j }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [i,j] : (i+1)*2 >= j }";
+	str2 = "{ [i, j] : j <= 2 + 2i }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [i] -> [i > 0 ? 4 : 5] }";
+	str2 = "{ [i] -> [5] : i <= 0; [i] -> [4] : i >= 1 }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "[N=2,M] -> { [i=[(M+N)/4]] }";
+	str2 = "[N, M] -> { [i] : N = 2 and 4i <= 2 + M and 4i >= -1 + M }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [x] : x >= 0 }";
+	str2 = "{ [x] : x-0 >= 0 }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [i] : ((i > 10)) }";
+	str2 = "{ [i] : i >= 11 }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	str = "{ [i] -> [0] }";
+	str2 = "{ [i] -> [0 * i] }";
+	if (test_parse_map_equal(ctx, str, str2) < 0)
+		return -1;
+
+	test_parse_pwqp(ctx, "{ [i] -> i + [ (i + [i/3])/2 ] }");
+	test_parse_map(ctx, "{ S1[i] -> [([i/10]),i%10] : 0 <= i <= 45 }");
+	test_parse_pwaff(ctx, "{ [i] -> [i + 1] : i > 0; [a] -> [a] : a < 0 }");
+	test_parse_pwqp(ctx, "{ [x] -> ([(x)/2] * [(x)/3]) }");
+
+	if (test_parse_map_equal(ctx, "{ [a] -> [b] : (not false) }",
+				      "{ [a] -> [b] : true }") < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{ [i] : i/2 <= 5 }",
+				      "{ [i] : i <= 10 }") < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{Sym=[n] [i] : i <= n }",
+				      "[n] -> { [i] : i <= n }") < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{ [*] }", "{ [a] }") < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{ [i] : 2*floor(i/2) = i }",
+				      "{ [i] : exists a : i = 2 a }") < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{ [a] -> [b] : a = 5 implies b = 5 }",
+				      "{ [a] -> [b] : a != 5 or b = 5 }") < 0)
+		return -1;
+
+	if (test_parse_map_equal(ctx, "{ [a] -> [a - 1 : a > 0] }",
+				      "{ [a] -> [a - 1] : a > 0 }") < 0)
+		return -1;
+	if (test_parse_map_equal(ctx,
+	    "{ [a] -> [a - 1 : a > 0; a : a <= 0] }",
+	    "{ [a] -> [a - 1] : a > 0; [a] -> [a] : a <= 0 }") < 0)
+		return -1;
+	if (test_parse_map_equal(ctx,
+	    "{ [a] -> [(a) * 2 : a >= 0; 0 : a < 0] }",
+	    "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
+		return -1;
+	if (test_parse_map_equal(ctx,
+	    "{ [a] -> [(a * 2) : a >= 0; 0 : a < 0] }",
+	    "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
+		return -1;
+	if (test_parse_map_equal(ctx,
+	    "{ [a] -> [(a * 2 : a >= 0); 0 : a < 0] }",
+	    "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
+		return -1;
+	if (test_parse_map_equal(ctx,
+	    "{ [a] -> [(a * 2 : a >= 0; 0 : a < 0)] }",
+	    "{ [a] -> [2a] : a >= 0; [a] -> [0] : a < 0 }") < 0)
+		return -1;
+
+	return 0;
+}
+
+void test_read(struct isl_ctx *ctx)
+{
+	char *filename;
+	FILE *input;
+	struct isl_basic_set *bset1, *bset2;
+	const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
+
+	filename = get_filename(ctx, "set", "omega");
+	assert(filename);
+	input = fopen(filename, "r");
+	assert(input);
+
+	bset1 = isl_basic_set_read_from_file(ctx, input);
+	bset2 = isl_basic_set_read_from_str(ctx, str);
+
+	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	free(filename);
+
+	fclose(input);
+}
+
+void test_bounded(struct isl_ctx *ctx)
+{
+	isl_set *set;
+	int bounded;
+
+	set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
+	bounded = isl_set_is_bounded(set);
+	assert(bounded);
+	isl_set_free(set);
+
+	set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
+	bounded = isl_set_is_bounded(set);
+	assert(!bounded);
+	isl_set_free(set);
+
+	set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
+	bounded = isl_set_is_bounded(set);
+	assert(!bounded);
+	isl_set_free(set);
+}
+
+/* Construct the basic set { [i] : 5 <= i <= N } */
+void test_construction(struct isl_ctx *ctx)
+{
+	isl_int v;
+	isl_space *dim;
+	isl_local_space *ls;
+	struct isl_basic_set *bset;
+	struct isl_constraint *c;
+
+	isl_int_init(v);
+
+	dim = isl_space_set_alloc(ctx, 1, 1);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_inequality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_param, 0, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_inequality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -5);
+	isl_constraint_set_constant(c, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	isl_int_clear(v);
+}
+
+void test_dim(struct isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map1, *map2;
+
+	map1 = isl_map_read_from_str(ctx,
+	    "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
+	map1 = isl_map_add_dims(map1, isl_dim_in, 1);
+	map2 = isl_map_read_from_str(ctx,
+	    "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
+	assert(isl_map_is_equal(map1, map2));
+	isl_map_free(map2);
+
+	map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
+	map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
+	assert(isl_map_is_equal(map1, map2));
+
+	isl_map_free(map1);
+	isl_map_free(map2);
+
+	str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
+	map1 = isl_map_read_from_str(ctx, str);
+	str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
+	map2 = isl_map_read_from_str(ctx, str);
+	map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
+	assert(isl_map_is_equal(map1, map2));
+
+	isl_map_free(map1);
+	isl_map_free(map2);
+}
+
+struct {
+	__isl_give isl_val *(*op)(__isl_take isl_val *v);
+	const char *arg;
+	const char *res;
+} val_un_tests[] = {
+	{ &isl_val_neg, "0", "0" },
+	{ &isl_val_abs, "0", "0" },
+	{ &isl_val_2exp, "0", "1" },
+	{ &isl_val_floor, "0", "0" },
+	{ &isl_val_ceil, "0", "0" },
+	{ &isl_val_neg, "1", "-1" },
+	{ &isl_val_neg, "-1", "1" },
+	{ &isl_val_neg, "1/2", "-1/2" },
+	{ &isl_val_neg, "-1/2", "1/2" },
+	{ &isl_val_neg, "infty", "-infty" },
+	{ &isl_val_neg, "-infty", "infty" },
+	{ &isl_val_neg, "NaN", "NaN" },
+	{ &isl_val_abs, "1", "1" },
+	{ &isl_val_abs, "-1", "1" },
+	{ &isl_val_abs, "1/2", "1/2" },
+	{ &isl_val_abs, "-1/2", "1/2" },
+	{ &isl_val_abs, "infty", "infty" },
+	{ &isl_val_abs, "-infty", "infty" },
+	{ &isl_val_abs, "NaN", "NaN" },
+	{ &isl_val_floor, "1", "1" },
+	{ &isl_val_floor, "-1", "-1" },
+	{ &isl_val_floor, "1/2", "0" },
+	{ &isl_val_floor, "-1/2", "-1" },
+	{ &isl_val_floor, "infty", "infty" },
+	{ &isl_val_floor, "-infty", "-infty" },
+	{ &isl_val_floor, "NaN", "NaN" },
+	{ &isl_val_ceil, "1", "1" },
+	{ &isl_val_ceil, "-1", "-1" },
+	{ &isl_val_ceil, "1/2", "1" },
+	{ &isl_val_ceil, "-1/2", "0" },
+	{ &isl_val_ceil, "infty", "infty" },
+	{ &isl_val_ceil, "-infty", "-infty" },
+	{ &isl_val_ceil, "NaN", "NaN" },
+	{ &isl_val_2exp, "-3", "1/8" },
+	{ &isl_val_2exp, "-1", "1/2" },
+	{ &isl_val_2exp, "1", "2" },
+	{ &isl_val_2exp, "2", "4" },
+	{ &isl_val_2exp, "3", "8" },
+	{ &isl_val_inv, "1", "1" },
+	{ &isl_val_inv, "2", "1/2" },
+	{ &isl_val_inv, "1/2", "2" },
+	{ &isl_val_inv, "-2", "-1/2" },
+	{ &isl_val_inv, "-1/2", "-2" },
+	{ &isl_val_inv, "0", "NaN" },
+	{ &isl_val_inv, "NaN", "NaN" },
+	{ &isl_val_inv, "infty", "0" },
+	{ &isl_val_inv, "-infty", "0" },
+};
+
+/* Perform some basic tests of unary operations on isl_val objects.
+ */
+static int test_un_val(isl_ctx *ctx)
+{
+	int i;
+	isl_val *v, *res;
+	__isl_give isl_val *(*fn)(__isl_take isl_val *v);
+	int ok;
+
+	for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
+		v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
+		res = isl_val_read_from_str(ctx, val_un_tests[i].res);
+		fn = val_un_tests[i].op;
+		v = fn(v);
+		if (isl_val_is_nan(res))
+			ok = isl_val_is_nan(v);
+		else
+			ok = isl_val_eq(v, res);
+		isl_val_free(v);
+		isl_val_free(res);
+		if (ok < 0)
+			return -1;
+		if (!ok)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return -1);
+	}
+
+	return 0;
+}
+
+struct {
+	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
+				__isl_take isl_val *v2);
+} val_bin_op[] = {
+	['+'] = { &isl_val_add },
+	['-'] = { &isl_val_sub },
+	['*'] = { &isl_val_mul },
+	['/'] = { &isl_val_div },
+	['g'] = { &isl_val_gcd },
+	['m'] = { &isl_val_min },
+	['M'] = { &isl_val_max },
+};
+
+struct {
+	const char *arg1;
+	unsigned char op;
+	const char *arg2;
+	const char *res;
+} val_bin_tests[] = {
+	{ "0", '+', "0", "0" },
+	{ "1", '+', "0", "1" },
+	{ "1", '+', "1", "2" },
+	{ "1", '-', "1", "0" },
+	{ "1", '*', "1", "1" },
+	{ "1", '/', "1", "1" },
+	{ "2", '*', "3", "6" },
+	{ "2", '*', "1/2", "1" },
+	{ "2", '*', "1/3", "2/3" },
+	{ "2/3", '*', "3/5", "2/5" },
+	{ "2/3", '*', "7/5", "14/15" },
+	{ "2", '/', "1/2", "4" },
+	{ "-2", '/', "-1/2", "4" },
+	{ "-2", '/', "1/2", "-4" },
+	{ "2", '/', "-1/2", "-4" },
+	{ "2", '/', "2", "1" },
+	{ "2", '/', "3", "2/3" },
+	{ "2/3", '/', "5/3", "2/5" },
+	{ "2/3", '/', "5/7", "14/15" },
+	{ "0", '/', "0", "NaN" },
+	{ "42", '/', "0", "NaN" },
+	{ "-42", '/', "0", "NaN" },
+	{ "infty", '/', "0", "NaN" },
+	{ "-infty", '/', "0", "NaN" },
+	{ "NaN", '/', "0", "NaN" },
+	{ "0", '/', "NaN", "NaN" },
+	{ "42", '/', "NaN", "NaN" },
+	{ "-42", '/', "NaN", "NaN" },
+	{ "infty", '/', "NaN", "NaN" },
+	{ "-infty", '/', "NaN", "NaN" },
+	{ "NaN", '/', "NaN", "NaN" },
+	{ "0", '/', "infty", "0" },
+	{ "42", '/', "infty", "0" },
+	{ "-42", '/', "infty", "0" },
+	{ "infty", '/', "infty", "NaN" },
+	{ "-infty", '/', "infty", "NaN" },
+	{ "NaN", '/', "infty", "NaN" },
+	{ "0", '/', "-infty", "0" },
+	{ "42", '/', "-infty", "0" },
+	{ "-42", '/', "-infty", "0" },
+	{ "infty", '/', "-infty", "NaN" },
+	{ "-infty", '/', "-infty", "NaN" },
+	{ "NaN", '/', "-infty", "NaN" },
+	{ "1", '-', "1/3", "2/3" },
+	{ "1/3", '+', "1/2", "5/6" },
+	{ "1/2", '+', "1/2", "1" },
+	{ "3/4", '-', "1/4", "1/2" },
+	{ "1/2", '-', "1/3", "1/6" },
+	{ "infty", '+', "42", "infty" },
+	{ "infty", '+', "infty", "infty" },
+	{ "42", '+', "infty", "infty" },
+	{ "infty", '-', "infty", "NaN" },
+	{ "infty", '*', "infty", "infty" },
+	{ "infty", '*', "-infty", "-infty" },
+	{ "-infty", '*', "infty", "-infty" },
+	{ "-infty", '*', "-infty", "infty" },
+	{ "0", '*', "infty", "NaN" },
+	{ "1", '*', "infty", "infty" },
+	{ "infty", '*', "0", "NaN" },
+	{ "infty", '*', "42", "infty" },
+	{ "42", '-', "infty", "-infty" },
+	{ "infty", '+', "-infty", "NaN" },
+	{ "4", 'g', "6", "2" },
+	{ "5", 'g', "6", "1" },
+	{ "42", 'm', "3", "3" },
+	{ "42", 'M', "3", "42" },
+	{ "3", 'm', "42", "3" },
+	{ "3", 'M', "42", "42" },
+	{ "42", 'm', "infty", "42" },
+	{ "42", 'M', "infty", "infty" },
+	{ "42", 'm', "-infty", "-infty" },
+	{ "42", 'M', "-infty", "42" },
+	{ "42", 'm', "NaN", "NaN" },
+	{ "42", 'M', "NaN", "NaN" },
+	{ "infty", 'm', "-infty", "-infty" },
+	{ "infty", 'M', "-infty", "infty" },
+};
+
+/* Perform some basic tests of binary operations on isl_val objects.
+ */
+static int test_bin_val(isl_ctx *ctx)
+{
+	int i;
+	isl_val *v1, *v2, *res;
+	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
+				__isl_take isl_val *v2);
+	int ok;
+
+	for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
+		v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
+		v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
+		res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
+		fn = val_bin_op[val_bin_tests[i].op].fn;
+		v1 = fn(v1, v2);
+		if (isl_val_is_nan(res))
+			ok = isl_val_is_nan(v1);
+		else
+			ok = isl_val_eq(v1, res);
+		isl_val_free(v1);
+		isl_val_free(res);
+		if (ok < 0)
+			return -1;
+		if (!ok)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return -1);
+	}
+
+	return 0;
+}
+
+/* Perform some basic tests on isl_val objects.
+ */
+static int test_val(isl_ctx *ctx)
+{
+	if (test_un_val(ctx) < 0)
+		return -1;
+	if (test_bin_val(ctx) < 0)
+		return -1;
+	return 0;
+}
+
+static int test_div(isl_ctx *ctx)
+{
+	unsigned n;
+	const char *str;
+	int empty;
+	isl_int v;
+	isl_space *dim;
+	isl_set *set;
+	isl_local_space *ls;
+	struct isl_basic_set *bset;
+	struct isl_constraint *c;
+
+	isl_int_init(v);
+
+	/* test 1 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+	assert(bset && bset->n_div == 1);
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 2 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+	assert(bset && bset->n_div == 1);
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 3 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -3);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 4);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+	assert(bset && bset->n_div == 1);
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 4 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 2);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_constant(c, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 6);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+	assert(isl_basic_set_is_empty(bset));
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 5 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
+
+	assert(bset && bset->n_div == 0);
+	isl_basic_set_free(bset);
+	isl_local_space_free(ls);
+
+	/* test 6 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 6);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
+
+	assert(bset && bset->n_div == 1);
+	isl_basic_set_free(bset);
+	isl_local_space_free(ls);
+
+	/* test 7 */
+	/* This test is a bit tricky.  We set up an equality
+	 *		a + 3b + 3c = 6 e0
+	 * Normalization of divs creates _two_ divs
+	 *		a = 3 e0
+	 *		c - b - e0 = 2 e1
+	 * Afterwards e0 is removed again because it has coefficient -1
+	 * and we end up with the original equality and div again.
+	 * Perhaps we can avoid the introduction of this temporary div.
+	 */
+	dim = isl_space_set_alloc(ctx, 0, 4);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	isl_int_set_si(v, -3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	isl_int_set_si(v, 6);
+	isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
+
+	/* Test disabled for now */
+	/*
+	assert(bset && bset->n_div == 1);
+	*/
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 8 */
+	dim = isl_space_set_alloc(ctx, 0, 5);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	isl_int_set_si(v, -3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
+	isl_int_set_si(v, 6);
+	isl_constraint_set_coefficient(c, isl_dim_set, 4, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	isl_int_set_si(v, 1);
+	isl_constraint_set_constant(c, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
+
+	/* Test disabled for now */
+	/*
+	assert(bset && bset->n_div == 1);
+	*/
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 9 */
+	dim = isl_space_set_alloc(ctx, 0, 4);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+	isl_int_set_si(v, -2);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, -1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, 3);
+	isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
+	isl_int_set_si(v, 2);
+	isl_constraint_set_constant(c, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
+
+	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
+
+	assert(!isl_basic_set_is_empty(bset));
+
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	/* test 10 */
+	dim = isl_space_set_alloc(ctx, 0, 3);
+	bset = isl_basic_set_universe(isl_space_copy(dim));
+	ls = isl_local_space_from_space(dim);
+
+	c = isl_equality_alloc(isl_local_space_copy(ls));
+	isl_int_set_si(v, 1);
+	isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+	isl_int_set_si(v, -2);
+	isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+	bset = isl_basic_set_add_constraint(bset, c);
+
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
+
+	bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
+
+	isl_local_space_free(ls);
+	isl_basic_set_free(bset);
+
+	isl_int_clear(v);
+
+	str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
+	    "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
+	set = isl_set_read_from_str(ctx, str);
+	set = isl_set_compute_divs(set);
+	isl_set_free(set);
+	if (!set)
+		return -1;
+
+	str = "{ [i,j] : 2*[i/2] + 3 * [j/4] <= 10 and 2 i = j }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	n = isl_basic_set_dim(bset, isl_dim_div);
+	isl_basic_set_free(bset);
+	if (!bset)
+		return -1;
+	if (n != 0)
+		isl_die(ctx, isl_error_unknown,
+			"expecting no existentials", return -1);
+
+	str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
+	set = isl_set_read_from_str(ctx, str);
+	set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
+	set = isl_set_fix_si(set, isl_dim_set, 2, -3);
+	empty = isl_set_is_empty(set);
+	isl_set_free(set);
+	if (empty < 0)
+		return -1;
+	if (!empty)
+		isl_die(ctx, isl_error_unknown,
+			"result not as accurate as expected", return -1);
+
+	return 0;
+}
+
+void test_application_case(struct isl_ctx *ctx, const char *name)
+{
+	char *filename;
+	FILE *input;
+	struct isl_basic_set *bset1, *bset2;
+	struct isl_basic_map *bmap;
+
+	filename = get_filename(ctx, name, "omega");
+	assert(filename);
+	input = fopen(filename, "r");
+	assert(input);
+
+	bset1 = isl_basic_set_read_from_file(ctx, input);
+	bmap = isl_basic_map_read_from_file(ctx, input);
+
+	bset1 = isl_basic_set_apply(bset1, bmap);
+
+	bset2 = isl_basic_set_read_from_file(ctx, input);
+
+	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	free(filename);
+
+	fclose(input);
+}
+
+void test_application(struct isl_ctx *ctx)
+{
+	test_application_case(ctx, "application");
+	test_application_case(ctx, "application2");
+}
+
+void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
+{
+	char *filename;
+	FILE *input;
+	struct isl_basic_set *bset1, *bset2;
+
+	filename = get_filename(ctx, name, "polylib");
+	assert(filename);
+	input = fopen(filename, "r");
+	assert(input);
+
+	bset1 = isl_basic_set_read_from_file(ctx, input);
+	bset2 = isl_basic_set_read_from_file(ctx, input);
+
+	bset1 = isl_basic_set_affine_hull(bset1);
+
+	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	free(filename);
+
+	fclose(input);
+}
+
+int test_affine_hull(struct isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_basic_set *bset, *bset2;
+	int n;
+	int subset;
+
+	test_affine_hull_case(ctx, "affine2");
+	test_affine_hull_case(ctx, "affine");
+	test_affine_hull_case(ctx, "affine3");
+
+	str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
+			"m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
+			"e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
+			"2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
+	set = isl_set_read_from_str(ctx, str);
+	bset = isl_set_affine_hull(set);
+	n = isl_basic_set_dim(bset, isl_dim_div);
+	isl_basic_set_free(bset);
+	if (n != 0)
+		isl_die(ctx, isl_error_unknown, "not expecting any divs",
+			return -1);
+
+	/* Check that isl_map_affine_hull is not confused by
+	 * the reordering of divs in isl_map_align_divs.
+	 */
+	str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
+				"32e0 = b and 32e1 = c); "
+		"[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
+	set = isl_set_read_from_str(ctx, str);
+	bset = isl_set_affine_hull(set);
+	isl_basic_set_free(bset);
+	if (!bset)
+		return -1;
+
+	str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
+			"32e2 = 31 + 31e0 }";
+	set = isl_set_read_from_str(ctx, str);
+	bset = isl_set_affine_hull(set);
+	str = "{ [a] : exists e : a = 32 e }";
+	bset2 = isl_basic_set_read_from_str(ctx, str);
+	subset = isl_basic_set_is_subset(bset, bset2);
+	isl_basic_set_free(bset);
+	isl_basic_set_free(bset2);
+	if (subset < 0)
+		return -1;
+	if (!subset)
+		isl_die(ctx, isl_error_unknown, "not as accurate as expected",
+			return -1);
+
+	return 0;
+}
+
+void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
+{
+	char *filename;
+	FILE *input;
+	struct isl_basic_set *bset1, *bset2;
+	struct isl_set *set;
+
+	filename = get_filename(ctx, name, "polylib");
+	assert(filename);
+	input = fopen(filename, "r");
+	assert(input);
+
+	bset1 = isl_basic_set_read_from_file(ctx, input);
+	bset2 = isl_basic_set_read_from_file(ctx, input);
+
+	set = isl_basic_set_union(bset1, bset2);
+	bset1 = isl_set_convex_hull(set);
+
+	bset2 = isl_basic_set_read_from_file(ctx, input);
+
+	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	free(filename);
+
+	fclose(input);
+}
+
+struct {
+	const char *set;
+	const char *hull;
+} convex_hull_tests[] = {
+	{ "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
+	       "(i0 = 1 and i1 = 0 and i2 = 1) or "
+	       "(i0 = 0 and i1 = 0 and i2 = 0) }",
+	  "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
+	{ "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
+	    "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
+	    "i2 <= 5 and i2 >= 4; "
+	    "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
+	  "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
+	    "i2 <= 5 + i0 and i2 >= i0 }" },
+	{ "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
+	    "{ [x, y] : 1 = 0 }" },
+};
+
+void test_convex_hull_algo(struct isl_ctx *ctx, int convex)
+{
+	int i;
+	int orig_convex = ctx->opt->convex;
+	ctx->opt->convex = convex;
+
+	test_convex_hull_case(ctx, "convex0");
+	test_convex_hull_case(ctx, "convex1");
+	test_convex_hull_case(ctx, "convex2");
+	test_convex_hull_case(ctx, "convex3");
+	test_convex_hull_case(ctx, "convex4");
+	test_convex_hull_case(ctx, "convex5");
+	test_convex_hull_case(ctx, "convex6");
+	test_convex_hull_case(ctx, "convex7");
+	test_convex_hull_case(ctx, "convex8");
+	test_convex_hull_case(ctx, "convex9");
+	test_convex_hull_case(ctx, "convex10");
+	test_convex_hull_case(ctx, "convex11");
+	test_convex_hull_case(ctx, "convex12");
+	test_convex_hull_case(ctx, "convex13");
+	test_convex_hull_case(ctx, "convex14");
+	test_convex_hull_case(ctx, "convex15");
+
+	for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
+		isl_set *set1, *set2;
+
+		set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
+		set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
+		set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
+		assert(isl_set_is_equal(set1, set2));
+		isl_set_free(set1);
+		isl_set_free(set2);
+	}
+
+	ctx->opt->convex = orig_convex;
+}
+
+void test_convex_hull(struct isl_ctx *ctx)
+{
+	test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM);
+	test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP);
+}
+
+void test_gist_case(struct isl_ctx *ctx, const char *name)
+{
+	char *filename;
+	FILE *input;
+	struct isl_basic_set *bset1, *bset2;
+
+	filename = get_filename(ctx, name, "polylib");
+	assert(filename);
+	input = fopen(filename, "r");
+	assert(input);
+
+	bset1 = isl_basic_set_read_from_file(ctx, input);
+	bset2 = isl_basic_set_read_from_file(ctx, input);
+
+	bset1 = isl_basic_set_gist(bset1, bset2);
+
+	bset2 = isl_basic_set_read_from_file(ctx, input);
+
+	assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	free(filename);
+
+	fclose(input);
+}
+
+struct {
+	const char *set;
+	const char *context;
+	const char *gist;
+} gist_tests[] = {
+	{ "{ [a, b, c] : a <= 15 and a >= 1 }",
+	  "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
+			"c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
+	  "{ [a, b, c] : a <= 15 }" },
+	{ "{ : }", "{ : 1 = 0 }", "{ : }" },
+	{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
+	{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
+	  "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
+};
+
+static int test_gist(struct isl_ctx *ctx)
+{
+	int i;
+	const char *str;
+	isl_basic_set *bset1, *bset2;
+	isl_map *map1, *map2;
+	int equal;
+
+	for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
+		int equal_input;
+		isl_basic_set *copy;
+
+		bset1 = isl_basic_set_read_from_str(ctx, gist_tests[i].set);
+		bset2 = isl_basic_set_read_from_str(ctx, gist_tests[i].context);
+		copy = isl_basic_set_copy(bset1);
+		bset1 = isl_basic_set_gist(bset1, bset2);
+		bset2 = isl_basic_set_read_from_str(ctx, gist_tests[i].gist);
+		equal = isl_basic_set_is_equal(bset1, bset2);
+		isl_basic_set_free(bset1);
+		isl_basic_set_free(bset2);
+		bset1 = isl_basic_set_read_from_str(ctx, gist_tests[i].set);
+		equal_input = isl_basic_set_is_equal(bset1, copy);
+		isl_basic_set_free(bset1);
+		isl_basic_set_free(copy);
+		if (equal < 0 || equal_input < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"incorrect gist result", return -1);
+		if (!equal_input)
+			isl_die(ctx, isl_error_unknown,
+				"gist modified input", return -1);
+	}
+
+	test_gist_case(ctx, "gist1");
+
+	str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
+	    "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
+	    "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
+	    "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
+	    "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
+	    "16e0 >= 16 + 16p6 + 15p10 and  p2 <= 15 and p3 >= 0 and "
+	    "p3 <= 31 and  p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
+	    "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
+	    "p10 <= 15 and p10 <= -1 + p0 - p6) }";
+	bset1 = isl_basic_set_read_from_str(ctx, str);
+	str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
+	    "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
+	    "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
+	    "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
+	    "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
+	    "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
+	    "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
+	    "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
+	bset2 = isl_basic_set_read_from_str(ctx, str);
+	bset1 = isl_basic_set_gist(bset1, bset2);
+	assert(bset1 && bset1->n_div == 0);
+	isl_basic_set_free(bset1);
+
+	/* Check that the integer divisions of the second disjunct
+	 * do not spread to the first disjunct.
+	 */
+	str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
+		"16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
+		"(exists (e0 = [(-1 + t1)/16], "
+			"e1 = [(-16 + t1 - 16e0)/4294967296]: "
+			"4294967296e1 = -16 + t1 - o0 - 16e0 and "
+			"16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
+			"o0 <= 4294967295 and t1 <= -1)) }";
+	map1 = isl_map_read_from_str(ctx, str);
+	str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
+	map2 = isl_map_read_from_str(ctx, str);
+	map1 = isl_map_gist(map1, map2);
+	if (!map1)
+		return -1;
+	if (map1->n != 1)
+		isl_die(ctx, isl_error_unknown, "expecting single disjunct",
+			isl_map_free(map1); return -1);
+	if (isl_basic_map_dim(map1->p[0], isl_dim_div) != 1)
+		isl_die(ctx, isl_error_unknown, "expecting single div",
+			isl_map_free(map1); return -1);
+	isl_map_free(map1);
+
+	return 0;
+}
+
+int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
+{
+	isl_set *set, *set2;
+	int equal;
+	int one;
+
+	set = isl_set_read_from_str(ctx, str);
+	set = isl_set_coalesce(set);
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set, set2);
+	one = set && set->n == 1;
+	isl_set_free(set);
+	isl_set_free(set2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"coalesced set not equal to input", return -1);
+	if (check_one && !one)
+		isl_die(ctx, isl_error_unknown,
+			"coalesced set should not be a union", return -1);
+
+	return 0;
+}
+
+int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
+{
+	int r = 0;
+	int bounded;
+
+	bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
+	isl_options_set_coalesce_bounded_wrapping(ctx, 0);
+
+	if (test_coalesce_set(ctx,
+		"{[x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
+			"-x - y + 1 >= 0 and -3 <= z <= 3;"
+		"[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
+			"x-z + 20 >= 0 and x+z + 20 >= 0 and "
+			"-10 <= y <= 0}", 1) < 0)
+		goto error;
+	if (test_coalesce_set(ctx,
+		"{[x,y] : 0 <= x,y <= 10; [5,y]: 4 <=y <= 11}", 1) < 0)
+		goto error;
+	if (test_coalesce_set(ctx,
+		"{[x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }", 1) < 0)
+		goto error;
+
+	if (0) {
+error:
+		r = -1;
+	}
+
+	isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
+
+	return r;
+}
+
+/* Inputs for coalescing tests.
+ * "str" is a string representation of the input set.
+ * "single_disjunct" is set if we expect the result to consist of
+ *	a single disjunct.
+ */
+struct {
+	int single_disjunct;
+	const char *str;
+} coalesce_tests[] = {
+	{ 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
+		       "y >= x & x >= 2 & 5 >= y }" },
+	{ 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
+		       "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
+	{ 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
+		       "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
+	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
+		       "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
+	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
+		       "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
+	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
+		       "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
+	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
+	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
+	{ 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
+	{ 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
+	{ 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
+	{ 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
+	{ 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
+	{ 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
+		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
+		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
+		"4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
+		"o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
+		"i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
+		"4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
+		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
+		"[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
+		"e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
+		"e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
+		"4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
+		"2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
+		"2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
+		"i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
+		"4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
+		"o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
+		"4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
+	{ 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
+	      "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
+	      "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
+	      "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
+	{ 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
+	  "[o0, o1, o2, o3, o4, o5, o6]] : "
+	  "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
+	  "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
+	  "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
+	  "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
+	  "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
+	  "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
+	  "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
+	  "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
+	  "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
+	  "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
+	  "o6 >= i3 + i6 - o3 and M >= 0 and "
+	  "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
+	  "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
+	{ 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
+		"(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
+		"(o0 = 0 and M >= 2 and N >= 3) or "
+		"(M = 0 and o0 = 0 and N >= 3) }" },
+	{ 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
+	    "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
+	    "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
+	    "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
+	{ 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
+	{ 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
+	{ 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
+		"(y = 3 and x = 1) }" },
+	{ 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
+		"i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
+		"i1 <= M and i3 <= M and i4 <= M) or "
+		"(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
+		"i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
+		"i4 <= -1 + M) }" },
+	{ 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
+		"(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
+	{ 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
+	{ 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
+	{ 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
+	{ 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
+	{ 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
+	{ 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
+	{ 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
+	{ 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
+	{ 0, "{ [a, b] : exists e : 2e = a and "
+		    "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
+	{ 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
+			"j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
+			"j >= 1 and j' <= i + j - i' and i >= 1; "
+		"[1, 1, 1, 1] }" },
+	{ 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
+		 "[i,j] : exists a : j = 3a }" },
+	{ 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
+			"c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
+			"a >= 3) or "
+		    "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
+			"b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
+	{ 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
+				"c <= 6 + 8a and a >= 3; "
+		"[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
+				"c <= 7 + 8a and a >= 3 and a <= 4 }" },
+	{ 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
+		"[x,0] : 3 <= x <= 4 }" },
+	{ 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
+		"[x,0] : 4 <= x <= 5 }" },
+	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
+		"[x,0] : 3 <= x <= 5 }" },
+	{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
+		"[x,0] : 3 <= x <= 4 }" },
+	{ 1 , "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
+			"i1 <= 0; "
+		"[i0, 0] : i0 >= 123 and i0 <= 124 }" },
+};
+
+/* Test the functionality of isl_set_coalesce.
+ * That is, check that the output is always equal to the input
+ * and in some cases that the result consists of a single disjunct.
+ */
+static int test_coalesce(struct isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
+		const char *str = coalesce_tests[i].str;
+		int check_one = coalesce_tests[i].single_disjunct;
+		if (test_coalesce_set(ctx, str, check_one) < 0)
+			return -1;
+	}
+
+	if (test_coalesce_unbounded_wrapping(ctx) < 0)
+		return -1;
+
+	return 0;
+}
+
+void test_closure(struct isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *dom;
+	isl_map *up, *right;
+	isl_map *map, *map2;
+	int exact;
+
+	/* COCOA example 1 */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
+			"1 <= i and i < n and 1 <= j and j < n or "
+			"i2 = i + 1 and j2 = j - 1 and "
+			"1 <= i and i < n and 2 <= j and j <= n }");
+	map = isl_map_power(map, &exact);
+	assert(exact);
+	isl_map_free(map);
+
+	/* COCOA example 1 */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
+			"1 <= i and i < n and 1 <= j and j < n or "
+			"i2 = i + 1 and j2 = j - 1 and "
+			"1 <= i and i < n and 2 <= j and j <= n }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
+			"1 <= i and i < n and 1 <= j and j <= n and "
+			"2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
+			"i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
+			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map2);
+	isl_map_free(map);
+
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
+				     " 0 <= y and y <= n }");
+	map = isl_map_transitive_closure(map, &exact);
+	map2 = isl_map_read_from_str(ctx,
+		"[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
+				     " 0 <= y and y <= n }");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map2);
+	isl_map_free(map);
+
+	/* COCOA example 2 */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
+			"1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
+			"i2 = i + 2 and j2 = j - 2 and "
+			"1 <= i and i < n - 1 and 3 <= j and j <= n }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
+			"1 <= i and i < n - 1 and 1 <= j and j <= n and "
+			"3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
+			"i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
+			"k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	/* COCOA Fig.2 left */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
+			"i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
+			"j <= n or "
+			"i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
+			"j <= 2 i - 3 and j <= n - 2 or "
+			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
+			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	isl_map_free(map);
+
+	/* COCOA Fig.2 right */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
+			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
+			"j <= n or "
+			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
+			"j <= 2 i - 4 and j <= n - 3 or "
+			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
+			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
+	map = isl_map_power(map, &exact);
+	assert(exact);
+	isl_map_free(map);
+
+	/* COCOA Fig.2 right */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
+			"i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
+			"j <= n or "
+			"i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
+			"j <= 2 i - 4 and j <= n - 3 or "
+			"i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
+			"i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
+			"i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
+			"j <= n and 3 + i + 2 j <= 3 n and "
+			"3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
+			"i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
+			"13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
+			"j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
+			"k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map2);
+	isl_map_free(map);
+
+	/* COCOA Fig.1 right */
+	dom = isl_set_read_from_str(ctx,
+		"{ [x,y] : x >= 0 and -2 x + 3 y >= 0 and x <= 3 and "
+			"2 x - 3 y + 3 >= 0 }");
+	right = isl_map_read_from_str(ctx,
+		"{ [x,y] -> [x2,y2] : x2 = x + 1 and y2 = y }");
+	up = isl_map_read_from_str(ctx,
+		"{ [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 }");
+	right = isl_map_intersect_domain(right, isl_set_copy(dom));
+	right = isl_map_intersect_range(right, isl_set_copy(dom));
+	up = isl_map_intersect_domain(up, isl_set_copy(dom));
+	up = isl_map_intersect_range(up, dom);
+	map = isl_map_union(up, right);
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx,
+		"{ [0,0] -> [0,1]; [0,0] -> [1,1]; [0,1] -> [1,1]; "
+		"  [2,2] -> [3,2]; [2,2] -> [3,3]; [3,2] -> [3,3] }");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map2);
+	isl_map_free(map);
+
+	/* COCOA Theorem 1 counter example */
+	map = isl_map_read_from_str(ctx,
+		"{ [i,j] -> [i2,j2] : i = 0 and 0 <= j and j <= 1 and "
+			"i2 = 1 and j2 = j or "
+			"i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	isl_map_free(map);
+
+	map = isl_map_read_from_str(ctx,
+		"[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
+			"1 <= i,i2 <= n and 1 <= j,j2 <= m or "
+			"i2 = i + 1 and 3 <= j2 - j <= 4 and "
+			"1 <= i,i2 <= n and 1 <= j,j2 <= m }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	isl_map_free(map);
+
+	/* Kelly et al 1996, fig 12 */
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
+			"1 <= i,j,j+1 <= n or "
+			"j = n and j2 = 1 and i2 = i + 1 and "
+			"1 <= i,i+1 <= n }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx,
+		"[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
+			"1 <= i <= n and i = i2 or "
+			"1 <= i < i2 <= n and 1 <= j <= n and "
+			"1 <= j2 <= n }");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map2);
+	isl_map_free(map);
+
+	/* Omega's closure4 */
+	map = isl_map_read_from_str(ctx,
+		"[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
+			"1 <= x,y <= 10 or "
+			"x2 = x + 1 and y2 = y and "
+			"1 <= x <= 20 && 5 <= y <= 15 }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	isl_map_free(map);
+
+	map = isl_map_read_from_str(ctx,
+		"[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
+	map = isl_map_transitive_closure(map, &exact);
+	assert(!exact);
+	map2 = isl_map_read_from_str(ctx,
+		"[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
+	    "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
+	    "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
+	    "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "{[0] -> [1]; [2] -> [3]}";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_transitive_closure(map, &exact);
+	assert(exact);
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
+	    "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
+	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
+	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
+	    "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
+	    "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
+	    "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
+	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
+	    "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
+	    "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
+	    "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
+	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
+	    "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
+	    "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
+	    "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
+	    "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+	    "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_transitive_closure(map, NULL);
+	assert(map);
+	isl_map_free(map);
+}
+
+void test_lex(struct isl_ctx *ctx)
+{
+	isl_space *dim;
+	isl_map *map;
+
+	dim = isl_space_set_alloc(ctx, 0, 0);
+	map = isl_map_lex_le(dim);
+	assert(!isl_map_is_empty(map));
+	isl_map_free(map);
+}
+
+static int test_lexmin(struct isl_ctx *ctx)
+{
+	int equal;
+	const char *str;
+	isl_basic_map *bmap;
+	isl_map *map, *map2;
+	isl_set *set;
+	isl_set *set2;
+	isl_pw_multi_aff *pma;
+
+	str = "[p0, p1] -> { [] -> [] : "
+	    "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
+	    "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
+	    "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
+	    "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
+	    "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
+	    "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
+	    "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
+	    "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
+	    "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
+	    "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
+	    "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_lexmin(map);
+	isl_map_free(map);
+
+	str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
+	    "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
+	set = isl_set_read_from_str(ctx, str);
+	set = isl_set_lexmax(set);
+	str = "[C] -> { [obj,a,b,c] : C = 8 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	set = isl_set_intersect(set, set2);
+	assert(!isl_set_is_empty(set));
+	isl_set_free(set);
+
+	str = "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_lexmin(map);
+	str = "{ [x] -> [5] : 6 <= x <= 8; "
+		"[x] -> [x] : x <= 5 or (9 <= x <= 10) }";
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }";
+	map = isl_map_read_from_str(ctx, str);
+	map2 = isl_map_copy(map);
+	map = isl_map_lexmin(map);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_lexmin(map);
+	str = "{ [x] -> [y] : (4y = x and x >= 0) or "
+		"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
+		"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
+		"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }";
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
+				" 8i' <= i and 8i' >= -7 + i }";
+	bmap = isl_basic_map_read_from_str(ctx, str);
+	pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
+	map2 = isl_map_from_pw_multi_aff(pma);
+	map = isl_map_from_basic_map(bmap);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_lexmin(map);
+	str = "{ T[a] -> S[b, c] : 2b = a and 2c = a }";
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	/* Check that empty pieces are properly combined. */
+	str = "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
+		"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
+		"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_lexmin(map);
+	str = "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
+		"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
+		"x >= 4 }";
+	map2 = isl_map_read_from_str(ctx, str);
+	assert(isl_map_is_equal(map, map2));
+	isl_map_free(map);
+	isl_map_free(map2);
+
+	str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
+				" 8i' <= i and 8i' >= -7 + i }";
+	set = isl_set_read_from_str(ctx, str);
+	pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
+	set2 = isl_set_from_pw_multi_aff(pma);
+	equal = isl_set_is_equal(set, set2);
+	isl_set_free(set);
+	isl_set_free(set2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected difference between set and "
+			"piecewise affine expression", return -1);
+
+	return 0;
+}
+
+/* Check that isl_set_min_val and isl_set_max_val compute the correct
+ * result on non-convex inputs.
+ */
+static int test_min(struct isl_ctx *ctx)
+{
+	isl_set *set;
+	isl_aff *aff;
+	isl_val *val;
+	int min_ok, max_ok;
+
+	set = isl_set_read_from_str(ctx, "{ [-1]; [1] }");
+	aff = isl_aff_read_from_str(ctx, "{ [x] -> [x] }");
+	val = isl_set_min_val(set, aff);
+	min_ok = isl_val_is_negone(val);
+	isl_val_free(val);
+	val = isl_set_max_val(set, aff);
+	max_ok = isl_val_is_one(val);
+	isl_val_free(val);
+	isl_aff_free(aff);
+	isl_set_free(set);
+
+	if (min_ok < 0 || max_ok < 0)
+		return -1;
+	if (!min_ok)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected minimum", return -1);
+	if (!max_ok)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected maximum", return -1);
+
+	return 0;
+}
+
+struct must_may {
+	isl_map *must;
+	isl_map *may;
+};
+
+static int collect_must_may(__isl_take isl_map *dep, int must,
+	void *dep_user, void *user)
+{
+	struct must_may *mm = (struct must_may *)user;
+
+	if (must)
+		mm->must = isl_map_union(mm->must, dep);
+	else
+		mm->may = isl_map_union(mm->may, dep);
+
+	return 0;
+}
+
+static int common_space(void *first, void *second)
+{
+	int depth = *(int *)first;
+	return 2 * depth;
+}
+
+static int map_is_equal(__isl_keep isl_map *map, const char *str)
+{
+	isl_map *map2;
+	int equal;
+
+	if (!map)
+		return -1;
+
+	map2 = isl_map_read_from_str(map->ctx, str);
+	equal = isl_map_is_equal(map, map2);
+	isl_map_free(map2);
+
+	return equal;
+}
+
+static int map_check_equal(__isl_keep isl_map *map, const char *str)
+{
+	int equal;
+
+	equal = map_is_equal(map, str);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(isl_map_get_ctx(map), isl_error_unknown,
+			"result not as expected", return -1);
+	return 0;
+}
+
+void test_dep(struct isl_ctx *ctx)
+{
+	const char *str;
+	isl_space *dim;
+	isl_map *map;
+	isl_access_info *ai;
+	isl_flow *flow;
+	int depth;
+	struct must_may mm;
+
+	depth = 3;
+
+	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+	flow = isl_access_info_compute_flow(ai);
+	dim = isl_space_alloc(ctx, 0, 3, 3);
+	mm.must = isl_map_empty(isl_space_copy(dim));
+	mm.may = isl_map_empty(dim);
+
+	isl_flow_foreach(flow, collect_must_may, &mm);
+
+	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
+	      "  [1,10,0] -> [2,5,0] }";
+	assert(map_is_equal(mm.must, str));
+	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+	assert(map_is_equal(mm.may, str));
+
+	isl_map_free(mm.must);
+	isl_map_free(mm.may);
+	isl_flow_free(flow);
+
+
+	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	flow = isl_access_info_compute_flow(ai);
+	dim = isl_space_alloc(ctx, 0, 3, 3);
+	mm.must = isl_map_empty(isl_space_copy(dim));
+	mm.may = isl_map_empty(dim);
+
+	isl_flow_foreach(flow, collect_must_may, &mm);
+
+	str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
+	assert(map_is_equal(mm.must, str));
+	str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
+	assert(map_is_equal(mm.may, str));
+
+	isl_map_free(mm.must);
+	isl_map_free(mm.may);
+	isl_flow_free(flow);
+
+
+	str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	flow = isl_access_info_compute_flow(ai);
+	dim = isl_space_alloc(ctx, 0, 3, 3);
+	mm.must = isl_map_empty(isl_space_copy(dim));
+	mm.may = isl_map_empty(dim);
+
+	isl_flow_foreach(flow, collect_must_may, &mm);
+
+	str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
+	      "  [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
+	assert(map_is_equal(mm.may, str));
+	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+	assert(map_is_equal(mm.must, str));
+
+	isl_map_free(mm.must);
+	isl_map_free(mm.may);
+	isl_flow_free(flow);
+
+
+	str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	flow = isl_access_info_compute_flow(ai);
+	dim = isl_space_alloc(ctx, 0, 3, 3);
+	mm.must = isl_map_empty(isl_space_copy(dim));
+	mm.may = isl_map_empty(dim);
+
+	isl_flow_foreach(flow, collect_must_may, &mm);
+
+	str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
+	      "  [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
+	assert(map_is_equal(mm.may, str));
+	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+	assert(map_is_equal(mm.must, str));
+
+	isl_map_free(mm.must);
+	isl_map_free(mm.may);
+	isl_flow_free(flow);
+
+
+	str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+	str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+	flow = isl_access_info_compute_flow(ai);
+	dim = isl_space_alloc(ctx, 0, 3, 3);
+	mm.must = isl_map_empty(isl_space_copy(dim));
+	mm.may = isl_map_empty(dim);
+
+	isl_flow_foreach(flow, collect_must_may, &mm);
+
+	str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
+	      "  [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
+	assert(map_is_equal(mm.may, str));
+	str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+	assert(map_is_equal(mm.must, str));
+
+	isl_map_free(mm.must);
+	isl_map_free(mm.may);
+	isl_flow_free(flow);
+
+
+	depth = 5;
+
+	str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_alloc(map, &depth, &common_space, 1);
+
+	str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
+	map = isl_map_read_from_str(ctx, str);
+	ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+	flow = isl_access_info_compute_flow(ai);
+	dim = isl_space_alloc(ctx, 0, 5, 5);
+	mm.must = isl_map_empty(isl_space_copy(dim));
+	mm.may = isl_map_empty(dim);
+
+	isl_flow_foreach(flow, collect_must_may, &mm);
+
+	str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
+	assert(map_is_equal(mm.must, str));
+	str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
+	assert(map_is_equal(mm.may, str));
+
+	isl_map_free(mm.must);
+	isl_map_free(mm.may);
+	isl_flow_free(flow);
+}
+
+/* Check that the dependence analysis proceeds without errors.
+ * Earlier versions of isl would break down during the analysis
+ * due to the use of the wrong spaces.
+ */
+static int test_flow(isl_ctx *ctx)
+{
+	const char *str;
+	isl_union_map *access, *schedule;
+	isl_union_map *must_dep, *may_dep;
+	int r;
+
+	str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
+	access = isl_union_map_read_from_str(ctx, str);
+	str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
+		"S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
+		"S2[] -> [1,0,0,0]; "
+		"S3[] -> [-1,0,0,0] }";
+	schedule = isl_union_map_read_from_str(ctx, str);
+	r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
+					isl_union_map_copy(access), schedule,
+					&must_dep, &may_dep, NULL, NULL);
+	isl_union_map_free(may_dep);
+	isl_union_map_free(must_dep);
+
+	return r;
+}
+
+struct {
+	const char *map;
+	int sv;
+} sv_tests[] = {
+	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
+	{ "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
+	{ "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
+	{ "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
+	{ "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
+	{ "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
+	{ "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
+	{ "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
+	{ "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
+};
+
+int test_sv(isl_ctx *ctx)
+{
+	isl_union_map *umap;
+	int i;
+	int sv;
+
+	for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
+		umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
+		sv = isl_union_map_is_single_valued(umap);
+		isl_union_map_free(umap);
+		if (sv < 0)
+			return -1;
+		if (sv_tests[i].sv && !sv)
+			isl_die(ctx, isl_error_internal,
+				"map not detected as single valued", return -1);
+		if (!sv_tests[i].sv && sv)
+			isl_die(ctx, isl_error_internal,
+				"map detected as single valued", return -1);
+	}
+
+	return 0;
+}
+
+void test_bijective_case(struct isl_ctx *ctx, const char *str, int bijective)
+{
+	isl_map *map;
+
+	map = isl_map_read_from_str(ctx, str);
+	if (bijective)
+		assert(isl_map_is_bijective(map));
+	else
+		assert(!isl_map_is_bijective(map));
+	isl_map_free(map);
+}
+
+void test_bijective(struct isl_ctx *ctx)
+{
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i]}", 0);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=i}", 1);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=0}", 1);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=N}", 1);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [j,i]}", 1);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i+j]}", 0);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> []}", 0);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i,j,N]}", 1);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i]}", 0);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [i,i]}", 0);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i,i]}", 0);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i,j]}", 1);
+	test_bijective_case(ctx, "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1);
+}
+
+/* Inputs for isl_pw_qpolynomial_gist tests.
+ * "pwqp" is the input, "set" is the context and "gist" is the expected result.
+ */
+struct {
+	const char *pwqp;
+	const char *set;
+	const char *gist;
+} pwqp_gist_tests[] = {
+	{ "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
+	{ "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
+	{ "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
+	  "{ [i] -> -1/2 + 1/2 * i }" },
+	{ "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
+};
+
+static int test_pwqp(struct isl_ctx *ctx)
+{
+	int i;
+	const char *str;
+	isl_set *set;
+	isl_pw_qpolynomial *pwqp1, *pwqp2;
+	int equal;
+
+	str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
+						isl_dim_in, 1, 1);
+
+	str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+	assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+	isl_pw_qpolynomial_free(pwqp1);
+
+	for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
+		str = pwqp_gist_tests[i].pwqp;
+		pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+		str = pwqp_gist_tests[i].set;
+		set = isl_set_read_from_str(ctx, str);
+		pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
+		str = pwqp_gist_tests[i].gist;
+		pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+		pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+		equal = isl_pw_qpolynomial_is_zero(pwqp1);
+		isl_pw_qpolynomial_free(pwqp1);
+
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return -1);
+	}
+
+	str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	str = "{ [i] -> ([(2 * [i/2])/5]) }";
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+	assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+	isl_pw_qpolynomial_free(pwqp1);
+
+	str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	str = "{ [x] -> x }";
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+	assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+	isl_pw_qpolynomial_free(pwqp1);
+
+	str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
+	pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+	assert(isl_pw_qpolynomial_is_zero(pwqp1));
+	isl_pw_qpolynomial_free(pwqp1);
+
+	str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
+	pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
+	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
+	isl_pw_qpolynomial_free(pwqp1);
+	isl_pw_qpolynomial_free(pwqp2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
+	pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
+	pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+	pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
+						isl_val_one(ctx));
+	equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
+	isl_pw_qpolynomial_free(pwqp1);
+	isl_pw_qpolynomial_free(pwqp2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	return 0;
+}
+
+void test_split_periods(isl_ctx *ctx)
+{
+	const char *str;
+	isl_pw_qpolynomial *pwqp;
+
+	str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
+		"U + 2V + 3 >= 0 and - U -2V  >= 0 and - U + 10 >= 0 and "
+		"U  >= 0; [U,V] -> U^2 : U >= 100 }";
+	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+	pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
+	assert(pwqp);
+
+	isl_pw_qpolynomial_free(pwqp);
+}
+
+void test_union(isl_ctx *ctx)
+{
+	const char *str;
+	isl_union_set *uset1, *uset2;
+	isl_union_map *umap1, *umap2;
+
+	str = "{ [i] : 0 <= i <= 1 }";
+	uset1 = isl_union_set_read_from_str(ctx, str);
+	str = "{ [1] -> [0] }";
+	umap1 = isl_union_map_read_from_str(ctx, str);
+
+	umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
+	assert(isl_union_map_is_equal(umap1, umap2));
+
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+
+	str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
+	umap1 = isl_union_map_read_from_str(ctx, str);
+	str = "{ A[i]; B[i] }";
+	uset1 = isl_union_set_read_from_str(ctx, str);
+
+	uset2 = isl_union_map_domain(umap1);
+
+	assert(isl_union_set_is_equal(uset1, uset2));
+
+	isl_union_set_free(uset1);
+	isl_union_set_free(uset2);
+}
+
+void test_bound(isl_ctx *ctx)
+{
+	const char *str;
+	isl_pw_qpolynomial *pwqp;
+	isl_pw_qpolynomial_fold *pwf;
+
+	str = "{ [[a, b, c, d] -> [e]] -> 0 }";
+	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
+	assert(isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in) == 4);
+	isl_pw_qpolynomial_fold_free(pwf);
+
+	str = "{ [[x]->[x]] -> 1 : exists a : x = 2 a }";
+	pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+	pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
+	assert(isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in) == 1);
+	isl_pw_qpolynomial_fold_free(pwf);
+}
+
+void test_lift(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_map *bmap;
+	isl_basic_set *bset;
+
+	str = "{ [i0] : exists e0 : i0 = 4e0 }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	bset = isl_basic_set_lift(bset);
+	bmap = isl_basic_map_from_range(bset);
+	bset = isl_basic_map_domain(bmap);
+	isl_basic_set_free(bset);
+}
+
+struct {
+	const char *set1;
+	const char *set2;
+	int subset;
+} subset_tests[] = {
+	{ "{ [112, 0] }",
+	  "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
+		"16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
+		"16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
+	{ "{ [65] }",
+	  "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
+		"e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
+		"e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
+		    "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
+		    "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
+		    "256e0 <= 255i and 256e0 >= -255 + 255i and "
+		    "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
+		    "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
+		    "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
+	{ "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
+	{ "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
+	{ "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
+	{ "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
+	{ "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
+			"4e0 >= -1 + t and i >= 57 and i <= 62 and "
+			"4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
+			"t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
+			"4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
+	  "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
+			"4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
+			"4e0 <= -57 + i0 + i1)) or "
+		"(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
+			"4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
+			"4e0 >= -61 + i0 + i1)) or "
+		"(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
+};
+
+static int test_subset(isl_ctx *ctx)
+{
+	int i;
+	isl_set *set1, *set2;
+	int subset;
+
+	for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
+		set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
+		set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
+		subset = isl_set_is_subset(set1, set2);
+		isl_set_free(set1);
+		isl_set_free(set2);
+		if (subset < 0)
+			return -1;
+		if (subset != subset_tests[i].subset)
+			isl_die(ctx, isl_error_unknown,
+				"incorrect subset result", return -1);
+	}
+
+	return 0;
+}
+
+struct {
+	const char *minuend;
+	const char *subtrahend;
+	const char *difference;
+} subtract_domain_tests[] = {
+	{ "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
+	{ "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
+	{ "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
+};
+
+static int test_subtract(isl_ctx *ctx)
+{
+	int i;
+	isl_union_map *umap1, *umap2;
+	isl_union_set *uset;
+	int equal;
+
+	for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
+		umap1 = isl_union_map_read_from_str(ctx,
+				subtract_domain_tests[i].minuend);
+		uset = isl_union_set_read_from_str(ctx,
+				subtract_domain_tests[i].subtrahend);
+		umap2 = isl_union_map_read_from_str(ctx,
+				subtract_domain_tests[i].difference);
+		umap1 = isl_union_map_subtract_domain(umap1, uset);
+		equal = isl_union_map_is_equal(umap1, umap2);
+		isl_union_map_free(umap1);
+		isl_union_map_free(umap2);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"incorrect subtract domain result", return -1);
+	}
+
+	return 0;
+}
+
+int test_factorize(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_set *bset;
+	isl_factorizer *f;
+
+	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
+	    "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
+	    "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
+	    "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
+	    "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
+	    "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
+	    "3i5 >= -2i0 - i2 + 3i4 }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	f = isl_basic_set_factorizer(bset);
+	isl_basic_set_free(bset);
+	isl_factorizer_free(f);
+	if (!f)
+		isl_die(ctx, isl_error_unknown,
+			"failed to construct factorizer", return -1);
+
+	str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
+	    "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
+	    "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
+	    "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
+	    "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
+	    "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
+	    "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
+	    "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
+	    "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
+	    "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	f = isl_basic_set_factorizer(bset);
+	isl_basic_set_free(bset);
+	isl_factorizer_free(f);
+	if (!f)
+		isl_die(ctx, isl_error_unknown,
+			"failed to construct factorizer", return -1);
+
+	return 0;
+}
+
+static int check_injective(__isl_take isl_map *map, void *user)
+{
+	int *injective = user;
+
+	*injective = isl_map_is_injective(map);
+	isl_map_free(map);
+
+	if (*injective < 0 || !*injective)
+		return -1;
+
+	return 0;
+}
+
+int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
+	const char *r, const char *s, int tilable, int parallel)
+{
+	int i;
+	isl_union_set *D;
+	isl_union_map *W, *R, *S;
+	isl_union_map *empty;
+	isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
+	isl_union_map *validity, *proximity, *coincidence;
+	isl_union_map *schedule;
+	isl_union_map *test;
+	isl_union_set *delta;
+	isl_union_set *domain;
+	isl_set *delta_set;
+	isl_set *slice;
+	isl_set *origin;
+	isl_schedule_constraints *sc;
+	isl_schedule *sched;
+	int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
+
+	D = isl_union_set_read_from_str(ctx, d);
+	W = isl_union_map_read_from_str(ctx, w);
+	R = isl_union_map_read_from_str(ctx, r);
+	S = isl_union_map_read_from_str(ctx, s);
+
+	W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
+	R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
+
+	empty = isl_union_map_empty(isl_union_map_get_space(S));
+        isl_union_map_compute_flow(isl_union_map_copy(R),
+				   isl_union_map_copy(W), empty,
+				   isl_union_map_copy(S),
+				   &dep_raw, NULL, NULL, NULL);
+        isl_union_map_compute_flow(isl_union_map_copy(W),
+				   isl_union_map_copy(W),
+				   isl_union_map_copy(R),
+				   isl_union_map_copy(S),
+				   &dep_waw, &dep_war, NULL, NULL);
+
+	dep = isl_union_map_union(dep_waw, dep_war);
+	dep = isl_union_map_union(dep, dep_raw);
+	validity = isl_union_map_copy(dep);
+	coincidence = isl_union_map_copy(dep);
+	proximity = isl_union_map_copy(dep);
+
+	sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
+	sc = isl_schedule_constraints_set_validity(sc, validity);
+	sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
+	sc = isl_schedule_constraints_set_proximity(sc, proximity);
+	sched = isl_schedule_constraints_compute_schedule(sc);
+	schedule = isl_schedule_get_map(sched);
+	isl_schedule_free(sched);
+	isl_union_map_free(W);
+	isl_union_map_free(R);
+	isl_union_map_free(S);
+
+	is_injection = 1;
+	isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
+
+	domain = isl_union_map_domain(isl_union_map_copy(schedule));
+	is_complete = isl_union_set_is_subset(D, domain);
+	isl_union_set_free(D);
+	isl_union_set_free(domain);
+
+	test = isl_union_map_reverse(isl_union_map_copy(schedule));
+	test = isl_union_map_apply_range(test, dep);
+	test = isl_union_map_apply_range(test, schedule);
+
+	delta = isl_union_map_deltas(test);
+	if (isl_union_set_n_set(delta) == 0) {
+		is_tilable = 1;
+		is_parallel = 1;
+		is_nonneg = 1;
+		isl_union_set_free(delta);
+	} else {
+		delta_set = isl_set_from_union_set(delta);
+
+		slice = isl_set_universe(isl_set_get_space(delta_set));
+		for (i = 0; i < tilable; ++i)
+			slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
+		is_tilable = isl_set_is_subset(delta_set, slice);
+		isl_set_free(slice);
+
+		slice = isl_set_universe(isl_set_get_space(delta_set));
+		for (i = 0; i < parallel; ++i)
+			slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
+		is_parallel = isl_set_is_subset(delta_set, slice);
+		isl_set_free(slice);
+
+		origin = isl_set_universe(isl_set_get_space(delta_set));
+		for (i = 0; i < isl_set_dim(origin, isl_dim_set); ++i)
+			origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
+
+		delta_set = isl_set_union(delta_set, isl_set_copy(origin));
+		delta_set = isl_set_lexmin(delta_set);
+
+		is_nonneg = isl_set_is_equal(delta_set, origin);
+
+		isl_set_free(origin);
+		isl_set_free(delta_set);
+	}
+
+	if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
+	    is_injection < 0 || is_complete < 0)
+		return -1;
+	if (!is_complete)
+		isl_die(ctx, isl_error_unknown,
+			"generated schedule incomplete", return -1);
+	if (!is_injection)
+		isl_die(ctx, isl_error_unknown,
+			"generated schedule not injective on each statement",
+			return -1);
+	if (!is_nonneg)
+		isl_die(ctx, isl_error_unknown,
+			"negative dependences in generated schedule",
+			return -1);
+	if (!is_tilable)
+		isl_die(ctx, isl_error_unknown,
+			"generated schedule not as tilable as expected",
+			return -1);
+	if (!is_parallel)
+		isl_die(ctx, isl_error_unknown,
+			"generated schedule not as parallel as expected",
+			return -1);
+
+	return 0;
+}
+
+static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
+	const char *domain, const char *validity, const char *proximity)
+{
+	isl_union_set *dom;
+	isl_union_map *dep;
+	isl_union_map *prox;
+	isl_schedule_constraints *sc;
+	isl_schedule *schedule;
+	isl_union_map *sched;
+
+	dom = isl_union_set_read_from_str(ctx, domain);
+	dep = isl_union_map_read_from_str(ctx, validity);
+	prox = isl_union_map_read_from_str(ctx, proximity);
+	sc = isl_schedule_constraints_on_domain(dom);
+	sc = isl_schedule_constraints_set_validity(sc, dep);
+	sc = isl_schedule_constraints_set_proximity(sc, prox);
+	schedule = isl_schedule_constraints_compute_schedule(sc);
+	sched = isl_schedule_get_map(schedule);
+	isl_schedule_free(schedule);
+
+	return sched;
+}
+
+/* Check that a schedule can be constructed on the given domain
+ * with the given validity and proximity constraints.
+ */
+static int test_has_schedule(isl_ctx *ctx, const char *domain,
+	const char *validity, const char *proximity)
+{
+	isl_union_map *sched;
+
+	sched = compute_schedule(ctx, domain, validity, proximity);
+	if (!sched)
+		return -1;
+
+	isl_union_map_free(sched);
+	return 0;
+}
+
+int test_special_schedule(isl_ctx *ctx, const char *domain,
+	const char *validity, const char *proximity, const char *expected_sched)
+{
+	isl_union_map *sched1, *sched2;
+	int equal;
+
+	sched1 = compute_schedule(ctx, domain, validity, proximity);
+	sched2 = isl_union_map_read_from_str(ctx, expected_sched);
+
+	equal = isl_union_map_is_equal(sched1, sched2);
+	isl_union_map_free(sched1);
+	isl_union_map_free(sched2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected schedule",
+			return -1);
+
+	return 0;
+}
+
+/* Check that the schedule map is properly padded, even after being
+ * reconstructed from the band forest.
+ */
+static int test_padded_schedule(isl_ctx *ctx)
+{
+	const char *str;
+	isl_union_set *D;
+	isl_union_map *validity, *proximity;
+	isl_schedule_constraints *sc;
+	isl_schedule *sched;
+	isl_union_map *map1, *map2;
+	isl_band_list *list;
+	int equal;
+
+	str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
+	D = isl_union_set_read_from_str(ctx, str);
+	validity = isl_union_map_empty(isl_union_set_get_space(D));
+	proximity = isl_union_map_copy(validity);
+	sc = isl_schedule_constraints_on_domain(D);
+	sc = isl_schedule_constraints_set_validity(sc, validity);
+	sc = isl_schedule_constraints_set_proximity(sc, proximity);
+	sched = isl_schedule_constraints_compute_schedule(sc);
+	map1 = isl_schedule_get_map(sched);
+	list = isl_schedule_get_band_forest(sched);
+	isl_band_list_free(list);
+	map2 = isl_schedule_get_map(sched);
+	isl_schedule_free(sched);
+	equal = isl_union_map_is_equal(map1, map2);
+	isl_union_map_free(map1);
+	isl_union_map_free(map2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"reconstructed schedule map not the same as original",
+			return -1);
+
+	return 0;
+}
+
+/* Input for testing of schedule construction based on
+ * conditional constraints.
+ *
+ * domain is the iteration domain
+ * flow are the flow dependences, which determine the validity and
+ * 	proximity constraints
+ * condition are the conditions on the conditional validity constraints
+ * conditional_validity are the conditional validity constraints
+ * outer_band_n is the expected number of members in the outer band
+ */
+struct {
+	const char *domain;
+	const char *flow;
+	const char *condition;
+	const char *conditional_validity;
+	int outer_band_n;
+} live_range_tests[] = {
+	/* Contrived example that illustrates that we need to keep
+	 * track of tagged condition dependences and
+	 * tagged conditional validity dependences
+	 * in isl_sched_edge separately.
+	 * In particular, the conditional validity constraints on A
+	 * cannot be satisfied,
+	 * but they can be ignored because there are no corresponding
+	 * condition constraints.  However, we do have an additional
+	 * conditional validity constraint that maps to the same
+	 * dependence relation
+	 * as the condition constraint on B.  If we did not make a distinction
+	 * between tagged condition and tagged conditional validity
+	 * dependences, then we
+	 * could end up treating this shared dependence as an condition
+	 * constraint on A, forcing a localization of the conditions,
+	 * which is impossible.
+	 */
+	{ "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
+	  "{ S[i] -> S[i+1] : 0 <= i < 99 }",
+	  "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
+	  "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
+	    "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
+	    "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
+	  1
+	},
+	/* TACO 2013 Fig. 7 */
+	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
+	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
+		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
+	  "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
+		   "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
+				"0 <= i < n and 0 <= j < n - 1 }",
+	  "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
+				"0 <= i < n and 0 <= j < j' < n;"
+		   "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
+				"0 <= i < i' < n and 0 <= j,j' < n;"
+		   "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
+				"0 <= i,j,j' < n and j < j' }",
+	    2
+	},
+	/* TACO 2013 Fig. 7, without tags */
+	{ "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
+	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
+		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
+	  "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
+		   "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
+	  "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
+		   "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
+		   "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
+	   1
+	},
+	/* TACO 2013 Fig. 12 */
+	{ "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
+	    "S3[i,3] : 0 <= i <= 1 }",
+	  "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
+	    "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
+	    "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
+	  "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
+	    "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
+	    "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
+	  "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
+	    "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
+	    "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
+	    "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
+	    "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
+	   1
+	}
+};
+
+/* Test schedule construction based on conditional constraints.
+ * In particular, check the number of members in the outer band
+ * as an indication of whether tiling is possible or not.
+ */
+static int test_conditional_schedule_constraints(isl_ctx *ctx)
+{
+	int i;
+	isl_union_set *domain;
+	isl_union_map *condition;
+	isl_union_map *flow;
+	isl_union_map *validity;
+	isl_schedule_constraints *sc;
+	isl_schedule *schedule;
+	isl_band_list *list;
+	isl_band *band;
+	int n_member;
+
+	for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
+		domain = isl_union_set_read_from_str(ctx,
+				live_range_tests[i].domain);
+		flow = isl_union_map_read_from_str(ctx,
+				live_range_tests[i].flow);
+		condition = isl_union_map_read_from_str(ctx,
+				live_range_tests[i].condition);
+		validity = isl_union_map_read_from_str(ctx,
+				live_range_tests[i].conditional_validity);
+		sc = isl_schedule_constraints_on_domain(domain);
+		sc = isl_schedule_constraints_set_validity(sc,
+				isl_union_map_copy(flow));
+		sc = isl_schedule_constraints_set_proximity(sc, flow);
+		sc = isl_schedule_constraints_set_conditional_validity(sc,
+				condition, validity);
+		schedule = isl_schedule_constraints_compute_schedule(sc);
+		list = isl_schedule_get_band_forest(schedule);
+		band = isl_band_list_get_band(list, 0);
+		n_member = isl_band_n_member(band);
+		isl_band_free(band);
+		isl_band_list_free(list);
+		isl_schedule_free(schedule);
+
+		if (!schedule)
+			return -1;
+		if (n_member != live_range_tests[i].outer_band_n)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected number of members in outer band",
+				return -1);
+	}
+	return 0;
+}
+
+int test_schedule(isl_ctx *ctx)
+{
+	const char *D, *W, *R, *V, *P, *S;
+
+	/* Handle resulting schedule with zero bands. */
+	if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
+		return -1;
+
+	/* Jacobi */
+	D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
+	W = "{ S1[t,i] -> a[t,i] }";
+	R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
+	    	"S1[t,i] -> a[t-1,i+1] }";
+	S = "{ S1[t,i] -> [t,i] }";
+	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
+		return -1;
+
+	/* Fig. 5 of CC2008 */
+	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
+				"j <= -1 + N }";
+	W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
+				"j >= 2 and j <= -1 + N }";
+	R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
+				"j >= 2 and j <= -1 + N; "
+		    "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
+				"j >= 2 and j <= -1 + N }";
+	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
+		return -1;
+
+	D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
+	W = "{ S1[i] -> a[i] }";
+	R = "{ S2[i] -> a[i+1] }";
+	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
+	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
+		return -1;
+
+	D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
+	W = "{ S1[i] -> a[i] }";
+	R = "{ S2[i] -> a[9-i] }";
+	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
+	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
+		return -1;
+
+	D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
+	W = "{ S1[i] -> a[i] }";
+	R = "[N] -> { S2[i] -> a[N-1-i] }";
+	S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
+	if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
+		return -1;
+	
+	D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
+	W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
+	R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
+	S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+
+	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
+	W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
+	R = "{ S2[i,j] -> a[i-1,j] }";
+	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
+	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
+		return -1;
+
+	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
+	W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
+	R = "{ S2[i,j] -> a[i,j-1] }";
+	S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
+	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
+		return -1;
+
+	D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
+	W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
+		    "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
+	R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
+	S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
+		    "S_0[] -> [0, 0, 0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
+		return -1;
+	ctx->opt->schedule_parametric = 0;
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+	ctx->opt->schedule_parametric = 1;
+
+	D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
+		    "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
+	W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
+	R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
+		    "S4[i] -> a[i,N] }";
+	S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
+		"S4[i] -> [4,i,0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
+		return -1;
+
+	D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
+	W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
+					"j <= N }";
+	R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
+					"j <= N; "
+		    "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
+					"j <= N }";
+	S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+
+	D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
+		    " S_2[t] : t >= 0 and t <= -1 + N; "
+		    " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
+				"i <= -1 + N }";
+	W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
+		    " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
+		    " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
+						"i >= 0 and i <= -1 + N }";
+	R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
+					    "i >= 0 and i <= -1 + N; "
+		    " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
+	S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
+		    " S_0[t] -> [0, t, 0] }";
+
+	if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
+		return -1;
+	ctx->opt->schedule_parametric = 0;
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+	ctx->opt->schedule_parametric = 1;
+
+	D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
+	S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
+	if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
+		return -1;
+
+	D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
+	    "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
+	W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
+					    "j >= 0 and j <= -1 + N; "
+			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
+	R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
+					    "j >= 0 and j <= -1 + N; "
+			"S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
+	S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+
+	D = "{ S_0[i] : i >= 0 }";
+	W = "{ S_0[i] -> a[i] : i >= 0 }";
+	R = "{ S_0[i] -> a[0] : i >= 0 }";
+	S = "{ S_0[i] -> [0, i, 0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+
+	D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
+	W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
+	R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
+	S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+
+	D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
+				"k <= -1 + n and k >= 0 }";
+	W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "							"k <= -1 + n and k >= 0 }";
+	R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
+					"k <= -1 + n and k >= 0; "
+		    "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
+					"k <= -1 + n and k >= 0; "
+		    "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
+					"k <= -1 + n and k >= 0 }";
+	S = "[n] -> { S_0[j, k] -> [2, j, k] }";
+	ctx->opt->schedule_outer_coincidence = 1;
+	if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+		return -1;
+	ctx->opt->schedule_outer_coincidence = 0;
+
+	D = "{Stmt_for_body24[i0, i1, i2, i3]:"
+		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
+		"i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
+	     "Stmt_for_body24[i0, i1, 1, 0]:"
+		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
+	     "Stmt_for_body7[i0, i1, i2]:"
+		"i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
+		"i2 <= 7 }";
+
+	V = "{Stmt_for_body24[0, i1, i2, i3] -> "
+		"Stmt_for_body24[1, i1, i2, i3]:"
+		"i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
+		"i2 >= 1;"
+	     "Stmt_for_body24[0, i1, i2, i3] -> "
+		"Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
+		"i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
+		"i3 >= 0;"
+	      "Stmt_for_body24[0, i1, i2, i3] ->"
+		"Stmt_for_body7[1, i1, 1 + i1 + i3]:"
+		"i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
+	      "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
+		"(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
+		"(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
+		"(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
+	      "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
+		"i1 <= 6 and i1 >= 0;"
+	      "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
+	      "Stmt_for_body7[i0, i1, i2] -> "
+		"Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
+		"i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
+		"o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
+	      "Stmt_for_body7[i0, i1, i2] -> "
+		"Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
+		"i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
+		"o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
+	P = V;
+	S = "{ Stmt_for_body24[i0, i1, i2, i3] -> "
+		"[i0, 5i0 + i1, 6i0 + i1 + i2, 1 + 6i0 + i1 + i2 + i3, 1];"
+	    "Stmt_for_body7[i0, i1, i2] -> [0, 5i0, 6i0 + i1, 6i0 + i2, 0] }";
+
+	if (test_special_schedule(ctx, D, V, P, S) < 0)
+		return -1;
+
+	D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
+	V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
+					   "j >= 1 and j <= 7;"
+		"S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
+					     "j >= 1 and j <= 8 }";
+	P = "{ }";
+	S = "{ S_0[i, j] -> [i + j, j] }";
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+	if (test_special_schedule(ctx, D, V, P, S) < 0)
+		return -1;
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+	/* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
+	D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
+				 "j >= 0 and j <= -1 + i }";
+	V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
+					"i <= -1 + N and j >= 0;"
+		     "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
+					"i <= -2 + N }";
+	P = "{ }";
+	S = "{ S_0[i, j] -> [i, j] }";
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+	if (test_special_schedule(ctx, D, V, P, S) < 0)
+		return -1;
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+	/* Test both algorithms on a case with only proximity dependences. */
+	D = "{ S[i,j] : 0 <= i <= 10 }";
+	V = "{ }";
+	P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
+	S = "{ S[i, j] -> [j, i] }";
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+	if (test_special_schedule(ctx, D, V, P, S) < 0)
+		return -1;
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+	if (test_special_schedule(ctx, D, V, P, S) < 0)
+		return -1;
+	
+	D = "{ A[a]; B[] }";
+	V = "{}";
+	P = "{ A[a] -> B[] }";
+	if (test_has_schedule(ctx, D, V, P) < 0)
+		return -1;
+
+	if (test_padded_schedule(ctx) < 0)
+		return -1;
+
+	/* Check that check for progress is not confused by rational
+	 * solution.
+	 */
+	D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
+	V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
+							"i0 <= -2 + N; "
+			"S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
+				"i0 <= N and i1 >= 0 and i1 <= -1 + N }";
+	P = "{}";
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+	if (test_has_schedule(ctx, D, V, P) < 0)
+		return -1;
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+	/* Check that we allow schedule rows that are only non-trivial
+	 * on some full-dimensional domains.
+	 */
+	D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
+	V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
+		"S1[j] -> S2[1] : 0 <= j <= 1 }";
+	P = "{}";
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+	if (test_has_schedule(ctx, D, V, P) < 0)
+		return -1;
+	ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+	if (test_conditional_schedule_constraints(ctx) < 0)
+		return -1;
+
+	return 0;
+}
+
+int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
+{
+	isl_union_map *umap;
+	int test;
+
+	umap = isl_union_map_read_from_str(ctx, str);
+	test = isl_union_map_plain_is_injective(umap);
+	isl_union_map_free(umap);
+	if (test < 0)
+		return -1;
+	if (test == injective)
+		return 0;
+	if (injective)
+		isl_die(ctx, isl_error_unknown,
+			"map not detected as injective", return -1);
+	else
+		isl_die(ctx, isl_error_unknown,
+			"map detected as injective", return -1);
+}
+
+int test_injective(isl_ctx *ctx)
+{
+	const char *str;
+
+	if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
+		return -1;
+	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
+		return -1;
+	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
+		return -1;
+	if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
+		return -1;
+	if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
+		return -1;
+	if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
+		return -1;
+	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
+		return -1;
+	if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
+		return -1;
+
+	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
+	if (test_plain_injective(ctx, str, 1))
+		return -1;
+	str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
+	if (test_plain_injective(ctx, str, 0))
+		return -1;
+
+	return 0;
+}
+
+static int aff_plain_is_equal(__isl_keep isl_aff *aff, const char *str)
+{
+	isl_aff *aff2;
+	int equal;
+
+	if (!aff)
+		return -1;
+
+	aff2 = isl_aff_read_from_str(isl_aff_get_ctx(aff), str);
+	equal = isl_aff_plain_is_equal(aff, aff2);
+	isl_aff_free(aff2);
+
+	return equal;
+}
+
+static int aff_check_plain_equal(__isl_keep isl_aff *aff, const char *str)
+{
+	int equal;
+
+	equal = aff_plain_is_equal(aff, str);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(isl_aff_get_ctx(aff), isl_error_unknown,
+			"result not as expected", return -1);
+	return 0;
+}
+
+struct {
+	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
+				__isl_take isl_aff *aff2);
+} aff_bin_op[] = {
+	['+'] = { &isl_aff_add },
+	['-'] = { &isl_aff_sub },
+	['*'] = { &isl_aff_mul },
+	['/'] = { &isl_aff_div },
+};
+
+struct {
+	const char *arg1;
+	unsigned char op;
+	const char *arg2;
+	const char *res;
+} aff_bin_tests[] = {
+	{ "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
+	  "{ [i] -> [2i] }" },
+	{ "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
+	  "{ [i] -> [0] }" },
+	{ "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
+	  "{ [i] -> [2i] }" },
+	{ "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
+	  "{ [i] -> [2i] }" },
+	{ "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
+	  "{ [i] -> [i/2] }" },
+	{ "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
+	  "{ [i] -> [i] }" },
+	{ "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
+	  "{ [i] -> [NaN] }" },
+	{ "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
+	  "{ [i] -> [NaN] }" },
+};
+
+/* Perform some basic tests of binary operations on isl_aff objects.
+ */
+static int test_bin_aff(isl_ctx *ctx)
+{
+	int i;
+	isl_aff *aff1, *aff2, *res;
+	__isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
+				__isl_take isl_aff *aff2);
+	int ok;
+
+	for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
+		aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
+		aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
+		res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
+		fn = aff_bin_op[aff_bin_tests[i].op].fn;
+		aff1 = fn(aff1, aff2);
+		if (isl_aff_is_nan(res))
+			ok = isl_aff_is_nan(aff1);
+		else
+			ok = isl_aff_plain_is_equal(aff1, res);
+		isl_aff_free(aff1);
+		isl_aff_free(res);
+		if (ok < 0)
+			return -1;
+		if (!ok)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return -1);
+	}
+
+	return 0;
+}
+
+struct {
+	__isl_give isl_union_pw_multi_aff *(*fn)(
+		__isl_take isl_union_pw_multi_aff *upma1,
+		__isl_take isl_union_pw_multi_aff *upma2);
+	const char *arg1;
+	const char *arg2;
+	const char *res;
+} upma_bin_tests[] = {
+	{ &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
+	  "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
+	{ &isl_union_pw_multi_aff_union_add, "{ A[] -> [0]; B[0] -> [1] }",
+	  "{ B[x] -> [2] : x >= 0 }",
+	  "{ A[] -> [0]; B[0] -> [3]; B[x] -> [2] : x >= 1 }" },
+};
+
+/* Perform some basic tests of binary operations on
+ * isl_union_pw_multi_aff objects.
+ */
+static int test_bin_upma(isl_ctx *ctx)
+{
+	int i;
+	isl_union_pw_multi_aff *upma1, *upma2, *res;
+	int ok;
+
+	for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
+		upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
+							upma_bin_tests[i].arg1);
+		upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
+							upma_bin_tests[i].arg2);
+		res = isl_union_pw_multi_aff_read_from_str(ctx,
+							upma_bin_tests[i].res);
+		upma1 = upma_bin_tests[i].fn(upma1, upma2);
+		ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
+		isl_union_pw_multi_aff_free(upma1);
+		isl_union_pw_multi_aff_free(res);
+		if (ok < 0)
+			return -1;
+		if (!ok)
+			isl_die(ctx, isl_error_unknown,
+				"unexpected result", return -1);
+	}
+
+	return 0;
+}
+
+int test_aff(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_space *space;
+	isl_local_space *ls;
+	isl_aff *aff;
+	int zero, equal;
+
+	if (test_bin_aff(ctx) < 0)
+		return -1;
+	if (test_bin_upma(ctx) < 0)
+		return -1;
+
+	space = isl_space_set_alloc(ctx, 0, 1);
+	ls = isl_local_space_from_space(space);
+	aff = isl_aff_zero_on_domain(ls);
+
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+	aff = isl_aff_scale_down_ui(aff, 3);
+	aff = isl_aff_floor(aff);
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+	aff = isl_aff_scale_down_ui(aff, 2);
+	aff = isl_aff_floor(aff);
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+
+	str = "{ [10] }";
+	set = isl_set_read_from_str(ctx, str);
+	aff = isl_aff_gist(aff, set);
+
+	aff = isl_aff_add_constant_si(aff, -16);
+	zero = isl_aff_plain_is_zero(aff);
+	isl_aff_free(aff);
+
+	if (zero < 0)
+		return -1;
+	if (!zero)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	aff = isl_aff_read_from_str(ctx, "{ [-1] }");
+	aff = isl_aff_scale_down_ui(aff, 64);
+	aff = isl_aff_floor(aff);
+	equal = aff_check_plain_equal(aff, "{ [-1] }");
+	isl_aff_free(aff);
+	if (equal < 0)
+		return -1;
+
+	return 0;
+}
+
+int test_dim_max(isl_ctx *ctx)
+{
+	int equal;
+	const char *str;
+	isl_set *set1, *set2;
+	isl_set *set;
+	isl_map *map;
+	isl_pw_aff *pwaff;
+
+	str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
+	set = isl_set_read_from_str(ctx, str);
+	pwaff = isl_set_dim_max(set, 0);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
+	set = isl_set_read_from_str(ctx, str);
+	pwaff = isl_set_dim_max(set, 0);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
+	set = isl_set_read_from_str(ctx, str);
+	pwaff = isl_set_dim_max(set, 0);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
+			"0 <= i < N and 0 <= j < M }";
+	map = isl_map_read_from_str(ctx, str);
+	set = isl_map_range(map);
+
+	pwaff = isl_set_dim_max(isl_set_copy(set), 0);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+
+	pwaff = isl_set_dim_max(isl_set_copy(set), 3);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	if (equal >= 0 && equal)
+		equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+
+	isl_set_free(set);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	/* Check that solutions are properly merged. */
+	str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
+				"c <= -1 + n - 4a - 2b and c >= -2b and "
+				"4a >= -4 + n and c >= 0 }";
+	set = isl_set_read_from_str(ctx, str);
+	pwaff = isl_set_dim_min(set, 2);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[n] -> { [(0)] : n >= 1 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	/* Check that empty solution lie in the right space. */
+	str = "[n] -> { [t,a] : 1 = 0 }";
+	set = isl_set_read_from_str(ctx, str);
+	pwaff = isl_set_dim_max(set, 0);
+	set1 = isl_set_from_pw_aff(pwaff);
+	str = "[n] -> { [t] : 1 = 0 }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set1, set2);
+	isl_set_free(set1);
+	isl_set_free(set2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	return 0;
+}
+
+/* Is "pma" obviously equal to the isl_pw_multi_aff represented by "str"?
+ */
+static int pw_multi_aff_plain_is_equal(__isl_keep isl_pw_multi_aff *pma,
+	const char *str)
+{
+	isl_ctx *ctx;
+	isl_pw_multi_aff *pma2;
+	int equal;
+
+	if (!pma)
+		return -1;
+
+	ctx = isl_pw_multi_aff_get_ctx(pma);
+	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
+	equal = isl_pw_multi_aff_plain_is_equal(pma, pma2);
+	isl_pw_multi_aff_free(pma2);
+
+	return equal;
+}
+
+/* Check that "pma" is obviously equal to the isl_pw_multi_aff
+ * represented by "str".
+ */
+static int pw_multi_aff_check_plain_equal(__isl_keep isl_pw_multi_aff *pma,
+	const char *str)
+{
+	int equal;
+
+	equal = pw_multi_aff_plain_is_equal(pma, str);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_unknown,
+			"result not as expected", return -1);
+	return 0;
+}
+
+/* Basic test for isl_pw_multi_aff_product.
+ *
+ * Check that multiple pieces are properly handled.
+ */
+static int test_product_pma(isl_ctx *ctx)
+{
+	int equal;
+	const char *str;
+	isl_pw_multi_aff *pma1, *pma2;
+
+	str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
+	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
+	str = "{ C[] -> D[] }";
+	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
+	pma1 = isl_pw_multi_aff_product(pma1, pma2);
+	str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
+		"[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
+	equal = pw_multi_aff_check_plain_equal(pma1, str);
+	isl_pw_multi_aff_free(pma1);
+	if (equal < 0)
+		return -1;
+
+	return 0;
+}
+
+int test_product(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_union_set *uset1, *uset2;
+	int ok;
+
+	str = "{ A[i] }";
+	set = isl_set_read_from_str(ctx, str);
+	set = isl_set_product(set, isl_set_copy(set));
+	ok = isl_set_is_wrapping(set);
+	isl_set_free(set);
+	if (ok < 0)
+		return -1;
+	if (!ok)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	str = "{ [] }";
+	uset1 = isl_union_set_read_from_str(ctx, str);
+	uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
+	str = "{ [[] -> []] }";
+	uset2 = isl_union_set_read_from_str(ctx, str);
+	ok = isl_union_set_is_equal(uset1, uset2);
+	isl_union_set_free(uset1);
+	isl_union_set_free(uset2);
+	if (ok < 0)
+		return -1;
+	if (!ok)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	if (test_product_pma(ctx) < 0)
+		return -1;
+
+	return 0;
+}
+
+/* Check that two sets are not considered disjoint just because
+ * they have a different set of (named) parameters.
+ */
+static int test_disjoint(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set, *set2;
+	int disjoint;
+
+	str = "[n] -> { [[]->[]] }";
+	set = isl_set_read_from_str(ctx, str);
+	str = "{ [[]->[]] }";
+	set2 = isl_set_read_from_str(ctx, str);
+	disjoint = isl_set_is_disjoint(set, set2);
+	isl_set_free(set);
+	isl_set_free(set2);
+	if (disjoint < 0)
+		return -1;
+	if (disjoint)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	return 0;
+}
+
+int test_equal(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set, *set2;
+	int equal;
+
+	str = "{ S_6[i] }";
+	set = isl_set_read_from_str(ctx, str);
+	str = "{ S_7[i] }";
+	set2 = isl_set_read_from_str(ctx, str);
+	equal = isl_set_is_equal(set, set2);
+	isl_set_free(set);
+	isl_set_free(set2);
+	if (equal < 0)
+		return -1;
+	if (equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	return 0;
+}
+
+static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, int fixed)
+{
+	int test;
+
+	test = isl_map_plain_is_fixed(map, type, pos, NULL);
+	isl_map_free(map);
+	if (test < 0)
+		return -1;
+	if (test == fixed)
+		return 0;
+	if (fixed)
+		isl_die(ctx, isl_error_unknown,
+			"map not detected as fixed", return -1);
+	else
+		isl_die(ctx, isl_error_unknown,
+			"map detected as fixed", return -1);
+}
+
+int test_fixed(isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map;
+
+	str = "{ [i] -> [i] }";
+	map = isl_map_read_from_str(ctx, str);
+	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
+		return -1;
+	str = "{ [i] -> [1] }";
+	map = isl_map_read_from_str(ctx, str);
+	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
+		return -1;
+	str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
+	map = isl_map_read_from_str(ctx, str);
+	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
+		return -1;
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_neg(map);
+	if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
+		return -1;
+
+	return 0;
+}
+
+struct isl_vertices_test_data {
+	const char *set;
+	int n;
+	const char *vertex[2];
+} vertices_tests[] = {
+	{ "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
+	  2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
+	{ "{ A[t, i] : t = 14 and i = 1 }",
+	  1, { "{ A[14, 1] }" } },
+};
+
+/* Check that "vertex" corresponds to one of the vertices in data->vertex.
+ */
+static int find_vertex(__isl_take isl_vertex *vertex, void *user)
+{
+	struct isl_vertices_test_data *data = user;
+	isl_ctx *ctx;
+	isl_multi_aff *ma;
+	isl_basic_set *bset;
+	isl_pw_multi_aff *pma;
+	int i;
+	int equal;
+
+	ctx = isl_vertex_get_ctx(vertex);
+	bset = isl_vertex_get_domain(vertex);
+	ma = isl_vertex_get_expr(vertex);
+	pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
+
+	for (i = 0; i < data->n; ++i) {
+		isl_pw_multi_aff *pma_i;
+
+		pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
+		equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
+		isl_pw_multi_aff_free(pma_i);
+
+		if (equal < 0 || equal)
+			break;
+	}
+
+	isl_pw_multi_aff_free(pma);
+	isl_vertex_free(vertex);
+
+	if (equal < 0)
+		return -1;
+
+	return equal ? 0 : - 1;
+}
+
+int test_vertices(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
+		isl_basic_set *bset;
+		isl_vertices *vertices;
+		int ok = 1;
+		int n;
+
+		bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
+		vertices = isl_basic_set_compute_vertices(bset);
+		n = isl_vertices_get_n_vertices(vertices);
+		if (vertices_tests[i].n != n)
+			ok = 0;
+		if (isl_vertices_foreach_vertex(vertices, &find_vertex,
+						&vertices_tests[i]) < 0)
+			ok = 0;
+		isl_vertices_free(vertices);
+		isl_basic_set_free(bset);
+
+		if (!vertices)
+			return -1;
+		if (!ok)
+			isl_die(ctx, isl_error_unknown, "unexpected vertices",
+				return -1);
+	}
+
+	return 0;
+}
+
+int test_union_pw(isl_ctx *ctx)
+{
+	int equal;
+	const char *str;
+	isl_union_set *uset;
+	isl_union_pw_qpolynomial *upwqp1, *upwqp2;
+
+	str = "{ [x] -> x^2 }";
+	upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
+	upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
+	uset = isl_union_pw_qpolynomial_domain(upwqp1);
+	upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
+	upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
+	equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
+	isl_union_pw_qpolynomial_free(upwqp1);
+	isl_union_pw_qpolynomial_free(upwqp2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	return 0;
+}
+
+int test_output(isl_ctx *ctx)
+{
+	char *s;
+	const char *str;
+	isl_pw_aff *pa;
+	isl_printer *p;
+	int equal;
+
+	str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
+	pa = isl_pw_aff_read_from_str(ctx, str);
+
+	p = isl_printer_to_str(ctx);
+	p = isl_printer_set_output_format(p, ISL_FORMAT_C);
+	p = isl_printer_print_pw_aff(p, pa);
+	s = isl_printer_get_str(p);
+	isl_printer_free(p);
+	isl_pw_aff_free(pa);
+	if (!s)
+		equal = -1;
+	else
+		equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
+	free(s);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+	return 0;
+}
+
+int test_sample(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_set *bset1, *bset2;
+	int empty, subset;
+
+	str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
+	    "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
+	    "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
+	    "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
+	    "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
+	    "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
+	    "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
+	    "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
+	    "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
+	    "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
+	    "3i >= 1 + 2b - 2c + e + 2f + 3g and "
+	    "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
+		"d - 1073741821e and "
+	    "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
+	    "3j >= 1 - a + b + 2e and "
+	    "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
+	    "3i <= 4 - a + 4b - e and "
+	    "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
+	    "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
+	    "c <= -1 + a and 3i >= -2 - a + 3e and "
+	    "1073741822e <= 1073741823 - a + 1073741822b + c and "
+	    "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
+	    "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
+	    "1073741823e >= 1 + 1073741823b - d and "
+	    "3i >= 1073741823b + c - 1073741823e - f and "
+	    "3i >= 1 + 2b + e + 3g }";
+	bset1 = isl_basic_set_read_from_str(ctx, str);
+	bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
+	empty = isl_basic_set_is_empty(bset2);
+	subset = isl_basic_set_is_subset(bset2, bset1);
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	if (empty < 0 || subset < 0)
+		return -1;
+	if (empty)
+		isl_die(ctx, isl_error_unknown, "point not found", return -1);
+	if (!subset)
+		isl_die(ctx, isl_error_unknown, "bad point found", return -1);
+
+	return 0;
+}
+
+int test_fixed_power(isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map;
+	isl_int exp;
+	int equal;
+
+	isl_int_init(exp);
+	str = "{ [i] -> [i + 1] }";
+	map = isl_map_read_from_str(ctx, str);
+	isl_int_set_si(exp, 23);
+	map = isl_map_fixed_power(map, exp);
+	equal = map_check_equal(map, "{ [i] -> [i + 23] }");
+	isl_int_clear(exp);
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	return 0;
+}
+
+int test_slice(isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map;
+	int equal;
+
+	str = "{ [i] -> [j] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
+	equal = map_check_equal(map, "{ [i] -> [i] }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	str = "{ [i] -> [j] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
+	equal = map_check_equal(map, "{ [i] -> [j] }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	str = "{ [i] -> [j] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
+	equal = map_check_equal(map, "{ [i] -> [-i] }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	str = "{ [i] -> [j] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
+	equal = map_check_equal(map, "{ [0] -> [j] }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	str = "{ [i] -> [j] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
+	equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	str = "{ [i] -> [j] }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
+	equal = map_check_equal(map, "{ [i] -> [j] : false }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	return 0;
+}
+
+int test_eliminate(isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map;
+	int equal;
+
+	str = "{ [i] -> [j] : i = 2j }";
+	map = isl_map_read_from_str(ctx, str);
+	map = isl_map_eliminate(map, isl_dim_out, 0, 1);
+	equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
+	isl_map_free(map);
+	if (equal < 0)
+		return -1;
+
+	return 0;
+}
+
+/* Check that isl_set_dim_residue_class detects that the values of j
+ * in the set below are all odd and that it does not detect any spurious
+ * strides.
+ */
+static int test_residue_class(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_int m, r;
+	int res;
+
+	str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
+		"[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
+	set = isl_set_read_from_str(ctx, str);
+	isl_int_init(m);
+	isl_int_init(r);
+	res = isl_set_dim_residue_class(set, 1, &m, &r);
+	if (res >= 0 &&
+	    (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
+		isl_die(ctx, isl_error_unknown, "incorrect residue class",
+			res = -1);
+	isl_int_clear(r);
+	isl_int_clear(m);
+	isl_set_free(set);
+
+	return res;
+}
+
+int test_align_parameters(isl_ctx *ctx)
+{
+	const char *str;
+	isl_space *space;
+	isl_multi_aff *ma1, *ma2;
+	int equal;
+
+	str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
+	ma1 = isl_multi_aff_read_from_str(ctx, str);
+
+	space = isl_space_params_alloc(ctx, 1);
+	space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
+	ma1 = isl_multi_aff_align_params(ma1, space);
+
+	str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
+	ma2 = isl_multi_aff_read_from_str(ctx, str);
+
+	equal = isl_multi_aff_plain_is_equal(ma1, ma2);
+
+	isl_multi_aff_free(ma1);
+	isl_multi_aff_free(ma2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"result not as expected", return -1);
+
+	return 0;
+}
+
+static int test_list(isl_ctx *ctx)
+{
+	isl_id *a, *b, *c, *d, *id;
+	isl_id_list *list;
+	int ok;
+
+	a = isl_id_alloc(ctx, "a", NULL);
+	b = isl_id_alloc(ctx, "b", NULL);
+	c = isl_id_alloc(ctx, "c", NULL);
+	d = isl_id_alloc(ctx, "d", NULL);
+
+	list = isl_id_list_alloc(ctx, 4);
+	list = isl_id_list_add(list, a);
+	list = isl_id_list_add(list, b);
+	list = isl_id_list_add(list, c);
+	list = isl_id_list_add(list, d);
+	list = isl_id_list_drop(list, 1, 1);
+
+	if (isl_id_list_n_id(list) != 3) {
+		isl_id_list_free(list);
+		isl_die(ctx, isl_error_unknown,
+			"unexpected number of elements in list", return -1);
+	}
+
+	id = isl_id_list_get_id(list, 0);
+	ok = id == a;
+	isl_id_free(id);
+	id = isl_id_list_get_id(list, 1);
+	ok = ok && id == c;
+	isl_id_free(id);
+	id = isl_id_list_get_id(list, 2);
+	ok = ok && id == d;
+	isl_id_free(id);
+
+	isl_id_list_free(list);
+
+	if (!ok)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected elements in list", return -1);
+
+	return 0;
+}
+
+const char *set_conversion_tests[] = {
+	"[N] -> { [i] : N - 1 <= 2 i <= N }",
+	"[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
+	"[N] -> { [i,j] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
+	"[N] -> { [[i]->[j]] : exists a : i = 4 a and N - 1 <= i, 2j <= N }",
+	"[N] -> { [3*floor(N/2) + 5*floor(N/3)] }",
+};
+
+/* Check that converting from isl_set to isl_pw_multi_aff and back
+ * to isl_set produces the original isl_set.
+ */
+static int test_set_conversion(isl_ctx *ctx)
+{
+	int i;
+	const char *str;
+	isl_set *set1, *set2;
+	isl_pw_multi_aff *pma;
+	int equal;
+
+	for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
+		str = set_conversion_tests[i];
+		set1 = isl_set_read_from_str(ctx, str);
+		pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
+		set2 = isl_set_from_pw_multi_aff(pma);
+		equal = isl_set_is_equal(set1, set2);
+		isl_set_free(set1);
+		isl_set_free(set2);
+
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown, "bad conversion",
+				return -1);
+	}
+
+	return 0;
+}
+
+/* Check that converting from isl_map to isl_pw_multi_aff and back
+ * to isl_map produces the original isl_map.
+ */
+static int test_map_conversion(isl_ctx *ctx)
+{
+	const char *str;
+	isl_map *map1, *map2;
+	isl_pw_multi_aff *pma;
+	int equal;
+
+	str = "{ [a, b, c, d] -> s0[a, b, e, f] : "
+		"exists (e0 = [(a - 2c)/3], e1 = [(-4 + b - 5d)/9], "
+		"e2 = [(-d + f)/9]: 3e0 = a - 2c and 9e1 = -4 + b - 5d and "
+		"9e2 = -d + f and f >= 0 and f <= 8 and 9e >= -5 - 2a and "
+		"9e <= -2 - 2a) }";
+	map1 = isl_map_read_from_str(ctx, str);
+	pma = isl_pw_multi_aff_from_map(isl_map_copy(map1));
+	map2 = isl_map_from_pw_multi_aff(pma);
+	equal = isl_map_is_equal(map1, map2);
+	isl_map_free(map1);
+	isl_map_free(map2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown, "bad conversion", return -1);
+
+	return 0;
+}
+
+static int test_conversion(isl_ctx *ctx)
+{
+	if (test_set_conversion(ctx) < 0)
+		return -1;
+	if (test_map_conversion(ctx) < 0)
+		return -1;
+	return 0;
+}
+
+/* Check that isl_basic_map_curry does not modify input.
+ */
+static int test_curry(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_map *bmap1, *bmap2;
+	int equal;
+
+	str = "{ [A[] -> B[]] -> C[] }";
+	bmap1 = isl_basic_map_read_from_str(ctx, str);
+	bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
+	equal = isl_basic_map_is_equal(bmap1, bmap2);
+	isl_basic_map_free(bmap1);
+	isl_basic_map_free(bmap2);
+
+	if (equal < 0)
+		return -1;
+	if (equal)
+		isl_die(ctx, isl_error_unknown,
+			"curried map should not be equal to original",
+			return -1);
+
+	return 0;
+}
+
+struct {
+	const char *set;
+	const char *ma;
+	const char *res;
+} preimage_tests[] = {
+	{ "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
+	  "{ A[j,i] -> B[i,j] }",
+	  "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
+	{ "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
+	  "{ A[a,b] -> B[a/2,b/6] }",
+	  "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
+	{ "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
+	  "{ A[a,b] -> B[a/2,b/6] }",
+	  "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
+		    "exists i,j : a = 2 i and b = 6 j }" },
+	{ "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
+	  "[n] -> { : 0 <= n <= 100 }" },
+	{ "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
+	  "{ A[a] -> B[2a] }",
+	  "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
+	{ "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
+	  "{ A[a] -> B[([a/2])] }",
+	  "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
+	{ "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
+	  "{ A[a] -> B[a,a,a/3] }",
+	  "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
+	{ "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
+	  "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
+};
+
+static int test_preimage_basic_set(isl_ctx *ctx)
+{
+	int i;
+	isl_basic_set *bset1, *bset2;
+	isl_multi_aff *ma;
+	int equal;
+
+	for (i = 0; i < ARRAY_SIZE(preimage_tests); ++i) {
+		bset1 = isl_basic_set_read_from_str(ctx, preimage_tests[i].set);
+		ma = isl_multi_aff_read_from_str(ctx, preimage_tests[i].ma);
+		bset2 = isl_basic_set_read_from_str(ctx, preimage_tests[i].res);
+		bset1 = isl_basic_set_preimage_multi_aff(bset1, ma);
+		equal = isl_basic_set_is_equal(bset1, bset2);
+		isl_basic_set_free(bset1);
+		isl_basic_set_free(bset2);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown, "bad preimage",
+				return -1);
+	}
+
+	return 0;
+}
+
+struct {
+	const char *map;
+	const char *ma;
+	const char *res;
+} preimage_domain_tests[] = {
+	{ "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
+	  "{ A[j,i] -> B[i,j] }",
+	  "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
+	{ "{ B[i] -> C[i]; D[i] -> E[i] }",
+	  "{ A[i] -> B[i + 1] }",
+	  "{ A[i] -> C[i + 1] }" },
+	{ "{ B[i] -> C[i]; B[i] -> E[i] }",
+	  "{ A[i] -> B[i + 1] }",
+	  "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
+	{ "{ B[i] -> C[([i/2])] }",
+	  "{ A[i] -> B[2i] }",
+	  "{ A[i] -> C[i] }" },
+	{ "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
+	  "{ A[i] -> B[([i/5]), ([i/7])] }",
+	  "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
+	{ "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
+	  "[N] -> { A[] -> B[([N/5])] }",
+	  "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
+	{ "{ B[i] -> C[i] : exists a : i = 5 a }",
+	  "{ A[i] -> B[2i] }",
+	  "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
+	{ "{ B[i] -> C[i] : exists a : i = 2 a; "
+	    "B[i] -> D[i] : exists a : i = 2 a + 1 }",
+	  "{ A[i] -> B[2i] }",
+	  "{ A[i] -> C[2i] }" },
+};
+
+static int test_preimage_union_map(isl_ctx *ctx)
+{
+	int i;
+	isl_union_map *umap1, *umap2;
+	isl_multi_aff *ma;
+	int equal;
+
+	for (i = 0; i < ARRAY_SIZE(preimage_domain_tests); ++i) {
+		umap1 = isl_union_map_read_from_str(ctx,
+						preimage_domain_tests[i].map);
+		ma = isl_multi_aff_read_from_str(ctx,
+						preimage_domain_tests[i].ma);
+		umap2 = isl_union_map_read_from_str(ctx,
+						preimage_domain_tests[i].res);
+		umap1 = isl_union_map_preimage_domain_multi_aff(umap1, ma);
+		equal = isl_union_map_is_equal(umap1, umap2);
+		isl_union_map_free(umap1);
+		isl_union_map_free(umap2);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown, "bad preimage",
+				return -1);
+	}
+
+	return 0;
+}
+
+static int test_preimage(isl_ctx *ctx)
+{
+	if (test_preimage_basic_set(ctx) < 0)
+		return -1;
+	if (test_preimage_union_map(ctx) < 0)
+		return -1;
+
+	return 0;
+}
+
+struct {
+	const char *ma1;
+	const char *ma;
+	const char *res;
+} pullback_tests[] = {
+	{ "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
+	  "{ A[a,b] -> C[b + 2a] }" },
+	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
+	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
+	{ "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
+	  "{ A[a] -> C[(a)/6] }" },
+	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
+	{ "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
+	  "{ A[a] -> C[(2a)/3] }" },
+	{ "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
+	{ "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
+	  "{ A[i,j] -> C[i + j, i + j] }"},
+	{ "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
+	{ "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
+	  "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
+};
+
+static int test_pullback(isl_ctx *ctx)
+{
+	int i;
+	isl_multi_aff *ma1, *ma2;
+	isl_multi_aff *ma;
+	int equal;
+
+	for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
+		ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
+		ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
+		ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
+		ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
+		equal = isl_multi_aff_plain_is_equal(ma1, ma2);
+		isl_multi_aff_free(ma1);
+		isl_multi_aff_free(ma2);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown, "bad pullback",
+				return -1);
+	}
+
+	return 0;
+}
+
+/* Check that negation is printed correctly.
+ */
+static int test_ast(isl_ctx *ctx)
+{
+	isl_ast_expr *expr, *expr1, *expr2, *expr3;
+	char *str;
+	int ok;
+
+	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
+	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
+	expr = isl_ast_expr_add(expr1, expr2);
+	expr = isl_ast_expr_neg(expr);
+	str = isl_ast_expr_to_str(expr);
+	ok = str ? !strcmp(str, "-(A + B)") : -1;
+	free(str);
+	isl_ast_expr_free(expr);
+
+	if (ok < 0)
+		return -1;
+	if (!ok)
+		isl_die(ctx, isl_error_unknown,
+			"isl_ast_expr printed incorrectly", return -1);
+
+	expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
+	expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
+	expr = isl_ast_expr_add(expr1, expr2);
+	expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
+	expr = isl_ast_expr_sub(expr3, expr);
+	str = isl_ast_expr_to_str(expr);
+	ok = str ? !strcmp(str, "C - (A + B)") : -1;
+	free(str);
+	isl_ast_expr_free(expr);
+
+	if (ok < 0)
+		return -1;
+	if (!ok)
+		isl_die(ctx, isl_error_unknown,
+			"isl_ast_expr printed incorrectly", return -1);
+
+	return 0;
+}
+
+/* Check that isl_ast_build_expr_from_set returns a valid expression
+ * for an empty set.  Note that isl_ast_build_expr_from_set getting
+ * called on an empty set probably indicates a bug in the caller.
+ */
+static int test_ast_build(isl_ctx *ctx)
+{
+	isl_set *set;
+	isl_ast_build *build;
+	isl_ast_expr *expr;
+
+	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+	build = isl_ast_build_from_context(set);
+
+	set = isl_set_empty(isl_space_params_alloc(ctx, 0));
+	expr = isl_ast_build_expr_from_set(build, set);
+
+	isl_ast_expr_free(expr);
+	isl_ast_build_free(build);
+
+	if (!expr)
+		return -1;
+
+	return 0;
+}
+
+/* Internal data structure for before_for and after_for callbacks.
+ *
+ * depth is the current depth
+ * before is the number of times before_for has been called
+ * after is the number of times after_for has been called
+ */
+struct isl_test_codegen_data {
+	int depth;
+	int before;
+	int after;
+};
+
+/* This function is called before each for loop in the AST generated
+ * from test_ast_gen1.
+ *
+ * Increment the number of calls and the depth.
+ * Check that the space returned by isl_ast_build_get_schedule_space
+ * matches the target space of the schedule returned by
+ * isl_ast_build_get_schedule.
+ * Return an isl_id that is checked by the corresponding call
+ * to after_for.
+ */
+static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
+	void *user)
+{
+	struct isl_test_codegen_data *data = user;
+	isl_ctx *ctx;
+	isl_space *space;
+	isl_union_map *schedule;
+	isl_union_set *uset;
+	isl_set *set;
+	int empty;
+	char name[] = "d0";
+
+	ctx = isl_ast_build_get_ctx(build);
+
+	if (data->before >= 3)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected number of for nodes", return NULL);
+	if (data->depth >= 2)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected depth", return NULL);
+
+	snprintf(name, sizeof(name), "d%d", data->depth);
+	data->before++;
+	data->depth++;
+
+	schedule = isl_ast_build_get_schedule(build);
+	uset = isl_union_map_range(schedule);
+	if (!uset)
+		return NULL;
+	if (isl_union_set_n_set(uset) != 1) {
+		isl_union_set_free(uset);
+		isl_die(ctx, isl_error_unknown,
+			"expecting single range space", return NULL);
+	}
+
+	space = isl_ast_build_get_schedule_space(build);
+	set = isl_union_set_extract_set(uset, space);
+	isl_union_set_free(uset);
+	empty = isl_set_is_empty(set);
+	isl_set_free(set);
+
+	if (empty < 0)
+		return NULL;
+	if (empty)
+		isl_die(ctx, isl_error_unknown,
+			"spaces don't match", return NULL);
+
+	return isl_id_alloc(ctx, name, NULL);
+}
+
+/* This function is called after each for loop in the AST generated
+ * from test_ast_gen1.
+ *
+ * Increment the number of calls and decrement the depth.
+ * Check that the annotation attached to the node matches
+ * the isl_id returned by the corresponding call to before_for.
+ */
+static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
+	__isl_keep isl_ast_build *build, void *user)
+{
+	struct isl_test_codegen_data *data = user;
+	isl_id *id;
+	const char *name;
+	int valid;
+
+	data->after++;
+	data->depth--;
+
+	if (data->after > data->before)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
+			"mismatch in number of for nodes",
+			return isl_ast_node_free(node));
+
+	id = isl_ast_node_get_annotation(node);
+	if (!id)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
+			"missing annotation", return isl_ast_node_free(node));
+
+	name = isl_id_get_name(id);
+	valid = name && atoi(name + 1) == data->depth;
+	isl_id_free(id);
+
+	if (!valid)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
+			"wrong annotation", return isl_ast_node_free(node));
+
+	return node;
+}
+
+/* Check that the before_each_for and after_each_for callbacks
+ * are called for each for loop in the generated code,
+ * that they are called in the right order and that the isl_id
+ * returned from the before_each_for callback is attached to
+ * the isl_ast_node passed to the corresponding after_each_for call.
+ */
+static int test_ast_gen1(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_union_map *schedule;
+	isl_ast_build *build;
+	isl_ast_node *tree;
+	struct isl_test_codegen_data data;
+
+	str = "[N] -> { : N >= 10 }";
+	set = isl_set_read_from_str(ctx, str);
+	str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
+		    "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
+	schedule = isl_union_map_read_from_str(ctx, str);
+
+	data.before = 0;
+	data.after = 0;
+	data.depth = 0;
+	build = isl_ast_build_from_context(set);
+	build = isl_ast_build_set_before_each_for(build,
+			&before_for, &data);
+	build = isl_ast_build_set_after_each_for(build,
+			&after_for, &data);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+	if (!tree)
+		return -1;
+
+	isl_ast_node_free(tree);
+
+	if (data.before != 3 || data.after != 3)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected number of for nodes", return -1);
+
+	return 0;
+}
+
+/* Check that the AST generator handles domains that are integrally disjoint
+ * but not ratinoally disjoint.
+ */
+static int test_ast_gen2(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_union_map *schedule;
+	isl_union_map *options;
+	isl_ast_build *build;
+	isl_ast_node *tree;
+
+	str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
+	schedule = isl_union_map_read_from_str(ctx, str);
+	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+	build = isl_ast_build_from_context(set);
+
+	str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
+	options = isl_union_map_read_from_str(ctx, str);
+	build = isl_ast_build_set_options(build, options);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+	if (!tree)
+		return -1;
+	isl_ast_node_free(tree);
+
+	return 0;
+}
+
+/* Increment *user on each call.
+ */
+static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
+	__isl_keep isl_ast_build *build, void *user)
+{
+	int *n = user;
+
+	(*n)++;
+
+	return node;
+}
+
+/* Test that unrolling tries to minimize the number of instances.
+ * In particular, for the schedule given below, make sure it generates
+ * 3 nodes (rather than 101).
+ */
+static int test_ast_gen3(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_union_map *schedule;
+	isl_union_map *options;
+	isl_ast_build *build;
+	isl_ast_node *tree;
+	int n_domain = 0;
+
+	str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
+	schedule = isl_union_map_read_from_str(ctx, str);
+	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+
+	str = "{ [i] -> unroll[0] }";
+	options = isl_union_map_read_from_str(ctx, str);
+
+	build = isl_ast_build_from_context(set);
+	build = isl_ast_build_set_options(build, options);
+	build = isl_ast_build_set_at_each_domain(build,
+			&count_domains, &n_domain);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+	if (!tree)
+		return -1;
+
+	isl_ast_node_free(tree);
+
+	if (n_domain != 3)
+		isl_die(ctx, isl_error_unknown,
+			"unexpected number of for nodes", return -1);
+
+	return 0;
+}
+
+/* Check that if the ast_build_exploit_nested_bounds options is set,
+ * we do not get an outer if node in the generated AST,
+ * while we do get such an outer if node if the options is not set.
+ */
+static int test_ast_gen4(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_union_map *schedule;
+	isl_ast_build *build;
+	isl_ast_node *tree;
+	enum isl_ast_node_type type;
+	int enb;
+
+	enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
+	str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
+
+	isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
+
+	schedule = isl_union_map_read_from_str(ctx, str);
+	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+	build = isl_ast_build_from_context(set);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+	if (!tree)
+		return -1;
+
+	type = isl_ast_node_get_type(tree);
+	isl_ast_node_free(tree);
+
+	if (type == isl_ast_node_if)
+		isl_die(ctx, isl_error_unknown,
+			"not expecting if node", return -1);
+
+	isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
+
+	schedule = isl_union_map_read_from_str(ctx, str);
+	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+	build = isl_ast_build_from_context(set);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+	if (!tree)
+		return -1;
+
+	type = isl_ast_node_get_type(tree);
+	isl_ast_node_free(tree);
+
+	if (type != isl_ast_node_if)
+		isl_die(ctx, isl_error_unknown,
+			"expecting if node", return -1);
+
+	isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
+
+	return 0;
+}
+
+/* This function is called for each leaf in the AST generated
+ * from test_ast_gen5.
+ *
+ * We finalize the AST generation by extending the outer schedule
+ * with a zero-dimensional schedule.  If this results in any for loops,
+ * then this means that we did not pass along enough information
+ * about the outer schedule to the inner AST generation.
+ */
+static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
+	void *user)
+{
+	isl_union_map *schedule, *extra;
+	isl_ast_node *tree;
+
+	schedule = isl_ast_build_get_schedule(build);
+	extra = isl_union_map_copy(schedule);
+	extra = isl_union_map_from_domain(isl_union_map_domain(extra));
+	schedule = isl_union_map_range_product(schedule, extra);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+
+	if (!tree)
+		return NULL;
+
+	if (isl_ast_node_get_type(tree) == isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
+			"code should not contain any for loop",
+			return isl_ast_node_free(tree));
+
+	return tree;
+}
+
+/* Check that we do not lose any information when going back and
+ * forth between internal and external schedule.
+ *
+ * In particular, we create an AST where we unroll the only
+ * non-constant dimension in the schedule.  We therefore do
+ * not expect any for loops in the AST.  However, older versions
+ * of isl would not pass along enough information about the outer
+ * schedule when performing an inner code generation from a create_leaf
+ * callback, resulting in the inner code generation producing a for loop.
+ */
+static int test_ast_gen5(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *set;
+	isl_union_map *schedule, *options;
+	isl_ast_build *build;
+	isl_ast_node *tree;
+
+	str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
+	schedule = isl_union_map_read_from_str(ctx, str);
+
+	str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
+				"4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
+	options = isl_union_map_read_from_str(ctx, str);
+
+	set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+	build = isl_ast_build_from_context(set);
+	build = isl_ast_build_set_options(build, options);
+        build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
+	tree = isl_ast_build_ast_from_schedule(build, schedule);
+	isl_ast_build_free(build);
+	isl_ast_node_free(tree);
+	if (!tree)
+		return -1;
+
+	return 0;
+}
+
+static int test_ast_gen(isl_ctx *ctx)
+{
+	if (test_ast_gen1(ctx) < 0)
+		return -1;
+	if (test_ast_gen2(ctx) < 0)
+		return -1;
+	if (test_ast_gen3(ctx) < 0)
+		return -1;
+	if (test_ast_gen4(ctx) < 0)
+		return -1;
+	if (test_ast_gen5(ctx) < 0)
+		return -1;
+	return 0;
+}
+
+/* Check if dropping output dimensions from an isl_pw_multi_aff
+ * works properly.
+ */
+static int test_pw_multi_aff(isl_ctx *ctx)
+{
+	const char *str;
+	isl_pw_multi_aff *pma1, *pma2;
+	int equal;
+
+	str = "{ [i,j] -> [i+j, 4i-j] }";
+	pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
+	str = "{ [i,j] -> [4i-j] }";
+	pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
+
+	pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
+
+	equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
+
+	isl_pw_multi_aff_free(pma1);
+	isl_pw_multi_aff_free(pma2);
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"expressions not equal", return -1);
+
+	return 0;
+}
+
+/* Check that we can properly parse multi piecewise affine expressions
+ * where the piecewise affine expressions have different domains.
+ */
+static int test_multi_pw_aff(isl_ctx *ctx)
+{
+	const char *str;
+	isl_set *dom, *dom2;
+	isl_multi_pw_aff *mpa1, *mpa2;
+	isl_pw_aff *pa;
+	int equal;
+	int equal_domain;
+
+	mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
+	dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
+	mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
+	mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
+	mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
+	str = "{ [i] -> [(i : i > 0), 2i] }";
+	mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
+
+	equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
+
+	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
+	dom = isl_pw_aff_domain(pa);
+	pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
+	dom2 = isl_pw_aff_domain(pa);
+	equal_domain = isl_set_is_equal(dom, dom2);
+
+	isl_set_free(dom);
+	isl_set_free(dom2);
+	isl_multi_pw_aff_free(mpa1);
+	isl_multi_pw_aff_free(mpa2);
+
+	if (equal < 0)
+		return -1;
+	if (!equal)
+		isl_die(ctx, isl_error_unknown,
+			"expressions not equal", return -1);
+
+	if (equal_domain < 0)
+		return -1;
+	if (equal_domain)
+		isl_die(ctx, isl_error_unknown,
+			"domains unexpectedly equal", return -1);
+
+	return 0;
+}
+
+/* This is a regression test for a bug where isl_basic_map_simplify
+ * would end up in an infinite loop.  In particular, we construct
+ * an empty basic set that is not obviously empty.
+ * isl_basic_set_is_empty marks the basic set as empty.
+ * After projecting out i3, the variable can be dropped completely,
+ * but isl_basic_map_simplify refrains from doing so if the basic set
+ * is empty and would end up in an infinite loop if it didn't test
+ * explicitly for empty basic maps in the outer loop.
+ */
+static int test_simplify(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_set *bset;
+	int empty;
+
+	str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
+		"i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
+		"25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
+		"i3 >= i2 }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	empty = isl_basic_set_is_empty(bset);
+	bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
+	isl_basic_set_free(bset);
+	if (!bset)
+		return -1;
+	if (!empty)
+		isl_die(ctx, isl_error_unknown,
+			"basic set should be empty", return -1);
+
+	return 0;
+}
+
+/* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
+ * with gbr context would fail to disable the use of the shifted tableau
+ * when transferring equalities for the input to the context, resulting
+ * in invalid sample values.
+ */
+static int test_partial_lexmin(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_set *bset;
+	isl_basic_map *bmap;
+	isl_map *map;
+
+	str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
+	bmap = isl_basic_map_read_from_str(ctx, str);
+	str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
+	isl_map_free(map);
+
+	if (!map)
+		return -1;
+
+	return 0;
+}
+
+/* Check that the variable compression performed on the existentially
+ * quantified variables inside isl_basic_set_compute_divs is not confused
+ * by the implicit equalities among the parameters.
+ */
+static int test_compute_divs(isl_ctx *ctx)
+{
+	const char *str;
+	isl_basic_set *bset;
+	isl_set *set;
+
+	str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
+		"b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
+		"2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
+		"32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
+	bset = isl_basic_set_read_from_str(ctx, str);
+	set = isl_basic_set_compute_divs(bset);
+	isl_set_free(set);
+	if (!set)
+		return -1;
+
+	return 0;
+}
+
+struct {
+	const char *set;
+	const char *dual;
+} coef_tests[] = {
+	{ "{ rat: [i] : 0 <= i <= 10 }",
+	  "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
+	{ "{ rat: [i] : FALSE }",
+	  "{ rat: coefficients[[cst] -> [a]] }" },
+	{ "{ rat: [i] : }",
+	  "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
+};
+
+struct {
+	const char *set;
+	const char *dual;
+} sol_tests[] = {
+	{ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
+	  "{ rat: [i] : 0 <= i <= 10 }" },
+	{ "{ rat: coefficients[[cst] -> [a]] : FALSE }",
+	  "{ rat: [i] }" },
+	{ "{ rat: coefficients[[cst] -> [a]] }",
+	  "{ rat: [i] : FALSE }" },
+};
+
+/* Test the basic functionality of isl_basic_set_coefficients and
+ * isl_basic_set_solutions.
+ */
+static int test_dual(isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
+		int equal;
+		isl_basic_set *bset1, *bset2;
+
+		bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
+		bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
+		bset1 = isl_basic_set_coefficients(bset1);
+		equal = isl_basic_set_is_equal(bset1, bset2);
+		isl_basic_set_free(bset1);
+		isl_basic_set_free(bset2);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"incorrect dual", return -1);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
+		int equal;
+		isl_basic_set *bset1, *bset2;
+
+		bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
+		bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
+		bset1 = isl_basic_set_solutions(bset1);
+		equal = isl_basic_set_is_equal(bset1, bset2);
+		isl_basic_set_free(bset1);
+		isl_basic_set_free(bset2);
+		if (equal < 0)
+			return -1;
+		if (!equal)
+			isl_die(ctx, isl_error_unknown,
+				"incorrect dual", return -1);
+	}
+
+	return 0;
+}
+
+struct {
+	const char *name;
+	int (*fn)(isl_ctx *ctx);
+} tests [] = {
+	{ "dual", &test_dual },
+	{ "dependence analysis", &test_flow },
+	{ "val", &test_val },
+	{ "compute divs", &test_compute_divs },
+	{ "partial lexmin", &test_partial_lexmin },
+	{ "simplify", &test_simplify },
+	{ "curry", &test_curry },
+	{ "piecewise multi affine expressions", &test_pw_multi_aff },
+	{ "multi piecewise affine expressions", &test_multi_pw_aff },
+	{ "conversion", &test_conversion },
+	{ "list", &test_list },
+	{ "align parameters", &test_align_parameters },
+	{ "preimage", &test_preimage },
+	{ "pullback", &test_pullback },
+	{ "AST", &test_ast },
+	{ "AST build", &test_ast_build },
+	{ "AST generation", &test_ast_gen },
+	{ "eliminate", &test_eliminate },
+	{ "residue class", &test_residue_class },
+	{ "div", &test_div },
+	{ "slice", &test_slice },
+	{ "fixed power", &test_fixed_power },
+	{ "sample", &test_sample },
+	{ "output", &test_output },
+	{ "vertices", &test_vertices },
+	{ "fixed", &test_fixed },
+	{ "equal", &test_equal },
+	{ "disjoint", &test_disjoint },
+	{ "product", &test_product },
+	{ "dim_max", &test_dim_max },
+	{ "affine", &test_aff },
+	{ "injective", &test_injective },
+	{ "schedule", &test_schedule },
+	{ "union_pw", &test_union_pw },
+	{ "parse", &test_parse },
+	{ "single-valued", &test_sv },
+	{ "affine hull", &test_affine_hull },
+	{ "coalesce", &test_coalesce },
+	{ "factorize", &test_factorize },
+	{ "subset", &test_subset },
+	{ "subtract", &test_subtract },
+	{ "lexmin", &test_lexmin },
+	{ "min", &test_min },
+	{ "gist", &test_gist },
+	{ "piecewise quasi-polynomials", &test_pwqp },
+};
+
+int main(int argc, char **argv)
+{
+	int i;
+	struct isl_ctx *ctx;
+	struct isl_options *options;
+
+	srcdir = getenv("srcdir");
+	assert(srcdir);
+
+	options = isl_options_new_with_defaults();
+	assert(options);
+	argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
+
+	ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
+	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+		printf("%s\n", tests[i].name);
+		if (tests[i].fn(ctx) < 0)
+			goto error;
+	}
+	test_lift(ctx);
+	test_bound(ctx);
+	test_union(ctx);
+	test_split_periods(ctx);
+	test_lex(ctx);
+	test_bijective(ctx);
+	test_dep(ctx);
+	test_read(ctx);
+	test_bounded(ctx);
+	test_construction(ctx);
+	test_dim(ctx);
+	test_application(ctx);
+	test_convex_hull(ctx);
+	test_closure(ctx);
+	isl_ctx_free(ctx);
+	return 0;
+error:
+	isl_ctx_free(ctx);
+	return -1;
+}

Added: polly/trunk/lib/External/isl/isl_transitive_closure.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_transitive_closure.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_transitive_closure.c (added)
+++ polly/trunk/lib/External/isl/isl_transitive_closure.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2981 @@
+/*
+ * Copyright 2010      INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France 
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/map.h>
+#include <isl_seq.h>
+#include <isl_space_private.h>
+#include <isl_lp_private.h>
+#include <isl/union_map.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_options_private.h>
+#include <isl_tarjan.h>
+
+int isl_map_is_transitively_closed(__isl_keep isl_map *map)
+{
+	isl_map *map2;
+	int closed;
+
+	map2 = isl_map_apply_range(isl_map_copy(map), isl_map_copy(map));
+	closed = isl_map_is_subset(map2, map);
+	isl_map_free(map2);
+
+	return closed;
+}
+
+int isl_union_map_is_transitively_closed(__isl_keep isl_union_map *umap)
+{
+	isl_union_map *umap2;
+	int closed;
+
+	umap2 = isl_union_map_apply_range(isl_union_map_copy(umap),
+					  isl_union_map_copy(umap));
+	closed = isl_union_map_is_subset(umap2, umap);
+	isl_union_map_free(umap2);
+
+	return closed;
+}
+ 
+/* Given a map that represents a path with the length of the path
+ * encoded as the difference between the last output coordindate
+ * and the last input coordinate, set this length to either
+ * exactly "length" (if "exactly" is set) or at least "length"
+ * (if "exactly" is not set).
+ */
+static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
+	int exactly, int length)
+{
+	isl_space *dim;
+	struct isl_basic_map *bmap;
+	unsigned d;
+	unsigned nparam;
+	int k;
+	isl_int *c;
+
+	if (!map)
+		return NULL;
+
+	dim = isl_map_get_space(map);
+	d = isl_space_dim(dim, isl_dim_in);
+	nparam = isl_space_dim(dim, isl_dim_param);
+	bmap = isl_basic_map_alloc_space(dim, 0, 1, 1);
+	if (exactly) {
+		k = isl_basic_map_alloc_equality(bmap);
+		c = bmap->eq[k];
+	} else {
+		k = isl_basic_map_alloc_inequality(bmap);
+		c = bmap->ineq[k];
+	}
+	if (k < 0)
+		goto error;
+	isl_seq_clr(c, 1 + isl_basic_map_total_dim(bmap));
+	isl_int_set_si(c[0], -length);
+	isl_int_set_si(c[1 + nparam + d - 1], -1);
+	isl_int_set_si(c[1 + nparam + d + d - 1], 1);
+
+	bmap = isl_basic_map_finalize(bmap);
+	map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+	return map;
+error:
+	isl_basic_map_free(bmap);
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Check whether the overapproximation of the power of "map" is exactly
+ * the power of "map".  Let R be "map" and A_k the overapproximation.
+ * The approximation is exact if
+ *
+ *	A_1 = R
+ *	A_k = A_{k-1} \circ R			k >= 2
+ *
+ * Since A_k is known to be an overapproximation, we only need to check
+ *
+ *	A_1 \subset R
+ *	A_k \subset A_{k-1} \circ R		k >= 2
+ *
+ * In practice, "app" has an extra input and output coordinate
+ * to encode the length of the path.  So, we first need to add
+ * this coordinate to "map" and set the length of the path to
+ * one.
+ */
+static int check_power_exactness(__isl_take isl_map *map,
+	__isl_take isl_map *app)
+{
+	int exact;
+	isl_map *app_1;
+	isl_map *app_2;
+
+	map = isl_map_add_dims(map, isl_dim_in, 1);
+	map = isl_map_add_dims(map, isl_dim_out, 1);
+	map = set_path_length(map, 1, 1);
+
+	app_1 = set_path_length(isl_map_copy(app), 1, 1);
+
+	exact = isl_map_is_subset(app_1, map);
+	isl_map_free(app_1);
+
+	if (!exact || exact < 0) {
+		isl_map_free(app);
+		isl_map_free(map);
+		return exact;
+	}
+
+	app_1 = set_path_length(isl_map_copy(app), 0, 1);
+	app_2 = set_path_length(app, 0, 2);
+	app_1 = isl_map_apply_range(map, app_1);
+
+	exact = isl_map_is_subset(app_2, app_1);
+
+	isl_map_free(app_1);
+	isl_map_free(app_2);
+
+	return exact;
+}
+
+/* Check whether the overapproximation of the power of "map" is exactly
+ * the power of "map", possibly after projecting out the power (if "project"
+ * is set).
+ *
+ * If "project" is set and if "steps" can only result in acyclic paths,
+ * then we check
+ *
+ *	A = R \cup (A \circ R)
+ *
+ * where A is the overapproximation with the power projected out, i.e.,
+ * an overapproximation of the transitive closure.
+ * More specifically, since A is known to be an overapproximation, we check
+ *
+ *	A \subset R \cup (A \circ R)
+ *
+ * Otherwise, we check if the power is exact.
+ *
+ * Note that "app" has an extra input and output coordinate to encode
+ * the length of the part.  If we are only interested in the transitive
+ * closure, then we can simply project out these coordinates first.
+ */
+static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
+	int project)
+{
+	isl_map *test;
+	int exact;
+	unsigned d;
+
+	if (!project)
+		return check_power_exactness(map, app);
+
+	d = isl_map_dim(map, isl_dim_in);
+	app = set_path_length(app, 0, 1);
+	app = isl_map_project_out(app, isl_dim_in, d, 1);
+	app = isl_map_project_out(app, isl_dim_out, d, 1);
+
+	app = isl_map_reset_space(app, isl_map_get_space(map));
+
+	test = isl_map_apply_range(isl_map_copy(map), isl_map_copy(app));
+	test = isl_map_union(test, isl_map_copy(map));
+
+	exact = isl_map_is_subset(app, test);
+
+	isl_map_free(app);
+	isl_map_free(test);
+
+	isl_map_free(map);
+
+	return exact;
+}
+
+/*
+ * The transitive closure implementation is based on the paper
+ * "Computing the Transitive Closure of a Union of Affine Integer
+ * Tuple Relations" by Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and
+ * Albert Cohen.
+ */
+
+/* Given a set of n offsets v_i (the rows of "steps"), construct a relation
+ * of the given dimension specification (Z^{n+1} -> Z^{n+1})
+ * that maps an element x to any element that can be reached
+ * by taking a non-negative number of steps along any of
+ * the extended offsets v'_i = [v_i 1].
+ * That is, construct
+ *
+ * { [x] -> [y] : exists k_i >= 0, y = x + \sum_i k_i v'_i }
+ *
+ * For any element in this relation, the number of steps taken
+ * is equal to the difference in the final coordinates.
+ */
+static __isl_give isl_map *path_along_steps(__isl_take isl_space *dim,
+	__isl_keep isl_mat *steps)
+{
+	int i, j, k;
+	struct isl_basic_map *path = NULL;
+	unsigned d;
+	unsigned n;
+	unsigned nparam;
+
+	if (!dim || !steps)
+		goto error;
+
+	d = isl_space_dim(dim, isl_dim_in);
+	n = steps->n_row;
+	nparam = isl_space_dim(dim, isl_dim_param);
+
+	path = isl_basic_map_alloc_space(isl_space_copy(dim), n, d, n);
+
+	for (i = 0; i < n; ++i) {
+		k = isl_basic_map_alloc_div(path);
+		if (k < 0)
+			goto error;
+		isl_assert(steps->ctx, i == k, goto error);
+		isl_int_set_si(path->div[k][0], 0);
+	}
+
+	for (i = 0; i < d; ++i) {
+		k = isl_basic_map_alloc_equality(path);
+		if (k < 0)
+			goto error;
+		isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
+		isl_int_set_si(path->eq[k][1 + nparam + i], 1);
+		isl_int_set_si(path->eq[k][1 + nparam + d + i], -1);
+		if (i == d - 1)
+			for (j = 0; j < n; ++j)
+				isl_int_set_si(path->eq[k][1 + nparam + 2 * d + j], 1);
+		else
+			for (j = 0; j < n; ++j)
+				isl_int_set(path->eq[k][1 + nparam + 2 * d + j],
+					    steps->row[j][i]);
+	}
+
+	for (i = 0; i < n; ++i) {
+		k = isl_basic_map_alloc_inequality(path);
+		if (k < 0)
+			goto error;
+		isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
+		isl_int_set_si(path->ineq[k][1 + nparam + 2 * d + i], 1);
+	}
+
+	isl_space_free(dim);
+
+	path = isl_basic_map_simplify(path);
+	path = isl_basic_map_finalize(path);
+	return isl_map_from_basic_map(path);
+error:
+	isl_space_free(dim);
+	isl_basic_map_free(path);
+	return NULL;
+}
+
+#define IMPURE		0
+#define PURE_PARAM	1
+#define PURE_VAR	2
+#define MIXED		3
+
+/* Check whether the parametric constant term of constraint c is never
+ * positive in "bset".
+ */
+static int parametric_constant_never_positive(__isl_keep isl_basic_set *bset,
+	isl_int *c, int *div_purity)
+{
+	unsigned d;
+	unsigned n_div;
+	unsigned nparam;
+	int i;
+	int k;
+	int empty;
+
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	d = isl_basic_set_dim(bset, isl_dim_set);
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+	bset = isl_basic_set_copy(bset);
+	bset = isl_basic_set_cow(bset);
+	bset = isl_basic_set_extend_constraints(bset, 0, 1);
+	k = isl_basic_set_alloc_inequality(bset);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
+	isl_seq_cpy(bset->ineq[k], c, 1 + nparam);
+	for (i = 0; i < n_div; ++i) {
+		if (div_purity[i] != PURE_PARAM)
+			continue;
+		isl_int_set(bset->ineq[k][1 + nparam + d + i],
+			    c[1 + nparam + d + i]);
+	}
+	isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
+	empty = isl_basic_set_is_empty(bset);
+	isl_basic_set_free(bset);
+
+	return empty;
+error:
+	isl_basic_set_free(bset);
+	return -1;
+}
+
+/* Return PURE_PARAM if only the coefficients of the parameters are non-zero.
+ * Return PURE_VAR if only the coefficients of the set variables are non-zero.
+ * Return MIXED if only the coefficients of the parameters and the set
+ * 	variables are non-zero and if moreover the parametric constant
+ * 	can never attain positive values.
+ * Return IMPURE otherwise.
+ */
+static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
+	int eq)
+{
+	unsigned d;
+	unsigned n_div;
+	unsigned nparam;
+	int empty;
+	int i;
+	int p = 0, v = 0;
+
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	d = isl_basic_set_dim(bset, isl_dim_set);
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+	for (i = 0; i < n_div; ++i) {
+		if (isl_int_is_zero(c[1 + nparam + d + i]))
+			continue;
+		switch (div_purity[i]) {
+		case PURE_PARAM: p = 1; break;
+		case PURE_VAR: v = 1; break;
+		default: return IMPURE;
+		}
+	}
+	if (!p && isl_seq_first_non_zero(c + 1, nparam) == -1)
+		return PURE_VAR;
+	if (!v && isl_seq_first_non_zero(c + 1 + nparam, d) == -1)
+		return PURE_PARAM;
+
+	empty = parametric_constant_never_positive(bset, c, div_purity);
+	if (eq && empty >= 0 && !empty) {
+		isl_seq_neg(c, c, 1 + nparam + d + n_div);
+		empty = parametric_constant_never_positive(bset, c, div_purity);
+	}
+
+	return empty < 0 ? -1 : empty ? MIXED : IMPURE;
+}
+
+/* Return an array of integers indicating the type of each div in bset.
+ * If the div is (recursively) defined in terms of only the parameters,
+ * then the type is PURE_PARAM.
+ * If the div is (recursively) defined in terms of only the set variables,
+ * then the type is PURE_VAR.
+ * Otherwise, the type is IMPURE.
+ */
+static __isl_give int *get_div_purity(__isl_keep isl_basic_set *bset)
+{
+	int i, j;
+	int *div_purity;
+	unsigned d;
+	unsigned n_div;
+	unsigned nparam;
+
+	if (!bset)
+		return NULL;
+
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+	d = isl_basic_set_dim(bset, isl_dim_set);
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+	div_purity = isl_alloc_array(bset->ctx, int, n_div);
+	if (n_div && !div_purity)
+		return NULL;
+
+	for (i = 0; i < bset->n_div; ++i) {
+		int p = 0, v = 0;
+		if (isl_int_is_zero(bset->div[i][0])) {
+			div_purity[i] = IMPURE;
+			continue;
+		}
+		if (isl_seq_first_non_zero(bset->div[i] + 2, nparam) != -1)
+			p = 1;
+		if (isl_seq_first_non_zero(bset->div[i] + 2 + nparam, d) != -1)
+			v = 1;
+		for (j = 0; j < i; ++j) {
+			if (isl_int_is_zero(bset->div[i][2 + nparam + d + j]))
+				continue;
+			switch (div_purity[j]) {
+			case PURE_PARAM: p = 1; break;
+			case PURE_VAR: v = 1; break;
+			default: p = v = 1; break;
+			}
+		}
+		div_purity[i] = v ? p ? IMPURE : PURE_VAR : PURE_PARAM;
+	}
+
+	return div_purity;
+}
+
+/* Given a path with the as yet unconstrained length at position "pos",
+ * check if setting the length to zero results in only the identity
+ * mapping.
+ */
+static int empty_path_is_identity(__isl_keep isl_basic_map *path, unsigned pos)
+{
+	isl_basic_map *test = NULL;
+	isl_basic_map *id = NULL;
+	int k;
+	int is_id;
+
+	test = isl_basic_map_copy(path);
+	test = isl_basic_map_extend_constraints(test, 1, 0);
+	k = isl_basic_map_alloc_equality(test);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(test->eq[k], 1 + isl_basic_map_total_dim(test));
+	isl_int_set_si(test->eq[k][pos], 1);
+	id = isl_basic_map_identity(isl_basic_map_get_space(path));
+	is_id = isl_basic_map_is_equal(test, id);
+	isl_basic_map_free(test);
+	isl_basic_map_free(id);
+	return is_id;
+error:
+	isl_basic_map_free(test);
+	return -1;
+}
+
+/* If any of the constraints is found to be impure then this function
+ * sets *impurity to 1.
+ *
+ * If impurity is NULL then we are dealing with a non-parametric set
+ * and so the constraints are obviously PURE_VAR.
+ */
+static __isl_give isl_basic_map *add_delta_constraints(
+	__isl_take isl_basic_map *path,
+	__isl_keep isl_basic_set *delta, unsigned off, unsigned nparam,
+	unsigned d, int *div_purity, int eq, int *impurity)
+{
+	int i, k;
+	int n = eq ? delta->n_eq : delta->n_ineq;
+	isl_int **delta_c = eq ? delta->eq : delta->ineq;
+	unsigned n_div;
+
+	n_div = isl_basic_set_dim(delta, isl_dim_div);
+
+	for (i = 0; i < n; ++i) {
+		isl_int *path_c;
+		int p = PURE_VAR;
+		if (impurity)
+			p = purity(delta, delta_c[i], div_purity, eq);
+		if (p < 0)
+			goto error;
+		if (p != PURE_VAR && p != PURE_PARAM && !*impurity)
+			*impurity = 1;
+		if (p == IMPURE)
+			continue;
+		if (eq && p != MIXED) {
+			k = isl_basic_map_alloc_equality(path);
+			path_c = path->eq[k];
+		} else {
+			k = isl_basic_map_alloc_inequality(path);
+			path_c = path->ineq[k];
+		}
+		if (k < 0)
+			goto error;
+		isl_seq_clr(path_c, 1 + isl_basic_map_total_dim(path));
+		if (p == PURE_VAR) {
+			isl_seq_cpy(path_c + off,
+				    delta_c[i] + 1 + nparam, d);
+			isl_int_set(path_c[off + d], delta_c[i][0]);
+		} else if (p == PURE_PARAM) {
+			isl_seq_cpy(path_c, delta_c[i], 1 + nparam);
+		} else {
+			isl_seq_cpy(path_c + off,
+				    delta_c[i] + 1 + nparam, d);
+			isl_seq_cpy(path_c, delta_c[i], 1 + nparam);
+		}
+		isl_seq_cpy(path_c + off - n_div,
+			    delta_c[i] + 1 + nparam + d, n_div);
+	}
+
+	return path;
+error:
+	isl_basic_map_free(path);
+	return NULL;
+}
+
+/* Given a set of offsets "delta", construct a relation of the
+ * given dimension specification (Z^{n+1} -> Z^{n+1}) that
+ * is an overapproximation of the relations that
+ * maps an element x to any element that can be reached
+ * by taking a non-negative number of steps along any of
+ * the elements in "delta".
+ * That is, construct an approximation of
+ *
+ *	{ [x] -> [y] : exists f \in \delta, k \in Z :
+ *					y = x + k [f, 1] and k >= 0 }
+ *
+ * For any element in this relation, the number of steps taken
+ * is equal to the difference in the final coordinates.
+ *
+ * In particular, let delta be defined as
+ *
+ *	\delta = [p] -> { [x] : A x + a >= 0 and B p + b >= 0 and
+ *				C x + C'p + c >= 0 and
+ *				D x + D'p + d >= 0 }
+ *
+ * where the constraints C x + C'p + c >= 0 are such that the parametric
+ * constant term of each constraint j, "C_j x + C'_j p + c_j",
+ * can never attain positive values, then the relation is constructed as
+ *
+ *	{ [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
+ *			A f + k a >= 0 and B p + b >= 0 and
+ *			C f + C'p + c >= 0 and k >= 1 }
+ *	union { [x] -> [x] }
+ *
+ * If the zero-length paths happen to correspond exactly to the identity
+ * mapping, then we return
+ *
+ *	{ [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
+ *			A f + k a >= 0 and B p + b >= 0 and
+ *			C f + C'p + c >= 0 and k >= 0 }
+ *
+ * instead.
+ *
+ * Existentially quantified variables in \delta are handled by
+ * classifying them as independent of the parameters, purely
+ * parameter dependent and others.  Constraints containing
+ * any of the other existentially quantified variables are removed.
+ * This is safe, but leads to an additional overapproximation.
+ *
+ * If there are any impure constraints, then we also eliminate
+ * the parameters from \delta, resulting in a set
+ *
+ *	\delta' = { [x] : E x + e >= 0 }
+ *
+ * and add the constraints
+ *
+ *			E f + k e >= 0
+ *
+ * to the constructed relation.
+ */
+static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
+	__isl_take isl_basic_set *delta)
+{
+	isl_basic_map *path = NULL;
+	unsigned d;
+	unsigned n_div;
+	unsigned nparam;
+	unsigned off;
+	int i, k;
+	int is_id;
+	int *div_purity = NULL;
+	int impurity = 0;
+
+	if (!delta)
+		goto error;
+	n_div = isl_basic_set_dim(delta, isl_dim_div);
+	d = isl_basic_set_dim(delta, isl_dim_set);
+	nparam = isl_basic_set_dim(delta, isl_dim_param);
+	path = isl_basic_map_alloc_space(isl_space_copy(dim), n_div + d + 1,
+			d + 1 + delta->n_eq, delta->n_eq + delta->n_ineq + 1);
+	off = 1 + nparam + 2 * (d + 1) + n_div;
+
+	for (i = 0; i < n_div + d + 1; ++i) {
+		k = isl_basic_map_alloc_div(path);
+		if (k < 0)
+			goto error;
+		isl_int_set_si(path->div[k][0], 0);
+	}
+
+	for (i = 0; i < d + 1; ++i) {
+		k = isl_basic_map_alloc_equality(path);
+		if (k < 0)
+			goto error;
+		isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
+		isl_int_set_si(path->eq[k][1 + nparam + i], 1);
+		isl_int_set_si(path->eq[k][1 + nparam + d + 1 + i], -1);
+		isl_int_set_si(path->eq[k][off + i], 1);
+	}
+
+	div_purity = get_div_purity(delta);
+	if (n_div && !div_purity)
+		goto error;
+
+	path = add_delta_constraints(path, delta, off, nparam, d,
+				     div_purity, 1, &impurity);
+	path = add_delta_constraints(path, delta, off, nparam, d,
+				     div_purity, 0, &impurity);
+	if (impurity) {
+		isl_space *dim = isl_basic_set_get_space(delta);
+		delta = isl_basic_set_project_out(delta,
+						  isl_dim_param, 0, nparam);
+		delta = isl_basic_set_add_dims(delta, isl_dim_param, nparam);
+		delta = isl_basic_set_reset_space(delta, dim);
+		if (!delta)
+			goto error;
+		path = isl_basic_map_extend_constraints(path, delta->n_eq,
+							delta->n_ineq + 1);
+		path = add_delta_constraints(path, delta, off, nparam, d,
+					     NULL, 1, NULL);
+		path = add_delta_constraints(path, delta, off, nparam, d,
+					     NULL, 0, NULL);
+		path = isl_basic_map_gauss(path, NULL);
+	}
+
+	is_id = empty_path_is_identity(path, off + d);
+	if (is_id < 0)
+		goto error;
+
+	k = isl_basic_map_alloc_inequality(path);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
+	if (!is_id)
+		isl_int_set_si(path->ineq[k][0], -1);
+	isl_int_set_si(path->ineq[k][off + d], 1);
+			
+	free(div_purity);
+	isl_basic_set_free(delta);
+	path = isl_basic_map_finalize(path);
+	if (is_id) {
+		isl_space_free(dim);
+		return isl_map_from_basic_map(path);
+	}
+	return isl_basic_map_union(path, isl_basic_map_identity(dim));
+error:
+	free(div_purity);
+	isl_space_free(dim);
+	isl_basic_set_free(delta);
+	isl_basic_map_free(path);
+	return NULL;
+}
+
+/* Given a dimension specification Z^{n+1} -> Z^{n+1} and a parameter "param",
+ * construct a map that equates the parameter to the difference
+ * in the final coordinates and imposes that this difference is positive.
+ * That is, construct
+ *
+ *	{ [x,x_s] -> [y,y_s] : k = y_s - x_s > 0 }
+ */
+static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_space *dim,
+	unsigned param)
+{
+	struct isl_basic_map *bmap;
+	unsigned d;
+	unsigned nparam;
+	int k;
+
+	d = isl_space_dim(dim, isl_dim_in);
+	nparam = isl_space_dim(dim, isl_dim_param);
+	bmap = isl_basic_map_alloc_space(dim, 0, 1, 1);
+	k = isl_basic_map_alloc_equality(bmap);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(bmap->eq[k], 1 + isl_basic_map_total_dim(bmap));
+	isl_int_set_si(bmap->eq[k][1 + param], -1);
+	isl_int_set_si(bmap->eq[k][1 + nparam + d - 1], -1);
+	isl_int_set_si(bmap->eq[k][1 + nparam + d + d - 1], 1);
+
+	k = isl_basic_map_alloc_inequality(bmap);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(bmap->ineq[k], 1 + isl_basic_map_total_dim(bmap));
+	isl_int_set_si(bmap->ineq[k][1 + param], 1);
+	isl_int_set_si(bmap->ineq[k][0], -1);
+
+	bmap = isl_basic_map_finalize(bmap);
+	return isl_map_from_basic_map(bmap);
+error:
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Check whether "path" is acyclic, where the last coordinates of domain
+ * and range of path encode the number of steps taken.
+ * That is, check whether
+ *
+ *	{ d | d = y - x and (x,y) in path }
+ *
+ * does not contain any element with positive last coordinate (positive length)
+ * and zero remaining coordinates (cycle).
+ */
+static int is_acyclic(__isl_take isl_map *path)
+{
+	int i;
+	int acyclic;
+	unsigned dim;
+	struct isl_set *delta;
+
+	delta = isl_map_deltas(path);
+	dim = isl_set_dim(delta, isl_dim_set);
+	for (i = 0; i < dim; ++i) {
+		if (i == dim -1)
+			delta = isl_set_lower_bound_si(delta, isl_dim_set, i, 1);
+		else
+			delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
+	}
+
+	acyclic = isl_set_is_empty(delta);
+	isl_set_free(delta);
+
+	return acyclic;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
+ * and a dimension specification (Z^{n+1} -> Z^{n+1}),
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the space D \times Z to another
+ * element from the same space, such that the first n coordinates of the
+ * difference between them is a sum of differences between images
+ * and pre-images in one of the R_i and such that the last coordinate
+ * is equal to the number of steps taken.
+ * That is, let
+ *
+ *	\Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ *	{ (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ *				d = (\sum_i k_i \delta_i, \sum_i k_i) }
+ *
+ * The elements of the singleton \Delta_i's are collected as the
+ * rows of the steps matrix.  For all these \Delta_i's together,
+ * a single path is constructed.
+ * For each of the other \Delta_i's, we compute an overapproximation
+ * of the paths along elements of \Delta_i.
+ * Since each of these paths performs an addition, composition is
+ * symmetric and we can simply compose all resulting paths in any order.
+ */
+static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *project)
+{
+	struct isl_mat *steps = NULL;
+	struct isl_map *path = NULL;
+	unsigned d;
+	int i, j, n;
+
+	d = isl_map_dim(map, isl_dim_in);
+
+	path = isl_map_identity(isl_space_copy(dim));
+
+	steps = isl_mat_alloc(map->ctx, map->n, d);
+	if (!steps)
+		goto error;
+
+	n = 0;
+	for (i = 0; i < map->n; ++i) {
+		struct isl_basic_set *delta;
+
+		delta = isl_basic_map_deltas(isl_basic_map_copy(map->p[i]));
+
+		for (j = 0; j < d; ++j) {
+			int fixed;
+
+			fixed = isl_basic_set_plain_dim_is_fixed(delta, j,
+							    &steps->row[n][j]);
+			if (fixed < 0) {
+				isl_basic_set_free(delta);
+				goto error;
+			}
+			if (!fixed)
+				break;
+		}
+
+
+		if (j < d) {
+			path = isl_map_apply_range(path,
+				path_along_delta(isl_space_copy(dim), delta));
+			path = isl_map_coalesce(path);
+		} else {
+			isl_basic_set_free(delta);
+			++n;
+		}
+	}
+
+	if (n > 0) {
+		steps->n_row = n;
+		path = isl_map_apply_range(path,
+				path_along_steps(isl_space_copy(dim), steps));
+	}
+
+	if (project && *project) {
+		*project = is_acyclic(isl_map_copy(path));
+		if (*project < 0)
+			goto error;
+	}
+
+	isl_space_free(dim);
+	isl_mat_free(steps);
+	return path;
+error:
+	isl_space_free(dim);
+	isl_mat_free(steps);
+	isl_map_free(path);
+	return NULL;
+}
+
+static int isl_set_overlaps(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+	isl_set *i;
+	int no_overlap;
+
+	if (!isl_space_tuple_is_equal(set1->dim, isl_dim_set,
+					set2->dim, isl_dim_set))
+		return 0;
+
+	i = isl_set_intersect(isl_set_copy(set1), isl_set_copy(set2));
+	no_overlap = isl_set_is_empty(i);
+	isl_set_free(i);
+
+	return no_overlap < 0 ? -1 : !no_overlap;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
+ * and a dimension specification (Z^{n+1} -> Z^{n+1}),
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the dom R \times Z to an
+ * element from ran R \times Z, such that the first n coordinates of the
+ * difference between them is a sum of differences between images
+ * and pre-images in one of the R_i and such that the last coordinate
+ * is equal to the number of steps taken.
+ * That is, let
+ *
+ *	\Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ *	{ (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ *				d = (\sum_i k_i \delta_i, \sum_i k_i) and
+ *				x in dom R and x + d in ran R and
+ *				\sum_i k_i >= 1 }
+ */
+static __isl_give isl_map *construct_component(__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *exact, int project)
+{
+	struct isl_set *domain = NULL;
+	struct isl_set *range = NULL;
+	struct isl_map *app = NULL;
+	struct isl_map *path = NULL;
+
+	domain = isl_map_domain(isl_map_copy(map));
+	domain = isl_set_coalesce(domain);
+	range = isl_map_range(isl_map_copy(map));
+	range = isl_set_coalesce(range);
+	if (!isl_set_overlaps(domain, range)) {
+		isl_set_free(domain);
+		isl_set_free(range);
+		isl_space_free(dim);
+
+		map = isl_map_copy(map);
+		map = isl_map_add_dims(map, isl_dim_in, 1);
+		map = isl_map_add_dims(map, isl_dim_out, 1);
+		map = set_path_length(map, 1, 1);
+		return map;
+	}
+	app = isl_map_from_domain_and_range(domain, range);
+	app = isl_map_add_dims(app, isl_dim_in, 1);
+	app = isl_map_add_dims(app, isl_dim_out, 1);
+
+	path = construct_extended_path(isl_space_copy(dim), map,
+					exact && *exact ? &project : NULL);
+	app = isl_map_intersect(app, path);
+
+	if (exact && *exact &&
+	    (*exact = check_exactness(isl_map_copy(map), isl_map_copy(app),
+				      project)) < 0)
+		goto error;
+
+	isl_space_free(dim);
+	app = set_path_length(app, 0, 1);
+	return app;
+error:
+	isl_space_free(dim);
+	isl_map_free(app);
+	return NULL;
+}
+
+/* Call construct_component and, if "project" is set, project out
+ * the final coordinates.
+ */
+static __isl_give isl_map *construct_projected_component(
+	__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *exact, int project)
+{
+	isl_map *app;
+	unsigned d;
+
+	if (!dim)
+		return NULL;
+	d = isl_space_dim(dim, isl_dim_in);
+
+	app = construct_component(dim, map, exact, project);
+	if (project) {
+		app = isl_map_project_out(app, isl_dim_in, d - 1, 1);
+		app = isl_map_project_out(app, isl_dim_out, d - 1, 1);
+	}
+	return app;
+}
+
+/* Compute an extended version, i.e., with path lengths, of
+ * an overapproximation of the transitive closure of "bmap"
+ * with path lengths greater than or equal to zero and with
+ * domain and range equal to "dom".
+ */
+static __isl_give isl_map *q_closure(__isl_take isl_space *dim,
+	__isl_take isl_set *dom, __isl_keep isl_basic_map *bmap, int *exact)
+{
+	int project = 1;
+	isl_map *path;
+	isl_map *map;
+	isl_map *app;
+
+	dom = isl_set_add_dims(dom, isl_dim_set, 1);
+	app = isl_map_from_domain_and_range(dom, isl_set_copy(dom));
+	map = isl_map_from_basic_map(isl_basic_map_copy(bmap));
+	path = construct_extended_path(dim, map, &project);
+	app = isl_map_intersect(app, path);
+
+	if ((*exact = check_exactness(map, isl_map_copy(app), project)) < 0)
+		goto error;
+
+	return app;
+error:
+	isl_map_free(app);
+	return NULL;
+}
+
+/* Check whether qc has any elements of length at least one
+ * with domain and/or range outside of dom and ran.
+ */
+static int has_spurious_elements(__isl_keep isl_map *qc,
+	__isl_keep isl_set *dom, __isl_keep isl_set *ran)
+{
+	isl_set *s;
+	int subset;
+	unsigned d;
+
+	if (!qc || !dom || !ran)
+		return -1;
+
+	d = isl_map_dim(qc, isl_dim_in);
+
+	qc = isl_map_copy(qc);
+	qc = set_path_length(qc, 0, 1);
+	qc = isl_map_project_out(qc, isl_dim_in, d - 1, 1);
+	qc = isl_map_project_out(qc, isl_dim_out, d - 1, 1);
+
+	s = isl_map_domain(isl_map_copy(qc));
+	subset = isl_set_is_subset(s, dom);
+	isl_set_free(s);
+	if (subset < 0)
+		goto error;
+	if (!subset) {
+		isl_map_free(qc);
+		return 1;
+	}
+
+	s = isl_map_range(qc);
+	subset = isl_set_is_subset(s, ran);
+	isl_set_free(s);
+
+	return subset < 0 ? -1 : !subset;
+error:
+	isl_map_free(qc);
+	return -1;
+}
+
+#define LEFT	2
+#define RIGHT	1
+
+/* For each basic map in "map", except i, check whether it combines
+ * with the transitive closure that is reflexive on C combines
+ * to the left and to the right.
+ *
+ * In particular, if
+ *
+ *	dom map_j \subseteq C
+ *
+ * then right[j] is set to 1.  Otherwise, if
+ *
+ *	ran map_i \cap dom map_j = \emptyset
+ *
+ * then right[j] is set to 0.  Otherwise, composing to the right
+ * is impossible.
+ *
+ * Similar, for composing to the left, we have if
+ *
+ *	ran map_j \subseteq C
+ *
+ * then left[j] is set to 1.  Otherwise, if
+ *
+ *	dom map_i \cap ran map_j = \emptyset
+ *
+ * then left[j] is set to 0.  Otherwise, composing to the left
+ * is impossible.
+ *
+ * The return value is or'd with LEFT if composing to the left
+ * is possible and with RIGHT if composing to the right is possible.
+ */
+static int composability(__isl_keep isl_set *C, int i,
+	isl_set **dom, isl_set **ran, int *left, int *right,
+	__isl_keep isl_map *map)
+{
+	int j;
+	int ok;
+
+	ok = LEFT | RIGHT;
+	for (j = 0; j < map->n && ok; ++j) {
+		int overlaps, subset;
+		if (j == i)
+			continue;
+
+		if (ok & RIGHT) {
+			if (!dom[j])
+				dom[j] = isl_set_from_basic_set(
+					isl_basic_map_domain(
+						isl_basic_map_copy(map->p[j])));
+			if (!dom[j])
+				return -1;
+			overlaps = isl_set_overlaps(ran[i], dom[j]);
+			if (overlaps < 0)
+				return -1;
+			if (!overlaps)
+				right[j] = 0;
+			else {
+				subset = isl_set_is_subset(dom[j], C);
+				if (subset < 0)
+					return -1;
+				if (subset)
+					right[j] = 1;
+				else
+					ok &= ~RIGHT;
+			}
+		}
+
+		if (ok & LEFT) {
+			if (!ran[j])
+				ran[j] = isl_set_from_basic_set(
+					isl_basic_map_range(
+						isl_basic_map_copy(map->p[j])));
+			if (!ran[j])
+				return -1;
+			overlaps = isl_set_overlaps(dom[i], ran[j]);
+			if (overlaps < 0)
+				return -1;
+			if (!overlaps)
+				left[j] = 0;
+			else {
+				subset = isl_set_is_subset(ran[j], C);
+				if (subset < 0)
+					return -1;
+				if (subset)
+					left[j] = 1;
+				else
+					ok &= ~LEFT;
+			}
+		}
+	}
+
+	return ok;
+}
+
+static __isl_give isl_map *anonymize(__isl_take isl_map *map)
+{
+	map = isl_map_reset(map, isl_dim_in);
+	map = isl_map_reset(map, isl_dim_out);
+	return map;
+}
+
+/* Return a map that is a union of the basic maps in "map", except i,
+ * composed to left and right with qc based on the entries of "left"
+ * and "right".
+ */
+static __isl_give isl_map *compose(__isl_keep isl_map *map, int i,
+	__isl_take isl_map *qc, int *left, int *right)
+{
+	int j;
+	isl_map *comp;
+
+	comp = isl_map_empty(isl_map_get_space(map));
+	for (j = 0; j < map->n; ++j) {
+		isl_map *map_j;
+
+		if (j == i)
+			continue;
+
+		map_j = isl_map_from_basic_map(isl_basic_map_copy(map->p[j]));
+		map_j = anonymize(map_j);
+		if (left && left[j])
+			map_j = isl_map_apply_range(map_j, isl_map_copy(qc));
+		if (right && right[j])
+			map_j = isl_map_apply_range(isl_map_copy(qc), map_j);
+		comp = isl_map_union(comp, map_j);
+	}
+
+	comp = isl_map_compute_divs(comp);
+	comp = isl_map_coalesce(comp);
+
+	isl_map_free(qc);
+
+	return comp;
+}
+
+/* Compute the transitive closure of "map" incrementally by
+ * computing
+ *
+ *	map_i^+ \cup qc^+
+ *
+ * or
+ *
+ *	map_i^+ \cup ((id \cup map_i^) \circ qc^+)
+ *
+ * or
+ *
+ *	map_i^+ \cup (qc^+ \circ (id \cup map_i^))
+ *
+ * depending on whether left or right are NULL.
+ */
+static __isl_give isl_map *compute_incremental(
+	__isl_take isl_space *dim, __isl_keep isl_map *map,
+	int i, __isl_take isl_map *qc, int *left, int *right, int *exact)
+{
+	isl_map *map_i;
+	isl_map *tc;
+	isl_map *rtc = NULL;
+
+	if (!map)
+		goto error;
+	isl_assert(map->ctx, left || right, goto error);
+
+	map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
+	tc = construct_projected_component(isl_space_copy(dim), map_i,
+						exact, 1);
+	isl_map_free(map_i);
+
+	if (*exact)
+		qc = isl_map_transitive_closure(qc, exact);
+
+	if (!*exact) {
+		isl_space_free(dim);
+		isl_map_free(tc);
+		isl_map_free(qc);
+		return isl_map_universe(isl_map_get_space(map));
+	}
+
+	if (!left || !right)
+		rtc = isl_map_union(isl_map_copy(tc),
+				    isl_map_identity(isl_map_get_space(tc)));
+	if (!right)
+		qc = isl_map_apply_range(rtc, qc);
+	if (!left)
+		qc = isl_map_apply_range(qc, rtc);
+	qc = isl_map_union(tc, qc);
+
+	isl_space_free(dim);
+
+	return qc;
+error:
+	isl_space_free(dim);
+	isl_map_free(qc);
+	return NULL;
+}
+
+/* Given a map "map", try to find a basic map such that
+ * map^+ can be computed as
+ *
+ * map^+ = map_i^+ \cup
+ *    \bigcup_j ((map_i^+ \cup Id_C)^+ \circ map_j \circ (map_i^+ \cup Id_C))^+
+ *
+ * with C the simple hull of the domain and range of the input map.
+ * map_i^ \cup Id_C is computed by allowing the path lengths to be zero
+ * and by intersecting domain and range with C.
+ * Of course, we need to check that this is actually equal to map_i^ \cup Id_C.
+ * Also, we only use the incremental computation if all the transitive
+ * closures are exact and if the number of basic maps in the union,
+ * after computing the integer divisions, is smaller than the number
+ * of basic maps in the input map.
+ */
+static int incemental_on_entire_domain(__isl_keep isl_space *dim,
+	__isl_keep isl_map *map,
+	isl_set **dom, isl_set **ran, int *left, int *right,
+	__isl_give isl_map **res)
+{
+	int i;
+	isl_set *C;
+	unsigned d;
+
+	*res = NULL;
+
+	C = isl_set_union(isl_map_domain(isl_map_copy(map)),
+			  isl_map_range(isl_map_copy(map)));
+	C = isl_set_from_basic_set(isl_set_simple_hull(C));
+	if (!C)
+		return -1;
+	if (C->n != 1) {
+		isl_set_free(C);
+		return 0;
+	}
+
+	d = isl_map_dim(map, isl_dim_in);
+
+	for (i = 0; i < map->n; ++i) {
+		isl_map *qc;
+		int exact_i, spurious;
+		int j;
+		dom[i] = isl_set_from_basic_set(isl_basic_map_domain(
+					isl_basic_map_copy(map->p[i])));
+		ran[i] = isl_set_from_basic_set(isl_basic_map_range(
+					isl_basic_map_copy(map->p[i])));
+		qc = q_closure(isl_space_copy(dim), isl_set_copy(C),
+				map->p[i], &exact_i);
+		if (!qc)
+			goto error;
+		if (!exact_i) {
+			isl_map_free(qc);
+			continue;
+		}
+		spurious = has_spurious_elements(qc, dom[i], ran[i]);
+		if (spurious) {
+			isl_map_free(qc);
+			if (spurious < 0)
+				goto error;
+			continue;
+		}
+		qc = isl_map_project_out(qc, isl_dim_in, d, 1);
+		qc = isl_map_project_out(qc, isl_dim_out, d, 1);
+		qc = isl_map_compute_divs(qc);
+		for (j = 0; j < map->n; ++j)
+			left[j] = right[j] = 1;
+		qc = compose(map, i, qc, left, right);
+		if (!qc)
+			goto error;
+		if (qc->n >= map->n) {
+			isl_map_free(qc);
+			continue;
+		}
+		*res = compute_incremental(isl_space_copy(dim), map, i, qc,
+				left, right, &exact_i);
+		if (!*res)
+			goto error;
+		if (exact_i)
+			break;
+		isl_map_free(*res);
+		*res = NULL;
+	}
+
+	isl_set_free(C);
+
+	return *res != NULL;
+error:
+	isl_set_free(C);
+	return -1;
+}
+
+/* Try and compute the transitive closure of "map" as
+ *
+ * map^+ = map_i^+ \cup
+ *    \bigcup_j ((map_i^+ \cup Id_C)^+ \circ map_j \circ (map_i^+ \cup Id_C))^+
+ *
+ * with C either the simple hull of the domain and range of the entire
+ * map or the simple hull of domain and range of map_i.
+ */
+static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *exact, int project)
+{
+	int i;
+	isl_set **dom = NULL;
+	isl_set **ran = NULL;
+	int *left = NULL;
+	int *right = NULL;
+	isl_set *C;
+	unsigned d;
+	isl_map *res = NULL;
+
+	if (!project)
+		return construct_projected_component(dim, map, exact, project);
+
+	if (!map)
+		goto error;
+	if (map->n <= 1)
+		return construct_projected_component(dim, map, exact, project);
+
+	d = isl_map_dim(map, isl_dim_in);
+
+	dom = isl_calloc_array(map->ctx, isl_set *, map->n);
+	ran = isl_calloc_array(map->ctx, isl_set *, map->n);
+	left = isl_calloc_array(map->ctx, int, map->n);
+	right = isl_calloc_array(map->ctx, int, map->n);
+	if (!ran || !dom || !left || !right)
+		goto error;
+
+	if (incemental_on_entire_domain(dim, map, dom, ran, left, right, &res) < 0)
+		goto error;
+
+	for (i = 0; !res && i < map->n; ++i) {
+		isl_map *qc;
+		int exact_i, spurious, comp;
+		if (!dom[i])
+			dom[i] = isl_set_from_basic_set(
+					isl_basic_map_domain(
+						isl_basic_map_copy(map->p[i])));
+		if (!dom[i])
+			goto error;
+		if (!ran[i])
+			ran[i] = isl_set_from_basic_set(
+					isl_basic_map_range(
+						isl_basic_map_copy(map->p[i])));
+		if (!ran[i])
+			goto error;
+		C = isl_set_union(isl_set_copy(dom[i]),
+				      isl_set_copy(ran[i]));
+		C = isl_set_from_basic_set(isl_set_simple_hull(C));
+		if (!C)
+			goto error;
+		if (C->n != 1) {
+			isl_set_free(C);
+			continue;
+		}
+		comp = composability(C, i, dom, ran, left, right, map);
+		if (!comp || comp < 0) {
+			isl_set_free(C);
+			if (comp < 0)
+				goto error;
+			continue;
+		}
+		qc = q_closure(isl_space_copy(dim), C, map->p[i], &exact_i);
+		if (!qc)
+			goto error;
+		if (!exact_i) {
+			isl_map_free(qc);
+			continue;
+		}
+		spurious = has_spurious_elements(qc, dom[i], ran[i]);
+		if (spurious) {
+			isl_map_free(qc);
+			if (spurious < 0)
+				goto error;
+			continue;
+		}
+		qc = isl_map_project_out(qc, isl_dim_in, d, 1);
+		qc = isl_map_project_out(qc, isl_dim_out, d, 1);
+		qc = isl_map_compute_divs(qc);
+		qc = compose(map, i, qc, (comp & LEFT) ? left : NULL,
+				(comp & RIGHT) ? right : NULL);
+		if (!qc)
+			goto error;
+		if (qc->n >= map->n) {
+			isl_map_free(qc);
+			continue;
+		}
+		res = compute_incremental(isl_space_copy(dim), map, i, qc,
+				(comp & LEFT) ? left : NULL,
+				(comp & RIGHT) ? right : NULL, &exact_i);
+		if (!res)
+			goto error;
+		if (exact_i)
+			break;
+		isl_map_free(res);
+		res = NULL;
+	}
+
+	for (i = 0; i < map->n; ++i) {
+		isl_set_free(dom[i]);
+		isl_set_free(ran[i]);
+	}
+	free(dom);
+	free(ran);
+	free(left);
+	free(right);
+
+	if (res) {
+		isl_space_free(dim);
+		return res;
+	}
+
+	return construct_projected_component(dim, map, exact, project);
+error:
+	if (dom)
+		for (i = 0; i < map->n; ++i)
+			isl_set_free(dom[i]);
+	free(dom);
+	if (ran)
+		for (i = 0; i < map->n; ++i)
+			isl_set_free(ran[i]);
+	free(ran);
+	free(left);
+	free(right);
+	isl_space_free(dim);
+	return NULL;
+}
+
+/* Given an array of sets "set", add "dom" at position "pos"
+ * and search for elements at earlier positions that overlap with "dom".
+ * If any can be found, then merge all of them, together with "dom", into
+ * a single set and assign the union to the first in the array,
+ * which becomes the new group leader for all groups involved in the merge.
+ * During the search, we only consider group leaders, i.e., those with
+ * group[i] = i, as the other sets have already been combined
+ * with one of the group leaders.
+ */
+static int merge(isl_set **set, int *group, __isl_take isl_set *dom, int pos)
+{
+	int i;
+
+	group[pos] = pos;
+	set[pos] = isl_set_copy(dom);
+
+	for (i = pos - 1; i >= 0; --i) {
+		int o;
+
+		if (group[i] != i)
+			continue;
+
+		o = isl_set_overlaps(set[i], dom);
+		if (o < 0)
+			goto error;
+		if (!o)
+			continue;
+
+		set[i] = isl_set_union(set[i], set[group[pos]]);
+		set[group[pos]] = NULL;
+		if (!set[i])
+			goto error;
+		group[group[pos]] = i;
+		group[pos] = i;
+	}
+
+	isl_set_free(dom);
+	return 0;
+error:
+	isl_set_free(dom);
+	return -1;
+}
+
+/* Replace each entry in the n by n grid of maps by the cross product
+ * with the relation { [i] -> [i + 1] }.
+ */
+static int add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
+{
+	int i, j, k;
+	isl_space *dim;
+	isl_basic_map *bstep;
+	isl_map *step;
+	unsigned nparam;
+
+	if (!map)
+		return -1;
+
+	dim = isl_map_get_space(map);
+	nparam = isl_space_dim(dim, isl_dim_param);
+	dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
+	dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
+	dim = isl_space_add_dims(dim, isl_dim_in, 1);
+	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	bstep = isl_basic_map_alloc_space(dim, 0, 1, 0);
+	k = isl_basic_map_alloc_equality(bstep);
+	if (k < 0) {
+		isl_basic_map_free(bstep);
+		return -1;
+	}
+	isl_seq_clr(bstep->eq[k], 1 + isl_basic_map_total_dim(bstep));
+	isl_int_set_si(bstep->eq[k][0], 1);
+	isl_int_set_si(bstep->eq[k][1 + nparam], 1);
+	isl_int_set_si(bstep->eq[k][1 + nparam + 1], -1);
+	bstep = isl_basic_map_finalize(bstep);
+	step = isl_map_from_basic_map(bstep);
+
+	for (i = 0; i < n; ++i)
+		for (j = 0; j < n; ++j)
+			grid[i][j] = isl_map_product(grid[i][j],
+						     isl_map_copy(step));
+
+	isl_map_free(step);
+
+	return 0;
+}
+
+/* The core of the Floyd-Warshall algorithm.
+ * Updates the given n x x matrix of relations in place.
+ *
+ * The algorithm iterates over all vertices.  In each step, the whole
+ * matrix is updated to include all paths that go to the current vertex,
+ * possibly stay there a while (including passing through earlier vertices)
+ * and then come back.  At the start of each iteration, the diagonal
+ * element corresponding to the current vertex is replaced by its
+ * transitive closure to account for all indirect paths that stay
+ * in the current vertex.
+ */
+static void floyd_warshall_iterate(isl_map ***grid, int n, int *exact)
+{
+	int r, p, q;
+
+	for (r = 0; r < n; ++r) {
+		int r_exact;
+		grid[r][r] = isl_map_transitive_closure(grid[r][r],
+				(exact && *exact) ? &r_exact : NULL);
+		if (exact && *exact && !r_exact)
+			*exact = 0;
+
+		for (p = 0; p < n; ++p)
+			for (q = 0; q < n; ++q) {
+				isl_map *loop;
+				if (p == r && q == r)
+					continue;
+				loop = isl_map_apply_range(
+						isl_map_copy(grid[p][r]),
+						isl_map_copy(grid[r][q]));
+				grid[p][q] = isl_map_union(grid[p][q], loop);
+				loop = isl_map_apply_range(
+						isl_map_copy(grid[p][r]),
+					isl_map_apply_range(
+						isl_map_copy(grid[r][r]),
+						isl_map_copy(grid[r][q])));
+				grid[p][q] = isl_map_union(grid[p][q], loop);
+				grid[p][q] = isl_map_coalesce(grid[p][q]);
+			}
+	}
+}
+
+/* Given a partition of the domains and ranges of the basic maps in "map",
+ * apply the Floyd-Warshall algorithm with the elements in the partition
+ * as vertices.
+ *
+ * In particular, there are "n" elements in the partition and "group" is
+ * an array of length 2 * map->n with entries in [0,n-1].
+ *
+ * We first construct a matrix of relations based on the partition information,
+ * apply Floyd-Warshall on this matrix of relations and then take the
+ * union of all entries in the matrix as the final result.
+ *
+ * If we are actually computing the power instead of the transitive closure,
+ * i.e., when "project" is not set, then the result should have the
+ * path lengths encoded as the difference between an extra pair of
+ * coordinates.  We therefore apply the nested transitive closures
+ * to relations that include these lengths.  In particular, we replace
+ * the input relation by the cross product with the unit length relation
+ * { [i] -> [i + 1] }.
+ */
+static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *exact, int project, int *group, int n)
+{
+	int i, j, k;
+	isl_map ***grid = NULL;
+	isl_map *app;
+
+	if (!map)
+		goto error;
+
+	if (n == 1) {
+		free(group);
+		return incremental_closure(dim, map, exact, project);
+	}
+
+	grid = isl_calloc_array(map->ctx, isl_map **, n);
+	if (!grid)
+		goto error;
+	for (i = 0; i < n; ++i) {
+		grid[i] = isl_calloc_array(map->ctx, isl_map *, n);
+		if (!grid[i])
+			goto error;
+		for (j = 0; j < n; ++j)
+			grid[i][j] = isl_map_empty(isl_map_get_space(map));
+	}
+
+	for (k = 0; k < map->n; ++k) {
+		i = group[2 * k];
+		j = group[2 * k + 1];
+		grid[i][j] = isl_map_union(grid[i][j],
+				isl_map_from_basic_map(
+					isl_basic_map_copy(map->p[k])));
+	}
+
+	if (!project && add_length(map, grid, n) < 0)
+		goto error;
+
+	floyd_warshall_iterate(grid, n, exact);
+
+	app = isl_map_empty(isl_map_get_space(map));
+
+	for (i = 0; i < n; ++i) {
+		for (j = 0; j < n; ++j)
+			app = isl_map_union(app, grid[i][j]);
+		free(grid[i]);
+	}
+	free(grid);
+
+	free(group);
+	isl_space_free(dim);
+
+	return app;
+error:
+	if (grid)
+		for (i = 0; i < n; ++i) {
+			if (!grid[i])
+				continue;
+			for (j = 0; j < n; ++j)
+				isl_map_free(grid[i][j]);
+			free(grid[i]);
+		}
+	free(grid);
+	free(group);
+	isl_space_free(dim);
+	return NULL;
+}
+
+/* Partition the domains and ranges of the n basic relations in list
+ * into disjoint cells.
+ *
+ * To find the partition, we simply consider all of the domains
+ * and ranges in turn and combine those that overlap.
+ * "set" contains the partition elements and "group" indicates
+ * to which partition element a given domain or range belongs.
+ * The domain of basic map i corresponds to element 2 * i in these arrays,
+ * while the domain corresponds to element 2 * i + 1.
+ * During the construction group[k] is either equal to k,
+ * in which case set[k] contains the union of all the domains and
+ * ranges in the corresponding group, or is equal to some l < k,
+ * with l another domain or range in the same group.
+ */
+static int *setup_groups(isl_ctx *ctx, __isl_keep isl_basic_map **list, int n,
+	isl_set ***set, int *n_group)
+{
+	int i;
+	int *group = NULL;
+	int g;
+
+	*set = isl_calloc_array(ctx, isl_set *, 2 * n);
+	group = isl_alloc_array(ctx, int, 2 * n);
+
+	if (!*set || !group)
+		goto error;
+
+	for (i = 0; i < n; ++i) {
+		isl_set *dom;
+		dom = isl_set_from_basic_set(isl_basic_map_domain(
+				isl_basic_map_copy(list[i])));
+		if (merge(*set, group, dom, 2 * i) < 0)
+			goto error;
+		dom = isl_set_from_basic_set(isl_basic_map_range(
+				isl_basic_map_copy(list[i])));
+		if (merge(*set, group, dom, 2 * i + 1) < 0)
+			goto error;
+	}
+
+	g = 0;
+	for (i = 0; i < 2 * n; ++i)
+		if (group[i] == i) {
+			if (g != i) {
+				(*set)[g] = (*set)[i];
+				(*set)[i] = NULL;
+			}
+			group[i] = g++;
+		} else
+			group[i] = group[group[i]];
+
+	*n_group = g;
+
+	return group;
+error:
+	if (*set) {
+		for (i = 0; i < 2 * n; ++i)
+			isl_set_free((*set)[i]);
+		free(*set);
+		*set = NULL;
+	}
+	free(group);
+	return NULL;
+}
+
+/* Check if the domains and ranges of the basic maps in "map" can
+ * be partitioned, and if so, apply Floyd-Warshall on the elements
+ * of the partition.  Note that we also apply this algorithm
+ * if we want to compute the power, i.e., when "project" is not set.
+ * However, the results are unlikely to be exact since the recursive
+ * calls inside the Floyd-Warshall algorithm typically result in
+ * non-linear path lengths quite quickly.
+ */
+static __isl_give isl_map *floyd_warshall(__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *exact, int project)
+{
+	int i;
+	isl_set **set = NULL;
+	int *group = NULL;
+	int n;
+
+	if (!map)
+		goto error;
+	if (map->n <= 1)
+		return incremental_closure(dim, map, exact, project);
+
+	group = setup_groups(map->ctx, map->p, map->n, &set, &n);
+	if (!group)
+		goto error;
+
+	for (i = 0; i < 2 * map->n; ++i)
+		isl_set_free(set[i]);
+
+	free(set);
+
+	return floyd_warshall_with_groups(dim, map, exact, project, group, n);
+error:
+	isl_space_free(dim);
+	return NULL;
+}
+
+/* Structure for representing the nodes of the graph of which
+ * strongly connected components are being computed.
+ *
+ * list contains the actual nodes
+ * check_closed is set if we may have used the fact that
+ * a pair of basic maps can be interchanged
+ */
+struct isl_tc_follows_data {
+	isl_basic_map **list;
+	int check_closed;
+};
+
+/* Check whether in the computation of the transitive closure
+ * "list[i]" (R_1) should follow (or be part of the same component as)
+ * "list[j]" (R_2).
+ *
+ * That is check whether
+ *
+ *	R_1 \circ R_2
+ *
+ * is a subset of
+ *
+ *	R_2 \circ R_1
+ *
+ * If so, then there is no reason for R_1 to immediately follow R_2
+ * in any path.
+ *
+ * *check_closed is set if the subset relation holds while
+ * R_1 \circ R_2 is not empty.
+ */
+static int basic_map_follows(int i, int j, void *user)
+{
+	struct isl_tc_follows_data *data = user;
+	struct isl_map *map12 = NULL;
+	struct isl_map *map21 = NULL;
+	int subset;
+
+	if (!isl_space_tuple_is_equal(data->list[i]->dim, isl_dim_in,
+				    data->list[j]->dim, isl_dim_out))
+		return 0;
+
+	map21 = isl_map_from_basic_map(
+			isl_basic_map_apply_range(
+				isl_basic_map_copy(data->list[j]),
+				isl_basic_map_copy(data->list[i])));
+	subset = isl_map_is_empty(map21);
+	if (subset < 0)
+		goto error;
+	if (subset) {
+		isl_map_free(map21);
+		return 0;
+	}
+
+	if (!isl_space_tuple_is_equal(data->list[i]->dim, isl_dim_in,
+				    data->list[i]->dim, isl_dim_out) ||
+	    !isl_space_tuple_is_equal(data->list[j]->dim, isl_dim_in,
+				    data->list[j]->dim, isl_dim_out)) {
+		isl_map_free(map21);
+		return 1;
+	}
+
+	map12 = isl_map_from_basic_map(
+			isl_basic_map_apply_range(
+				isl_basic_map_copy(data->list[i]),
+				isl_basic_map_copy(data->list[j])));
+
+	subset = isl_map_is_subset(map21, map12);
+
+	isl_map_free(map12);
+	isl_map_free(map21);
+
+	if (subset)
+		data->check_closed = 1;
+
+	return subset < 0 ? -1 : !subset;
+error:
+	isl_map_free(map21);
+	return -1;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
+ * and a dimension specification (Z^{n+1} -> Z^{n+1}),
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the dom R \times Z to an
+ * element from ran R \times Z, such that the first n coordinates of the
+ * difference between them is a sum of differences between images
+ * and pre-images in one of the R_i and such that the last coordinate
+ * is equal to the number of steps taken.
+ * If "project" is set, then these final coordinates are not included,
+ * i.e., a relation of type Z^n -> Z^n is returned.
+ * That is, let
+ *
+ *	\Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ *	{ (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ *				d = (\sum_i k_i \delta_i, \sum_i k_i) and
+ *				x in dom R and x + d in ran R }
+ *
+ * or
+ *
+ *	{ (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ *				d = (\sum_i k_i \delta_i) and
+ *				x in dom R and x + d in ran R }
+ *
+ * if "project" is set.
+ *
+ * We first split the map into strongly connected components, perform
+ * the above on each component and then join the results in the correct
+ * order, at each join also taking in the union of both arguments
+ * to allow for paths that do not go through one of the two arguments.
+ */
+static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
+	__isl_keep isl_map *map, int *exact, int project)
+{
+	int i, n, c;
+	struct isl_map *path = NULL;
+	struct isl_tc_follows_data data;
+	struct isl_tarjan_graph *g = NULL;
+	int *orig_exact;
+	int local_exact;
+
+	if (!map)
+		goto error;
+	if (map->n <= 1)
+		return floyd_warshall(dim, map, exact, project);
+
+	data.list = map->p;
+	data.check_closed = 0;
+	g = isl_tarjan_graph_init(map->ctx, map->n, &basic_map_follows, &data);
+	if (!g)
+		goto error;
+
+	orig_exact = exact;
+	if (data.check_closed && !exact)
+		exact = &local_exact;
+
+	c = 0;
+	i = 0;
+	n = map->n;
+	if (project)
+		path = isl_map_empty(isl_map_get_space(map));
+	else
+		path = isl_map_empty(isl_space_copy(dim));
+	path = anonymize(path);
+	while (n) {
+		struct isl_map *comp;
+		isl_map *path_comp, *path_comb;
+		comp = isl_map_alloc_space(isl_map_get_space(map), n, 0);
+		while (g->order[i] != -1) {
+			comp = isl_map_add_basic_map(comp,
+				    isl_basic_map_copy(map->p[g->order[i]]));
+			--n;
+			++i;
+		}
+		path_comp = floyd_warshall(isl_space_copy(dim),
+						comp, exact, project);
+		path_comp = anonymize(path_comp);
+		path_comb = isl_map_apply_range(isl_map_copy(path),
+						isl_map_copy(path_comp));
+		path = isl_map_union(path, path_comp);
+		path = isl_map_union(path, path_comb);
+		isl_map_free(comp);
+		++i;
+		++c;
+	}
+
+	if (c > 1 && data.check_closed && !*exact) {
+		int closed;
+
+		closed = isl_map_is_transitively_closed(path);
+		if (closed < 0)
+			goto error;
+		if (!closed) {
+			isl_tarjan_graph_free(g);
+			isl_map_free(path);
+			return floyd_warshall(dim, map, orig_exact, project);
+		}
+	}
+
+	isl_tarjan_graph_free(g);
+	isl_space_free(dim);
+
+	return path;
+error:
+	isl_tarjan_graph_free(g);
+	isl_space_free(dim);
+	isl_map_free(path);
+	return NULL;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D,
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the space D to another
+ * element from the same space, such that the difference between
+ * them is a strictly positive sum of differences between images
+ * and pre-images in one of the R_i.
+ * The number of differences in the sum is equated to parameter "param".
+ * That is, let
+ *
+ *	\Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ *	{ (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ *				d = \sum_i k_i \delta_i and k = \sum_i k_i > 0 }
+ * or
+ *
+ *	{ (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ *				d = \sum_i k_i \delta_i and \sum_i k_i > 0 }
+ *
+ * if "project" is set.
+ *
+ * If "project" is not set, then
+ * we construct an extended mapping with an extra coordinate
+ * that indicates the number of steps taken.  In particular,
+ * the difference in the last coordinate is equal to the number
+ * of steps taken to move from a domain element to the corresponding
+ * image element(s).
+ */
+static __isl_give isl_map *construct_power(__isl_keep isl_map *map,
+	int *exact, int project)
+{
+	struct isl_map *app = NULL;
+	isl_space *dim = NULL;
+	unsigned d;
+
+	if (!map)
+		return NULL;
+
+	dim = isl_map_get_space(map);
+
+	d = isl_space_dim(dim, isl_dim_in);
+	dim = isl_space_add_dims(dim, isl_dim_in, 1);
+	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+
+	app = construct_power_components(isl_space_copy(dim), map,
+					exact, project);
+
+	isl_space_free(dim);
+
+	return app;
+}
+
+/* Compute the positive powers of "map", or an overapproximation.
+ * If the result is exact, then *exact is set to 1.
+ *
+ * If project is set, then we are actually interested in the transitive
+ * closure, so we can use a more relaxed exactness check.
+ * The lengths of the paths are also projected out instead of being
+ * encoded as the difference between an extra pair of final coordinates.
+ */
+static __isl_give isl_map *map_power(__isl_take isl_map *map,
+	int *exact, int project)
+{
+	struct isl_map *app = NULL;
+
+	if (exact)
+		*exact = 1;
+
+	if (!map)
+		return NULL;
+
+	isl_assert(map->ctx,
+		isl_map_dim(map, isl_dim_in) == isl_map_dim(map, isl_dim_out),
+		goto error);
+
+	app = construct_power(map, exact, project);
+
+	isl_map_free(map);
+	return app;
+error:
+	isl_map_free(map);
+	isl_map_free(app);
+	return NULL;
+}
+
+/* Compute the positive powers of "map", or an overapproximation.
+ * The result maps the exponent to a nested copy of the corresponding power.
+ * If the result is exact, then *exact is set to 1.
+ * map_power constructs an extended relation with the path lengths
+ * encoded as the difference between the final coordinates.
+ * In the final step, this difference is equated to an extra parameter
+ * and made positive.  The extra coordinates are subsequently projected out
+ * and the parameter is turned into the domain of the result.
+ */
+__isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact)
+{
+	isl_space *target_dim;
+	isl_space *dim;
+	isl_map *diff;
+	unsigned d;
+	unsigned param;
+
+	if (!map)
+		return NULL;
+
+	d = isl_map_dim(map, isl_dim_in);
+	param = isl_map_dim(map, isl_dim_param);
+
+	map = isl_map_compute_divs(map);
+	map = isl_map_coalesce(map);
+
+	if (isl_map_plain_is_empty(map)) {
+		map = isl_map_from_range(isl_map_wrap(map));
+		map = isl_map_add_dims(map, isl_dim_in, 1);
+		map = isl_map_set_dim_name(map, isl_dim_in, 0, "k");
+		return map;
+	}
+
+	target_dim = isl_map_get_space(map);
+	target_dim = isl_space_from_range(isl_space_wrap(target_dim));
+	target_dim = isl_space_add_dims(target_dim, isl_dim_in, 1);
+	target_dim = isl_space_set_dim_name(target_dim, isl_dim_in, 0, "k");
+
+	map = map_power(map, exact, 0);
+
+	map = isl_map_add_dims(map, isl_dim_param, 1);
+	dim = isl_map_get_space(map);
+	diff = equate_parameter_to_length(dim, param);
+	map = isl_map_intersect(map, diff);
+	map = isl_map_project_out(map, isl_dim_in, d, 1);
+	map = isl_map_project_out(map, isl_dim_out, d, 1);
+	map = isl_map_from_range(isl_map_wrap(map));
+	map = isl_map_move_dims(map, isl_dim_in, 0, isl_dim_param, param, 1);
+
+	map = isl_map_reset_space(map, target_dim);
+
+	return map;
+}
+
+/* Compute a relation that maps each element in the range of the input
+ * relation to the lengths of all paths composed of edges in the input
+ * relation that end up in the given range element.
+ * The result may be an overapproximation, in which case *exact is set to 0.
+ * The resulting relation is very similar to the power relation.
+ * The difference are that the domain has been projected out, the
+ * range has become the domain and the exponent is the range instead
+ * of a parameter.
+ */
+__isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
+	int *exact)
+{
+	isl_space *dim;
+	isl_map *diff;
+	unsigned d;
+	unsigned param;
+
+	if (!map)
+		return NULL;
+
+	d = isl_map_dim(map, isl_dim_in);
+	param = isl_map_dim(map, isl_dim_param);
+
+	map = isl_map_compute_divs(map);
+	map = isl_map_coalesce(map);
+
+	if (isl_map_plain_is_empty(map)) {
+		if (exact)
+			*exact = 1;
+		map = isl_map_project_out(map, isl_dim_out, 0, d);
+		map = isl_map_add_dims(map, isl_dim_out, 1);
+		return map;
+	}
+
+	map = map_power(map, exact, 0);
+
+	map = isl_map_add_dims(map, isl_dim_param, 1);
+	dim = isl_map_get_space(map);
+	diff = equate_parameter_to_length(dim, param);
+	map = isl_map_intersect(map, diff);
+	map = isl_map_project_out(map, isl_dim_in, 0, d + 1);
+	map = isl_map_project_out(map, isl_dim_out, d, 1);
+	map = isl_map_reverse(map);
+	map = isl_map_move_dims(map, isl_dim_out, 0, isl_dim_param, param, 1);
+
+	return map;
+}
+
+/* Check whether equality i of bset is a pure stride constraint
+ * on a single dimensions, i.e., of the form
+ *
+ *	v = k e
+ *
+ * with k a constant and e an existentially quantified variable.
+ */
+static int is_eq_stride(__isl_keep isl_basic_set *bset, int i)
+{
+	unsigned nparam;
+	unsigned d;
+	unsigned n_div;
+	int pos1;
+	int pos2;
+
+	if (!bset)
+		return -1;
+
+	if (!isl_int_is_zero(bset->eq[i][0]))
+		return 0;
+
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	d = isl_basic_set_dim(bset, isl_dim_set);
+	n_div = isl_basic_set_dim(bset, isl_dim_div);
+
+	if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
+		return 0;
+	pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
+	if (pos1 == -1)
+		return 0;
+	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1, 
+					d - pos1 - 1) != -1)
+		return 0;
+
+	pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
+	if (pos2 == -1)
+		return 0;
+	if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d  + pos2 + 1,
+				   n_div - pos2 - 1) != -1)
+		return 0;
+	if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
+	    !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
+		return 0;
+
+	return 1;
+}
+
+/* Given a map, compute the smallest superset of this map that is of the form
+ *
+ *	{ i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
+ *
+ * (where p ranges over the (non-parametric) dimensions),
+ * compute the transitive closure of this map, i.e.,
+ *
+ *	{ i -> j : exists k > 0:
+ *		k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * and intersect domain and range of this transitive closure with
+ * the given domain and range.
+ *
+ * If with_id is set, then try to include as much of the identity mapping
+ * as possible, by computing
+ *
+ *	{ i -> j : exists k >= 0:
+ *		k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * instead (i.e., allow k = 0).
+ *
+ * In practice, we compute the difference set
+ *
+ *	delta  = { j - i | i -> j in map },
+ *
+ * look for stride constraint on the individual dimensions and compute
+ * (constant) lower and upper bounds for each individual dimension,
+ * adding a constraint for each bound not equal to infinity.
+ */
+static __isl_give isl_map *box_closure_on_domain(__isl_take isl_map *map,
+	__isl_take isl_set *dom, __isl_take isl_set *ran, int with_id)
+{
+	int i;
+	int k;
+	unsigned d;
+	unsigned nparam;
+	unsigned total;
+	isl_space *dim;
+	isl_set *delta;
+	isl_map *app = NULL;
+	isl_basic_set *aff = NULL;
+	isl_basic_map *bmap = NULL;
+	isl_vec *obj = NULL;
+	isl_int opt;
+
+	isl_int_init(opt);
+
+	delta = isl_map_deltas(isl_map_copy(map));
+
+	aff = isl_set_affine_hull(isl_set_copy(delta));
+	if (!aff)
+		goto error;
+	dim = isl_map_get_space(map);
+	d = isl_space_dim(dim, isl_dim_in);
+	nparam = isl_space_dim(dim, isl_dim_param);
+	total = isl_space_dim(dim, isl_dim_all);
+	bmap = isl_basic_map_alloc_space(dim,
+					aff->n_div + 1, aff->n_div, 2 * d + 1);
+	for (i = 0; i < aff->n_div + 1; ++i) {
+		k = isl_basic_map_alloc_div(bmap);
+		if (k < 0)
+			goto error;
+		isl_int_set_si(bmap->div[k][0], 0);
+	}
+	for (i = 0; i < aff->n_eq; ++i) {
+		if (!is_eq_stride(aff, i))
+			continue;
+		k = isl_basic_map_alloc_equality(bmap);
+		if (k < 0)
+			goto error;
+		isl_seq_clr(bmap->eq[k], 1 + nparam);
+		isl_seq_cpy(bmap->eq[k] + 1 + nparam + d,
+				aff->eq[i] + 1 + nparam, d);
+		isl_seq_neg(bmap->eq[k] + 1 + nparam,
+				aff->eq[i] + 1 + nparam, d);
+		isl_seq_cpy(bmap->eq[k] + 1 + nparam + 2 * d,
+				aff->eq[i] + 1 + nparam + d, aff->n_div);
+		isl_int_set_si(bmap->eq[k][1 + total + aff->n_div], 0);
+	}
+	obj = isl_vec_alloc(map->ctx, 1 + nparam + d);
+	if (!obj)
+		goto error;
+	isl_seq_clr(obj->el, 1 + nparam + d);
+	for (i = 0; i < d; ++ i) {
+		enum isl_lp_result res;
+
+		isl_int_set_si(obj->el[1 + nparam + i], 1);
+
+		res = isl_set_solve_lp(delta, 0, obj->el, map->ctx->one, &opt,
+					NULL, NULL);
+		if (res == isl_lp_error)
+			goto error;
+		if (res == isl_lp_ok) {
+			k = isl_basic_map_alloc_inequality(bmap);
+			if (k < 0)
+				goto error;
+			isl_seq_clr(bmap->ineq[k],
+					1 + nparam + 2 * d + bmap->n_div);
+			isl_int_set_si(bmap->ineq[k][1 + nparam + i], -1);
+			isl_int_set_si(bmap->ineq[k][1 + nparam + d + i], 1);
+			isl_int_neg(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], opt);
+		}
+
+		res = isl_set_solve_lp(delta, 1, obj->el, map->ctx->one, &opt,
+					NULL, NULL);
+		if (res == isl_lp_error)
+			goto error;
+		if (res == isl_lp_ok) {
+			k = isl_basic_map_alloc_inequality(bmap);
+			if (k < 0)
+				goto error;
+			isl_seq_clr(bmap->ineq[k],
+					1 + nparam + 2 * d + bmap->n_div);
+			isl_int_set_si(bmap->ineq[k][1 + nparam + i], 1);
+			isl_int_set_si(bmap->ineq[k][1 + nparam + d + i], -1);
+			isl_int_set(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], opt);
+		}
+
+		isl_int_set_si(obj->el[1 + nparam + i], 0);
+	}
+	k = isl_basic_map_alloc_inequality(bmap);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(bmap->ineq[k],
+			1 + nparam + 2 * d + bmap->n_div);
+	if (!with_id)
+		isl_int_set_si(bmap->ineq[k][0], -1);
+	isl_int_set_si(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], 1);
+
+	app = isl_map_from_domain_and_range(dom, ran);
+
+	isl_vec_free(obj);
+	isl_basic_set_free(aff);
+	isl_map_free(map);
+	bmap = isl_basic_map_finalize(bmap);
+	isl_set_free(delta);
+	isl_int_clear(opt);
+
+	map = isl_map_from_basic_map(bmap);
+	map = isl_map_intersect(map, app);
+
+	return map;
+error:
+	isl_vec_free(obj);
+	isl_basic_map_free(bmap);
+	isl_basic_set_free(aff);
+	isl_set_free(dom);
+	isl_set_free(ran);
+	isl_map_free(map);
+	isl_set_free(delta);
+	isl_int_clear(opt);
+	return NULL;
+}
+
+/* Given a map, compute the smallest superset of this map that is of the form
+ *
+ *	{ i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
+ *
+ * (where p ranges over the (non-parametric) dimensions),
+ * compute the transitive closure of this map, i.e.,
+ *
+ *	{ i -> j : exists k > 0:
+ *		k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * and intersect domain and range of this transitive closure with
+ * domain and range of the original map.
+ */
+static __isl_give isl_map *box_closure(__isl_take isl_map *map)
+{
+	isl_set *domain;
+	isl_set *range;
+
+	domain = isl_map_domain(isl_map_copy(map));
+	domain = isl_set_coalesce(domain);
+	range = isl_map_range(isl_map_copy(map));
+	range = isl_set_coalesce(range);
+
+	return box_closure_on_domain(map, domain, range, 0);
+}
+
+/* Given a map, compute the smallest superset of this map that is of the form
+ *
+ *	{ i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
+ *
+ * (where p ranges over the (non-parametric) dimensions),
+ * compute the transitive and partially reflexive closure of this map, i.e.,
+ *
+ *	{ i -> j : exists k >= 0:
+ *		k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * and intersect domain and range of this transitive closure with
+ * the given domain.
+ */
+static __isl_give isl_map *box_closure_with_identity(__isl_take isl_map *map,
+	__isl_take isl_set *dom)
+{
+	return box_closure_on_domain(map, dom, isl_set_copy(dom), 1);
+}
+
+/* Check whether app is the transitive closure of map.
+ * In particular, check that app is acyclic and, if so,
+ * check that
+ *
+ *	app \subset (map \cup (map \circ app))
+ */
+static int check_exactness_omega(__isl_keep isl_map *map,
+	__isl_keep isl_map *app)
+{
+	isl_set *delta;
+	int i;
+	int is_empty, is_exact;
+	unsigned d;
+	isl_map *test;
+
+	delta = isl_map_deltas(isl_map_copy(app));
+	d = isl_set_dim(delta, isl_dim_set);
+	for (i = 0; i < d; ++i)
+		delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
+	is_empty = isl_set_is_empty(delta);
+	isl_set_free(delta);
+	if (is_empty < 0)
+		return -1;
+	if (!is_empty)
+		return 0;
+
+	test = isl_map_apply_range(isl_map_copy(app), isl_map_copy(map));
+	test = isl_map_union(test, isl_map_copy(map));
+	is_exact = isl_map_is_subset(app, test);
+	isl_map_free(test);
+
+	return is_exact;
+}
+
+/* Check if basic map M_i can be combined with all the other
+ * basic maps such that
+ *
+ *	(\cup_j M_j)^+
+ *
+ * can be computed as
+ *
+ *	M_i \cup (\cup_{j \ne i} M_i^* \circ M_j \circ M_i^*)^+
+ *
+ * In particular, check if we can compute a compact representation
+ * of
+ *
+ *		M_i^* \circ M_j \circ M_i^*
+ *
+ * for each j != i.
+ * Let M_i^? be an extension of M_i^+ that allows paths
+ * of length zero, i.e., the result of box_closure(., 1).
+ * The criterion, as proposed by Kelly et al., is that
+ * id = M_i^? - M_i^+ can be represented as a basic map
+ * and that
+ *
+ *	id \circ M_j \circ id = M_j
+ *
+ * for each j != i.
+ *
+ * If this function returns 1, then tc and qc are set to
+ * M_i^+ and M_i^?, respectively.
+ */
+static int can_be_split_off(__isl_keep isl_map *map, int i,
+	__isl_give isl_map **tc, __isl_give isl_map **qc)
+{
+	isl_map *map_i, *id = NULL;
+	int j = -1;
+	isl_set *C;
+
+	*tc = NULL;
+	*qc = NULL;
+
+	C = isl_set_union(isl_map_domain(isl_map_copy(map)),
+			  isl_map_range(isl_map_copy(map)));
+	C = isl_set_from_basic_set(isl_set_simple_hull(C));
+	if (!C)
+		goto error;
+
+	map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
+	*tc = box_closure(isl_map_copy(map_i));
+	*qc = box_closure_with_identity(map_i, C);
+	id = isl_map_subtract(isl_map_copy(*qc), isl_map_copy(*tc));
+
+	if (!id || !*qc)
+		goto error;
+	if (id->n != 1 || (*qc)->n != 1)
+		goto done;
+
+	for (j = 0; j < map->n; ++j) {
+		isl_map *map_j, *test;
+		int is_ok;
+
+		if (i == j)
+			continue;
+		map_j = isl_map_from_basic_map(
+					isl_basic_map_copy(map->p[j]));
+		test = isl_map_apply_range(isl_map_copy(id),
+						isl_map_copy(map_j));
+		test = isl_map_apply_range(test, isl_map_copy(id));
+		is_ok = isl_map_is_equal(test, map_j);
+		isl_map_free(map_j);
+		isl_map_free(test);
+		if (is_ok < 0)
+			goto error;
+		if (!is_ok)
+			break;
+	}
+
+done:
+	isl_map_free(id);
+	if (j == map->n)
+		return 1;
+
+	isl_map_free(*qc);
+	isl_map_free(*tc);
+	*qc = NULL;
+	*tc = NULL;
+
+	return 0;
+error:
+	isl_map_free(id);
+	isl_map_free(*qc);
+	isl_map_free(*tc);
+	*qc = NULL;
+	*tc = NULL;
+	return -1;
+}
+
+static __isl_give isl_map *box_closure_with_check(__isl_take isl_map *map,
+	int *exact)
+{
+	isl_map *app;
+
+	app = box_closure(isl_map_copy(map));
+	if (exact)
+		*exact = check_exactness_omega(map, app);
+
+	isl_map_free(map);
+	return app;
+}
+
+/* Compute an overapproximation of the transitive closure of "map"
+ * using a variation of the algorithm from
+ * "Transitive Closure of Infinite Graphs and its Applications"
+ * by Kelly et al.
+ *
+ * We first check whether we can can split of any basic map M_i and
+ * compute
+ *
+ *	(\cup_j M_j)^+
+ *
+ * as
+ *
+ *	M_i \cup (\cup_{j \ne i} M_i^* \circ M_j \circ M_i^*)^+
+ *
+ * using a recursive call on the remaining map.
+ *
+ * If not, we simply call box_closure on the whole map.
+ */
+static __isl_give isl_map *transitive_closure_omega(__isl_take isl_map *map,
+	int *exact)
+{
+	int i, j;
+	int exact_i;
+	isl_map *app;
+
+	if (!map)
+		return NULL;
+	if (map->n == 1)
+		return box_closure_with_check(map, exact);
+
+	for (i = 0; i < map->n; ++i) {
+		int ok;
+		isl_map *qc, *tc;
+		ok = can_be_split_off(map, i, &tc, &qc);
+		if (ok < 0)
+			goto error;
+		if (!ok)
+			continue;
+
+		app = isl_map_alloc_space(isl_map_get_space(map), map->n - 1, 0);
+
+		for (j = 0; j < map->n; ++j) {
+			if (j == i)
+				continue;
+			app = isl_map_add_basic_map(app,
+						isl_basic_map_copy(map->p[j]));
+		}
+
+		app = isl_map_apply_range(isl_map_copy(qc), app);
+		app = isl_map_apply_range(app, qc);
+
+		app = isl_map_union(tc, transitive_closure_omega(app, NULL));
+		exact_i = check_exactness_omega(map, app);
+		if (exact_i == 1) {
+			if (exact)
+				*exact = exact_i;
+			isl_map_free(map);
+			return app;
+		}
+		isl_map_free(app);
+		if (exact_i < 0)
+			goto error;
+	}
+
+	return box_closure_with_check(map, exact);
+error:
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Compute the transitive closure  of "map", or an overapproximation.
+ * If the result is exact, then *exact is set to 1.
+ * Simply use map_power to compute the powers of map, but tell
+ * it to project out the lengths of the paths instead of equating
+ * the length to a parameter.
+ */
+__isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
+	int *exact)
+{
+	isl_space *target_dim;
+	int closed;
+
+	if (!map)
+		goto error;
+
+	if (map->ctx->opt->closure == ISL_CLOSURE_BOX)
+		return transitive_closure_omega(map, exact);
+
+	map = isl_map_compute_divs(map);
+	map = isl_map_coalesce(map);
+	closed = isl_map_is_transitively_closed(map);
+	if (closed < 0)
+		goto error;
+	if (closed) {
+		if (exact)
+			*exact = 1;
+		return map;
+	}
+
+	target_dim = isl_map_get_space(map);
+	map = map_power(map, exact, 1);
+	map = isl_map_reset_space(map, target_dim);
+
+	return map;
+error:
+	isl_map_free(map);
+	return NULL;
+}
+
+static int inc_count(__isl_take isl_map *map, void *user)
+{
+	int *n = user;
+
+	*n += map->n;
+
+	isl_map_free(map);
+
+	return 0;
+}
+
+static int collect_basic_map(__isl_take isl_map *map, void *user)
+{
+	int i;
+	isl_basic_map ***next = user;
+
+	for (i = 0; i < map->n; ++i) {
+		**next = isl_basic_map_copy(map->p[i]);
+		if (!**next)
+			goto error;
+		(*next)++;
+	}
+
+	isl_map_free(map);
+	return 0;
+error:
+	isl_map_free(map);
+	return -1;
+}
+
+/* Perform Floyd-Warshall on the given list of basic relations.
+ * The basic relations may live in different dimensions,
+ * but basic relations that get assigned to the diagonal of the
+ * grid have domains and ranges of the same dimension and so
+ * the standard algorithm can be used because the nested transitive
+ * closures are only applied to diagonal elements and because all
+ * compositions are peformed on relations with compatible domains and ranges.
+ */
+static __isl_give isl_union_map *union_floyd_warshall_on_list(isl_ctx *ctx,
+	__isl_keep isl_basic_map **list, int n, int *exact)
+{
+	int i, j, k;
+	int n_group;
+	int *group = NULL;
+	isl_set **set = NULL;
+	isl_map ***grid = NULL;
+	isl_union_map *app;
+
+	group = setup_groups(ctx, list, n, &set, &n_group);
+	if (!group)
+		goto error;
+
+	grid = isl_calloc_array(ctx, isl_map **, n_group);
+	if (!grid)
+		goto error;
+	for (i = 0; i < n_group; ++i) {
+		grid[i] = isl_calloc_array(ctx, isl_map *, n_group);
+		if (!grid[i])
+			goto error;
+		for (j = 0; j < n_group; ++j) {
+			isl_space *dim1, *dim2, *dim;
+			dim1 = isl_space_reverse(isl_set_get_space(set[i]));
+			dim2 = isl_set_get_space(set[j]);
+			dim = isl_space_join(dim1, dim2);
+			grid[i][j] = isl_map_empty(dim);
+		}
+	}
+
+	for (k = 0; k < n; ++k) {
+		i = group[2 * k];
+		j = group[2 * k + 1];
+		grid[i][j] = isl_map_union(grid[i][j],
+				isl_map_from_basic_map(
+					isl_basic_map_copy(list[k])));
+	}
+	
+	floyd_warshall_iterate(grid, n_group, exact);
+
+	app = isl_union_map_empty(isl_map_get_space(grid[0][0]));
+
+	for (i = 0; i < n_group; ++i) {
+		for (j = 0; j < n_group; ++j)
+			app = isl_union_map_add_map(app, grid[i][j]);
+		free(grid[i]);
+	}
+	free(grid);
+
+	for (i = 0; i < 2 * n; ++i)
+		isl_set_free(set[i]);
+	free(set);
+
+	free(group);
+	return app;
+error:
+	if (grid)
+		for (i = 0; i < n_group; ++i) {
+			if (!grid[i])
+				continue;
+			for (j = 0; j < n_group; ++j)
+				isl_map_free(grid[i][j]);
+			free(grid[i]);
+		}
+	free(grid);
+	if (set) {
+		for (i = 0; i < 2 * n; ++i)
+			isl_set_free(set[i]);
+		free(set);
+	}
+	free(group);
+	return NULL;
+}
+
+/* Perform Floyd-Warshall on the given union relation.
+ * The implementation is very similar to that for non-unions.
+ * The main difference is that it is applied unconditionally.
+ * We first extract a list of basic maps from the union map
+ * and then perform the algorithm on this list.
+ */
+static __isl_give isl_union_map *union_floyd_warshall(
+	__isl_take isl_union_map *umap, int *exact)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_basic_map **list = NULL;
+	isl_basic_map **next;
+	isl_union_map *res;
+
+	n = 0;
+	if (isl_union_map_foreach_map(umap, inc_count, &n) < 0)
+		goto error;
+
+	ctx = isl_union_map_get_ctx(umap);
+	list = isl_calloc_array(ctx, isl_basic_map *, n);
+	if (!list)
+		goto error;
+
+	next = list;
+	if (isl_union_map_foreach_map(umap, collect_basic_map, &next) < 0)
+		goto error;
+
+	res = union_floyd_warshall_on_list(ctx, list, n, exact);
+
+	if (list) {
+		for (i = 0; i < n; ++i)
+			isl_basic_map_free(list[i]);
+		free(list);
+	}
+
+	isl_union_map_free(umap);
+	return res;
+error:
+	if (list) {
+		for (i = 0; i < n; ++i)
+			isl_basic_map_free(list[i]);
+		free(list);
+	}
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+/* Decompose the give union relation into strongly connected components.
+ * The implementation is essentially the same as that of
+ * construct_power_components with the major difference that all
+ * operations are performed on union maps.
+ */
+static __isl_give isl_union_map *union_components(
+	__isl_take isl_union_map *umap, int *exact)
+{
+	int i;
+	int n;
+	isl_ctx *ctx;
+	isl_basic_map **list = NULL;
+	isl_basic_map **next;
+	isl_union_map *path = NULL;
+	struct isl_tc_follows_data data;
+	struct isl_tarjan_graph *g = NULL;
+	int c, l;
+	int recheck = 0;
+
+	n = 0;
+	if (isl_union_map_foreach_map(umap, inc_count, &n) < 0)
+		goto error;
+
+	if (n == 0)
+		return umap;
+	if (n <= 1)
+		return union_floyd_warshall(umap, exact);
+
+	ctx = isl_union_map_get_ctx(umap);
+	list = isl_calloc_array(ctx, isl_basic_map *, n);
+	if (!list)
+		goto error;
+
+	next = list;
+	if (isl_union_map_foreach_map(umap, collect_basic_map, &next) < 0)
+		goto error;
+
+	data.list = list;
+	data.check_closed = 0;
+	g = isl_tarjan_graph_init(ctx, n, &basic_map_follows, &data);
+	if (!g)
+		goto error;
+
+	c = 0;
+	i = 0;
+	l = n;
+	path = isl_union_map_empty(isl_union_map_get_space(umap));
+	while (l) {
+		isl_union_map *comp;
+		isl_union_map *path_comp, *path_comb;
+		comp = isl_union_map_empty(isl_union_map_get_space(umap));
+		while (g->order[i] != -1) {
+			comp = isl_union_map_add_map(comp,
+				    isl_map_from_basic_map(
+					isl_basic_map_copy(list[g->order[i]])));
+			--l;
+			++i;
+		}
+		path_comp = union_floyd_warshall(comp, exact);
+		path_comb = isl_union_map_apply_range(isl_union_map_copy(path),
+						isl_union_map_copy(path_comp));
+		path = isl_union_map_union(path, path_comp);
+		path = isl_union_map_union(path, path_comb);
+		++i;
+		++c;
+	}
+
+	if (c > 1 && data.check_closed && !*exact) {
+		int closed;
+
+		closed = isl_union_map_is_transitively_closed(path);
+		if (closed < 0)
+			goto error;
+		recheck = !closed;
+	}
+
+	isl_tarjan_graph_free(g);
+
+	for (i = 0; i < n; ++i)
+		isl_basic_map_free(list[i]);
+	free(list);
+
+	if (recheck) {
+		isl_union_map_free(path);
+		return union_floyd_warshall(umap, exact);
+	}
+
+	isl_union_map_free(umap);
+
+	return path;
+error:
+	isl_tarjan_graph_free(g);
+	if (list) {
+		for (i = 0; i < n; ++i)
+			isl_basic_map_free(list[i]);
+		free(list);
+	}
+	isl_union_map_free(umap);
+	isl_union_map_free(path);
+	return NULL;
+}
+
+/* Compute the transitive closure  of "umap", or an overapproximation.
+ * If the result is exact, then *exact is set to 1.
+ */
+__isl_give isl_union_map *isl_union_map_transitive_closure(
+	__isl_take isl_union_map *umap, int *exact)
+{
+	int closed;
+
+	if (!umap)
+		return NULL;
+
+	if (exact)
+		*exact = 1;
+
+	umap = isl_union_map_compute_divs(umap);
+	umap = isl_union_map_coalesce(umap);
+	closed = isl_union_map_is_transitively_closed(umap);
+	if (closed < 0)
+		goto error;
+	if (closed)
+		return umap;
+	umap = union_components(umap, exact);
+	return umap;
+error:
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+struct isl_union_power {
+	isl_union_map *pow;
+	int *exact;
+};
+
+static int power(__isl_take isl_map *map, void *user)
+{
+	struct isl_union_power *up = user;
+
+	map = isl_map_power(map, up->exact);
+	up->pow = isl_union_map_from_map(map);
+
+	return -1;
+}
+
+/* Construct a map [x] -> [x+1], with parameters prescribed by "dim".
+ */
+static __isl_give isl_union_map *increment(__isl_take isl_space *dim)
+{
+	int k;
+	isl_basic_map *bmap;
+
+	dim = isl_space_add_dims(dim, isl_dim_in, 1);
+	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
+	k = isl_basic_map_alloc_equality(bmap);
+	if (k < 0)
+		goto error;
+	isl_seq_clr(bmap->eq[k], isl_basic_map_total_dim(bmap));
+	isl_int_set_si(bmap->eq[k][0], 1);
+	isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_in)], 1);
+	isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_out)], -1);
+	return isl_union_map_from_map(isl_map_from_basic_map(bmap));
+error:
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Construct a map [[x]->[y]] -> [y-x], with parameters prescribed by "dim".
+ */
+static __isl_give isl_union_map *deltas_map(__isl_take isl_space *dim)
+{
+	isl_basic_map *bmap;
+
+	dim = isl_space_add_dims(dim, isl_dim_in, 1);
+	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	bmap = isl_basic_map_universe(dim);
+	bmap = isl_basic_map_deltas_map(bmap);
+
+	return isl_union_map_from_map(isl_map_from_basic_map(bmap));
+}
+
+/* Compute the positive powers of "map", or an overapproximation.
+ * The result maps the exponent to a nested copy of the corresponding power.
+ * If the result is exact, then *exact is set to 1.
+ */
+__isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
+	int *exact)
+{
+	int n;
+	isl_union_map *inc;
+	isl_union_map *dm;
+
+	if (!umap)
+		return NULL;
+	n = isl_union_map_n_map(umap);
+	if (n == 0)
+		return umap;
+	if (n == 1) {
+		struct isl_union_power up = { NULL, exact };
+		isl_union_map_foreach_map(umap, &power, &up);
+		isl_union_map_free(umap);
+		return up.pow;
+	}
+	inc = increment(isl_union_map_get_space(umap));
+	umap = isl_union_map_product(inc, umap);
+	umap = isl_union_map_transitive_closure(umap, exact);
+	umap = isl_union_map_zip(umap);
+	dm = deltas_map(isl_union_map_get_space(umap));
+	umap = isl_union_map_apply_domain(umap, dm);
+	
+	return umap;
+}
+
+#undef TYPE
+#define TYPE isl_map
+#include "isl_power_templ.c"
+
+#undef TYPE
+#define TYPE isl_union_map
+#include "isl_power_templ.c"

Added: polly/trunk/lib/External/isl/isl_union_map.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_union_map.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_union_map.c (added)
+++ polly/trunk/lib/External/isl/isl_union_map.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3373 @@
+/*
+ * Copyright 2010-2011 INRIA Saclay
+ * Copyright 2013-2014 Ecole Normale Superieure
+ * Copyright 2014      INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France 
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#define ISL_DIM_H
+#include <isl_map_private.h>
+#include <isl/ctx.h>
+#include <isl/hash.h>
+#include <isl/aff.h>
+#include <isl/map.h>
+#include <isl/set.h>
+#include <isl_space_private.h>
+#include <isl_union_map_private.h>
+#include <isl/union_set.h>
+#include <isl/deprecated/union_map_int.h>
+
+/* Return the number of parameters of "umap", where "type"
+ * is required to be set to isl_dim_param.
+ */
+unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type)
+{
+	if (!umap)
+		return 0;
+
+	if (type != isl_dim_param)
+		isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+			"can only reference parameters", return 0);
+
+	return isl_space_dim(umap->dim, type);
+}
+
+/* Return the number of parameters of "uset", where "type"
+ * is required to be set to isl_dim_param.
+ */
+unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+	enum isl_dim_type type)
+{
+	return isl_union_map_dim(uset, type);
+}
+
+/* Return the id of the specified dimension.
+ */
+__isl_give isl_id *isl_union_map_get_dim_id(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type, unsigned pos)
+{
+	if (!umap)
+		return NULL;
+
+	if (type != isl_dim_param)
+		isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+			"can only reference parameters", return NULL);
+
+	return isl_space_get_dim_id(umap->dim, type, pos);
+}
+
+/* Is this union set a parameter domain?
+ */
+int isl_union_set_is_params(__isl_keep isl_union_set *uset)
+{
+	isl_set *set;
+	int params;
+
+	if (!uset)
+		return -1;
+	if (uset->table.n != 1)
+		return 0;
+
+	set = isl_set_from_union_set(isl_union_set_copy(uset));
+	params = isl_set_is_params(set);
+	isl_set_free(set);
+	return params;
+}
+
+static __isl_give isl_union_map *isl_union_map_alloc(
+	__isl_take isl_space *space, int size)
+{
+	isl_union_map *umap;
+
+	space = isl_space_params(space);
+	if (!space)
+		return NULL;
+
+	umap = isl_calloc_type(space->ctx, isl_union_map);
+	if (!umap) {
+		isl_space_free(space);
+		return NULL;
+	}
+
+	umap->ref = 1;
+	umap->dim = space;
+	if (isl_hash_table_init(space->ctx, &umap->table, size) < 0)
+		return isl_union_map_free(umap);
+
+	return umap;
+}
+
+__isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *dim)
+{
+	return isl_union_map_alloc(dim, 16);
+}
+
+__isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *dim)
+{
+	return isl_union_map_empty(dim);
+}
+
+isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap)
+{
+	return umap ? umap->dim->ctx : NULL;
+}
+
+isl_ctx *isl_union_set_get_ctx(__isl_keep isl_union_set *uset)
+{
+	return uset ? uset->dim->ctx : NULL;
+}
+
+__isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap)
+{
+	if (!umap)
+		return NULL;
+	return isl_space_copy(umap->dim);
+}
+
+/* Return the position of the parameter with the given name
+ * in "umap".
+ * Return -1 if no such dimension can be found.
+ */
+int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type, const char *name)
+{
+	if (!umap)
+		return -1;
+	return isl_space_find_dim_by_name(umap->dim, type, name);
+}
+
+__isl_give isl_space *isl_union_set_get_space(__isl_keep isl_union_set *uset)
+{
+	return isl_union_map_get_space(uset);
+}
+
+static int free_umap_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_map_free(map);
+	return 0;
+}
+
+static int add_map(__isl_take isl_map *map, void *user)
+{
+	isl_union_map **umap = (isl_union_map **)user;
+
+	*umap = isl_union_map_add_map(*umap, map);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_dup(__isl_keep isl_union_map *umap)
+{
+	isl_union_map *dup;
+
+	if (!umap)
+		return NULL;
+
+	dup = isl_union_map_empty(isl_space_copy(umap->dim));
+	if (isl_union_map_foreach_map(umap, &add_map, &dup) < 0)
+		goto error;
+	return dup;
+error:
+	isl_union_map_free(dup);
+	return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_cow(__isl_take isl_union_map *umap)
+{
+	if (!umap)
+		return NULL;
+
+	if (umap->ref == 1)
+		return umap;
+	umap->ref--;
+	return isl_union_map_dup(umap);
+}
+
+struct isl_union_align {
+	isl_reordering *exp;
+	isl_union_map *res;
+};
+
+static int align_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_reordering *exp;
+	struct isl_union_align *data = user;
+
+	exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+				    isl_map_get_space(map));
+
+	data->res = isl_union_map_add_map(data->res,
+					isl_map_realign(isl_map_copy(map), exp));
+
+	return 0;
+}
+
+/* Align the parameters of umap along those of model.
+ * The result has the parameters of model first, in the same order
+ * as they appear in model, followed by any remaining parameters of
+ * umap that do not appear in model.
+ */
+__isl_give isl_union_map *isl_union_map_align_params(
+	__isl_take isl_union_map *umap, __isl_take isl_space *model)
+{
+	struct isl_union_align data = { NULL, NULL };
+
+	if (!umap || !model)
+		goto error;
+
+	if (isl_space_match(umap->dim, isl_dim_param, model, isl_dim_param)) {
+		isl_space_free(model);
+		return umap;
+	}
+
+	model = isl_space_params(model);
+	data.exp = isl_parameter_alignment_reordering(umap->dim, model);
+	if (!data.exp)
+		goto error;
+
+	data.res = isl_union_map_alloc(isl_space_copy(data.exp->dim),
+					umap->table.n);
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+					&align_entry, &data) < 0)
+		goto error;
+
+	isl_reordering_free(data.exp);
+	isl_union_map_free(umap);
+	isl_space_free(model);
+	return data.res;
+error:
+	isl_reordering_free(data.exp);
+	isl_union_map_free(umap);
+	isl_union_map_free(data.res);
+	isl_space_free(model);
+	return NULL;
+}
+
+__isl_give isl_union_set *isl_union_set_align_params(
+	__isl_take isl_union_set *uset, __isl_take isl_space *model)
+{
+	return isl_union_map_align_params(uset, model);
+}
+
+__isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
+	__isl_take isl_union_map *umap2)
+{
+	umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+	umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+	umap1 = isl_union_map_cow(umap1);
+
+	if (!umap1 || !umap2)
+		goto error;
+
+	if (isl_union_map_foreach_map(umap2, &add_map, &umap1) < 0)
+		goto error;
+
+	isl_union_map_free(umap2);
+
+	return umap1;
+error:
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	return NULL;
+}
+
+__isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
+	__isl_take isl_union_set *uset2)
+{
+	return isl_union_map_union(uset1, uset2);
+}
+
+__isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap)
+{
+	if (!umap)
+		return NULL;
+
+	umap->ref++;
+	return umap;
+}
+
+__isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset)
+{
+	return isl_union_map_copy(uset);
+}
+
+__isl_null isl_union_map *isl_union_map_free(__isl_take isl_union_map *umap)
+{
+	if (!umap)
+		return NULL;
+
+	if (--umap->ref > 0)
+		return NULL;
+
+	isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+			       &free_umap_entry, NULL);
+	isl_hash_table_clear(&umap->table);
+	isl_space_free(umap->dim);
+	free(umap);
+	return NULL;
+}
+
+__isl_null isl_union_set *isl_union_set_free(__isl_take isl_union_set *uset)
+{
+	return isl_union_map_free(uset);
+}
+
+static int has_dim(const void *entry, const void *val)
+{
+	isl_map *map = (isl_map *)entry;
+	isl_space *dim = (isl_space *)val;
+
+	return isl_space_is_equal(map->dim, dim);
+}
+
+__isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
+	__isl_take isl_map *map)
+{
+	uint32_t hash;
+	struct isl_hash_table_entry *entry;
+
+	if (!map || !umap)
+		goto error;
+
+	if (isl_map_plain_is_empty(map)) {
+		isl_map_free(map);
+		return umap;
+	}
+
+	if (!isl_space_match(map->dim, isl_dim_param, umap->dim, isl_dim_param)) {
+		umap = isl_union_map_align_params(umap, isl_map_get_space(map));
+		map = isl_map_align_params(map, isl_union_map_get_space(umap));
+	}
+
+	umap = isl_union_map_cow(umap);
+
+	if (!map || !umap)
+		goto error;
+
+	hash = isl_space_get_hash(map->dim);
+	entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
+				    &has_dim, map->dim, 1);
+	if (!entry)
+		goto error;
+
+	if (!entry->data)
+		entry->data = map;
+	else {
+		entry->data = isl_map_union(entry->data, isl_map_copy(map));
+		if (!entry->data)
+			goto error;
+		isl_map_free(map);
+	}
+
+	return umap;
+error:
+	isl_map_free(map);
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+__isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
+	__isl_take isl_set *set)
+{
+	return isl_union_map_add_map(uset, (isl_map *)set);
+}
+
+__isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map)
+{
+	isl_space *dim;
+	isl_union_map *umap;
+
+	if (!map)
+		return NULL;
+
+	dim = isl_map_get_space(map);
+	dim = isl_space_params(dim);
+	umap = isl_union_map_empty(dim);
+	umap = isl_union_map_add_map(umap, map);
+
+	return umap;
+}
+
+__isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set)
+{
+	return isl_union_map_from_map((isl_map *)set);
+}
+
+__isl_give isl_union_map *isl_union_map_from_basic_map(
+	__isl_take isl_basic_map *bmap)
+{
+	return isl_union_map_from_map(isl_map_from_basic_map(bmap));
+}
+
+__isl_give isl_union_set *isl_union_set_from_basic_set(
+	__isl_take isl_basic_set *bset)
+{
+	return isl_union_map_from_basic_map(bset);
+}
+
+struct isl_union_map_foreach_data
+{
+	int (*fn)(__isl_take isl_map *map, void *user);
+	void *user;
+};
+
+static int call_on_copy(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	struct isl_union_map_foreach_data *data;
+	data = (struct isl_union_map_foreach_data *)user;
+
+	return data->fn(isl_map_copy(map), data->user);
+}
+
+int isl_union_map_n_map(__isl_keep isl_union_map *umap)
+{
+	return umap ? umap->table.n : 0;
+}
+
+int isl_union_set_n_set(__isl_keep isl_union_set *uset)
+{
+	return uset ? uset->table.n : 0;
+}
+
+int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
+	int (*fn)(__isl_take isl_map *map, void *user), void *user)
+{
+	struct isl_union_map_foreach_data data = { fn, user };
+
+	if (!umap)
+		return -1;
+
+	return isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+				      &call_on_copy, &data);
+}
+
+static int copy_map(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_map **map_p = user;
+
+	*map_p = isl_map_copy(map);
+
+	return -1;
+}
+
+__isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap)
+{
+	isl_ctx *ctx;
+	isl_map *map = NULL;
+
+	if (!umap)
+		return NULL;
+	ctx = isl_union_map_get_ctx(umap);
+	if (umap->table.n != 1)
+		isl_die(ctx, isl_error_invalid,
+			"union map needs to contain elements in exactly "
+			"one space", goto error);
+
+	isl_hash_table_foreach(ctx, &umap->table, &copy_map, &map);
+
+	isl_union_map_free(umap);
+
+	return map;
+error:
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+__isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset)
+{
+	return isl_map_from_union_map(uset);
+}
+
+/* Extract the map in "umap" that lives in the given space (ignoring
+ * parameters).
+ */
+__isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
+	__isl_take isl_space *space)
+{
+	uint32_t hash;
+	struct isl_hash_table_entry *entry;
+
+	space = isl_space_drop_dims(space, isl_dim_param,
+					0, isl_space_dim(space, isl_dim_param));
+	space = isl_space_align_params(space, isl_union_map_get_space(umap));
+	if (!umap || !space)
+		goto error;
+
+	hash = isl_space_get_hash(space);
+	entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
+				    &has_dim, space, 0);
+	if (!entry)
+		return isl_map_empty(space);
+	isl_space_free(space);
+	return isl_map_copy(entry->data);
+error:
+	isl_space_free(space);
+	return NULL;
+}
+
+__isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
+	__isl_take isl_space *dim)
+{
+	return (isl_set *)isl_union_map_extract_map(uset, dim);
+}
+
+/* Check if umap contains a map in the given space.
+ */
+__isl_give int isl_union_map_contains(__isl_keep isl_union_map *umap,
+	__isl_keep isl_space *dim)
+{
+	uint32_t hash;
+	struct isl_hash_table_entry *entry;
+
+	if (!umap || !dim)
+		return -1;
+
+	hash = isl_space_get_hash(dim);
+	entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
+				    &has_dim, dim, 0);
+	return !!entry;
+}
+
+__isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
+	__isl_keep isl_space *dim)
+{
+	return isl_union_map_contains(uset, dim);
+}
+
+int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
+	int (*fn)(__isl_take isl_set *set, void *user), void *user)
+{
+	return isl_union_map_foreach_map(uset,
+		(int(*)(__isl_take isl_map *, void*))fn, user);
+}
+
+struct isl_union_set_foreach_point_data {
+	int (*fn)(__isl_take isl_point *pnt, void *user);
+	void *user;
+};
+
+static int foreach_point(__isl_take isl_set *set, void *user)
+{
+	struct isl_union_set_foreach_point_data *data = user;
+	int r;
+
+	r = isl_set_foreach_point(set, data->fn, data->user);
+	isl_set_free(set);
+
+	return r;
+}
+
+int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
+	int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
+{
+	struct isl_union_set_foreach_point_data data = { fn, user };
+	return isl_union_set_foreach_set(uset, &foreach_point, &data);
+}
+
+struct isl_union_map_gen_bin_data {
+	isl_union_map *umap2;
+	isl_union_map *res;
+};
+
+static int subtract_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_map *map = *entry;
+
+	hash = isl_space_get_hash(map->dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, map->dim, 0);
+	map = isl_map_copy(map);
+	if (entry2) {
+		int empty;
+		map = isl_map_subtract(map, isl_map_copy(entry2->data));
+
+		empty = isl_map_is_empty(map);
+		if (empty < 0) {
+			isl_map_free(map);
+			return -1;
+		}
+		if (empty) {
+			isl_map_free(map);
+			return 0;
+		}
+	}
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+static __isl_give isl_union_map *gen_bin_op(__isl_take isl_union_map *umap1,
+	__isl_take isl_union_map *umap2, int (*fn)(void **, void *))
+{
+	struct isl_union_map_gen_bin_data data = { NULL, NULL };
+
+	umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+	umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+	if (!umap1 || !umap2)
+		goto error;
+
+	data.umap2 = umap2;
+	data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
+				       umap1->table.n);
+	if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+				   fn, &data) < 0)
+		goto error;
+
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	return data.res;
+error:
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	isl_union_map_free(data.res);
+	return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_subtract(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return gen_bin_op(umap1, umap2, &subtract_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_subtract(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+	return isl_union_map_subtract(uset1, uset2);
+}
+
+struct isl_union_map_gen_bin_set_data {
+	isl_set *set;
+	isl_union_map *res;
+};
+
+static int intersect_params_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_set_data *data = user;
+	isl_map *map = *entry;
+	int empty;
+
+	map = isl_map_copy(map);
+	map = isl_map_intersect_params(map, isl_set_copy(data->set));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+static __isl_give isl_union_map *gen_bin_set_op(__isl_take isl_union_map *umap,
+	__isl_take isl_set *set, int (*fn)(void **, void *))
+{
+	struct isl_union_map_gen_bin_set_data data = { NULL, NULL };
+
+	umap = isl_union_map_align_params(umap, isl_set_get_space(set));
+	set = isl_set_align_params(set, isl_union_map_get_space(umap));
+
+	if (!umap || !set)
+		goto error;
+
+	data.set = set;
+	data.res = isl_union_map_alloc(isl_space_copy(umap->dim),
+				       umap->table.n);
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+				   fn, &data) < 0)
+		goto error;
+
+	isl_union_map_free(umap);
+	isl_set_free(set);
+	return data.res;
+error:
+	isl_union_map_free(umap);
+	isl_set_free(set);
+	isl_union_map_free(data.res);
+	return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect_params(
+	__isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+	return gen_bin_set_op(umap, set, &intersect_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_intersect_params(
+	__isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+	return isl_union_map_intersect_params(uset, set);
+}
+
+static __isl_give isl_union_map *union_map_intersect_params(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+	return isl_union_map_intersect_params(umap,
+						isl_set_from_union_set(uset));
+}
+
+static __isl_give isl_union_map *union_map_gist_params(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+	return isl_union_map_gist_params(umap, isl_set_from_union_set(uset));
+}
+
+struct isl_union_map_match_bin_data {
+	isl_union_map *umap2;
+	isl_union_map *res;
+	__isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*);
+};
+
+static int match_bin_entry(void **entry, void *user)
+{
+	struct isl_union_map_match_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_map *map = *entry;
+	int empty;
+
+	hash = isl_space_get_hash(map->dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, map->dim, 0);
+	if (!entry2)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = data->fn(map, isl_map_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+	if (empty) {
+		isl_map_free(map);
+		return 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+static __isl_give isl_union_map *match_bin_op(__isl_take isl_union_map *umap1,
+	__isl_take isl_union_map *umap2,
+	__isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*))
+{
+	struct isl_union_map_match_bin_data data = { NULL, NULL, fn };
+
+	umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+	umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+	if (!umap1 || !umap2)
+		goto error;
+
+	data.umap2 = umap2;
+	data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
+				       umap1->table.n);
+	if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+				   &match_bin_entry, &data) < 0)
+		goto error;
+
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	return data.res;
+error:
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	isl_union_map_free(data.res);
+	return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return match_bin_op(umap1, umap2, &isl_map_intersect);
+}
+
+/* Compute the intersection of the two union_sets.
+ * As a special case, if exactly one of the two union_sets
+ * is a parameter domain, then intersect the parameter domain
+ * of the other one with this set.
+ */
+__isl_give isl_union_set *isl_union_set_intersect(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+	int p1, p2;
+
+	p1 = isl_union_set_is_params(uset1);
+	p2 = isl_union_set_is_params(uset2);
+	if (p1 < 0 || p2 < 0)
+		goto error;
+	if (!p1 && p2)
+		return union_map_intersect_params(uset1, uset2);
+	if (p1 && !p2)
+		return union_map_intersect_params(uset2, uset1);
+	return isl_union_map_intersect(uset1, uset2);
+error:
+	isl_union_set_free(uset1);
+	isl_union_set_free(uset2);
+	return NULL;
+}
+
+static int gist_params_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_set_data *data = user;
+	isl_map *map = *entry;
+	int empty;
+
+	map = isl_map_copy(map);
+	map = isl_map_gist_params(map, isl_set_copy(data->set));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_gist_params(
+	__isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+	return gen_bin_set_op(umap, set, &gist_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_gist_params(
+	__isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+	return isl_union_map_gist_params(uset, set);
+}
+
+__isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
+	__isl_take isl_union_map *context)
+{
+	return match_bin_op(umap, context, &isl_map_gist);
+}
+
+__isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
+	__isl_take isl_union_set *context)
+{
+	if (isl_union_set_is_params(context))
+		return union_map_gist_params(uset, context);
+	return isl_union_map_gist(uset, context);
+}
+
+static __isl_give isl_map *lex_le_set(__isl_take isl_map *set1,
+	__isl_take isl_map *set2)
+{
+	return isl_set_lex_le_set((isl_set *)set1, (isl_set *)set2);
+}
+
+static __isl_give isl_map *lex_lt_set(__isl_take isl_map *set1,
+	__isl_take isl_map *set2)
+{
+	return isl_set_lex_lt_set((isl_set *)set1, (isl_set *)set2);
+}
+
+__isl_give isl_union_map *isl_union_set_lex_lt_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+	return match_bin_op(uset1, uset2, &lex_lt_set);
+}
+
+__isl_give isl_union_map *isl_union_set_lex_le_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+	return match_bin_op(uset1, uset2, &lex_le_set);
+}
+
+__isl_give isl_union_map *isl_union_set_lex_gt_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+	return isl_union_map_reverse(isl_union_set_lex_lt_union_set(uset2, uset1));
+}
+
+__isl_give isl_union_map *isl_union_set_lex_ge_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+	return isl_union_map_reverse(isl_union_set_lex_le_union_set(uset2, uset1));
+}
+
+__isl_give isl_union_map *isl_union_map_lex_gt_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return isl_union_map_reverse(isl_union_map_lex_lt_union_map(umap2, umap1));
+}
+
+__isl_give isl_union_map *isl_union_map_lex_ge_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return isl_union_map_reverse(isl_union_map_lex_le_union_map(umap2, umap1));
+}
+
+static int intersect_domain_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *dim;
+	isl_map *map = *entry;
+	int empty;
+
+	dim = isl_map_get_space(map);
+	dim = isl_space_domain(dim);
+	hash = isl_space_get_hash(dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, dim, 0);
+	isl_space_free(dim);
+	if (!entry2)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = isl_map_intersect_domain(map, isl_set_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+	if (empty) {
+		isl_map_free(map);
+		return 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Intersect the domain of "umap" with "uset".
+ * If "uset" is a parameters domain, then intersect the parameter
+ * domain of "umap" with this set.
+ */
+__isl_give isl_union_map *isl_union_map_intersect_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+	if (isl_union_set_is_params(uset))
+		return union_map_intersect_params(umap, uset);
+	return gen_bin_op(umap, uset, &intersect_domain_entry);
+}
+
+/* Remove the elements of data->umap2 from the domain of *entry
+ * and add the result to data->res.
+ */
+static int subtract_domain_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *dim;
+	isl_map *map = *entry;
+	int empty;
+
+	dim = isl_map_get_space(map);
+	dim = isl_space_domain(dim);
+	hash = isl_space_get_hash(dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, dim, 0);
+	isl_space_free(dim);
+
+	map = isl_map_copy(map);
+
+	if (!entry2) {
+		data->res = isl_union_map_add_map(data->res, map);
+		return 0;
+	}
+
+	map = isl_map_subtract_domain(map, isl_set_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+	if (empty) {
+		isl_map_free(map);
+		return 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Remove the elements of "uset" from the domain of "umap".
+ */
+__isl_give isl_union_map *isl_union_map_subtract_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *dom)
+{
+	return gen_bin_op(umap, dom, &subtract_domain_entry);
+}
+
+/* Remove the elements of data->umap2 from the range of *entry
+ * and add the result to data->res.
+ */
+static int subtract_range_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *space;
+	isl_map *map = *entry;
+	int empty;
+
+	space = isl_map_get_space(map);
+	space = isl_space_range(space);
+	hash = isl_space_get_hash(space);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, space, 0);
+	isl_space_free(space);
+
+	map = isl_map_copy(map);
+
+	if (!entry2) {
+		data->res = isl_union_map_add_map(data->res, map);
+		return 0;
+	}
+
+	map = isl_map_subtract_range(map, isl_set_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+	if (empty) {
+		isl_map_free(map);
+		return 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Remove the elements of "uset" from the range of "umap".
+ */
+__isl_give isl_union_map *isl_union_map_subtract_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *dom)
+{
+	return gen_bin_op(umap, dom, &subtract_range_entry);
+}
+
+static int gist_domain_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *dim;
+	isl_map *map = *entry;
+	int empty;
+
+	dim = isl_map_get_space(map);
+	dim = isl_space_domain(dim);
+	hash = isl_space_get_hash(dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, dim, 0);
+	isl_space_free(dim);
+	if (!entry2)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = isl_map_gist_domain(map, isl_set_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Compute the gist of "umap" with respect to the domain "uset".
+ * If "uset" is a parameters domain, then compute the gist
+ * with respect to this parameter domain.
+ */
+__isl_give isl_union_map *isl_union_map_gist_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+	if (isl_union_set_is_params(uset))
+		return union_map_gist_params(umap, uset);
+	return gen_bin_op(umap, uset, &gist_domain_entry);
+}
+
+static int gist_range_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *space;
+	isl_map *map = *entry;
+	int empty;
+
+	space = isl_map_get_space(map);
+	space = isl_space_range(space);
+	hash = isl_space_get_hash(space);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, space, 0);
+	isl_space_free(space);
+	if (!entry2)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = isl_map_gist_range(map, isl_set_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Compute the gist of "umap" with respect to the range "uset".
+ */
+__isl_give isl_union_map *isl_union_map_gist_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+	return gen_bin_op(umap, uset, &gist_range_entry);
+}
+
+static int intersect_range_entry(void **entry, void *user)
+{
+	struct isl_union_map_gen_bin_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *dim;
+	isl_map *map = *entry;
+	int empty;
+
+	dim = isl_map_get_space(map);
+	dim = isl_space_range(dim);
+	hash = isl_space_get_hash(dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, dim, 0);
+	isl_space_free(dim);
+	if (!entry2)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = isl_map_intersect_range(map, isl_set_copy(entry2->data));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0) {
+		isl_map_free(map);
+		return -1;
+	}
+	if (empty) {
+		isl_map_free(map);
+		return 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+	return gen_bin_op(umap, uset, &intersect_range_entry);
+}
+
+struct isl_union_map_bin_data {
+	isl_union_map *umap2;
+	isl_union_map *res;
+	isl_map *map;
+	int (*fn)(void **entry, void *user);
+};
+
+static int apply_range_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+	int empty;
+
+	if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+				 map2->dim, isl_dim_in))
+		return 0;
+
+	map2 = isl_map_apply_range(isl_map_copy(data->map), isl_map_copy(map2));
+
+	empty = isl_map_is_empty(map2);
+	if (empty < 0) {
+		isl_map_free(map2);
+		return -1;
+	}
+	if (empty) {
+		isl_map_free(map2);
+		return 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+static int bin_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map = *entry;
+
+	data->map = map;
+	if (isl_hash_table_foreach(data->umap2->dim->ctx, &data->umap2->table,
+				   data->fn, data) < 0)
+		return -1;
+
+	return 0;
+}
+
+static __isl_give isl_union_map *bin_op(__isl_take isl_union_map *umap1,
+	__isl_take isl_union_map *umap2, int (*fn)(void **entry, void *user))
+{
+	struct isl_union_map_bin_data data = { NULL, NULL, NULL, fn };
+
+	umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+	umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+	if (!umap1 || !umap2)
+		goto error;
+
+	data.umap2 = umap2;
+	data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
+				       umap1->table.n);
+	if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+				   &bin_entry, &data) < 0)
+		goto error;
+
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	return data.res;
+error:
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	isl_union_map_free(data.res);
+	return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_apply_range(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &apply_range_entry);
+}
+
+__isl_give isl_union_map *isl_union_map_apply_domain(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	umap1 = isl_union_map_reverse(umap1);
+	umap1 = isl_union_map_apply_range(umap1, umap2);
+	return isl_union_map_reverse(umap1);
+}
+
+__isl_give isl_union_set *isl_union_set_apply(
+	__isl_take isl_union_set *uset, __isl_take isl_union_map *umap)
+{
+	return isl_union_map_apply_range(uset, umap);
+}
+
+static int map_lex_lt_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+
+	if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+				 map2->dim, isl_dim_out))
+		return 0;
+
+	map2 = isl_map_lex_lt_map(isl_map_copy(data->map), isl_map_copy(map2));
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_lex_lt_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &map_lex_lt_entry);
+}
+
+static int map_lex_le_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+
+	if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+				 map2->dim, isl_dim_out))
+		return 0;
+
+	map2 = isl_map_lex_le_map(isl_map_copy(data->map), isl_map_copy(map2));
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_lex_le_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &map_lex_le_entry);
+}
+
+static int product_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+
+	map2 = isl_map_product(isl_map_copy(data->map), isl_map_copy(map2));
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
+	__isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &product_entry);
+}
+
+static int set_product_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_set *set2 = *entry;
+
+	set2 = isl_set_product(isl_set_copy(data->map), isl_set_copy(set2));
+
+	data->res = isl_union_set_add_set(data->res, set2);
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
+	__isl_take isl_union_set *uset2)
+{
+	return bin_op(uset1, uset2, &set_product_entry);
+}
+
+static int domain_product_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+
+	if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+				 map2->dim, isl_dim_out))
+		return 0;
+
+	map2 = isl_map_domain_product(isl_map_copy(data->map),
+				     isl_map_copy(map2));
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
+ */
+__isl_give isl_union_map *isl_union_map_domain_product(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &domain_product_entry);
+}
+
+static int range_product_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+
+	if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_in,
+				 map2->dim, isl_dim_in))
+		return 0;
+
+	map2 = isl_map_range_product(isl_map_copy(data->map),
+				     isl_map_copy(map2));
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_range_product(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &range_product_entry);
+}
+
+static int flat_range_product_entry(void **entry, void *user)
+{
+	struct isl_union_map_bin_data *data = user;
+	isl_map *map2 = *entry;
+
+	if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_in,
+				 map2->dim, isl_dim_in))
+		return 0;
+
+	map2 = isl_map_flat_range_product(isl_map_copy(data->map),
+					  isl_map_copy(map2));
+
+	data->res = isl_union_map_add_map(data->res, map2);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_flat_range_product(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+	return bin_op(umap1, umap2, &flat_range_product_entry);
+}
+
+static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
+	int (*fn)(void **, void *))
+{
+	isl_union_set *res;
+
+	if (!umap)
+		return NULL;
+
+	res = isl_union_map_alloc(isl_space_copy(umap->dim), umap->table.n);
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
+		goto error;
+
+	isl_union_map_free(umap);
+	return res;
+error:
+	isl_union_map_free(umap);
+	isl_union_set_free(res);
+	return NULL;
+}
+
+static int from_range_entry(void **entry, void *user)
+{
+	isl_map *set = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_map_add_map(*res,
+					isl_map_from_range(isl_set_copy(set)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_from_range(
+	__isl_take isl_union_set *uset)
+{
+	return cond_un_op(uset, &from_range_entry);
+}
+
+__isl_give isl_union_map *isl_union_map_from_domain(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_reverse(isl_union_map_from_range(uset));
+}
+
+__isl_give isl_union_map *isl_union_map_from_domain_and_range(
+	__isl_take isl_union_set *domain, __isl_take isl_union_set *range)
+{
+	return isl_union_map_apply_range(isl_union_map_from_domain(domain),
+				         isl_union_map_from_range(range));
+}
+
+static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
+	int (*fn)(void **, void *))
+{
+	umap = isl_union_map_cow(umap);
+	if (!umap)
+		return NULL;
+
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, NULL) < 0)
+		goto error;
+
+	return umap;
+error:
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+static int affine_entry(void **entry, void *user)
+{
+	isl_map **map = (isl_map **)entry;
+
+	*map = isl_map_from_basic_map(isl_map_affine_hull(*map));
+
+	return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_affine_hull(
+	__isl_take isl_union_map *umap)
+{
+	return un_op(umap, &affine_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_affine_hull(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_affine_hull(uset);
+}
+
+static int polyhedral_entry(void **entry, void *user)
+{
+	isl_map **map = (isl_map **)entry;
+
+	*map = isl_map_from_basic_map(isl_map_polyhedral_hull(*map));
+
+	return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_polyhedral_hull(
+	__isl_take isl_union_map *umap)
+{
+	return un_op(umap, &polyhedral_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_polyhedral_hull(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_polyhedral_hull(uset);
+}
+
+static int simple_entry(void **entry, void *user)
+{
+	isl_map **map = (isl_map **)entry;
+
+	*map = isl_map_from_basic_map(isl_map_simple_hull(*map));
+
+	return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_simple_hull(
+	__isl_take isl_union_map *umap)
+{
+	return un_op(umap, &simple_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_simple_hull(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_simple_hull(uset);
+}
+
+static int inplace_entry(void **entry, void *user)
+{
+	__isl_give isl_map *(*fn)(__isl_take isl_map *);
+	isl_map **map = (isl_map **)entry;
+	isl_map *copy;
+
+	fn = *(__isl_give isl_map *(**)(__isl_take isl_map *)) user;
+	copy = fn(isl_map_copy(*map));
+	if (!copy)
+		return -1;
+
+	isl_map_free(*map);
+	*map = copy;
+
+	return 0;
+}
+
+static __isl_give isl_union_map *inplace(__isl_take isl_union_map *umap,
+	__isl_give isl_map *(*fn)(__isl_take isl_map *))
+{
+	if (!umap)
+		return NULL;
+
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+				    &inplace_entry, &fn) < 0)
+		goto error;
+
+	return umap;
+error:
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_coalesce(
+	__isl_take isl_union_map *umap)
+{
+	return inplace(umap, &isl_map_coalesce);
+}
+
+__isl_give isl_union_set *isl_union_set_coalesce(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_coalesce(uset);
+}
+
+__isl_give isl_union_map *isl_union_map_detect_equalities(
+	__isl_take isl_union_map *umap)
+{
+	return inplace(umap, &isl_map_detect_equalities);
+}
+
+__isl_give isl_union_set *isl_union_set_detect_equalities(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_detect_equalities(uset);
+}
+
+__isl_give isl_union_map *isl_union_map_compute_divs(
+	__isl_take isl_union_map *umap)
+{
+	return inplace(umap, &isl_map_compute_divs);
+}
+
+__isl_give isl_union_set *isl_union_set_compute_divs(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_compute_divs(uset);
+}
+
+static int lexmin_entry(void **entry, void *user)
+{
+	isl_map **map = (isl_map **)entry;
+
+	*map = isl_map_lexmin(*map);
+
+	return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_lexmin(
+	__isl_take isl_union_map *umap)
+{
+	return un_op(umap, &lexmin_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_lexmin(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_lexmin(uset);
+}
+
+static int lexmax_entry(void **entry, void *user)
+{
+	isl_map **map = (isl_map **)entry;
+
+	*map = isl_map_lexmax(*map);
+
+	return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_lexmax(
+	__isl_take isl_union_map *umap)
+{
+	return un_op(umap, &lexmax_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_lexmax(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_lexmax(uset);
+}
+
+static int universe_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	map = isl_map_universe(isl_map_get_space(map));
+	*res = isl_union_map_add_map(*res, map);
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_universe(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &universe_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_universe(__isl_take isl_union_set *uset)
+{
+	return isl_union_map_universe(uset);
+}
+
+static int reverse_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	*res = isl_union_map_add_map(*res, isl_map_reverse(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &reverse_entry);
+}
+
+static int params_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_set_add_set(*res, isl_map_params(isl_map_copy(map)));
+
+	return 0;
+}
+
+/* Compute the parameter domain of the given union map.
+ */
+__isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap)
+{
+	int empty;
+
+	empty = isl_union_map_is_empty(umap);
+	if (empty < 0)
+		goto error;
+	if (empty) {
+		isl_space *space;
+		space = isl_union_map_get_space(umap);
+		isl_union_map_free(umap);
+		return isl_set_empty(space);
+	}
+	return isl_set_from_union_set(cond_un_op(umap, &params_entry));
+error:
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+/* Compute the parameter domain of the given union set.
+ */
+__isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset)
+{
+	return isl_union_map_params(uset);
+}
+
+static int domain_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_set_add_set(*res, isl_map_domain(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &domain_entry);
+}
+
+static int range_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_set_add_set(*res, isl_map_range(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &range_entry);
+}
+
+static int domain_map_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_map_add_map(*res,
+					isl_map_domain_map(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_domain_map(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &domain_map_entry);
+}
+
+static int range_map_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_map_add_map(*res,
+					isl_map_range_map(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_range_map(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &range_map_entry);
+}
+
+/* Check if "set" is of the form A[B -> C].
+ * If so, add A[B -> C] -> B to "res".
+ */
+static int wrapped_domain_map_entry(void **entry, void *user)
+{
+	isl_set *set = *entry;
+	isl_union_set **res = user;
+	int wrapping;
+
+	wrapping = isl_set_is_wrapping(set);
+	if (wrapping < 0)
+		return -1;
+	if (!wrapping)
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+				isl_set_wrapped_domain_map(isl_set_copy(set)));
+
+	return 0;
+}
+
+/* Given a collection of wrapped maps of the form A[B -> C],
+ * return the collection of maps A[B -> C] -> B.
+ */
+__isl_give isl_union_map *isl_union_set_wrapped_domain_map(
+	__isl_take isl_union_set *uset)
+{
+	return cond_un_op(uset, &wrapped_domain_map_entry);
+}
+
+static int deltas_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+					map->dim, isl_dim_out))
+		return 0;
+
+	*res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &deltas_entry);
+}
+
+static int deltas_map_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+					map->dim, isl_dim_out))
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+				     isl_map_deltas_map(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_deltas_map(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &deltas_map_entry);
+}
+
+static int identity_entry(void **entry, void *user)
+{
+	isl_set *set = *entry;
+	isl_union_map **res = user;
+
+	*res = isl_union_map_add_map(*res, isl_set_identity(isl_set_copy(set)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset)
+{
+	return cond_un_op(uset, &identity_entry);
+}
+
+/* If "map" is of the form [A -> B] -> C, then add A -> C to "res".
+ */
+static int domain_factor_domain_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_domain_is_wrapping(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+			    isl_map_domain_factor_domain(isl_map_copy(map)));
+
+	return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> C,
+ * construct the map A -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_domain_factor_domain(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &domain_factor_domain_entry);
+}
+
+/* If "map" is of the form [A -> B] -> C, then add B -> C to "res".
+ */
+static int domain_factor_range_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_domain_is_wrapping(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+				isl_map_domain_factor_range(isl_map_copy(map)));
+
+	return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> C,
+ * construct the map B -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_domain_factor_range(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &domain_factor_range_entry);
+}
+
+/* If "map" is of the form A -> [B -> C], then add A -> C to "res".
+ */
+static int range_factor_range_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_range_is_wrapping(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+				isl_map_range_factor_range(isl_map_copy(map)));
+
+	return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form A -> [B -> C],
+ * construct the map A -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_range_factor_range(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &range_factor_range_entry);
+}
+
+/* If "map" is of the form [A -> B] -> [C -> D], then add A -> C to "res".
+ */
+static int factor_domain_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_domain_is_wrapping(map) || !isl_map_range_is_wrapping(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+				isl_map_factor_domain(isl_map_copy(map)));
+
+	return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> [C -> D],
+ * construct the map A -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_factor_domain(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &factor_domain_entry);
+}
+
+/* If "map" is of the form [A -> B] -> [C -> D], then add B -> D to "res".
+ */
+static int factor_range_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_domain_is_wrapping(map) || !isl_map_range_is_wrapping(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res,
+				isl_map_factor_range(isl_map_copy(map)));
+
+	return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> [C -> D],
+ * construct the map B -> D and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_factor_range(
+	__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &factor_range_entry);
+}
+
+static int unwrap_entry(void **entry, void *user)
+{
+	isl_set *set = *entry;
+	isl_union_set **res = user;
+
+	if (!isl_set_is_wrapping(set))
+		return 0;
+
+	*res = isl_union_map_add_map(*res, isl_set_unwrap(isl_set_copy(set)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset)
+{
+	return cond_un_op(uset, &unwrap_entry);
+}
+
+static int wrap_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_set_add_set(*res, isl_map_wrap(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &wrap_entry);
+}
+
+struct isl_union_map_is_subset_data {
+	isl_union_map *umap2;
+	int is_subset;
+};
+
+static int is_subset_entry(void **entry, void *user)
+{
+	struct isl_union_map_is_subset_data *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_map *map = *entry;
+
+	hash = isl_space_get_hash(map->dim);
+	entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+				     hash, &has_dim, map->dim, 0);
+	if (!entry2) {
+		int empty = isl_map_is_empty(map);
+		if (empty < 0)
+			return -1;
+		if (empty)
+			return 0;
+		data->is_subset = 0;
+		return -1;
+	}
+
+	data->is_subset = isl_map_is_subset(map, entry2->data);
+	if (data->is_subset < 0 || !data->is_subset)
+		return -1;
+
+	return 0;
+}
+
+int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
+	__isl_keep isl_union_map *umap2)
+{
+	struct isl_union_map_is_subset_data data = { NULL, 1 };
+
+	umap1 = isl_union_map_copy(umap1);
+	umap2 = isl_union_map_copy(umap2);
+	umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+	umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+	if (!umap1 || !umap2)
+		goto error;
+
+	data.umap2 = umap2;
+	if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+				   &is_subset_entry, &data) < 0 &&
+	    data.is_subset)
+		goto error;
+
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+
+	return data.is_subset;
+error:
+	isl_union_map_free(umap1);
+	isl_union_map_free(umap2);
+	return -1;
+}
+
+int isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
+	__isl_keep isl_union_set *uset2)
+{
+	return isl_union_map_is_subset(uset1, uset2);
+}
+
+int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
+	__isl_keep isl_union_map *umap2)
+{
+	int is_subset;
+
+	if (!umap1 || !umap2)
+		return -1;
+	is_subset = isl_union_map_is_subset(umap1, umap2);
+	if (is_subset != 1)
+		return is_subset;
+	is_subset = isl_union_map_is_subset(umap2, umap1);
+	return is_subset;
+}
+
+int isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
+	__isl_keep isl_union_set *uset2)
+{
+	return isl_union_map_is_equal(uset1, uset2);
+}
+
+int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
+	__isl_keep isl_union_map *umap2)
+{
+	int is_subset;
+
+	if (!umap1 || !umap2)
+		return -1;
+	is_subset = isl_union_map_is_subset(umap1, umap2);
+	if (is_subset != 1)
+		return is_subset;
+	is_subset = isl_union_map_is_subset(umap2, umap1);
+	if (is_subset == -1)
+		return is_subset;
+	return !is_subset;
+}
+
+int isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
+	__isl_keep isl_union_set *uset2)
+{
+	return isl_union_map_is_strict_subset(uset1, uset2);
+}
+
+static int sample_entry(void **entry, void *user)
+{
+	isl_basic_map **sample = (isl_basic_map **)user;
+	isl_map *map = *entry;
+
+	*sample = isl_map_sample(isl_map_copy(map));
+	if (!*sample)
+		return -1;
+	if (!isl_basic_map_plain_is_empty(*sample))
+		return -1;
+	return 0;
+}
+
+__isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
+{
+	isl_basic_map *sample = NULL;
+
+	if (!umap)
+		return NULL;
+
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+				   &sample_entry, &sample) < 0 &&
+	    !sample)
+		goto error;
+
+	if (!sample)
+		sample = isl_basic_map_empty(isl_union_map_get_space(umap));
+
+	isl_union_map_free(umap);
+
+	return sample;
+error:
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+__isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
+{
+	return (isl_basic_set *)isl_union_map_sample(uset);
+}
+
+struct isl_forall_data {
+	int res;
+	int (*fn)(__isl_keep isl_map *map);
+};
+
+static int forall_entry(void **entry, void *user)
+{
+	struct isl_forall_data *data = user;
+	isl_map *map = *entry;
+
+	data->res = data->fn(map);
+	if (data->res < 0)
+		return -1;
+
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+static int union_map_forall(__isl_keep isl_union_map *umap,
+	int (*fn)(__isl_keep isl_map *map))
+{
+	struct isl_forall_data data = { 1, fn };
+
+	if (!umap)
+		return -1;
+
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+				   &forall_entry, &data) < 0 && data.res)
+		return -1;
+
+	return data.res;
+}
+
+struct isl_forall_user_data {
+	int res;
+	int (*fn)(__isl_keep isl_map *map, void *user);
+	void *user;
+};
+
+static int forall_user_entry(void **entry, void *user)
+{
+	struct isl_forall_user_data *data = user;
+	isl_map *map = *entry;
+
+	data->res = data->fn(map, data->user);
+	if (data->res < 0)
+		return -1;
+
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+/* Check if fn(map, user) returns true for all maps "map" in umap.
+ */
+static int union_map_forall_user(__isl_keep isl_union_map *umap,
+	int (*fn)(__isl_keep isl_map *map, void *user), void *user)
+{
+	struct isl_forall_user_data data = { 1, fn, user };
+
+	if (!umap)
+		return -1;
+
+	if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+				   &forall_user_entry, &data) < 0 && data.res)
+		return -1;
+
+	return data.res;
+}
+
+int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
+{
+	return union_map_forall(umap, &isl_map_is_empty);
+}
+
+int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
+{
+	return isl_union_map_is_empty(uset);
+}
+
+static int is_subset_of_identity(__isl_keep isl_map *map)
+{
+	int is_subset;
+	isl_space *dim;
+	isl_map *id;
+
+	if (!map)
+		return -1;
+
+	if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+					map->dim, isl_dim_out))
+		return 0;
+
+	dim = isl_map_get_space(map);
+	id = isl_map_identity(dim);
+
+	is_subset = isl_map_is_subset(map, id);
+
+	isl_map_free(id);
+
+	return is_subset;
+}
+
+/* Given an isl_union_map that consists of a single map, check
+ * if it is single-valued.
+ */
+static int single_map_is_single_valued(__isl_keep isl_union_map *umap)
+{
+	isl_map *map;
+	int sv;
+
+	umap = isl_union_map_copy(umap);
+	map = isl_map_from_union_map(umap);
+	sv = isl_map_is_single_valued(map);
+	isl_map_free(map);
+
+	return sv;
+}
+
+/* Internal data structure for single_valued_on_domain.
+ *
+ * "umap" is the union map to be tested.
+ * "sv" is set to 1 as long as "umap" may still be single-valued.
+ */
+struct isl_union_map_is_sv_data {
+	isl_union_map *umap;
+	int sv;
+};
+
+/* Check if the data->umap is single-valued on "set".
+ *
+ * If data->umap consists of a single map on "set", then test it
+ * as an isl_map.
+ *
+ * Otherwise, compute
+ *
+ *	M \circ M^-1
+ *
+ * check if the result is a subset of the identity mapping and
+ * store the result in data->sv.
+ *
+ * Terminate as soon as data->umap has been determined not to
+ * be single-valued.
+ */
+static int single_valued_on_domain(__isl_take isl_set *set, void *user)
+{
+	struct isl_union_map_is_sv_data *data = user;
+	isl_union_map *umap, *test;
+
+	umap = isl_union_map_copy(data->umap);
+	umap = isl_union_map_intersect_domain(umap,
+						isl_union_set_from_set(set));
+
+	if (isl_union_map_n_map(umap) == 1) {
+		data->sv = single_map_is_single_valued(umap);
+		isl_union_map_free(umap);
+	} else {
+		test = isl_union_map_reverse(isl_union_map_copy(umap));
+		test = isl_union_map_apply_range(test, umap);
+
+		data->sv = union_map_forall(test, &is_subset_of_identity);
+
+		isl_union_map_free(test);
+	}
+
+	if (data->sv < 0 || !data->sv)
+		return -1;
+	return 0;
+}
+
+/* Check if the given map is single-valued.
+ *
+ * If the union map consists of a single map, then test it as an isl_map.
+ * Otherwise, check if the union map is single-valued on each of its
+ * domain spaces.
+ */
+int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap)
+{
+	isl_union_map *universe;
+	isl_union_set *domain;
+	struct isl_union_map_is_sv_data data;
+
+	if (isl_union_map_n_map(umap) == 1)
+		return single_map_is_single_valued(umap);
+
+	universe = isl_union_map_universe(isl_union_map_copy(umap));
+	domain = isl_union_map_domain(universe);
+
+	data.sv = 1;
+	data.umap = umap;
+	if (isl_union_set_foreach_set(domain,
+			    &single_valued_on_domain, &data) < 0 && data.sv)
+		data.sv = -1;
+	isl_union_set_free(domain);
+
+	return data.sv;
+}
+
+int isl_union_map_is_injective(__isl_keep isl_union_map *umap)
+{
+	int in;
+
+	umap = isl_union_map_copy(umap);
+	umap = isl_union_map_reverse(umap);
+	in = isl_union_map_is_single_valued(umap);
+	isl_union_map_free(umap);
+
+	return in;
+}
+
+/* Represents a map that has a fixed value (v) for one of its
+ * range dimensions.
+ * The map in this structure is not reference counted, so it
+ * is only valid while the isl_union_map from which it was
+ * obtained is still alive.
+ */
+struct isl_fixed_map {
+	isl_int v;
+	isl_map *map;
+};
+
+static struct isl_fixed_map *alloc_isl_fixed_map_array(isl_ctx *ctx,
+	int n)
+{
+	int i;
+	struct isl_fixed_map *v;
+
+	v = isl_calloc_array(ctx, struct isl_fixed_map, n);
+	if (!v)
+		return NULL;
+	for (i = 0; i < n; ++i)
+		isl_int_init(v[i].v);
+	return v;
+}
+
+static void free_isl_fixed_map_array(struct isl_fixed_map *v, int n)
+{
+	int i;
+
+	if (!v)
+		return;
+	for (i = 0; i < n; ++i)
+		isl_int_clear(v[i].v);
+	free(v);
+}
+
+/* Compare the "v" field of two isl_fixed_map structs.
+ */
+static int qsort_fixed_map_cmp(const void *p1, const void *p2)
+{
+	const struct isl_fixed_map *e1 = (const struct isl_fixed_map *) p1;
+	const struct isl_fixed_map *e2 = (const struct isl_fixed_map *) p2;
+
+	return isl_int_cmp(e1->v, e2->v);
+}
+
+/* Internal data structure used while checking whether all maps
+ * in a union_map have a fixed value for a given output dimension.
+ * v is the list of maps, with the fixed value for the dimension
+ * n is the number of maps considered so far
+ * pos is the output dimension under investigation
+ */
+struct isl_fixed_dim_data {
+	struct isl_fixed_map *v;
+	int n;
+	int pos;
+};
+
+static int fixed_at_pos(__isl_keep isl_map *map, void *user)
+{
+	struct isl_fixed_dim_data *data = user;
+
+	data->v[data->n].map = map;
+	return isl_map_plain_is_fixed(map, isl_dim_out, data->pos,
+				      &data->v[data->n++].v);
+}
+
+static int plain_injective_on_range(__isl_take isl_union_map *umap,
+	int first, int n_range);
+
+/* Given a list of the maps, with their fixed values at output dimension "pos",
+ * check whether the ranges of the maps form an obvious partition.
+ *
+ * We first sort the maps according to their fixed values.
+ * If all maps have a different value, then we know the ranges form
+ * a partition.
+ * Otherwise, we collect the maps with the same fixed value and
+ * check whether each such collection is obviously injective
+ * based on later dimensions.
+ */
+static int separates(struct isl_fixed_map *v, int n,
+	__isl_take isl_space *dim, int pos, int n_range)
+{
+	int i;
+
+	if (!v)
+		goto error;
+
+	qsort(v, n, sizeof(*v), &qsort_fixed_map_cmp);
+
+	for (i = 0; i + 1 < n; ++i) {
+		int j, k;
+		isl_union_map *part;
+		int injective;
+
+		for (j = i + 1; j < n; ++j)
+			if (isl_int_ne(v[i].v, v[j].v))
+				break;
+
+		if (j == i + 1)
+			continue;
+
+		part = isl_union_map_alloc(isl_space_copy(dim), j - i);
+		for (k = i; k < j; ++k)
+			part = isl_union_map_add_map(part,
+						     isl_map_copy(v[k].map));
+
+		injective = plain_injective_on_range(part, pos + 1, n_range);
+		if (injective < 0)
+			goto error;
+		if (!injective)
+			break;
+
+		i = j - 1;
+	}
+
+	isl_space_free(dim);
+	free_isl_fixed_map_array(v, n);
+	return i + 1 >= n;
+error:
+	isl_space_free(dim);
+	free_isl_fixed_map_array(v, n);
+	return -1;
+}
+
+/* Check whether the maps in umap have obviously distinct ranges.
+ * In particular, check for an output dimension in the range
+ * [first,n_range) for which all maps have a fixed value
+ * and then check if these values, possibly along with fixed values
+ * at later dimensions, entail distinct ranges.
+ */
+static int plain_injective_on_range(__isl_take isl_union_map *umap,
+	int first, int n_range)
+{
+	isl_ctx *ctx;
+	int n;
+	struct isl_fixed_dim_data data = { NULL };
+
+	ctx = isl_union_map_get_ctx(umap);
+
+	n = isl_union_map_n_map(umap);
+	if (!umap)
+		goto error;
+
+	if (n <= 1) {
+		isl_union_map_free(umap);
+		return 1;
+	}
+
+	if (first >= n_range) {
+		isl_union_map_free(umap);
+		return 0;
+	}
+
+	data.v = alloc_isl_fixed_map_array(ctx, n);
+	if (!data.v)
+		goto error;
+
+	for (data.pos = first; data.pos < n_range; ++data.pos) {
+		int fixed;
+		int injective;
+		isl_space *dim;
+
+		data.n = 0;
+		fixed = union_map_forall_user(umap, &fixed_at_pos, &data);
+		if (fixed < 0)
+			goto error;
+		if (!fixed)
+			continue;
+		dim = isl_union_map_get_space(umap);
+		injective = separates(data.v, n, dim, data.pos, n_range);
+		isl_union_map_free(umap);
+		return injective;
+	}
+
+	free_isl_fixed_map_array(data.v, n);
+	isl_union_map_free(umap);
+
+	return 0;
+error:
+	free_isl_fixed_map_array(data.v, n);
+	isl_union_map_free(umap);
+	return -1;
+}
+
+/* Check whether the maps in umap that map to subsets of "ran"
+ * have obviously distinct ranges.
+ */
+static int plain_injective_on_range_wrap(__isl_keep isl_set *ran, void *user)
+{
+	isl_union_map *umap = user;
+
+	umap = isl_union_map_copy(umap);
+	umap = isl_union_map_intersect_range(umap,
+			isl_union_set_from_set(isl_set_copy(ran)));
+	return plain_injective_on_range(umap, 0, isl_set_dim(ran, isl_dim_set));
+}
+
+/* Check if the given union_map is obviously injective.
+ *
+ * In particular, we first check if all individual maps are obviously
+ * injective and then check if all the ranges of these maps are
+ * obviously disjoint.
+ */
+int isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap)
+{
+	int in;
+	isl_union_map *univ;
+	isl_union_set *ran;
+
+	in = union_map_forall(umap, &isl_map_plain_is_injective);
+	if (in < 0)
+		return -1;
+	if (!in)
+		return 0;
+
+	univ = isl_union_map_universe(isl_union_map_copy(umap));
+	ran = isl_union_map_range(univ);
+
+	in = union_map_forall_user(ran, &plain_injective_on_range_wrap, umap);
+
+	isl_union_set_free(ran);
+
+	return in;
+}
+
+int isl_union_map_is_bijective(__isl_keep isl_union_map *umap)
+{
+	int sv;
+
+	sv = isl_union_map_is_single_valued(umap);
+	if (sv < 0 || !sv)
+		return sv;
+
+	return isl_union_map_is_injective(umap);
+}
+
+static int zip_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_can_zip(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res, isl_map_zip(isl_map_copy(map)));
+
+	return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &zip_entry);
+}
+
+static int uncurry_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_can_uncurry(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res, isl_map_uncurry(isl_map_copy(map)));
+
+	return 0;
+}
+
+/* Given a union map, take the maps of the form A -> (B -> C) and
+ * return the union of the corresponding maps (A -> B) -> C.
+ */
+__isl_give isl_union_map *isl_union_map_uncurry(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &uncurry_entry);
+}
+
+static int curry_entry(void **entry, void *user)
+{
+	isl_map *map = *entry;
+	isl_union_map **res = user;
+
+	if (!isl_map_can_curry(map))
+		return 0;
+
+	*res = isl_union_map_add_map(*res, isl_map_curry(isl_map_copy(map)));
+
+	return 0;
+}
+
+/* Given a union map, take the maps of the form (A -> B) -> C and
+ * return the union of the corresponding maps A -> (B -> C).
+ */
+__isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap)
+{
+	return cond_un_op(umap, &curry_entry);
+}
+
+static int lift_entry(void **entry, void *user)
+{
+	isl_set *set = *entry;
+	isl_union_set **res = user;
+
+	*res = isl_union_set_add_set(*res, isl_set_lift(isl_set_copy(set)));
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset)
+{
+	return cond_un_op(uset, &lift_entry);
+}
+
+static int coefficients_entry(void **entry, void *user)
+{
+	isl_set *set = *entry;
+	isl_union_set **res = user;
+
+	set = isl_set_copy(set);
+	set = isl_set_from_basic_set(isl_set_coefficients(set));
+	*res = isl_union_set_add_set(*res, set);
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_coefficients(
+	__isl_take isl_union_set *uset)
+{
+	isl_ctx *ctx;
+	isl_space *dim;
+	isl_union_set *res;
+
+	if (!uset)
+		return NULL;
+
+	ctx = isl_union_set_get_ctx(uset);
+	dim = isl_space_set_alloc(ctx, 0, 0);
+	res = isl_union_map_alloc(dim, uset->table.n);
+	if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
+				   &coefficients_entry, &res) < 0)
+		goto error;
+
+	isl_union_set_free(uset);
+	return res;
+error:
+	isl_union_set_free(uset);
+	isl_union_set_free(res);
+	return NULL;
+}
+
+static int solutions_entry(void **entry, void *user)
+{
+	isl_set *set = *entry;
+	isl_union_set **res = user;
+
+	set = isl_set_copy(set);
+	set = isl_set_from_basic_set(isl_set_solutions(set));
+	if (!*res)
+		*res = isl_union_set_from_set(set);
+	else
+		*res = isl_union_set_add_set(*res, set);
+
+	if (!*res)
+		return -1;
+
+	return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_solutions(
+	__isl_take isl_union_set *uset)
+{
+	isl_union_set *res = NULL;
+
+	if (!uset)
+		return NULL;
+
+	if (uset->table.n == 0) {
+		res = isl_union_set_empty(isl_union_set_get_space(uset));
+		isl_union_set_free(uset);
+		return res;
+	}
+
+	if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
+				   &solutions_entry, &res) < 0)
+		goto error;
+
+	isl_union_set_free(uset);
+	return res;
+error:
+	isl_union_set_free(uset);
+	isl_union_set_free(res);
+	return NULL;
+}
+
+/* Is the domain space of "map" equal to "space"?
+ */
+static int domain_match(__isl_keep isl_map *map, __isl_keep isl_space *space)
+{
+	return isl_space_tuple_is_equal(map->dim, isl_dim_in,
+					space, isl_dim_out);
+}
+
+/* Is the range space of "map" equal to "space"?
+ */
+static int range_match(__isl_keep isl_map *map, __isl_keep isl_space *space)
+{
+	return isl_space_tuple_is_equal(map->dim, isl_dim_out,
+					space, isl_dim_out);
+}
+
+/* Is the set space of "map" equal to "space"?
+ */
+static int set_match(__isl_keep isl_map *map, __isl_keep isl_space *space)
+{
+	return isl_space_tuple_is_equal(map->dim, isl_dim_set,
+					space, isl_dim_out);
+}
+
+/* Internal data structure for preimage_pw_multi_aff.
+ *
+ * "pma" is the function under which the preimage should be taken.
+ * "space" is the space of "pma".
+ * "res" collects the results.
+ * "fn" computes the preimage for a given map.
+ * "match" returns true if "fn" can be called.
+ */
+struct isl_union_map_preimage_data {
+	isl_space *space;
+	isl_pw_multi_aff *pma;
+	isl_union_map *res;
+	int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space);
+	__isl_give isl_map *(*fn)(__isl_take isl_map *map,
+		__isl_take isl_pw_multi_aff *pma);
+};
+
+/* Call data->fn to compute the preimage of the domain or range of *entry
+ * under the function represented by data->pma, provided the domain/range
+ * space of *entry matches the target space of data->pma
+ * (as given by data->match), and add the result to data->res.
+ */
+static int preimage_entry(void **entry, void *user)
+{
+	int m;
+	isl_map *map = *entry;
+	struct isl_union_map_preimage_data *data = user;
+	int empty;
+
+	m = data->match(map, data->space);
+	if (m < 0)
+		return -1;
+	if (!m)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = data->fn(map, isl_pw_multi_aff_copy(data->pma));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0 || empty) {
+		isl_map_free(map);
+		return empty < 0 ? -1 : 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Compute the preimage of the domain or range of "umap" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the domain or range of "umap".
+ * The function "fn" performs the actual preimage computation on a map,
+ * while "match" determines to which maps the function should be applied.
+ */
+static __isl_give isl_union_map *preimage_pw_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma,
+	int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space),
+	__isl_give isl_map *(*fn)(__isl_take isl_map *map,
+		__isl_take isl_pw_multi_aff *pma))
+{
+	isl_ctx *ctx;
+	isl_space *space;
+	struct isl_union_map_preimage_data data;
+
+	umap = isl_union_map_align_params(umap,
+					    isl_pw_multi_aff_get_space(pma));
+	pma = isl_pw_multi_aff_align_params(pma, isl_union_map_get_space(umap));
+
+	if (!umap || !pma)
+		goto error;
+
+	ctx = isl_union_map_get_ctx(umap);
+	space = isl_union_map_get_space(umap);
+	data.space = isl_pw_multi_aff_get_space(pma);
+	data.pma = pma;
+	data.res = isl_union_map_alloc(space, umap->table.n);
+	data.match = match;
+	data.fn = fn;
+	if (isl_hash_table_foreach(ctx, &umap->table, &preimage_entry,
+					&data) < 0)
+		data.res = isl_union_map_free(data.res);
+
+	isl_space_free(data.space);
+	isl_union_map_free(umap);
+	isl_pw_multi_aff_free(pma);
+	return data.res;
+error:
+	isl_union_map_free(umap);
+	isl_pw_multi_aff_free(pma);
+	return NULL;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "pma",
+ * except that the domain has been replaced by the domain space of "pma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_pw_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma)
+{
+	return preimage_pw_multi_aff(umap, pma, &domain_match,
+					&isl_map_preimage_domain_pw_multi_aff);
+}
+
+/* Compute the preimage of the range of "umap" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the range of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with range space equal to the target space of "pma",
+ * except that the range has been replaced by the domain space of "pma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_range_pw_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma)
+{
+	return preimage_pw_multi_aff(umap, pma, &range_match,
+					&isl_map_preimage_range_pw_multi_aff);
+}
+
+/* Compute the preimage of "uset" under the function represented by "pma".
+ * In other words, plug in "pma" in "uset".
+ * The result contains sets that live in the same spaces as the sets of "uset"
+ * with space equal to the target space of "pma",
+ * except that the space has been replaced by the domain space of "pma".
+ */
+__isl_give isl_union_set *isl_union_set_preimage_pw_multi_aff(
+	__isl_take isl_union_set *uset, __isl_take isl_pw_multi_aff *pma)
+{
+	return preimage_pw_multi_aff(uset, pma, &set_match,
+					&isl_set_preimage_pw_multi_aff);
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "ma",
+ * except that the domain has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma)
+{
+	return isl_union_map_preimage_domain_pw_multi_aff(umap,
+					isl_pw_multi_aff_from_multi_aff(ma));
+}
+
+/* Compute the preimage of the range of "umap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the range of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with range space equal to the target space of "ma",
+ * except that the range has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_range_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma)
+{
+	return isl_union_map_preimage_range_pw_multi_aff(umap,
+					isl_pw_multi_aff_from_multi_aff(ma));
+}
+
+/* Compute the preimage of "uset" under the function represented by "ma".
+ * In other words, plug in "ma" in "uset".
+ * The result contains sets that live in the same spaces as the sets of "uset"
+ * with space equal to the target space of "ma",
+ * except that the space has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_set_preimage_multi_aff(
+	__isl_take isl_union_set *uset, __isl_take isl_multi_aff *ma)
+{
+	return isl_union_set_preimage_pw_multi_aff(uset,
+					isl_pw_multi_aff_from_multi_aff(ma));
+}
+
+/* Internal data structure for preimage_multi_pw_aff.
+ *
+ * "mpa" is the function under which the preimage should be taken.
+ * "space" is the space of "mpa".
+ * "res" collects the results.
+ * "fn" computes the preimage for a given map.
+ * "match" returns true if "fn" can be called.
+ */
+struct isl_union_map_preimage_mpa_data {
+	isl_space *space;
+	isl_multi_pw_aff *mpa;
+	isl_union_map *res;
+	int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space);
+	__isl_give isl_map *(*fn)(__isl_take isl_map *map,
+		__isl_take isl_multi_pw_aff *mpa);
+};
+
+/* Call data->fn to compute the preimage of the domain or range of *entry
+ * under the function represented by data->mpa, provided the domain/range
+ * space of *entry matches the target space of data->mpa
+ * (as given by data->match), and add the result to data->res.
+ */
+static int preimage_mpa_entry(void **entry, void *user)
+{
+	int m;
+	isl_map *map = *entry;
+	struct isl_union_map_preimage_mpa_data *data = user;
+	int empty;
+
+	m = data->match(map, data->space);
+	if (m < 0)
+		return -1;
+	if (!m)
+		return 0;
+
+	map = isl_map_copy(map);
+	map = data->fn(map, isl_multi_pw_aff_copy(data->mpa));
+
+	empty = isl_map_is_empty(map);
+	if (empty < 0 || empty) {
+		isl_map_free(map);
+		return empty < 0 ? -1 : 0;
+	}
+
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Compute the preimage of the domain or range of "umap" under the function
+ * represented by "mpa".
+ * In other words, plug in "mpa" in the domain or range of "umap".
+ * The function "fn" performs the actual preimage computation on a map,
+ * while "match" determines to which maps the function should be applied.
+ */
+static __isl_give isl_union_map *preimage_multi_pw_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa,
+	int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space),
+	__isl_give isl_map *(*fn)(__isl_take isl_map *map,
+		__isl_take isl_multi_pw_aff *mpa))
+{
+	isl_ctx *ctx;
+	isl_space *space;
+	struct isl_union_map_preimage_mpa_data data;
+
+	umap = isl_union_map_align_params(umap,
+					    isl_multi_pw_aff_get_space(mpa));
+	mpa = isl_multi_pw_aff_align_params(mpa, isl_union_map_get_space(umap));
+
+	if (!umap || !mpa)
+		goto error;
+
+	ctx = isl_union_map_get_ctx(umap);
+	space = isl_union_map_get_space(umap);
+	data.space = isl_multi_pw_aff_get_space(mpa);
+	data.mpa = mpa;
+	data.res = isl_union_map_alloc(space, umap->table.n);
+	data.match = match;
+	data.fn = fn;
+	if (isl_hash_table_foreach(ctx, &umap->table, &preimage_mpa_entry,
+					&data) < 0)
+		data.res = isl_union_map_free(data.res);
+
+	isl_space_free(data.space);
+	isl_union_map_free(umap);
+	isl_multi_pw_aff_free(mpa);
+	return data.res;
+error:
+	isl_union_map_free(umap);
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "mpa".
+ * In other words, plug in "mpa" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "mpa",
+ * except that the domain has been replaced by the domain space of "mpa".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_pw_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa)
+{
+	return preimage_multi_pw_aff(umap, mpa, &domain_match,
+					&isl_map_preimage_domain_multi_pw_aff);
+}
+
+/* Internal data structure for preimage_upma.
+ *
+ * "umap" is the map of which the preimage should be computed.
+ * "res" collects the results.
+ * "fn" computes the preimage for a given piecewise multi-affine function.
+ */
+struct isl_union_map_preimage_upma_data {
+	isl_union_map *umap;
+	isl_union_map *res;
+	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap,
+		__isl_take isl_pw_multi_aff *pma);
+};
+
+/* Call data->fn to compute the preimage of the domain or range of data->umap
+ * under the function represented by pma and add the result to data->res.
+ */
+static int preimage_upma(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+	struct isl_union_map_preimage_upma_data *data = user;
+	isl_union_map *umap;
+
+	umap = isl_union_map_copy(data->umap);
+	umap = data->fn(umap, pma);
+	data->res = isl_union_map_union(data->res, umap);
+
+	return data->res ? 0 : -1;
+}
+
+/* Compute the preimage of the domain or range of "umap" under the function
+ * represented by "upma".
+ * In other words, plug in "upma" in the domain or range of "umap".
+ * The function "fn" performs the actual preimage computation
+ * on a piecewise multi-affine function.
+ */
+static __isl_give isl_union_map *preimage_union_pw_multi_aff(
+	__isl_take isl_union_map *umap,
+	__isl_take isl_union_pw_multi_aff *upma,
+	__isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap,
+		__isl_take isl_pw_multi_aff *pma))
+{
+	struct isl_union_map_preimage_upma_data data;
+
+	data.umap = umap;
+	data.res = isl_union_map_empty(isl_union_map_get_space(umap));
+	data.fn = fn;
+	if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+						    &preimage_upma, &data) < 0)
+		data.res = isl_union_map_free(data.res);
+
+	isl_union_map_free(umap);
+	isl_union_pw_multi_aff_free(upma);
+
+	return data.res;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "upma".
+ * In other words, plug in "upma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to one of the target spaces of "upma",
+ * except that the domain has been replaced by one of the the domain spaces that
+ * corresponds to that target space of "upma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_union_pw_multi_aff(
+	__isl_take isl_union_map *umap,
+	__isl_take isl_union_pw_multi_aff *upma)
+{
+	return preimage_union_pw_multi_aff(umap, upma,
+				&isl_union_map_preimage_domain_pw_multi_aff);
+}
+
+/* Compute the preimage of the range of "umap" under the function
+ * represented by "upma".
+ * In other words, plug in "upma" in the range of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with range space equal to one of the target spaces of "upma",
+ * except that the range has been replaced by one of the the domain spaces that
+ * corresponds to that target space of "upma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_range_union_pw_multi_aff(
+	__isl_take isl_union_map *umap,
+	__isl_take isl_union_pw_multi_aff *upma)
+{
+	return preimage_union_pw_multi_aff(umap, upma,
+				&isl_union_map_preimage_range_pw_multi_aff);
+}
+
+/* Compute the preimage of "uset" under the function represented by "upma".
+ * In other words, plug in "upma" in the range of "uset".
+ * The result contains sets that live in the same spaces as the sets of "uset"
+ * with space equal to one of the target spaces of "upma",
+ * except that the space has been replaced by one of the the domain spaces that
+ * corresponds to that target space of "upma".
+ */
+__isl_give isl_union_set *isl_union_set_preimage_union_pw_multi_aff(
+	__isl_take isl_union_set *uset,
+	__isl_take isl_union_pw_multi_aff *upma)
+{
+	return preimage_union_pw_multi_aff(uset, upma,
+					&isl_union_set_preimage_pw_multi_aff);
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of *entry.
+ */
+static int reset_user(void **entry, void *user)
+{
+	isl_map **map = (isl_map **)entry;
+
+	*map = isl_map_reset_user(*map);
+
+	return *map ? 0 : -1;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the spaces of "umap".
+ */
+__isl_give isl_union_map *isl_union_map_reset_user(
+	__isl_take isl_union_map *umap)
+{
+	umap = isl_union_map_cow(umap);
+	if (!umap)
+		return NULL;
+	umap->dim = isl_space_reset_user(umap->dim);
+	if (!umap->dim)
+		return isl_union_map_free(umap);
+	umap = un_op(umap, &reset_user);
+
+	return umap;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the spaces of "uset".
+ */
+__isl_give isl_union_set *isl_union_set_reset_user(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_map_reset_user(uset);
+}
+
+/* Internal data structure for isl_union_map_project_out.
+ * "type", "first" and "n" are the arguments for the isl_map_project_out
+ * call.
+ * "res" collects the results.
+ */
+struct isl_union_map_project_out_data {
+	enum isl_dim_type type;
+	unsigned first;
+	unsigned n;
+
+	isl_union_map *res;
+};
+
+/* Turn the data->n dimensions of type data->type, starting at data->first
+ * into existentially quantified variables and add the result to data->res.
+ */
+static int project_out(__isl_take isl_map *map, void *user)
+{
+	struct isl_union_map_project_out_data *data = user;
+
+	map = isl_map_project_out(map, data->type, data->first, data->n);
+	data->res = isl_union_map_add_map(data->res, map);
+
+	return 0;
+}
+
+/* Turn the "n" dimensions of type "type", starting at "first"
+ * into existentially quantified variables.
+ * Since the space of an isl_union_map only contains parameters,
+ * type is required to be equal to isl_dim_param.
+ */
+__isl_give isl_union_map *isl_union_map_project_out(
+	__isl_take isl_union_map *umap,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	isl_space *space;
+	struct isl_union_map_project_out_data data = { type, first, n };
+
+	if (!umap)
+		return NULL;
+
+	if (type != isl_dim_param)
+		isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+			"can only project out parameters",
+			return isl_union_map_free(umap));
+
+	space = isl_union_map_get_space(umap);
+	space = isl_space_drop_dims(space, type, first, n);
+	data.res = isl_union_map_empty(space);
+	if (isl_union_map_foreach_map(umap, &project_out, &data) < 0)
+		data.res = isl_union_map_free(data.res);
+
+	isl_union_map_free(umap);
+
+	return data.res;
+}
+
+/* Internal data structure for isl_union_map_involves_dims.
+ * "first" and "n" are the arguments for the isl_map_involves_dims calls.
+ */
+struct isl_union_map_involves_dims_data {
+	unsigned first;
+	unsigned n;
+};
+
+/* Does "map" _not_ involve the data->n parameters starting at data->first?
+ */
+static int map_excludes(__isl_keep isl_map *map, void *user)
+{
+	struct isl_union_map_involves_dims_data *data = user;
+	int involves;
+
+	involves = isl_map_involves_dims(map,
+					isl_dim_param, data->first, data->n);
+	if (involves < 0)
+		return -1;
+	return !involves;
+}
+
+/* Does "umap" involve any of the n parameters starting at first?
+ * "type" is required to be set to isl_dim_param.
+ *
+ * "umap" involves any of those parameters if any of its maps
+ * involve the parameters.  In other words, "umap" does not
+ * involve any of the parameters if all its maps to not
+ * involve the parameters.
+ */
+int isl_union_map_involves_dims(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	struct isl_union_map_involves_dims_data data = { first, n };
+	int excludes;
+
+	if (type != isl_dim_param)
+		isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+			"can only reference parameters", return 0);
+
+	excludes = union_map_forall_user(umap, &map_excludes, &data);
+
+	if (excludes < 0)
+		return -1;
+
+	return !excludes;
+}

Added: polly/trunk/lib/External/isl/isl_union_map_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_union_map_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_union_map_private.h (added)
+++ polly/trunk/lib/External/isl/isl_union_map_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+#define isl_union_set	isl_union_map
+#include <isl/union_map.h>
+#include <isl/union_set.h>
+
+struct isl_union_map {
+	int ref;
+	isl_space *dim;
+
+	struct isl_hash_table	table;
+};

Added: polly/trunk/lib/External/isl/isl_union_templ.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_union_templ.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_union_templ.c (added)
+++ polly/trunk/lib/External/isl/isl_union_templ.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1107 @@
+/*
+ * Copyright 2010      INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France 
+ */
+
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xS(TYPE,NAME) struct TYPE ## _ ## NAME
+#define S(TYPE,NAME) xS(TYPE,NAME)
+
+struct UNION {
+	int ref;
+#ifdef HAS_TYPE
+	enum isl_fold type;
+#endif
+	isl_space *space;
+
+	struct isl_hash_table	table;
+};
+
+__isl_give UNION *FN(UNION,cow)(__isl_take UNION *u);
+
+isl_ctx *FN(UNION,get_ctx)(__isl_keep UNION *u)
+{
+	return u ? u->space->ctx : NULL;
+}
+
+__isl_give isl_space *FN(UNION,get_space)(__isl_keep UNION *u)
+{
+	if (!u)
+		return NULL;
+	return isl_space_copy(u->space);
+}
+
+/* Return the number of parameters of "u", where "type"
+ * is required to be set to isl_dim_param.
+ */
+unsigned FN(UNION,dim)(__isl_keep UNION *u, enum isl_dim_type type)
+{
+	if (!u)
+		return 0;
+
+	if (type != isl_dim_param)
+		isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+			"can only reference parameters", return 0);
+
+	return isl_space_dim(u->space, type);
+}
+
+/* Return the position of the parameter with the given name
+ * in "u".
+ * Return -1 if no such dimension can be found.
+ */
+int FN(UNION,find_dim_by_name)(__isl_keep UNION *u, enum isl_dim_type type,
+	const char *name)
+{
+	if (!u)
+		return -1;
+	return isl_space_find_dim_by_name(u->space, type, name);
+}
+
+#ifdef HAS_TYPE
+static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim,
+	enum isl_fold type, int size)
+#else
+static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim, int size)
+#endif
+{
+	UNION *u;
+
+	dim = isl_space_params(dim);
+	if (!dim)
+		return NULL;
+
+	u = isl_calloc_type(dim->ctx, UNION);
+	if (!u)
+		goto error;
+
+	u->ref = 1;
+#ifdef HAS_TYPE
+	u->type = type;
+#endif
+	u->space = dim;
+	if (isl_hash_table_init(dim->ctx, &u->table, size) < 0)
+		return FN(UNION,free)(u);
+
+	return u;
+error:
+	isl_space_free(dim);
+	return NULL;
+}
+
+#ifdef HAS_TYPE
+__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
+{
+	return FN(UNION,alloc)(dim, type, 16);
+}
+#else
+__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim)
+{
+	return FN(UNION,alloc)(dim, 16);
+}
+#endif
+
+__isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
+{
+	if (!u)
+		return NULL;
+
+	u->ref++;
+	return u;
+}
+
+S(UNION,foreach_data)
+{
+	int (*fn)(__isl_take PART *part, void *user);
+	void *user;
+};
+
+static int call_on_copy(void **entry, void *user)
+{
+	PART *part = *entry;
+	S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
+
+	return data->fn(FN(PART,copy)(part), data->user);
+}
+
+int FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
+	int (*fn)(__isl_take PART *part, void *user), void *user)
+{
+	S(UNION,foreach_data) data = { fn, user };
+
+	if (!u)
+		return -1;
+
+	return isl_hash_table_foreach(u->space->ctx, &u->table,
+				      &call_on_copy, &data);
+}
+
+/* Is the space of "entry" equal to "space"?
+ */
+static int has_space(const void *entry, const void *val)
+{
+	PART *part = (PART *)entry;
+	isl_space *space = (isl_space *) val;
+
+	return isl_space_is_equal(part->dim, space);
+}
+
+/* This function is not currently used by isl_aff.c.
+ */
+static int has_domain_space(const void *entry, const void *val)
+	__attribute__ ((unused));
+
+/* Is the domain space of "entry" equal to "space"?
+ */
+static int has_domain_space(const void *entry, const void *val)
+{
+	PART *part = (PART *)entry;
+	isl_space *space = (isl_space *) val;
+
+	if (isl_space_is_params(space))
+		return isl_space_is_set(part->dim);
+
+	return isl_space_tuple_is_equal(part->dim, isl_dim_in,
+					space, isl_dim_set);
+}
+
+/* Is the domain space of "entry" equal to the domain of "space"?
+ */
+static int has_same_domain_space(const void *entry, const void *val)
+{
+	PART *part = (PART *)entry;
+	isl_space *space = (isl_space *) val;
+
+	if (isl_space_is_set(space))
+		return isl_space_is_set(part->dim);
+
+	return isl_space_tuple_is_equal(part->dim, isl_dim_in,
+					space, isl_dim_in);
+}
+
+/* Extract the element of "u" living in "space" (ignoring parameters).
+ *
+ * Return the ZERO element if "u" does not contain any element
+ * living in "space".
+ */
+__isl_give PART *FN(FN(UNION,extract),PARTS)(__isl_keep UNION *u,
+	__isl_take isl_space *space)
+{
+	uint32_t hash;
+	struct isl_hash_table_entry *entry;
+
+	if (!u || !space)
+		goto error;
+	if (!isl_space_match(u->space, isl_dim_param, space, isl_dim_param)) {
+		space = isl_space_drop_dims(space, isl_dim_param,
+					0, isl_space_dim(space, isl_dim_param));
+		space = isl_space_align_params(space,
+					FN(UNION,get_space)(u));
+		if (!space)
+			goto error;
+	}
+
+	hash = isl_space_get_hash(space);
+	entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
+				    &has_space, space, 0);
+	if (!entry)
+#ifdef HAS_TYPE
+		return FN(PART,ZERO)(space, u->type);
+#else
+		return FN(PART,ZERO)(space);
+#endif
+	isl_space_free(space);
+	return FN(PART,copy)(entry->data);
+error:
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Add "part" to "u".
+ * If "disjoint" is set, then "u" is not allowed to already have
+ * a part that is defined on the same space as "part".
+ * Otherwise, compute the union sum of "part" and the part in "u"
+ * defined on the same space.
+ */
+static __isl_give UNION *FN(UNION,add_part_generic)(__isl_take UNION *u,
+	__isl_take PART *part, int disjoint)
+{
+	int empty;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry;
+
+	if (!part)
+		goto error;
+
+	empty = FN(PART,IS_ZERO)(part);
+	if (empty < 0)
+		goto error;
+	if (empty) {
+		FN(PART,free)(part);
+		return u;
+	}
+
+	u = FN(UNION,align_params)(u, FN(PART,get_space)(part));
+	part = FN(PART,align_params)(part, FN(UNION,get_space)(u));
+
+	u = FN(UNION,cow)(u);
+
+	if (!u)
+		goto error;
+
+	hash = isl_space_get_hash(part->dim);
+	entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
+				    &has_same_domain_space, part->dim, 1);
+	if (!entry)
+		goto error;
+
+	if (!entry->data)
+		entry->data = part;
+	else {
+		PART *entry_part = entry->data;
+		if (disjoint)
+			isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+				"additional part should live on separate "
+				"space", goto error);
+		if (!isl_space_tuple_is_equal(entry_part->dim, isl_dim_out,
+						part->dim, isl_dim_out))
+			isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+				"union expression can only contain a single "
+				"expression over a given domain", goto error);
+		entry->data = FN(PART,union_add_)(entry->data,
+						FN(PART,copy)(part));
+		if (!entry->data)
+			goto error;
+		empty = FN(PART,IS_ZERO)(part);
+		if (empty < 0)
+			goto error;
+		if (empty) {
+			FN(PART,free)(entry->data);
+			isl_hash_table_remove(u->space->ctx, &u->table, entry);
+		}
+		FN(PART,free)(part);
+	}
+
+	return u;
+error:
+	FN(PART,free)(part);
+	FN(UNION,free)(u);
+	return NULL;
+}
+
+/* Add "part" to "u", where "u" is assumed not to already have
+ * a part that is defined on the same space as "part".
+ */
+__isl_give UNION *FN(FN(UNION,add),PARTS)(__isl_take UNION *u,
+	__isl_take PART *part)
+{
+	return FN(UNION,add_part_generic)(u, part, 1);
+}
+
+static int add_part(__isl_take PART *part, void *user)
+{
+	UNION **u = (UNION **)user;
+
+	*u = FN(FN(UNION,add),PARTS)(*u, part);
+
+	return 0;
+}
+
+__isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
+{
+	UNION *dup;
+
+	if (!u)
+		return NULL;
+
+#ifdef HAS_TYPE
+	dup = FN(UNION,ZERO)(isl_space_copy(u->space), u->type);
+#else
+	dup = FN(UNION,ZERO)(isl_space_copy(u->space));
+#endif
+	if (FN(FN(UNION,foreach),PARTS)(u, &add_part, &dup) < 0)
+		goto error;
+	return dup;
+error:
+	FN(UNION,free)(dup);
+	return NULL;
+}
+
+__isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
+{
+	if (!u)
+		return NULL;
+
+	if (u->ref == 1)
+		return u;
+	u->ref--;
+	return FN(UNION,dup)(u);
+}
+
+static int free_u_entry(void **entry, void *user)
+{
+	PART *part = *entry;
+	FN(PART,free)(part);
+	return 0;
+}
+
+__isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
+{
+	if (!u)
+		return NULL;
+
+	if (--u->ref > 0)
+		return NULL;
+
+	isl_hash_table_foreach(u->space->ctx, &u->table, &free_u_entry, NULL);
+	isl_hash_table_clear(&u->table);
+	isl_space_free(u->space);
+	free(u);
+	return NULL;
+}
+
+S(UNION,align) {
+	isl_reordering *exp;
+	UNION *res;
+};
+
+#ifdef ALIGN_DOMAIN
+static int align_entry(__isl_take PART *part, void *user)
+{
+	isl_reordering *exp;
+	S(UNION,align) *data = user;
+
+	exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+				    FN(PART,get_domain_space)(part));
+
+	data->res = FN(FN(UNION,add),PARTS)(data->res,
+					    FN(PART,realign_domain)(part, exp));
+
+	return 0;
+}
+#else
+static int align_entry(__isl_take PART *part, void *user)
+{
+	isl_reordering *exp;
+	S(UNION,align) *data = user;
+
+	exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+				    FN(PART,get_space)(part));
+
+	data->res = FN(FN(UNION,add),PARTS)(data->res,
+					    FN(PART,realign)(part, exp));
+
+	return 0;
+}
+#endif
+
+__isl_give UNION *FN(UNION,align_params)(__isl_take UNION *u,
+	__isl_take isl_space *model)
+{
+	S(UNION,align) data = { NULL, NULL };
+
+	if (!u || !model)
+		goto error;
+
+	if (isl_space_match(u->space, isl_dim_param, model, isl_dim_param)) {
+		isl_space_free(model);
+		return u;
+	}
+
+	model = isl_space_params(model);
+	data.exp = isl_parameter_alignment_reordering(u->space, model);
+	if (!data.exp)
+		goto error;
+
+#ifdef HAS_TYPE
+	data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim),
+						u->type, u->table.n);
+#else
+	data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim), u->table.n);
+#endif
+	if (FN(FN(UNION,foreach),PARTS)(u, &align_entry, &data) < 0)
+		goto error;
+
+	isl_reordering_free(data.exp);
+	FN(UNION,free)(u);
+	isl_space_free(model);
+	return data.res;
+error:
+	isl_reordering_free(data.exp);
+	FN(UNION,free)(u);
+	FN(UNION,free)(data.res);
+	isl_space_free(model);
+	return NULL;
+}
+
+/* Add "part" to *u, taking the union sum if "u" already has
+ * a part defined on the same space as "part".
+ */
+static int union_add_part(__isl_take PART *part, void *user)
+{
+	UNION **u = (UNION **)user;
+
+	*u = FN(UNION,add_part_generic)(*u, part, 0);
+
+	return 0;
+}
+
+/* Compute the sum of "u1" and "u2" on the union of their domains,
+ * with the actual sum on the shared domain and
+ * the defined expression on the symmetric difference of the domains.
+ *
+ * This is an internal function that is exposed under different
+ * names depending on whether the base expressions have a zero default
+ * value.
+ * If they do, then this function is called "add".
+ * Otherwise, it is called "union_add".
+ */
+static __isl_give UNION *FN(UNION,union_add_)(__isl_take UNION *u1,
+	__isl_take UNION *u2)
+{
+	u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
+	u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
+
+	u1 = FN(UNION,cow)(u1);
+
+	if (!u1 || !u2)
+		goto error;
+
+	if (FN(FN(UNION,foreach),PARTS)(u2, &union_add_part, &u1) < 0)
+		goto error;
+
+	FN(UNION,free)(u2);
+
+	return u1;
+error:
+	FN(UNION,free)(u1);
+	FN(UNION,free)(u2);
+	return NULL;
+}
+
+__isl_give UNION *FN(FN(UNION,from),PARTS)(__isl_take PART *part)
+{
+	isl_space *dim;
+	UNION *u;
+
+	if (!part)
+		return NULL;
+
+	dim = FN(PART,get_space)(part);
+	dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
+	dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
+#ifdef HAS_TYPE
+	u = FN(UNION,ZERO)(dim, part->type);
+#else
+	u = FN(UNION,ZERO)(dim);
+#endif
+	u = FN(FN(UNION,add),PARTS)(u, part);
+
+	return u;
+}
+
+S(UNION,match_bin_data) {
+	UNION *u2;
+	UNION *res;
+	__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *);
+};
+
+/* Check if data->u2 has an element living in the same space as *entry.
+ * If so, call data->fn on the two elements and add the result to
+ * data->res.
+ */
+static int match_bin_entry(void **entry, void *user)
+{
+	S(UNION,match_bin_data) *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	isl_space *space;
+	PART *part = *entry;
+	PART *part2;
+
+	space = FN(PART,get_space)(part);
+	hash = isl_space_get_hash(space);
+	entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
+				     hash, &has_same_domain_space, space, 0);
+	isl_space_free(space);
+	if (!entry2)
+		return 0;
+
+	part2 = entry2->data;
+	if (!isl_space_tuple_is_equal(part->dim, isl_dim_out,
+					part2->dim, isl_dim_out))
+		isl_die(FN(UNION,get_ctx)(data->u2), isl_error_invalid,
+			"entries should have the same range space",
+			return -1);
+
+	part = FN(PART, copy)(part);
+	part = data->fn(part, FN(PART, copy)(entry2->data));
+
+	data->res = FN(FN(UNION,add),PARTS)(data->res, part);
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+/* This function is currently only used from isl_polynomial.c
+ * and not from isl_fold.c.
+ */
+static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
+	__isl_take UNION *u2,
+	__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
+	__attribute__ ((unused));
+/* For each pair of elements in "u1" and "u2" living in the same space,
+ * call "fn" and collect the results.
+ */
+static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
+	__isl_take UNION *u2,
+	__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
+{
+	S(UNION,match_bin_data) data = { NULL, NULL, fn };
+
+	u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
+	u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
+
+	if (!u1 || !u2)
+		goto error;
+
+	data.u2 = u2;
+#ifdef HAS_TYPE
+	data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->type,
+				    u1->table.n);
+#else
+	data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->table.n);
+#endif
+	if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+				    &match_bin_entry, &data) < 0)
+		goto error;
+
+	FN(UNION,free)(u1);
+	FN(UNION,free)(u2);
+	return data.res;
+error:
+	FN(UNION,free)(u1);
+	FN(UNION,free)(u2);
+	FN(UNION,free)(data.res);
+	return NULL;
+}
+
+/* Compute the sum of "u1" and "u2".
+ *
+ * If the base expressions have a default zero value, then the sum
+ * is computed on the union of the domains of "u1" and "u2".
+ * Otherwise, it is computed on their shared domains.
+ */
+__isl_give UNION *FN(UNION,add)(__isl_take UNION *u1, __isl_take UNION *u2)
+{
+#if DEFAULT_IS_ZERO
+	return FN(UNION,union_add_)(u1, u2);
+#else
+	return match_bin_op(u1, u2, &FN(PART,add));
+#endif
+}
+
+#ifndef NO_SUB
+/* Subtract "u2" from "u1" and return the result.
+ */
+__isl_give UNION *FN(UNION,sub)(__isl_take UNION *u1, __isl_take UNION *u2)
+{
+	return match_bin_op(u1, u2, &FN(PART,sub));
+}
+#endif
+
+S(UNION,any_set_data) {
+	isl_set *set;
+	UNION *res;
+	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
+};
+
+static int any_set_entry(void **entry, void *user)
+{
+	S(UNION,any_set_data) *data = user;
+	PW *pw = *entry;
+
+	pw = FN(PW,copy)(pw);
+	pw = data->fn(pw, isl_set_copy(data->set));
+
+	data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+/* Update each element of "u" by calling "fn" on the element and "set".
+ */
+static __isl_give UNION *any_set_op(__isl_take UNION *u,
+	__isl_take isl_set *set,
+	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
+{
+	S(UNION,any_set_data) data = { NULL, NULL, fn };
+
+	u = FN(UNION,align_params)(u, isl_set_get_space(set));
+	set = isl_set_align_params(set, FN(UNION,get_space)(u));
+
+	if (!u || !set)
+		goto error;
+
+	data.set = set;
+#ifdef HAS_TYPE
+	data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
+					u->table.n);
+#else
+	data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
+#endif
+	if (isl_hash_table_foreach(u->space->ctx, &u->table,
+				   &any_set_entry, &data) < 0)
+		goto error;
+
+	FN(UNION,free)(u);
+	isl_set_free(set);
+	return data.res;
+error:
+	FN(UNION,free)(u);
+	isl_set_free(set);
+	FN(UNION,free)(data.res);
+	return NULL;
+}
+
+/* Intersect the domain of "u" with the parameter domain "context".
+ */
+__isl_give UNION *FN(UNION,intersect_params)(__isl_take UNION *u,
+	__isl_take isl_set *set)
+{
+	return any_set_op(u, set, &FN(PW,intersect_params));
+}
+
+/* Compute the gist of the domain of "u" with respect to
+ * the parameter domain "context".
+ */
+__isl_give UNION *FN(UNION,gist_params)(__isl_take UNION *u,
+	__isl_take isl_set *set)
+{
+	return any_set_op(u, set, &FN(PW,gist_params));
+}
+
+S(UNION,match_domain_data) {
+	isl_union_set *uset;
+	UNION *res;
+	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
+};
+
+static int set_has_dim(const void *entry, const void *val)
+{
+	isl_set *set = (isl_set *)entry;
+	isl_space *dim = (isl_space *)val;
+
+	return isl_space_is_equal(set->dim, dim);
+}
+
+/* Find the set in data->uset that lives in the same space as the domain
+ * of *entry, apply data->fn to *entry and this set (if any), and add
+ * the result to data->res.
+ */
+static int match_domain_entry(void **entry, void *user)
+{
+	S(UNION,match_domain_data) *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	PW *pw = *entry;
+	isl_space *space;
+
+	space = FN(PW,get_domain_space)(pw);
+	hash = isl_space_get_hash(space);
+	entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
+				     hash, &set_has_dim, space, 0);
+	isl_space_free(space);
+	if (!entry2)
+		return 0;
+
+	pw = FN(PW,copy)(pw);
+	pw = data->fn(pw, isl_set_copy(entry2->data));
+
+	data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+/* Apply fn to each pair of PW in u and set in uset such that
+ * the set lives in the same space as the domain of PW
+ * and collect the results.
+ */
+static __isl_give UNION *match_domain_op(__isl_take UNION *u,
+	__isl_take isl_union_set *uset,
+	__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
+{
+	S(UNION,match_domain_data) data = { NULL, NULL, fn };
+
+	u = FN(UNION,align_params)(u, isl_union_set_get_space(uset));
+	uset = isl_union_set_align_params(uset, FN(UNION,get_space)(u));
+
+	if (!u || !uset)
+		goto error;
+
+	data.uset = uset;
+#ifdef HAS_TYPE
+	data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
+					u->table.n);
+#else
+	data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
+#endif
+	if (isl_hash_table_foreach(u->space->ctx, &u->table,
+				   &match_domain_entry, &data) < 0)
+		goto error;
+
+	FN(UNION,free)(u);
+	isl_union_set_free(uset);
+	return data.res;
+error:
+	FN(UNION,free)(u);
+	isl_union_set_free(uset);
+	FN(UNION,free)(data.res);
+	return NULL;
+}
+
+/* Intersect the domain of "u" with "uset".
+ * If "uset" is a parameters domain, then intersect the parameter
+ * domain of "u" with this set.
+ */
+__isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u,
+	__isl_take isl_union_set *uset)
+{
+	if (isl_union_set_is_params(uset))
+		return FN(UNION,intersect_params)(u,
+						isl_set_from_union_set(uset));
+	return match_domain_op(u, uset, &FN(PW,intersect_domain));
+}
+
+__isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
+	__isl_take isl_union_set *uset)
+{
+	if (isl_union_set_is_params(uset))
+		return FN(UNION,gist_params)(u, isl_set_from_union_set(uset));
+	return match_domain_op(u, uset, &FN(PW,gist));
+}
+
+#ifndef NO_EVAL
+__isl_give isl_val *FN(UNION,eval)(__isl_take UNION *u,
+	__isl_take isl_point *pnt)
+{
+	uint32_t hash;
+	struct isl_hash_table_entry *entry;
+	isl_space *space;
+	isl_val *v;
+
+	if (!u || !pnt)
+		goto error;
+
+	space = isl_space_copy(pnt->dim);
+	if (!space)
+		goto error;
+	hash = isl_space_get_hash(space);
+	entry = isl_hash_table_find(u->space->ctx, &u->table,
+				    hash, &has_domain_space, space, 0);
+	isl_space_free(space);
+	if (!entry) {
+		v = isl_val_zero(isl_point_get_ctx(pnt));
+		isl_point_free(pnt);
+	} else {
+		v = FN(PART,eval)(FN(PART,copy)(entry->data), pnt);
+	}
+	FN(UNION,free)(u);
+	return v;
+error:
+	FN(UNION,free)(u);
+	isl_point_free(pnt);
+	return NULL;
+}
+#endif
+
+static int coalesce_entry(void **entry, void *user)
+{
+	PW **pw = (PW **)entry;
+
+	*pw = FN(PW,coalesce)(*pw);
+	if (!*pw)
+		return -1;
+
+	return 0;
+}
+
+__isl_give UNION *FN(UNION,coalesce)(__isl_take UNION *u)
+{
+	if (!u)
+		return NULL;
+
+	if (isl_hash_table_foreach(u->space->ctx, &u->table,
+				   &coalesce_entry, NULL) < 0)
+		goto error;
+
+	return u;
+error:
+	FN(UNION,free)(u);
+	return NULL;
+}
+
+static int domain(__isl_take PART *part, void *user)
+{
+	isl_union_set **uset = (isl_union_set **)user;
+
+	*uset = isl_union_set_add_set(*uset, FN(PART,domain)(part));
+
+	return 0;
+}
+
+__isl_give isl_union_set *FN(UNION,domain)(__isl_take UNION *u)
+{
+	isl_union_set *uset;
+
+	uset = isl_union_set_empty(FN(UNION,get_space)(u));
+	if (FN(FN(UNION,foreach),PARTS)(u, &domain, &uset) < 0)
+		goto error;
+
+	FN(UNION,free)(u);
+	
+	return uset;
+error:
+	isl_union_set_free(uset);
+	FN(UNION,free)(u);
+	return NULL;
+}
+
+static int mul_isl_int(void **entry, void *user)
+{
+	PW **pw = (PW **)entry;
+	isl_int *v = user;
+
+	*pw = FN(PW,mul_isl_int)(*pw, *v);
+	if (!*pw)
+		return -1;
+
+	return 0;
+}
+
+__isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
+{
+	if (isl_int_is_one(v))
+		return u;
+
+	if (DEFAULT_IS_ZERO && u && isl_int_is_zero(v)) {
+		UNION *zero;
+		isl_space *dim = FN(UNION,get_space)(u);
+#ifdef HAS_TYPE
+		zero = FN(UNION,ZERO)(dim, u->type);
+#else
+		zero = FN(UNION,ZERO)(dim);
+#endif
+		FN(UNION,free)(u);
+		return zero;
+	}
+
+	u = FN(UNION,cow)(u);
+	if (!u)
+		return NULL;
+
+#ifdef HAS_TYPE
+	if (isl_int_is_neg(v))
+		u->type = isl_fold_type_negate(u->type);
+#endif
+	if (isl_hash_table_foreach(u->space->ctx, &u->table,
+				    &mul_isl_int, &v) < 0)
+		goto error;
+
+	return u;
+error:
+	FN(UNION,free)(u);
+	return NULL;
+}
+
+/* Multiply *entry by the isl_val "user".
+ *
+ * Return 0 on success and -1 on error.
+ */
+static int scale_val(void **entry, void *user)
+{
+	PW **pw = (PW **)entry;
+	isl_val *v = user;
+
+	*pw = FN(PW,scale_val)(*pw, isl_val_copy(v));
+	if (!*pw)
+		return -1;
+
+	return 0;
+}
+
+/* Multiply "u" by "v" and return the result.
+ */
+__isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u,
+	__isl_take isl_val *v)
+{
+	if (!u || !v)
+		goto error;
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return u;
+	}
+
+	if (DEFAULT_IS_ZERO && u && isl_val_is_zero(v)) {
+		UNION *zero;
+		isl_space *space = FN(UNION,get_space)(u);
+#ifdef HAS_TYPE
+		zero = FN(UNION,ZERO)(space, u->type);
+#else
+		zero = FN(UNION,ZERO)(space);
+#endif
+		FN(UNION,free)(u);
+		isl_val_free(v);
+		return zero;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational factor", goto error);
+
+	u = FN(UNION,cow)(u);
+	if (!u)
+		return NULL;
+
+#ifdef HAS_TYPE
+	if (isl_val_is_neg(v))
+		u->type = isl_fold_type_negate(u->type);
+#endif
+	if (isl_hash_table_foreach(u->space->ctx, &u->table, &scale_val, v) < 0)
+		goto error;
+
+	isl_val_free(v);
+	return u;
+error:
+	isl_val_free(v);
+	FN(UNION,free)(u);
+	return NULL;
+}
+
+/* Divide *entry by the isl_val "user".
+ *
+ * Return 0 on success and -1 on error.
+ */
+static int FN(UNION,scale_down_val_entry)(void **entry, void *user)
+{
+	PW **pw = (PW **)entry;
+	isl_val *v = user;
+
+	*pw = FN(PW,scale_down_val)(*pw, isl_val_copy(v));
+	if (!*pw)
+		return -1;
+
+	return 0;
+}
+
+/* Divide "u" by "v" and return the result.
+ */
+__isl_give UNION *FN(UNION,scale_down_val)(__isl_take UNION *u,
+	__isl_take isl_val *v)
+{
+	if (!u || !v)
+		goto error;
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return u;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational factor", goto error);
+	if (isl_val_is_zero(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"cannot scale down by zero", goto error);
+
+	u = FN(UNION,cow)(u);
+	if (!u)
+		return NULL;
+
+#ifdef HAS_TYPE
+	if (isl_val_is_neg(v))
+		u->type = isl_fold_type_negate(u->type);
+#endif
+	if (isl_hash_table_foreach(FN(UNION,get_ctx)(u), &u->table,
+				    &FN(UNION,scale_down_val_entry), v) < 0)
+		goto error;
+
+	isl_val_free(v);
+	return u;
+error:
+	isl_val_free(v);
+	FN(UNION,free)(u);
+	return NULL;
+}
+
+S(UNION,plain_is_equal_data)
+{
+	UNION *u2;
+	int is_equal;
+};
+
+static int plain_is_equal_entry(void **entry, void *user)
+{
+	S(UNION,plain_is_equal_data) *data = user;
+	uint32_t hash;
+	struct isl_hash_table_entry *entry2;
+	PW *pw = *entry;
+
+	hash = isl_space_get_hash(pw->dim);
+	entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
+				     hash, &has_same_domain_space, pw->dim, 0);
+	if (!entry2) {
+		data->is_equal = 0;
+		return -1;
+	}
+
+	data->is_equal = FN(PW,plain_is_equal)(pw, entry2->data);
+	if (data->is_equal < 0 || !data->is_equal)
+		return -1;
+
+	return 0;
+}
+
+int FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
+{
+	S(UNION,plain_is_equal_data) data = { NULL, 1 };
+
+	if (!u1 || !u2)
+		return -1;
+	if (u1 == u2)
+		return 1;
+	if (u1->table.n != u2->table.n)
+		return 0;
+
+	u1 = FN(UNION,copy)(u1);
+	u2 = FN(UNION,copy)(u2);
+	u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
+	u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
+	if (!u1 || !u2)
+		goto error;
+
+	data.u2 = u2;
+	if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+				   &plain_is_equal_entry, &data) < 0 &&
+	    data.is_equal)
+		goto error;
+
+	FN(UNION,free)(u1);
+	FN(UNION,free)(u2);
+
+	return data.is_equal;
+error:
+	FN(UNION,free)(u1);
+	FN(UNION,free)(u2);
+	return -1;
+}

Added: polly/trunk/lib/External/isl/isl_val.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_val.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_val.c (added)
+++ polly/trunk/lib/External/isl/isl_val.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1624 @@
+/*
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_int.h>
+#include <isl_ctx_private.h>
+#include <isl_val_private.h>
+
+#undef BASE
+#define BASE val
+
+#include <isl_list_templ.c>
+
+/* Allocate an isl_val object with indeterminate value.
+ */
+__isl_give isl_val *isl_val_alloc(isl_ctx *ctx)
+{
+	isl_val *v;
+
+	v = isl_alloc_type(ctx, struct isl_val);
+	if (!v)
+		return NULL;
+
+	v->ctx = ctx;
+	isl_ctx_ref(ctx);
+	v->ref = 1;
+	isl_int_init(v->n);
+	isl_int_init(v->d);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing zero.
+ */
+__isl_give isl_val *isl_val_zero(isl_ctx *ctx)
+{
+	return isl_val_int_from_si(ctx, 0);
+}
+
+/* Return a reference to an isl_val representing one.
+ */
+__isl_give isl_val *isl_val_one(isl_ctx *ctx)
+{
+	return isl_val_int_from_si(ctx, 1);
+}
+
+/* Return a reference to an isl_val representing negative one.
+ */
+__isl_give isl_val *isl_val_negone(isl_ctx *ctx)
+{
+	return isl_val_int_from_si(ctx, -1);
+}
+
+/* Return a reference to an isl_val representing NaN.
+ */
+__isl_give isl_val *isl_val_nan(isl_ctx *ctx)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set_si(v->n, 0);
+	isl_int_set_si(v->d, 0);
+
+	return v;
+}
+
+/* Change "v" into a NaN.
+ */
+__isl_give isl_val *isl_val_set_nan(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_nan(v))
+		return v;
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+
+	isl_int_set_si(v->n, 0);
+	isl_int_set_si(v->d, 0);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing +infinity.
+ */
+__isl_give isl_val *isl_val_infty(isl_ctx *ctx)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set_si(v->n, 1);
+	isl_int_set_si(v->d, 0);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing -infinity.
+ */
+__isl_give isl_val *isl_val_neginfty(isl_ctx *ctx)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set_si(v->n, -1);
+	isl_int_set_si(v->d, 0);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing the integer "i".
+ */
+__isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set_si(v->n, i);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Change the value of "v" to be equal to the integer "i".
+ */
+__isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_int(v) && isl_int_cmp_si(v->n, i) == 0)
+		return v;
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+
+	isl_int_set_si(v->n, i);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Change the value of "v" to be equal to zero.
+ */
+__isl_give isl_val *isl_val_set_zero(__isl_take isl_val *v)
+{
+	return isl_val_set_si(v, 0);
+}
+
+/* Return a reference to an isl_val representing the unsigned integer "u".
+ */
+__isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set_ui(v->n, u);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing the integer "n".
+ */
+__isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set(v->n, n);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing the rational value "n"/"d".
+ * Normalizing the isl_val (if needed) is left to the caller.
+ */
+__isl_give isl_val *isl_val_rat_from_isl_int(isl_ctx *ctx,
+	isl_int n, isl_int d)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set(v->n, n);
+	isl_int_set(v->d, d);
+
+	return v;
+}
+
+/* Return a new reference to "v".
+ */
+__isl_give isl_val *isl_val_copy(__isl_keep isl_val *v)
+{
+	if (!v)
+		return NULL;
+
+	v->ref++;
+	return v;
+}
+
+/* Return a fresh copy of "val".
+ */
+__isl_give isl_val *isl_val_dup(__isl_keep isl_val *val)
+{
+	isl_val *dup;
+
+	if (!val)
+		return NULL;
+
+	dup = isl_val_alloc(isl_val_get_ctx(val));
+	if (!dup)
+		return NULL;
+
+	isl_int_set(dup->n, val->n);
+	isl_int_set(dup->d, val->d);
+
+	return dup;
+}
+
+/* Return an isl_val that is equal to "val" and that has only
+ * a single reference.
+ */
+__isl_give isl_val *isl_val_cow(__isl_take isl_val *val)
+{
+	if (!val)
+		return NULL;
+
+	if (val->ref == 1)
+		return val;
+	val->ref--;
+	return isl_val_dup(val);
+}
+
+/* Free "v" and return NULL.
+ */
+__isl_null isl_val *isl_val_free(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+
+	if (--v->ref > 0)
+		return NULL;
+
+	isl_ctx_deref(v->ctx);
+	isl_int_clear(v->n);
+	isl_int_clear(v->d);
+	free(v);
+	return NULL;
+}
+
+/* Extract the numerator of a rational value "v" as an integer.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+long isl_val_get_num_si(__isl_keep isl_val *v)
+{
+	if (!v)
+		return 0;
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return 0);
+	if (!isl_int_fits_slong(v->n))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"numerator too large", return 0);
+	return isl_int_get_si(v->n);
+}
+
+/* Extract the numerator of a rational value "v" as an isl_int.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+int isl_val_get_num_isl_int(__isl_keep isl_val *v, isl_int *n)
+{
+	if (!v)
+		return -1;
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return -1);
+	isl_int_set(*n, v->n);
+	return 0;
+}
+
+/* Extract the denominator of a rational value "v" as an integer.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+long isl_val_get_den_si(__isl_keep isl_val *v)
+{
+	if (!v)
+		return 0;
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return 0);
+	if (!isl_int_fits_slong(v->d))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"denominator too large", return 0);
+	return isl_int_get_si(v->d);
+}
+
+/* Return an approximation of "v" as a double.
+ */
+double isl_val_get_d(__isl_keep isl_val *v)
+{
+	if (!v)
+		return 0;
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return 0);
+	return isl_int_get_d(v->n) / isl_int_get_d(v->d);
+}
+
+/* Return the isl_ctx to which "val" belongs.
+ */
+isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val)
+{
+	return val ? val->ctx : NULL;
+}
+
+/* Normalize "v".
+ *
+ * In particular, make sure that the denominator of a rational value
+ * is positive and the numerator and denominator do not have any
+ * common divisors.
+ *
+ * This function should not be called by an external user
+ * since it will only be given normalized values.
+ */
+__isl_give isl_val *isl_val_normalize(__isl_take isl_val *v)
+{
+	isl_ctx *ctx;
+
+	if (!v)
+		return NULL;
+	if (isl_val_is_int(v))
+		return v;
+	if (!isl_val_is_rat(v))
+		return v;
+	if (isl_int_is_neg(v->d)) {
+		isl_int_neg(v->d, v->d);
+		isl_int_neg(v->n, v->n);
+	}
+	ctx = isl_val_get_ctx(v);
+	isl_int_gcd(ctx->normalize_gcd, v->n, v->d);
+	if (isl_int_is_one(ctx->normalize_gcd))
+		return v;
+	isl_int_divexact(v->n, v->n, ctx->normalize_gcd);
+	isl_int_divexact(v->d, v->d, ctx->normalize_gcd);
+	return v;
+}
+
+/* Return the opposite of "v".
+ */
+__isl_give isl_val *isl_val_neg(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_nan(v))
+		return v;
+	if (isl_val_is_zero(v))
+		return v;
+
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+	isl_int_neg(v->n, v->n);
+
+	return v;
+}
+
+/* Return the inverse of "v".
+ */
+__isl_give isl_val *isl_val_inv(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_nan(v))
+		return v;
+	if (isl_val_is_zero(v)) {
+		isl_ctx *ctx = isl_val_get_ctx(v);
+		isl_val_free(v);
+		return isl_val_nan(ctx);
+	}
+	if (isl_val_is_infty(v) || isl_val_is_neginfty(v)) {
+		isl_ctx *ctx = isl_val_get_ctx(v);
+		isl_val_free(v);
+		return isl_val_zero(ctx);
+	}
+
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+	isl_int_swap(v->n, v->d);
+
+	return isl_val_normalize(v);
+}
+
+/* Return the absolute value of "v".
+ */
+__isl_give isl_val *isl_val_abs(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_nan(v))
+		return v;
+	if (isl_val_is_nonneg(v))
+		return v;
+	return isl_val_neg(v);
+}
+
+/* Return the "floor" (greatest integer part) of "v".
+ * That is, return the result of rounding towards -infinity.
+ */
+__isl_give isl_val *isl_val_floor(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_int(v))
+		return v;
+	if (!isl_val_is_rat(v))
+		return v;
+
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+	isl_int_fdiv_q(v->n, v->n, v->d);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Return the "ceiling" of "v".
+ * That is, return the result of rounding towards +infinity.
+ */
+__isl_give isl_val *isl_val_ceil(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_int(v))
+		return v;
+	if (!isl_val_is_rat(v))
+		return v;
+
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+	isl_int_cdiv_q(v->n, v->n, v->d);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Truncate "v".
+ * That is, return the result of rounding towards zero.
+ */
+__isl_give isl_val *isl_val_trunc(__isl_take isl_val *v)
+{
+	if (!v)
+		return NULL;
+	if (isl_val_is_int(v))
+		return v;
+	if (!isl_val_is_rat(v))
+		return v;
+
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+	isl_int_tdiv_q(v->n, v->n, v->d);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Return 2^v, where v is an integer (that is not too large).
+ */
+__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v)
+{
+	unsigned long exp;
+	int neg;
+
+	v = isl_val_cow(v);
+	if (!v)
+		return NULL;
+	if (!isl_val_is_int(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"can only compute integer powers",
+			return isl_val_free(v));
+	neg = isl_val_is_neg(v);
+	if (neg)
+		isl_int_neg(v->n, v->n);
+	if (!isl_int_fits_ulong(v->n))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"exponent too large", return isl_val_free(v));
+	exp = isl_int_get_ui(v->n);
+	if (neg) {
+		isl_int_mul_2exp(v->d, v->d, exp);
+		isl_int_set_si(v->n, 1);
+	} else {
+		isl_int_mul_2exp(v->n, v->d, exp);
+	}
+
+	return v;
+}
+
+/* Return the minimum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+
+	if (isl_val_is_nan(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_nan(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if (isl_val_le(v1, v2)) {
+		isl_val_free(v2);
+		return v1;
+	} else {
+		isl_val_free(v1);
+		return v2;
+	}
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Return the maximum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+
+	if (isl_val_is_nan(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_nan(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if (isl_val_ge(v1, v2)) {
+		isl_val_free(v2);
+		return v1;
+	} else {
+		isl_val_free(v1);
+		return v2;
+	}
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Return the sum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_add(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+	if (isl_val_is_nan(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_nan(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if ((isl_val_is_infty(v1) && isl_val_is_neginfty(v2)) ||
+	    (isl_val_is_neginfty(v1) && isl_val_is_infty(v2))) {
+		isl_val_free(v2);
+		return isl_val_set_nan(v1);
+	}
+	if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if (isl_val_is_zero(v1)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if (isl_val_is_zero(v2)) {
+		isl_val_free(v2);
+		return v1;
+	}
+
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		goto error;
+	if (isl_val_is_int(v1) && isl_val_is_int(v2))
+		isl_int_add(v1->n, v1->n, v2->n);
+	else {
+		if (isl_int_eq(v1->d, v2->d))
+			isl_int_add(v1->n, v1->n, v2->n);
+		else {
+			isl_int_mul(v1->n, v1->n, v2->d);
+			isl_int_addmul(v1->n, v2->n, v1->d);
+			isl_int_mul(v1->d, v1->d, v2->d);
+		}
+		v1 = isl_val_normalize(v1);
+	}
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Return the sum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1, unsigned long v2)
+{
+	if (!v1)
+		return NULL;
+	if (!isl_val_is_rat(v1))
+		return v1;
+	if (v2 == 0)
+		return v1;
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		return NULL;
+
+	isl_int_addmul_ui(v1->n, v1->d, v2);
+
+	return v1;
+}
+
+/* Subtract "v2" from "v1".
+ */
+__isl_give isl_val *isl_val_sub(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+	if (isl_val_is_nan(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_nan(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if ((isl_val_is_infty(v1) && isl_val_is_infty(v2)) ||
+	    (isl_val_is_neginfty(v1) && isl_val_is_neginfty(v2))) {
+		isl_val_free(v2);
+		return isl_val_set_nan(v1);
+	}
+	if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+		isl_val_free(v1);
+		return isl_val_neg(v2);
+	}
+	if (isl_val_is_zero(v2)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_zero(v1)) {
+		isl_val_free(v1);
+		return isl_val_neg(v2);
+	}
+
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		goto error;
+	if (isl_val_is_int(v1) && isl_val_is_int(v2))
+		isl_int_sub(v1->n, v1->n, v2->n);
+	else {
+		if (isl_int_eq(v1->d, v2->d))
+			isl_int_sub(v1->n, v1->n, v2->n);
+		else {
+			isl_int_mul(v1->n, v1->n, v2->d);
+			isl_int_submul(v1->n, v2->n, v1->d);
+			isl_int_mul(v1->d, v1->d, v2->d);
+		}
+		v1 = isl_val_normalize(v1);
+	}
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Subtract "v2" from "v1".
+ */
+__isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1, unsigned long v2)
+{
+	if (!v1)
+		return NULL;
+	if (!isl_val_is_rat(v1))
+		return v1;
+	if (v2 == 0)
+		return v1;
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		return NULL;
+
+	isl_int_submul_ui(v1->n, v1->d, v2);
+
+	return v1;
+}
+
+/* Return the product of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_mul(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+	if (isl_val_is_nan(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_nan(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if ((!isl_val_is_rat(v1) && isl_val_is_zero(v2)) ||
+	    (isl_val_is_zero(v1) && !isl_val_is_rat(v2))) {
+		isl_val_free(v2);
+		return isl_val_set_nan(v1);
+	}
+	if (isl_val_is_zero(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_zero(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+		if (isl_val_is_neg(v2))
+			v1 = isl_val_neg(v1);
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+		if (isl_val_is_neg(v1))
+			v2 = isl_val_neg(v2);
+		isl_val_free(v1);
+		return v2;
+	}
+
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		goto error;
+	if (isl_val_is_int(v1) && isl_val_is_int(v2))
+		isl_int_mul(v1->n, v1->n, v2->n);
+	else {
+		isl_int_mul(v1->n, v1->n, v2->n);
+		isl_int_mul(v1->d, v1->d, v2->d);
+		v1 = isl_val_normalize(v1);
+	}
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Return the product of "v1" and "v2".
+ *
+ * This is a private copy of isl_val_mul for use in the generic
+ * isl_multi_*_scale_val instantiated for isl_val.
+ */
+__isl_give isl_val *isl_val_scale_val(__isl_take isl_val *v1,
+	__isl_take isl_val *v2)
+{
+	return isl_val_mul(v1, v2);
+}
+
+/* Return the product of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1, unsigned long v2)
+{
+	if (!v1)
+		return NULL;
+	if (isl_val_is_nan(v1))
+		return v1;
+	if (!isl_val_is_rat(v1)) {
+		if (v2 == 0)
+			v1 = isl_val_set_nan(v1);
+		return v1;
+	}
+	if (v2 == 1)
+		return v1;
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		return NULL;
+
+	isl_int_mul_ui(v1->n, v1->n, v2);
+
+	return isl_val_normalize(v1);
+}
+
+/* Divide "v1" by "v2".
+ */
+__isl_give isl_val *isl_val_div(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+	if (isl_val_is_nan(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_nan(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	if (isl_val_is_zero(v2) ||
+	    (!isl_val_is_rat(v1) && !isl_val_is_rat(v2))) {
+		isl_val_free(v2);
+		return isl_val_set_nan(v1);
+	}
+	if (isl_val_is_zero(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+		if (isl_val_is_neg(v2))
+			v1 = isl_val_neg(v1);
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+		isl_val_free(v2);
+		return isl_val_set_zero(v1);
+	}
+
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		goto error;
+	if (isl_val_is_int(v2)) {
+		isl_int_mul(v1->d, v1->d, v2->n);
+		v1 = isl_val_normalize(v1);
+	} else {
+		isl_int_mul(v1->d, v1->d, v2->n);
+		isl_int_mul(v1->n, v1->n, v2->d);
+		v1 = isl_val_normalize(v1);
+	}
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Divide "v1" by "v2".
+ *
+ * This is a private copy of isl_val_div for use in the generic
+ * isl_multi_*_scale_down_val instantiated for isl_val.
+ */
+__isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1,
+	__isl_take isl_val *v2)
+{
+	return isl_val_div(v1, v2);
+}
+
+/* Given two integer values "v1" and "v2", check if "v1" is divisible by "v2".
+ */
+int isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	if (!v1 || !v2)
+		return -1;
+
+	if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+		isl_die(isl_val_get_ctx(v1), isl_error_invalid,
+			"expecting two integers", return -1);
+
+	return isl_int_is_divisible_by(v1->n, v2->n);
+}
+
+/* Given two integer values "v1" and "v2", return the residue of "v1"
+ * modulo "v2".
+ */
+__isl_give isl_val *isl_val_mod(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+	if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+		isl_die(isl_val_get_ctx(v1), isl_error_invalid,
+			"expecting two integers", goto error);
+	if (isl_val_is_nonneg(v1) && isl_val_lt(v1, v2)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		goto error;
+	isl_int_fdiv_r(v1->n, v1->n, v2->n);
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Given two integer values, return their greatest common divisor.
+ */
+__isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+	if (!v1 || !v2)
+		goto error;
+	if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+		isl_die(isl_val_get_ctx(v1), isl_error_invalid,
+			"expecting two integers", goto error);
+	if (isl_val_eq(v1, v2)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_one(v1)) {
+		isl_val_free(v2);
+		return v1;
+	}
+	if (isl_val_is_one(v2)) {
+		isl_val_free(v1);
+		return v2;
+	}
+	v1 = isl_val_cow(v1);
+	if (!v1)
+		goto error;
+	isl_int_gcd(v1->n, v1->n, v2->n);
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	return NULL;
+}
+
+/* Compute x, y and g such that g = gcd(a,b) and a*x+b*y = g.
+ */
+static void isl_int_gcdext(isl_int g, isl_int x, isl_int y,
+	isl_int a, isl_int b)
+{
+	isl_int d, tmp;
+	isl_int a_copy, b_copy;
+
+	isl_int_init(a_copy);
+	isl_int_init(b_copy);
+	isl_int_init(d);
+	isl_int_init(tmp);
+	isl_int_set(a_copy, a);
+	isl_int_set(b_copy, b);
+	isl_int_abs(g, a_copy);
+	isl_int_abs(d, b_copy);
+	isl_int_set_si(x, 1);
+	isl_int_set_si(y, 0);
+	while (isl_int_is_pos(d)) {
+		isl_int_fdiv_q(tmp, g, d);
+		isl_int_submul(x, tmp, y);
+		isl_int_submul(g, tmp, d);
+		isl_int_swap(g, d);
+		isl_int_swap(x, y);
+	}
+	if (isl_int_is_zero(a_copy))
+		isl_int_set_si(x, 0);
+	else if (isl_int_is_neg(a_copy))
+		isl_int_neg(x, x);
+	if (isl_int_is_zero(b_copy))
+		isl_int_set_si(y, 0);
+	else {
+		isl_int_mul(tmp, a_copy, x);
+		isl_int_sub(tmp, g, tmp);
+		isl_int_divexact(y, tmp, b_copy);
+	}
+	isl_int_clear(d);
+	isl_int_clear(tmp);
+	isl_int_clear(a_copy);
+	isl_int_clear(b_copy);
+}
+
+/* Given two integer values v1 and v2, return their greatest common divisor g,
+ * as well as two integers x and y such that x * v1 + y * v2 = g.
+ */
+__isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1,
+	__isl_take isl_val *v2, __isl_give isl_val **x, __isl_give isl_val **y)
+{
+	isl_ctx *ctx;
+	isl_val *a = NULL, *b = NULL;
+
+	if (!x && !y)
+		return isl_val_gcd(v1, v2);
+
+	if (!v1 || !v2)
+		goto error;
+
+	ctx = isl_val_get_ctx(v1);
+	if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+		isl_die(ctx, isl_error_invalid,
+			"expecting two integers", goto error);
+
+	v1 = isl_val_cow(v1);
+	a = isl_val_alloc(ctx);
+	b = isl_val_alloc(ctx);
+	if (!v1 || !a || !b)
+		goto error;
+	isl_int_gcdext(v1->n, a->n, b->n, v1->n, v2->n);
+	if (x) {
+		isl_int_set_si(a->d, 1);
+		*x = a;
+	} else
+		isl_val_free(a);
+	if (y) {
+		isl_int_set_si(b->d, 1);
+		*y = b;
+	} else
+		isl_val_free(b);
+	isl_val_free(v2);
+	return v1;
+error:
+	isl_val_free(v1);
+	isl_val_free(v2);
+	isl_val_free(a);
+	isl_val_free(b);
+	if (x)
+		*x = NULL;
+	if (y)
+		*y = NULL;
+	return NULL;
+}
+
+/* Does "v" represent an integer value?
+ */
+int isl_val_is_int(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_one(v->d);
+}
+
+/* Does "v" represent a rational value?
+ */
+int isl_val_is_rat(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return !isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent NaN?
+ */
+int isl_val_is_nan(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_zero(v->n) && isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent +infinity?
+ */
+int isl_val_is_infty(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_pos(v->n) && isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent -infinity?
+ */
+int isl_val_is_neginfty(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_neg(v->n) && isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent the integer zero?
+ */
+int isl_val_is_zero(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_zero(v->n) && !isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent the integer one?
+ */
+int isl_val_is_one(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_eq(v->n, v->d);
+}
+
+/* Does "v" represent the integer negative one?
+ */
+int isl_val_is_negone(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_neg(v->n) && isl_int_abs_eq(v->n, v->d);
+}
+
+/* Is "v" (strictly) positive?
+ */
+int isl_val_is_pos(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_pos(v->n);
+}
+
+/* Is "v" (strictly) negative?
+ */
+int isl_val_is_neg(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	return isl_int_is_neg(v->n);
+}
+
+/* Is "v" non-negative?
+ */
+int isl_val_is_nonneg(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	if (isl_val_is_nan(v))
+		return 0;
+
+	return isl_int_is_nonneg(v->n);
+}
+
+/* Is "v" non-positive?
+ */
+int isl_val_is_nonpos(__isl_keep isl_val *v)
+{
+	if (!v)
+		return -1;
+
+	if (isl_val_is_nan(v))
+		return 0;
+
+	return isl_int_is_nonpos(v->n);
+}
+
+/* Return the sign of "v".
+ *
+ * The sign of NaN is undefined.
+ */
+int isl_val_sgn(__isl_keep isl_val *v)
+{
+	if (!v)
+		return 0;
+	if (isl_val_is_zero(v))
+		return 0;
+	if (isl_val_is_pos(v))
+		return 1;
+	return -1;
+}
+
+/* Is "v1" (strictly) less than "v2"?
+ */
+int isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	isl_int t;
+	int lt;
+
+	if (!v1 || !v2)
+		return -1;
+	if (isl_val_is_int(v1) && isl_val_is_int(v2))
+		return isl_int_lt(v1->n, v2->n);
+	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+		return 0;
+	if (isl_val_eq(v1, v2))
+		return 0;
+	if (isl_val_is_infty(v2))
+		return 1;
+	if (isl_val_is_infty(v1))
+		return 0;
+	if (isl_val_is_neginfty(v1))
+		return 1;
+	if (isl_val_is_neginfty(v2))
+		return 0;
+
+	isl_int_init(t);
+	isl_int_mul(t, v1->n, v2->d);
+	isl_int_submul(t, v2->n, v1->d);
+	lt = isl_int_is_neg(t);
+	isl_int_clear(t);
+
+	return lt;
+}
+
+/* Is "v1" (strictly) greater than "v2"?
+ */
+int isl_val_gt(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	return isl_val_lt(v2, v1);
+}
+
+/* Is "v1" less than or equal to "v2"?
+ */
+int isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	isl_int t;
+	int le;
+
+	if (!v1 || !v2)
+		return -1;
+	if (isl_val_is_int(v1) && isl_val_is_int(v2))
+		return isl_int_le(v1->n, v2->n);
+	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+		return 0;
+	if (isl_val_eq(v1, v2))
+		return 1;
+	if (isl_val_is_infty(v2))
+		return 1;
+	if (isl_val_is_infty(v1))
+		return 0;
+	if (isl_val_is_neginfty(v1))
+		return 1;
+	if (isl_val_is_neginfty(v2))
+		return 0;
+
+	isl_int_init(t);
+	isl_int_mul(t, v1->n, v2->d);
+	isl_int_submul(t, v2->n, v1->d);
+	le = isl_int_is_nonpos(t);
+	isl_int_clear(t);
+
+	return le;
+}
+
+/* Is "v1" greater than or equal to "v2"?
+ */
+int isl_val_ge(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	return isl_val_le(v2, v1);
+}
+
+/* How does "v" compare to "i"?
+ *
+ * Return 1 if v is greater, -1 if v is smaller and 0 if v is equal to i.
+ *
+ * If v is NaN (or NULL), then the result is undefined.
+ */
+int isl_val_cmp_si(__isl_keep isl_val *v, long i)
+{
+	isl_int t;
+	int cmp;
+
+	if (!v)
+		return 0;
+	if (isl_val_is_int(v))
+		return isl_int_cmp_si(v->n, i);
+	if (isl_val_is_nan(v))
+		return 0;
+	if (isl_val_is_infty(v))
+		return 1;
+	if (isl_val_is_neginfty(v))
+		return -1;
+
+	isl_int_init(t);
+	isl_int_mul_si(t, v->d, i);
+	isl_int_sub(t, v->n, t);
+	cmp = isl_int_sgn(t);
+	isl_int_clear(t);
+
+	return cmp;
+}
+
+/* Is "v1" equal to "v2"?
+ */
+int isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	if (!v1 || !v2)
+		return -1;
+	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+		return 0;
+
+	return isl_int_eq(v1->n, v2->n) && isl_int_eq(v1->d, v2->d);
+}
+
+/* Is "v1" equal to "v2" in absolute value?
+ */
+int isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	if (!v1 || !v2)
+		return -1;
+	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+		return 0;
+
+	return isl_int_abs_eq(v1->n, v2->n) && isl_int_eq(v1->d, v2->d);
+}
+
+/* Is "v1" different from "v2"?
+ */
+int isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+	if (!v1 || !v2)
+		return -1;
+	if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+		return 0;
+
+	return isl_int_ne(v1->n, v2->n) || isl_int_ne(v1->d, v2->d);
+}
+
+/* Print a textual representation of "v" onto "p".
+ */
+__isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p,
+	__isl_keep isl_val *v)
+{
+	int neg;
+
+	if (!p || !v)
+		return isl_printer_free(p);
+
+	neg = isl_int_is_neg(v->n);
+	if (neg) {
+		p = isl_printer_print_str(p, "-");
+		isl_int_neg(v->n, v->n);
+	}
+	if (isl_int_is_zero(v->d)) {
+		int sgn = isl_int_sgn(v->n);
+		p = isl_printer_print_str(p, sgn < 0 ? "-infty" :
+					    sgn == 0 ? "NaN" : "infty");
+	} else
+		p = isl_printer_print_isl_int(p, v->n);
+	if (neg)
+		isl_int_neg(v->n, v->n);
+	if (!isl_int_is_zero(v->d) && !isl_int_is_one(v->d)) {
+		p = isl_printer_print_str(p, "/");
+		p = isl_printer_print_isl_int(p, v->d);
+	}
+
+	return p;
+}
+
+/* Is "val1" (obviously) equal to "val2"?
+ *
+ * This is a private copy of isl_val_eq for use in the generic
+ * isl_multi_*_plain_is_equal instantiated for isl_val.
+ */
+int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2)
+{
+	return isl_val_eq(val1, val2);
+}
+
+/* Does "v" have any non-zero coefficients
+ * for any dimension in the given range?
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have any coefficients, this function
+ * always return 0.
+ */
+int isl_val_involves_dims(__isl_keep isl_val *v, enum isl_dim_type type,
+	unsigned first, unsigned n)
+{
+	if (!v)
+		return -1;
+
+	return 0;
+}
+
+/* Insert "n" dimensions of type "type" at position "first".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * does not do anything.
+ */
+__isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	return v;
+}
+
+/* Drop the the "n" first dimensions of type "type" at position "first".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * does not do anything.
+ */
+__isl_give isl_val *isl_val_drop_dims(__isl_take isl_val *v,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	return v;
+}
+
+/* Change the name of the dimension of type "type" at position "pos" to "s".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * does not do anything.
+ */
+__isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v,
+	enum isl_dim_type type, unsigned pos, const char *s)
+{
+	return v;
+}
+
+/* Return the space of "v".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  The conditions surrounding the call to this function make sure
+ * that this function will never actually get called.  We return a valid
+ * space anyway, just in case.
+ */
+__isl_give isl_space *isl_val_get_space(__isl_keep isl_val *v)
+{
+	if (!v)
+		return NULL;
+
+	return isl_space_params_alloc(isl_val_get_ctx(v), 0);
+}
+
+/* Reset the domain space of "v" to "space".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ */
+__isl_give isl_val *isl_val_reset_domain_space(__isl_take isl_val *v,
+	__isl_take isl_space *space)
+{
+	if (!space)
+		return isl_val_free(v);
+	isl_space_free(space);
+	return v;
+}
+
+/* Align the parameters of "v" to those of "space".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ * Note that the conditions surrounding the call to this function make sure
+ * that this function will never actually get called.
+ */
+__isl_give isl_val *isl_val_align_params(__isl_take isl_val *v,
+	__isl_take isl_space *space)
+{
+	if (!space)
+		return isl_val_free(v);
+	isl_space_free(space);
+	return v;
+}
+
+/* Reorder the dimensions of the domain of "v" according
+ * to the given reordering.
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ */
+__isl_give isl_val *isl_val_realign_domain(__isl_take isl_val *v,
+	__isl_take isl_reordering *r)
+{
+	if (!r)
+		return isl_val_free(v);
+	isl_reordering_free(r);
+	return v;
+}
+
+/* Return an isl_val that is zero on "ls".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * simply returns a zero isl_val in the same context as "ls".
+ */
+__isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls)
+{
+	isl_ctx *ctx;
+
+	if (!ls)
+		return NULL;
+	ctx = isl_local_space_get_ctx(ls);
+	isl_local_space_free(ls);
+	return isl_val_zero(ctx);
+}
+
+/* Do the parameters of "v" match those of "space"?
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * simply returns 1, except if "v" or "space" are NULL.
+ */
+int isl_val_matching_params(__isl_keep isl_val *v, __isl_keep isl_space *space)
+{
+	if (!v || !space)
+		return -1;
+	return 1;
+}
+
+/* Check that the domain space of "v" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space.  Since an isl_val does not have an associated space, this function
+ * simply returns 0, except if "v" or "space" are NULL.
+ */
+int isl_val_check_match_domain_space(__isl_keep isl_val *v,
+	__isl_keep isl_space *space)
+{
+	if (!v || !space)
+		return -1;
+	return 0;
+}
+
+#undef BASE
+#define BASE val
+
+#define NO_DOMAIN
+#define NO_INTERSECT_DOMAIN
+#define NO_GIST
+#define NO_IDENTITY
+#define NO_FROM_BASE
+#define NO_MOVE_DIMS
+#include <isl_multi_templ.c>
+
+/* Apply "fn" to each of the elements of "mv" with as second argument "v".
+ */
+static __isl_give isl_multi_val *isl_multi_val_fn_val(
+	__isl_take isl_multi_val *mv,
+	__isl_give isl_val *(*fn)(__isl_take isl_val *v1,
+					__isl_take isl_val *v2),
+	__isl_take isl_val *v)
+{
+	int i;
+
+	mv = isl_multi_val_cow(mv);
+	if (!mv || !v)
+		goto error;
+
+	for (i = 0; i < mv->n; ++i) {
+		mv->p[i] = fn(mv->p[i], isl_val_copy(v));
+		if (!mv->p[i])
+			goto error;
+	}
+
+	isl_val_free(v);
+	return mv;
+error:
+	isl_val_free(v);
+	isl_multi_val_free(mv);
+	return NULL;
+}
+
+/* Add "v" to each of the elements of "mv".
+ */
+__isl_give isl_multi_val *isl_multi_val_add_val(__isl_take isl_multi_val *mv,
+	__isl_take isl_val *v)
+{
+	if (!v)
+		return isl_multi_val_free(mv);
+	if (isl_val_is_zero(v)) {
+		isl_val_free(v);
+		return mv;
+	}
+	return isl_multi_val_fn_val(mv, &isl_val_add, v);
+}
+
+/* Reduce the elements of "mv" modulo "v".
+ */
+__isl_give isl_multi_val *isl_multi_val_mod_val(__isl_take isl_multi_val *mv,
+	__isl_take isl_val *v)
+{
+	return isl_multi_val_fn_val(mv, &isl_val_mod, v);
+}

Added: polly/trunk/lib/External/isl/isl_val_gmp.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_val_gmp.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_val_gmp.c (added)
+++ polly/trunk/lib/External/isl/isl_val_gmp.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,128 @@
+#include <string.h>
+#include <isl/val_gmp.h>
+#include <isl_val_private.h>
+
+/* Return a reference to an isl_val representing the integer "z".
+ */
+__isl_give isl_val *isl_val_int_from_gmp(isl_ctx *ctx, mpz_t z)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set(v->n, z);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Return a reference to an isl_val representing the rational value "n"/"d".
+ */
+__isl_give isl_val *isl_val_from_gmp(isl_ctx *ctx, const mpz_t n, const mpz_t d)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	isl_int_set(v->n, n);
+	isl_int_set(v->d, d);
+
+	return isl_val_normalize(v);
+}
+
+/* Extract the numerator of a rational value "v" in "z".
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+int isl_val_get_num_gmp(__isl_keep isl_val *v, mpz_t z)
+{
+	if (!v)
+		return -1;
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return -1);
+	mpz_set(z, v->n);
+	return 0;
+}
+
+/* Extract the denominator of a rational value "v" in "z".
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z)
+{
+	if (!v)
+		return -1;
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return -1);
+	mpz_set(z, v->d);
+	return 0;
+}
+
+/* Return a reference to an isl_val representing the unsigned
+ * integer value stored in the "n" chunks of size "size" at "chunks".
+ * The least significant chunk is assumed to be stored first.
+ */
+__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
+	size_t size, const void *chunks)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	mpz_import(v->n, n, -1, size, 0, 0, chunks);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Return the number of chunks of size "size" required to
+ * store the absolute value of the numerator of "v".
+ */
+size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
+{
+	if (!v)
+		return 0;
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return 0);
+
+	size *= 8;
+	return (mpz_sizeinbase(v->n, 2) + size - 1) / size;
+}
+
+/* Store a representation of the absolute value of the numerator of "v"
+ * in terms of chunks of size "size" at "chunks".
+ * The least significant chunk is stored first.
+ * The number of chunks in the result can be obtained by calling
+ * isl_val_n_abs_num_chunks.  The user is responsible for allocating
+ * enough memory to store the results.
+ *
+ * In the special case of a zero value, isl_val_n_abs_num_chunks will
+ * return one, while mpz_export will not fill in any chunks.  We therefore
+ * do it ourselves.
+ */
+int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+	void *chunks)
+{
+	if (!v || !chunks)
+		return -1;
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return -1);
+
+	mpz_export(chunks, NULL, -1, size, 0, 0, v->n);
+	if (isl_val_is_zero(v))
+		memset(chunks, 0, size);
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/isl_val_imath.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_val_imath.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_val_imath.c (added)
+++ polly/trunk/lib/External/isl/isl_val_imath.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,64 @@
+#include <isl_val_private.h>
+
+/* Return a reference to an isl_val representing the unsigned
+ * integer value stored in the "n" chunks of size "size" at "chunks".
+ * The least significant chunk is assumed to be stored first.
+ */
+__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
+	size_t size, const void *chunks)
+{
+	isl_val *v;
+
+	v = isl_val_alloc(ctx);
+	if (!v)
+		return NULL;
+
+	impz_import(v->n, n, -1, size, 0, 0, chunks);
+	isl_int_set_si(v->d, 1);
+
+	return v;
+}
+
+/* Store a representation of the absolute value of the numerator of "v"
+ * in terms of chunks of size "size" at "chunks".
+ * The least significant chunk is stored first.
+ * The number of chunks in the result can be obtained by calling
+ * isl_val_n_abs_num_chunks.  The user is responsible for allocating
+ * enough memory to store the results.
+ *
+ * In the special case of a zero value, isl_val_n_abs_num_chunks will
+ * return one, while impz_export will not fill in any chunks.  We therefore
+ * do it ourselves.
+ */
+int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+	void *chunks)
+{
+	if (!v || !chunks)
+		return -1;
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return -1);
+
+	impz_export(chunks, NULL, -1, size, 0, 0, v->n);
+	if (isl_val_is_zero(v))
+		memset(chunks, 0, size);
+
+	return 0;
+}
+
+/* Return the number of chunks of size "size" required to
+ * store the absolute value of the numerator of "v".
+ */
+size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size)
+{
+	if (!v)
+		return 0;
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting rational value", return 0);
+
+	size *= 8;
+	return (impz_sizeinbase(v->n, 2) + size - 1) / size;
+}

Added: polly/trunk/lib/External/isl/isl_val_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_val_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_val_private.h (added)
+++ polly/trunk/lib/External/isl/isl_val_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,70 @@
+#ifndef ISL_VAL_PRIVATE_H
+#define ISL_VAL_PRIVATE_H
+
+#include <isl_int.h>
+#include <isl/val.h>
+#include <isl/local_space.h>
+#include <isl_reordering.h>
+
+/* Represents a "value", which may be an integer value, a rational value,
+ * plus or minus infinity or "not a number".
+ *
+ * Internally, +infinity is represented as 1/0,
+ * -infinity as -1/0 and NaN as 0/0.
+ *
+ * A rational value is always normalized before it is passed to the user.
+ */
+struct isl_val {
+	int ref;
+	isl_ctx *ctx;
+
+	isl_int n;
+	isl_int d;
+};
+
+#undef EL
+#define EL isl_val
+
+#include <isl_list_templ.h>
+
+__isl_give isl_val *isl_val_alloc(isl_ctx *ctx);
+__isl_give isl_val *isl_val_normalize(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n);
+__isl_give isl_val *isl_val_rat_from_isl_int(isl_ctx *ctx,
+	isl_int n, isl_int d);
+__isl_give isl_val *isl_val_cow(__isl_take isl_val *val);
+
+int isl_val_involves_dims(__isl_keep isl_val *v, enum isl_dim_type type,
+	unsigned first, unsigned n);
+__isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_val *isl_val_drop_dims(__isl_take isl_val *v,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v,
+	enum isl_dim_type type, unsigned pos, const char *s);
+__isl_give isl_space *isl_val_get_space(__isl_keep isl_val *v);
+__isl_give isl_val *isl_val_reset_domain_space(__isl_take isl_val *v,
+	__isl_take isl_space *space);
+__isl_give isl_val *isl_val_align_params(__isl_take isl_val *v,
+	__isl_take isl_space *space);
+__isl_give isl_val *isl_val_realign_domain(__isl_take isl_val *v,
+	__isl_take isl_reordering *r);
+__isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls);
+
+__isl_give isl_val *isl_val_scale_val(__isl_take isl_val *v1,
+	__isl_take isl_val *v2);
+__isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1,
+	__isl_take isl_val *v2);
+
+int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2);
+
+int isl_val_matching_params(__isl_keep isl_val *v, __isl_keep isl_space *space);
+int isl_val_check_match_domain_space(__isl_keep isl_val *v,
+	__isl_keep isl_space *space);
+
+#undef BASE
+#define BASE val
+
+#include <isl_multi_templ.h>
+
+#endif

Added: polly/trunk/lib/External/isl/isl_vec.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_vec.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_vec.c (added)
+++ polly/trunk/lib/External/isl/isl_vec.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,579 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2013      Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_seq.h>
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+#include <isl/deprecated/vec_int.h>
+
+isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec)
+{
+	return vec ? vec->ctx : NULL;
+}
+
+struct isl_vec *isl_vec_alloc(struct isl_ctx *ctx, unsigned size)
+{
+	struct isl_vec *vec;
+
+	vec = isl_alloc_type(ctx, struct isl_vec);
+	if (!vec)
+		return NULL;
+
+	vec->block = isl_blk_alloc(ctx, size);
+	if (isl_blk_is_error(vec->block))
+		goto error;
+
+	vec->ctx = ctx;
+	isl_ctx_ref(ctx);
+	vec->ref = 1;
+	vec->size = size;
+	vec->el = vec->block.data;
+
+	return vec;
+error:
+	isl_blk_free(ctx, vec->block);
+	return NULL;
+}
+
+__isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size)
+{
+	if (!vec)
+		return NULL;
+	if (size <= vec->size)
+		return vec;
+
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+
+	vec->block = isl_blk_extend(vec->ctx, vec->block, size);
+	if (!vec->block.data)
+		goto error;
+
+	vec->size = size;
+	vec->el = vec->block.data;
+
+	return vec;
+error:
+	isl_vec_free(vec);
+	return NULL;
+}
+
+__isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size)
+{
+	int extra;
+
+	if (!vec)
+		return NULL;
+	if (size <= vec->size)
+		return vec;
+
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+
+	extra = size - vec->size;
+	vec = isl_vec_extend(vec, size);
+	if (!vec)
+		return NULL;
+
+	isl_seq_clr(vec->el + size - extra, extra);
+
+	return vec;
+}
+
+/* Return a vector containing the elements of "vec1" followed by
+ * those of "vec2".
+ */
+__isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
+	__isl_take isl_vec *vec2)
+{
+	if (!vec1 || !vec2)
+		goto error;
+
+	if (vec2->size == 0) {
+		isl_vec_free(vec2);
+		return vec1;
+	}
+
+	if (vec1->size == 0) {
+		isl_vec_free(vec1);
+		return vec2;
+	}
+
+	vec1 = isl_vec_extend(vec1, vec1->size + vec2->size);
+	if (!vec1)
+		goto error;
+
+	isl_seq_cpy(vec1->el + vec1->size - vec2->size, vec2->el, vec2->size);
+
+	isl_vec_free(vec2);
+	return vec1;
+error:
+	isl_vec_free(vec1);
+	isl_vec_free(vec2);
+	return NULL;
+}
+
+struct isl_vec *isl_vec_copy(struct isl_vec *vec)
+{
+	if (!vec)
+		return NULL;
+
+	vec->ref++;
+	return vec;
+}
+
+struct isl_vec *isl_vec_dup(struct isl_vec *vec)
+{
+	struct isl_vec *vec2;
+
+	if (!vec)
+		return NULL;
+	vec2 = isl_vec_alloc(vec->ctx, vec->size);
+	if (!vec2)
+		return NULL;
+	isl_seq_cpy(vec2->el, vec->el, vec->size);
+	return vec2;
+}
+
+struct isl_vec *isl_vec_cow(struct isl_vec *vec)
+{
+	struct isl_vec *vec2;
+	if (!vec)
+		return NULL;
+
+	if (vec->ref == 1)
+		return vec;
+
+	vec2 = isl_vec_dup(vec);
+	isl_vec_free(vec);
+	return vec2;
+}
+
+__isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec)
+{
+	if (!vec)
+		return NULL;
+
+	if (--vec->ref > 0)
+		return NULL;
+
+	isl_ctx_deref(vec->ctx);
+	isl_blk_free(vec->ctx, vec->block);
+	free(vec);
+
+	return NULL;
+}
+
+int isl_vec_size(__isl_keep isl_vec *vec)
+{
+	return vec ? vec->size : -1;
+}
+
+int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v)
+{
+	if (!vec)
+		return -1;
+
+	if (pos < 0 || pos >= vec->size)
+		isl_die(vec->ctx, isl_error_invalid, "position out of range",
+			return -1);
+	isl_int_set(*v, vec->el[pos]);
+	return 0;
+}
+
+/* Extract the element at position "pos" of "vec".
+ */
+__isl_give isl_val *isl_vec_get_element_val(__isl_keep isl_vec *vec, int pos)
+{
+	isl_ctx *ctx;
+
+	if (!vec)
+		return NULL;
+	ctx = isl_vec_get_ctx(vec);
+	if (pos < 0 || pos >= vec->size)
+		isl_die(ctx, isl_error_invalid, "position out of range",
+			return NULL);
+	return isl_val_int_from_isl_int(ctx, vec->el[pos]);
+}
+
+__isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec,
+	int pos, isl_int v)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	if (pos < 0 || pos >= vec->size)
+		isl_die(vec->ctx, isl_error_invalid, "position out of range",
+			goto error);
+	isl_int_set(vec->el[pos], v);
+	return vec;
+error:
+	isl_vec_free(vec);
+	return NULL;
+}
+
+__isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec,
+	int pos, int v)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	if (pos < 0 || pos >= vec->size)
+		isl_die(vec->ctx, isl_error_invalid, "position out of range",
+			goto error);
+	isl_int_set_si(vec->el[pos], v);
+	return vec;
+error:
+	isl_vec_free(vec);
+	return NULL;
+}
+
+/* Replace the element at position "pos" of "vec" by "v".
+ */
+__isl_give isl_vec *isl_vec_set_element_val(__isl_take isl_vec *vec,
+	int pos, __isl_take isl_val *v)
+{
+	if (!v)
+		return isl_vec_free(vec);
+	if (!isl_val_is_int(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting integer value", goto error);
+	vec = isl_vec_set_element(vec, pos, v->n);
+	isl_val_free(v);
+	return vec;
+error:
+	isl_val_free(v);
+	return isl_vec_free(vec);
+}
+
+/* Compare the elements of "vec1" and "vec2" at position "pos".
+ */
+int isl_vec_cmp_element(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2,
+	int pos)
+{
+	if (!vec1 || !vec2)
+		return 0;
+	if (pos < 0 || pos >= vec1->size || pos >= vec2->size)
+		isl_die(isl_vec_get_ctx(vec1), isl_error_invalid,
+			"position out of range", return 0);
+	return isl_int_cmp(vec1->el[pos], vec2->el[pos]);
+}
+
+int isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2)
+{
+	if (!vec1 || !vec2)
+		return -1;
+
+	if (vec1->size != vec2->size)
+		return 0;
+
+	return isl_seq_eq(vec1->el, vec2->el, vec1->size);
+}
+
+__isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,
+	__isl_keep isl_vec *vec)
+{
+	int i;
+
+	if (!printer || !vec)
+		goto error;
+
+	printer = isl_printer_print_str(printer, "[");
+	for (i = 0; i < vec->size; ++i) {
+		if (i)
+			printer = isl_printer_print_str(printer, ",");
+		printer = isl_printer_print_isl_int(printer, vec->el[i]);
+	}
+	printer = isl_printer_print_str(printer, "]");
+
+	return printer;
+error:
+	isl_printer_free(printer);
+	return NULL;
+}
+
+void isl_vec_dump(struct isl_vec *vec)
+{
+	isl_printer *printer;
+
+	if (!vec)
+		return;
+
+	printer = isl_printer_to_file(vec->ctx, stderr);
+	printer = isl_printer_print_vec(printer, vec);
+	printer = isl_printer_end_line(printer);
+
+	isl_printer_free(printer);
+}
+
+__isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	isl_seq_set(vec->el, v, vec->size);
+	return vec;
+}
+
+__isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	isl_seq_set_si(vec->el, v, vec->size);
+	return vec;
+}
+
+/* Replace all elements of "vec" by "v".
+ */
+__isl_give isl_vec *isl_vec_set_val(__isl_take isl_vec *vec,
+	__isl_take isl_val *v)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec || !v)
+		goto error;
+	if (!isl_val_is_int(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting integer value", goto error);
+	isl_seq_set(vec->el, v->n, vec->size);
+	isl_val_free(v);
+	return vec;
+error:
+	isl_vec_free(vec);
+	isl_val_free(v);
+	return NULL;
+}
+
+__isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	isl_seq_clr(vec->el, vec->size);
+	return vec;
+}
+
+void isl_vec_lcm(struct isl_vec *vec, isl_int *lcm)
+{
+	isl_seq_lcm(vec->block.data, vec->size, lcm);
+}
+
+/* Given a rational vector, with the denominator in the first element
+ * of the vector, round up all coordinates.
+ */
+struct isl_vec *isl_vec_ceil(struct isl_vec *vec)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+
+	isl_seq_cdiv_q(vec->el + 1, vec->el + 1, vec->el[0], vec->size - 1);
+
+	isl_int_set_si(vec->el[0], 1);
+
+	return vec;
+}
+
+struct isl_vec *isl_vec_normalize(struct isl_vec *vec)
+{
+	if (!vec)
+		return NULL;
+	isl_seq_normalize(vec->ctx, vec->el, vec->size);
+	return vec;
+}
+
+__isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	isl_seq_neg(vec->el, vec->el, vec->size);
+	return vec;
+}
+
+__isl_give isl_vec *isl_vec_scale(__isl_take isl_vec *vec, isl_int m)
+{
+	if (isl_int_is_one(m))
+		return vec;
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+	isl_seq_scale(vec->el, vec->el, m, vec->size);
+	return vec;
+}
+
+/* Reduce the elements of "vec" modulo "m".
+ */
+__isl_give isl_vec *isl_vec_fdiv_r(__isl_take isl_vec *vec, isl_int m)
+{
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+
+	isl_seq_fdiv_r(vec->el, vec->el, m, vec->size);
+
+	return vec;
+}
+
+__isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1,
+	__isl_take isl_vec *vec2)
+{
+	vec1 = isl_vec_cow(vec1);
+	if (!vec1 || !vec2)
+		goto error;
+
+	isl_assert(vec1->ctx, vec1->size == vec2->size, goto error);
+
+	isl_seq_combine(vec1->el, vec1->ctx->one, vec1->el,
+			vec1->ctx->one, vec2->el, vec1->size);
+	
+	isl_vec_free(vec2);
+	return vec1;
+error:
+	isl_vec_free(vec1);
+	isl_vec_free(vec2);
+	return NULL;
+}
+
+static int qsort_int_cmp(const void *p1, const void *p2)
+{
+	const isl_int *i1 = (const isl_int *) p1;
+	const isl_int *i2 = (const isl_int *) p2;
+
+	return isl_int_cmp(*i1, *i2);
+}
+
+__isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec)
+{
+	if (!vec)
+		return NULL;
+	
+	qsort(vec->el, vec->size, sizeof(*vec->el), &qsort_int_cmp);
+
+	return vec;
+}
+
+__isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec,
+	unsigned pos, unsigned n)
+{
+	if (n == 0)
+		return vec;
+	vec = isl_vec_cow(vec);
+	if (!vec)
+		return NULL;
+
+	if (pos + n > vec->size)
+		isl_die(vec->ctx, isl_error_invalid,
+			"range out of bounds", goto error);
+
+	if (pos + n != vec->size)
+		isl_seq_cpy(vec->el + pos, vec->el + pos + n,
+			    vec->size - pos - n);
+
+	vec->size -= n;
+	
+	return vec;
+error:
+	isl_vec_free(vec);
+	return NULL;
+}
+
+__isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec,
+	unsigned pos, unsigned n)
+{
+	isl_vec *ext = NULL;
+
+	if (n == 0)
+		return vec;
+	if (!vec)
+		return NULL;
+
+	if (pos > vec->size)
+		isl_die(vec->ctx, isl_error_invalid,
+			"position out of bounds", goto error);
+
+	ext =  isl_vec_alloc(vec->ctx, vec->size + n);
+	if (!ext)
+		goto error;
+
+	isl_seq_cpy(ext->el, vec->el, pos);
+	isl_seq_cpy(ext->el + pos + n, vec->el + pos, vec->size - pos);
+
+	isl_vec_free(vec);
+	return ext;
+error:
+	isl_vec_free(vec);
+	isl_vec_free(ext);
+	return NULL;
+}
+
+__isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec,
+	unsigned pos, unsigned n)
+{
+	vec = isl_vec_insert_els(vec, pos, n);
+	if (!vec)
+		return NULL;
+
+	isl_seq_clr(vec->el + pos, n);
+
+	return vec;
+}
+
+/* Move the "n" elements starting as "src_pos" of "vec"
+ * to "dst_pos".  The elements originally at "dst_pos" are moved
+ * up or down depending on whether "dst_pos" is smaller or greater
+ * than "src_pos".
+ */
+__isl_give isl_vec *isl_vec_move_els(__isl_take isl_vec *vec,
+	unsigned dst_pos, unsigned src_pos, unsigned n)
+{
+	isl_vec *res;
+
+	if (!vec)
+		return NULL;
+
+	if (src_pos + n > vec->size)
+		isl_die(vec->ctx, isl_error_invalid,
+			"source range out of bounds", return isl_vec_free(vec));
+	if (dst_pos + n > vec->size)
+		isl_die(vec->ctx, isl_error_invalid,
+			"destination range out of bounds",
+			return isl_vec_free(vec));
+
+	if (n == 0 || dst_pos == src_pos)
+		return vec;
+
+	res = isl_vec_alloc(vec->ctx, vec->size);
+	if (!res)
+		return isl_vec_free(vec);
+
+	if (dst_pos < src_pos) {
+		isl_seq_cpy(res->el, vec->el, dst_pos);
+		isl_seq_cpy(res->el + dst_pos, vec->el + src_pos, n);
+		isl_seq_cpy(res->el + dst_pos + n,
+			    vec->el + dst_pos, src_pos - dst_pos);
+		isl_seq_cpy(res->el + src_pos + n,
+			    vec->el + src_pos + n, res->size - src_pos - n);
+	} else {
+		isl_seq_cpy(res->el, vec->el, src_pos);
+		isl_seq_cpy(res->el + src_pos,
+			    vec->el + src_pos + n, dst_pos - src_pos);
+		isl_seq_cpy(res->el + dst_pos, vec->el + src_pos, n);
+		isl_seq_cpy(res->el + dst_pos + n,
+			    vec->el + dst_pos + n, res->size - dst_pos - n);
+	}
+
+	isl_vec_free(vec);
+	return res;
+}

Added: polly/trunk/lib/External/isl/isl_vec_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_vec_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_vec_private.h (added)
+++ polly/trunk/lib/External/isl/isl_vec_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,24 @@
+#ifndef ISL_VEC_PRIVATE_H
+#define ISL_VEC_PRIVATE_H
+
+#include <isl_blk.h>
+#include <isl/vec.h>
+
+struct isl_vec {
+	int ref;
+
+	struct isl_ctx *ctx;
+
+	unsigned size;
+	isl_int *el;
+
+	struct isl_blk block;
+};
+
+__isl_give isl_vec *isl_vec_cow(__isl_take isl_vec *vec);
+
+void isl_vec_lcm(struct isl_vec *vec, isl_int *lcm);
+int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v);
+__isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v);
+
+#endif

Added: polly/trunk/lib/External/isl/isl_version.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_version.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_version.c (added)
+++ polly/trunk/lib/External/isl/isl_version.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,14 @@
+#include "isl_config.h"
+#include "gitversion.h"
+
+const char *isl_version(void)
+{
+	return GIT_HEAD_ID
+#ifdef USE_GMP_FOR_MP
+	"-GMP"
+#endif
+#ifdef USE_IMATH_FOR_MP
+	"-IMath"
+#endif
+	"\n";
+}

Added: polly/trunk/lib/External/isl/isl_vertices.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_vertices.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_vertices.c (added)
+++ polly/trunk/lib/External/isl/isl_vertices.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1578 @@
+/*
+ * Copyright 2010      INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
+ * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
+ * 91893 Orsay, France 
+ */
+
+#include <isl_map_private.h>
+#include <isl_aff_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_tab.h>
+#include <isl_space_private.h>
+#include <isl_morph.h>
+#include <isl_vertices_private.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+#define SELECTED	1
+#define DESELECTED	-1
+#define UNSELECTED	0
+
+static __isl_give isl_vertices *compute_chambers(__isl_take isl_basic_set *bset,
+	__isl_take isl_vertices *vertices);
+
+__isl_give isl_vertices *isl_vertices_copy(__isl_keep isl_vertices *vertices)
+{
+	if (!vertices)
+		return NULL;
+
+	vertices->ref++;
+	return vertices;
+}
+
+void isl_vertices_free(__isl_take isl_vertices *vertices)
+{
+	int i;
+
+	if (!vertices)
+		return;
+
+	if (--vertices->ref > 0)
+		return;
+
+	for (i = 0; i < vertices->n_vertices; ++i) {
+		isl_basic_set_free(vertices->v[i].vertex);
+		isl_basic_set_free(vertices->v[i].dom);
+	}
+	free(vertices->v);
+
+	for (i = 0; i < vertices->n_chambers; ++i) {
+		free(vertices->c[i].vertices);
+		isl_basic_set_free(vertices->c[i].dom);
+	}
+	free(vertices->c);
+
+	isl_basic_set_free(vertices->bset);
+	free(vertices);
+}
+
+struct isl_vertex_list {
+	struct isl_vertex v;
+	struct isl_vertex_list *next;
+};
+
+static void free_vertex_list(struct isl_vertex_list *list)
+{
+	struct isl_vertex_list *next;
+
+	for (; list; list = next) {
+		next = list->next;
+		isl_basic_set_free(list->v.vertex);
+		isl_basic_set_free(list->v.dom);
+		free(list);
+	}
+}
+
+static __isl_give isl_vertices *vertices_from_list(__isl_keep isl_basic_set *bset,
+	int n_vertices, struct isl_vertex_list *list)
+{
+	int i;
+	struct isl_vertex_list *next;
+	isl_vertices *vertices;
+
+	vertices = isl_calloc_type(bset->ctx, isl_vertices);
+	if (!vertices)
+		goto error;
+	vertices->ref = 1;
+	vertices->bset = isl_basic_set_copy(bset);
+	vertices->v = isl_alloc_array(bset->ctx, struct isl_vertex, n_vertices);
+	if (n_vertices && !vertices->v)
+		goto error;
+	vertices->n_vertices = n_vertices;
+
+	for (i = 0; list; list = next, i++) {
+		next = list->next;
+		vertices->v[i] = list->v;
+		free(list);
+	}
+
+	return vertices;
+error:
+	isl_vertices_free(vertices);
+	free_vertex_list(list);
+	return NULL;
+}
+
+/* Prepend a vertex to the linked list "list" based on the equalities in "tab".
+ */
+static int add_vertex(struct isl_vertex_list **list,
+	__isl_keep isl_basic_set *bset, struct isl_tab *tab)
+{
+	unsigned nvar;
+	unsigned nparam;
+	struct isl_vertex_list *v = NULL;
+
+	if (isl_tab_detect_implicit_equalities(tab) < 0)
+		return -1;
+
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+	v = isl_calloc_type(tab->mat->ctx, struct isl_vertex_list);
+	if (!v)
+		goto error;
+
+	v->v.vertex = isl_basic_set_copy(bset);
+	v->v.vertex = isl_basic_set_cow(v->v.vertex);
+	v->v.vertex = isl_basic_set_update_from_tab(v->v.vertex, tab);
+	v->v.vertex = isl_basic_set_simplify(v->v.vertex);
+	v->v.vertex = isl_basic_set_finalize(v->v.vertex);
+	if (!v->v.vertex)
+		goto error;
+	isl_assert(bset->ctx, v->v.vertex->n_eq >= nvar, goto error);
+	v->v.dom = isl_basic_set_copy(v->v.vertex);
+	v->v.dom = isl_basic_set_params(v->v.dom);
+	if (!v->v.dom)
+		goto error;
+
+	v->next = *list;
+	*list = v;
+
+	return 0;
+error:
+	free_vertex_list(v);
+	return -1;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of an empty parametric polytope.
+ */
+static __isl_give isl_vertices *vertices_empty(__isl_keep isl_basic_set *bset)
+{
+	isl_vertices *vertices;
+	unsigned nparam;
+
+	if (!bset)
+		return NULL;
+
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+	vertices = isl_calloc_type(bset->ctx, isl_vertices);
+	if (!vertices)
+		return NULL;
+	vertices->bset = isl_basic_set_copy(bset);
+	vertices->ref = 1;
+
+	vertices->n_vertices = 0;
+	vertices->n_chambers = 0;
+
+	return vertices;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of the parametric polytope defined using the same constraints
+ * as "bset" in the 0D case.
+ * There is exactly one 0D vertex and a single chamber containing
+ * the vertex.
+ */
+static __isl_give isl_vertices *vertices_0D(__isl_keep isl_basic_set *bset)
+{
+	isl_vertices *vertices;
+	unsigned nparam;
+
+	if (!bset)
+		return NULL;
+
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+	vertices = isl_calloc_type(bset->ctx, isl_vertices);
+	if (!vertices)
+		return NULL;
+	vertices->ref = 1;
+	vertices->bset = isl_basic_set_copy(bset);
+
+	vertices->v = isl_calloc_array(bset->ctx, struct isl_vertex, 1);
+	if (!vertices->v)
+		goto error;
+	vertices->n_vertices = 1;
+	vertices->v[0].vertex = isl_basic_set_copy(bset);
+	vertices->v[0].dom = isl_basic_set_params(isl_basic_set_copy(bset));
+	if (!vertices->v[0].vertex || !vertices->v[0].dom)
+		goto error;
+
+	vertices->c = isl_calloc_array(bset->ctx, struct isl_chamber, 1);
+	if (!vertices->c)
+		goto error;
+	vertices->n_chambers = 1;
+	vertices->c[0].n_vertices = 1;
+	vertices->c[0].vertices = isl_calloc_array(bset->ctx, int, 1);
+	if (!vertices->c[0].vertices)
+		goto error;
+	vertices->c[0].dom = isl_basic_set_copy(vertices->v[0].dom);
+	if (!vertices->c[0].dom)
+		goto error;
+
+	return vertices;
+error:
+	isl_vertices_free(vertices);
+	return NULL;
+}
+
+static int isl_mat_rank(__isl_keep isl_mat *mat)
+{
+	int row, col;
+	isl_mat *H;
+
+	H = isl_mat_left_hermite(isl_mat_copy(mat), 0, NULL, NULL);
+	if (!H)
+		return -1;
+
+	for (col = 0; col < H->n_col; ++col) {
+		for (row = 0; row < H->n_row; ++row)
+			if (!isl_int_is_zero(H->row[row][col]))
+				break;
+		if (row == H->n_row)
+			break;
+	}
+
+	isl_mat_free(H);
+
+	return col;
+}
+
+/* Is the row pointed to by "f" linearly independent of the "n" first
+ * rows in "facets"?
+ */
+static int is_independent(__isl_keep isl_mat *facets, int n, isl_int *f)
+{
+	int rank;
+
+	if (isl_seq_first_non_zero(f, facets->n_col) < 0)
+		return 0;
+
+	isl_seq_cpy(facets->row[n], f, facets->n_col);
+	facets->n_row = n + 1;
+	rank = isl_mat_rank(facets);
+	if (rank < 0)
+		return -1;
+
+	return rank == n + 1;
+}
+
+/* Check whether we can select constraint "level", given the current selection
+ * reflected by facets in "tab", the rows of "facets" and the earlier
+ * "selected" elements of "selection".
+ *
+ * If the constraint is (strictly) redundant in the tableau, selecting it would
+ * result in an empty tableau, so it can't be selected.
+ * If the set variable part of the constraint is not linearly indepedent
+ * of the set variable parts of the already selected constraints,
+ * the constraint cannot be selected.
+ * If selecting the constraint results in an empty tableau, the constraint
+ * cannot be selected.
+ * Finally, if selecting the constraint results in some explicitly
+ * deselected constraints turning into equalities, then the corresponding
+ * vertices have already been generated, so the constraint cannot be selected.
+ */
+static int can_select(__isl_keep isl_basic_set *bset, int level,
+	struct isl_tab *tab, __isl_keep isl_mat *facets, int selected,
+	int *selection)
+{
+	int i;
+	int indep;
+	unsigned ovar;
+	struct isl_tab_undo *snap;
+
+	if (isl_tab_is_redundant(tab, level))
+		return 0;
+
+	ovar = isl_space_offset(bset->dim, isl_dim_set);
+
+	indep = is_independent(facets, selected, bset->ineq[level] + 1 + ovar);
+	if (indep < 0)
+		return -1;
+	if (!indep)
+		return 0;
+
+	snap = isl_tab_snap(tab);
+	if (isl_tab_select_facet(tab, level) < 0)
+		return -1;
+
+	if (tab->empty) {
+		if (isl_tab_rollback(tab, snap) < 0)
+			return -1;
+		return 0;
+	}
+
+	for (i = 0; i < level; ++i) {
+		int sgn;
+
+		if (selection[i] != DESELECTED)
+			continue;
+
+		if (isl_tab_is_equality(tab, i))
+			sgn = 0;
+		else if (isl_tab_is_redundant(tab, i))
+			sgn = 1;
+		else
+			sgn = isl_tab_sign_of_max(tab, i);
+		if (sgn < -1)
+			return -1;
+		if (sgn <= 0) {
+			if (isl_tab_rollback(tab, snap) < 0)
+				return -1;
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of a parametric polytope that is not full-dimensional.
+ *
+ * Simply map the parametric polytope to a lower dimensional space
+ * and map the resulting vertices back.
+ */
+static __isl_give isl_vertices *lower_dim_vertices(
+	__isl_keep isl_basic_set *bset)
+{
+	isl_morph *morph;
+	isl_vertices *vertices;
+
+	bset = isl_basic_set_copy(bset);
+	morph = isl_basic_set_full_compression(bset);
+	bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
+
+	vertices = isl_basic_set_compute_vertices(bset);
+	isl_basic_set_free(bset);
+
+	morph = isl_morph_inverse(morph);
+
+	vertices = isl_morph_vertices(morph, vertices);
+
+	return vertices;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of the parametric polytope defined using the same constraints
+ * as "bset".  "bset" is assumed to have no existentially quantified
+ * variables.
+ *
+ * The vertices themselves are computed in a fairly simplistic way.
+ * We simply run through all combinations of d constraints,
+ * with d the number of set variables, and check if those d constraints
+ * define a vertex.  To avoid the generation of duplicate vertices,
+ * which we may happen if a vertex is defined by more that d constraints,
+ * we make sure we only generate the vertex for the d constraints with
+ * smallest index.
+ *
+ * We set up a tableau and keep track of which facets have been
+ * selected.  The tableau is marked strict_redundant so that we can be
+ * sure that any constraint that is marked redundant (and that is not
+ * also marked zero) is not an equality.
+ * If a constraint is marked DESELECTED, it means the constraint was
+ * SELECTED before (in combination with the same selection of earlier
+ * constraints).  If such a deselected constraint turns out to be an
+ * equality, then any vertex that may still be found with the current
+ * selection has already been generated when the constraint was selected.
+ * A constraint is marked UNSELECTED when there is no way selecting
+ * the constraint could lead to a vertex (in combination with the current
+ * selection of earlier constraints).
+ *
+ * The set variable coefficients of the selected constraints are stored
+ * in the facets matrix.
+ */
+__isl_give isl_vertices *isl_basic_set_compute_vertices(
+	__isl_keep isl_basic_set *bset)
+{
+	struct isl_tab *tab;
+	int level;
+	int init;
+	unsigned nvar;
+	int *selection = NULL;
+	int selected;
+	struct isl_tab_undo **snap = NULL;
+	isl_mat *facets = NULL;
+	struct isl_vertex_list *list = NULL;
+	int n_vertices = 0;
+	isl_vertices *vertices;
+
+	if (!bset)
+		return NULL;
+
+	if (isl_basic_set_plain_is_empty(bset))
+		return vertices_empty(bset);
+
+	if (bset->n_eq != 0)
+		return lower_dim_vertices(bset);
+
+	isl_assert(bset->ctx, isl_basic_set_dim(bset, isl_dim_div) == 0,
+		return NULL);
+
+	if (isl_basic_set_dim(bset, isl_dim_set) == 0)
+		return vertices_0D(bset);
+
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+	bset = isl_basic_set_copy(bset);
+	bset = isl_basic_set_set_rational(bset);
+	if (!bset)
+		return NULL;
+
+	tab = isl_tab_from_basic_set(bset, 0);
+	if (!tab)
+		goto error;
+	tab->strict_redundant = 1;
+
+	if (tab->empty)	{
+		vertices = vertices_empty(bset);
+		isl_basic_set_free(bset);
+		isl_tab_free(tab);
+		return vertices;
+	}
+
+	selection = isl_alloc_array(bset->ctx, int, bset->n_ineq);
+	snap = isl_alloc_array(bset->ctx, struct isl_tab_undo *, bset->n_ineq);
+	facets = isl_mat_alloc(bset->ctx, nvar, nvar);
+	if ((bset->n_ineq && (!selection || !snap)) || !facets)
+		goto error;
+
+	level = 0;
+	init = 1;
+	selected = 0;
+
+	while (level >= 0) {
+		if (level >= bset->n_ineq ||
+		    (!init && selection[level] != SELECTED)) {
+			--level;
+			init = 0;
+			continue;
+		}
+		if (init) {
+			int ok;
+			snap[level] = isl_tab_snap(tab);
+			ok = can_select(bset, level, tab, facets, selected,
+					selection);
+			if (ok < 0)
+				goto error;
+			if (ok) {
+				selection[level] = SELECTED;
+				selected++;
+			} else
+				selection[level] = UNSELECTED;
+		} else {
+			selection[level] = DESELECTED;
+			selected--;
+			if (isl_tab_rollback(tab, snap[level]) < 0)
+				goto error;
+		}
+		if (selected == nvar) {
+			if (tab->n_dead == nvar) {
+				if (add_vertex(&list, bset, tab) < 0)
+					goto error;
+				n_vertices++;
+			}
+			init = 0;
+			continue;
+		}
+		++level;
+		init = 1;
+	}
+
+	isl_mat_free(facets);
+	free(selection);
+	free(snap);
+
+	isl_tab_free(tab);
+
+	vertices = vertices_from_list(bset, n_vertices, list);
+
+	vertices = compute_chambers(bset, vertices);
+
+	return vertices;
+error:
+	free_vertex_list(list);
+	isl_mat_free(facets);
+	free(selection);
+	free(snap);
+	isl_tab_free(tab);
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+struct isl_chamber_list {
+	struct isl_chamber c;
+	struct isl_chamber_list *next;
+};
+
+static void free_chamber_list(struct isl_chamber_list *list)
+{
+	struct isl_chamber_list *next;
+
+	for (; list; list = next) {
+		next = list->next;
+		isl_basic_set_free(list->c.dom);
+		free(list->c.vertices);
+		free(list);
+	}
+}
+
+/* Check whether the basic set "bset" is a superset of the basic set described
+ * by "tab", i.e., check whether all constraints of "bset" are redundant.
+ */
+static int bset_covers_tab(__isl_keep isl_basic_set *bset, struct isl_tab *tab)
+{
+	int i;
+
+	if (!bset || !tab)
+		return -1;
+
+	for (i = 0; i < bset->n_ineq; ++i) {
+		enum isl_ineq_type type = isl_tab_ineq_type(tab, bset->ineq[i]);
+		switch (type) {
+		case isl_ineq_error:		return -1;
+		case isl_ineq_redundant:	continue;
+		default:			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static __isl_give isl_vertices *vertices_add_chambers(
+	__isl_take isl_vertices *vertices, int n_chambers,
+	struct isl_chamber_list *list)
+{
+	int i;
+	isl_ctx *ctx;
+	struct isl_chamber_list *next;
+
+	ctx = isl_vertices_get_ctx(vertices);
+	vertices->c = isl_alloc_array(ctx, struct isl_chamber, n_chambers);
+	if (!vertices->c)
+		goto error;
+	vertices->n_chambers = n_chambers;
+
+	for (i = 0; list; list = next, i++) {
+		next = list->next;
+		vertices->c[i] = list->c;
+		free(list);
+	}
+
+	return vertices;
+error:
+	isl_vertices_free(vertices);
+	free_chamber_list(list);
+	return NULL;
+}
+
+/* Can "tab" be intersected with "bset" without resulting in
+ * a lower-dimensional set.
+ */
+static int can_intersect(struct isl_tab *tab, __isl_keep isl_basic_set *bset)
+{
+	int i;
+	struct isl_tab_undo *snap;
+
+	if (isl_tab_extend_cons(tab, bset->n_ineq) < 0)
+		return -1;
+
+	snap = isl_tab_snap(tab);
+
+	for (i = 0; i < bset->n_ineq; ++i) {
+		if (isl_tab_ineq_type(tab, bset->ineq[i]) == isl_ineq_redundant)
+			continue;
+		if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0)
+			return -1;
+	}
+
+	if (isl_tab_detect_implicit_equalities(tab) < 0)
+		return -1;
+	if (tab->n_dead) {
+		if (isl_tab_rollback(tab, snap) < 0)
+			return -1;
+		return 0;
+	}
+
+	return 1;
+}
+
+static int add_chamber(struct isl_chamber_list **list,
+	__isl_keep isl_vertices *vertices, struct isl_tab *tab, int *selection)
+{
+	int n_frozen;
+	int i, j;
+	int n_vertices = 0;
+	struct isl_tab_undo *snap;
+	struct isl_chamber_list *c = NULL;
+
+	for (i = 0; i < vertices->n_vertices; ++i)
+		if (selection[i])
+			n_vertices++;
+
+	snap = isl_tab_snap(tab);
+
+	for (i = 0; i < tab->n_con && tab->con[i].frozen; ++i)
+		tab->con[i].frozen = 0;
+	n_frozen = i;
+
+	if (isl_tab_detect_redundant(tab) < 0)
+		return -1;
+
+	c = isl_calloc_type(tab->mat->ctx, struct isl_chamber_list);
+	if (!c)
+		goto error;
+	c->c.vertices = isl_alloc_array(tab->mat->ctx, int, n_vertices);
+	if (n_vertices && !c->c.vertices)
+		goto error;
+	c->c.dom = isl_basic_set_from_basic_map(isl_basic_map_copy(tab->bmap));
+	c->c.dom = isl_basic_set_set_rational(c->c.dom);
+	c->c.dom = isl_basic_set_cow(c->c.dom);
+	c->c.dom = isl_basic_set_update_from_tab(c->c.dom, tab);
+	c->c.dom = isl_basic_set_simplify(c->c.dom);
+	c->c.dom = isl_basic_set_finalize(c->c.dom);
+	if (!c->c.dom)
+		goto error;
+
+	c->c.n_vertices = n_vertices;
+
+	for (i = 0, j = 0; i < vertices->n_vertices; ++i)
+		if (selection[i]) {
+			c->c.vertices[j] = i;
+			j++;
+		}
+
+	c->next = *list;
+	*list = c;
+
+	for (i = 0; i < n_frozen; ++i)
+		tab->con[i].frozen = 1;
+
+	if (isl_tab_rollback(tab, snap) < 0)
+		return -1;
+
+	return 0;
+error:
+	free_chamber_list(c);
+	return -1;
+}
+
+struct isl_facet_todo {
+	struct isl_tab *tab;	/* A tableau representation of the facet */
+	isl_basic_set *bset;    /* A normalized basic set representation */
+	isl_vec *constraint;	/* Constraint pointing to the other side */
+	struct isl_facet_todo *next;
+};
+
+static void free_todo(struct isl_facet_todo *todo)
+{
+	while (todo) {
+		struct isl_facet_todo *next = todo->next;
+
+		isl_tab_free(todo->tab);
+		isl_basic_set_free(todo->bset);
+		isl_vec_free(todo->constraint);
+		free(todo);
+
+		todo = next;
+	}
+}
+
+static struct isl_facet_todo *create_todo(struct isl_tab *tab, int con)
+{
+	int i;
+	int n_frozen;
+	struct isl_tab_undo *snap;
+	struct isl_facet_todo *todo;
+
+	snap = isl_tab_snap(tab);
+
+	for (i = 0; i < tab->n_con && tab->con[i].frozen; ++i)
+		tab->con[i].frozen = 0;
+	n_frozen = i;
+
+	if (isl_tab_detect_redundant(tab) < 0)
+		return NULL;
+
+	todo = isl_calloc_type(tab->mat->ctx, struct isl_facet_todo);
+	if (!todo)
+		return NULL;
+
+	todo->constraint = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+	if (!todo->constraint)
+		goto error;
+	isl_seq_neg(todo->constraint->el, tab->bmap->ineq[con], 1 + tab->n_var);
+	todo->bset = isl_basic_set_from_basic_map(isl_basic_map_copy(tab->bmap));
+	todo->bset = isl_basic_set_set_rational(todo->bset);
+	todo->bset = isl_basic_set_cow(todo->bset);
+	todo->bset = isl_basic_set_update_from_tab(todo->bset, tab);
+	todo->bset = isl_basic_set_simplify(todo->bset);
+	todo->bset = isl_basic_set_sort_constraints(todo->bset);
+	if (!todo->bset)
+		goto error;
+	ISL_F_SET(todo->bset, ISL_BASIC_SET_NORMALIZED);
+	todo->tab = isl_tab_dup(tab);
+	if (!todo->tab)
+		goto error;
+
+	for (i = 0; i < n_frozen; ++i)
+		tab->con[i].frozen = 1;
+
+	if (isl_tab_rollback(tab, snap) < 0)
+		goto error;
+
+	return todo;
+error:
+	free_todo(todo);
+	return NULL;
+}
+
+/* Create todo items for all interior facets of the chamber represented
+ * by "tab" and collect them in "next".
+ */
+static int init_todo(struct isl_facet_todo **next, struct isl_tab *tab)
+{
+	int i;
+	struct isl_tab_undo *snap;
+	struct isl_facet_todo *todo;
+
+	snap = isl_tab_snap(tab);
+
+	for (i = 0; i < tab->n_con; ++i) {
+		if (tab->con[i].frozen)
+			continue;
+		if (tab->con[i].is_redundant)
+			continue;
+
+		if (isl_tab_select_facet(tab, i) < 0)
+			return -1;
+
+		todo = create_todo(tab, i);
+		if (!todo)
+			return -1;
+
+		todo->next = *next;
+		*next = todo;
+
+		if (isl_tab_rollback(tab, snap) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* Does the linked list contain a todo item that is the opposite of "todo".
+ * If so, return 1 and remove the opposite todo item.
+ */
+static int has_opposite(struct isl_facet_todo *todo,
+	struct isl_facet_todo **list)
+{
+	for (; *list; list = &(*list)->next) {
+		int eq;
+		eq = isl_basic_set_plain_is_equal(todo->bset, (*list)->bset);
+		if (eq < 0)
+			return -1;
+		if (!eq)
+			continue;
+		todo = *list;
+		*list = todo->next;
+		todo->next = NULL;
+		free_todo(todo);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Create todo items for all interior facets of the chamber represented
+ * by "tab" and collect them in first->next, taking care to cancel
+ * opposite todo items.
+ */
+static int update_todo(struct isl_facet_todo *first, struct isl_tab *tab)
+{
+	int i;
+	struct isl_tab_undo *snap;
+	struct isl_facet_todo *todo;
+
+	snap = isl_tab_snap(tab);
+
+	for (i = 0; i < tab->n_con; ++i) {
+		int drop;
+
+		if (tab->con[i].frozen)
+			continue;
+		if (tab->con[i].is_redundant)
+			continue;
+
+		if (isl_tab_select_facet(tab, i) < 0)
+			return -1;
+
+		todo = create_todo(tab, i);
+		if (!todo)
+			return -1;
+
+		drop = has_opposite(todo, &first->next);
+		if (drop < 0)
+			return -1;
+
+		if (drop)
+			free_todo(todo);
+		else {
+			todo->next = first->next;
+			first->next = todo;
+		}
+
+		if (isl_tab_rollback(tab, snap) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+/* Compute the chamber decomposition of the parametric polytope respresented
+ * by "bset" given the parametric vertices and their activity domains.
+ *
+ * We are only interested in full-dimensional chambers.
+ * Each of these chambers is the intersection of the activity domains of
+ * one or more vertices and the union of all chambers is equal to the
+ * projection of the entire parametric polytope onto the parameter space.
+ *
+ * We first create an initial chamber by intersecting as many activity
+ * domains as possible without ending up with an empty or lower-dimensional
+ * set.  As a minor optimization, we only consider those activity domains
+ * that contain some arbitrary point.
+ *
+ * For each of interior facets of the chamber, we construct a todo item,
+ * containing the facet and a constraint containing the other side of the facet,
+ * for constructing the chamber on the other side.
+ * While their are any todo items left, we pick a todo item and
+ * create the required chamber by intersecting all activity domains
+ * that contain the facet and have a full-dimensional intersection with
+ * the other side of the facet.  For each of the interior facets, we
+ * again create todo items, taking care to cancel opposite todo items.
+ */
+static __isl_give isl_vertices *compute_chambers(__isl_take isl_basic_set *bset,
+	__isl_take isl_vertices *vertices)
+{
+	int i;
+	isl_ctx *ctx;
+	isl_vec *sample = NULL;
+	struct isl_tab *tab = NULL;
+	struct isl_tab_undo *snap;
+	int *selection = NULL;
+	int n_chambers = 0;
+	struct isl_chamber_list *list = NULL;
+	struct isl_facet_todo *todo = NULL;
+
+	if (!bset || !vertices)
+		goto error;
+
+	ctx = isl_vertices_get_ctx(vertices);
+	selection = isl_alloc_array(ctx, int, vertices->n_vertices);
+	if (vertices->n_vertices && !selection)
+		goto error;
+
+	bset = isl_basic_set_params(bset);
+
+	tab = isl_tab_from_basic_set(bset, 1);
+	if (!tab)
+		goto error;
+	for (i = 0; i < bset->n_ineq; ++i)
+		if (isl_tab_freeze_constraint(tab, i) < 0)
+			goto error;
+	isl_basic_set_free(bset);
+
+	snap = isl_tab_snap(tab);
+
+	sample = isl_tab_get_sample_value(tab);
+
+	for (i = 0; i < vertices->n_vertices; ++i) {
+		selection[i] = isl_basic_set_contains(vertices->v[i].dom, sample);
+		if (selection[i] < 0)
+			goto error;
+		if (!selection[i])
+			continue;
+		selection[i] = can_intersect(tab, vertices->v[i].dom);
+		if (selection[i] < 0)
+			goto error;
+	}
+
+	if (isl_tab_detect_redundant(tab) < 0)
+		goto error;
+
+	if (add_chamber(&list, vertices, tab, selection) < 0)
+		goto error;
+	n_chambers++;
+
+	if (init_todo(&todo, tab) < 0)
+		goto error;
+
+	while (todo) {
+		struct isl_facet_todo *next;
+
+		if (isl_tab_rollback(tab, snap) < 0)
+			goto error;
+
+		if (isl_tab_add_ineq(tab, todo->constraint->el) < 0)
+			goto error;
+		if (isl_tab_freeze_constraint(tab, tab->n_con - 1) < 0)
+			goto error;
+
+		for (i = 0; i < vertices->n_vertices; ++i) {
+			selection[i] = bset_covers_tab(vertices->v[i].dom,
+							todo->tab);
+			if (selection[i] < 0)
+				goto error;
+			if (!selection[i])
+				continue;
+			selection[i] = can_intersect(tab, vertices->v[i].dom);
+			if (selection[i] < 0)
+				goto error;
+		}
+
+		if (isl_tab_detect_redundant(tab) < 0)
+			goto error;
+
+		if (add_chamber(&list, vertices, tab, selection) < 0)
+			goto error;
+		n_chambers++;
+
+		if (update_todo(todo, tab) < 0)
+			goto error;
+
+		next = todo->next;
+		todo->next = NULL;
+		free_todo(todo);
+		todo = next;
+	}
+
+	isl_vec_free(sample);
+
+	isl_tab_free(tab);
+	free(selection);
+
+	vertices = vertices_add_chambers(vertices, n_chambers, list);
+
+	for (i = 0; vertices && i < vertices->n_vertices; ++i) {
+		isl_basic_set_free(vertices->v[i].dom);
+		vertices->v[i].dom = NULL;
+	}
+
+	return vertices;
+error:
+	free_chamber_list(list);
+	free_todo(todo);
+	isl_vec_free(sample);
+	isl_tab_free(tab);
+	free(selection);
+	if (!tab)
+		isl_basic_set_free(bset);
+	isl_vertices_free(vertices);
+	return NULL;
+}
+
+isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex)
+{
+	return vertex ? isl_vertices_get_ctx(vertex->vertices) : NULL;
+}
+
+int isl_vertex_get_id(__isl_keep isl_vertex *vertex)
+{
+	return vertex ? vertex->id : -1;
+}
+
+__isl_give isl_basic_set *isl_basic_set_set_integral(__isl_take isl_basic_set *bset)
+{
+	if (!bset)
+		return NULL;
+
+	if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
+		return bset;
+
+	bset = isl_basic_set_cow(bset);
+	if (!bset)
+		return NULL;
+
+	ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
+
+	return isl_basic_set_finalize(bset);
+}
+
+/* Return the activity domain of the vertex "vertex".
+ */
+__isl_give isl_basic_set *isl_vertex_get_domain(__isl_keep isl_vertex *vertex)
+{
+	struct isl_vertex *v;
+
+	if (!vertex)
+		return NULL;
+
+	v = &vertex->vertices->v[vertex->id];
+	if (!v->dom) {
+		v->dom = isl_basic_set_copy(v->vertex);
+		v->dom = isl_basic_set_params(v->dom);
+		v->dom = isl_basic_set_set_integral(v->dom);
+	}
+
+	return isl_basic_set_copy(v->dom);
+}
+
+/* Return a multiple quasi-affine expression describing the vertex "vertex"
+ * in terms of the parameters,
+ */
+__isl_give isl_multi_aff *isl_vertex_get_expr(__isl_keep isl_vertex *vertex)
+{
+	struct isl_vertex *v;
+	isl_basic_set *bset;
+
+	if (!vertex)
+		return NULL;
+
+	v = &vertex->vertices->v[vertex->id];
+
+	bset = isl_basic_set_copy(v->vertex);
+	return isl_multi_aff_from_basic_set_equalities(bset);
+}
+
+static __isl_give isl_vertex *isl_vertex_alloc(__isl_take isl_vertices *vertices,
+	int id)
+{
+	isl_ctx *ctx;
+	isl_vertex *vertex;
+
+	if (!vertices)
+		return NULL;
+
+	ctx = isl_vertices_get_ctx(vertices);
+	vertex = isl_alloc_type(ctx, isl_vertex);
+	if (!vertex)
+		goto error;
+
+	vertex->vertices = vertices;
+	vertex->id = id;
+
+	return vertex;
+error:
+	isl_vertices_free(vertices);
+	return NULL;
+}
+
+void isl_vertex_free(__isl_take isl_vertex *vertex)
+{
+	if (!vertex)
+		return;
+	isl_vertices_free(vertex->vertices);
+	free(vertex);
+}
+
+isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell)
+{
+	return cell ? cell->dom->ctx : NULL;
+}
+
+__isl_give isl_basic_set *isl_cell_get_domain(__isl_keep isl_cell *cell)
+{
+	return cell ? isl_basic_set_copy(cell->dom) : NULL;
+}
+
+static __isl_give isl_cell *isl_cell_alloc(__isl_take isl_vertices *vertices,
+	__isl_take isl_basic_set *dom, int id)
+{
+	int i;
+	isl_cell *cell = NULL;
+
+	if (!vertices || !dom)
+		goto error;
+
+	cell = isl_calloc_type(dom->ctx, isl_cell);
+	if (!cell)
+		goto error;
+
+	cell->n_vertices = vertices->c[id].n_vertices;
+	cell->ids = isl_alloc_array(dom->ctx, int, cell->n_vertices);
+	if (cell->n_vertices && !cell->ids)
+		goto error;
+	for (i = 0; i < cell->n_vertices; ++i)
+		cell->ids[i] = vertices->c[id].vertices[i];
+	cell->vertices = vertices;
+	cell->dom = dom;
+
+	return cell;
+error:
+	isl_cell_free(cell);
+	isl_vertices_free(vertices);
+	isl_basic_set_free(dom);
+	return NULL;
+}
+
+void isl_cell_free(__isl_take isl_cell *cell)
+{
+	if (!cell)
+		return;
+
+	isl_vertices_free(cell->vertices);
+	free(cell->ids);
+	isl_basic_set_free(cell->dom);
+	free(cell);
+}
+
+/* Create a tableau of the cone obtained by first homogenizing the given
+ * polytope and then making all inequalities strict by setting the
+ * constant term to -1.
+ */
+static struct isl_tab *tab_for_shifted_cone(__isl_keep isl_basic_set *bset)
+{
+	int i;
+	isl_vec *c = NULL;
+	struct isl_tab *tab;
+
+	if (!bset)
+		return NULL;
+	tab = isl_tab_alloc(bset->ctx, bset->n_ineq + 1,
+			    1 + isl_basic_set_total_dim(bset), 0);
+	if (!tab)
+		return NULL;
+	tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
+	if (ISL_F_ISSET(bset, ISL_BASIC_MAP_EMPTY)) {
+		if (isl_tab_mark_empty(tab) < 0)
+			goto error;
+		return tab;
+	}
+
+	c = isl_vec_alloc(bset->ctx, 1 + 1 + isl_basic_set_total_dim(bset));
+	if (!c)
+		goto error;
+
+	isl_int_set_si(c->el[0], 0);
+	for (i = 0; i < bset->n_eq; ++i) {
+		isl_seq_cpy(c->el + 1, bset->eq[i], c->size - 1);
+		if (isl_tab_add_eq(tab, c->el) < 0)
+			goto error;
+	}
+
+	isl_int_set_si(c->el[0], -1);
+	for (i = 0; i < bset->n_ineq; ++i) {
+		isl_seq_cpy(c->el + 1, bset->ineq[i], c->size - 1);
+		if (isl_tab_add_ineq(tab, c->el) < 0)
+			goto error;
+		if (tab->empty) {
+			isl_vec_free(c);
+			return tab;
+		}
+	}
+
+	isl_seq_clr(c->el + 1, c->size - 1);
+	isl_int_set_si(c->el[1], 1);
+	if (isl_tab_add_ineq(tab, c->el) < 0)
+		goto error;
+
+	isl_vec_free(c);
+	return tab;
+error:
+	isl_vec_free(c);
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Compute an interior point of "bset" by selecting an interior
+ * point in homogeneous space and projecting the point back down.
+ */
+static __isl_give isl_vec *isl_basic_set_interior_point(
+	__isl_keep isl_basic_set *bset)
+{
+	isl_vec *vec;
+	struct isl_tab *tab;
+
+	tab = tab_for_shifted_cone(bset);
+	vec = isl_tab_get_sample_value(tab);
+	isl_tab_free(tab);
+	if (!vec)
+		return NULL;
+
+	isl_seq_cpy(vec->el, vec->el + 1, vec->size - 1);
+	vec->size--;
+
+	return vec;
+}
+
+/* Call "fn" on all chambers of the parametric polytope with the shared
+ * facets of neighboring chambers only appearing in one of the chambers.
+ *
+ * We pick an interior point from one of the chambers and then make
+ * all constraints that do not satisfy this point strict.
+ */
+int isl_vertices_foreach_disjoint_cell(__isl_keep isl_vertices *vertices,
+	int (*fn)(__isl_take isl_cell *cell, void *user), void *user)
+{
+	int i, j;
+	isl_vec *vec;
+	isl_int v;
+	isl_cell *cell;
+
+	if (!vertices)
+		return -1;
+
+	if (vertices->n_chambers == 0)
+		return 0;
+
+	if (vertices->n_chambers == 1) {
+		isl_basic_set *dom = isl_basic_set_copy(vertices->c[0].dom);
+		dom = isl_basic_set_set_integral(dom);
+		cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, 0);
+		if (!cell)
+			return -1;
+		return fn(cell, user);
+	}
+
+	vec = isl_basic_set_interior_point(vertices->c[0].dom);
+	if (!vec)
+		return -1;
+
+	isl_int_init(v);
+
+	for (i = 0; i < vertices->n_chambers; ++i) {
+		int r;
+		isl_basic_set *dom = isl_basic_set_copy(vertices->c[i].dom);
+		dom = isl_basic_set_cow(dom);
+		if (!dom)
+			goto error;
+		for (j = 0; i && j < dom->n_ineq; ++j) {
+			isl_seq_inner_product(vec->el, dom->ineq[j], vec->size,
+						&v);
+			if (!isl_int_is_neg(v))
+				continue;
+			isl_int_sub_ui(dom->ineq[j][0], dom->ineq[j][0], 1);
+		}
+		dom = isl_basic_set_set_integral(dom);
+		cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, i);
+		if (!cell)
+			goto error;
+		r = fn(cell, user);
+		if (r < 0)
+			goto error;
+	}
+
+	isl_int_clear(v);
+	isl_vec_free(vec);
+
+	return 0;
+error:
+	isl_int_clear(v);
+	isl_vec_free(vec);
+	return -1;
+}
+
+int isl_vertices_foreach_cell(__isl_keep isl_vertices *vertices,
+	int (*fn)(__isl_take isl_cell *cell, void *user), void *user)
+{
+	int i;
+	isl_cell *cell;
+
+	if (!vertices)
+		return -1;
+
+	if (vertices->n_chambers == 0)
+		return 0;
+
+	for (i = 0; i < vertices->n_chambers; ++i) {
+		int r;
+		isl_basic_set *dom = isl_basic_set_copy(vertices->c[i].dom);
+
+		cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, i);
+		if (!cell)
+			return -1;
+
+		r = fn(cell, user);
+		if (r < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int isl_vertices_foreach_vertex(__isl_keep isl_vertices *vertices,
+	int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user)
+{
+	int i;
+	isl_vertex *vertex;
+
+	if (!vertices)
+		return -1;
+
+	if (vertices->n_vertices == 0)
+		return 0;
+
+	for (i = 0; i < vertices->n_vertices; ++i) {
+		int r;
+
+		vertex = isl_vertex_alloc(isl_vertices_copy(vertices), i);
+		if (!vertex)
+			return -1;
+
+		r = fn(vertex, user);
+		if (r < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int isl_cell_foreach_vertex(__isl_keep isl_cell *cell,
+	int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user)
+{
+	int i;
+	isl_vertex *vertex;
+
+	if (!cell)
+		return -1;
+
+	if (cell->n_vertices == 0)
+		return 0;
+
+	for (i = 0; i < cell->n_vertices; ++i) {
+		int r;
+
+		vertex = isl_vertex_alloc(isl_vertices_copy(cell->vertices),
+					  cell->ids[i]);
+		if (!vertex)
+			return -1;
+
+		r = fn(vertex, user);
+		if (r < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+isl_ctx *isl_vertices_get_ctx(__isl_keep isl_vertices *vertices)
+{
+	return vertices ? vertices->bset->ctx : NULL;
+}
+
+int isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices)
+{
+	return vertices ? vertices->n_vertices : -1;
+}
+
+__isl_give isl_vertices *isl_morph_vertices(__isl_take isl_morph *morph,
+	__isl_take isl_vertices *vertices)
+{
+	int i;
+	isl_morph *param_morph = NULL;
+
+	if (!morph || !vertices)
+		goto error;
+
+	isl_assert(vertices->bset->ctx, vertices->ref == 1, goto error);
+
+	param_morph = isl_morph_copy(morph);
+	param_morph = isl_morph_dom_params(param_morph);
+	param_morph = isl_morph_ran_params(param_morph);
+
+	for (i = 0; i < vertices->n_vertices; ++i) {
+		vertices->v[i].dom = isl_morph_basic_set(
+			isl_morph_copy(param_morph), vertices->v[i].dom);
+		vertices->v[i].vertex = isl_morph_basic_set(
+			isl_morph_copy(morph), vertices->v[i].vertex);
+		if (!vertices->v[i].vertex)
+			goto error;
+	}
+
+	for (i = 0; i < vertices->n_chambers; ++i) {
+		vertices->c[i].dom = isl_morph_basic_set(
+			isl_morph_copy(param_morph), vertices->c[i].dom);
+		if (!vertices->c[i].dom)
+			goto error;
+	}
+
+	isl_morph_free(param_morph);
+	isl_morph_free(morph);
+	return vertices;
+error:
+	isl_morph_free(param_morph);
+	isl_morph_free(morph);
+	isl_vertices_free(vertices);
+	return NULL;
+}
+
+/* Construct a simplex isl_cell spanned by the vertices with indices in
+ * "simplex_ids" and "other_ids" and call "fn" on this isl_cell.
+ */
+static int call_on_simplex(__isl_keep isl_cell *cell,
+	int *simplex_ids, int n_simplex, int *other_ids, int n_other,
+	int (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
+{
+	int i;
+	isl_ctx *ctx;
+	struct isl_cell *simplex;
+
+	ctx = isl_cell_get_ctx(cell);
+
+	simplex = isl_calloc_type(ctx, struct isl_cell);
+	if (!simplex)
+		return -1;
+	simplex->vertices = isl_vertices_copy(cell->vertices);
+	if (!simplex->vertices)
+		goto error;
+	simplex->dom = isl_basic_set_copy(cell->dom);
+	if (!simplex->dom)
+		goto error;
+	simplex->n_vertices = n_simplex + n_other;
+	simplex->ids = isl_alloc_array(ctx, int, simplex->n_vertices);
+	if (!simplex->ids)
+		goto error;
+
+	for (i = 0; i < n_simplex; ++i)
+		simplex->ids[i] = simplex_ids[i];
+	for (i = 0; i < n_other; ++i)
+		simplex->ids[n_simplex + i] = other_ids[i];
+
+	return fn(simplex, user);
+error:
+	isl_cell_free(simplex);
+	return -1;
+}
+
+/* Check whether the parametric vertex described by "vertex"
+ * lies on the facet corresponding to constraint "facet" of "bset".
+ * The isl_vec "v" is a temporary vector than can be used by this function.
+ *
+ * We eliminate the variables from the facet constraint using the
+ * equalities defining the vertex and check if the result is identical
+ * to zero.
+ *
+ * It would probably be better to keep track of the constraints defining
+ * a vertex during the vertex construction so that we could simply look
+ * it up here.
+ */
+static int vertex_on_facet(__isl_keep isl_basic_set *vertex,
+	__isl_keep isl_basic_set *bset, int facet, __isl_keep isl_vec *v)
+{
+	int i;
+	isl_int m;
+
+	isl_seq_cpy(v->el, bset->ineq[facet], v->size);
+
+	isl_int_init(m);
+	for (i = 0; i < vertex->n_eq; ++i) {
+		int k = isl_seq_last_non_zero(vertex->eq[i], v->size);
+		isl_seq_elim(v->el, vertex->eq[i], k, v->size, &m);
+	}
+	isl_int_clear(m);
+
+	return isl_seq_first_non_zero(v->el, v->size) == -1;
+}
+
+/* Triangulate the polytope spanned by the vertices with ids
+ * in "simplex_ids" and "other_ids" and call "fn" on each of
+ * the resulting simplices.
+ * If the input polytope is already a simplex, we simply call "fn".
+ * Otherwise, we pick a point from "other_ids" and add it to "simplex_ids".
+ * Then we consider each facet of "bset" that does not contain the point
+ * we just picked, but does contain some of the other points in "other_ids"
+ * and call ourselves recursively on the polytope spanned by the new
+ * "simplex_ids" and those points in "other_ids" that lie on the facet.
+ */
+static int triangulate(__isl_keep isl_cell *cell, __isl_keep isl_vec *v,
+	int *simplex_ids, int n_simplex, int *other_ids, int n_other,
+	int (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
+{
+	int i, j, k;
+	int d, nparam;
+	int *ids;
+	isl_ctx *ctx;
+	isl_basic_set *vertex;
+	isl_basic_set *bset;
+
+	ctx = isl_cell_get_ctx(cell);
+	d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set);
+	nparam = isl_basic_set_dim(cell->vertices->bset, isl_dim_param);
+
+	if (n_simplex + n_other == d + 1)
+		return call_on_simplex(cell, simplex_ids, n_simplex,
+				       other_ids, n_other, fn, user);
+
+	simplex_ids[n_simplex] = other_ids[0];
+	vertex = cell->vertices->v[other_ids[0]].vertex;
+	bset = cell->vertices->bset;
+
+	ids = isl_alloc_array(ctx, int, n_other - 1);
+	for (i = 0; i < bset->n_ineq; ++i) {
+		if (isl_seq_first_non_zero(bset->ineq[i] + 1 + nparam, d) == -1)
+			continue;
+		if (vertex_on_facet(vertex, bset, i, v))
+			continue;
+
+		for (j = 1, k = 0; j < n_other; ++j) {
+			isl_basic_set *ov;
+			ov = cell->vertices->v[other_ids[j]].vertex;
+			if (vertex_on_facet(ov, bset, i, v))
+				ids[k++] = other_ids[j];
+		}
+		if (k == 0)
+			continue;
+
+		if (triangulate(cell, v, simplex_ids, n_simplex + 1,
+				ids, k, fn, user) < 0)
+			goto error;
+	}
+	free(ids);
+
+	return 0;
+error:
+	free(ids);
+	return -1;
+}
+
+/* Triangulate the given cell and call "fn" on each of the resulting
+ * simplices.
+ */
+int isl_cell_foreach_simplex(__isl_take isl_cell *cell,
+	int (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
+{
+	int d, total;
+	int r;
+	isl_ctx *ctx;
+	isl_vec *v = NULL;
+	int *simplex_ids = NULL;
+
+	if (!cell)
+		return -1;
+
+	d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set);
+	total = isl_basic_set_total_dim(cell->vertices->bset);
+
+	if (cell->n_vertices == d + 1)
+		return fn(cell, user);
+
+	ctx = isl_cell_get_ctx(cell);
+	simplex_ids = isl_alloc_array(ctx, int, d + 1);
+	if (!simplex_ids)
+		goto error;
+
+	v = isl_vec_alloc(ctx, 1 + total);
+	if (!v)
+		goto error;
+
+	r = triangulate(cell, v, simplex_ids, 0,
+			cell->ids, cell->n_vertices, fn, user);
+
+	isl_vec_free(v);
+	free(simplex_ids);
+
+	isl_cell_free(cell);
+
+	return r;
+error:
+	free(simplex_ids);
+	isl_vec_free(v);
+	isl_cell_free(cell);
+	return -1;
+}

Added: polly/trunk/lib/External/isl/isl_vertices_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_vertices_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_vertices_private.h (added)
+++ polly/trunk/lib/External/isl/isl_vertices_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,64 @@
+#include <isl/set.h>
+#include <isl/vertices.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_morph;
+
+/* A parametric vertex.  "vertex" contains the actual description
+ * of the vertex as a singleton parametric set.  "dom" is the projection
+ * of "vertex" onto the parameter space, i.e., the activity domain
+ * of the vertex.
+ */
+struct isl_vertex {
+	isl_basic_set *dom;
+	isl_basic_set *vertex;
+};
+
+/* A chamber in the chamber decomposition.  The indices of the "n_vertices"
+ * active vertices are stored in "vertices".
+ */
+struct isl_chamber {
+	int n_vertices;
+	int *vertices;
+	isl_basic_set *dom;
+};
+
+struct isl_vertices {
+	int ref;
+
+	/* The rational basic set spanned by the vertices. */
+	isl_basic_set *bset;
+
+	int n_vertices;
+	struct isl_vertex *v;
+
+	int n_chambers;
+	struct isl_chamber *c;
+};
+
+struct isl_cell {
+	int n_vertices;
+	int *ids;
+	isl_vertices *vertices;
+	isl_basic_set *dom;
+};
+
+struct isl_external_vertex {
+	isl_vertices *vertices;
+	int id;
+};
+
+int isl_vertices_foreach_disjoint_cell(__isl_keep isl_vertices *vertices,
+	int (*fn)(__isl_take isl_cell *cell, void *user), void *user);
+int isl_cell_foreach_simplex(__isl_take isl_cell *cell,
+	int (*fn)(__isl_take isl_cell *simplex, void *user), void *user);
+
+__isl_give isl_vertices *isl_morph_vertices(__isl_take struct isl_morph *morph,
+	__isl_take isl_vertices *vertices);
+
+#if defined(__cplusplus)
+}
+#endif

Added: polly/trunk/lib/External/isl/m4/ax_c___attribute__.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_c___attribute__.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_c___attribute__.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_c___attribute__.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,66 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_c___attribute__.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_C___ATTRIBUTE__
+#
+# DESCRIPTION
+#
+#   Provides a test for the compiler support of __attribute__ extensions.
+#   Defines HAVE___ATTRIBUTE__ if it is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Stepan Kasal <skasal at redhat.com>
+#   Copyright (c) 2008 Christian Haggstrom
+#   Copyright (c) 2008 Ryan McCabe <ryan at numb.org>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 8
+
+AC_DEFUN([AX_C___ATTRIBUTE__], [
+  AC_CACHE_CHECK([for __attribute__], [ax_cv___attribute__],
+    [AC_COMPILE_IFELSE(
+      [AC_LANG_PROGRAM(
+	[[#include <stdlib.h>
+	  static void foo(void) __attribute__ ((unused));
+	  static void
+	  foo(void) {
+	      exit(1);
+	  }
+        ]], [])],
+      [ax_cv___attribute__=yes],
+      [ax_cv___attribute__=no]
+    )
+  ])
+  if test "$ax_cv___attribute__" = "yes"; then
+    AC_DEFINE([HAVE___ATTRIBUTE__], 1, [define if your compiler has __attribute__])
+  fi
+])

Added: polly/trunk/lib/External/isl/m4/ax_cc_maxopt.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_cc_maxopt.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_cc_maxopt.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_cc_maxopt.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,188 @@
+# ===========================================================================
+#          http://www.nongnu.org/autoconf-archive/ax_cc_maxopt.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CC_MAXOPT
+#
+# DESCRIPTION
+#
+#   Try to turn on "good" C optimization flags for various compilers and
+#   architectures, for some definition of "good". (In our case, good for
+#   FFTW and hopefully for other scientific codes. Modify as needed.)
+#
+#   The user can override the flags by setting the CFLAGS environment
+#   variable. The user can also specify --enable-portable-binary in order to
+#   disable any optimization flags that might result in a binary that only
+#   runs on the host architecture.
+#
+#   Note also that the flags assume that ANSI C aliasing rules are followed
+#   by the code (e.g. for gcc's -fstrict-aliasing), and that floating-point
+#   computations can be re-ordered as needed.
+#
+#   Requires macros: AX_CHECK_COMPILER_FLAGS, AX_COMPILER_VENDOR,
+#   AX_GCC_ARCHFLAG, AX_GCC_X86_CPUID.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2008 Matteo Frigo
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CC_MAXOPT],
+[
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AX_COMPILER_VENDOR])
+AC_REQUIRE([AC_CANONICAL_HOST])
+
+AC_ARG_ENABLE(portable-binary, [AC_HELP_STRING([--enable-portable-binary], [disable compiler optimizations that would produce unportable binaries])],
+	acx_maxopt_portable=$withval, acx_maxopt_portable=no)
+
+# Try to determine "good" native compiler flags if none specified via CFLAGS
+if test "$ac_test_CFLAGS" != "set"; then
+  CFLAGS=""
+  case $ax_cv_c_compiler_vendor in
+    dec) CFLAGS="-newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host"
+	 if test "x$acx_maxopt_portable" = xno; then
+           CFLAGS="$CFLAGS -arch host"
+         fi;;
+
+    sun) CFLAGS="-native -fast -xO5 -dalign"
+	 if test "x$acx_maxopt_portable" = xyes; then
+	   CFLAGS="$CFLAGS -xarch=generic"
+         fi;;
+
+    hp)  CFLAGS="+Oall +Optrs_ansi +DSnative"
+	 if test "x$acx_maxopt_portable" = xyes; then
+	   CFLAGS="$CFLAGS +DAportable"
+	 fi;;
+
+    ibm) if test "x$acx_maxopt_portable" = xno; then
+           xlc_opt="-qarch=auto -qtune=auto"
+	 else
+           xlc_opt="-qtune=auto"
+	 fi
+         AX_CHECK_COMPILER_FLAGS($xlc_opt,
+         	CFLAGS="-O3 -qansialias -w $xlc_opt",
+               [CFLAGS="-O3 -qansialias -w"
+                echo "******************************************************"
+                echo "*  You seem to have the IBM  C compiler.  It is      *"
+                echo "*  recommended for best performance that you use:    *"
+                echo "*                                                    *"
+                echo "*    CFLAGS=-O3 -qarch=xxx -qtune=xxx -qansialias -w *"
+                echo "*                      ^^^        ^^^                *"
+                echo "*  where xxx is pwr2, pwr3, 604, or whatever kind of *"
+                echo "*  CPU you have.  (Set the CFLAGS environment var.   *"
+                echo "*  and re-run configure.)  For more info, man cc.    *"
+                echo "******************************************************"])
+         ;;
+
+    intel) CFLAGS="-O3 -ansi_alias"
+	if test "x$acx_maxopt_portable" = xno; then
+	  icc_archflag=unknown
+	  icc_flags=""
+	  case $host_cpu in
+	    i686*|x86_64*)
+              # icc accepts gcc assembly syntax, so these should work:
+	      AX_GCC_X86_CPUID(0)
+              AX_GCC_X86_CPUID(1)
+	      case $ax_cv_gcc_x86_cpuid_0 in # see AX_GCC_ARCHFLAG
+                *:756e6547:*:*) # Intel
+                  case $ax_cv_gcc_x86_cpuid_1 in
+                    *6a?:*[[234]]:*:*|*6[[789b]]?:*:*:*) icc_flags="-xK";;
+                    *f3[[347]]:*:*:*|*f4[1347]:*:*:*) icc_flags="-xP -xN -xW -xK";;
+                    *f??:*:*:*) icc_flags="-xN -xW -xK";;
+                  esac ;;
+              esac ;;
+          esac
+          if test "x$icc_flags" != x; then
+            for flag in $icc_flags; do
+              AX_CHECK_COMPILER_FLAGS($flag, [icc_archflag=$flag; break])
+            done
+          fi
+          AC_MSG_CHECKING([for icc architecture flag])
+	  AC_MSG_RESULT($icc_archflag)
+          if test "x$icc_archflag" != xunknown; then
+            CFLAGS="$CFLAGS $icc_archflag"
+          fi
+        fi
+	;;
+
+    gnu)
+     # default optimization flags for gcc on all systems
+     CFLAGS="-O3 -fomit-frame-pointer"
+
+     # -malign-double for x86 systems
+     AX_CHECK_COMPILER_FLAGS(-malign-double, CFLAGS="$CFLAGS -malign-double")
+
+     #  -fstrict-aliasing for gcc-2.95+
+     AX_CHECK_COMPILER_FLAGS(-fstrict-aliasing,
+	CFLAGS="$CFLAGS -fstrict-aliasing")
+
+     # note that we enable "unsafe" fp optimization with other compilers, too
+     AX_CHECK_COMPILER_FLAGS(-ffast-math, CFLAGS="$CFLAGS -ffast-math")
+
+     AX_GCC_ARCHFLAG($acx_maxopt_portable)
+
+     # drop to -O1 for gcc 4.2
+     $CC --version |
+	sed -e 's/.* \(@<:@0-9@:>@@<:@0-9@:>@*\)\.\(@<:@0-9@:>@@<:@0-9@:>@*\).*/\1 \2/' |
+	(read major minor
+	    if test $major -eq 4 -a $minor -eq 2; then
+				exit 0
+	    fi
+	    exit 1
+	) && CFLAGS="-O1"
+     ;;
+  esac
+
+  if test -z "$CFLAGS"; then
+	echo ""
+	echo "********************************************************"
+        echo "* WARNING: Don't know the best CFLAGS for this system  *"
+        echo "* Use ./configure CFLAGS=... to specify your own flags *"
+	echo "* (otherwise, a default of CFLAGS=-O3 will be used)    *"
+	echo "********************************************************"
+	echo ""
+        CFLAGS="-O3"
+  fi
+
+  AX_CHECK_COMPILER_FLAGS($CFLAGS, [], [
+	echo ""
+        echo "********************************************************"
+        echo "* WARNING: The guessed CFLAGS don't seem to work with  *"
+        echo "* your compiler.                                       *"
+        echo "* Use ./configure CFLAGS=... to specify your own flags *"
+        echo "********************************************************"
+        echo ""
+        CFLAGS=""
+  ])
+
+fi
+])

Added: polly/trunk/lib/External/isl/m4/ax_cflags_warn_all.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_cflags_warn_all.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_cflags_warn_all.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_cflags_warn_all.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,149 @@
+# ===========================================================================
+#       http://www.nongnu.org/autoconf-archive/ax_cflags_warn_all.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
+#
+# DESCRIPTION
+#
+#   Try to find a compiler option that enables most reasonable warnings.
+#
+#   For the GNU CC compiler it will be -Wall (and -ansi -pedantic) The
+#   result is added to the shellvar being CFLAGS by default.
+#
+#   Currently this macro knows about GCC, Solaris C compiler, Digital Unix C
+#   compiler, C for AIX Compiler, HP-UX C compiler, IRIX C compiler, NEC
+#   SX-5 (Super-UX 10) C compiler, and Cray J90 (Unicos 10.0.0.8) C
+#   compiler.
+#
+#    - $1 shell-variable-to-add-to : CFLAGS
+#    - $2 add-value-if-not-found : nothing
+#    - $3 action-if-found : add value to shellvariable
+#    - $4 action-if-not-found : nothing
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic  % -Wall"       dnl   GCC
+   "-xstrconst % -v"          dnl Solaris C
+   "-std1      % -verbose -w0 -warnprotos" dnl Digital Unix
+   "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+   "-ansi -ansiE % -fullwarn" dnl IRIX
+   "+ESlit     % +w1"         dnl HP-UX C
+   "-Xc        % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+   "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+   #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+   AC_TRY_COMPILE([],[return 0;],
+   [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+     .ok|.ok,*) m4_ifvaln($3,$3) ;;
+   .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+        AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+                      m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+   *) m4_ifvaln($3,$3,[
+   if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+   then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+   else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+                      m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+   fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ax_cv_cxxflags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic  % -Wall"       dnl   GCC
+   "-xstrconst % -v"          dnl Solaris C
+   "-std1      % -verbose -w0 -warnprotos" dnl Digital Unix
+   "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+   "-ansi -ansiE % -fullwarn" dnl IRIX
+   "+ESlit     % +w1"         dnl HP-UX C
+   "-Xc        % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+   "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+   #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+   AC_TRY_COMPILE([],[return 0;],
+   [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+     .ok|.ok,*) m4_ifvaln($3,$3) ;;
+   .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+        AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+                      m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+   *) m4_ifvaln($3,$3,[
+   if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+   then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+   else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+                      m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+   fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl  implementation tactics:
+dnl   the for-argument contains a list of options. The first part of
+dnl   these does only exist to detect the compiler - usually it is
+dnl   a global option to enable -ansi or -extrawarnings. All other
+dnl   compilers will fail about it. That was needed since a lot of
+dnl   compilers will give false positives for some option-syntax
+dnl   like -Woption or -Xoption as they think of it is a pass-through
+dnl   to later compile stages or something. The "%" is used as a
+dnl   delimimiter. A non-option comment can be given after "%%" marks
+dnl   which will be shown but not added to the respective C/CXXFLAGS.

Added: polly/trunk/lib/External/isl/m4/ax_check_compiler_flags.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_check_compiler_flags.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_check_compiler_flags.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_check_compiler_flags.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,74 @@
+# ===========================================================================
+#     http://www.nongnu.org/autoconf-archive/ax_check_compiler_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE])
+#
+# DESCRIPTION
+#
+#   Check whether the given compiler FLAGS work with the current language's
+#   compiler, or whether they give an error. (Warnings, however, are
+#   ignored.)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2009 Matteo Frigo
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CHECK_COMPILER_FLAGS],
+[AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX
+AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1])
+dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname:
+AS_LITERAL_IF([$1],
+  [AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1]), [
+      ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
+      _AC_LANG_PREFIX[]FLAGS="$1"
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+        AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=yes,
+        AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=no)
+      _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])],
+  [ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
+   _AC_LANG_PREFIX[]FLAGS="$1"
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+     eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=yes,
+     eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=no)
+   _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])
+eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])
+AC_MSG_RESULT($ax_check_compiler_flags)
+if test "x$ax_check_compiler_flags" = xyes; then
+	m4_default([$2], :)
+else
+	m4_default([$3], :)
+fi
+])dnl AX_CHECK_COMPILER_FLAGS

Added: polly/trunk/lib/External/isl/m4/ax_compiler_vendor.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_compiler_vendor.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_compiler_vendor.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_compiler_vendor.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,63 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPILER_VENDOR
+#
+# DESCRIPTION
+#
+#   Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
+#   hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
+#   watcom, etc. The vendor is returned in the cache variable
+#   $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2008 Matteo Frigo
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 9
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[
+AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+ [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
+  # note: don't check for gcc first since some other compilers define __GNUC__
+  for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ clang:__clang__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
+    vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+#if !($vencpp)
+      thisisanerror;
+#endif
+])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
+  done
+ ])
+])

Added: polly/trunk/lib/External/isl/m4/ax_create_pkgconfig_info.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_create_pkgconfig_info.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_create_pkgconfig_info.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_create_pkgconfig_info.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,351 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_create_pkgconfig_info.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CREATE_PKGCONFIG_INFO [(outputfile, [requires [,libs [,summary [,cflags [, ldflags]]]]])]
+#
+# DESCRIPTION
+#
+#   Defaults:
+#
+#     $1 = $PACKAGE_NAME.pc
+#     $2 = (empty)
+#     $3 = $PACKAGE_LIBS $LIBS (as set at that point in configure.ac)
+#     $4 = $PACKAGE_SUMMARY (or $1 Library)
+#     $5 = $PACKAGE_CFLAGS (as set at the point in configure.ac)
+#     $6 = $PACKAGE_LDFLAGS (as set at the point in configure.ac)
+#
+#     PACKAGE_NAME defaults to $PACKAGE if not set.
+#     PACKAGE_LIBS defaults to -l$PACKAGE_NAME if not set.
+#
+#   The resulting file is called $PACKAGE.pc.in / $PACKAGE.pc
+#
+#   You will find this macro most useful in conjunction with
+#   ax_spec_defaults that can read good initializers from the .spec file. In
+#   consequencd, most of the generatable installable stuff can be made from
+#   information being updated in a single place for the whole project.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+#   Copyright (c) 2008 Sven Verdoolaege <skimo at kotnet.org>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 12
+
+AC_DEFUN([AX_CREATE_PKGCONFIG_INFO],[dnl
+AS_VAR_PUSHDEF([PKGCONFIG_suffix],[ax_create_pkgconfig_suffix])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libdir],[ax_create_pkgconfig_libdir])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libfile],[ax_create_pkgconfig_libfile])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libname],[ax_create_pkgconfig_libname])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_version],[ax_create_pkgconfig_version])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_description],[ax_create_pkgconfig_description])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_requires],[ax_create_pkgconfig_requires])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_pkglibs],[ax_create_pkgconfig_pkglibs])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libs],[ax_create_pkgconfig_libs])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_ldflags],[ax_create_pkgconfig_ldflags])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_cppflags],[ax_create_pkgconfig_cppflags])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_generate],[ax_create_pkgconfig_generate])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_src_libdir],[ax_create_pkgconfig_src_libdir])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_src_headers],[ax_create_pkgconfig_src_headers])dnl
+
+# we need the expanded forms...
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+AC_MSG_CHECKING(our pkgconfig libname)
+test ".$PKGCONFIG_libname" != "." || \
+PKGCONFIG_libname="ifelse($1,,${PACKAGE_NAME},`basename $1 .pc`)"
+test ".$PKGCONFIG_libname" != "." || \
+PKGCONFIG_libname="$PACKAGE"
+PKGCONFIG_libname=`eval echo "$PKGCONFIG_libname"`
+PKGCONFIG_libname=`eval echo "$PKGCONFIG_libname"`
+AC_MSG_RESULT($PKGCONFIG_libname)
+
+AC_MSG_CHECKING(our pkgconfig version)
+test ".$PKGCONFIG_version" != "." || \
+PKGCONFIG_version="${PACKAGE_VERSION}"
+test ".$PKGCONFIG_version" != "." || \
+PKGCONFIG_version="$VERSION"
+PKGCONFIG_version=`eval echo "$PKGCONFIG_version"`
+PKGCONFIG_version=`eval echo "$PKGCONFIG_version"`
+AC_MSG_RESULT($PKGCONFIG_version)
+
+AC_MSG_CHECKING(our pkgconfig_libdir)
+test ".$pkgconfig_libdir" = "." && \
+pkgconfig_libdir='${libdir}/pkgconfig'
+PKGCONFIG_libdir=`eval echo "$pkgconfig_libdir"`
+PKGCONFIG_libdir=`eval echo "$PKGCONFIG_libdir"`
+PKGCONFIG_libdir=`eval echo "$PKGCONFIG_libdir"`
+AC_MSG_RESULT($pkgconfig_libdir)
+test "$pkgconfig_libdir" != "$PKGCONFIG_libdir" && (
+AC_MSG_RESULT(expanded our pkgconfig_libdir... $PKGCONFIG_libdir))
+AC_SUBST([pkgconfig_libdir])
+
+AC_MSG_CHECKING(our pkgconfig_libfile)
+test ".$pkgconfig_libfile" != "." || \
+pkgconfig_libfile="ifelse($1,,$PKGCONFIG_libname.pc,`basename $1`)"
+PKGCONFIG_libfile=`eval echo "$pkgconfig_libfile"`
+PKGCONFIG_libfile=`eval echo "$PKGCONFIG_libfile"`
+AC_MSG_RESULT($pkgconfig_libfile)
+test "$pkgconfig_libfile" != "$PKGCONFIG_libfile" && (
+AC_MSG_RESULT(expanded our pkgconfig_libfile... $PKGCONFIG_libfile))
+AC_SUBST([pkgconfig_libfile])
+
+AC_MSG_CHECKING(our package / suffix)
+PKGCONFIG_suffix="$program_suffix"
+test ".$PKGCONFIG_suffix" != .NONE || PKGCONFIG_suffix=""
+AC_MSG_RESULT(${PACKAGE_NAME} / ${PKGCONFIG_suffix})
+
+AC_MSG_CHECKING(our pkgconfig description)
+PKGCONFIG_description="ifelse($4,,$PACKAGE_SUMMARY,$4)"
+test ".$PKGCONFIG_description" != "." || \
+PKGCONFIG_description="$PKGCONFIG_libname Library"
+PKGCONFIG_description=`eval echo "$PKGCONFIG_description"`
+PKGCONFIG_description=`eval echo "$PKGCONFIG_description"`
+AC_MSG_RESULT($PKGCONFIG_description)
+
+AC_MSG_CHECKING(our pkgconfig requires)
+PKGCONFIG_requires="ifelse($2,,$PACKAGE_REQUIRES,$2)"
+PKGCONFIG_requires=`eval echo "$PKGCONFIG_requires"`
+PKGCONFIG_requires=`eval echo "$PKGCONFIG_requires"`
+AC_MSG_RESULT($PKGCONFIG_requires)
+
+AC_MSG_CHECKING(our pkgconfig ext libs)
+PKGCONFIG_pkglibs="$PACKAGE_LIBS"
+test ".$PKGCONFIG_pkglibs" != "." || PKGCONFIG_pkglibs="-l$PKGCONFIG_libname"
+PKGCONFIG_libs="ifelse($3,,$PKGCONFIG_pkglibs $LIBS,$3)"
+PKGCONFIG_libs=`eval echo "$PKGCONFIG_libs"`
+PKGCONFIG_libs=`eval echo "$PKGCONFIG_libs"`
+AC_MSG_RESULT($PKGCONFIG_libs)
+
+AC_MSG_CHECKING(our pkgconfig cppflags)
+PKGCONFIG_cppflags="ifelse($5,,$PACKAGE_CFLAGS,$5)"
+PKGCONFIG_cppflags=`eval echo "$PKGCONFIG_cppflags"`
+PKGCONFIG_cppflags=`eval echo "$PKGCONFIG_cppflags"`
+AC_MSG_RESULT($PKGCONFIG_cppflags)
+
+AC_MSG_CHECKING(our pkgconfig ldflags)
+PKGCONFIG_ldflags="ifelse($6,,$PACKAGE_LDFLAGS,$5)"
+PKGCONFIG_ldflags=`eval echo "$PKGCONFIG_ldflags"`
+PKGCONFIG_ldflags=`eval echo "$PKGCONFIG_ldflags"`
+AC_MSG_RESULT($PKGCONFIG_ldflags)
+
+test ".$PKGCONFIG_generate" != "." || \
+PKGCONFIG_generate="ifelse($1,,$PKGCONFIG_libname.pc,$1)"
+PKGCONFIG_generate=`eval echo "$PKGCONFIG_generate"`
+PKGCONFIG_generate=`eval echo "$PKGCONFIG_generate"`
+test "$pkgconfig_libfile" != "$PKGCONFIG_generate" && (
+AC_MSG_RESULT(generate the pkgconfig later... $PKGCONFIG_generate))
+
+if test ".$PKGCONFIG_src_libdir" = "." ; then
+PKGCONFIG_src_libdir=`pwd`
+PKGCONFIG_src_libdir=`AS_DIRNAME("$PKGCONFIG_src_libdir/$PKGCONFIG_generate")`
+test ! -d $PKGCONFIG_src_libdir/src || \
+PKGCONFIG_src_libdir="$PKGCONFIG_src_libdir/src"
+case ".$objdir" in
+*libs) PKGCONFIG_src_libdir="$PKGCONFIG_src_libdir/$objdir" ;; esac
+AC_MSG_RESULT(noninstalled pkgconfig -L $PKGCONFIG_src_libdir)
+fi
+
+if test ".$PKGCONFIG_src_headers" = "." ; then
+PKGCONFIG_src_headers=`pwd`
+v="$ac_top_srcdir" ;
+test ".$v" != "." || v="$ax_spec_dir"
+test ".$v" != "." || v="$srcdir"
+case "$v" in /*) PKGCONFIG_src_headers="" ;; esac
+PKGCONFIG_src_headers=`AS_DIRNAME("$PKGCONFIG_src_headers/$v/x")`
+test ! -d $PKGCONFIG_src_headers/incl[]ude || \
+PKGCONFIG_src_headers="$PKGCONFIG_src_headers/incl[]ude"
+AC_MSG_RESULT(noninstalled pkgconfig -I $PKGCONFIG_src_headers)
+fi
+
+
+dnl AC_CONFIG_COMMANDS crap disallows to use $PKGCONFIG_libfile here...
+AC_CONFIG_COMMANDS([$ax_create_pkgconfig_generate],[
+pkgconfig_generate="$ax_create_pkgconfig_generate"
+if test ! -f "$pkgconfig_generate.in"
+then generate="true"
+elif grep ' generated by configure ' $pkgconfig_generate.in >/dev/null
+then generate="true"
+else generate="false";
+fi
+if $generate ; then
+AC_MSG_NOTICE(creating $pkgconfig_generate.in)
+cat > $pkgconfig_generate.in <<AXEOF
+# generated by configure / remove this line to disable regeneration
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+includedir=@includedir@
+package=@PACKAGE@
+suffix=@suffix@
+
+Name: @PACKAGE_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @PACKAGE_VERSION@
+Requires: @PACKAGE_REQUIRES@
+Libs: -L\${libdir} @LDFLAGS@ @LIBS@
+Cflags: -I\${includedir} @CPPFLAGS@
+AXEOF
+fi # DONE generate $pkgconfig_generate.in
+AC_MSG_NOTICE(creating $pkgconfig_generate)
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_libdir}|
+s|@datarootdir@|${pkgconfig_datarootdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_includedir}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed  $pkgconfig_generate.in > $pkgconfig_generate
+if test ! -s $pkgconfig_generate ; then
+    AC_MSG_ERROR([$pkgconfig_generate is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_generate
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.pc/'`
+AC_MSG_NOTICE(creating $pkgconfig_uninstalled)
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_src_libdir}|
+s|@datarootdir@|${pkgconfig_datarootdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_src_headers}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+    AC_MSG_ERROR([$pkgconfig_uninstalled is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+           pkgconfig_requires_add=`echo ${pkgconfig_requires}`
+if test ".$pkgconfig_requires_add" != "." ; then
+           pkgconfig_requires_add="pkg-config $pkgconfig_requires_add"
+    else   pkgconfig_requires_add=":" ; fi
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.sh/'`
+AC_MSG_NOTICE(creating $pkgconfig_uninstalled)
+cat >conftest.sed <<AXEOF
+s|@prefix@|\"${pkgconfig_prefix}\"|
+s|@exec_prefix@|\"${pkgconfig_execprefix}\"|
+s|@bindir@|\"${pkgconfig_bindir}\"|
+s|@libdir@|\"${pkgconfig_src_libdir}\"|
+s|@datarootdir@|\"${pkgconfig_datarootdir}\"|
+s|@datadir@|\"${pkgconfig_datadir}\"|
+s|@sysconfdir@|\"${pkgconfig_sysconfdir}\"|
+s|@includedir@|\"${pkgconfig_src_headers}\"|
+s|@suffix@|\"${pkgconfig_suffix}\"|
+s|@PACKAGE@|\"${pkgconfig_package}\"|
+s|@PACKAGE_NAME@|\"${pkgconfig_libname}\"|
+s|@PACKAGE_DESCRIPTION@|\"${pkgconfig_description}\"|
+s|@PACKAGE_VERSION@|\"${pkgconfig_version}\"|
+s|@PACKAGE_REQUIRES@|\"${pkgconfig_requires}\"|
+s|@LIBS@|\"${pkgconfig_libs}\"|
+s|@LDFLAGS@|\"${pkgconfig_ldflags}\"|
+s|@CPPFLAGS@|\"${pkgconfig_cppflags}\"|
+s>Name:>for option\\; do case \"\$option\" in --list-all|--name) echo >
+s>Description: *>\\;\\; --help) pkg-config --help \\; echo Buildscript Of >
+s>Version: *>\\;\\; --modversion|--version) echo >
+s>Requires:>\\;\\; --requires) echo $pkgconfig_requires_add>
+s>Libs: *>\\;\\; --libs) echo >
+s>Cflags: *>\\;\\; --cflags) echo >
+/--libs)/a\\
+       $pkgconfig_requires_add
+/--cflags)/a\\
+       $pkgconfig_requires_add\\
+;; --variable=*) eval echo '\$'\`echo \$option | sed -e 's/.*=//'\`\\
+;; --uninstalled) exit 0 \\
+;; *) ;; esac done
+AXEOF
+sed -f conftest.sed  $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+    AC_MSG_ERROR([$pkgconfig_uninstalled is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+],[
+dnl AC_CONFIG_COMMANDS crap, the AS_PUSHVAR defines are invalid here...
+ax_create_pkgconfig_generate="$ax_create_pkgconfig_generate"
+pkgconfig_prefix='$prefix'
+pkgconfig_execprefix='$exec_prefix'
+pkgconfig_bindir='$bindir'
+pkgconfig_libdir='$libdir'
+pkgconfig_includedir='$includedir'
+pkgconfig_datarootdir='$datarootdir'
+pkgconfig_datadir='$datadir'
+pkgconfig_sysconfdir='$sysconfdir'
+pkgconfig_suffix='$ax_create_pkgconfig_suffix'
+pkgconfig_package='$PACKAGE_NAME'
+pkgconfig_libname='$ax_create_pkgconfig_libname'
+pkgconfig_description='$ax_create_pkgconfig_description'
+pkgconfig_version='$ax_create_pkgconfig_version'
+pkgconfig_requires='$ax_create_pkgconfig_requires'
+pkgconfig_libs='$ax_create_pkgconfig_libs'
+pkgconfig_ldflags='$ax_create_pkgconfig_ldflags'
+pkgconfig_cppflags='$ax_create_pkgconfig_cppflags'
+pkgconfig_src_libdir='$ax_create_pkgconfig_src_libdir'
+pkgconfig_src_headers='$ax_create_pkgconfig_src_headers'
+])dnl
+AS_VAR_POPDEF([PKGCONFIG_suffix])dnl
+AS_VAR_POPDEF([PKGCONFIG_libdir])dnl
+AS_VAR_POPDEF([PKGCONFIG_libfile])dnl
+AS_VAR_POPDEF([PKGCONFIG_libname])dnl
+AS_VAR_POPDEF([PKGCONFIG_version])dnl
+AS_VAR_POPDEF([PKGCONFIG_description])dnl
+AS_VAR_POPDEF([PKGCONFIG_requires])dnl
+AS_VAR_POPDEF([PKGCONFIG_pkglibs])dnl
+AS_VAR_POPDEF([PKGCONFIG_libs])dnl
+AS_VAR_POPDEF([PKGCONFIG_ldflags])dnl
+AS_VAR_POPDEF([PKGCONFIG_cppflags])dnl
+AS_VAR_POPDEF([PKGCONFIG_generate])dnl
+AS_VAR_POPDEF([PKGCONFIG_src_libdir])dnl
+AS_VAR_POPDEF([PKGCONFIG_src_headers])dnl
+])

Added: polly/trunk/lib/External/isl/m4/ax_create_stdint_h.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_create_stdint_h.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_create_stdint_h.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_create_stdint_h.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,739 @@
+# ===========================================================================
+#           http://autoconf-archive.cryp.to/ax_create_stdint_h.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])]
+#
+# DESCRIPTION
+#
+#   the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
+#   existence of an include file <stdint.h> that defines a set of typedefs,
+#   especially uint8_t,int32_t,uintptr_t. Many older installations will not
+#   provide this file, but some will have the very same definitions in
+#   <inttypes.h>. In other enviroments we can use the inet-types in
+#   <sys/types.h> which would define the typedefs int8_t and u_int8_t
+#   respectivly.
+#
+#   This macros will create a local "_stdint.h" or the headerfile given as
+#   an argument. In many cases that file will just "#include <stdint.h>" or
+#   "#include <inttypes.h>", while in other environments it will provide the
+#   set of basic 'stdint's definitions/typedefs:
+#
+#     int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
+#     int_least32_t.. int_fast32_t.. intmax_t
+#
+#   which may or may not rely on the definitions of other files, or using
+#   the AC_CHECK_SIZEOF macro to determine the actual sizeof each type.
+#
+#   if your header files require the stdint-types you will want to create an
+#   installable file mylib-int.h that all your other installable header may
+#   include. So if you have a library package named "mylib", just use
+#
+#        AX_CREATE_STDINT_H(mylib-int.h)
+#
+#   in configure.ac and go to install that very header file in Makefile.am
+#   along with the other headers (mylib.h) - and the mylib-specific headers
+#   can simply use "#include <mylib-int.h>" to obtain the stdint-types.
+#
+#   Remember, if the system already had a valid <stdint.h>, the generated
+#   file will include it directly. No need for fuzzy HAVE_STDINT_H things...
+#   (oops, GCC 4.2.x has deliberatly disabled its stdint.h for non-c99
+#   compilation and the c99-mode is not the default. Therefore this macro
+#   will not use the compiler's stdint.h - please complain to the GCC
+#   developers).
+#
+# LAST MODIFICATION
+#
+#   2008-04-12
+#
+# COPYLEFT
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Macro Archive. When you make and
+#   distribute a modified version of the Autoconf Macro, you may extend this
+#   special exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CHECK_DATA_MODEL],[
+   AC_CHECK_SIZEOF(char)
+   AC_CHECK_SIZEOF(short)
+   AC_CHECK_SIZEOF(int)
+   AC_CHECK_SIZEOF(long)
+   AC_CHECK_SIZEOF(void*)
+   ac_cv_char_data_model=""
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+   ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model=""
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+   ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+   AC_MSG_CHECKING([data model])
+   case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+    122/242)     ac_cv_data_model="IP16"  ; n="standard 16bit machine" ;;
+    122/244)     ac_cv_data_model="LP32"  ; n="standard 32bit machine" ;;
+    122/*)       ac_cv_data_model="i16"   ; n="unusual int16 model" ;;
+    124/444)     ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+    124/488)     ac_cv_data_model="LP64"  ; n="standard 64bit unixish" ;;
+    124/448)     ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+    124/*)       ac_cv_data_model="i32"   ; n="unusual int32 model" ;;
+    128/888)     ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+    128/*)       ac_cv_data_model="i64"   ; n="unusual int64 model" ;;
+    222/*2)      ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+    333/*3)      ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+    444/*4)      ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+    666/*6)      ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+    888/*8)      ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+    222/*|333/*|444/*|666/*|888/*) :
+                 ac_cv_data_model="iDSP"  ; n="unusual dsptype" ;;
+     *)          ac_cv_data_model="none"  ; n="very unusual model" ;;
+   esac
+   AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
+])
+
+dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
+AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
+AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
+ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h])
+  do
+   unset ac_cv_type_uintptr_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$2],[$2]) break
+  done
+  AC_MSG_CHECKING([for stdint uintptr_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
+AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
+ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h])
+  do
+   unset ac_cv_type_uint32_t
+   unset ac_cv_type_uint64_t
+   AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$2],[$2]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint uint32_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
+AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
+ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
+  AC_MSG_RESULT([(..)])
+  for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
+   unset ac_cv_type_u_int32_t
+   unset ac_cv_type_u_int64_t
+   AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
+   AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
+   m4_ifvaln([$2],[$2]) break
+   break;
+  done
+  AC_MSG_CHECKING([for stdint u_int32_t])
+ ])
+])
+
+AC_DEFUN([AX_CREATE_STDINT_H],
+[# ------ AX CREATE STDINT H -------------------------------------
+AC_MSG_CHECKING([for stdint types])
+ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)`
+# try to shortcircuit - if the default include path of the compiler
+# can find a "stdint.h" header then we assume that all compilers can.
+AC_CACHE_VAL([ac_cv_header_stdint_t],[
+old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS=""
+old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS=""
+old_CFLAGS="$CFLAGS"     ; CFLAGS=""
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[ac_cv_stdint_result="(assuming C99 compatible system)"
+ ac_cv_header_stdint_t="stdint.h"; ],
+[ac_cv_header_stdint_t=""])
+if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then
+CFLAGS="-std=c99"
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)])
+fi
+CXXFLAGS="$old_CXXFLAGS"
+CPPFLAGS="$old_CPPFLAGS"
+CFLAGS="$old_CFLAGS" ])
+
+v="... $ac_cv_header_stdint_h"
+if test "$ac_stdint_h" = "stdint.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)])
+elif test "$ac_stdint_h" = "inttypes.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)])
+elif test "_$ac_cv_header_stdint_t" = "_" ; then
+ AC_MSG_RESULT([(putting them into $ac_stdint_h)$v])
+else
+ ac_cv_header_stdint="$ac_cv_header_stdint_t"
+ AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)])
+fi
+
+if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
+
+dnl .....intro message done, now do a few system checks.....
+dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type,
+dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW
+dnl instead that is triggered with 3 or more arguments (see types.m4)
+
+inttype_headers=`echo $2 | sed -e 's/,/ /g'`
+
+ac_cv_stdint_result="(no helpful system typedefs seen)"
+AX_CHECK_HEADER_STDINT_X(dnl
+   stdint.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+AX_CHECK_HEADER_STDINT_O(dnl,
+   inttypes.h sys/inttypes.h stdint.h $inttype_headers,
+   ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
+fi
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+if test "_$ac_cv_header_stdint_o" = "_" ; then
+AX_CHECK_HEADER_STDINT_U(dnl,
+   sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
+   ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
+fi fi
+
+dnl if there was no good C99 header file, do some typedef checks...
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+   AC_MSG_CHECKING([for stdint datatype model])
+   AC_MSG_RESULT([(..)])
+   AX_CHECK_DATA_MODEL
+fi
+
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_x"
+elif  test "_$ac_cv_header_stdint_o" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_o"
+elif  test "_$ac_cv_header_stdint_u" != "_" ; then
+   ac_cv_header_stdint="$ac_cv_header_stdint_u"
+else
+   ac_cv_header_stdint="stddef.h"
+fi
+
+AC_MSG_CHECKING([for extra inttypes in chosen header])
+AC_MSG_RESULT([($ac_cv_header_stdint)])
+dnl see if int_least and int_fast types are present in _this_ header.
+unset ac_cv_type_int_least32_t
+unset ac_cv_type_int_fast32_t
+AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>])
+AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>])
+AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>])
+
+fi # shortcircut to system "stdint.h"
+# ------------------ PREPARE VARIABLES ------------------------------
+if test "$GCC" = "yes" ; then
+ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1`
+else
+ac_cv_stdint_message="using $CC"
+fi
+
+AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
+$ac_cv_stdint_result])
+
+dnl -----------------------------------------------------------------
+# ----------------- DONE inttypes.h checks START header -------------
+AC_CONFIG_COMMANDS([$ac_stdint_h],[
+AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
+ac_stdint=$tmp/_stdint.h
+
+echo "#ifndef" $_ac_stdint_h >$ac_stdint
+echo "#define" $_ac_stdint_h "1" >>$ac_stdint
+echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint
+echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
+echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_t" != "_" ; then
+echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
+
+cat >>$ac_stdint <<STDINT_EOF
+
+/* ................... shortcircuit part ........................... */
+
+#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H
+#include <stdint.h>
+#else
+#include <stddef.h>
+
+/* .................... configured part ............................ */
+
+STDINT_EOF
+
+echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+  ac_header="$ac_cv_header_stdint_x"
+  echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint
+fi
+
+echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint
+if  test "_$ac_cv_header_stdint_o" != "_" ; then
+  ac_header="$ac_cv_header_stdint_o"
+  echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint
+fi
+
+echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint
+if  test "_$ac_cv_header_stdint_u" != "_" ; then
+  ac_header="$ac_cv_header_stdint_u"
+  echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+  echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint
+fi
+
+echo "" >>$ac_stdint
+
+if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then
+  echo "#include <$ac_header>" >>$ac_stdint
+  echo "" >>$ac_stdint
+fi fi
+
+echo "/* which 64bit typedef has been found */" >>$ac_stdint
+if test "$ac_cv_type_uint64_t" = "yes" ; then
+echo "#define   _STDINT_HAVE_UINT64_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint
+fi
+if test "$ac_cv_type_u_int64_t" = "yes" ; then
+echo "#define   _STDINT_HAVE_U_INT64_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* which type model has been detected */" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define   _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define   _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
+else
+echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
+echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* whether int_least types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_least32_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INT_LEAST32_T" "1"  >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint
+fi
+echo "/* whether int_fast types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_fast32_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint
+fi
+echo "/* whether intmax_t type was detected */" >>$ac_stdint
+if test "$ac_cv_type_intmax_t" = "yes"; then
+echo "#define   _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+  cat >>$ac_stdint <<STDINT_EOF
+/* .................... detections part ............................ */
+
+/* whether we need to define bitspecific types from compiler base types */
+#ifndef _STDINT_HEADER_INTPTR
+#ifndef _STDINT_HEADER_UINT32
+#ifndef _STDINT_HEADER_U_INT32
+#define _STDINT_NEED_INT_MODEL_T
+#else
+#define _STDINT_HAVE_U_INT_TYPES
+#endif
+#endif
+#endif
+
+#ifdef _STDINT_HAVE_U_INT_TYPES
+#undef _STDINT_NEED_INT_MODEL_T
+#endif
+
+#ifdef  _STDINT_CHAR_MODEL
+#if     _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124
+#ifndef _STDINT_BYTE_MODEL
+#define _STDINT_BYTE_MODEL 12
+#endif
+#endif
+#endif
+
+#ifndef _STDINT_HAVE_INT_LEAST32_T
+#define _STDINT_NEED_INT_LEAST_T
+#endif
+
+#ifndef _STDINT_HAVE_INT_FAST32_T
+#define _STDINT_NEED_INT_FAST_T
+#endif
+
+#ifndef _STDINT_HEADER_INTPTR
+#define _STDINT_NEED_INTPTR_T
+#ifndef _STDINT_HAVE_INTMAX_T
+#define _STDINT_NEED_INTMAX_T
+#endif
+#endif
+
+
+/* .................... definition part ............................ */
+
+/* some system headers have good uint64_t */
+#ifndef _HAVE_UINT64_T
+#if     defined _STDINT_HAVE_UINT64_T  || defined HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#elif   defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T
+#define _HAVE_UINT64_T
+typedef u_int64_t uint64_t;
+#endif
+#endif
+
+#ifndef _HAVE_UINT64_T
+/* .. here are some common heuristics using compiler runtime specifics */
+#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+#elif !defined __STRICT_ANSI__
+#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
+#define _HAVE_UINT64_T
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__
+/* note: all ELF-systems seem to have loff-support which needs 64-bit */
+#if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
+#elif defined __alpha || (defined __mips && defined _ABIN32)
+#if !defined _NO_LONGLONG
+typedef long int64_t;
+typedef unsigned long uint64_t;
+#endif
+  /* compiler/cpu type to define int64_t */
+#endif
+#endif
+#endif
+
+#if defined _STDINT_HAVE_U_INT_TYPES
+/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */
+typedef u_int8_t uint8_t;
+typedef u_int16_t uint16_t;
+typedef u_int32_t uint32_t;
+
+/* glibc compatibility */
+#ifndef __int8_t_defined
+#define __int8_t_defined
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INT_MODEL_T
+/* we must guess all the basic types. Apart from byte-adressable system, */
+/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */
+/* (btw, those nibble-addressable systems are way off, or so we assume) */
+
+dnl   /* have a look at "64bit and data size neutrality" at */
+dnl   /* http://unix.org/version2/whatsnew/login_64bit.html */
+dnl   /* (the shorthand "ILP" types always have a "P" part) */
+
+#if defined _STDINT_BYTE_MODEL
+#if _STDINT_LONG_MODEL+0 == 242
+/* 2:4:2 =  IP16 = a normal 16-bit system                */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned long   uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          long    int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444
+/* 2:4:4 =  LP32 = a 32-bit system derived from a 16-bit */
+/* 4:4:4 = ILP32 = a normal 32-bit system                */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488
+/* 4:8:4 =  IP32 = a 32-bit system prepared for 64-bit    */
+/* 4:8:8 =  LP64 = a normal 64-bit system                 */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+/* this system has a "long" of 64bit */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+typedef unsigned long   uint64_t;
+typedef          long    int64_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 448
+/*      LLP64   a 64-bit system derived from a 32-bit system */
+typedef unsigned char   uint8_t;
+typedef unsigned short  uint16_t;
+typedef unsigned int    uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef          char    int8_t;
+typedef          short   int16_t;
+typedef          int     int32_t;
+#endif
+/* assuming the system has a "long long" */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef unsigned long long uint64_t;
+typedef          long long  int64_t;
+#endif
+#else
+#define _STDINT_NO_INT32_T
+#endif
+#else
+#define _STDINT_NO_INT8_T
+#define _STDINT_NO_INT32_T
+#endif
+#endif
+
+/*
+ * quote from SunOS-5.8 sys/inttypes.h:
+ * Use at your own risk.  As of February 1996, the committee is squarely
+ * behind the fixed sized types; the "least" and "fast" types are still being
+ * discussed.  The probability that the "fast" types may be removed before
+ * the standard is finalized is high enough that they are not currently
+ * implemented.
+ */
+
+#if defined _STDINT_NEED_INT_LEAST_T
+typedef  int8_t    int_least8_t;
+typedef  int16_t   int_least16_t;
+typedef  int32_t   int_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef  int64_t   int_least64_t;
+#endif
+
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t  uint_least64_t;
+#endif
+  /* least types */
+#endif
+
+#if defined _STDINT_NEED_INT_FAST_T
+typedef  int8_t    int_fast8_t;
+typedef  int       int_fast16_t;
+typedef  int32_t   int_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef  int64_t   int_fast64_t;
+#endif
+
+typedef uint8_t   uint_fast8_t;
+typedef unsigned  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t  uint_fast64_t;
+#endif
+  /* fast types */
+#endif
+
+#ifdef _STDINT_NEED_INTMAX_T
+#ifdef _HAVE_UINT64_T
+typedef  int64_t       intmax_t;
+typedef uint64_t      uintmax_t;
+#else
+typedef          long  intmax_t;
+typedef unsigned long uintmax_t;
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INTPTR_T
+#ifndef __intptr_t_defined
+#define __intptr_t_defined
+/* we encourage using "long" to store pointer values, never use "int" ! */
+#if   _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484
+typedef  unsigned int   uintptr_t;
+typedef           int    intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444
+typedef  unsigned long  uintptr_t;
+typedef           long   intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T
+typedef        uint64_t uintptr_t;
+typedef         int64_t  intptr_t;
+#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */
+typedef  unsigned long  uintptr_t;
+typedef           long   intptr_t;
+#endif
+#endif
+#endif
+
+/* The ISO C99 standard specifies that in C++ implementations these
+   should only be defined if explicitly requested.  */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed.  */
+# define INT8_C(c)      c
+# define INT16_C(c)     c
+# define INT32_C(c)     c
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INT64_C(c)    c ## L
+# else
+#  define INT64_C(c)    c ## LL
+# endif
+
+/* Unsigned.  */
+# define UINT8_C(c)     c ## U
+# define UINT16_C(c)    c ## U
+# define UINT32_C(c)    c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define UINT64_C(c)   c ## UL
+# else
+#  define UINT64_C(c)   c ## ULL
+# endif
+
+/* Maximal type.  */
+# ifdef _HAVE_LONGLONG_UINT64_T
+#  define INTMAX_C(c)   c ## L
+#  define UINTMAX_C(c)  c ## UL
+# else
+#  define INTMAX_C(c)   c ## LL
+#  define UINTMAX_C(c)  c ## ULL
+# endif
+
+  /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types.  */
+# define INT8_MIN               (-128)
+# define INT16_MIN              (-32767-1)
+# define INT32_MIN              (-2147483647-1)
+#ifndef INT64_MIN
+# define INT64_MIN              (-__INT64_C(9223372036854775807)-1)
+#endif
+/* Maximum of signed integral types.  */
+# define INT8_MAX               (127)
+# define INT16_MAX              (32767)
+# define INT32_MAX              (2147483647)
+#ifndef INT64_MAX
+# define INT64_MAX              (__INT64_C(9223372036854775807))
+#endif
+
+/* Maximum of unsigned integral types.  */
+#ifndef UINT8_MAX
+# define UINT8_MAX              (255)
+#endif
+#ifndef UINT16_MAX
+# define UINT16_MAX             (65535)
+#endif
+# define UINT32_MAX             (4294967295U)
+#ifndef UINT64_MAX
+# define UINT64_MAX             (__UINT64_C(18446744073709551615))
+#endif
+
+/* Minimum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MIN         INT8_MIN
+# define INT_LEAST16_MIN        INT16_MIN
+# define INT_LEAST32_MIN        INT32_MIN
+# define INT_LEAST64_MIN        INT64_MIN
+/* Maximum of signed integral types having a minimum size.  */
+# define INT_LEAST8_MAX         INT8_MAX
+# define INT_LEAST16_MAX        INT16_MAX
+# define INT_LEAST32_MAX        INT32_MAX
+# define INT_LEAST64_MAX        INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size.  */
+# define UINT_LEAST8_MAX        UINT8_MAX
+# define UINT_LEAST16_MAX       UINT16_MAX
+# define UINT_LEAST32_MAX       UINT32_MAX
+# define UINT_LEAST64_MAX       UINT64_MAX
+
+  /* shortcircuit*/
+#endif
+  /* once */
+#endif
+#endif
+STDINT_EOF
+fi
+    if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
+      AC_MSG_NOTICE([$ac_stdint_h is unchanged])
+    else
+      ac_dir=`AS_DIRNAME(["$ac_stdint_h"])`
+      AS_MKDIR_P(["$ac_dir"])
+      rm -f $ac_stdint_h
+      mv $ac_stdint $ac_stdint_h
+    fi
+],[# variables for create stdint.h replacement
+PACKAGE="$PACKAGE"
+VERSION="$VERSION"
+ac_stdint_h="$ac_stdint_h"
+_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h)
+ac_cv_stdint_message="$ac_cv_stdint_message"
+ac_cv_header_stdint_t="$ac_cv_header_stdint_t"
+ac_cv_header_stdint_x="$ac_cv_header_stdint_x"
+ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
+ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
+ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
+ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
+ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
+ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
+ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
+])
+])

Added: polly/trunk/lib/External/isl/m4/ax_detect_git_head.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_detect_git_head.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_detect_git_head.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_detect_git_head.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,32 @@
+AC_DEFUN([AX_DETECT_GIT_HEAD], [
+	AC_SUBST(GIT_HEAD_ID)
+	AC_SUBST(GIT_HEAD)
+	AC_SUBST(GIT_HEAD_VERSION)
+	if test -f $srcdir/.git; then
+		gitdir=`GIT_DIR=$srcdir/.git git rev-parse --git-dir`
+		GIT_HEAD="$gitdir/index"
+		GIT_REPO="$gitdir"
+		GIT_HEAD_ID=`GIT_DIR=$GIT_REPO git describe --always`
+	elif test -f $srcdir/.git/HEAD; then
+		GIT_HEAD="$srcdir/.git/index"
+		GIT_REPO="$srcdir/.git"
+		GIT_HEAD_ID=`GIT_DIR=$GIT_REPO git describe --always`
+	elif test -f $srcdir/GIT_HEAD_ID; then
+		GIT_HEAD_ID=`cat $srcdir/GIT_HEAD_ID`
+	else
+		mysrcdir=`(cd $srcdir; pwd)`
+		head=`basename $mysrcdir | sed -e 's/.*-//'`
+		head2=`echo $head | sed -e 's/[^0-9a-f]//'`
+		head3=`echo $head2 | sed -e 's/........................................//'`
+		if test "x$head3" = "x" -a "x$head" = "x$head2"; then
+			GIT_HEAD_ID="$head"
+		else
+			GIT_HEAD_ID="UNKNOWN"
+		fi
+	fi
+	if test -z "$GIT_REPO" ; then
+		GIT_HEAD_VERSION="$GIT_HEAD_ID"
+	else
+	    GIT_HEAD_VERSION="\`GIT_DIR=$GIT_REPO git describe --always\`"
+	fi
+])

Added: polly/trunk/lib/External/isl/m4/ax_detect_gmp.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_detect_gmp.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_detect_gmp.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_detect_gmp.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,48 @@
+AC_DEFUN([AX_DETECT_GMP], [
+AC_DEFINE([USE_GMP_FOR_MP], [], [use gmp to implement isl_int])
+AX_SUBMODULE(gmp,system|build,system)
+case "$with_gmp" in
+system)
+	if test "x$with_gmp_prefix" != "x"; then
+		isl_configure_args="$isl_configure_args --with-gmp=$with_gmp_prefix"
+		MP_CPPFLAGS="-I$with_gmp_prefix/include"
+		MP_LDFLAGS="-L$with_gmp_prefix/lib"
+	fi
+	MP_LIBS=-lgmp
+	SAVE_CPPFLAGS="$CPPFLAGS"
+	SAVE_LDFLAGS="$LDFLAGS"
+	SAVE_LIBS="$LIBS"
+	CPPFLAGS="$MP_CPPFLAGS $CPPFLAGS"
+	LDFLAGS="$MP_LDFLAGS $LDFLAGS"
+	LIBS="$MP_LIBS $LIBS"
+	AC_CHECK_HEADER([gmp.h], [], [AC_ERROR([gmp.h header not found])])
+	AC_CHECK_LIB([gmp], [main], [], [AC_ERROR([gmp library not found])])
+	AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <gmp.h>]], [[
+		mpz_t n, d;
+		if (mpz_divisible_p(n, d))
+			mpz_divexact_ui(n, n, 4);
+	]])], [], [AC_ERROR([gmp library too old])])
+	CPPFLAGS="$SAVE_CPPFLAGS"
+	LDFLAGS="$SAVE_LDFLAGS"
+	LIBS="$SAVE_LIBS"
+	;;
+build)
+	MP_CPPFLAGS="-I$gmp_srcdir -I$with_gmp_builddir"
+	MP_LIBS="$with_gmp_builddir/libgmp.la"
+	;;
+esac
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
+CPPFLAGS="$MP_CPPFLAGS $CPPFLAGS"
+LDFLAGS="$MP_LDFLAGS $LDFLAGS"
+LIBS="$MP_LIBS $LIBS"
+need_get_memory_functions=false
+AC_CHECK_DECLS(mp_get_memory_functions,[],[
+	need_get_memory_functions=true
+],[#include <gmp.h>])
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
+AM_CONDITIONAL(NEED_GET_MEMORY_FUNCTIONS, test x$need_get_memory_functions = xtrue)
+])

Added: polly/trunk/lib/External/isl/m4/ax_detect_imath.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_detect_imath.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_detect_imath.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_detect_imath.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,15 @@
+AC_DEFUN([AX_DETECT_IMATH], [
+AC_DEFINE([USE_IMATH_FOR_MP], [], [use imath to implement isl_int])
+
+MP_CPPFLAGS="-I$srcdir/imath_wrap"
+MP_LDFLAGS=""
+MP_LIBS=""
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$MP_CPPFLAGS $CPPFLAGS"
+AC_CHECK_HEADER([imath.h], [], [AC_ERROR([imath.h header not found])])
+AC_CHECK_HEADER([gmp_compat.h], [], [AC_ERROR([gmp_compat.h header not found])])
+CPPFLAGS="$SAVE_CPPFLAGS"
+
+AM_CONDITIONAL(NEED_GET_MEMORY_FUNCTIONS, test x = xfalse)
+])

Added: polly/trunk/lib/External/isl/m4/ax_gcc_archflag.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_gcc_archflag.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_gcc_archflag.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_gcc_archflag.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,213 @@
+# ===========================================================================
+#         http://www.nongnu.org/autoconf-archive/ax_gcc_archflag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE])
+#
+# DESCRIPTION
+#
+#   This macro tries to guess the "native" arch corresponding to the target
+#   architecture for use with gcc's -march=arch or -mtune=arch flags. If
+#   found, the cache variable $ax_cv_gcc_archflag is set to this flag and
+#   ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is is set to
+#   "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is
+#   to add $ax_cv_gcc_archflag to the end of $CFLAGS.
+#
+#   PORTABLE? should be either [yes] (default) or [no]. In the former case,
+#   the flag is set to -mtune (or equivalent) so that the architecture is
+#   only used for tuning, but the instruction set used is still portable. In
+#   the latter case, the flag is set to -march (or equivalent) so that
+#   architecture-specific instructions are enabled.
+#
+#   The user can specify --with-gcc-arch=<arch> in order to override the
+#   macro's choice of architecture, or --without-gcc-arch to disable this.
+#
+#   When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is
+#   called unless the user specified --with-gcc-arch manually.
+#
+#   Requires macros: AX_CHECK_COMPILER_FLAGS, AX_GCC_X86_CPUID
+#
+#   (The main emphasis here is on recent CPUs, on the principle that doing
+#   high-performance computing on old hardware is uncommon.)
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2008 Matteo Frigo
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_GCC_ARCHFLAG],
+[AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_CANONICAL_HOST])
+
+AC_ARG_WITH(gcc-arch, [AC_HELP_STRING([--with-gcc-arch=<arch>], [use architecture <arch> for gcc -march/-mtune, instead of guessing])],
+	ax_gcc_arch=$withval, ax_gcc_arch=yes)
+
+AC_MSG_CHECKING([for gcc architecture flag])
+AC_MSG_RESULT([])
+AC_CACHE_VAL(ax_cv_gcc_archflag,
+[
+ax_cv_gcc_archflag="unknown"
+
+if test "$GCC" = yes; then
+
+if test "x$ax_gcc_arch" = xyes; then
+ax_gcc_arch=""
+if test "$cross_compiling" = no; then
+case $host_cpu in
+  i[[3456]]86*|x86_64*) # use cpuid codes, in part from x86info-1.7 by D. Jones
+     AX_GCC_X86_CPUID(0)
+     AX_GCC_X86_CPUID(1)
+     case $ax_cv_gcc_x86_cpuid_0 in
+       *:756e6547:*:*) # Intel
+          case $ax_cv_gcc_x86_cpuid_1 in
+	    *5[[48]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;;
+	    *5??:*:*:*) ax_gcc_arch=pentium ;;
+	    *6[[3456]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
+	    *6a?:*[[01]]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
+	    *6a?:*[[234]]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
+	    *6[[9d]]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;;
+	    *6[[78b]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
+	    *6??:*:*:*) ax_gcc_arch=pentiumpro ;;
+            *f3[[347]]:*:*:*|*f4[1347]:*:*:*)
+		case $host_cpu in
+                  x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;;
+                  *) ax_gcc_arch="prescott pentium4 pentiumpro" ;;
+                esac ;;
+            *f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";;
+          esac ;;
+       *:68747541:*:*) # AMD
+          case $ax_cv_gcc_x86_cpuid_1 in
+	    *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;;
+	    *5[[8d]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;;
+	    *5[[9]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;;
+	    *60?:*:*:*) ax_gcc_arch=k7 ;;
+	    *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;;
+	    *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;;
+	    *67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;;
+	    *6[[68a]]?:*:*:*)
+	       AX_GCC_X86_CPUID(0x80000006) # L2 cache size
+	       case $ax_cv_gcc_x86_cpuid_0x80000006 in
+                 *:*:*[[1-9a-f]]??????:*) # (L2 = ecx >> 16) >= 256
+			ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;;
+                 *) ax_gcc_arch="athlon-4 athlon k7" ;;
+	       esac ;;
+	    *f[[4cef8b]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;;
+	    *f5?:*:*:*) ax_gcc_arch="opteron k8" ;;
+	    *f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;;
+	    *f??:*:*:*) ax_gcc_arch="k8" ;;
+          esac ;;
+	*:746e6543:*:*) # IDT
+	   case $ax_cv_gcc_x86_cpuid_1 in
+	     *54?:*:*:*) ax_gcc_arch=winchip-c6 ;;
+	     *58?:*:*:*) ax_gcc_arch=winchip2 ;;
+	     *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;;
+	     *69?:*:*:*) ax_gcc_arch="c3-2 c3" ;;
+	   esac ;;
+     esac
+     if test x"$ax_gcc_arch" = x; then # fallback
+	case $host_cpu in
+	  i586*) ax_gcc_arch=pentium ;;
+	  i686*) ax_gcc_arch=pentiumpro ;;
+        esac
+     fi
+     ;;
+
+  sparc*)
+     AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/])
+     cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null`
+     cputype=`echo "$cputype" | tr -d ' -' |tr $as_cr_LETTERS $as_cr_letters`
+     case $cputype in
+         *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;;
+         *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;;
+         *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;;
+         *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;;
+         *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;;
+         *cypress*) ax_gcc_arch=cypress ;;
+     esac ;;
+
+  alphaev5) ax_gcc_arch=ev5 ;;
+  alphaev56) ax_gcc_arch=ev56 ;;
+  alphapca56) ax_gcc_arch="pca56 ev56" ;;
+  alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;;
+  alphaev6) ax_gcc_arch=ev6 ;;
+  alphaev67) ax_gcc_arch=ev67 ;;
+  alphaev68) ax_gcc_arch="ev68 ev67" ;;
+  alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;;
+  alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;;
+  alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;;
+
+  powerpc*)
+     cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null`
+     cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'`
+     case $cputype in
+       *750*) ax_gcc_arch="750 G3" ;;
+       *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;;
+       *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;;
+       *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;;
+       *970*) ax_gcc_arch="970 G5 power4";;
+       *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";;
+       *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";;
+       603ev|8240) ax_gcc_arch="$cputype 603e 603";;
+       *) ax_gcc_arch=$cputype ;;
+     esac
+     ax_gcc_arch="$ax_gcc_arch powerpc"
+     ;;
+esac
+fi # not cross-compiling
+fi # guess arch
+
+if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then
+for arch in $ax_gcc_arch; do
+  if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code
+    flags="-mtune=$arch"
+    # -mcpu=$arch and m$arch generate nonportable code on every arch except
+    # x86.  And some other arches (e.g. Alpha) don't accept -mtune.  Grrr.
+    case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac
+  else
+    flags="-march=$arch -mcpu=$arch -m$arch"
+  fi
+  for flag in $flags; do
+    AX_CHECK_COMPILER_FLAGS($flag, [ax_cv_gcc_archflag=$flag; break])
+  done
+  test "x$ax_cv_gcc_archflag" = xunknown || break
+done
+fi
+
+fi # $GCC=yes
+])
+AC_MSG_CHECKING([for gcc architecture flag])
+AC_MSG_RESULT($ax_cv_gcc_archflag)
+if test "x$ax_cv_gcc_archflag" = xunknown; then
+  m4_default([$3],:)
+else
+  m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"])
+fi
+])

Added: polly/trunk/lib/External/isl/m4/ax_gcc_warn_unused_result.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_gcc_warn_unused_result.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_gcc_warn_unused_result.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_gcc_warn_unused_result.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,56 @@
+# ===========================================================================
+#    http://www.nongnu.org/autoconf-archive/ax_gcc_warn_unused_result.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_GCC_WARN_UNUSED_RESULT
+#
+# DESCRIPTION
+#
+#   The macro will compile a test program to see whether the compiler does
+#   understand the per-function postfix pragma.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_GCC_WARN_UNUSED_RESULT],[dnl
+AC_CACHE_CHECK(
+ [whether the compiler supports function __attribute__((__warn_unused_result__))],
+ ax_cv_gcc_warn_unused_result,[
+ AC_TRY_COMPILE([__attribute__((__warn_unused_result__))
+ int f(int i) { return i; }],
+ [],
+ ax_cv_gcc_warn_unused_result=yes, ax_cv_gcc_warn_unused_result=no)])
+ if test "$ax_cv_gcc_warn_unused_result" = yes; then
+   AC_DEFINE([GCC_WARN_UNUSED_RESULT],[__attribute__((__warn_unused_result__))],
+    [most gcc compilers know a function __attribute__((__warn_unused_result__))])
+ fi
+])

Added: polly/trunk/lib/External/isl/m4/ax_gcc_x86_cpuid.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_gcc_x86_cpuid.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_gcc_x86_cpuid.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_gcc_x86_cpuid.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,77 @@
+# ===========================================================================
+#        http://www.nongnu.org/autoconf-archive/ax_gcc_x86_cpuid.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_GCC_X86_CPUID(OP)
+#
+# DESCRIPTION
+#
+#   On Pentium and later x86 processors, with gcc or a compiler that has a
+#   compatible syntax for inline assembly instructions, run a small program
+#   that executes the cpuid instruction with input OP. This can be used to
+#   detect the CPU type.
+#
+#   On output, the values of the eax, ebx, ecx, and edx registers are stored
+#   as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable
+#   ax_cv_gcc_x86_cpuid_OP.
+#
+#   If the cpuid instruction fails (because you are running a
+#   cross-compiler, or because you are not using gcc, or because you are on
+#   a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP
+#   is set to the string "unknown".
+#
+#   This macro mainly exists to be used in AX_GCC_ARCHFLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+#   Copyright (c) 2008 Matteo Frigo
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_GCC_X86_CPUID],
+[AC_REQUIRE([AC_PROG_CC])
+AC_LANG_PUSH([C])
+AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1,
+ [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>], [
+     int op = $1, eax, ebx, ecx, edx;
+     FILE *f;
+      __asm__("cpuid"
+        : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
+        : "a" (op));
+     f = fopen("conftest_cpuid", "w"); if (!f) return 1;
+     fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx);
+     fclose(f);
+     return 0;
+])],
+     [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid],
+     [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid],
+     [ax_cv_gcc_x86_cpuid_$1=unknown])])
+AC_LANG_POP([C])
+])

Added: polly/trunk/lib/External/isl/m4/ax_set_warning_flags.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_set_warning_flags.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_set_warning_flags.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_set_warning_flags.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,17 @@
+dnl Add a set of flags to WARNING_FLAGS, that enable compiler warnings for
+dnl isl. The warnings that are enabled vary with the compiler and only include
+dnl warnings that did not trigger at the time of adding these flags.
+AC_DEFUN([AX_SET_WARNING_FLAGS],[dnl
+	AX_COMPILER_VENDOR
+
+	WARNING_FLAGS=""
+
+	if test "${ax_cv_c_compiler_vendor}" = "clang"; then
+		dnl isl is at the moment clean of -Wall warnings.  If clang adds
+		dnl new warnings to -Wall which cause false positives, the
+		dnl specific warning types will be disabled explicitally (by
+		dnl adding for example -Wno-return-type). To temporarily disable
+		dnl all warnings run configure with CFLAGS=-Wno-all.
+		WARNING_FLAGS="-Wall"
+	fi
+])

Added: polly/trunk/lib/External/isl/m4/ax_submodule.m4
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/m4/ax_submodule.m4?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/m4/ax_submodule.m4 (added)
+++ polly/trunk/lib/External/isl/m4/ax_submodule.m4 Wed Feb  4 14:55:43 2015
@@ -0,0 +1,71 @@
+AC_DEFUN([AX_SUBMODULE],
+[
+
+m4_if(m4_bregexp($2,|,choice),choice,
+	[AC_ARG_WITH($1,
+		[AS_HELP_STRING([--with-$1=$2],
+				[Which $1 to use [default=$3]])])])
+case "system" in
+$2)
+	AC_ARG_WITH($1_prefix,
+		    [AS_HELP_STRING([--with-$1-prefix=DIR],
+				    [Prefix of $1 installation])])
+	AC_ARG_WITH($1_exec_prefix,
+		    [AS_HELP_STRING([--with-$1-exec-prefix=DIR],
+				    [Exec prefix of $1 installation])])
+esac
+m4_if(m4_bregexp($2,build,build),build,
+	[AC_ARG_WITH($1_builddir,
+		[AS_HELP_STRING([--with-$1-builddir=DIR],
+				[Location of $1 builddir])])])
+if test "x$with_$1_prefix" != "x" -a "x$with_$1_exec_prefix" = "x"; then
+	with_$1_exec_prefix=$with_$1_prefix
+fi
+if test "x$with_$1_prefix" != "x" -o "x$with_$1_exec_prefix" != "x"; then
+	if test "x$with_$1" != "x" -a "x$with_$1" != "xyes" -a "x$with_$1" != "xsystem"; then
+		AC_MSG_ERROR([Setting $with_$1_prefix implies use of system $1])
+	fi
+	with_$1="system"
+fi
+if test "x$with_$1_builddir" != "x"; then
+	if test "x$with_$1" != "x" -a "x$with_$1" != "xyes" -a "x$with_$1" != "xbuild"; then
+		AC_MSG_ERROR([Setting $with_$1_builddir implies use of build $1])
+	fi
+	with_$1="build"
+	$1_srcdir=`echo @abs_srcdir@ | $with_$1_builddir/config.status --file=-`
+	AC_MSG_NOTICE($1 sources in $$1_srcdir)
+fi
+if test "x$with_$1_exec_prefix" != "x"; then
+	export PKG_CONFIG_PATH="$with_$1_exec_prefix/lib/pkgconfig${PKG_CONFIG_PATH+:$PKG_CONFIG_PATH}"
+fi
+case "$with_$1" in
+$2)
+	;;
+*)
+	case "$3" in
+	bundled)
+		if test -d $srcdir/.git -a \
+			-d $srcdir/$1 -a \
+			! -d $srcdir/$1/.git; then
+			AC_MSG_WARN([git repo detected, but submodule $1 not initialized])
+			AC_MSG_WARN([You may want to run])
+			AC_MSG_WARN([	git submodule init])
+			AC_MSG_WARN([	git submodule update])
+			AC_MSG_WARN([	sh autogen.sh])
+		fi
+		if test -f $srcdir/$1/configure; then
+			with_$1="bundled"
+		else
+			with_$1="no"
+		fi
+		;;
+	*)
+		with_$1="$3"
+		;;
+	esac
+	;;
+esac
+AC_MSG_CHECKING([which $1 to use])
+AC_MSG_RESULT($with_$1)
+
+])

Added: polly/trunk/lib/External/isl/mp_get_memory_functions.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/mp_get_memory_functions.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/mp_get_memory_functions.c (added)
+++ polly/trunk/lib/External/isl/mp_get_memory_functions.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,14 @@
+#include <gmp.h>
+
+void mp_get_memory_functions(
+		void *(**alloc_func_ptr) (size_t),
+		void *(**realloc_func_ptr) (void *, size_t, size_t),
+		void (**free_func_ptr) (void *, size_t))
+{
+	if (alloc_func_ptr)
+		*alloc_func_ptr = __gmp_allocate_func;
+	if (realloc_func_ptr)
+		*realloc_func_ptr = __gmp_reallocate_func;
+	if (free_func_ptr)
+		*free_func_ptr = __gmp_free_func;
+}

Added: polly/trunk/lib/External/isl/pip.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/pip.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/pip.c (added)
+++ polly/trunk/lib/External/isl/pip.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+#include <isl_map_private.h>
+#include <isl/aff.h>
+#include <isl/set.h>
+#include "isl_tab.h"
+#include "isl_sample.h"
+#include "isl_scan.h"
+#include <isl_seq.h>
+#include <isl_ilp_private.h>
+#include <isl/printer.h>
+#include <isl_point_private.h>
+#include <isl_vec_private.h>
+#include <isl/options.h>
+
+/* The input of this program is the same as that of the "example" program
+ * from the PipLib distribution, except that the "big parameter column"
+ * should always be -1.
+ *
+ * Context constraints in PolyLib format
+ * -1
+ * Problem constraints in PolyLib format
+ * Optional list of options
+ *
+ * The options are
+ *	Maximize	compute maximum instead of minimum
+ *	Rational	compute rational optimum instead of integer optimum
+ *	Urs_parms	don't assume parameters are non-negative
+ *	Urs_unknowns	don't assume unknowns are non-negative
+ */
+
+struct options {
+	struct isl_options	*isl;
+	unsigned		 verify;
+	unsigned		 format;
+};
+
+#define FORMAT_SET	0
+#define FORMAT_AFF	1
+
+struct isl_arg_choice pip_format[] = {
+	{"set",		FORMAT_SET},
+	{"affine",	FORMAT_AFF},
+	{0}
+};
+
+ISL_ARGS_START(struct options, options_args)
+ISL_ARG_CHILD(struct options, isl, "isl", &isl_options_args, "isl options")
+ISL_ARG_BOOL(struct options, verify, 'T', "verify", 0, NULL)
+ISL_ARG_CHOICE(struct options, format, 0, "format",
+	pip_format, FORMAT_SET, "output format")
+ISL_ARGS_END
+
+ISL_ARG_DEF(options, struct options, options_args)
+
+static __isl_give isl_basic_set *set_bounds(__isl_take isl_basic_set *bset)
+{
+	unsigned nparam;
+	int i, r;
+	isl_point *pt, *pt2;
+	isl_basic_set *box;
+
+	nparam = isl_basic_set_dim(bset, isl_dim_param);
+	r = nparam >= 8 ? 4 : nparam >= 5 ? 6 : 30;
+
+	pt = isl_basic_set_sample_point(isl_basic_set_copy(bset));
+	pt2 = isl_point_copy(pt);
+
+	for (i = 0; i < nparam; ++i) {
+		pt = isl_point_add_ui(pt, isl_dim_param, i, r);
+		pt2 = isl_point_sub_ui(pt2, isl_dim_param, i, r);
+	}
+
+	box = isl_basic_set_box_from_points(pt, pt2);
+
+	return isl_basic_set_intersect(bset, box);
+}
+
+static struct isl_basic_set *to_parameter_domain(struct isl_basic_set *context)
+{
+	context = isl_basic_set_move_dims(context, isl_dim_param, 0,
+		    isl_dim_set, 0, isl_basic_set_dim(context, isl_dim_set));
+	context = isl_basic_set_params(context);
+	return context;
+}
+
+isl_basic_set *plug_in_parameters(isl_basic_set *bset, struct isl_vec *params)
+{
+	int i;
+
+	for (i = 0; i < params->size - 1; ++i)
+		bset = isl_basic_set_fix(bset,
+					 isl_dim_param, i, params->el[1 + i]);
+
+	bset = isl_basic_set_remove_dims(bset,
+					 isl_dim_param, 0, params->size - 1);
+
+	isl_vec_free(params);
+
+	return bset;
+}
+
+isl_set *set_plug_in_parameters(isl_set *set, struct isl_vec *params)
+{
+	int i;
+
+	for (i = 0; i < params->size - 1; ++i)
+		set = isl_set_fix(set, isl_dim_param, i, params->el[1 + i]);
+
+	set = isl_set_remove_dims(set, isl_dim_param, 0, params->size - 1);
+
+	isl_vec_free(params);
+
+	return set;
+}
+
+/* Compute the lexicographically minimal (or maximal if max is set)
+ * element of bset for the given values of the parameters, by
+ * successively solving an ilp problem in each direction.
+ */
+struct isl_vec *opt_at(struct isl_basic_set *bset,
+	struct isl_vec *params, int max)
+{
+	unsigned dim;
+	struct isl_vec *opt;
+	struct isl_vec *obj;
+	int i;
+
+	dim = isl_basic_set_dim(bset, isl_dim_set);
+
+	bset = plug_in_parameters(bset, params);
+
+	if (isl_basic_set_plain_is_empty(bset)) {
+		opt = isl_vec_alloc(bset->ctx, 0);
+		isl_basic_set_free(bset);
+		return opt;
+	}
+
+	opt = isl_vec_alloc(bset->ctx, 1 + dim);
+	assert(opt);
+
+	obj = isl_vec_alloc(bset->ctx, 1 + dim);
+	assert(obj);
+
+	isl_int_set_si(opt->el[0], 1);
+	isl_int_set_si(obj->el[0], 0);
+
+	for (i = 0; i < dim; ++i) {
+		enum isl_lp_result res;
+
+		isl_seq_clr(obj->el + 1, dim);
+		isl_int_set_si(obj->el[1 + i], 1);
+		res = isl_basic_set_solve_ilp(bset, max, obj->el,
+						&opt->el[1 + i], NULL);
+		if (res == isl_lp_empty)
+			goto empty;
+		assert(res == isl_lp_ok);
+		bset = isl_basic_set_fix(bset, isl_dim_set, i, opt->el[1 + i]);
+	}
+
+	isl_basic_set_free(bset);
+	isl_vec_free(obj);
+
+	return opt;
+empty:
+	isl_vec_free(opt);
+	opt = isl_vec_alloc(bset->ctx, 0);
+	isl_basic_set_free(bset);
+	isl_vec_free(obj);
+
+	return opt;
+}
+
+struct isl_scan_pip {
+	struct isl_scan_callback callback;
+	isl_basic_set *bset;
+	isl_set *sol;
+	isl_set *empty;
+	int stride;
+	int n;
+	int max;
+};
+
+/* Check if the "manually" computed optimum of bset at the "sample"
+ * values of the parameters agrees with the solution of pilp problem
+ * represented by the pair (sol, empty).
+ * In particular, if there is no solution for this value of the parameters,
+ * then it should be an element of the parameter domain "empty".
+ * Otherwise, the optimal solution, should be equal to the result of
+ * plugging in the value of the parameters in "sol".
+ */
+static int scan_one(struct isl_scan_callback *callback,
+	__isl_take isl_vec *sample)
+{
+	struct isl_scan_pip *sp = (struct isl_scan_pip *)callback;
+	struct isl_vec *opt;
+
+	sp->n--;
+
+	opt = opt_at(isl_basic_set_copy(sp->bset), isl_vec_copy(sample), sp->max);
+	assert(opt);
+
+	if (opt->size == 0) {
+		isl_point *sample_pnt;
+		sample_pnt = isl_point_alloc(isl_set_get_space(sp->empty), sample);
+		assert(isl_set_contains_point(sp->empty, sample_pnt));
+		isl_point_free(sample_pnt);
+		isl_vec_free(opt);
+	} else {
+		isl_set *sol;
+		isl_set *opt_set;
+		opt_set = isl_set_from_basic_set(isl_basic_set_from_vec(opt));
+		sol = set_plug_in_parameters(isl_set_copy(sp->sol), sample);
+		assert(isl_set_is_equal(opt_set, sol));
+		isl_set_free(sol);
+		isl_set_free(opt_set);
+	}
+
+	if (!(sp->n % sp->stride)) {
+		printf("o");
+		fflush(stdout);
+	}
+
+	return sp->n >= 1 ? 0 : -1;
+}
+
+static void check_solution(isl_basic_set *bset, isl_basic_set *context,
+	isl_set *sol, isl_set *empty, int max)
+{
+	struct isl_scan_pip sp;
+	isl_int count, count_max;
+	int i, n;
+	int r;
+
+	context = set_bounds(context);
+	context = isl_basic_set_underlying_set(context);
+
+	isl_int_init(count);
+	isl_int_init(count_max);
+
+	isl_int_set_si(count_max, 2000);
+	r = isl_basic_set_count_upto(context, count_max, &count);
+	assert(r >= 0);
+	n = isl_int_get_si(count);
+
+	isl_int_clear(count_max);
+	isl_int_clear(count);
+
+	sp.callback.add = scan_one;
+	sp.bset = bset;
+	sp.sol = sol;
+	sp.empty = empty;
+	sp.n = n;
+	sp.stride = n > 70 ? 1 + (n + 1)/70 : 1;
+	sp.max = max;
+
+	for (i = 0; i < n; i += sp.stride)
+		printf(".");
+	printf("\r");
+	fflush(stdout);
+
+	isl_basic_set_scan(context, &sp.callback);
+
+	printf("\n");
+
+	isl_basic_set_free(bset);
+}
+
+int main(int argc, char **argv)
+{
+	struct isl_ctx *ctx;
+	struct isl_basic_set *context, *bset, *copy, *context_copy;
+	struct isl_set *set = NULL;
+	struct isl_set *empty;
+	isl_pw_multi_aff *pma = NULL;
+	int neg_one;
+	char s[1024];
+	int urs_parms = 0;
+	int urs_unknowns = 0;
+	int max = 0;
+	int rational = 0;
+	int n;
+	int nparam;
+	struct options *options;
+
+	options = options_new_with_defaults();
+	assert(options);
+	argc = options_parse(options, argc, argv, ISL_ARG_ALL);
+
+	ctx = isl_ctx_alloc_with_options(&options_args, options);
+
+	context = isl_basic_set_read_from_file(ctx, stdin);
+	assert(context);
+	n = fscanf(stdin, "%d", &neg_one);
+	assert(n == 1);
+	assert(neg_one == -1);
+	bset = isl_basic_set_read_from_file(ctx, stdin);
+
+	while (fgets(s, sizeof(s), stdin)) {
+		if (strncasecmp(s, "Maximize", 8) == 0)
+			max = 1;
+		if (strncasecmp(s, "Rational", 8) == 0) {
+			rational = 1;
+			bset = isl_basic_set_set_rational(bset);
+		}
+		if (strncasecmp(s, "Urs_parms", 9) == 0)
+			urs_parms = 1;
+		if (strncasecmp(s, "Urs_unknowns", 12) == 0)
+			urs_unknowns = 1;
+	}
+	if (!urs_parms)
+		context = isl_basic_set_intersect(context,
+		isl_basic_set_positive_orthant(isl_basic_set_get_space(context)));
+	context = to_parameter_domain(context);
+	nparam = isl_basic_set_dim(context, isl_dim_param);
+	if (nparam != isl_basic_set_dim(bset, isl_dim_param)) {
+		int dim = isl_basic_set_dim(bset, isl_dim_set);
+		bset = isl_basic_set_move_dims(bset, isl_dim_param, 0,
+					    isl_dim_set, dim - nparam, nparam);
+	}
+	if (!urs_unknowns)
+		bset = isl_basic_set_intersect(bset,
+		isl_basic_set_positive_orthant(isl_basic_set_get_space(bset)));
+
+	if (options->verify) {
+		copy = isl_basic_set_copy(bset);
+		context_copy = isl_basic_set_copy(context);
+	}
+
+	if (options->format == FORMAT_AFF) {
+		if (max)
+			pma = isl_basic_set_partial_lexmax_pw_multi_aff(bset,
+								context, &empty);
+		else
+			pma = isl_basic_set_partial_lexmin_pw_multi_aff(bset,
+								context, &empty);
+	} else {
+		if (max)
+			set = isl_basic_set_partial_lexmax(bset,
+								context, &empty);
+		else
+			set = isl_basic_set_partial_lexmin(bset,
+								context, &empty);
+	}
+
+	if (options->verify) {
+		assert(!rational);
+		if (options->format == FORMAT_AFF)
+			set = isl_set_from_pw_multi_aff(pma);
+		check_solution(copy, context_copy, set, empty, max);
+		isl_set_free(set);
+	} else {
+		isl_printer *p;
+		p = isl_printer_to_file(ctx, stdout);
+		if (options->format == FORMAT_AFF)
+			p = isl_printer_print_pw_multi_aff(p, pma);
+		else
+			p = isl_printer_print_set(p, set);
+		p = isl_printer_end_line(p);
+		p = isl_printer_print_str(p, "no solution: ");
+		p = isl_printer_print_set(p, empty);
+		p = isl_printer_end_line(p);
+		isl_printer_free(p);
+		isl_set_free(set);
+		isl_pw_multi_aff_free(pma);
+	}
+
+	isl_set_free(empty);
+	isl_ctx_free(ctx);
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/pip_test.sh.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/pip_test.sh.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/pip_test.sh.in (added)
+++ polly/trunk/lib/External/isl/pip_test.sh.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+EXEEXT=@EXEEXT@
+
+PIP_TESTS="\
+	boulet.pip \
+	brisebarre.pip \
+	cg1.pip \
+	esced.pip \
+	ex2.pip \
+	ex.pip \
+	fimmel.pip \
+	max.pip \
+	negative.pip \
+	seghir-vd.pip \
+	small.pip \
+	sor1d.pip \
+	square.pip \
+	sven.pip \
+	tobi.pip"
+
+for i in $PIP_TESTS; do
+	echo $i;
+	./isl_pip$EXEEXT --format=set --context=gbr -T < $srcdir/test_inputs/$i || exit
+	./isl_pip$EXEEXT --format=set --context=lexmin -T < $srcdir/test_inputs/$i || exit
+	./isl_pip$EXEEXT --format=affine --context=gbr -T < $srcdir/test_inputs/$i || exit
+	./isl_pip$EXEEXT --format=affine --context=lexmin -T < $srcdir/test_inputs/$i || exit
+done

Propchange: polly/trunk/lib/External/isl/pip_test.sh.in
------------------------------------------------------------------------------
    svn:executable = *

Added: polly/trunk/lib/External/isl/polyhedron_detect_equalities.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/polyhedron_detect_equalities.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/polyhedron_detect_equalities.c (added)
+++ polly/trunk/lib/External/isl/polyhedron_detect_equalities.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl/set.h>
+
+int main(int argc, char **argv)
+{
+	struct isl_ctx *ctx = isl_ctx_alloc();
+	struct isl_basic_set *bset;
+
+	bset = isl_basic_set_read_from_file(ctx, stdin);
+	bset = isl_basic_set_detect_equalities(bset);
+	isl_basic_set_print(bset, stdout, 0, "", "", ISL_FORMAT_POLYLIB);
+	isl_basic_set_free(bset);
+	isl_ctx_free(ctx);
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/polyhedron_minimize.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/polyhedron_minimize.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/polyhedron_minimize.c (added)
+++ polly/trunk/lib/External/isl/polyhedron_minimize.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl/set.h>
+#include <isl/vec.h>
+#include <isl_ilp_private.h>
+#include <isl_seq.h>
+#include <isl_vec_private.h>
+
+/* The input of this program is the same as that of the "polytope_minimize"
+ * program from the barvinok distribution.
+ *
+ * Constraints of set is PolyLib format.
+ * Linear or affine objective function in PolyLib format.
+ */
+
+static struct isl_vec *isl_vec_lin_to_aff(struct isl_vec *vec)
+{
+	struct isl_vec *aff;
+
+	if (!vec)
+		return NULL;
+	aff = isl_vec_alloc(vec->ctx, 1 + vec->size);
+	if (!aff)
+		goto error;
+	isl_int_set_si(aff->el[0], 0);
+	isl_seq_cpy(aff->el + 1, vec->el, vec->size);
+	isl_vec_free(vec);
+	return aff;
+error:
+	isl_vec_free(vec);
+	return NULL;
+}
+
+/* Rotate elements of vector right.
+ * In particular, move the constant term from the end of the
+ * vector to the start of the vector.
+ */
+static struct isl_vec *vec_ror(struct isl_vec *vec)
+{
+	int i;
+
+	if (!vec)
+		return NULL;
+	for (i = vec->size - 2; i >= 0; --i)
+		isl_int_swap(vec->el[i], vec->el[i + 1]);
+	return vec;
+}
+
+int main(int argc, char **argv)
+{
+	struct isl_ctx *ctx = isl_ctx_alloc();
+	struct isl_basic_set *bset;
+	struct isl_vec *obj;
+	struct isl_vec *sol;
+	isl_int opt;
+	unsigned dim;
+	enum isl_lp_result res;
+	isl_printer *p;
+
+	isl_int_init(opt);
+	bset = isl_basic_set_read_from_file(ctx, stdin);
+	assert(bset);
+	obj = isl_vec_read_from_file(ctx, stdin);
+	assert(obj);
+	dim = isl_basic_set_total_dim(bset);
+	assert(obj->size >= dim && obj->size <= dim + 1);
+	if (obj->size != dim + 1)
+		obj = isl_vec_lin_to_aff(obj);
+	else
+		obj = vec_ror(obj);
+	res = isl_basic_set_solve_ilp(bset, 0, obj->el, &opt, &sol);
+	switch (res) {
+	case isl_lp_error:
+		fprintf(stderr, "error\n");
+		return -1;
+	case isl_lp_empty:
+		fprintf(stdout, "empty\n");
+		break;
+	case isl_lp_unbounded:
+		fprintf(stdout, "unbounded\n");
+		break;
+	case isl_lp_ok:
+		p = isl_printer_to_file(ctx, stdout);
+		p = isl_printer_print_vec(p, sol);
+		p = isl_printer_end_line(p);
+		p = isl_printer_print_isl_int(p, opt);
+		p = isl_printer_end_line(p);
+		isl_printer_free(p);
+	}
+	isl_basic_set_free(bset);
+	isl_vec_free(obj);
+	isl_vec_free(sol);
+	isl_ctx_free(ctx);
+	isl_int_clear(opt);
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/polyhedron_sample.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/polyhedron_sample.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/polyhedron_sample.c (added)
+++ polly/trunk/lib/External/isl/polyhedron_sample.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl_map_private.h>
+#include "isl_sample.h"
+#include <isl/vec.h>
+
+int main(int argc, char **argv)
+{
+	struct isl_ctx *ctx = isl_ctx_alloc();
+	struct isl_basic_set *bset;
+	struct isl_vec *sample;
+	isl_printer *p;
+
+	bset = isl_basic_set_read_from_file(ctx, stdin);
+	sample = isl_basic_set_sample_vec(isl_basic_set_copy(bset));
+	p = isl_printer_to_file(ctx, stdout);
+	p = isl_printer_print_vec(p, sample);
+	p = isl_printer_end_line(p);
+	isl_printer_free(p);
+	assert(sample);
+	if (isl_vec_size(sample) > 0)
+		assert(isl_basic_set_contains(bset, sample));
+	isl_basic_set_free(bset);
+	isl_vec_free(sample);
+	isl_ctx_free(ctx);
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/polytope_scan.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/polytope_scan.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/polytope_scan.c (added)
+++ polly/trunk/lib/External/isl/polytope_scan.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl_map_private.h>
+#include "isl_equalities.h"
+#include <isl_seq.h>
+#include "isl_scan.h"
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+/* The input of this program is the same as that of the "polytope_scan"
+ * program from the barvinok distribution.
+ *
+ * Constraints of set is PolyLib format.
+ *
+ * The input set is assumed to be bounded.
+ */
+
+struct scan_samples {
+	struct isl_scan_callback callback;
+	struct isl_mat *samples;
+};
+
+static int scan_samples_add_sample(struct isl_scan_callback *cb,
+	__isl_take isl_vec *sample)
+{
+	struct scan_samples *ss = (struct scan_samples *)cb;
+
+	ss->samples = isl_mat_extend(ss->samples, ss->samples->n_row + 1,
+						  ss->samples->n_col);
+	if (!ss->samples)
+		goto error;
+
+	isl_seq_cpy(ss->samples->row[ss->samples->n_row - 1],
+		    sample->el, sample->size);
+
+	isl_vec_free(sample);
+	return 0;
+error:
+	isl_vec_free(sample);
+	return -1;
+}
+
+static struct isl_mat *isl_basic_set_scan_samples(struct isl_basic_set *bset)
+{
+	isl_ctx *ctx;
+	unsigned dim;
+	struct scan_samples ss;
+
+	ctx = isl_basic_set_get_ctx(bset);
+	dim = isl_basic_set_total_dim(bset);
+	ss.callback.add = scan_samples_add_sample;
+	ss.samples = isl_mat_alloc(ctx, 0, 1 + dim);
+	if (!ss.samples)
+		goto error;
+
+	if (isl_basic_set_scan(bset, &ss.callback) < 0) {
+		isl_mat_free(ss.samples);
+		return NULL;
+	}
+
+	return ss.samples;
+error:
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+static struct isl_mat *isl_basic_set_samples(struct isl_basic_set *bset)
+{
+	struct isl_mat *T;
+	struct isl_mat *samples;
+
+	if (!bset)
+		return NULL;
+
+	if (bset->n_eq == 0)
+		return isl_basic_set_scan_samples(bset);
+
+	bset = isl_basic_set_remove_equalities(bset, &T, NULL);
+	samples = isl_basic_set_scan_samples(bset);
+	return isl_mat_product(samples, isl_mat_transpose(T));
+}
+
+int main(int argc, char **argv)
+{
+	struct isl_ctx *ctx = isl_ctx_alloc();
+	struct isl_basic_set *bset;
+	struct isl_mat *samples;
+
+	bset = isl_basic_set_read_from_file(ctx, stdin);
+	samples = isl_basic_set_samples(bset);
+	isl_mat_print_internal(samples, stdout, 0);
+	isl_mat_free(samples);
+	isl_ctx_free(ctx);
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/print.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/print.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/print.c (added)
+++ polly/trunk/lib/External/isl/print.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,100 @@
+#include <isl/ctx.h>
+#include <isl/id.h>
+#include <isl/space.h>
+#include <isl/local_space.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/union_set.h>
+#include <isl/union_map.h>
+#include <isl/polynomial.h>
+#include <isl/band.h>
+#include <isl/constraint.h>
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/printer.h>
+#include <isl/val.h>
+
+#undef BASE
+#define BASE id
+#include <print_templ.c>
+#undef BASE
+#define BASE val
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_val
+#include <print_templ.c>
+#undef BASE
+#define BASE space
+#include <print_templ.c>
+#undef BASE
+#define BASE local_space
+#include <print_templ.c>
+#undef BASE
+#define BASE basic_set
+#include <print_templ.c>
+#undef BASE
+#define BASE basic_map
+#include <print_templ.c>
+#undef BASE
+#define BASE set
+#include <print_templ.c>
+#undef BASE
+#define BASE map
+#include <print_templ.c>
+#undef BASE
+#define BASE union_set
+#include <print_templ.c>
+#undef BASE
+#define BASE union_map
+#include <print_templ.c>
+#undef BASE
+#define BASE qpolynomial
+#include <print_templ.c>
+#undef BASE
+#define BASE qpolynomial_fold
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_qpolynomial
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_qpolynomial_fold
+#include <print_templ.c>
+#undef BASE
+#define BASE union_pw_qpolynomial
+#include <print_templ.c>
+#undef BASE
+#define BASE union_pw_qpolynomial_fold
+#include <print_templ.c>
+#undef BASE
+#define BASE band
+#include <print_templ.c>
+#undef BASE
+#define BASE constraint
+#include <print_templ.c>
+#undef BASE
+#define BASE aff
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_multi_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE union_pw_multi_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_pw_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE point
+#include <print_templ.c>
+#undef BASE
+#define BASE ast_expr
+#include <print_templ.c>
+#undef BASE
+#define BASE ast_node
+#include <print_templ.c>

Added: polly/trunk/lib/External/isl/print_templ.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/print_templ.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/print_templ.c (added)
+++ polly/trunk/lib/External/isl/print_templ.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,33 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+void FN(TYPE,dump)(__isl_keep TYPE *obj)
+{
+	isl_printer *p;
+
+	if (!obj)
+		return;
+	p = isl_printer_to_file(FN(TYPE,get_ctx)(obj), stderr);
+	p = FN(isl_printer_print,BASE)(p, obj);
+	p = isl_printer_end_line(p);
+	isl_printer_free(p);
+}
+
+__isl_give char *FN(TYPE,to_str)(__isl_keep TYPE *obj)
+{
+	isl_printer *p;
+	char *s;
+
+	if (!obj)
+		return NULL;
+	p = isl_printer_to_str(FN(TYPE,get_ctx)(obj));
+	p = FN(isl_printer_print,BASE)(p, obj);
+	s = isl_printer_get_str(p);
+	isl_printer_free(p);
+
+	return s;
+}

Added: polly/trunk/lib/External/isl/test_inputs/affine.polylib
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/affine.polylib?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/affine.polylib (added)
+++ polly/trunk/lib/External/isl/test_inputs/affine.polylib Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+# the affine hull of {[a,b] : a=b && 1 <= a <= 163} ...
+3 4
+0 1 -1 0
+1 1  0 -1
+1 -1 0 163
+
+# ... is {[a,b] : a=b} (and not {[In_1,In_2]}, as Omega 1.2 claims)
+1 4
+0 1 -1 0

Added: polly/trunk/lib/External/isl/test_inputs/affine2.polylib
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/affine2.polylib?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/affine2.polylib (added)
+++ polly/trunk/lib/External/isl/test_inputs/affine2.polylib Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+5 5
+1 -2 0 1 0
+1 2 0 -1 1
+1 0 -2 1 0
+1 0 2 -1 1
+1 0 0 1 -1
+
+1 5
+0 1 -1 0 0

Added: polly/trunk/lib/External/isl/test_inputs/affine3.polylib
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/affine3.polylib?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/affine3.polylib (added)
+++ polly/trunk/lib/External/isl/test_inputs/affine3.polylib Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+3 4
+1 1 0 0
+1 -7 4 2
+1 5 -4 2
+
+1 4
+0 3 -2 0

Added: polly/trunk/lib/External/isl/test_inputs/application.omega
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/application.omega?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/application.omega (added)
+++ polly/trunk/lib/External/isl/test_inputs/application.omega Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{[x]}
+{[x] -> [y] : y = 2x}
+{[y]: Exists ( alpha : 2alpha = y)}

Added: polly/trunk/lib/External/isl/test_inputs/application2.omega
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/application2.omega?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/application2.omega (added)
+++ polly/trunk/lib/External/isl/test_inputs/application2.omega Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{[x] : x >= 0 && x <= 20 }
+{[x] -> [y] : y = 2x}
+{[y]: Exists ( alpha : 2alpha = y && 0 <= y && y <= 40)}

Added: polly/trunk/lib/External/isl/test_inputs/basicLinear.pwqp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/basicLinear.pwqp?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/basicLinear.pwqp (added)
+++ polly/trunk/lib/External/isl/test_inputs/basicLinear.pwqp Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+[P, Q] -> { [n, m] -> n : n >= 1 and m >= n and m <= P and m <= Q }

Added: polly/trunk/lib/External/isl/test_inputs/basicLinear2.pwqp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/basicLinear2.pwqp?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/basicLinear2.pwqp (added)
+++ polly/trunk/lib/External/isl/test_inputs/basicLinear2.pwqp Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+[P, Q] -> { [n, m] -> n : n >= 1 and m >= n and m <= P and n >= -1 + Q }

Added: polly/trunk/lib/External/isl/test_inputs/basicTest.pwqp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/basicTest.pwqp?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/basicTest.pwqp (added)
+++ polly/trunk/lib/External/isl/test_inputs/basicTest.pwqp Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+[p] -> { [n, m] -> (n + n^2) : n >= 1 and m >= n and m <= p }

Added: polly/trunk/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp (added)
+++ polly/trunk/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+[p] -> { [n, m] -> (n + n^3) : n >= -1 and m >= n and m <= p }

Added: polly/trunk/lib/External/isl/test_inputs/boulet.pip
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/boulet.pip?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/boulet.pip (added)
+++ polly/trunk/lib/External/isl/test_inputs/boulet.pip Wed Feb  4 14:55:43 2015
@@ -0,0 +1,13 @@
+0 3
+
+-1
+
+5 6
+1 1 -1  2 0 0
+1 0  1  1 4 20
+1 0 -1 -1 0 0
+1 0  1 -1 2 10
+1 0 -1  1 2 10
+
+Urs_parms
+Urs_unknowns

Added: polly/trunk/lib/External/isl/test_inputs/brisebarre.pip
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/brisebarre.pip?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/brisebarre.pip (added)
+++ polly/trunk/lib/External/isl/test_inputs/brisebarre.pip Wed Feb  4 14:55:43 2015
@@ -0,0 +1,34 @@
+# ---------------------- CONTEXT ----------------------
+1 2
+1    0
+
+-1
+
+# ----------------------- DOMAIN ----------------------
+26 6
+1    3    0    0     0    -98300
+1   -3    0    0     0     98308
+1  432   36    6     1 -14757611
+1 -432  -36   -6    -1  14758510
+1   54    9    3     1  -1923190
+1  -54   -9   -3    -1   1923303
+1   48   12    6     3  -1782238
+1  -48  -12   -6    -3   1782339
+1   27    9    6     4  -1045164
+1  -27   -9   -6    -4   1045221
+1  432  180  150   125 -17434139
+1 -432 -180 -150  -125  17435038
+1    6    3    3     3   -252443
+1   -6   -3   -3    -3    252456
+1  432  252  294   343 -18949275
+1 -432 -252 -294  -343  18950174
+1   27   18   24    32  -1234720
+1  -27  -18  -24   -32   1234777
+1   48   36   54    81  -2288453
+1  -48  -36  -54   -81   2288554
+1   54   45   75   125  -2684050
+1  -54  -45  -75  -125   2684163
+1  432  396  726  1331 -22386005
+1 -432 -396 -726 -1331  22386904
+1    3    3    6    12   -162072
+1   -3   -3   -6   -12    162080

Added: polly/trunk/lib/External/isl/test_inputs/cg1.pip
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/cg1.pip?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/cg1.pip (added)
+++ polly/trunk/lib/External/isl/test_inputs/cg1.pip Wed Feb  4 14:55:43 2015
@@ -0,0 +1,15 @@
+2 4
+  1  1  0 -1
+  1 -1  1  0
+
+-1
+
+8 7
+  1  0  1  0 -1  0  0
+  1  0 -1  0  1  0  0
+  1  1  0  0  0 -1  0
+  1 -1  0  0  0  1  0
+  1  0  1  0  0  0 -1
+  1  0 -1  0  0  1  0
+  1  0 -1  1  0  0 -1
+  1  0  0 -1  0  1  0

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+  if (c0 >= 1)
+    b(c0 - 1);
+  if (c0 <= 9)
+    a(c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ a[i] -> [i] : 0 <= i < 10; b[i] -> [i+1] : 0 <= i < 10 }
+{ : }
+{ [i] -> atomic[x] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = ((b0 + 32767) % 32768) + 1; c0 <= 65534; c0 += 32768)
+  A(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+# Check that isl properly handles atomic domains that are unions.
+[nn, b0] -> { A[a] -> [a, 0, b0] : exists (e0 = [(b0 - a)/32768]: 32768e0 = b0 - a and a >= 1 and b0 >= 0 and b0 <= 32767 and a <= 65534) }
+[nn, b0] -> { : b0 >= 0 and b0 <= 32767 }
+[nn, b0] -> { [a, b, c] -> atomic[2] : c >= 1; [a, 0, c] -> atomic[2] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= 64; c0 += 1) {
+  if (c0 >= 63) {
+    sync();
+  } else if (c0 >= 1) {
+    sync();
+  } else
+    sync();
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+# Check that isl is not confused by inconsistent
+# separation_class and atomic options.
+{ sync[] -> [i, 0] : 0 <= i <= 64 }
+{ : }
+{ [i, 0] -> separation_class[[1] -> [0]] : 1 <= i <= 62; [i, 0] -> atomic[1]}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 64; c0 += 1)
+  sync();

Added: polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/atomic4.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+# Check that isl is not confused by inconsistent separate and atomic options.
+{ sync[] -> [i, 0] : 0 <= i <= 64 }
+{ : }
+{ [i, 0] -> separate[1] : 1 <= i <= 62; [i, 0] -> atomic[1] : i <= 10 or i >= 20 }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1();

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[] -> [0] }
+{  :  }
+{ [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+if (M >= 0)
+  S1();

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[] -> [0] : M >= 0 }
+[M] -> {  :  }
+[M] -> { [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1();

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/0D-3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[] -> [0] : M >= 0 }
+[M] -> {  : M >= 0 }
+[M] -> { [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1(2 * M, M);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[2M, M] -> [2M, M, 0] }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1(2 * M, N + 2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/1point-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[2M, 2 + N] -> [2M, 2 + N, 0] }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,14 @@
+{
+  for (int c0 = m; c0 <= min(n, p - 1); c0 += 1)
+    S1(c0);
+  for (int c0 = p; c0 <= min(m - 1, q); c0 += 1)
+    S2(c0);
+  for (int c0 = max(m, p); c0 <= min(n, q); c0 += 1) {
+    S1(c0);
+    S2(c0);
+  }
+  for (int c0 = max(max(m, p), q + 1); c0 <= n; c0 += 1)
+    S1(c0);
+  for (int c0 = max(max(m, n + 1), p); c0 <= q; c0 += 1)
+    S2(c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/4-param.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[m, n, p, q] -> { S1[i0] -> [i0, 0] : i0 >= m and i0 <= n; S2[i0] -> [i0, 1] : i0 >= p and i0 <= q }
+[m, n, p, q] -> {  :  }
+[m, n, p, q] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/README
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/README?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/README (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/README Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+The tests in this directory have been adapted from the corresponding CLooG
+test cases.

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1(0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/backtrack.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[0] -> [0, 0] }
+{  :  }
+{ [i, j] -> atomic[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 2; c0 += 1)
+  S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= 2 }
+{  :  }
+{ [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1(0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[0] -> [0, 0] }
+{  :  }
+{ [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M; c0 += 1)
+  S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= M }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M + 1; c0 += 1)
+  S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= 1 + M }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1(1, floord(M + 1, 2));

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[1, i1] -> [1, i1, 0] : 2i1 >= M and 2i1 <= 1 + M }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+{
+  S1();
+  S3(0);
+  S2();
+  S3(1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S3[i0] -> [i0, 1] : i0 >= 0 and i0 <= 1; S1[] -> [0, 0]; S2[] -> [1, 0] }
+{  :  }
+{ [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+  S1(c0, 1);
+  S3(c0, 1);
+  S2(c0, 1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, 1] -> [i0, 1, 6] : i0 >= 0 and i0 <= 9; S2[i0, 1] -> [i0, 1, 11] : i0 >= 0 and i0 <= 9; S3[i0, 1] -> [i0, 1, 8] : i0 >= 0 and i0 <= 9 }
+{  :  }
+{ [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+{
+  S1();
+  for (int c0 = 0; c0 <= 1; c0 += 1)
+    S3(c0);
+  S2();
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/block3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S2[] -> [1]; S3[i0] -> [i0] : i0 >= 0 and i0 <= 1; S1[] -> [0] }
+{  :  }
+{ [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,18 @@
+{
+  for (int c0 = 2; c0 <= 3; c0 += 1)
+    for (int c1 = -c0 + 6; c1 <= 6; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 4; c0 <= 8; c0 += 1) {
+    if (c0 >= 6) {
+      S2(c0, -c0 + 9);
+    } else {
+      if (c0 == 4)
+        for (int c1 = 3; c1 <= 4; c1 += 1)
+          S1(4, c1);
+      S1(c0, -c0 + 9);
+      S2(c0, -c0 + 9);
+    }
+    for (int c1 = max(c0 - 1, -c0 + 10); c1 <= 6; c1 += 1)
+      S1(c0, c1);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, i1] -> [i0, i1, 0] : i1 >= 6 - i0 and i0 >= 2 and i1 >= 3 and i1 <= 6 and i1 >= -1 + i0; S2[i0, 9 - i0] -> [i0, 9 - i0, 1] : i0 <= 8 and i0 >= 4 }
+{  :  }
+{ [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  S1(c0);
+  for (int c2 = 1; c2 < c0; c2 += 1)
+    S2(c0, c2);
+  S3(c0);
+  for (int c2 = c0 + 1; c2 <= n; c2 += 1) {
+    S4(c0, c2);
+    for (int c4 = 1; c4 < c0; c4 += 1)
+      S5(c0, c2, c4);
+    S6(c0, c2);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S1[i0] -> [i0, 1, 0, 0, 0, 0] : i0 >= 1 and i0 <= n; S2[i0, i1] -> [i0, 2, i1, 1, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S6[i0, i1] -> [i0, 4, i1, 3, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [i0, 3, 0, 0, 0, 0] : i0 >= 1 and i0 <= n; S4[i0, i1] -> [i0, 4, i1, 1, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S5[i0, i1, i2] -> [i0, 4, i1, 2, i2, 1] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> {  :  }
+[n] -> { [i, j, k, l, m, n'] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,20 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1) {
+    S1(c1);
+    for (int c2 = c1 + 1; c2 <= M; c2 += 1)
+      S4(c1, c2);
+  }
+  for (int c0 = 1; c0 < 3 * M - 1; c0 += 3) {
+    S3((c0 + 2) / 3);
+    if (3 * M >= c0 + 8) {
+      for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1) {
+        S6((c0 + 2) / 3, c1);
+        for (int c4 = (c0 + 5) / 3; c4 < c1; c4 += 1)
+          S5(c4, c1, (c0 + 2) / 3);
+      }
+    } else if (c0 + 5 == 3 * M)
+      S6(M - 1, M);
+    for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1)
+      S2(c1, (c0 + 2) / 3);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [3i1, i0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0; S4[i0, i1] -> [0, i0, i1] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S1[i0] -> [0, i0, 0] : i0 >= 1 and i0 <= M; S6[i0, i1] -> [-1 + 3i0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S3[i0] -> [-2 + 3i0, 0, 0] : i0 >= 1 and i0 <= M; S5[i0, i1, i2] -> [-1 + 3i2, i1, i2] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 and i2 <= -1 + i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+for (int c0 = -N + 1; c0 <= N; c0 += 1) {
+  for (int c1 = max(0, c0 - 1); c1 < min(N, N + c0 - 1); c1 += 1)
+    S2(c1, -c0 + c1 + 1);
+  for (int c1 = max(0, c0); c1 < min(N, N + c0); c1 += 1)
+    S1(c1, -c0 + c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/christian.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[N] -> { S1[i0, i1] -> [i0 - i1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S2[i0, i1] -> [1 + i0 - i1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N }
+[N] -> {  :  }
+[N] -> { [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,86 @@
+{
+  if (m == 1) {
+    S1(0, 1, 1, 1);
+    S8(0, 1);
+  } else if (m >= 2) {
+    S1(0, 1, 1, 1);
+    S3(0, 1, 1, 2, 1, 1, 1, 2);
+    S4(0, 1, 2, 2, 1, 1, 2, 2);
+    S2(0, 1, 1, 1, 1, 1, 2, 1);
+    S8(0, 1);
+  }
+  for (int c0 = 1; c0 < 2 * m - 3; c0 += 1) {
+    if (c0 + 1 == m) {
+      S5(m - 2, 1, m - 1, 1, m - 1, 1, m, 1);
+      S1(m - 1, 1, m, 1);
+      S3(m - 1, 1, m, 2, m, 1, m, 2);
+    } else if (m >= c0 + 2) {
+      S5(c0 - 1, 1, c0, 1, c0, 1, c0 + 1, 1);
+      S1(c0, 1, c0 + 1, 1);
+      S3(c0, 1, c0 + 1, 2, c0 + 1, 1, c0 + 1, 2);
+      S4(c0, 1, c0 + 2, 2, c0 + 1, 1, c0 + 2, 2);
+      S2(c0, 1, c0 + 1, 1, c0 + 1, 1, c0 + 2, 1);
+    } else {
+      S5(c0 - 1, -m + c0 + 2, c0, -m + c0 + 2, m - 1, -m + c0 + 2, m, -m + c0 + 2);
+      S6(c0 - 1, -m + c0 + 1, c0, -m + c0 + 2, m, -m + c0 + 1, m, -m + c0 + 2);
+      S1(c0, -m + c0 + 2, m, -m + c0 + 2);
+      S3(c0, -m + c0 + 2, c0 + 1, -m + c0 + 3, m, -m + c0 + 2, m, -m + c0 + 3);
+    }
+    for (int c2 = max(2, -m + c0 + 3); c2 <= min(m - 1, c0); c2 += 1) {
+      S5(c0 - 1, c2, c0, c2, c0 - c2 + 1, c2, c0 - c2 + 2, c2);
+      S7(c0 - 1, c2 - 1, c0 + 1, c2, c0 - c2 + 2, c2 - 1, c0 - c2 + 3, c2);
+      S6(c0 - 1, c2 - 1, c0, c2, c0 - c2 + 2, c2 - 1, c0 - c2 + 2, c2);
+      S1(c0, c2, c0 - c2 + 2, c2);
+      S3(c0, c2, c0 + 1, c2 + 1, c0 - c2 + 2, c2, c0 - c2 + 2, c2 + 1);
+      S4(c0, c2, c0 + 2, c2 + 1, c0 - c2 + 2, c2, c0 - c2 + 3, c2 + 1);
+      S2(c0, c2, c0 + 1, c2, c0 - c2 + 2, c2, c0 - c2 + 3, c2);
+    }
+    if (c0 + 1 == m) {
+      S7(m - 2, m - 1, m, m, 1, m - 1, 2, m);
+      S6(m - 2, m - 1, m - 1, m, 1, m - 1, 1, m);
+      S1(m - 1, m, 1, m);
+      S2(m - 1, m, m, m, 1, m, 2, m);
+    } else if (c0 >= m) {
+      S5(c0 - 1, m, c0, m, -m + c0 + 1, m, -m + c0 + 2, m);
+      S7(c0 - 1, m - 1, c0 + 1, m, -m + c0 + 2, m - 1, -m + c0 + 3, m);
+      S6(c0 - 1, m - 1, c0, m, -m + c0 + 2, m - 1, -m + c0 + 2, m);
+      S1(c0, m, -m + c0 + 2, m);
+      S2(c0, m, c0 + 1, m, -m + c0 + 2, m, -m + c0 + 3, m);
+    } else {
+      S7(c0 - 1, c0, c0 + 1, c0 + 1, 1, c0, 2, c0 + 1);
+      S6(c0 - 1, c0, c0, c0 + 1, 1, c0, 1, c0 + 1);
+      S1(c0, c0 + 1, 1, c0 + 1);
+      S3(c0, c0 + 1, c0 + 1, c0 + 2, 1, c0 + 1, 1, c0 + 2);
+      S4(c0, c0 + 1, c0 + 2, c0 + 2, 1, c0 + 1, 2, c0 + 2);
+      S2(c0, c0 + 1, c0 + 1, c0 + 1, 1, c0 + 1, 2, c0 + 1);
+    }
+    for (int c8 = max(1, -m + c0 + 2); c8 <= min(m, c0 + 1); c8 += 1)
+      S8(c0, c8);
+  }
+  if (m >= 2) {
+    if (m >= 3) {
+      S5(2 * m - 4, m - 1, 2 * m - 3, m - 1, m - 1, m - 1, m, m - 1);
+      S6(2 * m - 4, m - 2, 2 * m - 3, m - 1, m, m - 2, m, m - 1);
+      S1(2 * m - 3, m - 1, m, m - 1);
+      S3(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
+      S5(2 * m - 4, m, 2 * m - 3, m, m - 2, m, m - 1, m);
+      S7(2 * m - 4, m - 1, 2 * m - 2, m, m - 1, m - 1, m, m);
+      S6(2 * m - 4, m - 1, 2 * m - 3, m, m - 1, m - 1, m - 1, m);
+      S1(2 * m - 3, m, m - 1, m);
+    } else {
+      S5(0, 1, 1, 1, 1, 1, 2, 1);
+      S1(1, 1, 2, 1);
+      S3(1, 1, 2, 2, 2, 1, 2, 2);
+      S7(0, 1, 2, 2, 1, 1, 2, 2);
+      S6(0, 1, 1, 2, 1, 1, 1, 2);
+      S1(1, 2, 1, 2);
+    }
+    S2(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
+    for (int c8 = m - 1; c8 <= m; c8 += 1)
+      S8(2 * m - 3, c8);
+    S5(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
+    S6(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
+    S1(2 * m - 2, m, m, m);
+    S8(2 * m - 2, m);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[m] -> { S2[i0, i1, 1 + i0, i1, 2 + i0 - i1, i1, 3 + i0 - i1, i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 3 - m + i0 and i1 >= 1; S4[i0, i1, 2 + i0, 1 + i1, 2 + i0 - i1, i1, 3 + i0 - i1, 1 + i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -4 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 3 - m + i0 and i1 >= 1; S5[i0, i1, 1 + i0, i1, 2 + i0 - i1, i1, 3 + i0 - i1, i1] -> [1 + i0, 0, i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 3 - m + i0 and i1 >= 1; S7[i0, i1, 2 + i0, 1 + i1, 2 + i0 - i1, i1, 3 + i0 - i1, 1 + i1] -> [1 + i0, 0, 1 + i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -4 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 3 - m + i0 and i1 >= 1; S6[i0, i1, 1 + i0, 1 + i1, 2 + i0 - i1, i1, 2 + i0 - i1, 1 + i1] -> [1 + i0, 0, 1 + i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 
 + i0 and i1 <= -1 + m and i1 >= 2 - m + i0 and i1 >= 1; S3[i0, i1, 1 + i0, 1 + i1, 2 + i0 - i1, i1, 2 + i0 - i1, 1 + i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 2 - m + i0 and i1 >= 1; S8[i0, i1] -> [i0, 1, 0, 0, 0, 0, 0] : i0 <= -2 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 2 - m + i0 and i1 >= 1; S1[i0, i1, 2 + i0 - i1, i1] -> [i0, 0, i1, 1, 0, 0, 0] : m >= 1 and i1 >= 2 - m + i0 and i1 <= 1 + i0 and i1 <= m and i1 >= 1 }
+[m] -> {  : m >= 0 }
+[m] -> { [i, j, k, l, m', n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(max(max(4, 5 * outerTimeTileScatter), 5 * outerProcTileScatter1), 5 * outerProcTileScatter2 + 1), 5 * outerProcTileScatter1 + 5 * outerProcTileScatter2 - N), 10 * outerProcTileScatter2 - N + 1), 10 * outerProcTileScatter1 - 2 * N + 2); c0 <= min(min(min(min(min(min(5 * outerTimeTileScatter + 4, 10 * outerProcTileScatter1 + 4), 5 * outerProcTileScatter1 + 5 * outerProcTileScatter2 + 5), 5 * outerProcTileScatter1 + M + 2), 2 * M + 2 * N - 6), 5 * outerProcTileScatter2 + M + N), 10 * outerProcTileScatter2 + N + 3); c0 += 1)
+  for (int c1 = max(max(max(max(5 * outerProcTileScatter1, 5 * outerProcTileScatter2 + 1), -5 * outerProcTileScatter2 + c0 - 1), -M + c0 + 2), (c0 + 1) / 2 + 2); c1 <= min(min(min(min(5 * outerProcTileScatter1 + 4, 5 * outerProcTileScatter2 + N + 2), -5 * outerProcTileScatter2 + N + c0), c0), N + c0 / 2 - 1); c1 += 1)
+    for (int c2 = max(max(5 * outerProcTileScatter2, -N + c1 + 2), c0 - c1 + 3); c2 <= min(min(5 * outerProcTileScatter2 + 4, c1 - 1), N + c0 - c1); c2 += 1)
+      S1(c0 - c1 + 1, -c0 + c1 + c2 - 2, c1 - c2, c0, c1, c2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { S1[i0, i1, i2, 2i0 + i1 + i2, 1 + i0 + i1 + i2, 1 + i0 + i1] -> [2i0 + i1 + i2, 1 + i0 + i1 + i2, 1 + i0 + i1] : N >= 3 and i2 <= 3 + 5outerProcTileScatter1 - i0 - i1 and i1 >= -1 + 5outerProcTileScatter2 - i0 and M >= 2 and i2 <= 4 + 5outerTimeTileScatter - 2i0 - i1 and i1 <= 3 + 5outerProcTileScatter2 - i0 and i2 >= 1 and i2 <= -2 + N and i1 >= 1 and i1 <= -2 + N and i0 >= 1 and i0 <= -1 + M and i2 >= 5outerTimeTileScatter - 2i0 - i1 and i2 >= -1 + 5outerProcTileScatter1 - i0 - i1 }
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> {  :  }
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,18 @@
+{
+  for (int c1 = 0; c1 <= min(1023, M + 1024); c1 += 1) {
+    S1(c1);
+    S3(c1);
+  }
+  for (int c1 = max(0, M + 1025); c1 <= 1023; c1 += 1) {
+    S2(c1);
+    S3(c1);
+  }
+  for (int c0 = 0; c0 <= min(1023, M + 1024); c0 += 1) {
+    S4(c0);
+    S6(c0);
+  }
+  for (int c0 = max(0, M + 1025); c0 <= 1023; c0 += 1) {
+    S5(c0);
+    S6(c0);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constant.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S5[i0] -> [i0, 0, 1] : i0 >= 0 and i0 <= 1023 and i0 >= 1025 + M; S1[i0] -> [-1, i0, 0] : i0 >= 0 and i0 <= 1023 and i0 <= 1024 + M; S3[i0] -> [-1, i0, 2] : i0 >= 0 and i0 <= 1023; S2[i0] -> [-1, i0, 1] : i0 >= 0 and i0 <= 1023 and i0 >= 1025 + M; S4[i0] -> [i0, 0, 0] : i0 >= 0 and i0 <= 1023 and i0 <= 1024 + M; S6[i0] -> [i0, 0, 2] : i0 >= 0 and i0 <= 1023 }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= 199; c0 += 1) {
+  for (int c2 = 50 * c0; c2 <= 50 * c0 + 24; c2 += 1)
+    for (int c3 = 0; c3 <= c2; c3 += 1)
+      S1(c0, c2, c3);
+  for (int c2 = 50 * c0 + 25; c2 <= 50 * c0 + 49; c2 += 1)
+    for (int c3 = 0; c3 <= c2; c3 += 1)
+      S2(c0, c2, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/constbound.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S2[i0, i1, i2] -> [i0, 1, i1, i2] : i1 >= 0 and i1 <= 9999 and i2 >= 0 and i2 <= i1 and i1 >= 25 + 50i0 and i1 <= 49 + 50i0; S1[i0, i1, i2] -> [i0, 0, i1, i2] : i1 >= 0 and i1 <= 9999 and i2 >= 0 and i2 <= i1 and i1 >= 50i0 and i1 <= 24 + 50i0 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,14 @@
+for (int c0 = -n + 1; c0 <= n; c0 += 1) {
+  if (c0 <= 0)
+    for (int c2 = -c0 + 4; c2 <= 2 * n - c0 + 2; c2 += 2)
+      S1(1, -c0 + 1, ((c0 + c2) / 2) - 1);
+  for (int c1 = max(c0 + 2, -c0 + 4); c1 <= min(2 * n - c0, 2 * n + c0); c1 += 2) {
+    for (int c2 = c1 + 2; c2 <= 2 * n + c1; c2 += 2)
+      S1((c0 + c1) / 2, (-c0 + c1) / 2, (-c1 + c2) / 2);
+    for (int c2 = 1; c2 <= n; c2 += 1)
+      S2(((c0 + c1) / 2) - 1, (-c0 + c1) / 2, c2);
+  }
+  if (c0 >= 1)
+    for (int c2 = 1; c2 <= n; c2 += 1)
+      S2(n, n - c0 + 1, c2);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/darte.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [1 + i0 - i1, 2 + i0 + i1, i2] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= n and i2 >= 1 and i2 <= n; S1[i0, i1, i2] -> [i0 - i1, i0 + i1, i0 + i1 + 2i2] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= n and i2 >= 1 and i2 <= n }
+[n] -> {  :  }
+[n] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,12 @@
+{
+  for (int c0 = 0; c0 <= min(T_2 - 1, T_66); c0 += 1) {
+    S1(c0);
+    S2(c0);
+  }
+  for (int c0 = T_2; c0 <= min(T_67 - 1, T_66); c0 += 1)
+    S2(c0);
+  for (int c0 = max(0, T_66 + 1); c0 < T_2; c0 += 1)
+    S1(c0);
+  if (T_2 == 0 && T_67 == 0)
+    S1(0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dealII.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[T_2, T_67, T_66] -> { S1[scat_0] -> [scat_0, 0] : (scat_0 <= -1 + T_2 and scat_0 >= 0) or (scat_0 <= -T_67 and scat_0 >= 0); S2[scat_0] -> [scat_0, 1] : (scat_0 <= -1 + T_2 and scat_0 >= 0 and scat_0 <= T_66) or (scat_0 <= -1 + T_67 and scat_0 >= 0 and scat_0 <= T_66) }
+[T_2, T_67, T_66] -> {  : T_2 <= 4 and T_2 >= 0 and T_67 <= 4 and T_67 >= 0 }
+[T_2, T_67, T_66] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+for (int c1 = 1; c1 <= 10; c1 += 1) {
+  for (int c3 = 1; c3 <= c1; c3 += 1)
+    S1(c1, c3);
+  for (int c3 = 11; c3 <= M; c3 += 1)
+    S2(c1, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= 10 and i1 >= 11 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= 10 and i1 >= 1 and i1 <= i0 }
+[M] -> {  : M >= 20 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S1(0, c1);
+  for (int c0 = 1; c0 <= N; c0 += 1)
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[0, i1] -> [0, i1, 0] : i1 <= M and N >= 0 and i1 >= 1; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i1 <= M and i0 <= N and i1 >= 1 }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,12 @@
+{
+  for (int c0 = 1; c0 <= min(M, N); c0 += 1) {
+    S1(c0);
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+  }
+  for (int c0 = N + 1; c0 <= M; c0 += 1)
+    S1(c0);
+  for (int c0 = M + 1; c0 <= N; c0 += 1)
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/dot2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0, 0, 0] : i0 >= 1 and i0 <= M }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,23 @@
+{
+  S4(1, 0, 0);
+  S7(1, 0, 0);
+  S8(1, 0, 3);
+  for (int c0 = 2; c0 <= 9; c0 += 1) {
+    S2(c0, -7, 0);
+    for (int c1 = -7; c1 < c0 - 8; c1 += 1)
+      S3(c0, c1, 1);
+    S6(c0, c0 - 9, 2);
+    S8(c0, 0, 3);
+    for (int c1 = 1; c1 < c0; c1 += 1)
+      S5(c0, c1, 3);
+  }
+  S2(10, -7, 0);
+  for (int c1 = -7; c1 <= 1; c1 += 1)
+    S3(10, c1, 1);
+  S6(10, 1, 2);
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    S5(10, c1, 3);
+    S1(10, c1, 4);
+  }
+  S1(10, 10, 4);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S5[i0, i1, 3] -> [i0, i1, 3, 4] : i1 <= -1 + i0 and i0 <= 10 and i1 >= 1; S8[i0, 0, 3] -> [i0, 0, 3, 7] : i0 >= 1 and i0 <= 9; S2[i0, -7, 0] -> [i0, -7, 0, 1] : i0 >= 2 and i0 <= 10; S3[i0, i1, 1] -> [i0, i1, 1, 2] : i1 >= -7 and i0 <= 10 and i1 <= -9 + i0; S1[10, i1, 4] -> [10, i1, 4, 0] : i1 >= 1 and i1 <= 10; S7[1, 0, 0] -> [1, 0, 0, 6]; S4[1, 0, 0] -> [1, 0, 0, 3]; S6[i0, -9 + i0, 2] -> [i0, -9 + i0, 2, 5] : i0 >= 2 and i0 <= 10 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  S1(c0);
+  for (int c1 = 1; c1 <= m; c1 += 1)
+    S2(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/emploi.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [i0, 0, 0] : (i0 >= 1 and i0 <= n and i0 <= 2m) or (i0 >= 1 and i0 <= n and i0 >= m); S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= m }
+[m, n] -> {  :  }
+[m, n] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 <= 5; c0 += 1)
+  for (int c1 = c0 <= 2 ? 2 * c0 : 4; c1 <= (c0 >= 2 ? 2 * c0 : 4); c1 += 1) {
+    if (c1 == 2 * c0)
+      S1(c0, 2 * c0);
+    if (c1 == 4)
+      S2(c0, 4);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, 2i0] -> [i0, 2i0, 0] : i0 >= 0 and i0 <= 5; S2[i0, 4] -> [i0, 4, 1] : i0 >= 0 and i0 <= 5 }
+{  :  }
+{ [i, j, k] -> atomic[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= 10000; c0 += 1)
+  for (int c1 = 1000; c1 <= 1016; c1 += 1)
+    for (int c2 = 1; c2 < 2 * c1 - 1998; c2 += 1) {
+      if (c1 <= 1008 && c2 + 1999 == 2 * c1)
+        S2(c0, c1, 2 * c1 - 1999, 1, c0, 2 * c1 - 1000, 1, 2, c0, c1 - 499, 2 * c1 - 1999, c0, 2 * c1 - 1999, c1 - 999, c1 - 999);
+      if (c2 == 1 && c1 % 2 == 0)
+        S1(c0, c1, 1, 2, c0, (c1 / 2) + 1, c1 - 999, c0, c1 - 999, (c1 / 2) - 499, (c1 / 2) - 499);
+    }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/equality2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, i1, 1, 2, i0, i5, -999 + i1, i0, -999 + i1, i9, i10] -> [i0, i1, 1, 2, i0, n, -999 + i1, i0, -999 + i1, r, s, 0, 0, 0, 0, 0] : 2s = -998 + i1 and 2n = 2 + i1 and 2i10 = -998 + i1 and 2i5 = 2 + i1 and 2i9 = -998 + i1 and 2r = -998 + i1 and i0 >= 1 and i0 <= 10000 and i1 >= 1000 and i1 <= 1016; S2[i0, i1, -1999 + 2i1, 1, i0, -1000 + 2i1, 1, 2, i0, -499 + i1, -1999 + 2i1, i0, -1999 + 2i1, -999 + i1, -999 + i1] -> [i0, i1, -1999 + 2i1, 1, i0, -1000 + 2i1, 1, 2, i0, -499 + i1, -1999 + 2i1, i0, -1999 + 2i1, -999 + i1, -999 + i1, 1] : i0 >= 1 and i0 <= 10000 and i1 >= 1000 and i1 <= 1008 }
+{  :  }
+{ [i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x] -> atomic[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= m; c0 += 1) {
+  S1(c0);
+  for (int c1 = 1; c1 <= n; c1 += 1)
+    S2(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/esced.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n, m] -> { S1[i0] -> [i0, 0, 0] : i0 >= 1 and i0 <= m; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= m and i1 >= 1 and i1 <= n }
+[n, m] -> {  :  }
+[n, m] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,15 @@
+{
+  for (int c0 = 0; c0 <= 14; c0 += 1)
+    for (int c1 = 0; c1 < n - 14; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 15; c0 <= n; c0 += 1) {
+    for (int c1 = 0; c1 <= 9; c1 += 1)
+      S1(c0, c1);
+    for (int c1 = 10; c1 < n - 14; c1 += 1) {
+      S1(c0, c1);
+      S2(c0, c1);
+    }
+    for (int c1 = n - 14; c1 <= n; c1 += 1)
+      S2(c0, c1);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/ex1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 15 and i0 <= n and i1 >= 10 and i1 <= n; S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= -15 + n }
+[n] -> {  : n >= 25 }
+[n] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,155 @@
+{
+  for (int c0 = 0; c0 <= 36; c0 += 1) {
+    for (int c1 = -6; c1 < c0 / 14 - 5; c1 += 1) {
+      for (int c2 = -((-2 * c1 + 3) / 5) + 9; c2 <= c1 + 12; c2 += 1)
+        S6(c0, c1, c2);
+      for (int c2 = c1 + 24; c2 <= -2 * c1 + 24; c2 += 1)
+        S2(c0, c1, c2);
+      for (int c2 = -2 * c1 + 30; c2 <= c1 + 48; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    for (int c1 = c0 / 14 - 5; c1 < 0; c1 += 1) {
+      if (c1 >= -3 && 2 * c0 >= 7 * c1 + 42)
+        S7(c0, c1, 6);
+      for (int c2 = max(c1 - (6 * c0 + 77) / 77 + 13, -((-2 * c1 + 3) / 5) + 9); c2 <= c1 + 12; c2 += 1)
+        S6(c0, c1, c2);
+      for (int c2 = c1 - (3 * c0 + 14) / 14 + 49; c2 <= c1 + 48; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    S3(c0, 0, 0);
+    S10(c0, 0, 0);
+    for (int c2 = 1; c2 <= 5; c2 += 1)
+      S3(c0, 0, c2);
+    for (int c2 = 6; c2 <= 2 * c0 / 21 + 4; c2 += 1) {
+      S3(c0, 0, c2);
+      S7(c0, 0, c2);
+    }
+    for (int c2 = max(6, 2 * c0 / 21 + 5); c2 <= -((6 * c0 + 77) / 77) + 12; c2 += 1)
+      S3(c0, 0, c2);
+    for (int c2 = -((6 * c0 + 77) / 77) + 13; c2 <= 12; c2 += 1) {
+      S3(c0, 0, c2);
+      S6(c0, 0, c2);
+    }
+    for (int c2 = 13; c2 <= 24; c2 += 1)
+      S3(c0, 0, c2);
+    for (int c2 = -((3 * c0 + 14) / 14) + 49; c2 <= 48; c2 += 1)
+      S1(c0, 0, c2);
+    for (int c1 = 1; c1 <= 18; c1 += 1) {
+      for (int c2 = -8 * c1; c2 <= min(6, -8 * c1 + 24); c2 += 1)
+        S3(c0, c1, c2);
+      if (c1 == 2) {
+        S3(c0, 2, 7);
+      } else if (c0 >= 35 && c1 == 1) {
+        S3(c0, 1, 7);
+        S7(c0, 1, 7);
+      } else if (c0 <= 34 && c1 == 1)
+        S3(c0, 1, 7);
+      for (int c2 = 8; c2 <= min(-8 * c1 + 24, c1 - (6 * c0 + 77) / 77 + 12); c2 += 1)
+        S3(c0, c1, c2);
+      for (int c2 = max(-8 * c1 + 25, c1 - (6 * c0 + 77) / 77 + 13); c2 <= c1 + 12; c2 += 1)
+        S6(c0, c1, c2);
+      if (c1 == 1) {
+        for (int c2 = -((6 * c0 + 77) / 77) + 14; c2 <= 13; c2 += 1) {
+          S3(c0, 1, c2);
+          S6(c0, 1, c2);
+        }
+        for (int c2 = 14; c2 <= 16; c2 += 1)
+          S3(c0, 1, c2);
+      }
+      for (int c2 = c1 - (3 * c0 + 14) / 14 + 49; c2 <= c1 + 48; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    for (int c1 = 19; c1 <= 24; c1 += 1) {
+      for (int c2 = -8 * c1; c2 <= -8 * c1 + 24; c2 += 1)
+        S3(c0, c1, c2);
+      for (int c2 = c1 - (6 * c0 + 77) / 77 + 13; c2 <= 30; c2 += 1)
+        S6(c0, c1, c2);
+    }
+  }
+  for (int c0 = 37; c0 <= 218; c0 += 1) {
+    for (int c1 = (c0 + 5) / 14 - 8; c1 < min(0, c0 / 14 - 5); c1 += 1) {
+      if (c0 <= 46 && c1 == -3)
+        S7(c0, -3, 6);
+      if (-77 * ((-3 * c1 + 1) / 5) + 447 >= 6 * c0)
+        S6(c0, c1, -((-2 * c1 + 3) / 5) + 9);
+      for (int c2 = c1 + 24; c2 <= -2 * c1 + 24; c2 += 1)
+        S2(c0, c1, c2);
+      for (int c2 = -2 * c1 + 30; c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    if (c0 <= 148)
+      for (int c1 = max(0, (c0 + 5) / 14 - 8); c1 < c0 / 14 - 5; c1 += 1) {
+        if (c1 == 0)
+          S2(c0, 0, 24);
+        for (int c2 = max(c1 + 24, -2 * c1 + 30); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+          S1(c0, c1, c2);
+      }
+    if (c0 >= 79 && c0 % 14 >= 9) {
+      for (int c2 = max((c0 - 70) / 14 + 24, (c0 - 70) / 14 - (3 * c0 + 14) / 14 + 49); c2 <= (c0 - 70) / 14 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+        S1(c0, c0 / 14 - 5, c2);
+    } else if (c0 <= 69 && c0 % 14 >= 9) {
+      if (c0 <= 41)
+        S7(c0, -3, 6);
+      S6(c0, c0 / 14 - 5, 8);
+      for (int c2 = -((-c0 + 83) / 14) - (3 * c0 + 14) / 14 + 49; c2 <= -((-c0 + 83) / 14) - (3 * c0 + 17) / 14 + 56; c2 += 1)
+        S1(c0, c0 / 14 - 5, c2);
+    }
+    for (int c1 = (c0 + 5) / 14 - 5; c1 < 0; c1 += 1) {
+      if (7 * c1 + 114 >= 2 * c0)
+        S7(c0, c1, 6);
+      for (int c2 = max(8, c1 - (6 * c0 + 77) / 77 + 13); c2 <= c1 - (6 * c0 + 91) / 77 + 15; c2 += 1)
+        S6(c0, c1, c2);
+      for (int c2 = c1 - (3 * c0 + 14) / 14 + 49; c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    for (int c1 = max(0, (c0 + 5) / 14 - 5); c1 < c0 / 14 - 2; c1 += 1) {
+      for (int c2 = max(c1, -2 * c1 + 6); c2 <= min(-2 * c1 + 24, (2 * c0 - 7 * c1 - 10) / 21 + 1); c2 += 1)
+        S9(c0, c1, c2);
+      if (c1 >= 1 && c1 <= 6 && 14 * c1 + 46 >= c0)
+        S9(c0, c1, c1 + 5);
+      for (int c2 = max(c1 + 6, (2 * c0 - 7 * c1 - 10) / 21 + 2); c2 <= (2 * c1 + 1) / 5 + 7; c2 += 1) {
+        S7(c0, c1, c2);
+        S9(c0, c1, c2);
+      }
+      if (c1 <= 3 && 7 * c1 + 21 * ((2 * c1 + 41) / 5) >= 2 * c0 + 12)
+        S9(c0, c1, (2 * c1 + 1) / 5 + 8);
+      for (int c2 = (2 * c1 + 1) / 5 + 9; c2 <= c1 - (6 * c0 + 91) / 77 + 15; c2 += 1) {
+        S6(c0, c1, c2);
+        S9(c0, c1, c2);
+      }
+      for (int c2 = max(max(c1 + 6, c1 - (6 * c0 + 91) / 77 + 16), (2 * c0 - 7 * c1 - 10) / 21 + 2); c2 <= -2 * c1 + 24; c2 += 1)
+        S9(c0, c1, c2);
+      for (int c2 = max(c1, -2 * c1 + 30); c2 <= min(c1 + 24, c1 - (3 * c0 + 17) / 14 + 47); c2 += 1)
+        S8(c0, c1, c2);
+      for (int c2 = max(c1 + 24, c1 - (3 * c0 + 14) / 14 + 49); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    for (int c1 = c0 / 14 - 2; c1 <= 18; c1 += 1) {
+      for (int c2 = c1 + 6; c2 <= min((2 * c1 + 1) / 5 + 7, floord(2 * c0 - 7 * c1, 21) + 4); c2 += 1)
+        S7(c0, c1, c2);
+      for (int c2 = max(6, (c0 + 5) / 14 + 1); c2 <= min(min(c1, c0 / 14 + 3), -c1 + c1 / 2 + 18); c2 += 1)
+        S5(c0, c1, c2);
+      for (int c2 = max(max(c1 + 6, c1 - (6 * c0 + 77) / 77 + 13), (2 * c1 + 1) / 5 + 9); c2 <= c1 - (6 * c0 + 91) / 77 + 15; c2 += 1)
+        S6(c0, c1, c2);
+      for (int c2 = max(c1 + (3 * c0 + 3) / 14 - 40, -c1 + (c1 + 1) / 2 + 21); c2 <= min(c1, c1 + 3 * c0 / 14 - 33); c2 += 1)
+        S4(c0, c1, c2);
+      for (int c2 = max(c1, c1 - (3 * c0 + 14) / 14 + 40); c2 <= min(c1 + 24, c1 - (3 * c0 + 17) / 14 + 47); c2 += 1)
+        S8(c0, c1, c2);
+      for (int c2 = max(c1 + 24, c1 - (3 * c0 + 14) / 14 + 49); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+        S1(c0, c1, c2);
+    }
+    for (int c1 = 19; c1 <= 24; c1 += 1) {
+      for (int c2 = max(c1 - 12, (c0 + 5) / 14 + 1); c2 <= min(c0 / 14 + 3, -c1 + c1 / 2 + 18); c2 += 1)
+        S5(c0, c1, c2);
+      for (int c2 = max(max(c1 - 12, c1 + (3 * c0 + 3) / 14 - 40), -c1 + (c1 + 1) / 2 + 21); c2 <= min(c1, c1 + 3 * c0 / 14 - 33); c2 += 1)
+        S4(c0, c1, c2);
+      for (int c2 = max(c1 + 6, c1 - (6 * c0 + 77) / 77 + 13); c2 <= min(30, c1 - (6 * c0 + 91) / 77 + 15); c2 += 1)
+        S6(c0, c1, c2);
+      for (int c2 = max(c1, c1 - (3 * c0 + 14) / 14 + 40); c2 <= min(c1 + 24, c1 - (3 * c0 + 17) / 14 + 47); c2 += 1)
+        S8(c0, c1, c2);
+    }
+    for (int c1 = 25; c1 <= min(42, -((3 * c0 + 17) / 14) + 71); c1 += 1)
+      for (int c2 = max(c1 - 12, c1 + (3 * c0 + 3) / 14 - 40); c2 <= min(min(30, c1), c1 + 3 * c0 / 14 - 33); c2 += 1)
+        S4(c0, c1, c2);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S5[idx4, idx5, idx6] -> [idx4, idx5, idx6, 4] : 14idx6 <= 42 + idx4 and 14idx6 >= 6 + idx4 and idx6 <= idx5 and idx6 >= -12 + idx5 and idx6 >= 6 and idx6 <= 30 and 2idx6 <= 36 - idx5; S8[idx4, idx5, idx6] -> [idx4, idx5, idx6, 7] : 14idx6 >= 546 - 3idx4 + 14idx5 and 14idx6 <= 654 - 3idx4 + 14idx5 and idx6 >= idx5 and idx6 <= 24 + idx5 and idx5 >= 0 and idx5 <= 24 and idx6 >= 30 - 2idx5; S2[idx4, idx5, idx6] -> [idx4, idx5, idx6, 1] : 14idx5 <= -84 + idx4 and 14idx5 >= -120 + idx4 and idx6 >= 24 + idx5 and idx6 <= 48 + idx5 and idx5 >= -6 and idx5 <= 18 and idx6 <= 24 - 2idx5; S10[idx4, idx5, idx6] -> [idx4, idx5, idx6, 9] : 7idx6 <= idx4 - 28idx5 and 7idx6 >= -36 + idx4 - 28idx5 and idx6 >= idx5 and idx6 <= 24 + idx5 and idx5 >= 0 and idx5 <= 24 and idx6 <= -2idx5; S3[idx4, idx5, idx6] -> [idx4, idx5, idx6, 2] : idx4 >= 0 and idx4 <= 36 and idx6 >= -8idx5 and idx6 <= 24 - 8idx5 and idx5 >= 0 and idx5 <= 24; S1[idx4, idx5, idx6] -> [idx4, idx5, idx6, 0] : 14idx6 >= 672 - 3idx4 + 14
 idx5 and 14idx6 <= 780 - 3idx4 + 14idx5 and idx6 >= 24 + idx5 and idx6 <= 48 + idx5 and idx5 >= -6 and idx5 <= 18 and idx6 >= 30 - 2idx5; S7[idx4, idx5, idx6] -> [idx4, idx5, idx6, 6] : 21idx6 <= 84 + 2idx4 - 7idx5 and 21idx6 >= 12 + 2idx4 - 7idx5 and idx6 <= 12 + idx5 and idx6 >= 6 + idx5 and idx6 >= 6 and idx6 <= 30 and 5idx6 <= 36 + 2idx5; S9[idx4, idx5, idx6] -> [idx4, idx5, idx6, 8] : 14idx5 <= -42 + idx4 and 14idx5 >= -78 + idx4 and idx6 >= idx5 and idx6 <= 24 + idx5 and idx5 >= 0 and idx5 <= 24 and idx6 <= 24 - 2idx5 and idx6 >= 6 - 2idx5; S4[idx4, idx5, idx6] -> [idx4, idx5, idx6, 3] : 14idx6 <= -462 + 3idx4 + 14idx5 and 14idx6 >= -570 + 3idx4 + 14idx5 and idx6 <= idx5 and idx6 >= -12 + idx5 and idx6 >= 6 and idx6 <= 30 and 2idx6 >= 42 - idx5; S6[idx4, idx5, idx6] -> [idx4, idx5, idx6, 5] : 77idx6 >= 924 - 6idx4 + 77idx5 and 77idx6 <= 1140 - 6idx4 + 77idx5 and idx6 <= 12 + idx5 and idx6 >= 6 + idx5 and idx6 >= 6 and idx6 <= 30 and 5idx6 >= 42 + 2idx5 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+{
+  S3(1, 1);
+  for (int c0 = 2; c0 <= M; c0 += 1) {
+    S1(c0, 1);
+    for (int c1 = 2; c1 < c0; c1 += 1)
+      S2(c0, c1);
+    S4(c0, c0);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i1 <= -1 + i0 and i1 >= 2 and i0 <= M; S4[i0, i0] -> [i0, i0, 3] : M >= 3 and i0 <= M and i0 >= 2; S1[i0, 1] -> [i0, 1, 0] : M >= 3 and i0 <= M and i0 >= 2; S3[1, 1] -> [1, 1, 2] : M >= 3 }
+[M] -> {  : M >= 3 }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+{
+  S3(1, 0);
+  for (int c2 = 2; c2 <= M; c2 += 1)
+    S1(1, 1, c2);
+  for (int c0 = 2; c0 <= M; c0 += 1) {
+    S4(c0, 0);
+    for (int c2 = c0 + 1; c2 <= M; c2 += 1)
+      S2(c0, 1, c2);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[1, 1, i2] -> [1, 1, i2, 0] : M >= 3 and i2 <= M and i2 >= 2; S2[i0, 1, i2] -> [i0, 1, i2, 1] : i2 >= 1 + i0 and i0 >= 2 and i2 <= M; S4[i0, 0] -> [i0, 0, 0, 3] : i0 >= 2 and M >= 3 and i0 <= M; S3[1, 0] -> [1, 0, 0, 2] : M >= 3 }
+[M] -> {  : M >= 3 }
+[M] -> { [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,17 @@
+{
+  S3(2, 1);
+  S1(3, 1);
+  for (int c0 = 4; c0 <= M + 1; c0 += 1) {
+    S1(c0, 1);
+    for (int c1 = 2; c1 < (c0 + 1) / 2; c1 += 1)
+      S2(c0, c1);
+    if (c0 % 2 == 0)
+      S4(c0, c0 / 2);
+  }
+  for (int c0 = M + 2; c0 <= 2 * M; c0 += 1) {
+    for (int c1 = -M + c0; c1 < (c0 + 1) / 2; c1 += 1)
+      S2(c0, c1);
+    if (c0 % 2 == 0)
+      S4(c0, c0 / 2);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : 2i1 <= -1 + i0 and i1 >= 2 and i1 >= -M + i0; S4[i0, i1] -> [i0, j, 3] : 2j = i0 and 2i1 = i0 and M >= 3 and i0 <= 2M and i0 >= 4; S1[i0, 1] -> [i0, 1, 0] : M >= 3 and i0 <= 1 + M and i0 >= 3; S3[2, 1] -> [2, 1, 2] : M >= 3 }
+[M] -> {  : M >= 3 }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 < M; c0 += 1)
+  for (int c1 = c0 + 1; c1 <= M; c1 += 1) {
+    for (int c3 = c0 + 1; c3 <= M; c3 += 1)
+      S2(c0, c3, c1);
+    for (int c3 = 1; c3 < c0; c3 += 1)
+      S1(c0, c3, c1);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gauss.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [i0, i2] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S2[i0, i1, i2] -> [i0, i2] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 + i0 and i2 <= M }
+[M] -> {  :  }
+[M] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,16 @@
+{
+  for (int c0 = 1; c0 <= N; c0 += 1)
+    S1(c0);
+  for (int c0 = N + 1; c0 <= 2 * N; c0 += 1)
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S2(c1, -N + c0);
+  for (int c0 = 2 * N + 1; c0 <= M + N; c0 += 1) {
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S3(c1, -2 * N + c0);
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S2(c1, -N + c0);
+  }
+  for (int c0 = M + N + 1; c0 <= M + 2 * N; c0 += 1)
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S3(c1, -2 * N + c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S3[i0, i1] -> [2N + i1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S2[i0, i1] -> [N + i1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0] : i0 >= 1 and i0 <= N }
+[M, N] -> {  : N <= M and M >= 2 and N >= 2 }
+[M, N] -> { [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,20 @@
+{
+  for (int c0 = 1; c0 <= 4; c0 += 1)
+    for (int c1 = 5; c1 < M - 9; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 5; c0 < M - 9; c0 += 1) {
+    for (int c1 = -c0 + 1; c1 <= 4; c1 += 1)
+      S2(c0 + c1, c0);
+    for (int c1 = 5; c1 <= min(M - 10, M - c0); c1 += 1) {
+      S1(c0, c1);
+      S2(c0 + c1, c0);
+    }
+    for (int c1 = M - c0 + 1; c1 < M - 9; c1 += 1)
+      S1(c0, c1);
+    for (int c1 = M - 9; c1 <= M - c0; c1 += 1)
+      S2(c0 + c1, c0);
+  }
+  for (int c0 = M - 9; c0 <= M; c0 += 1)
+    for (int c1 = 5; c1 < M - 9; c1 += 1)
+      S1(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, i1] : i0 >= 1 and i0 <= M and i1 >= 5 and i1 <= -10 + M; S2[i0, i1] -> [i1, i0 - i1] : i0 >= 1 and i0 <= M and i1 >= 5 and i1 <= -10 + M }
+[M] -> {  : M >= 16 }
+[M] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+{
+  for (int c0 = M + 1; c0 <= 2 * M; c0 += 1)
+    S1(-M + c0);
+  for (int c0 = 2 * M + 1; c0 <= M + N; c0 += 1) {
+    S2(-2 * M + c0);
+    S1(-M + c0);
+  }
+  for (int c0 = M + N + 1; c0 <= 2 * M + N; c0 += 1)
+    S2(-2 * M + c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/gesced3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0] -> [2M + i0] : i0 >= 1 and i0 <= N; S1[i0] -> [M + i0] : i0 >= 1 and i0 <= N }
+[M, N] -> {  : N >= M and M >= 2 }
+[M, N] -> { [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+{
+  for (int c0 = 1; c0 <= N; c0 += 1)
+    S1(c0);
+  for (int c0 = N + 1; c0 <= 2 * N; c0 += 1)
+    S2(c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/guide.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [i0, 0] : (i0 >= 1 and i0 <= N and i0 <= 2M) or (i0 >= 1 and i0 <= N and i0 >= M); S2[i0] -> [i0, 1] : i0 >= 1 + N and i0 <= 2N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+  S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [i0, 0] : (i0 >= 1 and i0 <= n and i0 >= m) or (i0 >= 1 and i0 <= n and i0 <= 2m) }
+[m, n] -> {  :  }
+[m, n] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S1(c0, c1);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/iftest2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : (i0 >= 1 and i0 <= N and i0 >= M and i1 >= 1 and i1 <= M) or (i0 >= 1 and i0 <= N and i0 <= 2M and i1 >= 1 and i1 <= M) }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+{
+  for (int c0 = 1; c0 <= N; c0 += 1) {
+    S1(c0);
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+  }
+  for (int c0 = N + 1; 1; c0 += 1)
+    S1(c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/infinite2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0, 0, 0] : i0 >= 1 }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+if (((t1 + 31) % 32) + g2 >= 2 && N >= ((t1 + 31) % 32) + g2 + 2 && (h0 - 1) % 2 == 0)
+  for (int c0 = max(((t0 + 15) % 16) + 1, ((g1 + t0 + 13) % 16) - g1 + 3); c0 <= min(32, N - g1 - 1); c0 += 16)
+    S1(g1 + c0 - 1, ((t1 + 31) % 32) + g2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { S1[i0, i1] -> [1 - g1 + i0, 1 - g2 + i1, t0, t1] : exists (e0 = [(-1 + h0)/2], e1 = [(-2016b0 - g1)/2048], e2 = [(-992b1 - g2)/1024], e3 = [(-1 + t0 - i0)/16], e4 = [(-1 + t1 - i1)/32]: g0 = h0 and 2e0 = -1 + h0 and 2048e1 = -2016b0 - g1 and 1024e2 = -992b1 - g2 and 16e3 = -1 + t0 - i0 and 32e4 = -1 + t1 - i1 and h0 >= 1 and h0 <= -1 + 2T and i0 >= 2 and i0 <= -2 + N and i1 >= 2 and i1 <= -2 + N and b1 <= 31 and b1 >= 0 and b0 <= 63 and b0 >= 0 and i1 <= 31 + g2 and i1 >= g2 and N >= 4 and i0 >= g1 and i0 <= 31 + g1 and g2 <= -2 + N and g2 >= -29 and g1 <= -2 + N and g1 >= -29 and g1 >= 32b0 and g2 >= 32b1 and 32b0 <= -2 + N and 32b1 <= -2 + N and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 31) }
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> {  : exists (e0 = [(-32b0 + g1)/2048], e1 = [(-32b1 + g2)/1024]: g0 = h0 and 2048e0 = -32b0 + g1 and 1024e1 = -32b1 + g2 and g2 <= -2 + N and g2 >= -29 and g1 <= -2 + N and g1 >= -29 and b1 >= 0 and b1 <= 31 and b0 <= 63 and 32b1 <= -2 + N and 32b0 <= -2 + N and b0 >= 0 and N >= 4 and h0 >= 0 and h0 <= -1 + 2T and g2 >= 32b1 and g1 >= 32b0 and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 31) }
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { [i, j, k, l] -> separate[x] : x >= 3 }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= M; c0 += 1)
+  for (int c1 = 1; c1 <= c0; c1 += 1)
+    S1(c1, c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/largeur.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i1, i0] : i0 >= 1 and i0 <= M and i1 >= i0 and i1 <= M }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,32 @@
+{
+  S1(0, 0);
+  for (int c0 = 1; c0 <= N; c0 += 1) {
+    S2(c0, 0);
+    for (int c1 = 1; c1 < c0; c1 += 1)
+      S6(c0, c1);
+    S3(c0, c0);
+  }
+  S7(N + 1, 0);
+  for (int c1 = 1; c1 <= N; c1 += 1) {
+    S6(N + 1, c1);
+    S8(N + 1, c1);
+  }
+  for (int c0 = N + 2; c0 < 2 * M - N - 1; c0 += 1) {
+    S7(c0, -N + (N + c0 + 1) / 2 - 1);
+    if ((N - c0) % 2 == 0) {
+      S5(c0, (-N + c0) / 2);
+      S8(c0, (-N + c0) / 2);
+    }
+    for (int c1 = -N + (N + c0) / 2 + 1; c1 < (N + c0 + 1) / 2; c1 += 1) {
+      S6(c0, c1);
+      S8(c0, c1);
+    }
+    if ((N - c0) % 2 == 0) {
+      S4(c0, (N + c0) / 2);
+      S8(c0, (N + c0) / 2);
+    }
+  }
+  for (int c0 = 2 * M - N - 1; c0 < 2 * M - 1; c0 += 1)
+    for (int c1 = -M + c0 + 1; c1 < M; c1 += 1)
+      S6(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S8[i0, i1] -> [i0, i1, 7] : i0 >= 1 + N and 2i1 <= N + i0 and 2i1 >= -N + i0 and i0 <= -2 + 2M - N and N <= -2 + M and N >= 1; S1[0, 0] -> [0, 0, 0] : N <= -2 + M and N >= 1; S5[i0, i1] -> [i0, j, 4] : 2j = -N + i0 and 2i1 = -N + i0 and i0 >= 2 + N and i0 <= -2 + 2M - N and N >= 1; S7[i0, i1] -> [i0, i1, 6] : i0 >= 1 + N and 2i1 <= -1 - N + i0 and i0 <= -2 + 2M - N and 2i1 >= -2 - N + i0 and N <= -2 + M and N >= 1; S2[i0, 0] -> [i0, 0, 1] : i0 >= 1 and i0 <= N and N <= -2 + M; S3[i0, i0] -> [i0, i0, 2] : i0 >= 1 and i0 <= N and N <= -2 + M; S4[i0, i1] -> [i0, j, 3] : 2j = N + i0 and 2i1 = N + i0 and i0 >= 2 + N and i0 <= -2 + 2M - N and N >= 1; S6[i0, i1] -> [i0, i1, 5] : 2i1 <= -1 + N + i0 and i1 <= -1 + i0 and i1 >= 1 - M + i0 and 2i1 >= 1 - N + i0 and i1 >= 1 and i1 <= -1 + M and N <= -2 + M }
+[M, N] -> {  : N <= -2 + M and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+  S2(c0);
+  S1(c0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lex.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S2[i0] -> [i0, -1, 0] : i0 >= 0 and i0 <= 10; S1[i0] -> [i0, 0, 0] : i0 >= 0 and i0 <= 10 }
+{  :  }
+{ [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  for (int c1 = 1; c1 < c0; c1 += 1)
+    S1(c0, c1);
+  S1(c0, c0);
+  S2(c0, c0);
+  for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+    S1(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i0] -> [i0, i0, 1] : i0 >= 1 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 1 and i0 <= M and i1 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  for (int c1 = 1; c1 <= min(M, c0 + 1); c1 += 1)
+    S1(c0, c1);
+  if (c0 + 1 >= M) {
+    S2(c0, c0 + 2);
+  } else {
+    S1(c0, c0 + 2);
+    S2(c0, c0 + 2);
+  }
+  for (int c1 = c0 + 3; c1 <= M; c1 += 1)
+    S1(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, 2 + i0] -> [i0, 2 + i0, 1] : i0 >= 1 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 1 and i0 <= M and i1 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,17 @@
+{
+  for (int c1 = 0; c1 <= 7; c1 += 1)
+    S1(1, c1);
+  for (int c0 = 2; c0 <= 6; c0 += 1) {
+    for (int c1 = 0; c1 < c0 - 1; c1 += 1)
+      S2(c0, c1);
+    for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+      S1(c0, c1);
+      S2(c0, c1);
+    }
+    for (int c1 = 5; c1 <= 7; c1 += 1)
+      S1(c0, c1);
+  }
+  for (int c0 = 7; c0 <= 8; c0 += 1)
+    for (int c1 = c0 - 1; c1 <= 7; c1 += 1)
+      S1(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logo.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 2 and i0 <= 6 and i1 >= 0 and i1 <= 4; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 <= 7 and i1 >= -1 + i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,17 @@
+{
+  for (int c1 = 0; c1 <= m; c1 += 1)
+    S1(1, c1);
+  for (int c0 = 2; c0 <= n; c0 += 1) {
+    for (int c1 = 0; c1 < c0 - 1; c1 += 1)
+      S2(c0, c1);
+    for (int c1 = c0 - 1; c1 <= n; c1 += 1) {
+      S1(c0, c1);
+      S2(c0, c1);
+    }
+    for (int c1 = n + 1; c1 <= m; c1 += 1)
+      S1(c0, c1);
+  }
+  for (int c0 = n + 1; c0 <= m + 1; c0 += 1)
+    for (int c1 = c0 - 1; c1 <= m; c1 += 1)
+      S1(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/logopar.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 <= m and i1 >= -1 + i0; S2[i0, i1] -> [i0, i1, 1] : i0 >= 2 and i0 <= n and i1 >= 0 and i1 <= n }
+[m, n] -> {  : n <= m and m >= 0 and n >= 2 }
+[m, n] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  for (int c1 = 2; c1 <= n; c1 += 1)
+    for (int c2 = 1; c2 < min(c0, c1); c2 += 1)
+      S2(c2, c1, c0);
+  for (int c3 = c0 + 1; c3 <= n; c3 += 1)
+    S1(c0, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [i2, i1] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 + i0 and i2 <= n; S1[i0, i1] -> [i0, n] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n }
+[n] -> {  :  }
+[n] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  for (int c1 = 2; c1 <= n; c1 += 1)
+    for (int c2 = 1; c2 < min(c0, c1); c2 += 1)
+      S2(c0, c1, c2, c1, c0);
+  for (int c3 = c0 + 1; c3 <= n; c3 += 1)
+    S1(c0, n, c0, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lu2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, n, i0, i3] -> [i0, n, i0, i3, 0, 0] : i0 >= 1 and i0 <= n and i3 >= 1 + i0 and i3 <= n; S2[i0, i1, i2, i1, i0] -> [i0, i1, i2, i1, i0, 1] : i2 >= 1 and i2 <= n and i2 <= -1 + i1 and i1 <= n and i2 <= -1 + i0 and i0 <= n }
+[n] -> {  :  }
+[n] -> { [i, j, k, l, m, n'] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  for (int c1 = 1; c1 < c0; c1 += 1)
+    for (int c2 = c1 + 1; c2 <= M; c2 += 1)
+      S2(c0, c1, c2, c2, c0);
+  for (int c3 = c0 + 1; c3 <= M; c3 += 1)
+    S1(c0, c0, M, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/lux.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i0, M, i3] -> [i0, i0, M, i3, 0, 0] : i0 >= 1 and i0 <= M and i3 >= 1 + i0 and i3 <= M; S2[i0, i1, i2, i2, i0] -> [i0, i1, i2, i2, i0, 1] : i1 >= 1 and i1 <= M and i2 >= 1 + i1 and i2 <= M and i1 <= -1 + i0 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+{
+  S1(0);
+  for (int c0 = 0; c0 <= 10; c0 += 1) {
+    if (c0 >= 2)
+      S2(c0);
+    S3(c0);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/merge.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S3[i0] -> [i0, 2] : i0 >= 0 and i0 <= 10; S2[i0] -> [i0, 1] : i0 >= 2 and i0 <= 10; S1[0] -> [0, 0] }
+{  :  }
+{ [i, j] -> atomic[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+  for (int c1 = 0; c1 <= min(min(M, c0), N - c0); c1 += 1)
+    S1(c0, c1);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 0 and i1 <= M and i1 <= i0 and i1 <= N - i0 }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+  for (int c1 = 0; c1 <= min(min(M, c0), N - c0); c1 += 1)
+    for (int c2 = 0; c2 <= min(min(M, c0), N - c0); c2 += 1)
+      S1(c0, c1, c2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2] -> [i0, i1, i2, 0] : i0 >= 1 and i1 >= 0 and i1 <= M and i1 <= i0 and i1 <= N - i0 and i2 >= 0 and i2 <= M and i2 <= i0 and i2 <= N - i0 }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= min(10, M); c0 += 1)
+  for (int c1 = 0; c1 <= min(10, M); c1 += 1)
+    S1(c0, c1);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= M and i0 <= 10 and i1 >= 0 and i1 <= M and i1 <= 10 }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = max(-M, -N); c0 <= min(N, O); c0 += 1)
+  S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0] -> [i0, 0] : i0 >= -M and i0 >= -N and i0 <= N and i0 <= O }
+[M, N, O] -> {  :  }
+[M, N, O] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+  if ((c0 + 1) % 3 >= 1)
+    S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0] -> [i0, 0] : exists (e0 = [(1 + i0)/3]: i0 >= 0 and i0 <= 3 and 3e0 <= i0 and 3e0 >= -1 + i0) }
+{  :  }
+{ [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+  if ((c0 + 1) % 3 >= 1)
+    S1(c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i] -> [i, 0] : exists (e0 = [(i)/3]: i >= 0 and i <= 3 and 3e0 <= i and 3e0 >= -1 + i) }
+{  :  }
+{ [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+for (int c0 = max(0, 32 * h0 - 1991); c0 <= min(999, 32 * h0 + 31); c0 += 1)
+  if ((32 * h0 - c0 + 32) % 64 >= 1)
+    for (int c1 = 0; c1 <= 999; c1 += 1)
+      S1(c0, c1);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[h0] -> { S1[i0, i1] -> [i0, i1, 0] : exists (e0 = [(32 + 32h0 - i0)/64]: i0 >= 0 and i0 <= 999 and i0 >= -2015 + 32h0 and 32e0 >= -999 + 32h0 - i0 and i1 >= 0 and i1 <= 999 and 64e0 >= -31 + 32h0 - i0 and 64e0 <= 31 + 32h0 - i0 and i0 <= 32 + 32h0) }
+[h0] -> {  : h0 <= 93 and h0 >= 0 }
+[h0] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= 10; c0 += 3) {
+  S1(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+  S2(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+  S3(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mod4.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S2[j, div41, div42, 2, mod6_a] -> [j, div41, k, 2, m, 1] : 3k = 1 + j and 3div42 = 1 + j and 3m = -2 + j and 3mod6_a = -2 + j and 3div41 >= 1 + j and 3div41 <= 2 + j and j >= 1 and j <= 10; S1[j, div41, div42, 2, mod6_a] -> [j, div41, div42, 2, m, 0] : 3m = -2 + j and 3mod6_a = -2 + j and j >= 1 and j <= 10 and 3div41 >= j and 3div42 >= -1 + j and 3div42 <= 1 + j and 3div41 <= 2 + j; S3[j, div41, div42, 2, mod6_a] -> [j, div41, div42, 2, m, 2] : 3m = -2 + j and 3mod6_a = -2 + j and j >= 1 and j <= 10 and 3div41 >= j and 3div42 >= -1 + j and 3div42 <= 1 + j and 3div41 <= 2 + j }
+{  :  }
+{ [i, j, k, l, m, n] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+for (int c0 = 0; c0 <= M; c0 += 1) {
+  for (int c1 = 0; c1 <= min(N, c0); c1 += 1) {
+    S1(c0, c1);
+    S2(c0, c1);
+  }
+  for (int c1 = max(0, N + 1); c1 <= c0; c1 += 1)
+    S1(c0, c1);
+  for (int c1 = c0 + 1; c1 <= N; c1 += 1)
+    S2(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mode.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= i0; S2[i0, i1] -> [i0, i1, 1] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= M; c0 += 1) {
+  for (int c1 = 0; c1 <= min(N, c0); c1 += 1) {
+    S1(c0, c1);
+    S2(c0, c1);
+  }
+  for (int c1 = N + 1; c1 <= c0; c1 += 1)
+    S1(c0, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i1 >= 0 and i1 <= i0 and i0 <= M; S2[i0, i1] -> [i0, i1, 1] : i1 >= 0 and i1 <= i0 and i0 <= M and i1 <= N }
+[M, N] -> {  : N <= M and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+{
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = -1 + i0 and 2j = -1 + i0 and 6k = -2 + i0 and 6i2 = -2 + i0 and i0 >= 0 and i0 <= 100 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 5; c0 <= 100; c0 += 6)
+  S1(c0, (c0 - 1) / 2, (c0 - 2) / 3);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = -1 + i0 and 2j = -1 + i0 and 3k = -2 + i0 and 3i2 = -2 + i0 and i0 >= 0 and i0 <= 100 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+if (g4 == 0 && N >= g0 + t1 + 1 && t1 <= 7) {
+  for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
+    S1(g0 + t1, g1 + c0);
+} else if (g4 >= 4 && N >= g0 + t1 + 1 && t1 <= 7 && g4 % 4 == 0)
+  for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
+    S1(g0 + t1, g1 + c0);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { S1[g0 + t1, i1] -> [-g1 + i1, t1, t0, t1] : (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g1 >= 128b1 and t1 <= -1 + N - g0 and g0 >= 8b0 and i1 <= -1 + N and b0 <= 15 and b0 >= 0 and b1 <= 31 and b1 >= 0 and i1 <= 127 + g1 and t1 >= 0 and t1 <= 7 and i1 >= g1 and t0 >= 0 and t0 <= 15)) or (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g1 >= 128b1 and t1 <= -1 + N - g0 and g0 >= 8b0 and i1 <= -1 + N and b0 <= 15 and b0 >= 0 and b1 <= 31 and b1 >= 0 and i1 <= 127 + g1 and t1 >= 0 and t1 <= 7 and i1 >= g1 and t0 >= 0 and t0 <= 15 and N >= 1)) or (exists (e0 = [(-g1)/128], e1 = [(128b1 + 3
 1g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g0 >= 8b0 and t1 <= -1 + N - g0 and g1 >= 128b1 and i1 <= -1 + N and N >= 1 and t1 <= 7 and b1 <= 31 and b1 >= 0 and b0 <= 15 and b0 >= 0 and t0 <= 15 and i1 <= 127 + g1 and i1 >= g1 and t1 >= 0 and t0 >= 0)); S1[g0 + t1, i1] -> [-g1 + i1, t1, t0, t1] : exists (e0 = [(g4)/4], e1 = [(-g1)/128], e2 = [(128b1 + 31g1)/4096], e3 = [(t0 - i1)/16], e4 = [(-120b0 - g0)/128]: g3 = 128b1 and g2 = 8b0 and 4e0 = g4 and 128e1 = -g1 and 4096e2 = 128b1 + 31g1 and 16e3 = t0 - i1 and 128e4 = -120b0 - g0 and g0 >= 8b0 and t1 <= -1 + N - g0 and g1 >= 128b1 and i1 <= -1 + N and g4 <= -1 + N and t1 <= 7 and b1 <= 31 and b1 >= 0 and b0 <= 15 and b0 >= 0 and g4 >= 0 and i1 <= 127 + g1 and i1 >= g1 and t1 >= 0 and t0 >= 0 and t0 <= 15) }
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> {  : exists (e0 = [(g0)/8], e1 = [(-128b1 + g1)/4096], e2 = [(8b0 - g0)/128]: g2 = 8b0 and g3 = 128b1 and 8e0 = g0 and 4096e1 = -128b1 + g1 and 128e2 = 8b0 - g0 and b0 >= 0 and g4 <= -1 + N and b0 <= 15 and g1 <= -1 + N and g4 >= 0 and b1 <= 31 and g0 <= -1 + N and g1 >= 128b1 and b1 >= 0 and g0 >= 8b0 and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 15) }
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1 @@
+S1(N + 2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[2 + N] -> [1 + M, N] }
+[M, N] -> {  :  }
+[M, N] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M; c0 += 2)
+  S1(c0, c0 / 2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, j, 0] : 2j = i0 and 2i1 = i0 and i0 >= 0 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= n; c0 += 2) {
+  if (c0 % 4 == 0)
+    S2(c0, c0 / 4);
+  S1(c0, c0 / 2);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1] -> [i0, j, 1] : 4j = i0 and 4i1 = i0 and i0 >= 1 and i0 <= n; S1[i0, i1] -> [i0, j, 0] : 2j = i0 and 2i1 = i0 and i0 >= 1 and i0 <= n }
+[n] -> {  : n >= 2 }
+[n] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 5 * n; c0 += 1)
+  for (int c1 = max(-((5 * n - c0 + 1) % 2) - n + c0 + 1, 2 * floord(c0 - 1, 3) + 2); c1 <= min(c0, n + c0 - (n + c0 + 2) / 3); c1 += 2)
+    S1((3 * c1 / 2) - c0, c0 - c1);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, i1] -> [2i0 + 3i1, 2i0 + 2i1] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= n }
+[n] -> {  :  }
+[n] -> { [i, j] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,13 @@
+{
+  for (int c0 = 1; c0 <= 6; c0 += 2) {
+    for (int c2 = 1; c2 <= c0; c2 += 1) {
+      S1(c0, (c0 - 1) / 2, c2);
+      S2(c0, (c0 - 1) / 2, c2);
+    }
+    for (int c2 = c0 + 1; c2 <= p; c2 += 1)
+      S1(c0, (c0 - 1) / 2, c2);
+  }
+  for (int c0 = 7; c0 <= m; c0 += 2)
+    for (int c2 = 1; c2 <= p; c2 += 1)
+      S1(c0, (c0 - 1) / 2, c2);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[m, n, p] -> { S1[i, k, j] -> [i, j', j, 0] : 2k = -1 + i and 2j' = -1 + i and i >= 1 and i <= m and j >= 1 and j <= p; S2[i, k, j] -> [i, j', j, 1] : 2k = -1 + i and 2j' = -1 + i and i >= 1 and i <= n and j >= 1 and j <= i }
+[m, n, p] -> {  : n = 6 and m >= 7 and p >= 7 }
+[m, n, p] -> { [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,16 @@
+{
+  for (int c1 = 0; c1 <= 2; c1 += 1) {
+    S1(c1);
+    for (int c2 = 0; c2 <= -c1 + 11; c2 += 1) {
+      S2(c1, c2);
+      S3(c1, c2);
+    }
+    S4(c1);
+  }
+  for (int c1 = 0; c1 <= 14; c1 += 1) {
+    S5(c1);
+    for (int c2 = 0; c2 <= 9; c2 += 1)
+      S6(c1, c2);
+    S7(c1);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/orc.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S2[i0, i1] -> [0, 1 + 3i0, 2i1] : i0 >= 0 and i0 <= 2 and i1 >= 0 and i1 <= 11 - i0; S4[i0] -> [0, 2 + 3i0, 0] : i0 >= 0 and i0 <= 2; S5[i0] -> [2, 3i0, 0] : i0 >= 0 and i0 <= 14; S6[i0, i1] -> [2, 1 + 3i0, i1] : i0 >= 0 and i0 <= 14 and i1 >= 0 and i1 <= 9; S1[i0] -> [0, 3i0, 0] : i0 >= 0 and i0 <= 2; S7[i0] -> [2, 2 + 3i0, 0] : i0 >= 0 and i0 <= 14; S3[i0, i1] -> [0, 1 + 3i0, 1 + 2i1] : i0 >= 0 and i0 <= 2 and i1 >= 0 and i1 <= 11 - i0 }
+{  :  }
+{ [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+if (M >= 3 && N >= 4)
+  for (int c0 = 1; c0 < (2 * M + 2 * N - 2) / 5; c0 += 1)
+    for (int c1 = max(c0 - (M + 2) / 5, (c0 + 1) / 2); c1 <= min(min(c0, (M + 2 * N) / 5 - 1), (2 * N + 5 * c0 + 1) / 10); c1 += 1)
+      for (int c2 = max(max(max(max(0, c0 - c1 - 1), c1 - (N + 6) / 5 + 1), c0 - (M + N + 4) / 5 + 1), floord(-N + 5 * c0 - 3, 10) + 1); c2 <= min(min(min(c1, (M + N - 2) / 5), c0 - c1 + (N - 1) / 5 + 1), (N + 5 * c0 + 3) / 10); c2 += 1)
+        for (int c3 = max(max(max(c0, 2 * c1 - (2 * N + 5) / 5 + 1), c1 + c2 - (N + 3) / 5), 2 * c2 - (N + 2) / 5); c3 <= min(min(min(min(min(c0 + 1, c1 + c2 + 1), c1 + (M - 2) / 5 + 1), 2 * c2 + (N - 2) / 5 + 1), (2 * M + 2 * N - 1) / 5 - 1), c2 + (M + N) / 5); c3 += 1)
+          for (int c4 = max(max(max(max(c1, c0 - c2), c0 - (M + 6) / 5 + 1), c3 - (M + 2) / 5), (c3 + 1) / 2); c4 <= min(min(min(min(min(min(min(c0, c1 + 1), -c2 + c3 + (N - 1) / 5 + 1), c0 - c2 + N / 5 + 1), (M + 2 * N + 1) / 5 - 1), c2 + (N + 2) / 5), (2 * N + 5 * c0 + 3) / 10), (2 * N + 5 * c3 + 2) / 10); c4 += 1)
+            S1(c0, c1, c2, c3, c4, c2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/otl.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2, i3, i4, i2] -> [i0, i1, i2, i3, i4, i2] : 5i0 <= -7 + 2M + 2N and i4 >= i0 - i2 and 10i2 >= -2 - N + 5i0 and i2 >= -1 + i0 - i1 and 2i4 >= i0 and i0 >= 1 and i1 >= 1 and 2i1 >= i0 and i2 >= 0 and 5i2 >= 1 - M - N + 5i0 and 5i4 >= -1 - M + 5i0 and i3 >= i0 and 5i1 >= -2 - M + 5i0 and i3 >= 1 and 5i3 >= -3 - N + 5i1 + 5i2 and 5i2 <= 4 + N + 5i0 - 5i1 and i4 >= 1 and i2 <= i0 and 5i3 >= -2N + 10i1 and 5i1 <= -5 + M + 2N and 10i1 <= 1 + 2N + 5i0 and 5i2 >= -1 - N + 5i1 and i4 >= i1 and i3 >= i1 and i2 <= i1 and i1 <= i0 and 5i4 <= 4 + N - 5i2 + 5i3 and 5i4 <= 5 + N + 5i0 - 5i2 and 5i3 >= -2 - N + 10i2 and 5i2 <= -2 + M + N and 10i2 <= 3 + N + 5i0 and N >= 4 and i4 >= i2 and i3 >= i2 and M >= 3 and i4 <= i0 and 5i3 <= -6 + 2M + 2N and i4 >= -1 - i2 + i3 and 5i3 <= 3 + N + 10i2 and i3 <= 1 + i1 + i2 and i4 <= 1 + i1 and 2i4 >= i3 and 5i4 <= 2 + N + 5i2 and i3 <= 1 + 2i1 and i4 <= i3 and 5i3 <= M + N + 5i2 and 5i4 >= -2 - M + 5i3 and 10i4 <= 3 + 2N + 5i0 and i3 <
 = 1 + i0 and 5i3 <= 3 + M + 5i1 and 5i4 <= -4 + M + 2N and 10i4 <= 2 + 2N + 5i3 }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m, n] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= (M <= 0 ? 0 : M); c0 += 1) {
+  if (M >= c0)
+    S1(c0);
+  if (c0 == 0)
+    S2(0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/param-split.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= M; S2[0] -> [0, 1] }
+[M] -> {  :  }
+[M] -> { [i, j] -> atomic[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,11 @@
+for (int c0 = 1; c0 <= floord(Ny, 2) + 2; c0 += 1)
+  for (int c1 = max(c0 - 1, c0 / 2 + 1); c1 <= min(c0, (Ny + 2 * c0) / 4); c1 += 1) {
+    if (Ny + 2 * c0 >= 4 * c1 + 1) {
+      for (int c2 = 1; c2 <= 2; c2 += 1) {
+        S1(c0 - c1, c1, 2 * c0 - 2 * c1, -2 * c0 + 4 * c1, c2);
+        S2(c0 - c1, c1, 2 * c0 - 2 * c1, -2 * c0 + 4 * c1 - 1, c2);
+      }
+    } else
+      for (int c2 = 1; c2 <= 2; c2 += 1)
+        S2((-Ny + 2 * c0) / 4, (Ny + 2 * c0) / 4, (-Ny / 2) + c0, Ny - 1, c2);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/pouchet.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[Ny] -> { S1[i0, i1, 2i0, -2i0 + 2i1, i4] -> [i0 + i1, i1, i4, 2i0, -2i0 + 2i1, i4] : i0 >= 0 and i0 <= 1 and i1 >= 1 + i0 and 2i1 <= -1 + Ny + 2i0 and i4 >= 1 and i4 <= 2; S2[i0, i1, 2i0, -1 - 2i0 + 2i1, i4] -> [i0 + i1, i1, i4, 2i0, -2i0 + 2i1, 1 + i4] : i0 >= 0 and i0 <= 1 and i1 >= 1 + i0 and 2i1 <= Ny + 2i0 and i4 >= 1 and i4 <= 2 }
+[Ny] -> {  :  }
+[Ny] -> { [i, j, k, l, m, n] -> separate[x] : x >= 2 }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 2 * n; c0 += 1)
+  for (int c1 = max(0, -n + c0); c1 <= min(n, c0); c1 += 1)
+    S1(c1, c0 - c1);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/rectangle.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, i1] -> [i0 + i1] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= n }
+[n] -> {  : n >= 0 }
+[n] -> { [i] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,54 @@
+if (N >= 1) {
+  S1(0);
+  if (N == 1) {
+    for (int c3 = 0; c3 < M; c3 += 1)
+      S2(0, c3);
+    S3(0);
+    for (int c3 = 0; c3 < M; c3 += 1)
+      S4(0, c3);
+    S10(0);
+    S5(0);
+  } else {
+    for (int c3 = 0; c3 < M; c3 += 1)
+      S2(0, c3);
+    S3(0);
+    for (int c3 = 0; c3 < M; c3 += 1)
+      S4(0, c3);
+    S10(0);
+    S1(1);
+    S5(0);
+  }
+  for (int c1 = 2; c1 < N; c1 += 1) {
+    for (int c3 = c1 - 1; c3 < N; c3 += 1) {
+      S6(c1 - 2, c3);
+      for (int c5 = c1 - 2; c5 < M; c5 += 1)
+        S7(c1 - 2, c3, c5);
+      S8(c1 - 2, c3);
+      for (int c5 = c1 - 2; c5 < M; c5 += 1)
+        S9(c1 - 2, c3, c5);
+    }
+    for (int c3 = c1 - 1; c3 < M; c3 += 1)
+      S2(c1 - 1, c3);
+    S3(c1 - 1);
+    for (int c3 = c1 - 1; c3 < M; c3 += 1)
+      S4(c1 - 1, c3);
+    S10(c1 - 1);
+    S1(c1);
+    S5(c1 - 1);
+  }
+  if (N >= 2) {
+    S6(N - 2, N - 1);
+    for (int c5 = N - 2; c5 < M; c5 += 1)
+      S7(N - 2, N - 1, c5);
+    S8(N - 2, N - 1);
+    for (int c5 = N - 2; c5 < M; c5 += 1)
+      S9(N - 2, N - 1, c5);
+    for (int c3 = N - 1; c3 < M; c3 += 1)
+      S2(N - 1, c3);
+    S3(N - 1);
+    for (int c3 = N - 1; c3 < M; c3 += 1)
+      S4(N - 1, c3);
+    S10(N - 1);
+    S5(N - 1);
+  }
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [0, i0, 5, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S9[i0, i1, i2] -> [0, 2 + i0, 0, i1, 3, i2, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N and i2 >= i0 and i2 <= -1 + M; S10[i0] -> [0, 1 + i0, 4, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S3[i0] -> [0, 1 + i0, 2, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S6[i0, i1] -> [0, 2 + i0, 0, i1, 0, 0, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N; S8[i0, i1] -> [0, 2 + i0, 0, i1, 2, 0, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N; S2[i0, i1] -> [0, 1 + i0, 1, i1, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= i0 and i1 <= -1 + M; S4[i0, i1] -> [0, 1 + i0, 3, i1, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= i0 and i1 <= -1 + M; S7[i0, i1, i2] -> [0, 2 + i0, 0, i1, 1, i2, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N and i2 >= i0 and i2 <= -1 + M; S5[i0] -> [0, 1 + i0, 6, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c0 = 3; c0 <= 9; c0 += 1)
+  for (int c1 = max(c0 - 6, -(c0 % 2) + 2); c1 <= min(3, c0 - 2); c1 += 2)
+    S1(c0, c1, (c0 - c1) / 2);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, i1, k, 0] : 2k = i0 - i1 and 2i2 = i0 - i1 and i1 >= 1 and i1 <= 3 and i1 <= -2 + i0 and i1 >= -6 + i0 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 < 3 * M; c1 += 1) {
+  if ((c1 - 2) % 3 == 0)
+    S1((c1 + 1) / 3);
+  for (int c3 = (c1 + 1) / 3 + 1; c3 <= min(M, c1 - 2); c3 += 1)
+    for (int c5 = -c3 + (c1 + c3 + 1) / 2 + 1; c5 <= min(c3, c1 - c3); c5 += 1)
+      S3(c1 - c3 - c5 + 1, c3, c5);
+  for (int c3 = -c1 + 2 * ((2 * c1 + 1) / 3) + 2; c3 <= min(M, c1); c3 += 2)
+    S2(((c1 - c3) / 2) + 1, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S3[i0, i1, i2] -> [0, -1 + i0 + i1 + i2, 1, i1, 1, i2, 0] : i0 >= 1 and i1 <= M and i2 >= 1 + i0 and i2 <= i1; S2[i0, i1] -> [0, -2 + 2i0 + i1, 2, i1, 0, 0, 0] : i0 >= 1 and i1 >= 1 + i0 and i1 <= M; S1[i0] -> [0, -1 + 3i0, 0, 0, 0, 0, 0] : i0 >= 1 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    S1(c1);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S2(c1);
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    S3(c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [0, i0, 0] : i0 >= 0 and i0 <= M; S3[i0] -> [2, i0, 0] : i0 >= 0 and i0 <= M; S2[i0] -> [1, i0, 0] : i0 >= 1 and i0 <= M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,12 @@
+if (N >= 1) {
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    S1(1, c3);
+  for (int c1 = 2; c1 <= N; c1 += 1) {
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1 - 1, c3);
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  }
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    S2(N, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [0, 1 + i0, 0, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 1, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+for (int c1 = 0; c1 < M; c1 += 1)
+  for (int c3 = 0; c3 < M; c3 += 1)
+    S1(c1, c3);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 0 and i0 <= -1 + M and i1 >= 0 and i1 <= -1 + M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c1 = 1; c1 <= M; c1 += 1) {
+  for (int c3 = 2; c3 < N; c3 += 1)
+    for (int c5 = 2; c5 < N; c5 += 1)
+      S1(c1, c3, c5);
+  for (int c3 = 2; c3 < N; c3 += 1)
+    for (int c5 = 2; c5 < N; c5 += 1)
+      S2(c1, c3, c5);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1, i2] -> [0, 1 + 2i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N; S1[i0, i1, i2] -> [0, 2i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+for (int c1 = -99; c1 <= 100; c1 += 1) {
+  if (c1 <= 0)
+    S1(1, -c1 + 1);
+  for (int c3 = max(1, -2 * c1 + 3); c3 <= min(199, -2 * c1 + 199); c3 += 2) {
+    S2(((c3 - 1) / 2) + c1, (c3 + 1) / 2);
+    S1(((c3 + 1) / 2) + c1, (c3 + 1) / 2);
+  }
+  if (c1 >= 1)
+    S2(100, -c1 + 101);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+{ S2[i0, i1] -> [0, 1 + i0 - i1, 0, -1 + 2i1, 1] : i0 >= 1 and i0 <= 100 and i1 >= 1 and i1 <= 100; S1[i0, i1] -> [0, i0 - i1, 0, 2i1, 0] : i0 >= 1 and i0 <= 100 and i1 >= 1 and i1 <= 100 }
+{  :  }
+{ [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S1(c1);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 2; c3 <= N; c3 += 1)
+      S2(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      S3(c1, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [0, i0, 0, 0, 0] : i0 >= 1 and i0 <= M; S2[i0, i1] -> [1, i0, 1, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= N; S3[i0, i1] -> [2, i0, 2, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + N }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,11 @@
+for (int c1 = 5; c1 <= 5 * M; c1 += 1) {
+  for (int c3 = max(2, floord(-M + c1, 4)); c3 < min(M, (c1 + 1) / 3 - 2); c3 += 1)
+    for (int c5 = max(1, -M - c3 + (M + c1) / 2 - 2); c5 < min(c3, -2 * c3 + (c1 + c3) / 2 - 2); c5 += 1)
+      S1(c1 - 2 * c3 - 2 * c5 - 5, c3, c5);
+  for (int c3 = max(1, floord(-M + c1, 4)); c3 < (c1 + 1) / 5; c3 += 1)
+    S2(c1 - 4 * c3 - 3, c3);
+  if (c1 % 5 == 0)
+    S4(c1 / 5);
+  for (int c3 = max(-3 * M - c1 + 3 * ((M + c1) / 2) + 1, -((c1 - 1) % 3) + 3); c3 < (c1 + 1) / 5; c3 += 3)
+    S3((c1 - 2 * c3 - 1) / 3, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, 5 + i0 + 2i1 + 2i2, 0, i1, 0, i2, 0] : i0 <= M and i1 <= -1 + i0 and i2 >= 1 and i2 <= -1 + i1; S3[i0, i1] -> [0, 1 + 3i0 + 2i1, 2, i1, 0, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0; S2[i0, i1] -> [0, 3 + i0 + 4i1, 1, i1, 1, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0; S4[i0] -> [0, 5i0, 2, 0, 0, 0, 0] : i0 >= 1 and i0 <= M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+for (int c1 = 1; c1 < 2 * M - 1; c1 += 1) {
+  for (int c3 = max(-M + 1, -c1 + 1); c3 < 0; c3 += 1) {
+    for (int c7 = max(1, -M + c1 + 1); c7 <= min(M - 1, c1 + c3); c7 += 1)
+      S1(c7, c1 + c3 - c7, -c3);
+    for (int c5 = max(-M + c1 + 1, -c3); c5 < min(M, c1); c5 += 1)
+      S2(c1 - c5, c3 + c5, c5);
+  }
+  for (int c7 = max(1, -M + c1 + 1); c7 <= min(M - 1, c1); c7 += 1)
+    S1(c7, c1 - c7, 0);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0 + i1 + i2, 0, -i2, 0, i2, 0] : i0 >= 1 and i0 <= -1 + M and i1 >= 0 and i2 >= 0 and i2 <= -1 + M - i1; S2[i0, i1, i2] -> [0, i0 + i2, 0, i1 - i2, 1, i2, 0] : i0 >= 1 and i0 <= -1 + M and i1 >= 0 and i2 >= 1 + i1 and i2 <= -1 + M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,11 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S3(c1, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S3[i0, i1] -> [2, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c3, c1);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i1, 0, i0, 0] : i0 >= 1 and i0 <= M and i1 >= 0 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,17 @@
+if (M >= 0 && N >= 0)
+  for (int c1 = -4; c1 <= 3 * M + N; c1 += 1) {
+    if (3 * M + N >= c1 + 1 && c1 >= 3 * M) {
+      S2(M, -3 * M + c1);
+    } else if (3 * M >= c1 + 4 && (c1 - 2) % 3 == 0)
+      S1((c1 + 4) / 3, 0);
+    for (int c3 = max(-3 * M + c1 + 3, (c1 + 6) % 3); c3 <= min(N - 1, c1); c3 += 3) {
+      S2((c1 - c3) / 3, c3);
+      S1(((c1 - c3) / 3) + 1, c3 + 1);
+    }
+    if (c1 >= N && (N - c1) % 3 == 0) {
+      S2((-N + c1) / 3, N);
+    } else if (N >= c1 + 4 && c1 >= -3)
+      S1(0, c1 + 4);
+    for (int c3 = max(-3 * M + c1, (c1 + 6) % 3); c3 <= min(N, c1); c3 += 3)
+      S3((c1 - c3) / 3, c3);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [0, 3i0 + i1, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N; S3[i0, i1] -> [0, 3i0 + i1, 1, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N; S1[i0, i1] -> [0, -4 + 3i0 + i1, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+  for (int c3 = 2; c3 <= M + c1; c3 += 1)
+    for (int c5 = max(1, -c1 + c3); c5 <= min(M, c3 - 1); c5 += 1)
+      S1(c1, c5, c3 - c5);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0, 0, i1 + i2, 0, i1, 0] : i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c1 = 2; c1 <= 2 * M; c1 += 1)
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    for (int c5 = 1; c5 <= M; c5 += 1)
+      for (int c7 = max(1, -M + c1); c7 <= min(M, c1 - 1); c7 += 1)
+        S1(c5, c3, c7, c1 - c7);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2, i3] -> [0, i2 + i3, 0, i1, 0, i0, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M and i3 >= 1 and i3 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o, p, q] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    for (int c5 = 1; c5 <= M; c5 += 1)
+      for (int c7 = 1; c7 <= M; c7 += 1)
+        S1(c3, c5, c1, c7);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2, i3] -> [0, i2, 0, i0, 0, i1, 0, i3, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M and i3 >= 1 and i3 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o, p, q] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,85 @@
+{
+  if (N >= 2)
+    for (int c1 = 1; c1 < O; c1 += 1) {
+      for (int c5 = 1; c5 <= M; c5 += 1)
+        S1(c1, 1, c5);
+      for (int c5 = 1; c5 < M; c5 += 1) {
+        S6(c1, 1, c5);
+        S7(c1, 1, c5);
+      }
+      if (N >= 3) {
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, 1, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S1(c1, 2, c5);
+        for (int c5 = 1; c5 < M; c5 += 1) {
+          S6(c1, 2, c5);
+          S7(c1, 2, c5);
+        }
+        for (int c5 = 1; c5 < M; c5 += 1)
+          S11(c1, 1, c5);
+      } else {
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, 1, c5);
+        for (int c5 = 1; c5 < M; c5 += 1)
+          S11(c1, 1, c5);
+      }
+      for (int c3 = 3; c3 < 2 * N - 4; c3 += 2) {
+        for (int c5 = 1; c5 < M; c5 += 1)
+          S10(c1, (c3 - 1) / 2, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, (c3 + 1) / 2, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S1(c1, (c3 + 3) / 2, c5);
+        for (int c5 = 1; c5 < M; c5 += 1) {
+          S6(c1, (c3 + 3) / 2, c5);
+          S7(c1, (c3 + 3) / 2, c5);
+        }
+        for (int c5 = 1; c5 < M; c5 += 1)
+          S11(c1, (c3 + 1) / 2, c5);
+      }
+      if (N >= 3) {
+        for (int c5 = 1; c5 < M; c5 += 1)
+          S10(c1, N - 2, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, N - 1, c5);
+        for (int c5 = 1; c5 < M; c5 += 1)
+          S11(c1, N - 1, c5);
+      }
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S10(c1, N - 1, c5);
+    }
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1) {
+      for (int c5 = 1; c5 <= M; c5 += 1)
+        S2(c1, c3, c5);
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S8(c1, c3, c5);
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S9(c1, c3, c5);
+    }
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S4(c1, c3, c5);
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S5(c1, c3, c5);
+  for (int c1 = R; c1 < O; c1 += 1)
+    for (int c3 = Q; c3 < N; c3 += 1)
+      for (int c5 = P; c5 < M; c5 += 1)
+        S12(c1, c3, c5);
+  for (int c1 = R; c1 < O; c1 += 1)
+    for (int c3 = Q; c3 < N; c3 += 1)
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S13(c1, c3, c5);
+  for (int c1 = R; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      for (int c5 = P; c5 < M; c5 += 1)
+        S14(c1, c3, c5);
+  for (int c1 = R; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S15(c1, c3, c5);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R, S, T, U] -> { S8[i0, i1, i2] -> [1, i0, 0, 2i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S11[i0, i1, i2] -> [0, i0, 0, 2i1, 4, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S6[i0, i1, i2] -> [0, i0, 0, -2 + 2i1, 2, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S9[i0, i1, i2] -> [1, i0, 0, 1 + 2i1, 3, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S1[i0, i1, i2] -> [0, i0, 0, -3 + 2i1, 2, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S4[i0, i1, i2] -> [2, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S2[i0, i1, i2] -> [1, i0, 0, 2i1, 0, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S7[i0, i1, i2] -> [0, i0, 0, -2 + 2i1, 2, i2, 1] :
  i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S10[i0, i1, i2] -> [0, i0, 0, 1 + 2i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S3[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 1, i2, 2] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S15[i0, i1, i2] -> [7, i0, 1, i1, 1, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S5[i0, i1, i2] -> [3, i0, 0, i1, 1, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S13[i0, i1, i2] -> [5, i0, 0, i1, 1, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S12[i0, i1, i2] -> [4, i0, 0, i1, 0, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= P and i2 <= -1 + M; S14[i0, i1, i2] -> [6, i0, 1, i1, 0, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= P and i2 <= -1 + M
  }
+[M, N, O, P, Q, R, S, T, U] -> {  :  }
+[M, N, O, P, Q, R, S, T, U] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,18 @@
+{
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = Q; c3 < N; c3 += 1)
+      for (int c5 = P; c5 < M; c5 += 1)
+        S1(c1, c3, c5);
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = Q; c3 < N; c3 += 1)
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S2(c1, c3, c5);
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      for (int c5 = P; c5 < M; c5 += 1)
+        S3(c1, c3, c5);
+  for (int c1 = 1; c1 < O; c1 += 1)
+    for (int c3 = 1; c3 < N; c3 += 1)
+      for (int c5 = 1; c5 < M; c5 += 1)
+        S4(c1, c3, c5);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R, S, T, U] -> { S1[i0, i1, i2] -> [0, i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= P and i2 <= -1 + M; S4[i0, i1, i2] -> [3, i0, 1, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S2[i0, i1, i2] -> [1, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S3[i0, i1, i2] -> [2, i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= P and i2 <= -1 + M }
+[M, N, O, P, Q, R, S, T, U] -> {  :  }
+[M, N, O, P, Q, R, S, T, U] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 < O; c1 += 1)
+  for (int c3 = 3; c3 < 2 * N - 2; c3 += 2) {
+    for (int c5 = 1; c5 <= M; c5 += 1) {
+      S1(c1, (c3 + 1) / 2, c5);
+      S2(c1, (c3 + 1) / 2, c5);
+    }
+    for (int c5 = 2; c5 < M; c5 += 1)
+      S3(c1, (c3 + 1) / 2, c5);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S2[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S3[i0, i1, i2] -> [0, i0, 0, 2i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M }
+[M, N, O] -> {  :  }
+[M, N, O] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 < O; c1 += 1)
+  for (int c3 = 3; c3 < 2 * N - 2; c3 += 2) {
+    for (int c5 = 1; c5 <= M; c5 += 1) {
+      S1(c1, (c3 + 1) / 2, c5);
+      S2(c1, (c3 + 1) / 2, c5);
+    }
+    for (int c5 = 2; c5 < M; c5 += 1)
+      S3(c1, (c3 + 1) / 2, c5);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S2[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S3[i0, i1, i2] -> [0, i0, 0, 2i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M }
+[M, N, O] -> {  :  }
+[M, N, O] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,33 @@
+if (M >= 2 && N >= 3)
+  for (int c1 = 2; c1 < O; c1 += 1) {
+    for (int c5 = 2; c5 <= M; c5 += 1)
+      S1(c1, 2, c5);
+    for (int c3 = 3; c3 < N; c3 += 1) {
+      for (int c5 = 2; c5 <= M; c5 += 1)
+        S2(c1, c3 - 1, c5);
+      if (M >= 3) {
+        S4(c1, c3 - 1, 2);
+        for (int c5 = 2; c5 < M - 1; c5 += 1) {
+          S3(c1, c3 - 1, c5);
+          S5(c1, c3 - 1, c5);
+          S4(c1, c3 - 1, c5 + 1);
+        }
+        S3(c1, c3 - 1, M - 1);
+        S5(c1, c3 - 1, M - 1);
+      }
+      for (int c5 = 2; c5 <= M; c5 += 1)
+        S1(c1, c3, c5);
+    }
+    for (int c5 = 2; c5 <= M; c5 += 1)
+      S2(c1, N - 1, c5);
+    if (M >= 3) {
+      S4(c1, N - 1, 2);
+      for (int c5 = 2; c5 < M - 1; c5 += 1) {
+        S3(c1, N - 1, c5);
+        S5(c1, N - 1, c5);
+        S4(c1, N - 1, c5 + 1);
+      }
+      S3(c1, N - 1, M - 1);
+      S5(c1, N - 1, M - 1);
+    }
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R] -> { S1[i0, i1, i2] -> [0, i0, 0, i1, 2, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= M; S4[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, -1 + i2, 2] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S3[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S5[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S2[i0, i1, i2] -> [0, i0, 0, 1 + i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= M }
+[M, N, O, P, Q, R] -> {  :  }
+[M, N, O, P, Q, R] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+  for (int c3 = 1; c3 < 2 * N; c3 += 1) {
+    for (int c5 = max(1, -N + c3); c5 < (c3 + 1) / 2; c5 += 1)
+      S1(c1, c3 - c5, c5);
+    if ((c3 - 1) % 2 == 0)
+      S2(c1, (c3 + 1) / 2);
+  }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2] -> [0, i0, 0, i1 + i2, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 <= N and i2 >= 1 and i2 <= -1 + i1; S2[i0, i1] -> [0, i0, 0, -1 + 2i1, 1, 0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 1, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,9 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      for (int c5 = 1; c5 <= M; c5 += 1)
+        S2(c1, c3, c5);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1, i2] -> [1, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0, 0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,10 @@
+for (int c1 = 3; c1 < 2 * M; c1 += 1) {
+  for (int c3 = c1 / 2 + 2; c3 <= M; c3 += 1)
+    for (int c7 = c1 / 2 + 1; c7 < min(c1, c3); c7 += 1)
+      S1(c7, c1 - c7, c3);
+  for (int c3 = max(1, -M + c1); c3 < (c1 + 1) / 2; c3 += 1)
+    S2(c1 - c3, c3);
+  for (int c3 = c1 / 2 + 2; c3 <= M; c3 += 1)
+    for (int c7 = c1 / 2 + 1; c7 < min(c1, c3); c7 += 1)
+      S3(c7, c1 - c7, c3);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0 + i1, 0, i2, 0, i2, 0] : i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S3[i0, i1, i2] -> [0, i0 + i1, 2, i2, 2, i2, 0] : i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S2[i0, i1] -> [0, i0 + i1, 1, i1, 1, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,8 @@
+for (int c1 = 1; c1 <= M; c1 += 1) {
+  for (int c3 = 2; c3 < N; c3 += 1)
+    for (int c5 = 2; c5 < N; c5 += 1)
+      S1(c1, c3, c5);
+  for (int c3 = 2; c3 < N; c3 += 1)
+    for (int c5 = 2; c5 < N; c5 += 1)
+      S2(c1, c3, c5);
+}

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1, i2] -> [0, 1 + 2i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N; S1[i0, i1, i2] -> [0, 2i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c1 = 2; c1 <= M; c1 += 7)
+  S1(c1, (c1 - 2) / 7);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, 0, 0] : 7i1 = -2 + i0 and i0 >= 2 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2 @@
+for (int c1 = 2; c1 <= M; c1 += 7)
+  S1(c1, (c1 - 2) / 7);

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, 0, 0] : 7i1 = -2 + i0 and i0 >= 0 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }

Added: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,5 @@
+for (int c1 = 0; c1 <= 9; c1 += 2)
+  for (int c3 = 0; c3 <= min(4, c1 + 3); c3 += 2)
+    for (int c5 = max(1, c1); c5 <= min(c1 + 1, c1 - c3 + 4); c5 += 1)
+      for (int c7 = max(1, -c1 + c3 + c5); c7 <= min(4, -c1 + c3 + c5 + 1); c7 += 1)
+