summaryrefslogtreecommitdiffstats
path: root/polly/lib/External/isl/isl_scheduler.c
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/External/isl/isl_scheduler.c')
-rw-r--r--polly/lib/External/isl/isl_scheduler.c465
1 files changed, 288 insertions, 177 deletions
diff --git a/polly/lib/External/isl/isl_scheduler.c b/polly/lib/External/isl/isl_scheduler.c
index 156eb419310..a214e1c3452 100644
--- a/polly/lib/External/isl/isl_scheduler.c
+++ b/polly/lib/External/isl/isl_scheduler.c
@@ -45,7 +45,8 @@ enum isl_edge_type {
isl_edge_condition,
isl_edge_conditional_validity,
isl_edge_proximity,
- isl_edge_last = isl_edge_proximity
+ isl_edge_last = isl_edge_proximity,
+ isl_edge_local
};
/* The constraints that need to be satisfied by a schedule on "domain".
@@ -267,6 +268,17 @@ isl_ctx *isl_schedule_constraints_get_ctx(
return sc ? isl_union_set_get_ctx(sc->domain) : NULL;
}
+/* Return the domain of "sc".
+ */
+__isl_give isl_union_set *isl_schedule_constraints_get_domain(
+ __isl_keep isl_schedule_constraints *sc)
+{
+ if (!sc)
+ return NULL;
+
+ return isl_union_set_copy(sc->domain);
+}
+
/* Return the validity constraints of "sc".
*/
__isl_give isl_union_map *isl_schedule_constraints_get_validity(
@@ -468,6 +480,8 @@ static int node_scc_at_least(struct isl_sched_node *node, int scc)
* If these fields are NULL, then they represent the empty relation.
* src is the source node
* dst is the sink node
+ *
+ * types is a bit vector containing the types of this edge.
* validity is set if the edge is used to ensure correctness
* coincidence is used to enforce zero dependence distances
* proximity is set if the edge is used to minimize dependence distances
@@ -490,17 +504,96 @@ struct isl_sched_edge {
struct isl_sched_node *src;
struct isl_sched_node *dst;
- unsigned validity : 1;
- unsigned coincidence : 1;
- unsigned proximity : 1;
- unsigned local : 1;
- unsigned condition : 1;
- unsigned conditional_validity : 1;
+ unsigned types;
int start;
int end;
};
+/* Is "edge" marked as being of type "type"?
+ */
+static int is_type(struct isl_sched_edge *edge, enum isl_edge_type type)
+{
+ return ISL_FL_ISSET(edge->types, 1 << type);
+}
+
+/* Mark "edge" as being of type "type".
+ */
+static void set_type(struct isl_sched_edge *edge, enum isl_edge_type type)
+{
+ ISL_FL_SET(edge->types, 1 << type);
+}
+
+/* No longer mark "edge" as being of type "type"?
+ */
+static void clear_type(struct isl_sched_edge *edge, enum isl_edge_type type)
+{
+ ISL_FL_CLR(edge->types, 1 << type);
+}
+
+/* Is "edge" marked as a validity edge?
+ */
+static int is_validity(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_validity);
+}
+
+/* Mark "edge" as a validity edge.
+ */
+static void set_validity(struct isl_sched_edge *edge)
+{
+ set_type(edge, isl_edge_validity);
+}
+
+/* Is "edge" marked as a proximity edge?
+ */
+static int is_proximity(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_proximity);
+}
+
+/* Is "edge" marked as a local edge?
+ */
+static int is_local(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_local);
+}
+
+/* Mark "edge" as a local edge.
+ */
+static void set_local(struct isl_sched_edge *edge)
+{
+ set_type(edge, isl_edge_local);
+}
+
+/* No longer mark "edge" as a local edge.
+ */
+static void clear_local(struct isl_sched_edge *edge)
+{
+ clear_type(edge, isl_edge_local);
+}
+
+/* Is "edge" marked as a coincidence edge?
+ */
+static int is_coincidence(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_coincidence);
+}
+
+/* Is "edge" marked as a condition edge?
+ */
+static int is_condition(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_condition);
+}
+
+/* Is "edge" marked as a conditional validity edge?
+ */
+static int is_conditional_validity(struct isl_sched_edge *edge)
+{
+ return is_type(edge, isl_edge_conditional_validity);
+}
+
/* Internal information about the dependence graph used during
* the construction of the schedule.
*
@@ -534,7 +627,9 @@ struct isl_sched_edge {
* and sink spaces; there is one such table for each type;
* a given edge may be referenced from more than one table
* if the corresponding relation appears in more than one of the
- * sets of dependences
+ * sets of dependences; however, for each type there is only
+ * a single edge between a given pair of source and sink space
+ * in the entire graph
*
* node_table contains pointers into the node array, hashed on the space
*
@@ -1058,23 +1153,17 @@ struct isl_extract_edge_data {
};
/* Merge edge2 into edge1, freeing the contents of edge2.
- * "type" is the type of the schedule constraint from which edge2 was
- * extracted.
* Return 0 on success and -1 on failure.
*
* edge1 and edge2 are assumed to have the same value for the map field.
*/
-static int merge_edge(enum isl_edge_type type, struct isl_sched_edge *edge1,
+static int merge_edge(struct isl_sched_edge *edge1,
struct isl_sched_edge *edge2)
{
- edge1->validity |= edge2->validity;
- edge1->coincidence |= edge2->coincidence;
- edge1->proximity |= edge2->proximity;
- edge1->condition |= edge2->condition;
- edge1->conditional_validity |= edge2->conditional_validity;
+ edge1->types |= edge2->types;
isl_map_free(edge2->map);
- if (type == isl_edge_condition) {
+ if (is_condition(edge2)) {
if (!edge1->tagged_condition)
edge1->tagged_condition = edge2->tagged_condition;
else
@@ -1083,7 +1172,7 @@ static int merge_edge(enum isl_edge_type type, struct isl_sched_edge *edge1,
edge2->tagged_condition);
}
- if (type == isl_edge_conditional_validity) {
+ if (is_conditional_validity(edge2)) {
if (!edge1->tagged_validity)
edge1->tagged_validity = edge2->tagged_validity;
else
@@ -1092,9 +1181,9 @@ static int merge_edge(enum isl_edge_type type, struct isl_sched_edge *edge1,
edge2->tagged_validity);
}
- if (type == isl_edge_condition && !edge1->tagged_condition)
+ if (is_condition(edge2) && !edge1->tagged_condition)
return -1;
- if (type == isl_edge_conditional_validity && !edge1->tagged_validity)
+ if (is_conditional_validity(edge2) && !edge1->tagged_validity)
return -1;
return 0;
@@ -1173,6 +1262,38 @@ static __isl_give isl_map *map_intersect_domains(__isl_take isl_map *tagged,
return tagged;
}
+/* Return a pointer to the node that lives in the domain space of "map"
+ * or NULL if there is no such node.
+ */
+static struct isl_sched_node *find_domain_node(isl_ctx *ctx,
+ struct isl_sched_graph *graph, __isl_keep isl_map *map)
+{
+ struct isl_sched_node *node;
+ isl_space *space;
+
+ space = isl_space_domain(isl_map_get_space(map));
+ node = graph_find_node(ctx, graph, space);
+ isl_space_free(space);
+
+ return node;
+}
+
+/* Return a pointer to the node that lives in the range space of "map"
+ * or NULL if there is no such node.
+ */
+static struct isl_sched_node *find_range_node(isl_ctx *ctx,
+ struct isl_sched_graph *graph, __isl_keep isl_map *map)
+{
+ struct isl_sched_node *node;
+ isl_space *space;
+
+ space = isl_space_range(isl_map_get_space(map));
+ node = graph_find_node(ctx, graph, space);
+ isl_space_free(space);
+
+ return node;
+}
+
/* Add a new edge to the graph based on the given map
* and add it to data->graph->edge_table[data->type].
* If a dependence relation of a given type happens to be identical
@@ -1202,7 +1323,6 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
struct isl_extract_edge_data *data = user;
struct isl_sched_graph *graph = data->graph;
struct isl_sched_node *src, *dst;
- isl_space *dim;
struct isl_sched_edge *edge;
isl_map *tagged = NULL;
@@ -1216,12 +1336,8 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
}
}
- dim = isl_space_domain(isl_map_get_space(map));
- src = graph_find_node(ctx, graph, dim);
- isl_space_free(dim);
- dim = isl_space_range(isl_map_get_space(map));
- dst = graph_find_node(ctx, graph, dim);
- isl_space_free(dim);
+ src = find_domain_node(ctx, graph, map);
+ dst = find_range_node(ctx, graph, map);
if (!src || !dst) {
isl_map_free(map);
@@ -1240,30 +1356,16 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
graph->edge[graph->n_edge].src = src;
graph->edge[graph->n_edge].dst = dst;
graph->edge[graph->n_edge].map = map;
- graph->edge[graph->n_edge].validity = 0;
- graph->edge[graph->n_edge].coincidence = 0;
- graph->edge[graph->n_edge].proximity = 0;
- graph->edge[graph->n_edge].condition = 0;
- graph->edge[graph->n_edge].local = 0;
- graph->edge[graph->n_edge].conditional_validity = 0;
+ graph->edge[graph->n_edge].types = 0;
graph->edge[graph->n_edge].tagged_condition = NULL;
graph->edge[graph->n_edge].tagged_validity = NULL;
- if (data->type == isl_edge_validity)
- graph->edge[graph->n_edge].validity = 1;
- if (data->type == isl_edge_coincidence)
- graph->edge[graph->n_edge].coincidence = 1;
- if (data->type == isl_edge_proximity)
- graph->edge[graph->n_edge].proximity = 1;
- if (data->type == isl_edge_condition) {
- graph->edge[graph->n_edge].condition = 1;
+ set_type(&graph->edge[graph->n_edge], data->type);
+ if (data->type == isl_edge_condition)
graph->edge[graph->n_edge].tagged_condition =
isl_union_map_from_map(tagged);
- }
- if (data->type == isl_edge_conditional_validity) {
- graph->edge[graph->n_edge].conditional_validity = 1;
+ if (data->type == isl_edge_conditional_validity)
graph->edge[graph->n_edge].tagged_validity =
isl_union_map_from_map(tagged);
- }
edge = graph_find_matching_edge(graph, &graph->edge[graph->n_edge]);
if (!edge) {
@@ -1274,12 +1376,70 @@ static isl_stat extract_edge(__isl_take isl_map *map, void *user)
return graph_edge_table_add(ctx, graph, data->type,
&graph->edge[graph->n_edge++]);
- if (merge_edge(data->type, edge, &graph->edge[graph->n_edge]) < 0)
+ if (merge_edge(edge, &graph->edge[graph->n_edge]) < 0)
return -1;
return graph_edge_table_add(ctx, graph, data->type, edge);
}
+/* Initialize the schedule graph "graph" from the schedule constraints "sc".
+ *
+ * The context is included in the domain before the nodes of
+ * the graphs are extracted in order to be able to exploit
+ * any possible additional equalities.
+ * Note that this intersection is only performed locally here.
+ */
+static isl_stat graph_init(struct isl_sched_graph *graph,
+ __isl_keep isl_schedule_constraints *sc)
+{
+ isl_ctx *ctx;
+ isl_union_set *domain;
+ struct isl_extract_edge_data data;
+ enum isl_edge_type i;
+ isl_stat r;
+
+ if (!sc)
+ return isl_stat_error;
+
+ ctx = isl_schedule_constraints_get_ctx(sc);
+
+ domain = isl_schedule_constraints_get_domain(sc);
+ graph->n = isl_union_set_n_set(domain);
+ isl_union_set_free(domain);
+
+ if (graph_alloc(ctx, graph, graph->n,
+ isl_schedule_constraints_n_map(sc)) < 0)
+ return isl_stat_error;
+
+ if (compute_max_row(graph, sc) < 0)
+ return isl_stat_error;
+ graph->root = 1;
+ graph->n = 0;
+ domain = isl_schedule_constraints_get_domain(sc);
+ domain = isl_union_set_intersect_params(domain,
+ isl_set_copy(sc->context));
+ r = isl_union_set_foreach_set(domain, &extract_node, graph);
+ isl_union_set_free(domain);
+ if (r < 0)
+ return isl_stat_error;
+ if (graph_init_table(ctx, graph) < 0)
+ return isl_stat_error;
+ for (i = isl_edge_first; i <= isl_edge_last; ++i)
+ graph->max_edge[i] = isl_union_map_n_map(sc->constraint[i]);
+ if (graph_init_edge_tables(ctx, graph) < 0)
+ return isl_stat_error;
+ graph->n_edge = 0;
+ data.graph = graph;
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ data.type = i;
+ if (isl_union_map_foreach_map(sc->constraint[i],
+ &extract_edge, &data) < 0)
+ return isl_stat_error;
+ }
+
+ return isl_stat_ok;
+}
+
/* Check whether there is any dependence from node[j] to node[i]
* or from node[i] to node[j].
*/
@@ -1821,8 +1981,9 @@ static int add_all_validity_constraints(struct isl_sched_graph *graph,
struct isl_sched_edge *edge= &graph->edge[i];
int local;
- local = edge->local || (edge->coincidence && use_coincidence);
- if (!edge->validity && !local)
+ local = is_local(edge) ||
+ (is_coincidence(edge) && use_coincidence);
+ if (!is_validity(edge) && !local)
continue;
if (edge->src != edge->dst)
continue;
@@ -1834,8 +1995,9 @@ static int add_all_validity_constraints(struct isl_sched_graph *graph,
struct isl_sched_edge *edge = &graph->edge[i];
int local;
- local = edge->local || (edge->coincidence && use_coincidence);
- if (!edge->validity && !local)
+ local = is_local(edge) ||
+ (is_coincidence(edge) && use_coincidence);
+ if (!is_validity(edge) && !local)
continue;
if (edge->src == edge->dst)
continue;
@@ -1867,8 +2029,9 @@ static int add_all_proximity_constraints(struct isl_sched_graph *graph,
struct isl_sched_edge *edge= &graph->edge[i];
int local;
- local = edge->local || (edge->coincidence && use_coincidence);
- if (!edge->proximity && !local)
+ local = is_local(edge) ||
+ (is_coincidence(edge) && use_coincidence);
+ if (!is_proximity(edge) && !local)
continue;
if (edge->src == edge->dst &&
add_intra_proximity_constraints(graph, edge, 1, local) < 0)
@@ -1876,7 +2039,7 @@ static int add_all_proximity_constraints(struct isl_sched_graph *graph,
if (edge->src != edge->dst &&
add_inter_proximity_constraints(graph, edge, 1, local) < 0)
return -1;
- if (edge->validity || local)
+ if (is_validity(edge) || local)
continue;
if (edge->src == edge->dst &&
add_intra_proximity_constraints(graph, edge, -1, 0) < 0)
@@ -1951,15 +2114,15 @@ static int node_update_cmap(struct isl_sched_node *node)
static int edge_multiplicity(struct isl_sched_edge *edge, int carry,
int use_coincidence)
{
- if (carry && !edge->validity && !edge->conditional_validity)
+ if (carry && !is_validity(edge) && !is_conditional_validity(edge))
return 0;
if (carry)
return 1;
- if (edge->proximity || edge->local)
+ if (is_proximity(edge) || is_local(edge))
return 2;
- if (use_coincidence && edge->coincidence)
+ if (use_coincidence && is_coincidence(edge))
return 2;
- if (edge->validity)
+ if (is_validity(edge))
return 1;
return 0;
}
@@ -2230,7 +2393,7 @@ static int check_conflict(int con, void *user)
return 0;
for (i = 0; i < graph->n_edge; ++i) {
- if (!graph->edge[i].validity)
+ if (!is_validity(&graph->edge[i]))
continue;
if (graph->edge[i].src == graph->edge[i].dst)
continue;
@@ -2628,9 +2791,9 @@ static int unconditionalize_adjacent_validity(struct isl_sched_graph *graph,
int adjacent;
isl_union_map *validity;
- if (!graph->edge[i].conditional_validity)
+ if (!is_conditional_validity(&graph->edge[i]))
continue;
- if (graph->edge[i].validity)
+ if (is_validity(&graph->edge[i]))
continue;
validity = graph->edge[i].tagged_validity;
@@ -2642,7 +2805,7 @@ static int unconditionalize_adjacent_validity(struct isl_sched_graph *graph,
if (!adjacent)
continue;
- graph->edge[i].validity = 1;
+ set_validity(&graph->edge[i]);
}
isl_union_set_free(condition_source);
@@ -2680,9 +2843,9 @@ static int update_edges(isl_ctx *ctx, struct isl_sched_graph *graph)
isl_union_set *uset;
isl_union_map *umap;
- if (!graph->edge[i].condition)
+ if (!is_condition(&graph->edge[i]))
continue;
- if (graph->edge[i].local)
+ if (is_local(&graph->edge[i]))
continue;
local = is_condition_false(&graph->edge[i]);
if (local < 0)
@@ -2776,7 +2939,7 @@ static __isl_give isl_union_set_list *extract_sccs(isl_ctx *ctx,
}
/* Return a list of two unions of universe domains, one for the SCCs up
- * to and including graph->src_scc and another for the other SCCS.
+ * to and including graph->src_scc and another for the other SCCs.
*/
static __isl_give isl_union_set_list *extract_split(isl_ctx *ctx,
struct isl_sched_graph *graph)
@@ -2866,7 +3029,7 @@ static int copy_edges(isl_ctx *ctx, struct isl_sched_graph *dst,
dst_src = graph_find_node(ctx, dst, edge->src->space);
dst_dst = graph_find_node(ctx, dst, edge->dst->space);
if (!dst_src || !dst_dst) {
- if (edge->validity || edge->conditional_validity)
+ if (is_validity(edge) || is_conditional_validity(edge))
isl_die(ctx, isl_error_internal,
"backward (conditional) validity edge",
return -1);
@@ -2882,12 +3045,7 @@ static int copy_edges(isl_ctx *ctx, struct isl_sched_graph *dst,
dst->edge[dst->n_edge].map = map;
dst->edge[dst->n_edge].tagged_condition = tagged_condition;
dst->edge[dst->n_edge].tagged_validity = tagged_validity;
- dst->edge[dst->n_edge].validity = edge->validity;
- dst->edge[dst->n_edge].proximity = edge->proximity;
- dst->edge[dst->n_edge].coincidence = edge->coincidence;
- dst->edge[dst->n_edge].condition = edge->condition;
- dst->edge[dst->n_edge].conditional_validity =
- edge->conditional_validity;
+ dst->edge[dst->n_edge].types = edge->types;
dst->n_edge++;
if (edge->tagged_condition && !tagged_condition)
@@ -2941,9 +3099,7 @@ static __isl_give isl_schedule_node *compute_schedule_wcc(
/* Compute a schedule for a subgraph of "graph". In particular, for
* the graph composed of nodes that satisfy node_pred and edges that
- * that satisfy edge_pred. The caller should precompute the number
- * of nodes and edges that satisfy these predicates and pass them along
- * as "n" and "n_edge".
+ * that satisfy edge_pred.
* If the subgraph is known to consist of a single component, then wcc should
* be set and then we call compute_schedule_wcc on the constructed subgraph.
* Otherwise, we call compute_schedule, which will check whether the subgraph
@@ -2954,14 +3110,21 @@ static __isl_give isl_schedule_node *compute_schedule_wcc(
*/
static __isl_give isl_schedule_node *compute_sub_schedule(
__isl_take isl_schedule_node *node, isl_ctx *ctx,
- struct isl_sched_graph *graph, int n, int n_edge,
+ struct isl_sched_graph *graph,
int (*node_pred)(struct isl_sched_node *node, int data),
int (*edge_pred)(struct isl_sched_edge *edge, int data),
int data, int wcc)
{
struct isl_sched_graph split = { 0 };
+ int i, n = 0, n_edge = 0;
int t;
+ for (i = 0; i < graph->n; ++i)
+ if (node_pred(&graph->node[i], data))
+ ++n;
+ for (i = 0; i < graph->n_edge; ++i)
+ if (edge_pred(&graph->edge[i], data))
+ ++n_edge;
if (graph_alloc(ctx, &split, n, n_edge) < 0)
goto error;
if (copy_nodes(&split, graph, node_pred, data) < 0)
@@ -3036,8 +3199,10 @@ static int reset_band(struct isl_sched_graph *graph)
/* Split the current graph into two parts and compute a schedule for each
* part individually. In particular, one part consists of all SCCs up
* to and including graph->src_scc, while the other part contains the other
- * SCCS. The split is enforced by a sequence node inserted at position "node"
+ * SCCs. The split is enforced by a sequence node inserted at position "node"
* in the schedule tree. Return the updated schedule node.
+ * If either of these two parts consists of a sequence, then it is spliced
+ * into the sequence containing the two parts.
*
* The current band is reset. It would be possible to reuse
* the previously computed rows as the first rows in the next
@@ -3047,7 +3212,7 @@ static int reset_band(struct isl_sched_graph *graph)
static __isl_give isl_schedule_node *compute_split_schedule(
__isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
{
- int i, n, e1, e2;
+ int is_seq;
isl_ctx *ctx;
isl_union_set_list *filters;
@@ -3057,42 +3222,32 @@ static __isl_give isl_schedule_node *compute_split_schedule(
if (reset_band(graph) < 0)
return isl_schedule_node_free(node);
- n = 0;
- for (i = 0; i < graph->n; ++i) {
- struct isl_sched_node *node = &graph->node[i];
- int before = node->scc <= graph->src_scc;
-
- if (before)
- n++;
- }
-
- e1 = e2 = 0;
- for (i = 0; i < graph->n_edge; ++i) {
- if (graph->edge[i].dst->scc <= graph->src_scc)
- e1++;
- if (graph->edge[i].src->scc > graph->src_scc)
- e2++;
- }
-
next_band(graph);
ctx = isl_schedule_node_get_ctx(node);
filters = extract_split(ctx, graph);
node = isl_schedule_node_insert_sequence(node, filters);
- node = isl_schedule_node_child(node, 0);
+ node = isl_schedule_node_child(node, 1);
node = isl_schedule_node_child(node, 0);
- node = compute_sub_schedule(node, ctx, graph, n, e1,
- &node_scc_at_most, &edge_dst_scc_at_most,
- graph->src_scc, 0);
- node = isl_schedule_node_parent(node);
- node = isl_schedule_node_next_sibling(node);
- node = isl_schedule_node_child(node, 0);
- node = compute_sub_schedule(node, ctx, graph, graph->n - n, e2,
+ node = compute_sub_schedule(node, ctx, graph,
&node_scc_at_least, &edge_src_scc_at_least,
graph->src_scc + 1, 0);
+ is_seq = isl_schedule_node_get_type(node) == isl_schedule_node_sequence;
+ node = isl_schedule_node_parent(node);
+ node = isl_schedule_node_parent(node);
+ if (is_seq)
+ node = isl_schedule_node_sequence_splice_child(node, 1);
+ node = isl_schedule_node_child(node, 0);
+ node = isl_schedule_node_child(node, 0);
+ node = compute_sub_schedule(node, ctx, graph,
+ &node_scc_at_most, &edge_dst_scc_at_most,
+ graph->src_scc, 0);
+ is_seq = isl_schedule_node_get_type(node) == isl_schedule_node_sequence;
node = isl_schedule_node_parent(node);
node = isl_schedule_node_parent(node);
+ if (is_seq)
+ node = isl_schedule_node_sequence_splice_child(node, 0);
return node;
}
@@ -3303,7 +3458,7 @@ static int add_all_constraints(struct isl_sched_graph *graph)
for (i = 0; i < graph->n_edge; ++i) {
struct isl_sched_edge *edge= &graph->edge[i];
- if (!edge->validity && !edge->conditional_validity)
+ if (!is_validity(edge) && !is_conditional_validity(edge))
continue;
for (j = 0; j < edge->map->n; ++j) {
@@ -3668,6 +3823,11 @@ static int is_any_trivial(struct isl_sched_graph *graph,
/* Construct a schedule row for each node such that as many dependences
* as possible are carried and then continue with the next band.
*
+ * Note that despite the fact that the problem is solved using a rational
+ * solver, the solution is guaranteed to be integral.
+ * Specifically, the dependence distance lower bounds e_i (and therefore
+ * also their sum) are integers. See Lemma 5 of [1].
+ *
* If the computed schedule row turns out to be trivial on one or
* more nodes where it should not be trivial, then we throw it away
* and try again on each component separately.
@@ -3684,6 +3844,10 @@ static int is_any_trivial(struct isl_sched_graph *graph,
* of the schedule tree and continue with the construction of the schedule.
* This insertion and the continued construction is performed by split_scaled
* after optionally checking for non-trivial common divisors.
+ *
+ * [1] P. Feautrier, Some Efficient Solutions to the Affine Scheduling
+ * Problem, Part II: Multi-Dimensional Time.
+ * In Intl. Journal of Parallel Programming, 1992.
*/
static __isl_give isl_schedule_node *carry_dependences(
__isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
@@ -3802,8 +3966,8 @@ static int has_validity_edges(struct isl_sched_graph *graph)
return -1;
if (empty)
continue;
- if (graph->edge[i].validity ||
- graph->edge[i].conditional_validity)
+ if (is_validity(&graph->edge[i]) ||
+ is_conditional_validity(&graph->edge[i]))
return 1;
}
@@ -3846,8 +4010,8 @@ static void clear_local_edges(struct isl_sched_graph *graph)
int i;
for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].condition)
- graph->edge[i].local = 0;
+ if (is_condition(&graph->edge[i]))
+ clear_local(&graph->edge[i]);
}
/* Does "graph" have both condition and conditional validity edges?
@@ -3859,9 +4023,9 @@ static int need_condition_check(struct isl_sched_graph *graph)
int any_conditional_validity = 0;
for (i = 0; i < graph->n_edge; ++i) {
- if (graph->edge[i].condition)
+ if (is_condition(&graph->edge[i]))
any_condition = 1;
- if (graph->edge[i].conditional_validity)
+ if (is_conditional_validity(&graph->edge[i]))
any_conditional_validity = 1;
}
@@ -3875,7 +4039,7 @@ static int has_any_coincidence(struct isl_sched_graph *graph)
int i;
for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].coincidence)
+ if (is_coincidence(&graph->edge[i]))
return 1;
return 0;
@@ -3943,9 +4107,9 @@ static int has_adjacent_true_conditions(struct isl_sched_graph *graph,
int adjacent, local;
isl_union_map *condition;
- if (!graph->edge[i].condition)
+ if (!is_condition(&graph->edge[i]))
continue;
- if (graph->edge[i].local)
+ if (is_local(&graph->edge[i]))
continue;
condition = graph->edge[i].tagged_condition;
@@ -3958,7 +4122,7 @@ static int has_adjacent_true_conditions(struct isl_sched_graph *graph,
if (!adjacent)
continue;
- graph->edge[i].local = 1;
+ set_local(&graph->edge[i]);
local = is_condition_false(&graph->edge[i]);
if (local < 0)
@@ -3998,7 +4162,7 @@ static int has_violated_conditional_constraint(isl_ctx *ctx,
isl_union_map *umap;
int violated;
- if (!graph->edge[i].conditional_validity)
+ if (!is_conditional_validity(&graph->edge[i]))
continue;
violated = is_violated(graph, i);
@@ -4182,8 +4346,7 @@ static __isl_give isl_schedule_node *compute_component_schedule(
__isl_take isl_schedule_node *node, struct isl_sched_graph *graph,
int wcc)
{
- int component, i;
- int n, n_edge;
+ int component;
isl_ctx *ctx;
isl_union_set_list *filters;
@@ -4198,19 +4361,9 @@ static __isl_give isl_schedule_node *compute_component_schedule(
node = isl_schedule_node_insert_sequence(node, filters);
for (component = 0; component < graph->scc; ++component) {
- n = 0;
- for (i = 0; i < graph->n; ++i)
- if (graph->node[i].scc == component)
- n++;
- n_edge = 0;
- for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].src->scc == component &&
- graph->edge[i].dst->scc == component)
- n_edge++;
-
node = isl_schedule_node_child(node, component);
node = isl_schedule_node_child(node, 0);
- node = compute_sub_schedule(node, ctx, graph, n, n_edge,
+ node = compute_sub_schedule(node, ctx, graph,
&node_scc_exactly,
&edge_scc_exactly, component, wcc);
node = isl_schedule_node_parent(node);
@@ -4267,12 +4420,6 @@ static __isl_give isl_schedule_node *compute_schedule(isl_schedule_node *node,
* then the conditional validity dependences may be violated inside
* a tilable band, provided they have no adjacent non-local
* condition dependences.
- *
- * The context is included in the domain before the nodes of
- * the graphs are extracted in order to be able to exploit
- * any possible additional equalities.
- * However, the returned schedule contains the original domain
- * (before this intersection).
*/
__isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
__isl_take isl_schedule_constraints *sc)
@@ -4282,65 +4429,29 @@ __isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
isl_schedule *sched;
isl_schedule_node *node;
isl_union_set *domain;
- struct isl_extract_edge_data data;
- enum isl_edge_type i;
- int r;
sc = isl_schedule_constraints_align_params(sc);
- if (!sc)
- return NULL;
- graph.n = isl_union_set_n_set(sc->domain);
- if (graph.n == 0) {
- isl_union_set *domain = isl_union_set_copy(sc->domain);
- sched = isl_schedule_from_domain(domain);
- goto done;
- }
- if (graph_alloc(ctx, &graph, graph.n,
- isl_schedule_constraints_n_map(sc)) < 0)
- goto error;
- if (compute_max_row(&graph, sc) < 0)
- goto error;
- graph.root = 1;
- graph.n = 0;
- domain = isl_union_set_copy(sc->domain);
- domain = isl_union_set_intersect_params(domain,
- isl_set_copy(sc->context));
- r = isl_union_set_foreach_set(domain, &extract_node, &graph);
- isl_union_set_free(domain);
- if (r < 0)
- goto error;
- if (graph_init_table(ctx, &graph) < 0)
- goto error;
- for (i = isl_edge_first; i <= isl_edge_last; ++i)
- graph.max_edge[i] = isl_union_map_n_map(sc->constraint[i]);
- if (graph_init_edge_tables(ctx, &graph) < 0)
- goto error;
- graph.n_edge = 0;
- data.graph = &graph;
- for (i = isl_edge_first; i <= isl_edge_last; ++i) {
- data.type = i;
- if (isl_union_map_foreach_map(sc->constraint[i],
- &extract_edge, &data) < 0)
- goto error;
+ domain = isl_schedule_constraints_get_domain(sc);
+ if (isl_union_set_n_set(domain) == 0) {
+ isl_schedule_constraints_free(sc);
+ return isl_schedule_from_domain(domain);
}
- node = isl_schedule_node_from_domain(isl_union_set_copy(sc->domain));
+ if (graph_init(&graph, sc) < 0)
+ domain = isl_union_set_free(domain);
+
+ node = isl_schedule_node_from_domain(domain);
node = isl_schedule_node_child(node, 0);
if (graph.n > 0)
node = compute_schedule(node, &graph);
sched = isl_schedule_node_get_schedule(node);
isl_schedule_node_free(node);
-done:
graph_free(ctx, &graph);
isl_schedule_constraints_free(sc);
return sched;
-error:
- graph_free(ctx, &graph);
- isl_schedule_constraints_free(sc);
- return NULL;
}
/* Compute a schedule for the given union of domains that respects
OpenPOWER on IntegriCloud