/* 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);
}
Exemple #2
0
/* 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;
}