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