static isl_map* build_access_function (scoplib_scop_p scop, scoplib_statement_p s, scoplib_matrix_p m, isl_space* space, isl_ctx* ctxt, int* row_pos, int array_id) { isl_map* ret = NULL; int i; isl_val* tmp = isl_val_int_from_si (ctxt, 0); for (i = *row_pos; i < m->NbRows; ++i) { if (SCOPVAL_get_si(m->p[i][0]) == array_id) { ret = isl_map_universe (isl_space_copy (space)); int pos = 0; do { isl_local_space* ls = isl_local_space_from_space (isl_space_copy (space)); isl_constraint* cst = isl_equality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_in, k, isl_val_copy(tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy(tmp)); // Set output dimension. tmp = isl_val_set_si (tmp, -1); isl_constraint_set_coefficient_val (cst, isl_dim_out, pos++, isl_val_copy (tmp)); // Insert constraint. ret = isl_map_add_constraint (ret, cst); ++i; } while (i < m->NbRows && SCOPVAL_get_si(m->p[i][0]) == 0); *row_pos = i; break; } } isl_val_free (tmp); return ret; }
/* Set the stride and offset of data->pos to the given * value and expression. * * If we had already found a stride before, then the two strides * are combined into a single stride. * * In particular, if the new stride information is of the form * * i = f + s (...) * * and the old stride information is of the form * * i = f2 + s2 (...) * * then we compute the extended gcd of s and s2 * * a s + b s2 = g, * * with g = gcd(s,s2), multiply the first equation with t1 = b s2/g * and the second with t2 = a s1/g. * This results in * * i = (b s2 + a s1)/g i = t1 f + t2 f2 + (s s2)/g (...) * * so that t1 f + t2 f2 is the combined offset and (s s2)/g = lcm(s,s2) * is the combined stride. */ static isl_stat set_stride(struct isl_detect_stride_data *data, __isl_take isl_val *stride, __isl_take isl_aff *offset) { int pos; if (!stride || !offset) goto error; pos = data->pos; if (data->found) { isl_val *stride2, *a, *b, *g; isl_aff *offset2; stride2 = data->stride; g = isl_val_gcdext(isl_val_copy(stride), isl_val_copy(stride2), &a, &b); a = isl_val_mul(a, isl_val_copy(stride)); a = isl_val_div(a, isl_val_copy(g)); stride2 = isl_val_div(stride2, g); b = isl_val_mul(b, isl_val_copy(stride2)); stride = isl_val_mul(stride, stride2); if (!data->want_offset) { isl_val_free(a); isl_val_free(b); } else { offset2 = data->offset; offset2 = isl_aff_scale_val(offset2, a); offset = isl_aff_scale_val(offset, b); offset = isl_aff_add(offset, offset2); } } data->found = 1; data->stride = stride; if (data->want_offset) data->offset = offset; else isl_aff_free(offset); if (!data->stride || (data->want_offset && !data->offset)) return isl_stat_error; return isl_stat_ok; error: isl_val_free(stride); isl_aff_free(offset); return isl_stat_error; }
static isl_set* build_iteration_domain (scoplib_scop_p scop, scoplib_statement_p s, isl_space* space, isl_ctx* ctxt) { isl_set* ret = isl_set_universe (isl_space_domain (isl_space_copy (space))); int i; isl_val* tmp = isl_val_int_from_si (ctxt, 0); scoplib_matrix_p m = s->domain->elt; for (i = 0; i < m->NbRows; ++i) { isl_local_space* ls = isl_local_space_from_space (isl_set_get_space (ret)); isl_constraint* cst; if (SCOPVAL_get_si(m->p[i][0]) == 0) cst = isl_equality_alloc (isl_local_space_copy (ls)); else cst = isl_inequality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_set, k, isl_val_copy (tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy (tmp)); // Insert constraint. ret = isl_set_add_constraint (ret, cst); } isl_val_free (tmp); return ret; }
/* Make a copy of "si" and return it. */ __isl_give isl_stride_info *isl_stride_info_copy( __isl_keep isl_stride_info *si) { if (!si) return NULL; return isl_stride_info_alloc(isl_val_copy(si->stride), isl_aff_copy(si->offset)); }
/* Construct an isl_multi_val living in "space" with all values equal to "val". */ __isl_give isl_multi_val *ppcg_multi_val_from_int(__isl_take isl_space *space, int val) { int i, n; isl_ctx *ctx; isl_val *v; isl_multi_val *mv; if (!space) return NULL; ctx = isl_space_get_ctx(space); n = isl_space_dim(space, isl_dim_set); mv = isl_multi_val_zero(space); v = isl_val_int_from_si(ctx, val); for (i = 0; i < n; ++i) mv = isl_multi_val_set_val(mv, i, isl_val_copy(v)); isl_val_free(v); return mv; }
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_ctx *ctx; isl_val *size, *subsize, *size1; res = isl_equality_alloc (ls); ctx = isl_local_space_get_ctx (ls); size = isl_val_int_from_ui (ctx, 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; size1 = isl_val_copy (size); res = isl_constraint_set_coefficient_val (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); subsize = isl_set_max_val (pdr->extent, aff); isl_aff_free (aff); size = isl_val_mul (size1, subsize); } isl_val_free (size); return res; }
static void *isl_obj_val_copy(void *v) { return isl_val_copy((isl_val *)v); }
static isl_map* build_schedule (scoplib_scop_p scop, scoplib_statement_p s, isl_space* sp, isl_ctx* ctxt) { // Set up the space. isl_space* space_in = isl_space_domain (isl_space_copy (sp)); int dout = s->schedule->NbRows; isl_space* space_out = isl_space_set_alloc(ctxt, scop->nb_parameters, dout); int i; char buffer[32]; char* name; for (i = 0; i < dout; ++i) { sprintf (buffer, "t%d", i); name = strdup (buffer); space_out = isl_space_set_dim_name (space_out, isl_dim_set, i, name); } for (i = 0; i < scop->nb_parameters; ++i) { name = strdup (((SgVariableSymbol*)(scop->parameters[i]))->get_name().str()); space_out = isl_space_set_dim_name (space_out, isl_dim_param, i, name); } isl_space* space = isl_space_map_from_domain_and_range (isl_space_copy (space_in), isl_space_copy (space_out)); isl_map* ret = isl_map_universe (isl_space_copy (space)); isl_val* tmp = isl_val_int_from_si (ctxt, 0); scoplib_matrix_p m = s->schedule; for (i = 0; i < m->NbRows; ++i) { isl_local_space* ls = isl_local_space_from_space (isl_space_copy (space)); isl_constraint* cst; if (SCOPVAL_get_si(m->p[i][0]) == 0) cst = isl_equality_alloc (isl_local_space_copy (ls)); else cst = isl_inequality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_in, k, isl_val_copy (tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy (tmp)); // Set output dimension. tmp = isl_val_set_si (tmp, -1); isl_constraint_set_coefficient_val (cst, isl_dim_out, i, isl_val_copy (tmp)); // Insert constraint. ret = isl_map_add_constraint (ret, cst); } isl_val_free (tmp); return ret; }
/* Return the stride of "si". */ __isl_give isl_val *isl_stride_info_get_stride(__isl_keep isl_stride_info *si) { if (!si) return NULL; return isl_val_copy(si->stride); }
/* 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; }