/* Given a stride constraint on iterator i (specified by level) of the form * * i = f(outer iterators) + stride * f(existentials) * * extract f as an isl_aff. */ static isl_aff *extract_stride_offset(__isl_keep isl_constraint *c, int level, CloogStride *stride) { int i; isl_space *dim = isl_constraint_get_space(c); isl_local_space *ls = isl_local_space_from_space(dim); isl_aff *offset = isl_aff_zero_on_domain(ls); isl_int u; unsigned nparam, nvar; isl_int_init(u); nparam = isl_constraint_dim(c, isl_dim_param); nvar = isl_constraint_dim(c, isl_dim_set); for (i = 0; i < nparam; ++i) { isl_constraint_get_coefficient(c, isl_dim_param, i, &u); isl_int_mul(u, u, stride->factor); offset = isl_aff_set_coefficient(offset, isl_dim_param, i, u); } for (i = 0; i < nvar; ++i) { if (i == level - 1) continue; isl_constraint_get_coefficient(c, isl_dim_set, i, &u); isl_int_mul(u, u, stride->factor); offset = isl_aff_set_coefficient(offset, isl_dim_in, i, u); } isl_constraint_get_constant(c, &u); isl_int_mul(u, u, stride->factor); offset = isl_aff_set_constant(offset, u); isl_int_clear(u); return offset; }
/** * cloog_constraint_equal_type function : * This function returns the type of the equality in the constraint (line) of * (constraints) for the element (level). An equality is 'constant' iff all * other factors are null except the constant one. It is a 'pure item' iff * it is equal or opposite to a single variable or parameter. * Otherwise it is an 'affine expression'. * For instance: * i = -13 is constant, i = j, j = -M are pure items, * j = 2*M, i = j+1, 2*j = M are affine expressions. * * - constraints is the matrix of constraints, * - level is the column number in equal of the element which is 'equal to', */ static int cloog_constraint_equal_type(CloogConstraint *cc, int level) { int i; isl_int c; int type = EQTYPE_NONE; struct isl_constraint *constraint = cloog_constraint_to_isl(cc); isl_int_init(c); isl_constraint_get_constant(constraint, &c); if (!isl_int_is_zero(c)) type = EQTYPE_CONSTANT; isl_constraint_get_coefficient(constraint, isl_dim_set, level - 1, &c); if (!isl_int_is_one(c) && !isl_int_is_negone(c)) type = EQTYPE_EXAFFINE; for (i = 0; i < isl_constraint_dim(constraint, isl_dim_param); ++i) { isl_constraint_get_coefficient(constraint, isl_dim_param, i, &c); if (isl_int_is_zero(c)) continue; if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) || type != EQTYPE_NONE) { type = EQTYPE_EXAFFINE; break; } type = EQTYPE_PUREITEM; } for (i = 0; i < isl_constraint_dim(constraint, isl_dim_set); ++i) { if (i == level - 1) continue; isl_constraint_get_coefficient(constraint, isl_dim_set, i, &c); if (isl_int_is_zero(c)) continue; if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) || type != EQTYPE_NONE) { type = EQTYPE_EXAFFINE; break; } type = EQTYPE_PUREITEM; } for (i = 0; i < isl_constraint_dim(constraint, isl_dim_div); ++i) { isl_constraint_get_coefficient(constraint, isl_dim_div, i, &c); if (isl_int_is_zero(c)) continue; if ((!isl_int_is_one(c) && !isl_int_is_negone(c)) || type != EQTYPE_NONE) { type = EQTYPE_EXAFFINE; break; } type = EQTYPE_PUREITEM; } isl_int_clear(c); if (type == EQTYPE_NONE) type = EQTYPE_CONSTANT; return type; }
/// 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; }
static struct cloog_isl_dim constraint_cloog_dim_to_isl_dim( CloogConstraint *constraint, int pos) { enum isl_dim_type types[] = { isl_dim_set, isl_dim_div, isl_dim_param }; int i; struct cloog_isl_dim ci_dim; for (i = 0; i < 3; ++i) { isl_constraint *c = cloog_constraint_to_isl(constraint); unsigned dim = isl_constraint_dim(c, types[i]); if (pos < dim) { ci_dim.type = types[i]; ci_dim.pos = pos; return ci_dim; } pos -= dim; } assert(0); }
int cloog_constraint_total_dimension(CloogConstraint *constraint) { isl_constraint *c; c = cloog_constraint_to_isl(constraint); return isl_constraint_dim(c, isl_dim_all); }
/* 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; }