[polly] r290681 - Update to isl-0.18-28-gccb9f33

Tobias Grosser via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 28 11:35:50 PST 2016


Author: grosser
Date: Wed Dec 28 13:35:49 2016
New Revision: 290681

URL: http://llvm.org/viewvc/llvm-project?rev=290681&view=rev
Log:
Update to isl-0.18-28-gccb9f33

Another set of isl coalesce changes.

Modified:
    polly/trunk/lib/External/isl/GIT_HEAD_ID
    polly/trunk/lib/External/isl/doc/manual.pdf
    polly/trunk/lib/External/isl/isl_coalesce.c
    polly/trunk/lib/External/isl/isl_tab.c
    polly/trunk/lib/External/isl/isl_tab.h
    polly/trunk/lib/External/isl/isl_test.c

Modified: polly/trunk/lib/External/isl/GIT_HEAD_ID
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/GIT_HEAD_ID?rev=290681&r1=290680&r2=290681&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/GIT_HEAD_ID (original)
+++ polly/trunk/lib/External/isl/GIT_HEAD_ID Wed Dec 28 13:35:49 2016
@@ -1 +1 @@
-isl-0.18-17-g2844ebf
+isl-0.18-28-gccb9f33

Modified: polly/trunk/lib/External/isl/doc/manual.pdf
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/doc/manual.pdf?rev=290681&r1=290680&r2=290681&view=diff
==============================================================================
Binary files polly/trunk/lib/External/isl/doc/manual.pdf (original) and polly/trunk/lib/External/isl/doc/manual.pdf Wed Dec 28 13:35:49 2016 differ

Modified: polly/trunk/lib/External/isl/isl_coalesce.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_coalesce.c?rev=290681&r1=290680&r2=290681&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_coalesce.c (original)
+++ polly/trunk/lib/External/isl/isl_coalesce.c Wed Dec 28 13:35:49 2016
@@ -615,8 +615,11 @@ static int contains(struct isl_coalesce_
  * In particular, we replace constraint k, say f >= 0, by constraint
  * f <= -1, add the inequalities of "j" that are valid for "i"
  * and check if the result is a subset of basic map "j".
- * If so, then we know that this result is exactly equal to basic map "j"
- * since all its constraints are valid for basic map "j".
+ * To improve the chances of the subset relation being detected,
+ * any variable that only attains a single integer value
+ * in the tableau of "i" is first fixed to that value.
+ * If the result is a subset, then we know that this result is exactly equal
+ * to basic map "j" since all its constraints are valid for basic map "j".
  * By combining the valid constraints of "i" (all equalities and all
  * inequalities except "k") and the valid constraints of "j" we therefore
  * obtain a basic map that is equal to their union.
@@ -677,6 +680,8 @@ static enum isl_change is_adj_ineq_exten
 		if (isl_tab_add_ineq(info[i].tab, info[j].bmap->ineq[k]) < 0)
 			return isl_change_error;
 	}
+	if (isl_tab_detect_constants(info[i].tab) < 0)
+		return isl_change_error;
 
 	super = contains(&info[j], info[i].tab);
 	if (super < 0)
@@ -2298,72 +2303,263 @@ static int same_divs(__isl_keep isl_basi
 	return 1;
 }
 
-/* Expand info->tab in the same way info->bmap was expanded in
- * isl_basic_map_expand_divs using the expansion "exp" and
+/* Assuming that "tab" contains the equality constraints and
+ * the initial inequality constraints of "bmap", copy the remaining
+ * inequality constraints of "bmap" to "Tab".
+ */
+static isl_stat copy_ineq(struct isl_tab *tab, __isl_keep isl_basic_map *bmap)
+{
+	int i, n_ineq;
+
+	if (!bmap)
+		return isl_stat_error;
+
+	n_ineq = tab->n_con - tab->n_eq;
+	for (i = n_ineq; i < bmap->n_ineq; ++i)
+		if (isl_tab_add_ineq(tab, bmap->ineq[i]) < 0)
+			return isl_stat_error;
+
+	return isl_stat_ok;
+}
+
+/* Description of an integer division that is added
+ * during an expansion.
+ * "pos" is the position of the corresponding variable.
+ * "cst" indicates whether this integer division has a fixed value.
+ * "val" contains the fixed value, if the value is fixed.
+ */
+struct isl_expanded {
+	int pos;
+	isl_bool cst;
+	isl_int val;
+};
+
+/* For each of the "n" integer division variables "expanded",
+ * if the variable has a fixed value, then add two inequality
+ * constraints expressing the fixed value.
+ * Otherwise, add the corresponding div constraints.
+ * The caller is responsible for removing the div constraints
+ * that it added for all these "n" integer divisions.
+ *
+ * The div constraints and the pair of inequality constraints
+ * forcing the fixed value cannot both be added for a given variable
+ * as the combination may render some of the original constraints redundant.
+ * These would then be ignored during the coalescing detection,
+ * while they could remain in the fused result.
+ *
+ * The two added inequality constraints are
+ *
+ *	-a + v >= 0
+ *	a - v >= 0
+ *
+ * with "a" the variable and "v" its fixed value.
+ * The facet corresponding to one of these two constraints is selected
+ * in the tableau to ensure that the pair of inequality constraints
+ * is treated as an equality constraint.
+ *
+ * The information in info->ineq is thrown away because it was
+ * computed in terms of div constraints, while some of those
+ * have now been replaced by these pairs of inequality constraints.
+ */
+static isl_stat fix_constant_divs(struct isl_coalesce_info *info,
+	int n, struct isl_expanded *expanded)
+{
+	unsigned o_div;
+	int i;
+	isl_vec *ineq;
+
+	o_div = isl_basic_map_offset(info->bmap, isl_dim_div) - 1;
+	ineq = isl_vec_alloc(isl_tab_get_ctx(info->tab), 1 + info->tab->n_var);
+	if (!ineq)
+		return isl_stat_error;
+	isl_seq_clr(ineq->el + 1, info->tab->n_var);
+
+	for (i = 0; i < n; ++i) {
+		if (!expanded[i].cst) {
+			info->bmap = isl_basic_map_extend_constraints(
+						info->bmap, 0, 2);
+			if (isl_basic_map_add_div_constraints(info->bmap,
+						expanded[i].pos - o_div) < 0)
+				break;
+		} else {
+			isl_int_set_si(ineq->el[1 + expanded[i].pos], -1);
+			isl_int_set(ineq->el[0], expanded[i].val);
+			info->bmap = isl_basic_map_add_ineq(info->bmap,
+								ineq->el);
+			isl_int_set_si(ineq->el[1 + expanded[i].pos], 1);
+			isl_int_neg(ineq->el[0], expanded[i].val);
+			info->bmap = isl_basic_map_add_ineq(info->bmap,
+								ineq->el);
+			isl_int_set_si(ineq->el[1 + expanded[i].pos], 0);
+		}
+		if (copy_ineq(info->tab, info->bmap) < 0)
+			break;
+		if (expanded[i].cst &&
+		    isl_tab_select_facet(info->tab, info->tab->n_con - 1) < 0)
+			break;
+	}
+
+	isl_vec_free(ineq);
+
+	clear_status(info);
+	init_status(info);
+
+	return i < n ? isl_stat_error : isl_stat_ok;
+}
+
+/* Insert the "n" integer division variables "expanded"
+ * into info->tab and info->bmap and
  * update info->ineq with respect to the redundant constraints
- * in the resulting tableau. "bmap" is the original version
- * of info->bmap, i.e., the one that corresponds to the current
- * state of info->tab.  The number of constraints in "bmap"
+ * in the resulting tableau.
+ * "bmap" contains the result of this insertion in info->bmap,
+ * while info->bmap is the original version
+ * of "bmap", i.e., the one that corresponds to the current
+ * state of info->tab.  The number of constraints in info->bmap
  * is assumed to be the same as the number of constraints
  * in info->tab.  This is required to be able to detect
- * the extra constraints in info->bmap.
+ * the extra constraints in "bmap".
  *
  * In particular, introduce extra variables corresponding
  * to the extra integer divisions and add the div constraints
- * that were added to info->bmap after info->tab was created
- * from the original info->bmap.
+ * that were added to "bmap" after info->tab was created
+ * from info->bmap.
+ * Furthermore, check if these extra integer divisions happen
+ * to attain a fixed integer value in info->tab.
+ * If so, replace the corresponding div constraints by pairs
+ * of inequality constraints that fix these
+ * integer divisions to their single integer values.
+ * Replace info->bmap by "bmap" to match the changes to info->tab.
  * info->ineq was computed without a tableau and therefore
  * does not take into account the redundant constraints
  * in the tableau.  Mark them here.
+ * There is no need to check the newly added div constraints
+ * since they cannot be redundant.
+ * The redundancy check is not performed when constants have been discovered
+ * since info->ineq is completely thrown away in this case.
  */
-static isl_stat expand_tab(struct isl_coalesce_info *info, int *exp,
-	__isl_keep isl_basic_map *bmap)
+static isl_stat tab_insert_divs(struct isl_coalesce_info *info,
+	int n, struct isl_expanded *expanded, __isl_take isl_basic_map *bmap)
 {
-	unsigned total, pos, n_div;
-	int extra_var;
-	int i, n, j, n_ineq;
+	int i, n_ineq;
 	unsigned n_eq;
+	struct isl_tab_undo *snap;
+	int any;
 
 	if (!bmap)
 		return isl_stat_error;
-	if (bmap->n_eq + bmap->n_ineq != info->tab->n_con)
+	if (info->bmap->n_eq + info->bmap->n_ineq != info->tab->n_con)
 		isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
 			"original tableau does not correspond "
-			"to original basic map", return isl_stat_error);
+			"to original basic map", goto error);
 
-	total = isl_basic_map_dim(info->bmap, isl_dim_all);
-	n_div = isl_basic_map_dim(info->bmap, isl_dim_div);
+	if (isl_tab_extend_vars(info->tab, n) < 0)
+		goto error;
+	if (isl_tab_extend_cons(info->tab, 2 * n) < 0)
+		goto error;
+
+	for (i = 0; i < n; ++i) {
+		if (isl_tab_insert_var(info->tab, expanded[i].pos) < 0)
+			goto error;
+	}
+
+	snap = isl_tab_snap(info->tab);
+
+	n_ineq = info->tab->n_con - info->tab->n_eq;
+	if (copy_ineq(info->tab, bmap) < 0)
+		goto error;
+
+	isl_basic_map_free(info->bmap);
+	info->bmap = bmap;
+
+	any = 0;
+	for (i = 0; i < n; ++i) {
+		expanded[i].cst = isl_tab_is_constant(info->tab,
+					    expanded[i].pos, &expanded[i].val);
+		if (expanded[i].cst < 0)
+			return isl_stat_error;
+		if (expanded[i].cst)
+			any = 1;
+	}
+
+	if (any) {
+		if (isl_tab_rollback(info->tab, snap) < 0)
+			return isl_stat_error;
+		info->bmap = isl_basic_map_cow(info->bmap);
+		if (isl_basic_map_free_inequality(info->bmap, 2 * n) < 0)
+			return isl_stat_error;
+
+		return fix_constant_divs(info, n, expanded);
+	}
+
+	n_eq = info->bmap->n_eq;
+	for (i = 0; i < n_ineq; ++i) {
+		if (isl_tab_is_redundant(info->tab, n_eq + i))
+			info->ineq[i] = STATUS_REDUNDANT;
+	}
+
+	return isl_stat_ok;
+error:
+	isl_basic_map_free(bmap);
+	return isl_stat_error;
+}
+
+/* Expand info->tab and info->bmap in the same way "bmap" was expanded
+ * in isl_basic_map_expand_divs using the expansion "exp" and
+ * update info->ineq with respect to the redundant constraints
+ * in the resulting tableau. info->bmap is the original version
+ * of "bmap", i.e., the one that corresponds to the current
+ * state of info->tab.  The number of constraints in info->bmap
+ * is assumed to be the same as the number of constraints
+ * in info->tab.  This is required to be able to detect
+ * the extra constraints in "bmap".
+ *
+ * Extract the positions where extra local variables are introduced
+ * from "exp" and call tab_insert_divs.
+ */
+static isl_stat expand_tab(struct isl_coalesce_info *info, int *exp,
+	__isl_take isl_basic_map *bmap)
+{
+	isl_ctx *ctx;
+	struct isl_expanded *expanded;
+	int i, j, k, n;
+	int extra_var;
+	unsigned total, pos, n_div;
+	isl_stat r;
+
+	total = isl_basic_map_dim(bmap, isl_dim_all);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
 	pos = total - n_div;
 	extra_var = total - info->tab->n_var;
 	n = n_div - extra_var;
 
-	if (isl_tab_extend_vars(info->tab, extra_var) < 0)
-		return isl_stat_error;
-	if (isl_tab_extend_cons(info->tab, 2 * extra_var) < 0)
-		return isl_stat_error;
+	ctx = isl_basic_map_get_ctx(bmap);
+	expanded = isl_calloc_array(ctx, struct isl_expanded, extra_var);
+	if (extra_var && !expanded)
+		goto error;
 
 	i = 0;
+	k = 0;
 	for (j = 0; j < n_div; ++j) {
 		if (i < n && exp[i] == j) {
 			++i;
 			continue;
 		}
-		if (isl_tab_insert_var(info->tab, pos + j) < 0)
-			return isl_stat_error;
+		expanded[k++].pos = pos + j;
 	}
 
-	n_ineq = info->tab->n_con - info->tab->n_eq;
-	for (i = n_ineq; i < info->bmap->n_ineq; ++i)
-		if (isl_tab_add_ineq(info->tab, info->bmap->ineq[i]) < 0)
-			return isl_stat_error;
+	for (k = 0; k < extra_var; ++k)
+		isl_int_init(expanded[k].val);
 
-	n_eq = info->bmap->n_eq;
-	for (i = 0; i < info->bmap->n_ineq; ++i) {
-		if (isl_tab_is_redundant(info->tab, n_eq + i))
-			info->ineq[i] = STATUS_REDUNDANT;
-	}
+	r = tab_insert_divs(info, extra_var, expanded, bmap);
 
-	return isl_stat_ok;
+	for (k = 0; k < extra_var; ++k)
+		isl_int_clear(expanded[k].val);
+	free(expanded);
+
+	return r;
+error:
+	isl_basic_map_free(bmap);
+	return isl_stat_error;
 }
 
 /* Check if the union of the basic maps represented by info[i] and info[j]
@@ -2412,10 +2608,9 @@ static enum isl_change coalesce_expand_t
 		return known < 0 ? isl_change_error : isl_change_none;
 	}
 
-	bmap_i = info[i].bmap;
-	info[i].bmap = isl_basic_map_copy(bmap);
+	bmap_i = isl_basic_map_copy(info[i].bmap);
 	snap = isl_tab_snap(info[i].tab);
-	if (!info[i].bmap || expand_tab(&info[i], exp, bmap_i) < 0)
+	if (expand_tab(&info[i], exp, bmap) < 0)
 		change = isl_change_error;
 
 	init_status(&info[j]);
@@ -2433,7 +2628,6 @@ static enum isl_change coalesce_expand_t
 			change = isl_change_error;
 	}
 
-	isl_basic_map_free(bmap);
 	return change;
 }
 

Modified: polly/trunk/lib/External/isl/isl_tab.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tab.c?rev=290681&r1=290680&r2=290681&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_tab.c (original)
+++ polly/trunk/lib/External/isl/isl_tab.c Wed Dec 28 13:35:49 2016
@@ -2,6 +2,7 @@
  * Copyright 2008-2009 Katholieke Universiteit Leuven
  * Copyright 2013      Ecole Normale Superieure
  * Copyright 2014      INRIA Rocquencourt
+ * Copyright 2016      Sven Verdoolaege
  *
  * Use of this software is governed by the MIT license
  *
@@ -2010,13 +2011,21 @@ error:
 	return NULL;
 }
 
+/* Does the sample value of row "row" of "tab" involve the big parameter,
+ * if any?
+ */
+static int row_is_big(struct isl_tab *tab, int row)
+{
+	return tab->M && !isl_int_is_zero(tab->mat->row[row][2]);
+}
+
 static int row_is_manifestly_zero(struct isl_tab *tab, int row)
 {
 	unsigned off = 2 + tab->M;
 
 	if (!isl_int_is_zero(tab->mat->row[row][1]))
 		return 0;
-	if (tab->M && !isl_int_is_zero(tab->mat->row[row][2]))
+	if (row_is_big(tab, row))
 		return 0;
 	return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
 					tab->n_col - tab->n_dead) == -1;
@@ -2576,6 +2585,22 @@ struct isl_vec *isl_tab_get_sample_value
 	return vec;
 }
 
+/* Store the sample value of "var" of "tab" rounded up (if sgn > 0)
+ * or down (if sgn < 0) to the nearest integer in *v.
+ */
+static void get_rounded_sample_value(struct isl_tab *tab,
+	struct isl_tab_var *var, int sgn, isl_int *v)
+{
+	if (!var->is_row)
+		isl_int_set_si(*v, 0);
+	else if (sgn > 0)
+		isl_int_cdiv_q(*v, tab->mat->row[var->index][1],
+				   tab->mat->row[var->index][0]);
+	else
+		isl_int_fdiv_q(*v, tab->mat->row[var->index][1],
+				   tab->mat->row[var->index][0]);
+}
+
 /* Update "bmap" based on the results of the tableau "tab".
  * In particular, implicit equalities are made explicit, redundant constraints
  * are removed and if the sample value happens to be integer, it is stored
@@ -3187,7 +3212,7 @@ int isl_tab_is_equality(struct isl_tab *
 
 	off = 2 + tab->M;
 	return isl_int_is_zero(tab->mat->row[row][1]) &&
-		(!tab->M || isl_int_is_zero(tab->mat->row[row][2])) &&
+		!row_is_big(tab, row) &&
 		isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
 					tab->n_col - tab->n_dead) == -1;
 }
@@ -3264,8 +3289,7 @@ enum isl_lp_result isl_tab_min(struct is
 			isl_int_set(*opt, tab->mat->row[var->index][1]);
 			isl_int_set(*opt_denom, tab->mat->row[var->index][0]);
 		} else
-			isl_int_cdiv_q(*opt, tab->mat->row[var->index][1],
-					     tab->mat->row[var->index][0]);
+			get_rounded_sample_value(tab, var, 1, opt);
 	}
 	if (isl_tab_rollback(tab, snap) < 0)
 		return isl_lp_error;
@@ -3294,6 +3318,241 @@ int isl_tab_is_redundant(struct isl_tab
 	return tab->con[con].is_row && tab->con[con].index < tab->n_redundant;
 }
 
+/* Is variable "var" of "tab" fixed to a constant value by its row
+ * in the tableau?
+ * If so and if "value" is not NULL, then store this constant value
+ * in "value".
+ *
+ * That is, is it a row variable that only has non-zero coefficients
+ * for dead columns?
+ */
+static isl_bool is_constant(struct isl_tab *tab, struct isl_tab_var *var,
+	isl_int *value)
+{
+	unsigned off = 2 + tab->M;
+	isl_mat *mat = tab->mat;
+	int n;
+	int row;
+	int pos;
+
+	if (!var->is_row)
+		return isl_bool_false;
+	row = var->index;
+	if (row_is_big(tab, row))
+		return isl_bool_false;
+	n = tab->n_col - tab->n_dead;
+	pos = isl_seq_first_non_zero(mat->row[row] + off + tab->n_dead, n);
+	if (pos != -1)
+		return isl_bool_false;
+	if (value)
+		isl_int_divexact(*value, mat->row[row][1], mat->row[row][0]);
+	return isl_bool_true;
+}
+
+/* Has the variable "var' of "tab" reached a value that is greater than
+ * or equal (if sgn > 0) or smaller than or equal (if sgn < 0) to "target"?
+ * "tmp" has been initialized by the caller and can be used
+ * to perform local computations.
+ *
+ * If the sample value involves the big parameter, then any value
+ * is reached.
+ * Otherwise check if n/d >= t, i.e., n >= d * t (if sgn > 0)
+ * or n/d <= t, i.e., n <= d * t (if sgn < 0).
+ */
+static int reached(struct isl_tab *tab, struct isl_tab_var *var, int sgn,
+	isl_int target, isl_int *tmp)
+{
+	if (row_is_big(tab, var->index))
+		return 1;
+	isl_int_mul(*tmp, tab->mat->row[var->index][0], target);
+	if (sgn > 0)
+		return isl_int_ge(tab->mat->row[var->index][1], *tmp);
+	else
+		return isl_int_le(tab->mat->row[var->index][1], *tmp);
+}
+
+/* Can variable "var" of "tab" attain the value "target" by
+ * pivoting up (if sgn > 0) or down (if sgn < 0)?
+ * If not, then pivot up [down] to the greatest [smallest]
+ * rational value.
+ * "tmp" has been initialized by the caller and can be used
+ * to perform local computations.
+ *
+ * If the variable is manifestly unbounded in the desired direction,
+ * then it can attain any value.
+ * Otherwise, it can be moved to a row.
+ * Continue pivoting until the target is reached.
+ * If no more pivoting can be performed, the maximal [minimal]
+ * rational value has been reached and the target cannot be reached.
+ * If the variable would be pivoted into a manifestly unbounded column,
+ * then the target can be reached.
+ */
+static isl_bool var_reaches(struct isl_tab *tab, struct isl_tab_var *var,
+	int sgn, isl_int target, isl_int *tmp)
+{
+	int row, col;
+
+	if (sgn < 0 && min_is_manifestly_unbounded(tab, var))
+		return isl_bool_true;
+	if (sgn > 0 && max_is_manifestly_unbounded(tab, var))
+		return isl_bool_true;
+	if (to_row(tab, var, sgn) < 0)
+		return isl_bool_error;
+	while (!reached(tab, var, sgn, target, tmp)) {
+		find_pivot(tab, var, var, sgn, &row, &col);
+		if (row == -1)
+			return isl_bool_false;
+		if (row == var->index)
+			return isl_bool_true;
+		if (isl_tab_pivot(tab, row, col) < 0)
+			return isl_bool_error;
+	}
+
+	return isl_bool_true;
+}
+
+/* Check if variable "var" of "tab" can only attain a single (integer)
+ * value, and, if so, add an equality constraint to fix the variable
+ * to this single value and store the result in "target".
+ * "target" and "tmp" have been initialized by the caller.
+ *
+ * Given the current sample value, round it down and check
+ * whether it is possible to attain a strictly smaller integer value.
+ * If so, the variable is not restricted to a single integer value.
+ * Otherwise, the search stops at the smallest rational value.
+ * Round up this value and check whether it is possible to attain
+ * a strictly greater integer value.
+ * If so, the variable is not restricted to a single integer value.
+ * Otherwise, the search stops at the greatest rational value.
+ * If rounding down this value yields a value that is different
+ * from rounding up the smallest rational value, then the variable
+ * cannot attain any integer value.  Mark the tableau empty.
+ * Otherwise, add an equality constraint that fixes the variable
+ * to the single integer value found.
+ */
+static isl_bool detect_constant_with_tmp(struct isl_tab *tab,
+	struct isl_tab_var *var, isl_int *target, isl_int *tmp)
+{
+	isl_bool reached;
+	isl_vec *eq;
+	int pos;
+	isl_stat r;
+
+	get_rounded_sample_value(tab, var, -1, target);
+	isl_int_sub_ui(*target, *target, 1);
+	reached = var_reaches(tab, var, -1, *target, tmp);
+	if (reached < 0 || reached)
+		return isl_bool_not(reached);
+	get_rounded_sample_value(tab, var, 1, target);
+	isl_int_add_ui(*target, *target, 1);
+	reached = var_reaches(tab, var, 1, *target, tmp);
+	if (reached < 0 || reached)
+		return isl_bool_not(reached);
+	get_rounded_sample_value(tab, var, -1, tmp);
+	isl_int_sub_ui(*target, *target, 1);
+	if (isl_int_ne(*target, *tmp)) {
+		if (isl_tab_mark_empty(tab) < 0)
+			return isl_bool_error;
+		return isl_bool_false;
+	}
+
+	if (isl_tab_extend_cons(tab, 1) < 0)
+		return isl_bool_error;
+	eq = isl_vec_alloc(isl_tab_get_ctx(tab), 1 + tab->n_var);
+	if (!eq)
+		return isl_bool_error;
+	pos = var - tab->var;
+	isl_seq_clr(eq->el + 1, tab->n_var);
+	isl_int_set_si(eq->el[1 + pos], -1);
+	isl_int_set(eq->el[0], *target);
+	r = isl_tab_add_eq(tab, eq->el);
+	isl_vec_free(eq);
+
+	return r < 0 ? isl_bool_error : isl_bool_true;
+}
+
+/* Check if variable "var" of "tab" can only attain a single (integer)
+ * value, and, if so, add an equality constraint to fix the variable
+ * to this single value and store the result in "value" (if "value"
+ * is not NULL).
+ *
+ * If the current sample value involves the big parameter,
+ * then the variable cannot have a fixed integer value.
+ * If the variable is already fixed to a single value by its row, then
+ * there is no need to add another equality constraint.
+ *
+ * Otherwise, allocate some temporary variables and continue
+ * with detect_constant_with_tmp.
+ */
+static isl_bool get_constant(struct isl_tab *tab, struct isl_tab_var *var,
+	isl_int *value)
+{
+	isl_int target, tmp;
+	isl_bool is_cst;
+
+	if (var->is_row && row_is_big(tab, var->index))
+		return isl_bool_false;
+	is_cst = is_constant(tab, var, value);
+	if (is_cst < 0 || is_cst)
+		return is_cst;
+
+	if (!value)
+		isl_int_init(target);
+	isl_int_init(tmp);
+
+	is_cst = detect_constant_with_tmp(tab, var,
+					    value ? value : &target, &tmp);
+
+	isl_int_clear(tmp);
+	if (!value)
+		isl_int_clear(target);
+
+	return is_cst;
+}
+
+/* Check if variable "var" of "tab" can only attain a single (integer)
+ * value, and, if so, add an equality constraint to fix the variable
+ * to this single value and store the result in "value" (if "value"
+ * is not NULL).
+ *
+ * For rational tableaus, nothing needs to be done.
+ */
+isl_bool isl_tab_is_constant(struct isl_tab *tab, int var, isl_int *value)
+{
+	if (!tab)
+		return isl_bool_error;
+	if (var < 0 || var >= tab->n_var)
+		isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
+			"position out of bounds", return isl_bool_error);
+	if (tab->rational)
+		return isl_bool_false;
+
+	return get_constant(tab, &tab->var[var], value);
+}
+
+/* Check if any of the variables of "tab" can only attain a single (integer)
+ * value, and, if so, add equality constraints to fix those variables
+ * to these single values.
+ *
+ * For rational tableaus, nothing needs to be done.
+ */
+isl_stat isl_tab_detect_constants(struct isl_tab *tab)
+{
+	int i;
+
+	if (!tab)
+		return isl_stat_error;
+	if (tab->rational)
+		return isl_stat_ok;
+
+	for (i = 0; i < tab->n_var; ++i) {
+		if (get_constant(tab, &tab->var[i], NULL) < 0)
+			return isl_stat_error;
+	}
+
+	return isl_stat_ok;
+}
+
 /* Take a snapshot of the tableau that can be restored by a call to
  * isl_tab_rollback.
  */

Modified: polly/trunk/lib/External/isl/isl_tab.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tab.h?rev=290681&r1=290680&r2=290681&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_tab.h (original)
+++ polly/trunk/lib/External/isl/isl_tab.h Wed Dec 28 13:35:49 2016
@@ -317,6 +317,8 @@ int isl_tab_save_samples(struct isl_tab
 
 struct isl_tab *isl_tab_detect_equalities(struct isl_tab *tab,
 	struct isl_tab *tab_cone) WARN_UNUSED;
+isl_bool isl_tab_is_constant(struct isl_tab *tab, int var, isl_int *value);
+isl_stat isl_tab_detect_constants(struct isl_tab *tab);
 
 int isl_tab_push_callback(struct isl_tab *tab,
 	struct isl_tab_callback *callback) WARN_UNUSED;

Modified: polly/trunk/lib/External/isl/isl_test.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_test.c?rev=290681&r1=290680&r2=290681&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_test.c (original)
+++ polly/trunk/lib/External/isl/isl_test.c Wed Dec 28 13:35:49 2016
@@ -1878,6 +1878,19 @@ struct {
 			"(a < 0 and 3*floor((a)/3) < a) }" },
 	{ 1, "{ [a] : (a <= 0 and 3*floor((a)/3) = a) or "
 			"(a < -1 and 3*floor((a)/3) < a) }" },
+	{ 1, "{ [a, b] : a <= 1024 and b >= 0 and "
+		"((-31 - a + b <= 32*floor((-1 - a)/32) <= -33 + b and "
+		  "32*floor((-1 - a)/32) <= -16 + b + 16*floor((-1 - a)/16))"
+		"or (2 <= a <= 15 and b < a)) }" },
+	{ 1, "{ [a] : a > 0 and ((16*floor((a)/16) < a and "
+			"32*floor((a)/32) < a) or a <= 15) }" },
+	{ 1, "{ [a, b, c, d] : (-a + d) mod 64 = 0 and a <= 8 and b <= 1 and "
+			"10 - a <= c <= 3 and d >= 5 and 9 - 64b <= d <= 70;"
+	    "[a, b = 1, c, d] : (-a + d) mod 64 = 0 and a <= 8 and c >= 4 and "
+			"10 - a <= c <= 5 and 5 <= d <= 73 - c }" },
+	{ 1, "[n, m] -> { S_0[i] : (-n + i) mod 3 = 0 and m >= 3 + n and "
+			    "i >= n and 3*floor((2 + n + 2m)/3) <= n + 3m - i; "
+			 "S_0[n] : n <= m <= 2 + n }" },
 };
 
 /* A specialized coalescing test case that would result




More information about the llvm-commits mailing list