/* Check if the variable (e) at position level is defined by a
 * pair of inequalities
 *		 <a, i> + -m e +  <b, p> + k1 >= 0
 *		<-a, i> +  m e + <-b, p> + k2 >= 0
 * with 0 <= k1 + k2 < m
 * If so return the row number of the upper bound and set *lower
 * to the row number of the lower bound.  If not, return -1.
 *
 * If the variable at position level occurs in any other constraint,
 * then we currently return -1.  The modulo guard that we would generate
 * would still be correct, but we would also need to generate
 * guards corresponding to the other constraints, and this has not
 * been implemented yet.
 */
CloogConstraint *cloog_constraint_set_defining_inequalities(
	CloogConstraintSet *constraints,
	int level, CloogConstraint **lower, int nb_par)
{
	struct isl_constraint *u;
	struct isl_constraint *l;
	struct cloog_isl_dim dim;
	struct isl_basic_set *bset;
	struct cloog_isl_other other;

	bset = cloog_constraints_set_to_isl(constraints);
	dim = set_cloog_dim_to_isl_dim(constraints, level - 1);
	if (!isl_basic_set_has_defining_inequalities(bset, dim.type, dim.pos,
								&l, &u))
		return cloog_constraint_invalid();

	other.l = l;
	other.u = u;
	other.found = 0;
	other.level = level;
	isl_basic_set_foreach_constraint(bset, &check_other_constraint, &other);
	if (other.found) {
		isl_constraint_free(l);
		isl_constraint_free(u);
		*lower = NULL;
		return NULL;
	}
	*lower = cloog_constraint_from_isl_constraint(l);
	return cloog_constraint_from_isl_constraint(u);
}
Exemple #2
0
/* Given a lower and upper bound on the final variable and constraints
 * on the remaining variables where these bounds are active,
 * eliminate the variable from data->poly based on these bounds.
 * If the polynomial has been determined to be monotonic
 * in the variable, then simply plug in the appropriate bound.
 * If the current polynomial is tight and if this bound is integer,
 * then the result is still tight.  In all other cases, the results
 * may not be tight.
 * Otherwise, plug in the largest bound (in absolute value) in
 * the positive terms (if an upper bound is wanted) or the negative terms
 * (if a lower bounded is wanted) and the other bound in the other terms.
 *
 * If all variables have been eliminated, then record the result.
 * Ohterwise, recurse on the next variable.
 */
static isl_stat propagate_on_bound_pair(__isl_take isl_constraint *lower,
	__isl_take isl_constraint *upper, __isl_take isl_basic_set *bset,
	void *user)
{
	struct range_data *data = (struct range_data *)user;
	int save_tight = data->tight;
	isl_qpolynomial *poly;
	isl_stat r;
	unsigned nvar;

	nvar = isl_basic_set_dim(bset, isl_dim_set);

	if (data->monotonicity) {
		isl_qpolynomial *sub;
		isl_space *dim = isl_qpolynomial_get_domain_space(data->poly);
		if (data->monotonicity * data->sign > 0) {
			if (data->tight)
				data->tight = bound_is_integer(upper, nvar);
			sub = bound2poly(upper, dim, nvar, 1);
			isl_constraint_free(lower);
		} else {
			if (data->tight)
				data->tight = bound_is_integer(lower, nvar);
			sub = bound2poly(lower, dim, nvar, -1);
			isl_constraint_free(upper);
		}
		poly = isl_qpolynomial_copy(data->poly);
		poly = plug_in_at_pos(poly, nvar, sub, data);
		poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1);
	} else {
		isl_qpolynomial *l, *u;
		isl_qpolynomial *pos, *neg;
		isl_space *dim = isl_qpolynomial_get_domain_space(data->poly);
		unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
		int sign = data->sign * data->signs[nparam + nvar];

		data->tight = 0;

		u = bound2poly(upper, isl_space_copy(dim), nvar, 1);
		l = bound2poly(lower, dim, nvar, -1);

		pos = isl_qpolynomial_terms_of_sign(data->poly, data->signs, sign);
		neg = isl_qpolynomial_terms_of_sign(data->poly, data->signs, -sign);

		pos = plug_in_at_pos(pos, nvar, u, data);
		neg = plug_in_at_pos(neg, nvar, l, data);

		poly = isl_qpolynomial_add(pos, neg);
		poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1);
	}

	if (isl_basic_set_dim(bset, isl_dim_set) == 0)
		r = add_guarded_poly(bset, poly, data);
	else
		r = propagate_on_domain(bset, poly, data);

	data->tight = save_tight;

	return r;
}
/* Update the given lower bound on level such that it satisfies the stride
 * constraint.  The computation performed here is essentially the same
 * as that performed in constraint_stride_lower_c.
 *
 * We update the constraint
 *
 *	a i + f >= 0
 *
 * to
 *
 *	i >= s * ceil((-f/a - d)/s) + d
 *
 * with s the stride and d the offset encoded in the stride constraint.
 */
CloogConstraint *cloog_constraint_stride_lower_bound(CloogConstraint *c,
	int level, CloogStride *stride)
{
	isl_constraint *stride_c = cloog_constraint_to_isl(stride->constraint);
	isl_constraint *bound = cloog_constraint_to_isl(c);
	isl_aff *offset;
	isl_aff *lower;

	lower = isl_constraint_get_bound(bound, isl_dim_set, level - 1);
	isl_constraint_free(bound);

	offset = extract_stride_offset(stride_c, level, stride);

	lower = isl_aff_sub(lower, isl_aff_copy(offset));
	lower = isl_aff_scale_down(lower, stride->stride);
	lower = isl_aff_ceil(lower);
	lower = isl_aff_scale(lower, stride->stride);
	lower = isl_aff_add(lower, offset);
	lower = isl_aff_neg(lower);
	lower = isl_aff_add_coefficient_si(lower, isl_dim_in, level - 1, 1);

	bound = isl_inequality_from_aff(lower);

	return cloog_constraint_from_isl_constraint(bound);
}
static int cloog_isl_foreach_cb(__isl_take isl_constraint *c, void *user)
{
	struct cloog_isl_foreach *data = (struct cloog_isl_foreach *)user;
	int ret;

	if (isl_constraint_is_div_constraint(c)) {
		isl_constraint_free(c);
		return 0;
	}

	ret = data->fn(cloog_constraint_from_isl_constraint(c), data->user);

	isl_constraint_free(c);

	return ret;
}
void cloog_equal_free(CloogEqualities *equal)
{
	int i;

	for (i = 0; i < equal->n; ++i)
		isl_constraint_free(equal->constraints[i]);
	free(equal->constraints);
	free(equal->types);
	free(equal);
}
Exemple #6
0
/// Add an isl constraint to an ScopLib matrix.
///
/// @param user The matrix
/// @param c The constraint
int ScopLib::accessToMatrix_constraint(isl_constraint *c, void *user) {
  scoplib_matrix_p m = (scoplib_matrix_p) user;

  int nb_params = isl_constraint_dim(c, isl_dim_param);
  int nb_in = isl_constraint_dim(c, isl_dim_in);
  int nb_div = isl_constraint_dim(c, isl_dim_div);

  assert(!nb_div && "Existentially quantified variables not yet supported");

  scoplib_vector_p vec =
    scoplib_vector_malloc(nb_params + nb_in + 2);

  isl_int v;
  isl_int_init(v);

  // The access dimension has to be one.
  isl_constraint_get_coefficient(c, isl_dim_out, 0, &v);
  assert((isl_int_is_one(v) || isl_int_is_negone(v))
         && "Access relations not supported in scoplib");
  bool inverse = isl_int_is_one(v);

  // Assign variables
  for (int i = 0; i < nb_in; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_in, i, &v);

    if (inverse) isl_int_neg(v,v);

    isl_int_set(vec->p[i + 1], v);
  }

  // Assign parameters
  for (int i = 0; i < nb_params; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_param, i, &v);

    if (inverse) isl_int_neg(v,v);

    isl_int_set(vec->p[nb_in + i + 1], v);
  }

  // Assign constant
  isl_constraint_get_constant(c, &v);

  if (inverse) isl_int_neg(v,v);

  isl_int_set(vec->p[nb_in + nb_params + 1], v);

  scoplib_matrix_insert_vector(m, vec, m->NbRows);

  isl_constraint_free(c);
  isl_int_clear(v);

  return 0;
}
Exemple #7
0
/// Add an isl constraint to an ScopLib matrix.
///
/// @param user The matrix
/// @param c The constraint
int ScopLib::scatteringToMatrix_constraint(isl_constraint *c, void *user) {
  scoplib_matrix_p m = (scoplib_matrix_p) user;

  int nb_params = isl_constraint_dim(c, isl_dim_param);
  int nb_in = isl_constraint_dim(c, isl_dim_in);
  int nb_div = isl_constraint_dim(c, isl_dim_div);

  assert(!nb_div && "Existentially quantified variables not yet supported");

  scoplib_vector_p vec =
    scoplib_vector_malloc(nb_params + nb_in + 2);

  // Assign type
  if (isl_constraint_is_equality(c))
    scoplib_vector_tag_equality(vec);
  else
    scoplib_vector_tag_inequality(vec);

  isl_int v;
  isl_int_init(v);

  // Assign variables
  for (int i = 0; i < nb_in; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_in, i, &v);
    isl_int_set(vec->p[i + 1], v);
  }

  // Assign parameters
  for (int i = 0; i < nb_params; ++i) {
    isl_constraint_get_coefficient(c, isl_dim_param, i, &v);
    isl_int_set(vec->p[nb_in + i + 1], v);
  }

  // Assign constant
  isl_constraint_get_constant(c, &v);
  isl_int_set(vec->p[nb_in + nb_params + 1], v);

  scoplib_vector_p null =
    scoplib_vector_malloc(nb_params + nb_in + 2);

  vec = scoplib_vector_sub(null, vec);
  scoplib_matrix_insert_vector(m, vec, 0);

  isl_constraint_free(c);
  isl_int_clear(v);

  return 0;
}
/* Set other->found to 1 if the given constraint involves other->level
 * and is different from other->u and other->l.
 */
static int check_other_constraint(__isl_take isl_constraint *c, void *user)
{
	struct cloog_isl_other *other = user;
	CloogConstraint *cc;

	if (!isl_constraint_is_equal(c, other->l) &&
	    !isl_constraint_is_equal(c, other->u)) {
		cc = cloog_constraint_from_isl_constraint(c);
		if (cloog_constraint_involves(cc, other->level - 1))
			other->found = 1;
	}

	isl_constraint_free(c);

	return other->found ? -1 : 0;
}
void cloog_constraint_release(CloogConstraint *constraint)
{
	isl_constraint_free(cloog_constraint_to_isl(constraint));
}
/**
 * cloog_equal_del function :
 * This function reset the equality corresponding to the iterator (level)
 * in the equality matrix (equal).
 * - July 2nd 2002: first version. 
 */
void cloog_equal_del(CloogEqualities *equal, int level)
{ 
	equal->types[level-1] = EQTYPE_NONE;
	isl_constraint_free(equal->constraints[level - 1]);
	equal->constraints[level-1] = NULL;
}
Exemple #11
0
/* Check if constraint "c" imposes any stride on dimension data->pos
 * and, if so, update the stride information in "data".
 *
 * In order to impose a stride on the dimension, "c" needs to be an equality
 * and it needs to involve the dimension.  Note that "c" may also be
 * a div constraint and thus an inequality that we cannot use.
 *
 * Let c be of the form
 *
 *	h(p) + g * v * i + g * stride * f(alpha) = 0
 *
 * with h(p) an expression in terms of the parameters and other dimensions
 * and f(alpha) an expression in terms of the existentially quantified
 * variables.
 *
 * If "stride" is not zero and not one, then it represents a non-trivial stride
 * on "i".  We compute a and b such that
 *
 *	a v + b stride = 1
 *
 * We have
 *
 *	g v i = -h(p) + g stride f(alpha)
 *
 *	a g v i = -a h(p) + g stride f(alpha)
 *
 *	a g v i + b g stride i = -a h(p) + g stride * (...)
 *
 *	g i = -a h(p) + g stride * (...)
 *
 *	i = -a h(p)/g + stride * (...)
 *
 * The expression "-a h(p)/g" can therefore be used as offset.
 */
static isl_stat detect_stride(__isl_take isl_constraint *c, void *user)
{
	struct isl_detect_stride_data *data = user;
	int i, n_div;
	isl_ctx *ctx;
	isl_stat r = isl_stat_ok;
	isl_val *v, *stride, *m;
	isl_bool is_eq, relevant, has_stride;

	is_eq = isl_constraint_is_equality(c);
	relevant = isl_constraint_involves_dims(c, isl_dim_set, data->pos, 1);
	if (is_eq < 0 || relevant < 0)
		goto error;
	if (!is_eq || !relevant) {
		isl_constraint_free(c);
		return isl_stat_ok;
	}

	ctx = isl_constraint_get_ctx(c);
	stride = isl_val_zero(ctx);
	n_div = isl_constraint_dim(c, isl_dim_div);
	for (i = 0; i < n_div; ++i) {
		v = isl_constraint_get_coefficient_val(c, isl_dim_div, i);
		stride = isl_val_gcd(stride, v);
	}

	v = isl_constraint_get_coefficient_val(c, isl_dim_set, data->pos);
	m = isl_val_gcd(isl_val_copy(stride), isl_val_copy(v));
	stride = isl_val_div(stride, isl_val_copy(m));
	v = isl_val_div(v, isl_val_copy(m));

	has_stride = isl_val_gt_si(stride, 1);
	if (has_stride >= 0 && has_stride) {
		isl_aff *aff;
		isl_val *gcd, *a, *b;

		gcd = isl_val_gcdext(v, isl_val_copy(stride), &a, &b);
		isl_val_free(gcd);
		isl_val_free(b);

		aff = isl_constraint_get_aff(c);
		for (i = 0; i < n_div; ++i)
			aff = isl_aff_set_coefficient_si(aff,
							 isl_dim_div, i, 0);
		aff = isl_aff_set_coefficient_si(aff, isl_dim_in, data->pos, 0);
		aff = isl_aff_remove_unused_divs(aff);
		a = isl_val_neg(a);
		aff = isl_aff_scale_val(aff, a);
		aff = isl_aff_scale_down_val(aff, m);
		r = set_stride(data, stride, aff);
	} else {
		isl_val_free(stride);
		isl_val_free(m);
		isl_val_free(v);
	}

	isl_constraint_free(c);
	if (has_stride < 0)
		return isl_stat_error;
	return r;
error:
	isl_constraint_free(c);
	return isl_stat_error;
}