/* 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); }
/* 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); }
/// 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; }
/// 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; }
/* 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; }