X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=isl_coalesce.c;h=f5f637cc7cec5808bfe5f7f1c14568fb0d377e07;hb=f2b5428f06192e4aa836643b5911e8e4e3cecc1f;hp=a95ccc58b696f15b78a86e74ca2117c695865b2a;hpb=64e09ae0d4ab16682b8a4bbbf6ae524d67cd521a;p=platform%2Fupstream%2Fisl.git diff --git a/isl_coalesce.c b/isl_coalesce.c index a95ccc5..f5f637c 100644 --- a/isl_coalesce.c +++ b/isl_coalesce.c @@ -1,4 +1,17 @@ +/* + * Copyright 2008-2009 Katholieke Universiteit Leuven + * Copyright 2010 INRIA Saclay + * + * Use of this software is governed by the GNU LGPLv2.1 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 + */ + #include "isl_map_private.h" +#include "isl_seq.h" #include "isl_tab.h" #define STATUS_ERROR -1 @@ -129,31 +142,44 @@ static void drop(struct isl_map *map, int i, struct isl_tab **tabs) map->n--; } -/* Replace the pair of basic maps i and j but the basic map bounded - * by the valid constraints in both basic maps. +/* Replace the pair of basic maps i and j by the basic map bounded + * by the valid constraints in both basic maps and the constraint + * in extra (if not NULL). */ -static int fuse(struct isl_map *map, int i, int j, struct isl_tab **tabs, - int *ineq_i, int *ineq_j) +static int fuse(struct isl_map *map, int i, int j, + struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j, + __isl_keep isl_mat *extra) { int k, l; struct isl_basic_map *fused = NULL; struct isl_tab *fused_tab = NULL; unsigned total = isl_basic_map_total_dim(map->p[i]); + unsigned extra_rows = extra ? extra->n_row : 0; fused = isl_basic_map_alloc_dim(isl_dim_copy(map->p[i]->dim), map->p[i]->n_div, map->p[i]->n_eq + map->p[j]->n_eq, - map->p[i]->n_ineq + map->p[j]->n_ineq); + map->p[i]->n_ineq + map->p[j]->n_ineq + extra_rows); if (!fused) goto error; for (k = 0; k < map->p[i]->n_eq; ++k) { - int l = isl_basic_map_alloc_equality(fused); + if (eq_i && (eq_i[2 * k] != STATUS_VALID || + eq_i[2 * k + 1] != STATUS_VALID)) + continue; + l = isl_basic_map_alloc_equality(fused); + if (l < 0) + goto error; isl_seq_cpy(fused->eq[l], map->p[i]->eq[k], 1 + total); } for (k = 0; k < map->p[j]->n_eq; ++k) { - int l = isl_basic_map_alloc_equality(fused); + if (eq_j && (eq_j[2 * k] != STATUS_VALID || + eq_j[2 * k + 1] != STATUS_VALID)) + continue; + l = isl_basic_map_alloc_equality(fused); + if (l < 0) + goto error; isl_seq_cpy(fused->eq[l], map->p[j]->eq[k], 1 + total); } @@ -161,6 +187,8 @@ static int fuse(struct isl_map *map, int i, int j, struct isl_tab **tabs, if (ineq_i[k] != STATUS_VALID) continue; l = isl_basic_map_alloc_inequality(fused); + if (l < 0) + goto error; isl_seq_cpy(fused->ineq[l], map->p[i]->ineq[k], 1 + total); } @@ -168,20 +196,33 @@ static int fuse(struct isl_map *map, int i, int j, struct isl_tab **tabs, if (ineq_j[k] != STATUS_VALID) continue; l = isl_basic_map_alloc_inequality(fused); + if (l < 0) + goto error; isl_seq_cpy(fused->ineq[l], map->p[j]->ineq[k], 1 + total); } for (k = 0; k < map->p[i]->n_div; ++k) { int l = isl_basic_map_alloc_div(fused); + if (l < 0) + goto error; isl_seq_cpy(fused->div[l], map->p[i]->div[k], 1 + 1 + total); } + for (k = 0; k < extra_rows; ++k) { + l = isl_basic_map_alloc_inequality(fused); + if (l < 0) + goto error; + isl_seq_cpy(fused->ineq[l], extra->row[k], 1 + total); + } + fused = isl_basic_map_gauss(fused, NULL); ISL_F_SET(fused, ISL_BASIC_MAP_FINAL); + if (ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_RATIONAL) && + ISL_F_ISSET(map->p[j], ISL_BASIC_MAP_RATIONAL)) + ISL_F_SET(fused, ISL_BASIC_MAP_RATIONAL); fused_tab = isl_tab_from_basic_map(fused); - fused_tab = isl_tab_detect_redundant(fused_tab); - if (!fused_tab) + if (isl_tab_detect_redundant(fused_tab) < 0) goto error; isl_basic_map_free(map->p[i]); @@ -192,6 +233,7 @@ static int fuse(struct isl_map *map, int i, int j, struct isl_tab **tabs, return 1; error: + isl_tab_free(fused_tab); isl_basic_map_free(fused); return -1; } @@ -236,7 +278,8 @@ static int check_facets(struct isl_map *map, int i, int j, if (stat != STATUS_VALID) break; } - isl_tab_rollback(tabs[i], snap); + if (isl_tab_rollback(tabs[i], snap) < 0) + return -1; if (l < map->p[j]->n_ineq) break; } @@ -244,7 +287,7 @@ static int check_facets(struct isl_map *map, int i, int j, if (k < map->p[i]->n_ineq) /* BAD CUT PAIR */ return 0; - return fuse(map, i, j, tabs, ineq_i, ineq_j); + return fuse(map, i, j, tabs, NULL, ineq_i, NULL, ineq_j, NULL); } /* Both basic maps have at least one inequality with and adjacent @@ -285,7 +328,7 @@ static int check_adj_ineq(struct isl_map *map, int i, int j, ; else if (count(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ) == 1 && count(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ) == 1) - changed = fuse(map, i, j, tabs, ineq_i, ineq_j); + changed = fuse(map, i, j, tabs, NULL, ineq_i, NULL, ineq_j, NULL); /* else ADJ INEQ TOO MANY */ return changed; @@ -322,18 +365,13 @@ static int contains(struct isl_map *map, int i, int *ineq_i, return 1; } -/* At least one of the basic maps has an equality that is adjacent - * to inequality. Make sure that only one of the basic maps has - * such an equality and that the other basic map has exactly one - * inequality adjacent to an equality. - * We call the basic map that has the inequality "i" and the basic - * map that has the equality "j". - * If "i" has any "cut" inequality, then relaxing the inequality - * by one would not result in a basic map that contains the other - * basic map. - * Otherwise, we relax the constraint, compute the corresponding +/* Basic map "i" has an inequality "k" that is adjacent to some equality + * of basic map "j". All the other inequalities are valid for "j". + * Check if basic map "j" forms an extension of basic map "i". + * + * In particular, we relax constraint "k", compute the corresponding * facet and check whether it is included in the other basic map. - * If so, we know that relaxing the constraint extend the basic + * If so, we know that relaxing the constraint extends the basic * map with exactly the other basic map (we already know that this * other basic map is included in the extension, because there * were no "cut" inequalities in "i") and we can replace the @@ -345,15 +383,282 @@ static int contains(struct isl_map *map, int i, int *ineq_i, * \ || \ | * \___|| \____| */ -static int check_adj_eq(struct isl_map *map, int i, int j, +static int is_extension(struct isl_map *map, int i, int j, int k, struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j) { int changed = 0; int super; - int k; struct isl_tab_undo *snap, *snap2; unsigned n_eq = map->p[i]->n_eq; + snap = isl_tab_snap(tabs[i]); + tabs[i] = isl_tab_relax(tabs[i], n_eq + k); + snap2 = isl_tab_snap(tabs[i]); + tabs[i] = isl_tab_select_facet(tabs[i], n_eq + k); + super = contains(map, j, ineq_j, tabs[i]); + if (super) { + if (isl_tab_rollback(tabs[i], snap2) < 0) + return -1; + map->p[i] = isl_basic_map_cow(map->p[i]); + if (!map->p[i]) + return -1; + isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1); + ISL_F_SET(map->p[i], ISL_BASIC_MAP_FINAL); + drop(map, j, tabs); + changed = 1; + } else + if (isl_tab_rollback(tabs[i], snap) < 0) + return -1; + + return changed; +} + +/* For each non-redundant constraint in "bmap" (as determined by "tab"), + * wrap the constraint around "bound" such that it includes the whole + * set "set" and append the resulting constraint to "wraps". + * "wraps" is assumed to have been pre-allocated to the appropriate size. + * wraps->n_row is the number of actual wrapped constraints that have + * been added. + * If any of the wrapping problems results in a constraint that is + * identical to "bound", then this means that "set" is unbounded in such + * way that no wrapping is possible. If this happens then wraps->n_row + * is reset to zero. + */ +static int add_wraps(__isl_keep isl_mat *wraps, __isl_keep isl_basic_map *bmap, + struct isl_tab *tab, isl_int *bound, __isl_keep isl_set *set) +{ + int l; + int w; + unsigned total = isl_basic_map_total_dim(bmap); + + w = wraps->n_row; + + for (l = 0; l < bmap->n_ineq; ++l) { + if (isl_seq_is_neg(bound, bmap->ineq[l], 1 + total)) + continue; + if (isl_seq_eq(bound, bmap->ineq[l], 1 + total)) + continue; + if (isl_tab_is_redundant(tab, bmap->n_eq + l)) + continue; + + isl_seq_cpy(wraps->row[w], bound, 1 + total); + if (!isl_set_wrap_facet(set, wraps->row[w], bmap->ineq[l])) + return -1; + if (isl_seq_eq(wraps->row[w], bound, 1 + total)) + goto unbounded; + ++w; + } + for (l = 0; l < bmap->n_eq; ++l) { + if (isl_seq_is_neg(bound, bmap->eq[l], 1 + total)) + continue; + if (isl_seq_eq(bound, bmap->eq[l], 1 + total)) + continue; + + isl_seq_cpy(wraps->row[w], bound, 1 + total); + isl_seq_neg(wraps->row[w + 1], bmap->eq[l], 1 + total); + if (!isl_set_wrap_facet(set, wraps->row[w], wraps->row[w + 1])) + return -1; + if (isl_seq_eq(wraps->row[w], bound, 1 + total)) + goto unbounded; + ++w; + + isl_seq_cpy(wraps->row[w], bound, 1 + total); + if (!isl_set_wrap_facet(set, wraps->row[w], bmap->eq[l])) + return -1; + if (isl_seq_eq(wraps->row[w], bound, 1 + total)) + goto unbounded; + ++w; + } + + wraps->n_row = w; + return 0; +unbounded: + wraps->n_row = 0; + return 0; +} + +/* Given a basic set i with a constraint k that is adjacent to either the + * whole of basic set j or a facet of basic set j, check if we can wrap + * both the facet corresponding to k and the facet of j (or the whole of j) + * around their ridges to include the other set. + * If so, replace the pair of basic sets by their union. + * + * All constraints of i (except k) are assumed to be valid for j. + * + * In the case where j has a facet adjacent to i, tab[j] is assumed + * to have been restricted to this facet, so that the non-redundant + * constraints in tab[j] are the ridges of the facet. + * Note that for the purpose of wrapping, it does not matter whether + * we wrap the ridges of i around the whole of j or just around + * the facet since all the other constraints are assumed to be valid for j. + * In practice, we wrap to include the whole of j. + * ____ _____ + * / | / \ + * / || / | + * \ || => \ | + * \ || \ | + * \___|| \____| + * + */ +static int can_wrap_in_facet(struct isl_map *map, int i, int j, int k, + struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j) +{ + int changed = 0; + struct isl_mat *wraps = NULL; + struct isl_set *set_i = NULL; + struct isl_set *set_j = NULL; + struct isl_vec *bound = NULL; + unsigned total = isl_basic_map_total_dim(map->p[i]); + struct isl_tab_undo *snap; + + snap = isl_tab_snap(tabs[i]); + + set_i = isl_set_from_basic_set( + isl_basic_map_underlying_set(isl_basic_map_copy(map->p[i]))); + set_j = isl_set_from_basic_set( + isl_basic_map_underlying_set(isl_basic_map_copy(map->p[j]))); + wraps = isl_mat_alloc(map->ctx, 2 * (map->p[i]->n_eq + map->p[j]->n_eq) + + map->p[i]->n_ineq + map->p[j]->n_ineq, + 1 + total); + bound = isl_vec_alloc(map->ctx, 1 + total); + if (!set_i || !set_j || !wraps || !bound) + goto error; + + isl_seq_cpy(bound->el, map->p[i]->ineq[k], 1 + total); + isl_int_add_ui(bound->el[0], bound->el[0], 1); + + isl_seq_cpy(wraps->row[0], bound->el, 1 + total); + wraps->n_row = 1; + + if (add_wraps(wraps, map->p[j], tabs[j], bound->el, set_i) < 0) + goto error; + if (!wraps->n_row) + goto unbounded; + + tabs[i] = isl_tab_select_facet(tabs[i], map->p[i]->n_eq + k); + if (isl_tab_detect_redundant(tabs[i]) < 0) + goto error; + + isl_seq_neg(bound->el, map->p[i]->ineq[k], 1 + total); + + if (add_wraps(wraps, map->p[i], tabs[i], bound->el, set_j) < 0) + goto error; + if (!wraps->n_row) + goto unbounded; + + changed = fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, wraps); + + if (!changed) { +unbounded: + if (isl_tab_rollback(tabs[i], snap) < 0) + goto error; + } + + isl_mat_free(wraps); + + isl_set_free(set_i); + isl_set_free(set_j); + + isl_vec_free(bound); + + return changed; +error: + isl_vec_free(bound); + isl_mat_free(wraps); + isl_set_free(set_i); + isl_set_free(set_j); + return -1; +} + +/* Given two basic sets i and j such that i has exactly one cut constraint, + * check if we can wrap the corresponding facet around its ridges to include + * the other basic set (and nothing else). + * If so, replace the pair by their union. + * + * We first check if j has a facet adjacent to the cut constraint of i. + * If so, we try to wrap in the facet. + * ____ _____ + * / ___|_ / \ + * / | | / | + * \ | | => \ | + * \|____| \ | + * \___| \____/ + */ +static int can_wrap_in_set(struct isl_map *map, int i, int j, + struct isl_tab **tabs, int *ineq_i, int *ineq_j) +{ + int changed = 0; + int k, l; + unsigned total = isl_basic_map_total_dim(map->p[i]); + struct isl_tab_undo *snap; + + for (k = 0; k < map->p[i]->n_ineq; ++k) + if (ineq_i[k] == STATUS_CUT) + break; + + isl_assert(map->ctx, k < map->p[i]->n_ineq, return -1); + + isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1); + for (l = 0; l < map->p[j]->n_ineq; ++l) { + if (isl_tab_is_redundant(tabs[j], map->p[j]->n_eq + l)) + continue; + if (isl_seq_eq(map->p[i]->ineq[k], + map->p[j]->ineq[l], 1 + total)) + break; + } + isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1); + + if (l >= map->p[j]->n_ineq) + return 0; + + snap = isl_tab_snap(tabs[j]); + tabs[j] = isl_tab_select_facet(tabs[j], map->p[j]->n_eq + l); + if (isl_tab_detect_redundant(tabs[j]) < 0) + return -1; + + changed = can_wrap_in_facet(map, i, j, k, tabs, NULL, ineq_i, NULL, ineq_j); + + if (!changed && isl_tab_rollback(tabs[j], snap) < 0) + return -1; + + return changed; +} + +/* Check if either i or j has a single cut constraint that can + * be used to wrap in (a facet of) the other basic set. + * if so, replace the pair by their union. + */ +static int check_wrap(struct isl_map *map, int i, int j, + struct isl_tab **tabs, int *ineq_i, int *ineq_j) +{ + int changed = 0; + + if (count(ineq_i, map->p[i]->n_ineq, STATUS_CUT) == 1) + changed = can_wrap_in_set(map, i, j, tabs, ineq_i, ineq_j); + if (changed) + return changed; + + if (count(ineq_j, map->p[j]->n_ineq, STATUS_CUT) == 1) + changed = can_wrap_in_set(map, j, i, tabs, ineq_j, ineq_i); + return changed; +} + +/* At least one of the basic maps has an equality that is adjacent + * to inequality. Make sure that only one of the basic maps has + * such an equality and that the other basic map has exactly one + * inequality adjacent to an equality. + * We call the basic map that has the inequality "i" and the basic + * map that has the equality "j". + * If "i" has any "cut" inequality, then relaxing the inequality + * by one would not result in a basic map that contains the other + * basic map. + */ +static int check_adj_eq(struct isl_map *map, int i, int j, + struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j) +{ + int changed = 0; + int k; + if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ) && any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ)) /* ADJ EQ TOO MANY */ @@ -380,22 +685,11 @@ static int check_adj_eq(struct isl_map *map, int i, int j, if (ineq_i[k] == STATUS_ADJ_EQ) break; - snap = isl_tab_snap(tabs[i]); - tabs[i] = isl_tab_relax(tabs[i], n_eq + k); - snap2 = isl_tab_snap(tabs[i]); - tabs[i] = isl_tab_select_facet(tabs[i], n_eq + k); - super = contains(map, j, ineq_j, tabs[i]); - if (super) { - isl_tab_rollback(tabs[i], snap2); - map->p[i] = isl_basic_map_cow(map->p[i]); - if (!map->p[i]) - return -1; - isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1); - ISL_F_SET(map->p[i], ISL_BASIC_MAP_FINAL); - drop(map, j, tabs); - changed = 1; - } else - isl_tab_rollback(tabs[i], snap); + changed = is_extension(map, i, j, k, tabs, eq_i, ineq_i, eq_j, ineq_j); + if (changed) + return changed; + + changed = can_wrap_in_facet(map, i, j, k, tabs, eq_i, ineq_i, eq_j, ineq_j); return changed; } @@ -422,7 +716,7 @@ static int check_adj_eq(struct isl_map *map, int i, int j, * adj_ineq the given constraint is adjacent (on the outside) * to an inequality of the other basic map * - * We consider four cases in which we can replace the pair by a single + * We consider six cases in which we can replace the pair by a single * basic map. We ignore all "redundant" constraints. * * 1. all constraints of one basic map are valid @@ -447,6 +741,23 @@ static int check_adj_eq(struct isl_map *map, int i, int j, * => the pair can be replaced by the basic map containing * the inequality, with the inequality relaxed. * + * 5. there is a single adjacent pair of an inequality and an equality, + * the other constraints of the basic map containing the inequality are + * "valid". Moreover, the facets corresponding to both + * the inequality and the equality can be wrapped around their + * ridges to include the other basic map + * => the pair can be replaced by a basic map consisting + * of the valid constraints in both basic maps together + * with all wrapping constraints + * + * 6. one of the basic maps has a single cut constraint and + * the other basic map has a constraint adjacent to this constraint. + * Moreover, the facets corresponding to both constraints + * can be wrapped around their ridges to include the other basic map + * => the pair can be replaced by a basic map consisting + * of the valid constraints in both basic maps together + * with all wrapping constraints + * * Throughout the computation, we maintain a collection of tableaus * corresponding to the basic maps. When the basic maps are dropped * or combined, the tableaus are modified accordingly. @@ -509,8 +820,11 @@ static int coalesce_pair(struct isl_map *map, int i, int j, } else if (any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ) || any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ)) { changed = check_adj_ineq(map, i, j, tabs, ineq_i, ineq_j); - } else + } else { changed = check_facets(map, i, j, tabs, ineq_i, ineq_j); + if (!changed) + changed = check_wrap(map, i, j, tabs, ineq_i, ineq_j); + } done: free(eq_i); @@ -573,9 +887,10 @@ struct isl_map *isl_map_coalesce(struct isl_map *map) if (!tabs[i]) goto error; if (!ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_NO_IMPLICIT)) - tabs[i] = isl_tab_detect_equalities(tabs[i]); + tabs[i] = isl_tab_detect_implicit_equalities(tabs[i]); if (!ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_NO_REDUNDANT)) - tabs[i] = isl_tab_detect_redundant(tabs[i]); + if (isl_tab_detect_redundant(tabs[i]) < 0) + goto error; } for (i = map->n - 1; i >= 0; --i) if (tabs[i]->empty) @@ -614,5 +929,5 @@ error: */ struct isl_set *isl_set_coalesce(struct isl_set *set) { - (struct isl_set *)isl_map_coalesce((struct isl_map *)set); + return (struct isl_set *)isl_map_coalesce((struct isl_map *)set); }