/* 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; }
/* Compute a common lattice of solutions to the linear modulo * constraints specified by B and d. * See also the documentation of isl_mat_parameter_compression. * We put the matrix * * A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ] * * on a common denominator. This denominator D is the lcm of modulos d. * Since L_i = U_i^{-1} diag(d_i, 1, ... 1), we have * L_i^{-T} = U_i^T diag(d_i, 1, ... 1)^{-T} = U_i^T diag(1/d_i, 1, ..., 1). * Putting this on the common denominator, we have * D * L_i^{-T} = U_i^T diag(D/d_i, D, ..., D). */ static struct isl_mat *parameter_compression_multi( struct isl_mat *B, struct isl_vec *d) { int i, j, k; isl_int D; struct isl_mat *A = NULL, *U = NULL; struct isl_mat *T; unsigned size; isl_int_init(D); isl_vec_lcm(d, &D); size = B->n_col - 1; A = isl_mat_alloc(B->ctx, size, B->n_row * size); U = isl_mat_alloc(B->ctx, size, size); if (!U || !A) goto error; for (i = 0; i < B->n_row; ++i) { isl_seq_cpy(U->row[0], B->row[i] + 1, size); U = isl_mat_unimodular_complete(U, 1); if (!U) goto error; isl_int_divexact(D, D, d->block.data[i]); for (k = 0; k < U->n_col; ++k) isl_int_mul(A->row[k][i*size+0], D, U->row[0][k]); isl_int_mul(D, D, d->block.data[i]); for (j = 1; j < U->n_row; ++j) for (k = 0; k < U->n_col; ++k) isl_int_mul(A->row[k][i*size+j], D, U->row[j][k]); } A = isl_mat_left_hermite(A, 0, NULL, NULL); T = isl_mat_sub_alloc(A, 0, A->n_row, 0, A->n_row); T = isl_mat_lin_to_aff(T); if (!T) goto error; isl_int_set(T->row[0][0], D); T = isl_mat_right_inverse(T); if (!T) goto error; isl_assert(T->ctx, isl_int_is_one(T->row[0][0]), goto error); T = isl_mat_transpose(T); isl_mat_free(A); isl_mat_free(U); isl_int_clear(D); return T; error: isl_mat_free(A); isl_mat_free(U); isl_int_clear(D); return NULL; }
static isl_constraint * build_linearized_memory_access (isl_map *map, poly_dr_p pdr) { isl_constraint *res; isl_local_space *ls = isl_local_space_from_space (isl_map_get_space (map)); unsigned offset, nsubs; int i; isl_int size, subsize; res = isl_equality_alloc (ls); isl_int_init (size); isl_int_set_ui (size, 1); isl_int_init (subsize); isl_int_set_ui (subsize, 1); nsubs = isl_set_dim (pdr->extent, isl_dim_set); /* -1 for the already included L dimension. */ offset = isl_map_dim (map, isl_dim_out) - 1 - nsubs; res = isl_constraint_set_coefficient_si (res, isl_dim_out, offset + nsubs, -1); /* Go through all subscripts from last to first. First dimension is the alias set, ignore it. */ for (i = nsubs - 1; i >= 1; i--) { isl_space *dc; isl_aff *aff; res = isl_constraint_set_coefficient (res, isl_dim_out, offset + i, size); dc = isl_set_get_space (pdr->extent); aff = isl_aff_zero_on_domain (isl_local_space_from_space (dc)); aff = isl_aff_set_coefficient_si (aff, isl_dim_in, i, 1); isl_set_max (pdr->extent, aff, &subsize); isl_aff_free (aff); isl_int_mul (size, size, subsize); } isl_int_clear (subsize); isl_int_clear (size); return res; }
static void copy_solution(struct isl_vec *vec, int maximize, isl_int *opt, isl_int *opt_denom, PipQuast *sol) { int i; PipList *list; isl_int tmp; if (opt) { if (opt_denom) { isl_seq_cpy_from_pip(opt, &sol->list->vector->the_vector[0], 1); isl_seq_cpy_from_pip(opt_denom, &sol->list->vector->the_deno[0], 1); } else if (maximize) mpz_fdiv_q(*opt, sol->list->vector->the_vector[0], sol->list->vector->the_deno[0]); else mpz_cdiv_q(*opt, sol->list->vector->the_vector[0], sol->list->vector->the_deno[0]); } if (!vec) return; isl_int_init(tmp); isl_int_set_si(vec->el[0], 1); for (i = 0, list = sol->list->next; list; ++i, list = list->next) { isl_seq_cpy_from_pip(&vec->el[1 + i], &list->vector->the_deno[0], 1); isl_int_lcm(vec->el[0], vec->el[0], vec->el[1 + i]); } for (i = 0, list = sol->list->next; list; ++i, list = list->next) { isl_seq_cpy_from_pip(&tmp, &list->vector->the_deno[0], 1); isl_int_divexact(tmp, vec->el[0], tmp); isl_seq_cpy_from_pip(&vec->el[1 + i], &list->vector->the_vector[0], 1); isl_int_mul(vec->el[1 + i], vec->el[1 + i], tmp); } isl_int_clear(tmp); }
/* Apply the morphism to the basic set. * We basically just compute the preimage of "bset" under the inverse mapping * in morph, add in stride constraints and intersect with the range * of the morphism. */ __isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph, __isl_take isl_basic_set *bset) { isl_basic_set *res = NULL; isl_mat *mat = NULL; int i, k; int max_stride; if (!morph || !bset) goto error; isl_assert(bset->ctx, isl_space_is_equal(bset->dim, morph->dom->dim), goto error); max_stride = morph->inv->n_row - 1; if (isl_int_is_one(morph->inv->row[0][0])) max_stride = 0; res = isl_basic_set_alloc_space(isl_space_copy(morph->ran->dim), bset->n_div + max_stride, bset->n_eq + max_stride, bset->n_ineq); for (i = 0; i < bset->n_div; ++i) if (isl_basic_set_alloc_div(res) < 0) goto error; mat = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 0, morph->inv->n_row); mat = isl_mat_product(mat, isl_mat_copy(morph->inv)); if (!mat) goto error; for (i = 0; i < bset->n_eq; ++i) { k = isl_basic_set_alloc_equality(res); if (k < 0) goto error; isl_seq_cpy(res->eq[k], mat->row[i], mat->n_col); isl_seq_scale(res->eq[k] + mat->n_col, bset->eq[i] + mat->n_col, morph->inv->row[0][0], bset->n_div); } isl_mat_free(mat); mat = isl_mat_sub_alloc6(bset->ctx, bset->ineq, 0, bset->n_ineq, 0, morph->inv->n_row); mat = isl_mat_product(mat, isl_mat_copy(morph->inv)); if (!mat) goto error; for (i = 0; i < bset->n_ineq; ++i) { k = isl_basic_set_alloc_inequality(res); if (k < 0) goto error; isl_seq_cpy(res->ineq[k], mat->row[i], mat->n_col); isl_seq_scale(res->ineq[k] + mat->n_col, bset->ineq[i] + mat->n_col, morph->inv->row[0][0], bset->n_div); } isl_mat_free(mat); mat = isl_mat_sub_alloc6(bset->ctx, bset->div, 0, bset->n_div, 1, morph->inv->n_row); mat = isl_mat_product(mat, isl_mat_copy(morph->inv)); if (!mat) goto error; for (i = 0; i < bset->n_div; ++i) { isl_int_mul(res->div[i][0], morph->inv->row[0][0], bset->div[i][0]); isl_seq_cpy(res->div[i] + 1, mat->row[i], mat->n_col); isl_seq_scale(res->div[i] + 1 + mat->n_col, bset->div[i] + 1 + mat->n_col, morph->inv->row[0][0], bset->n_div); } isl_mat_free(mat); res = add_strides(res, morph); if (isl_basic_set_is_rational(bset)) res = isl_basic_set_set_rational(res); res = isl_basic_set_simplify(res); res = isl_basic_set_finalize(res); res = isl_basic_set_intersect(res, isl_basic_set_copy(morph->ran)); isl_morph_free(morph); isl_basic_set_free(bset); return res; error: isl_mat_free(mat); isl_morph_free(morph); isl_basic_set_free(bset); isl_basic_set_free(res); return NULL; }
__isl_give isl_basic_set *isl_basic_set_box_from_points( __isl_take isl_point *pnt1, __isl_take isl_point *pnt2) { isl_basic_set *bset; unsigned total; int i; int k; isl_int t; isl_int_init(t); if (!pnt1 || !pnt2) goto error; isl_assert(pnt1->dim->ctx, isl_dim_equal(pnt1->dim, pnt2->dim), goto error); if (isl_point_is_void(pnt1) && isl_point_is_void(pnt2)) { isl_dim *dim = isl_dim_copy(pnt1->dim); isl_point_free(pnt1); isl_point_free(pnt2); isl_int_clear(t); return isl_basic_set_empty(dim); } if (isl_point_is_void(pnt1)) { isl_point_free(pnt1); isl_int_clear(t); return isl_basic_set_from_point(pnt2); } if (isl_point_is_void(pnt2)) { isl_point_free(pnt2); isl_int_clear(t); return isl_basic_set_from_point(pnt1); } total = isl_dim_total(pnt1->dim); bset = isl_basic_set_alloc_dim(isl_dim_copy(pnt1->dim), 0, 0, 2 * total); for (i = 0; i < total; ++i) { isl_int_mul(t, pnt1->vec->el[1 + i], pnt2->vec->el[0]); isl_int_submul(t, pnt2->vec->el[1 + i], pnt1->vec->el[0]); k = isl_basic_set_alloc_inequality(bset); if (k < 0) goto error; isl_seq_clr(bset->ineq[k] + 1, total); if (isl_int_is_pos(t)) { isl_int_set_si(bset->ineq[k][1 + i], -1); isl_int_set(bset->ineq[k][0], pnt1->vec->el[1 + i]); } else { isl_int_set_si(bset->ineq[k][1 + i], 1); isl_int_neg(bset->ineq[k][0], pnt1->vec->el[1 + i]); } isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt1->vec->el[0]); k = isl_basic_set_alloc_inequality(bset); if (k < 0) goto error; isl_seq_clr(bset->ineq[k] + 1, total); if (isl_int_is_pos(t)) { isl_int_set_si(bset->ineq[k][1 + i], 1); isl_int_neg(bset->ineq[k][0], pnt2->vec->el[1 + i]); } else { isl_int_set_si(bset->ineq[k][1 + i], -1); isl_int_set(bset->ineq[k][0], pnt2->vec->el[1 + i]); } isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt2->vec->el[0]); } bset = isl_basic_set_finalize(bset); isl_point_free(pnt1); isl_point_free(pnt2); isl_int_clear(t); return bset; error: isl_point_free(pnt1); isl_point_free(pnt2); isl_int_clear(t); return NULL; }