mirror of
https://review.haiku-os.org/buildtools
synced 2024-11-23 07:18:49 +01:00
9897128cb9
Change-Id: I9d707083f0a9e71d3bcc02b3265bfb233bdbe46c Reviewed-on: https://review.haiku-os.org/c/buildtools/+/3019 Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
236 lines
7.5 KiB
C
236 lines
7.5 KiB
C
/*
|
|
* Copyright 2008-2009 Katholieke Universiteit Leuven
|
|
* Copyright 2010 INRIA Saclay
|
|
* Copyright 2011 Sven Verdoolaege
|
|
*
|
|
* Use of this software is governed by the MIT license
|
|
*
|
|
* Written by Sven Verdoolaege, K.U.Leuven, Departement
|
|
* Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
|
|
* and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
|
|
* ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
|
|
*/
|
|
|
|
#define xSF(TYPE,SUFFIX) TYPE ## SUFFIX
|
|
#define SF(TYPE,SUFFIX) xSF(TYPE,SUFFIX)
|
|
|
|
/* Given a basic map with at least two parallel constraints (as found
|
|
* by the function parallel_constraints), first look for more constraints
|
|
* parallel to the two constraint and replace the found list of parallel
|
|
* constraints by a single constraint with as "input" part the minimum
|
|
* of the input parts of the list of constraints. Then, recursively call
|
|
* basic_map_partial_lexopt (possibly finding more parallel constraints)
|
|
* and plug in the definition of the minimum in the result.
|
|
*
|
|
* As in parallel_constraints, only inequality constraints that only
|
|
* involve input variables that do not occur in any other inequality
|
|
* constraints are considered.
|
|
*
|
|
* More specifically, given a set of constraints
|
|
*
|
|
* a x + b_i(p) >= 0
|
|
*
|
|
* Replace this set by a single constraint
|
|
*
|
|
* a x + u >= 0
|
|
*
|
|
* with u a new parameter with constraints
|
|
*
|
|
* u <= b_i(p)
|
|
*
|
|
* Any solution to the new system is also a solution for the original system
|
|
* since
|
|
*
|
|
* a x >= -u >= -b_i(p)
|
|
*
|
|
* Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
|
|
* therefore be plugged into the solution.
|
|
*/
|
|
static TYPE *SF(basic_map_partial_lexopt_symm,SUFFIX)(
|
|
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
|
|
__isl_give isl_set **empty, int max, int first, int second)
|
|
{
|
|
int i, n, k;
|
|
int *list = NULL;
|
|
isl_size bmap_in, bmap_param, bmap_all;
|
|
unsigned n_in, n_out, n_div;
|
|
isl_ctx *ctx;
|
|
isl_vec *var = NULL;
|
|
isl_mat *cst = NULL;
|
|
isl_space *map_space, *set_space;
|
|
|
|
map_space = isl_basic_map_get_space(bmap);
|
|
set_space = empty ? isl_basic_set_get_space(dom) : NULL;
|
|
|
|
bmap_in = isl_basic_map_dim(bmap, isl_dim_in);
|
|
bmap_param = isl_basic_map_dim(bmap, isl_dim_param);
|
|
bmap_all = isl_basic_map_dim(bmap, isl_dim_all);
|
|
if (bmap_in < 0 || bmap_param < 0 || bmap_all < 0)
|
|
goto error;
|
|
n_in = bmap_param + bmap_in;
|
|
n_out = bmap_all - n_in;
|
|
|
|
ctx = isl_basic_map_get_ctx(bmap);
|
|
list = isl_alloc_array(ctx, int, bmap->n_ineq);
|
|
var = isl_vec_alloc(ctx, n_out);
|
|
if ((bmap->n_ineq && !list) || (n_out && !var))
|
|
goto error;
|
|
|
|
list[0] = first;
|
|
list[1] = second;
|
|
isl_seq_cpy(var->el, bmap->ineq[first] + 1 + n_in, n_out);
|
|
for (i = second + 1, n = 2; i < bmap->n_ineq; ++i) {
|
|
if (isl_seq_eq(var->el, bmap->ineq[i] + 1 + n_in, n_out) &&
|
|
all_single_occurrence(bmap, i, n_in))
|
|
list[n++] = i;
|
|
}
|
|
|
|
cst = isl_mat_alloc(ctx, n, 1 + n_in);
|
|
if (!cst)
|
|
goto error;
|
|
|
|
for (i = 0; i < n; ++i)
|
|
isl_seq_cpy(cst->row[i], bmap->ineq[list[i]], 1 + n_in);
|
|
|
|
bmap = isl_basic_map_cow(bmap);
|
|
if (!bmap)
|
|
goto error;
|
|
for (i = n - 1; i >= 0; --i)
|
|
if (isl_basic_map_drop_inequality(bmap, list[i]) < 0)
|
|
goto error;
|
|
|
|
bmap = isl_basic_map_add_dims(bmap, isl_dim_in, 1);
|
|
bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
|
|
k = isl_basic_map_alloc_inequality(bmap);
|
|
if (k < 0)
|
|
goto error;
|
|
isl_seq_clr(bmap->ineq[k], 1 + n_in);
|
|
isl_int_set_si(bmap->ineq[k][1 + n_in], 1);
|
|
isl_seq_cpy(bmap->ineq[k] + 1 + n_in + 1, var->el, n_out);
|
|
bmap = isl_basic_map_finalize(bmap);
|
|
|
|
n_div = isl_basic_set_dim(dom, isl_dim_div);
|
|
dom = isl_basic_set_add_dims(dom, isl_dim_set, 1);
|
|
dom = isl_basic_set_extend_constraints(dom, 0, n);
|
|
for (i = 0; i < n; ++i) {
|
|
k = isl_basic_set_alloc_inequality(dom);
|
|
if (k < 0)
|
|
goto error;
|
|
isl_seq_cpy(dom->ineq[k], cst->row[i], 1 + n_in);
|
|
isl_int_set_si(dom->ineq[k][1 + n_in], -1);
|
|
isl_seq_clr(dom->ineq[k] + 1 + n_in + 1, n_div);
|
|
}
|
|
|
|
isl_vec_free(var);
|
|
free(list);
|
|
|
|
return SF(basic_map_partial_lexopt_symm_core,SUFFIX)(bmap, dom, empty,
|
|
max, cst, map_space, set_space);
|
|
error:
|
|
isl_space_free(map_space);
|
|
isl_space_free(set_space);
|
|
isl_mat_free(cst);
|
|
isl_vec_free(var);
|
|
free(list);
|
|
isl_basic_set_free(dom);
|
|
isl_basic_map_free(bmap);
|
|
return NULL;
|
|
}
|
|
|
|
/* Recursive part of isl_tab_basic_map_partial_lexopt*, after detecting
|
|
* equalities and removing redundant constraints.
|
|
*
|
|
* We first check if there are any parallel constraints (left).
|
|
* If not, we are in the base case.
|
|
* If there are parallel constraints, we replace them by a single
|
|
* constraint in basic_map_partial_lexopt_symm_pma and then call
|
|
* this function recursively to look for more parallel constraints.
|
|
*/
|
|
static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
|
|
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
|
|
__isl_give isl_set **empty, int max)
|
|
{
|
|
isl_bool par = isl_bool_false;
|
|
int first, second;
|
|
|
|
if (!bmap)
|
|
goto error;
|
|
|
|
if (bmap->ctx->opt->pip_symmetry)
|
|
par = parallel_constraints(bmap, &first, &second);
|
|
if (par < 0)
|
|
goto error;
|
|
if (!par)
|
|
return SF(basic_map_partial_lexopt_base,SUFFIX)(bmap, dom,
|
|
empty, max);
|
|
|
|
return SF(basic_map_partial_lexopt_symm,SUFFIX)(bmap, dom, empty, max,
|
|
first, second);
|
|
error:
|
|
isl_basic_set_free(dom);
|
|
isl_basic_map_free(bmap);
|
|
return NULL;
|
|
}
|
|
|
|
/* Compute the lexicographic minimum (or maximum if "flags" includes
|
|
* ISL_OPT_MAX) of "bmap" over the domain "dom" and return the result as
|
|
* either a map or a piecewise multi-affine expression depending on TYPE.
|
|
* If "empty" is not NULL, then *empty is assigned a set that
|
|
* contains those parts of the domain where there is no solution.
|
|
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
|
|
* should be computed over the domain of "bmap". "empty" is also NULL
|
|
* in this case.
|
|
* If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
|
|
* then we compute the rational optimum. Otherwise, we compute
|
|
* the integral optimum.
|
|
*
|
|
* We perform some preprocessing. As the PILP solver does not
|
|
* handle implicit equalities very well, we first make sure all
|
|
* the equalities are explicitly available.
|
|
*
|
|
* We also add context constraints to the basic map and remove
|
|
* redundant constraints. This is only needed because of the
|
|
* way we handle simple symmetries. In particular, we currently look
|
|
* for symmetries on the constraints, before we set up the main tableau.
|
|
* It is then no good to look for symmetries on possibly redundant constraints.
|
|
* If the domain was extracted from the basic map, then there is
|
|
* no need to add back those constraints again.
|
|
*/
|
|
__isl_give TYPE *SF(isl_tab_basic_map_partial_lexopt,SUFFIX)(
|
|
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
|
|
__isl_give isl_set **empty, unsigned flags)
|
|
{
|
|
int max, full;
|
|
isl_bool compatible;
|
|
|
|
if (empty)
|
|
*empty = NULL;
|
|
|
|
full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
|
|
if (full)
|
|
dom = extract_domain(bmap, flags);
|
|
compatible = isl_basic_map_compatible_domain(bmap, dom);
|
|
if (compatible < 0)
|
|
goto error;
|
|
if (!compatible)
|
|
isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
|
|
"domain does not match input", goto error);
|
|
|
|
max = ISL_FL_ISSET(flags, ISL_OPT_MAX);
|
|
if (isl_basic_set_dim(dom, isl_dim_all) == 0)
|
|
return SF(basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty,
|
|
max);
|
|
|
|
if (!full)
|
|
bmap = isl_basic_map_intersect_domain(bmap,
|
|
isl_basic_set_copy(dom));
|
|
bmap = isl_basic_map_detect_equalities(bmap);
|
|
bmap = isl_basic_map_remove_redundancies(bmap);
|
|
|
|
return SF(basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty, max);
|
|
error:
|
|
isl_basic_set_free(dom);
|
|
isl_basic_map_free(bmap);
|
|
return NULL;
|
|
}
|