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