9697161c85f360d2519bd1630f60241e52eda4d4
[platform/upstream/isl.git] / isl_schedule.c
1 /*
2  * Copyright 2011      INRIA Saclay
3  *
4  * Use of this software is governed by the GNU LGPLv2.1 license
5  *
6  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
7  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
8  * 91893 Orsay, France
9  */
10
11 #include <isl_ctx_private.h>
12 #include <isl_map_private.h>
13 #include <isl_space_private.h>
14 #include <isl/hash.h>
15 #include <isl/constraint.h>
16 #include <isl/schedule.h>
17 #include <isl_mat_private.h>
18 #include <isl/set.h>
19 #include <isl/seq.h>
20 #include <isl_tab.h>
21 #include <isl_dim_map.h>
22 #include <isl_hmap_map_basic_set.h>
23 #include <isl_qsort.h>
24 #include <isl_schedule_private.h>
25 #include <isl_band_private.h>
26 #include <isl_list_private.h>
27 #include <isl_options_private.h>
28
29 /*
30  * The scheduling algorithm implemented in this file was inspired by
31  * Bondhugula et al., "Automatic Transformations for Communication-Minimized
32  * Parallelization and Locality Optimization in the Polyhedral Model".
33  */
34
35
36 /* Internal information about a node that is used during the construction
37  * of a schedule.
38  * dim represents the space in which the domain lives
39  * sched is a matrix representation of the schedule being constructed
40  *      for this node
41  * sched_map is an isl_map representation of the same (partial) schedule
42  *      sched_map may be NULL
43  * rank is the number of linearly independent rows in the linear part
44  *      of sched
45  * the columns of cmap represent a change of basis for the schedule
46  *      coefficients; the first rank columns span the linear part of
47  *      the schedule rows
48  * start is the first variable in the LP problem in the sequences that
49  *      represents the schedule coefficients of this node
50  * nvar is the dimension of the domain
51  * nparam is the number of parameters or 0 if we are not constructing
52  *      a parametric schedule
53  *
54  * scc is the index of SCC (or WCC) this node belongs to
55  *
56  * band contains the band index for each of the rows of the schedule.
57  * band_id is used to differentiate between separate bands at the same
58  * level within the same parent band, i.e., bands that are separated
59  * by the parent band or bands that are independent of each other.
60  * zero contains a boolean for each of the rows of the schedule,
61  * indicating whether the corresponding scheduling dimension results
62  * in zero dependence distances within its band and with respect
63  * to the proximity edges.
64  *
65  * index, min_index and on_stack are used during the SCC detection
66  * index represents the order in which nodes are visited.
67  * min_index is the index of the root of a (sub)component.
68  * on_stack indicates whether the node is currently on the stack.
69  */
70 struct isl_sched_node {
71         isl_space *dim;
72         isl_mat *sched;
73         isl_map *sched_map;
74         int      rank;
75         isl_mat *cmap;
76         int      start;
77         int      nvar;
78         int      nparam;
79
80         int      scc;
81
82         int     *band;
83         int     *band_id;
84         int     *zero;
85
86         /* scc detection */
87         int      index;
88         int      min_index;
89         int      on_stack;
90 };
91
92 static int node_has_dim(const void *entry, const void *val)
93 {
94         struct isl_sched_node *node = (struct isl_sched_node *)entry;
95         isl_space *dim = (isl_space *)val;
96
97         return isl_space_is_equal(node->dim, dim);
98 }
99
100 /* An edge in the dependence graph.  An edge may be used to
101  * ensure validity of the generated schedule, to minimize the dependence
102  * distance or both
103  *
104  * map is the dependence relation
105  * src is the source node
106  * dst is the sink node
107  * validity is set if the edge is used to ensure correctness
108  * proximity is set if the edge is used to minimize dependence distances
109  *
110  * For validity edges, start and end mark the sequence of inequality
111  * constraints in the LP problem that encode the validity constraint
112  * corresponding to this edge.
113  */
114 struct isl_sched_edge {
115         isl_map *map;
116
117         struct isl_sched_node *src;
118         struct isl_sched_node *dst;
119
120         int validity;
121         int proximity;
122
123         int start;
124         int end;
125 };
126
127 enum isl_edge_type {
128         isl_edge_validity = 0,
129         isl_edge_proximity,
130         isl_edge_last = isl_edge_proximity
131 };
132
133 /* Internal information about the dependence graph used during
134  * the construction of the schedule.
135  *
136  * intra_hmap is a cache, mapping dependence relations to their dual,
137  *      for dependences from a node to itself
138  * inter_hmap is a cache, mapping dependence relations to their dual,
139  *      for dependences between distinct nodes
140  *
141  * n is the number of nodes
142  * node is the list of nodes
143  * maxvar is the maximal number of variables over all nodes
144  * n_row is the current (maximal) number of linearly independent
145  *      rows in the node schedules
146  * n_total_row is the current number of rows in the node schedules
147  * n_band is the current number of completed bands
148  * band_start is the starting row in the node schedules of the current band
149  * root is set if this graph is the original dependence graph,
150  *      without any splitting
151  *
152  * sorted contains a list of node indices sorted according to the
153  *      SCC to which a node belongs
154  *
155  * n_edge is the number of edges
156  * edge is the list of edges
157  * max_edge contains the maximal number of edges of each type;
158  *      in particular, it contains the number of edges in the inital graph.
159  * edge_table contains pointers into the edge array, hashed on the source
160  *      and sink spaces; there is one such table for each type;
161  *      a given edge may be referenced from more than one table
162  *      if the corresponding relation appears in more than of the
163  *      sets of dependences
164  *
165  * node_table contains pointers into the node array, hashed on the space
166  *
167  * region contains a list of variable sequences that should be non-trivial
168  *
169  * lp contains the (I)LP problem used to obtain new schedule rows
170  *
171  * src_scc and dst_scc are the source and sink SCCs of an edge with
172  *      conflicting constraints
173  *
174  * scc, sp, index and stack are used during the detection of SCCs
175  * scc is the number of the next SCC
176  * stack contains the nodes on the path from the root to the current node
177  * sp is the stack pointer
178  * index is the index of the last node visited
179  */
180 struct isl_sched_graph {
181         isl_hmap_map_basic_set *intra_hmap;
182         isl_hmap_map_basic_set *inter_hmap;
183
184         struct isl_sched_node *node;
185         int n;
186         int maxvar;
187         int n_row;
188
189         int *sorted;
190
191         int n_band;
192         int n_total_row;
193         int band_start;
194
195         int root;
196
197         struct isl_sched_edge *edge;
198         int n_edge;
199         int max_edge[isl_edge_last + 1];
200         struct isl_hash_table *edge_table[isl_edge_last + 1];
201
202         struct isl_hash_table *node_table;
203         struct isl_region *region;
204
205         isl_basic_set *lp;
206
207         int src_scc;
208         int dst_scc;
209
210         /* scc detection */
211         int scc;
212         int sp;
213         int index;
214         int *stack;
215 };
216
217 /* Initialize node_table based on the list of nodes.
218  */
219 static int graph_init_table(isl_ctx *ctx, struct isl_sched_graph *graph)
220 {
221         int i;
222
223         graph->node_table = isl_hash_table_alloc(ctx, graph->n);
224         if (!graph->node_table)
225                 return -1;
226
227         for (i = 0; i < graph->n; ++i) {
228                 struct isl_hash_table_entry *entry;
229                 uint32_t hash;
230
231                 hash = isl_space_get_hash(graph->node[i].dim);
232                 entry = isl_hash_table_find(ctx, graph->node_table, hash,
233                                             &node_has_dim,
234                                             graph->node[i].dim, 1);
235                 if (!entry)
236                         return -1;
237                 entry->data = &graph->node[i];
238         }
239
240         return 0;
241 }
242
243 /* Return a pointer to the node that lives within the given space,
244  * or NULL if there is no such node.
245  */
246 static struct isl_sched_node *graph_find_node(isl_ctx *ctx,
247         struct isl_sched_graph *graph, __isl_keep isl_space *dim)
248 {
249         struct isl_hash_table_entry *entry;
250         uint32_t hash;
251
252         hash = isl_space_get_hash(dim);
253         entry = isl_hash_table_find(ctx, graph->node_table, hash,
254                                     &node_has_dim, dim, 0);
255
256         return entry ? entry->data : NULL;
257 }
258
259 static int edge_has_src_and_dst(const void *entry, const void *val)
260 {
261         const struct isl_sched_edge *edge = entry;
262         const struct isl_sched_edge *temp = val;
263
264         return edge->src == temp->src && edge->dst == temp->dst;
265 }
266
267 /* Add the given edge to graph->edge_table[type].
268  */
269 static int graph_edge_table_add(isl_ctx *ctx, struct isl_sched_graph *graph,
270         enum isl_edge_type type, struct isl_sched_edge *edge)
271 {
272         struct isl_hash_table_entry *entry;
273         uint32_t hash;
274
275         hash = isl_hash_init();
276         hash = isl_hash_builtin(hash, edge->src);
277         hash = isl_hash_builtin(hash, edge->dst);
278         entry = isl_hash_table_find(ctx, graph->edge_table[type], hash,
279                                     &edge_has_src_and_dst, edge, 1);
280         if (!entry)
281                 return -1;
282         entry->data = edge;
283
284         return 0;
285 }
286
287 /* Allocate the edge_tables based on the maximal number of edges of
288  * each type.
289  */
290 static int graph_init_edge_tables(isl_ctx *ctx, struct isl_sched_graph *graph)
291 {
292         int i;
293
294         for (i = 0; i <= isl_edge_last; ++i) {
295                 graph->edge_table[i] = isl_hash_table_alloc(ctx,
296                                                             graph->max_edge[i]);
297                 if (!graph->edge_table[i])
298                         return -1;
299         }
300
301         return 0;
302 }
303
304 /* If graph->edge_table[type] contains an edge from the given source
305  * to the given destination, then return the hash table entry of this edge.
306  * Otherwise, return NULL.
307  */
308 static struct isl_hash_table_entry *graph_find_edge_entry(
309         struct isl_sched_graph *graph,
310         enum isl_edge_type type,
311         struct isl_sched_node *src, struct isl_sched_node *dst)
312 {
313         isl_ctx *ctx = isl_space_get_ctx(src->dim);
314         uint32_t hash;
315         struct isl_sched_edge temp = { .src = src, .dst = dst };
316
317         hash = isl_hash_init();
318         hash = isl_hash_builtin(hash, temp.src);
319         hash = isl_hash_builtin(hash, temp.dst);
320         return isl_hash_table_find(ctx, graph->edge_table[type], hash,
321                                     &edge_has_src_and_dst, &temp, 0);
322 }
323
324
325 /* If graph->edge_table[type] contains an edge from the given source
326  * to the given destination, then return this edge.
327  * Otherwise, return NULL.
328  */
329 static struct isl_sched_edge *graph_find_edge(struct isl_sched_graph *graph,
330         enum isl_edge_type type,
331         struct isl_sched_node *src, struct isl_sched_node *dst)
332 {
333         struct isl_hash_table_entry *entry;
334
335         entry = graph_find_edge_entry(graph, type, src, dst);
336         if (!entry)
337                 return NULL;
338
339         return entry->data;
340 }
341
342 /* Check whether the dependence graph has an edge of the give type
343  * between the given two nodes.
344  */
345 static int graph_has_edge(struct isl_sched_graph *graph,
346         enum isl_edge_type type,
347         struct isl_sched_node *src, struct isl_sched_node *dst)
348 {
349         struct isl_sched_edge *edge;
350         int empty;
351
352         edge = graph_find_edge(graph, type, src, dst);
353         if (!edge)
354                 return 0;
355
356         empty = isl_map_plain_is_empty(edge->map);
357         if (empty < 0)
358                 return -1;
359
360         return !empty;
361 }
362
363 /* If there is an edge from the given source to the given destination
364  * of any type then return this edge.
365  * Otherwise, return NULL.
366  */
367 static struct isl_sched_edge *graph_find_any_edge(struct isl_sched_graph *graph,
368         struct isl_sched_node *src, struct isl_sched_node *dst)
369 {
370         int i;
371         struct isl_sched_edge *edge;
372
373         for (i = 0; i <= isl_edge_last; ++i) {
374                 edge = graph_find_edge(graph, i, src, dst);
375                 if (edge)
376                         return edge;
377         }
378
379         return NULL;
380 }
381
382 /* Remove the given edge from all the edge_tables that refer to it.
383  */
384 static void graph_remove_edge(struct isl_sched_graph *graph,
385         struct isl_sched_edge *edge)
386 {
387         isl_ctx *ctx = isl_map_get_ctx(edge->map);
388         int i;
389
390         for (i = 0; i <= isl_edge_last; ++i) {
391                 struct isl_hash_table_entry *entry;
392
393                 entry = graph_find_edge_entry(graph, i, edge->src, edge->dst);
394                 if (!entry)
395                         continue;
396                 if (entry->data != edge)
397                         continue;
398                 isl_hash_table_remove(ctx, graph->edge_table[i], entry);
399         }
400 }
401
402 /* Check whether the dependence graph has a validity edge
403  * between the given two nodes.
404  */
405 static int graph_has_validity_edge(struct isl_sched_graph *graph,
406         struct isl_sched_node *src, struct isl_sched_node *dst)
407 {
408         return graph_has_edge(graph, isl_edge_validity, src, dst);
409 }
410
411 static int graph_alloc(isl_ctx *ctx, struct isl_sched_graph *graph,
412         int n_node, int n_edge)
413 {
414         int i;
415
416         graph->n = n_node;
417         graph->n_edge = n_edge;
418         graph->node = isl_calloc_array(ctx, struct isl_sched_node, graph->n);
419         graph->sorted = isl_calloc_array(ctx, int, graph->n);
420         graph->region = isl_alloc_array(ctx, struct isl_region, graph->n);
421         graph->stack = isl_alloc_array(ctx, int, graph->n);
422         graph->edge = isl_calloc_array(ctx,
423                                         struct isl_sched_edge, graph->n_edge);
424
425         graph->intra_hmap = isl_hmap_map_basic_set_alloc(ctx, 2 * n_edge);
426         graph->inter_hmap = isl_hmap_map_basic_set_alloc(ctx, 2 * n_edge);
427
428         if (!graph->node || !graph->region || !graph->stack || !graph->edge ||
429             !graph->sorted)
430                 return -1;
431
432         for(i = 0; i < graph->n; ++i)
433                 graph->sorted[i] = i;
434
435         return 0;
436 }
437
438 static void graph_free(isl_ctx *ctx, struct isl_sched_graph *graph)
439 {
440         int i;
441
442         isl_hmap_map_basic_set_free(ctx, graph->intra_hmap);
443         isl_hmap_map_basic_set_free(ctx, graph->inter_hmap);
444
445         for (i = 0; i < graph->n; ++i) {
446                 isl_space_free(graph->node[i].dim);
447                 isl_mat_free(graph->node[i].sched);
448                 isl_map_free(graph->node[i].sched_map);
449                 isl_mat_free(graph->node[i].cmap);
450                 if (graph->root) {
451                         free(graph->node[i].band);
452                         free(graph->node[i].band_id);
453                         free(graph->node[i].zero);
454                 }
455         }
456         free(graph->node);
457         free(graph->sorted);
458         for (i = 0; i < graph->n_edge; ++i)
459                 isl_map_free(graph->edge[i].map);
460         free(graph->edge);
461         free(graph->region);
462         free(graph->stack);
463         for (i = 0; i <= isl_edge_last; ++i)
464                 isl_hash_table_free(ctx, graph->edge_table[i]);
465         isl_hash_table_free(ctx, graph->node_table);
466         isl_basic_set_free(graph->lp);
467 }
468
469 /* Add a new node to the graph representing the given set.
470  */
471 static int extract_node(__isl_take isl_set *set, void *user)
472 {
473         int nvar, nparam;
474         isl_ctx *ctx;
475         isl_space *dim;
476         isl_mat *sched;
477         struct isl_sched_graph *graph = user;
478         int *band, *band_id, *zero;
479
480         ctx = isl_set_get_ctx(set);
481         dim = isl_set_get_space(set);
482         isl_set_free(set);
483         nvar = isl_space_dim(dim, isl_dim_set);
484         nparam = isl_space_dim(dim, isl_dim_param);
485         if (!ctx->opt->schedule_parametric)
486                 nparam = 0;
487         sched = isl_mat_alloc(ctx, 0, 1 + nparam + nvar);
488         graph->node[graph->n].dim = dim;
489         graph->node[graph->n].nvar = nvar;
490         graph->node[graph->n].nparam = nparam;
491         graph->node[graph->n].sched = sched;
492         graph->node[graph->n].sched_map = NULL;
493         band = isl_alloc_array(ctx, int, graph->n_edge + nvar);
494         graph->node[graph->n].band = band;
495         band_id = isl_calloc_array(ctx, int, graph->n_edge + nvar);
496         graph->node[graph->n].band_id = band_id;
497         zero = isl_calloc_array(ctx, int, graph->n_edge + nvar);
498         graph->node[graph->n].zero = zero;
499         graph->n++;
500
501         if (!sched || !band || !band_id || !zero)
502                 return -1;
503
504         return 0;
505 }
506
507 struct isl_extract_edge_data {
508         enum isl_edge_type type;
509         struct isl_sched_graph *graph;
510 };
511
512 /* Add a new edge to the graph based on the given map
513  * and add it to data->graph->edge_table[data->type].
514  * If a dependence relation of a given type happens to be identical
515  * to one of the dependence relations of a type that was added before,
516  * then we don't create a new edge, but instead mark the original edge
517  * as also representing a dependence of the current type.
518  */
519 static int extract_edge(__isl_take isl_map *map, void *user)
520 {
521         isl_ctx *ctx = isl_map_get_ctx(map);
522         struct isl_extract_edge_data *data = user;
523         struct isl_sched_graph *graph = data->graph;
524         struct isl_sched_node *src, *dst;
525         isl_space *dim;
526         struct isl_sched_edge *edge;
527         int is_equal;
528
529         dim = isl_space_domain(isl_map_get_space(map));
530         src = graph_find_node(ctx, graph, dim);
531         isl_space_free(dim);
532         dim = isl_space_range(isl_map_get_space(map));
533         dst = graph_find_node(ctx, graph, dim);
534         isl_space_free(dim);
535
536         if (!src || !dst) {
537                 isl_map_free(map);
538                 return 0;
539         }
540
541         graph->edge[graph->n_edge].src = src;
542         graph->edge[graph->n_edge].dst = dst;
543         graph->edge[graph->n_edge].map = map;
544         if (data->type == isl_edge_validity) {
545                 graph->edge[graph->n_edge].validity = 1;
546                 graph->edge[graph->n_edge].proximity = 0;
547         }
548         if (data->type == isl_edge_proximity) {
549                 graph->edge[graph->n_edge].validity = 0;
550                 graph->edge[graph->n_edge].proximity = 1;
551         }
552         graph->n_edge++;
553
554         edge = graph_find_any_edge(graph, src, dst);
555         if (!edge)
556                 return graph_edge_table_add(ctx, graph, data->type,
557                                     &graph->edge[graph->n_edge - 1]);
558         is_equal = isl_map_plain_is_equal(map, edge->map);
559         if (is_equal < 0)
560                 return -1;
561         if (!is_equal)
562                 return graph_edge_table_add(ctx, graph, data->type,
563                                     &graph->edge[graph->n_edge - 1]);
564
565         graph->n_edge--;
566         edge->validity |= graph->edge[graph->n_edge].validity;
567         edge->proximity |= graph->edge[graph->n_edge].proximity;
568         isl_map_free(map);
569
570         return graph_edge_table_add(ctx, graph, data->type, edge);
571 }
572
573 /* Check whether there is a validity dependence from src to dst,
574  * forcing dst to follow src.
575  */
576 static int node_follows(struct isl_sched_graph *graph, 
577         struct isl_sched_node *dst, struct isl_sched_node *src)
578 {
579         return graph_has_validity_edge(graph, src, dst);
580 }
581
582 /* Perform Tarjan's algorithm for computing the strongly connected components
583  * in the dependence graph (only validity edges).
584  * If directed is not set, we consider the graph to be undirected and
585  * we effectively compute the (weakly) connected components.
586  */
587 static int detect_sccs_tarjan(struct isl_sched_graph *g, int i, int directed)
588 {
589         int j;
590
591         g->node[i].index = g->index;
592         g->node[i].min_index = g->index;
593         g->node[i].on_stack = 1;
594         g->index++;
595         g->stack[g->sp++] = i;
596
597         for (j = g->n - 1; j >= 0; --j) {
598                 int f;
599
600                 if (j == i)
601                         continue;
602                 if (g->node[j].index >= 0 &&
603                         (!g->node[j].on_stack ||
604                          g->node[j].index > g->node[i].min_index))
605                         continue;
606                 
607                 f = node_follows(g, &g->node[i], &g->node[j]);
608                 if (f < 0)
609                         return -1;
610                 if (!f && !directed) {
611                         f = node_follows(g, &g->node[j], &g->node[i]);
612                         if (f < 0)
613                                 return -1;
614                 }
615                 if (!f)
616                         continue;
617                 if (g->node[j].index < 0) {
618                         detect_sccs_tarjan(g, j, directed);
619                         if (g->node[j].min_index < g->node[i].min_index)
620                                 g->node[i].min_index = g->node[j].min_index;
621                 } else if (g->node[j].index < g->node[i].min_index)
622                         g->node[i].min_index = g->node[j].index;
623         }
624
625         if (g->node[i].index != g->node[i].min_index)
626                 return 0;
627
628         do {
629                 j = g->stack[--g->sp];
630                 g->node[j].on_stack = 0;
631                 g->node[j].scc = g->scc;
632         } while (j != i);
633         g->scc++;
634
635         return 0;
636 }
637
638 static int detect_ccs(struct isl_sched_graph *graph, int directed)
639 {
640         int i;
641
642         graph->index = 0;
643         graph->sp = 0;
644         graph->scc = 0;
645         for (i = graph->n - 1; i >= 0; --i)
646                 graph->node[i].index = -1;
647
648         for (i = graph->n - 1; i >= 0; --i) {
649                 if (graph->node[i].index >= 0)
650                         continue;
651                 if (detect_sccs_tarjan(graph, i, directed) < 0)
652                         return -1;
653         }
654
655         return 0;
656 }
657
658 /* Apply Tarjan's algorithm to detect the strongly connected components
659  * in the dependence graph.
660  */
661 static int detect_sccs(struct isl_sched_graph *graph)
662 {
663         return detect_ccs(graph, 1);
664 }
665
666 /* Apply Tarjan's algorithm to detect the (weakly) connected components
667  * in the dependence graph.
668  */
669 static int detect_wccs(struct isl_sched_graph *graph)
670 {
671         return detect_ccs(graph, 0);
672 }
673
674 static int cmp_scc(const void *a, const void *b, void *data)
675 {
676         struct isl_sched_graph *graph = data;
677         const int *i1 = a;
678         const int *i2 = b;
679
680         return graph->node[*i1].scc - graph->node[*i2].scc;
681 }
682
683 /* Sort the elements of graph->sorted according to the corresponding SCCs.
684  */
685 static void sort_sccs(struct isl_sched_graph *graph)
686 {
687         isl_quicksort(graph->sorted, graph->n, sizeof(int), &cmp_scc, graph);
688 }
689
690 /* Given a dependence relation R from a node to itself,
691  * construct the set of coefficients of valid constraints for elements
692  * in that dependence relation.
693  * In particular, the result contains tuples of coefficients
694  * c_0, c_n, c_x such that
695  *
696  *      c_0 + c_n n + c_x y - c_x x >= 0 for each (x,y) in R
697  *
698  * or, equivalently,
699  *
700  *      c_0 + c_n n + c_x d >= 0 for each d in delta R = { y - x | (x,y) in R }
701  *
702  * We choose here to compute the dual of delta R.
703  * Alternatively, we could have computed the dual of R, resulting
704  * in a set of tuples c_0, c_n, c_x, c_y, and then
705  * plugged in (c_0, c_n, c_x, -c_x).
706  */
707 static __isl_give isl_basic_set *intra_coefficients(
708         struct isl_sched_graph *graph, __isl_take isl_map *map)
709 {
710         isl_ctx *ctx = isl_map_get_ctx(map);
711         isl_set *delta;
712         isl_basic_set *coef;
713
714         if (isl_hmap_map_basic_set_has(ctx, graph->intra_hmap, map))
715                 return isl_hmap_map_basic_set_get(ctx, graph->intra_hmap, map);
716
717         delta = isl_set_remove_divs(isl_map_deltas(isl_map_copy(map)));
718         coef = isl_set_coefficients(delta);
719         isl_hmap_map_basic_set_set(ctx, graph->intra_hmap, map,
720                                         isl_basic_set_copy(coef));
721
722         return coef;
723 }
724
725 /* Given a dependence relation R, * construct the set of coefficients
726  * of valid constraints for elements in that dependence relation.
727  * In particular, the result contains tuples of coefficients
728  * c_0, c_n, c_x, c_y such that
729  *
730  *      c_0 + c_n n + c_x x + c_y y >= 0 for each (x,y) in R
731  *
732  */
733 static __isl_give isl_basic_set *inter_coefficients(
734         struct isl_sched_graph *graph, __isl_take isl_map *map)
735 {
736         isl_ctx *ctx = isl_map_get_ctx(map);
737         isl_set *set;
738         isl_basic_set *coef;
739
740         if (isl_hmap_map_basic_set_has(ctx, graph->inter_hmap, map))
741                 return isl_hmap_map_basic_set_get(ctx, graph->inter_hmap, map);
742
743         set = isl_map_wrap(isl_map_remove_divs(isl_map_copy(map)));
744         coef = isl_set_coefficients(set);
745         isl_hmap_map_basic_set_set(ctx, graph->inter_hmap, map,
746                                         isl_basic_set_copy(coef));
747
748         return coef;
749 }
750
751 /* Add constraints to graph->lp that force validity for the given
752  * dependence from a node i to itself.
753  * That is, add constraints that enforce
754  *
755  *      (c_i_0 + c_i_n n + c_i_x y) - (c_i_0 + c_i_n n + c_i_x x)
756  *      = c_i_x (y - x) >= 0
757  *
758  * for each (x,y) in R.
759  * We obtain general constraints on coefficients (c_0, c_n, c_x)
760  * of valid constraints for (y - x) and then plug in (0, 0, c_i_x^+ - c_i_x^-),
761  * where c_i_x = c_i_x^+ - c_i_x^-, with c_i_x^+ and c_i_x^- non-negative.
762  * In graph->lp, the c_i_x^- appear before their c_i_x^+ counterpart.
763  *
764  * Actually, we do not construct constraints for the c_i_x themselves,
765  * but for the coefficients of c_i_x written as a linear combination
766  * of the columns in node->cmap.
767  */
768 static int add_intra_validity_constraints(struct isl_sched_graph *graph,
769         struct isl_sched_edge *edge)
770 {
771         unsigned total;
772         isl_map *map = isl_map_copy(edge->map);
773         isl_ctx *ctx = isl_map_get_ctx(map);
774         isl_space *dim;
775         isl_dim_map *dim_map;
776         isl_basic_set *coef;
777         struct isl_sched_node *node = edge->src;
778
779         coef = intra_coefficients(graph, map);
780
781         dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
782
783         coef = isl_basic_set_transform_dims(coef, isl_dim_set,
784                     isl_space_dim(dim, isl_dim_set), isl_mat_copy(node->cmap));
785
786         total = isl_basic_set_total_dim(graph->lp);
787         dim_map = isl_dim_map_alloc(ctx, total);
788         isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 1, 2,
789                           isl_space_dim(dim, isl_dim_set), 1,
790                           node->nvar, -1);
791         isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 2, 2,
792                           isl_space_dim(dim, isl_dim_set), 1,
793                           node->nvar, 1);
794         graph->lp = isl_basic_set_extend_constraints(graph->lp,
795                         coef->n_eq, coef->n_ineq);
796         graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
797                                                            coef, dim_map);
798         isl_space_free(dim);
799
800         return 0;
801 }
802
803 /* Add constraints to graph->lp that force validity for the given
804  * dependence from node i to node j.
805  * That is, add constraints that enforce
806  *
807  *      (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x) >= 0
808  *
809  * for each (x,y) in R.
810  * We obtain general constraints on coefficients (c_0, c_n, c_x, c_y)
811  * of valid constraints for R and then plug in
812  * (c_j_0 - c_i_0, c_j_n^+ - c_j_n^- - (c_i_n^+ - c_i_n^-),
813  *  c_j_x^+ - c_j_x^- - (c_i_x^+ - c_i_x^-)),
814  * where c_* = c_*^+ - c_*^-, with c_*^+ and c_*^- non-negative.
815  * In graph->lp, the c_*^- appear before their c_*^+ counterpart.
816  *
817  * Actually, we do not construct constraints for the c_*_x themselves,
818  * but for the coefficients of c_*_x written as a linear combination
819  * of the columns in node->cmap.
820  */
821 static int add_inter_validity_constraints(struct isl_sched_graph *graph,
822         struct isl_sched_edge *edge)
823 {
824         unsigned total;
825         isl_map *map = isl_map_copy(edge->map);
826         isl_ctx *ctx = isl_map_get_ctx(map);
827         isl_space *dim;
828         isl_dim_map *dim_map;
829         isl_basic_set *coef;
830         struct isl_sched_node *src = edge->src;
831         struct isl_sched_node *dst = edge->dst;
832
833         coef = inter_coefficients(graph, map);
834
835         dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
836
837         coef = isl_basic_set_transform_dims(coef, isl_dim_set,
838                     isl_space_dim(dim, isl_dim_set), isl_mat_copy(src->cmap));
839         coef = isl_basic_set_transform_dims(coef, isl_dim_set,
840                     isl_space_dim(dim, isl_dim_set) + src->nvar,
841                     isl_mat_copy(dst->cmap));
842
843         total = isl_basic_set_total_dim(graph->lp);
844         dim_map = isl_dim_map_alloc(ctx, total);
845
846         isl_dim_map_range(dim_map, dst->start, 0, 0, 0, 1, 1);
847         isl_dim_map_range(dim_map, dst->start + 1, 2, 1, 1, dst->nparam, -1);
848         isl_dim_map_range(dim_map, dst->start + 2, 2, 1, 1, dst->nparam, 1);
849         isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 1, 2,
850                           isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
851                           dst->nvar, -1);
852         isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 2, 2,
853                           isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
854                           dst->nvar, 1);
855
856         isl_dim_map_range(dim_map, src->start, 0, 0, 0, 1, -1);
857         isl_dim_map_range(dim_map, src->start + 1, 2, 1, 1, src->nparam, 1);
858         isl_dim_map_range(dim_map, src->start + 2, 2, 1, 1, src->nparam, -1);
859         isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 1, 2,
860                           isl_space_dim(dim, isl_dim_set), 1,
861                           src->nvar, 1);
862         isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 2, 2,
863                           isl_space_dim(dim, isl_dim_set), 1,
864                           src->nvar, -1);
865
866         edge->start = graph->lp->n_ineq;
867         graph->lp = isl_basic_set_extend_constraints(graph->lp,
868                         coef->n_eq, coef->n_ineq);
869         graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
870                                                            coef, dim_map);
871         isl_space_free(dim);
872         edge->end = graph->lp->n_ineq;
873
874         return 0;
875 }
876
877 /* Add constraints to graph->lp that bound the dependence distance for the given
878  * dependence from a node i to itself.
879  * If s = 1, we add the constraint
880  *
881  *      c_i_x (y - x) <= m_0 + m_n n
882  *
883  * or
884  *
885  *      -c_i_x (y - x) + m_0 + m_n n >= 0
886  *
887  * for each (x,y) in R.
888  * If s = -1, we add the constraint
889  *
890  *      -c_i_x (y - x) <= m_0 + m_n n
891  *
892  * or
893  *
894  *      c_i_x (y - x) + m_0 + m_n n >= 0
895  *
896  * for each (x,y) in R.
897  * We obtain general constraints on coefficients (c_0, c_n, c_x)
898  * of valid constraints for (y - x) and then plug in (m_0, m_n, -s * c_i_x),
899  * with each coefficient (except m_0) represented as a pair of non-negative
900  * coefficients.
901  *
902  * Actually, we do not construct constraints for the c_i_x themselves,
903  * but for the coefficients of c_i_x written as a linear combination
904  * of the columns in node->cmap.
905  */
906 static int add_intra_proximity_constraints(struct isl_sched_graph *graph,
907         struct isl_sched_edge *edge, int s)
908 {
909         unsigned total;
910         unsigned nparam;
911         isl_map *map = isl_map_copy(edge->map);
912         isl_ctx *ctx = isl_map_get_ctx(map);
913         isl_space *dim;
914         isl_dim_map *dim_map;
915         isl_basic_set *coef;
916         struct isl_sched_node *node = edge->src;
917
918         coef = intra_coefficients(graph, map);
919
920         dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
921
922         coef = isl_basic_set_transform_dims(coef, isl_dim_set,
923                     isl_space_dim(dim, isl_dim_set), isl_mat_copy(node->cmap));
924
925         nparam = isl_space_dim(node->dim, isl_dim_param);
926         total = isl_basic_set_total_dim(graph->lp);
927         dim_map = isl_dim_map_alloc(ctx, total);
928         isl_dim_map_range(dim_map, 1, 0, 0, 0, 1, 1);
929         isl_dim_map_range(dim_map, 4, 2, 1, 1, nparam, -1);
930         isl_dim_map_range(dim_map, 5, 2, 1, 1, nparam, 1);
931         isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 1, 2,
932                           isl_space_dim(dim, isl_dim_set), 1,
933                           node->nvar, s);
934         isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 2, 2,
935                           isl_space_dim(dim, isl_dim_set), 1,
936                           node->nvar, -s);
937         graph->lp = isl_basic_set_extend_constraints(graph->lp,
938                         coef->n_eq, coef->n_ineq);
939         graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
940                                                            coef, dim_map);
941         isl_space_free(dim);
942
943         return 0;
944 }
945
946 /* Add constraints to graph->lp that bound the dependence distance for the given
947  * dependence from node i to node j.
948  * If s = 1, we add the constraint
949  *
950  *      (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x)
951  *              <= m_0 + m_n n
952  *
953  * or
954  *
955  *      -(c_j_0 + c_j_n n + c_j_x y) + (c_i_0 + c_i_n n + c_i_x x) +
956  *              m_0 + m_n n >= 0
957  *
958  * for each (x,y) in R.
959  * If s = -1, we add the constraint
960  *
961  *      -((c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x))
962  *              <= m_0 + m_n n
963  *
964  * or
965  *
966  *      (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x) +
967  *              m_0 + m_n n >= 0
968  *
969  * for each (x,y) in R.
970  * We obtain general constraints on coefficients (c_0, c_n, c_x, c_y)
971  * of valid constraints for R and then plug in
972  * (m_0 - s*c_j_0 + s*c_i_0, m_n - s*c_j_n + s*c_i_n,
973  *  -s*c_j_x+s*c_i_x)
974  * with each coefficient (except m_0, c_j_0 and c_i_0)
975  * represented as a pair of non-negative coefficients.
976  *
977  * Actually, we do not construct constraints for the c_*_x themselves,
978  * but for the coefficients of c_*_x written as a linear combination
979  * of the columns in node->cmap.
980  */
981 static int add_inter_proximity_constraints(struct isl_sched_graph *graph,
982         struct isl_sched_edge *edge, int s)
983 {
984         unsigned total;
985         unsigned nparam;
986         isl_map *map = isl_map_copy(edge->map);
987         isl_ctx *ctx = isl_map_get_ctx(map);
988         isl_space *dim;
989         isl_dim_map *dim_map;
990         isl_basic_set *coef;
991         struct isl_sched_node *src = edge->src;
992         struct isl_sched_node *dst = edge->dst;
993
994         coef = inter_coefficients(graph, map);
995
996         dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
997
998         coef = isl_basic_set_transform_dims(coef, isl_dim_set,
999                     isl_space_dim(dim, isl_dim_set), isl_mat_copy(src->cmap));
1000         coef = isl_basic_set_transform_dims(coef, isl_dim_set,
1001                     isl_space_dim(dim, isl_dim_set) + src->nvar,
1002                     isl_mat_copy(dst->cmap));
1003
1004         nparam = isl_space_dim(src->dim, isl_dim_param);
1005         total = isl_basic_set_total_dim(graph->lp);
1006         dim_map = isl_dim_map_alloc(ctx, total);
1007
1008         isl_dim_map_range(dim_map, 1, 0, 0, 0, 1, 1);
1009         isl_dim_map_range(dim_map, 4, 2, 1, 1, nparam, -1);
1010         isl_dim_map_range(dim_map, 5, 2, 1, 1, nparam, 1);
1011
1012         isl_dim_map_range(dim_map, dst->start, 0, 0, 0, 1, -s);
1013         isl_dim_map_range(dim_map, dst->start + 1, 2, 1, 1, dst->nparam, s);
1014         isl_dim_map_range(dim_map, dst->start + 2, 2, 1, 1, dst->nparam, -s);
1015         isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 1, 2,
1016                           isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
1017                           dst->nvar, s);
1018         isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 2, 2,
1019                           isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
1020                           dst->nvar, -s);
1021
1022         isl_dim_map_range(dim_map, src->start, 0, 0, 0, 1, s);
1023         isl_dim_map_range(dim_map, src->start + 1, 2, 1, 1, src->nparam, -s);
1024         isl_dim_map_range(dim_map, src->start + 2, 2, 1, 1, src->nparam, s);
1025         isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 1, 2,
1026                           isl_space_dim(dim, isl_dim_set), 1,
1027                           src->nvar, -s);
1028         isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 2, 2,
1029                           isl_space_dim(dim, isl_dim_set), 1,
1030                           src->nvar, s);
1031
1032         graph->lp = isl_basic_set_extend_constraints(graph->lp,
1033                         coef->n_eq, coef->n_ineq);
1034         graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
1035                                                            coef, dim_map);
1036         isl_space_free(dim);
1037
1038         return 0;
1039 }
1040
1041 static int add_all_validity_constraints(struct isl_sched_graph *graph)
1042 {
1043         int i;
1044
1045         for (i = 0; i < graph->n_edge; ++i) {
1046                 struct isl_sched_edge *edge= &graph->edge[i];
1047                 if (!edge->validity)
1048                         continue;
1049                 if (edge->src != edge->dst)
1050                         continue;
1051                 if (add_intra_validity_constraints(graph, edge) < 0)
1052                         return -1;
1053         }
1054
1055         for (i = 0; i < graph->n_edge; ++i) {
1056                 struct isl_sched_edge *edge = &graph->edge[i];
1057                 if (!edge->validity)
1058                         continue;
1059                 if (edge->src == edge->dst)
1060                         continue;
1061                 if (add_inter_validity_constraints(graph, edge) < 0)
1062                         return -1;
1063         }
1064
1065         return 0;
1066 }
1067
1068 /* Add constraints to graph->lp that bound the dependence distance
1069  * for all dependence relations.
1070  * If a given proximity dependence is identical to a validity
1071  * dependence, then the dependence distance is already bounded
1072  * from below (by zero), so we only need to bound the distance
1073  * from above.
1074  * Otherwise, we need to bound the distance both from above and from below.
1075  */
1076 static int add_all_proximity_constraints(struct isl_sched_graph *graph)
1077 {
1078         int i;
1079
1080         for (i = 0; i < graph->n_edge; ++i) {
1081                 struct isl_sched_edge *edge= &graph->edge[i];
1082                 if (!edge->proximity)
1083                         continue;
1084                 if (edge->src == edge->dst &&
1085                     add_intra_proximity_constraints(graph, edge, 1) < 0)
1086                         return -1;
1087                 if (edge->src != edge->dst &&
1088                     add_inter_proximity_constraints(graph, edge, 1) < 0)
1089                         return -1;
1090                 if (edge->validity)
1091                         continue;
1092                 if (edge->src == edge->dst &&
1093                     add_intra_proximity_constraints(graph, edge, -1) < 0)
1094                         return -1;
1095                 if (edge->src != edge->dst &&
1096                     add_inter_proximity_constraints(graph, edge, -1) < 0)
1097                         return -1;
1098         }
1099
1100         return 0;
1101 }
1102
1103 /* Compute a basis for the rows in the linear part of the schedule
1104  * and extend this basis to a full basis.  The remaining rows
1105  * can then be used to force linear independence from the rows
1106  * in the schedule.
1107  *
1108  * In particular, given the schedule rows S, we compute
1109  *
1110  *      S = H Q
1111  *
1112  * with H the Hermite normal form of S.  That is, all but the
1113  * first rank columns of Q are zero and so each row in S is
1114  * a linear combination of the first rank rows of Q.
1115  * The matrix Q is then transposed because we will write the
1116  * coefficients of the next schedule row as a column vector s
1117  * and express this s as a linear combination s = Q c of the
1118  * computed basis.
1119  */
1120 static int node_update_cmap(struct isl_sched_node *node)
1121 {
1122         isl_mat *H, *Q;
1123         int n_row = isl_mat_rows(node->sched);
1124
1125         H = isl_mat_sub_alloc(node->sched, 0, n_row,
1126                               1 + node->nparam, node->nvar);
1127
1128         H = isl_mat_left_hermite(H, 0, NULL, &Q);
1129         isl_mat_free(node->cmap);
1130         node->cmap = isl_mat_transpose(Q);
1131         node->rank = isl_mat_initial_non_zero_cols(H);
1132         isl_mat_free(H);
1133
1134         if (!node->cmap || node->rank < 0)
1135                 return -1;
1136         return 0;
1137 }
1138
1139 /* Count the number of equality and inequality constraints
1140  * that will be added for the given map.
1141  * If carry is set, then we are counting the number of (validity)
1142  * constraints that will be added in setup_carry_lp and we count
1143  * each edge exactly once.  Otherwise, we count as follows
1144  * validity             -> 1 (>= 0)
1145  * validity+proximity   -> 2 (>= 0 and upper bound)
1146  * proximity            -> 2 (lower and upper bound)
1147  */
1148 static int count_map_constraints(struct isl_sched_graph *graph,
1149         struct isl_sched_edge *edge, __isl_take isl_map *map,
1150         int *n_eq, int *n_ineq, int carry)
1151 {
1152         isl_basic_set *coef;
1153         int f = carry ? 1 : edge->proximity ? 2 : 1;
1154
1155         if (carry && !edge->validity) {
1156                 isl_map_free(map);
1157                 return 0;
1158         }
1159
1160         if (edge->src == edge->dst)
1161                 coef = intra_coefficients(graph, map);
1162         else
1163                 coef = inter_coefficients(graph, map);
1164         if (!coef)
1165                 return -1;
1166         *n_eq += f * coef->n_eq;
1167         *n_ineq += f * coef->n_ineq;
1168         isl_basic_set_free(coef);
1169
1170         return 0;
1171 }
1172
1173 /* Count the number of equality and inequality constraints
1174  * that will be added to the main lp problem.
1175  * We count as follows
1176  * validity             -> 1 (>= 0)
1177  * validity+proximity   -> 2 (>= 0 and upper bound)
1178  * proximity            -> 2 (lower and upper bound)
1179  */
1180 static int count_constraints(struct isl_sched_graph *graph,
1181         int *n_eq, int *n_ineq)
1182 {
1183         int i;
1184
1185         *n_eq = *n_ineq = 0;
1186         for (i = 0; i < graph->n_edge; ++i) {
1187                 struct isl_sched_edge *edge= &graph->edge[i];
1188                 isl_map *map = isl_map_copy(edge->map);
1189
1190                 if (count_map_constraints(graph, edge, map,
1191                                           n_eq, n_ineq, 0) < 0)
1192                         return -1;
1193         }
1194
1195         return 0;
1196 }
1197
1198 /* Add constraints that bound the values of the variable and parameter
1199  * coefficients of the schedule.
1200  *
1201  * The maximal value of the coefficients is defined by the option
1202  * 'schedule_max_coefficient'.
1203  */
1204 static int add_bound_coefficient_constraints(isl_ctx *ctx,
1205         struct isl_sched_graph *graph)
1206 {
1207         int i, j, k;
1208         int max_coefficient;
1209         int total;
1210
1211         max_coefficient = ctx->opt->schedule_max_coefficient;
1212
1213         if (max_coefficient == -1)
1214                 return 0;
1215
1216         total = isl_basic_set_total_dim(graph->lp);
1217
1218         for (i = 0; i < graph->n; ++i) {
1219                 struct isl_sched_node *node = &graph->node[i];
1220                 for (j = 0; j < 2 * node->nparam + 2 * node->nvar; ++j) {
1221                         int dim;
1222                         k = isl_basic_set_alloc_inequality(graph->lp);
1223                         if (k < 0)
1224                                 return -1;
1225                         dim = 1 + node->start + 1 + j;
1226                         isl_seq_clr(graph->lp->ineq[k], 1 +  total);
1227                         isl_int_set_si(graph->lp->ineq[k][dim], -1);
1228                         isl_int_set_si(graph->lp->ineq[k][0], max_coefficient);
1229                 }
1230         }
1231
1232         return 0;
1233 }
1234
1235 /* Construct an ILP problem for finding schedule coefficients
1236  * that result in non-negative, but small dependence distances
1237  * over all dependences.
1238  * In particular, the dependence distances over proximity edges
1239  * are bounded by m_0 + m_n n and we compute schedule coefficients
1240  * with small values (preferably zero) of m_n and m_0.
1241  *
1242  * All variables of the ILP are non-negative.  The actual coefficients
1243  * may be negative, so each coefficient is represented as the difference
1244  * of two non-negative variables.  The negative part always appears
1245  * immediately before the positive part.
1246  * Other than that, the variables have the following order
1247  *
1248  *      - sum of positive and negative parts of m_n coefficients
1249  *      - m_0
1250  *      - sum of positive and negative parts of all c_n coefficients
1251  *              (unconstrained when computing non-parametric schedules)
1252  *      - sum of positive and negative parts of all c_x coefficients
1253  *      - positive and negative parts of m_n coefficients
1254  *      - for each node
1255  *              - c_i_0
1256  *              - positive and negative parts of c_i_n (if parametric)
1257  *              - positive and negative parts of c_i_x
1258  *
1259  * The c_i_x are not represented directly, but through the columns of
1260  * node->cmap.  That is, the computed values are for variable t_i_x
1261  * such that c_i_x = Q t_i_x with Q equal to node->cmap.
1262  *
1263  * The constraints are those from the edges plus two or three equalities
1264  * to express the sums.
1265  *
1266  * If force_zero is set, then we add equalities to ensure that
1267  * the sum of the m_n coefficients and m_0 are both zero.
1268  */
1269 static int setup_lp(isl_ctx *ctx, struct isl_sched_graph *graph,
1270         int force_zero)
1271 {
1272         int i, j;
1273         int k;
1274         unsigned nparam;
1275         unsigned total;
1276         isl_space *dim;
1277         int parametric;
1278         int param_pos;
1279         int n_eq, n_ineq;
1280         int max_constant_term;
1281         int max_coefficient;
1282
1283         max_constant_term = ctx->opt->schedule_max_constant_term;
1284         max_coefficient = ctx->opt->schedule_max_coefficient;
1285
1286         parametric = ctx->opt->schedule_parametric;
1287         nparam = isl_space_dim(graph->node[0].dim, isl_dim_param);
1288         param_pos = 4;
1289         total = param_pos + 2 * nparam;
1290         for (i = 0; i < graph->n; ++i) {
1291                 struct isl_sched_node *node = &graph->node[graph->sorted[i]];
1292                 if (node_update_cmap(node) < 0)
1293                         return -1;
1294                 node->start = total;
1295                 total += 1 + 2 * (node->nparam + node->nvar);
1296         }
1297
1298         if (count_constraints(graph, &n_eq, &n_ineq) < 0)
1299                 return -1;
1300
1301         dim = isl_space_set_alloc(ctx, 0, total);
1302         isl_basic_set_free(graph->lp);
1303         n_eq += 2 + parametric + force_zero;
1304         if (max_constant_term != -1)
1305                 n_ineq += graph->n;
1306         if (max_coefficient != -1)
1307                 for (i = 0; i < graph->n; ++i)
1308                         n_ineq += 2 * graph->node[i].nparam +
1309                                   2 * graph->node[i].nvar;
1310
1311         graph->lp = isl_basic_set_alloc_space(dim, 0, n_eq, n_ineq);
1312
1313         k = isl_basic_set_alloc_equality(graph->lp);
1314         if (k < 0)
1315                 return -1;
1316         isl_seq_clr(graph->lp->eq[k], 1 +  total);
1317         if (!force_zero)
1318                 isl_int_set_si(graph->lp->eq[k][1], -1);
1319         for (i = 0; i < 2 * nparam; ++i)
1320                 isl_int_set_si(graph->lp->eq[k][1 + param_pos + i], 1);
1321
1322         if (force_zero) {
1323                 k = isl_basic_set_alloc_equality(graph->lp);
1324                 if (k < 0)
1325                         return -1;
1326                 isl_seq_clr(graph->lp->eq[k], 1 +  total);
1327                 isl_int_set_si(graph->lp->eq[k][2], -1);
1328         }
1329
1330         if (parametric) {
1331                 k = isl_basic_set_alloc_equality(graph->lp);
1332                 if (k < 0)
1333                         return -1;
1334                 isl_seq_clr(graph->lp->eq[k], 1 +  total);
1335                 isl_int_set_si(graph->lp->eq[k][3], -1);
1336                 for (i = 0; i < graph->n; ++i) {
1337                         int pos = 1 + graph->node[i].start + 1;
1338
1339                         for (j = 0; j < 2 * graph->node[i].nparam; ++j)
1340                                 isl_int_set_si(graph->lp->eq[k][pos + j], 1);
1341                 }
1342         }
1343
1344         k = isl_basic_set_alloc_equality(graph->lp);
1345         if (k < 0)
1346                 return -1;
1347         isl_seq_clr(graph->lp->eq[k], 1 +  total);
1348         isl_int_set_si(graph->lp->eq[k][4], -1);
1349         for (i = 0; i < graph->n; ++i) {
1350                 struct isl_sched_node *node = &graph->node[i];
1351                 int pos = 1 + node->start + 1 + 2 * node->nparam;
1352
1353                 for (j = 0; j < 2 * node->nvar; ++j)
1354                         isl_int_set_si(graph->lp->eq[k][pos + j], 1);
1355         }
1356
1357         if (max_constant_term != -1)
1358                 for (i = 0; i < graph->n; ++i) {
1359                         struct isl_sched_node *node = &graph->node[i];
1360                         k = isl_basic_set_alloc_inequality(graph->lp);
1361                         if (k < 0)
1362                                 return -1;
1363                         isl_seq_clr(graph->lp->ineq[k], 1 +  total);
1364                         isl_int_set_si(graph->lp->ineq[k][1 + node->start], -1);
1365                         isl_int_set_si(graph->lp->ineq[k][0], max_constant_term);
1366                 }
1367
1368         if (add_bound_coefficient_constraints(ctx, graph) < 0)
1369                 return -1;
1370         if (add_all_validity_constraints(graph) < 0)
1371                 return -1;
1372         if (add_all_proximity_constraints(graph) < 0)
1373                 return -1;
1374
1375         return 0;
1376 }
1377
1378 /* Analyze the conflicting constraint found by
1379  * isl_tab_basic_set_non_trivial_lexmin.  If it corresponds to the validity
1380  * constraint of one of the edges between distinct nodes, living, moreover
1381  * in distinct SCCs, then record the source and sink SCC as this may
1382  * be a good place to cut between SCCs.
1383  */
1384 static int check_conflict(int con, void *user)
1385 {
1386         int i;
1387         struct isl_sched_graph *graph = user;
1388
1389         if (graph->src_scc >= 0)
1390                 return 0;
1391
1392         con -= graph->lp->n_eq;
1393
1394         if (con >= graph->lp->n_ineq)
1395                 return 0;
1396
1397         for (i = 0; i < graph->n_edge; ++i) {
1398                 if (!graph->edge[i].validity)
1399                         continue;
1400                 if (graph->edge[i].src == graph->edge[i].dst)
1401                         continue;
1402                 if (graph->edge[i].src->scc == graph->edge[i].dst->scc)
1403                         continue;
1404                 if (graph->edge[i].start > con)
1405                         continue;
1406                 if (graph->edge[i].end <= con)
1407                         continue;
1408                 graph->src_scc = graph->edge[i].src->scc;
1409                 graph->dst_scc = graph->edge[i].dst->scc;
1410         }
1411
1412         return 0;
1413 }
1414
1415 /* Check whether the next schedule row of the given node needs to be
1416  * non-trivial.  Lower-dimensional domains may have some trivial rows,
1417  * but as soon as the number of remaining required non-trivial rows
1418  * is as large as the number or remaining rows to be computed,
1419  * all remaining rows need to be non-trivial.
1420  */
1421 static int needs_row(struct isl_sched_graph *graph, struct isl_sched_node *node)
1422 {
1423         return node->nvar - node->rank >= graph->maxvar - graph->n_row;
1424 }
1425
1426 /* Solve the ILP problem constructed in setup_lp.
1427  * For each node such that all the remaining rows of its schedule
1428  * need to be non-trivial, we construct a non-triviality region.
1429  * This region imposes that the next row is independent of previous rows.
1430  * In particular the coefficients c_i_x are represented by t_i_x
1431  * variables with c_i_x = Q t_i_x and Q a unimodular matrix such that
1432  * its first columns span the rows of the previously computed part
1433  * of the schedule.  The non-triviality region enforces that at least
1434  * one of the remaining components of t_i_x is non-zero, i.e.,
1435  * that the new schedule row depends on at least one of the remaining
1436  * columns of Q.
1437  */
1438 static __isl_give isl_vec *solve_lp(struct isl_sched_graph *graph)
1439 {
1440         int i;
1441         isl_vec *sol;
1442         isl_basic_set *lp;
1443
1444         for (i = 0; i < graph->n; ++i) {
1445                 struct isl_sched_node *node = &graph->node[i];
1446                 int skip = node->rank;
1447                 graph->region[i].pos = node->start + 1 + 2*(node->nparam+skip);
1448                 if (needs_row(graph, node))
1449                         graph->region[i].len = 2 * (node->nvar - skip);
1450                 else
1451                         graph->region[i].len = 0;
1452         }
1453         lp = isl_basic_set_copy(graph->lp);
1454         sol = isl_tab_basic_set_non_trivial_lexmin(lp, 2, graph->n,
1455                                        graph->region, &check_conflict, graph);
1456         return sol;
1457 }
1458
1459 /* Update the schedules of all nodes based on the given solution
1460  * of the LP problem.
1461  * The new row is added to the current band.
1462  * All possibly negative coefficients are encoded as a difference
1463  * of two non-negative variables, so we need to perform the subtraction
1464  * here.  Moreover, if use_cmap is set, then the solution does
1465  * not refer to the actual coefficients c_i_x, but instead to variables
1466  * t_i_x such that c_i_x = Q t_i_x and Q is equal to node->cmap.
1467  * In this case, we then also need to perform this multiplication
1468  * to obtain the values of c_i_x.
1469  *
1470  * If check_zero is set, then the first two coordinates of sol are
1471  * assumed to correspond to the dependence distance.  If these two
1472  * coordinates are zero, then the corresponding scheduling dimension
1473  * is marked as being zero distance.
1474  */
1475 static int update_schedule(struct isl_sched_graph *graph,
1476         __isl_take isl_vec *sol, int use_cmap, int check_zero)
1477 {
1478         int i, j;
1479         int zero = 0;
1480         isl_vec *csol = NULL;
1481
1482         if (!sol)
1483                 goto error;
1484         if (sol->size == 0)
1485                 isl_die(sol->ctx, isl_error_internal,
1486                         "no solution found", goto error);
1487
1488         if (check_zero)
1489                 zero = isl_int_is_zero(sol->el[1]) &&
1490                            isl_int_is_zero(sol->el[2]);
1491
1492         for (i = 0; i < graph->n; ++i) {
1493                 struct isl_sched_node *node = &graph->node[i];
1494                 int pos = node->start;
1495                 int row = isl_mat_rows(node->sched);
1496
1497                 isl_vec_free(csol);
1498                 csol = isl_vec_alloc(sol->ctx, node->nvar);
1499                 if (!csol)
1500                         goto error;
1501
1502                 isl_map_free(node->sched_map);
1503                 node->sched_map = NULL;
1504                 node->sched = isl_mat_add_rows(node->sched, 1);
1505                 if (!node->sched)
1506                         goto error;
1507                 node->sched = isl_mat_set_element(node->sched, row, 0,
1508                                                   sol->el[1 + pos]);
1509                 for (j = 0; j < node->nparam + node->nvar; ++j)
1510                         isl_int_sub(sol->el[1 + pos + 1 + 2 * j + 1],
1511                                     sol->el[1 + pos + 1 + 2 * j + 1],
1512                                     sol->el[1 + pos + 1 + 2 * j]);
1513                 for (j = 0; j < node->nparam; ++j)
1514                         node->sched = isl_mat_set_element(node->sched,
1515                                         row, 1 + j, sol->el[1+pos+1+2*j+1]);
1516                 for (j = 0; j < node->nvar; ++j)
1517                         isl_int_set(csol->el[j],
1518                                     sol->el[1+pos+1+2*(node->nparam+j)+1]);
1519                 if (use_cmap)
1520                         csol = isl_mat_vec_product(isl_mat_copy(node->cmap),
1521                                                    csol);
1522                 if (!csol)
1523                         goto error;
1524                 for (j = 0; j < node->nvar; ++j)
1525                         node->sched = isl_mat_set_element(node->sched,
1526                                         row, 1 + node->nparam + j, csol->el[j]);
1527                 node->band[graph->n_total_row] = graph->n_band;
1528                 node->zero[graph->n_total_row] = zero;
1529         }
1530         isl_vec_free(sol);
1531         isl_vec_free(csol);
1532
1533         graph->n_row++;
1534         graph->n_total_row++;
1535
1536         return 0;
1537 error:
1538         isl_vec_free(sol);
1539         isl_vec_free(csol);
1540         return -1;
1541 }
1542
1543 /* Convert node->sched into a map and return this map.
1544  * We simply add equality constraints that express each output variable
1545  * as the affine combination of parameters and input variables specified
1546  * by the schedule matrix.
1547  *
1548  * The result is cached in node->sched_map, which needs to be released
1549  * whenever node->sched is updated.
1550  */
1551 static __isl_give isl_map *node_extract_schedule(struct isl_sched_node *node)
1552 {
1553         int i, j;
1554         isl_space *dim;
1555         isl_local_space *ls;
1556         isl_basic_map *bmap;
1557         isl_constraint *c;
1558         int nrow, ncol;
1559         isl_int v;
1560
1561         if (node->sched_map)
1562                 return isl_map_copy(node->sched_map);
1563
1564         nrow = isl_mat_rows(node->sched);
1565         ncol = isl_mat_cols(node->sched) - 1;
1566         dim = isl_space_from_domain(isl_space_copy(node->dim));
1567         dim = isl_space_add_dims(dim, isl_dim_out, nrow);
1568         bmap = isl_basic_map_universe(isl_space_copy(dim));
1569         ls = isl_local_space_from_space(dim);
1570
1571         isl_int_init(v);
1572
1573         for (i = 0; i < nrow; ++i) {
1574                 c = isl_equality_alloc(isl_local_space_copy(ls));
1575                 isl_constraint_set_coefficient_si(c, isl_dim_out, i, -1);
1576                 isl_mat_get_element(node->sched, i, 0, &v);
1577                 isl_constraint_set_constant(c, v);
1578                 for (j = 0; j < node->nparam; ++j) {
1579                         isl_mat_get_element(node->sched, i, 1 + j, &v);
1580                         isl_constraint_set_coefficient(c, isl_dim_param, j, v);
1581                 }
1582                 for (j = 0; j < node->nvar; ++j) {
1583                         isl_mat_get_element(node->sched,
1584                                             i, 1 + node->nparam + j, &v);
1585                         isl_constraint_set_coefficient(c, isl_dim_in, j, v);
1586                 }
1587                 bmap = isl_basic_map_add_constraint(bmap, c);
1588         }
1589
1590         isl_int_clear(v);
1591
1592         isl_local_space_free(ls);
1593
1594         node->sched_map = isl_map_from_basic_map(bmap);
1595         return isl_map_copy(node->sched_map);
1596 }
1597
1598 /* Update the given dependence relation based on the current schedule.
1599  * That is, intersect the dependence relation with a map expressing
1600  * that source and sink are executed within the same iteration of
1601  * the current schedule.
1602  * This is not the most efficient way, but this shouldn't be a critical
1603  * operation.
1604  */
1605 static __isl_give isl_map *specialize(__isl_take isl_map *map,
1606         struct isl_sched_node *src, struct isl_sched_node *dst)
1607 {
1608         isl_map *src_sched, *dst_sched, *id;
1609
1610         src_sched = node_extract_schedule(src);
1611         dst_sched = node_extract_schedule(dst);
1612         id = isl_map_apply_range(src_sched, isl_map_reverse(dst_sched));
1613         return isl_map_intersect(map, id);
1614 }
1615
1616 /* Update the dependence relations of all edges based on the current schedule.
1617  * If a dependence is carried completely by the current schedule, then
1618  * it is removed from the edge_tables.  It is kept in the list of edges
1619  * as otherwise all edge_tables would have to be recomputed.
1620  */
1621 static int update_edges(isl_ctx *ctx, struct isl_sched_graph *graph)
1622 {
1623         int i;
1624
1625         for (i = graph->n_edge - 1; i >= 0; --i) {
1626                 struct isl_sched_edge *edge = &graph->edge[i];
1627                 edge->map = specialize(edge->map, edge->src, edge->dst);
1628                 if (!edge->map)
1629                         return -1;
1630
1631                 if (isl_map_plain_is_empty(edge->map))
1632                         graph_remove_edge(graph, edge);
1633         }
1634
1635         return 0;
1636 }
1637
1638 static void next_band(struct isl_sched_graph *graph)
1639 {
1640         graph->band_start = graph->n_total_row;
1641         graph->n_band++;
1642 }
1643
1644 /* Topologically sort statements mapped to the same schedule iteration
1645  * and add a row to the schedule corresponding to this order.
1646  */
1647 static int sort_statements(isl_ctx *ctx, struct isl_sched_graph *graph)
1648 {
1649         int i, j;
1650
1651         if (graph->n <= 1)
1652                 return 0;
1653
1654         if (update_edges(ctx, graph) < 0)
1655                 return -1;
1656
1657         if (graph->n_edge == 0)
1658                 return 0;
1659
1660         if (detect_sccs(graph) < 0)
1661                 return -1;
1662
1663         for (i = 0; i < graph->n; ++i) {
1664                 struct isl_sched_node *node = &graph->node[i];
1665                 int row = isl_mat_rows(node->sched);
1666                 int cols = isl_mat_cols(node->sched);
1667
1668                 isl_map_free(node->sched_map);
1669                 node->sched_map = NULL;
1670                 node->sched = isl_mat_add_rows(node->sched, 1);
1671                 if (!node->sched)
1672                         return -1;
1673                 node->sched = isl_mat_set_element_si(node->sched, row, 0,
1674                                                      node->scc);
1675                 for (j = 1; j < cols; ++j)
1676                         node->sched = isl_mat_set_element_si(node->sched,
1677                                                              row, j, 0);
1678                 node->band[graph->n_total_row] = graph->n_band;
1679         }
1680
1681         graph->n_total_row++;
1682         next_band(graph);
1683
1684         return 0;
1685 }
1686
1687 /* Construct an isl_schedule based on the computed schedule stored
1688  * in graph and with parameters specified by dim.
1689  */
1690 static __isl_give isl_schedule *extract_schedule(struct isl_sched_graph *graph,
1691         __isl_take isl_space *dim)
1692 {
1693         int i;
1694         isl_ctx *ctx;
1695         isl_schedule *sched = NULL;
1696                 
1697         if (!dim)
1698                 return NULL;
1699
1700         ctx = isl_space_get_ctx(dim);
1701         sched = isl_calloc(ctx, struct isl_schedule,
1702                            sizeof(struct isl_schedule) +
1703                            (graph->n - 1) * sizeof(struct isl_schedule_node));
1704         if (!sched)
1705                 goto error;
1706
1707         sched->ref = 1;
1708         sched->n = graph->n;
1709         sched->n_band = graph->n_band;
1710         sched->n_total_row = graph->n_total_row;
1711
1712         for (i = 0; i < sched->n; ++i) {
1713                 int r, b;
1714                 int *band_end, *band_id, *zero;
1715
1716                 band_end = isl_alloc_array(ctx, int, graph->n_band);
1717                 band_id = isl_alloc_array(ctx, int, graph->n_band);
1718                 zero = isl_alloc_array(ctx, int, graph->n_total_row);
1719                 sched->node[i].sched = node_extract_schedule(&graph->node[i]);
1720                 sched->node[i].band_end = band_end;
1721                 sched->node[i].band_id = band_id;
1722                 sched->node[i].zero = zero;
1723                 if (!band_end || !band_id || !zero)
1724                         goto error;
1725
1726                 for (r = 0; r < graph->n_total_row; ++r)
1727                         zero[r] = graph->node[i].zero[r];
1728                 for (r = b = 0; r < graph->n_total_row; ++r) {
1729                         if (graph->node[i].band[r] == b)
1730                                 continue;
1731                         band_end[b++] = r;
1732                         if (graph->node[i].band[r] == -1)
1733                                 break;
1734                 }
1735                 if (r == graph->n_total_row)
1736                         band_end[b++] = r;
1737                 sched->node[i].n_band = b;
1738                 for (--b; b >= 0; --b)
1739                         band_id[b] = graph->node[i].band_id[b];
1740         }
1741
1742         sched->dim = dim;
1743
1744         return sched;
1745 error:
1746         isl_space_free(dim);
1747         isl_schedule_free(sched);
1748         return NULL;
1749 }
1750
1751 /* Copy nodes that satisfy node_pred from the src dependence graph
1752  * to the dst dependence graph.
1753  */
1754 static int copy_nodes(struct isl_sched_graph *dst, struct isl_sched_graph *src,
1755         int (*node_pred)(struct isl_sched_node *node, int data), int data)
1756 {
1757         int i;
1758
1759         dst->n = 0;
1760         for (i = 0; i < src->n; ++i) {
1761                 if (!node_pred(&src->node[i], data))
1762                         continue;
1763                 dst->node[dst->n].dim = isl_space_copy(src->node[i].dim);
1764                 dst->node[dst->n].nvar = src->node[i].nvar;
1765                 dst->node[dst->n].nparam = src->node[i].nparam;
1766                 dst->node[dst->n].sched = isl_mat_copy(src->node[i].sched);
1767                 dst->node[dst->n].sched_map =
1768                         isl_map_copy(src->node[i].sched_map);
1769                 dst->node[dst->n].band = src->node[i].band;
1770                 dst->node[dst->n].band_id = src->node[i].band_id;
1771                 dst->node[dst->n].zero = src->node[i].zero;
1772                 dst->n++;
1773         }
1774
1775         return 0;
1776 }
1777
1778 /* Copy non-empty edges that satisfy edge_pred from the src dependence graph
1779  * to the dst dependence graph.
1780  * If the source or destination node of the edge is not in the destination
1781  * graph, then it must be a backward proximity edge and it should simply
1782  * be ignored.
1783  */
1784 static int copy_edges(isl_ctx *ctx, struct isl_sched_graph *dst,
1785         struct isl_sched_graph *src,
1786         int (*edge_pred)(struct isl_sched_edge *edge, int data), int data)
1787 {
1788         int i;
1789         int t;
1790
1791         dst->n_edge = 0;
1792         for (i = 0; i < src->n_edge; ++i) {
1793                 struct isl_sched_edge *edge = &src->edge[i];
1794                 isl_map *map;
1795                 struct isl_sched_node *dst_src, *dst_dst;
1796
1797                 if (!edge_pred(edge, data))
1798                         continue;
1799
1800                 if (isl_map_plain_is_empty(edge->map))
1801                         continue;
1802
1803                 dst_src = graph_find_node(ctx, dst, edge->src->dim);
1804                 dst_dst = graph_find_node(ctx, dst, edge->dst->dim);
1805                 if (!dst_src || !dst_dst) {
1806                         if (edge->validity)
1807                                 isl_die(ctx, isl_error_internal,
1808                                         "backward validity edge", return -1);
1809                         continue;
1810                 }
1811
1812                 map = isl_map_copy(edge->map);
1813
1814                 dst->edge[dst->n_edge].src = dst_src;
1815                 dst->edge[dst->n_edge].dst = dst_dst;
1816                 dst->edge[dst->n_edge].map = map;
1817                 dst->edge[dst->n_edge].validity = edge->validity;
1818                 dst->edge[dst->n_edge].proximity = edge->proximity;
1819                 dst->n_edge++;
1820
1821                 for (t = 0; t <= isl_edge_last; ++t) {
1822                         if (edge !=
1823                             graph_find_edge(src, t, edge->src, edge->dst))
1824                                 continue;
1825                         if (graph_edge_table_add(ctx, dst, t,
1826                                             &dst->edge[dst->n_edge - 1]) < 0)
1827                                 return -1;
1828                 }
1829         }
1830
1831         return 0;
1832 }
1833
1834 /* Given a "src" dependence graph that contains the nodes from "dst"
1835  * that satisfy node_pred, copy the schedule computed in "src"
1836  * for those nodes back to "dst".
1837  */
1838 static int copy_schedule(struct isl_sched_graph *dst,
1839         struct isl_sched_graph *src,
1840         int (*node_pred)(struct isl_sched_node *node, int data), int data)
1841 {
1842         int i;
1843
1844         src->n = 0;
1845         for (i = 0; i < dst->n; ++i) {
1846                 if (!node_pred(&dst->node[i], data))
1847                         continue;
1848                 isl_mat_free(dst->node[i].sched);
1849                 isl_map_free(dst->node[i].sched_map);
1850                 dst->node[i].sched = isl_mat_copy(src->node[src->n].sched);
1851                 dst->node[i].sched_map =
1852                         isl_map_copy(src->node[src->n].sched_map);
1853                 src->n++;
1854         }
1855
1856         dst->n_total_row = src->n_total_row;
1857         dst->n_band = src->n_band;
1858
1859         return 0;
1860 }
1861
1862 /* Compute the maximal number of variables over all nodes.
1863  * This is the maximal number of linearly independent schedule
1864  * rows that we need to compute.
1865  * Just in case we end up in a part of the dependence graph
1866  * with only lower-dimensional domains, we make sure we will
1867  * compute the required amount of extra linearly independent rows.
1868  */
1869 static int compute_maxvar(struct isl_sched_graph *graph)
1870 {
1871         int i;
1872
1873         graph->maxvar = 0;
1874         for (i = 0; i < graph->n; ++i) {
1875                 struct isl_sched_node *node = &graph->node[i];
1876                 int nvar;
1877
1878                 if (node_update_cmap(node) < 0)
1879                         return -1;
1880                 nvar = node->nvar + graph->n_row - node->rank;
1881                 if (nvar > graph->maxvar)
1882                         graph->maxvar = nvar;
1883         }
1884
1885         return 0;
1886 }
1887
1888 static int compute_schedule(isl_ctx *ctx, struct isl_sched_graph *graph);
1889 static int compute_schedule_wcc(isl_ctx *ctx, struct isl_sched_graph *graph);
1890
1891 /* Compute a schedule for a subgraph of "graph".  In particular, for
1892  * the graph composed of nodes that satisfy node_pred and edges that
1893  * that satisfy edge_pred.  The caller should precompute the number
1894  * of nodes and edges that satisfy these predicates and pass them along
1895  * as "n" and "n_edge".
1896  * If the subgraph is known to consist of a single component, then wcc should
1897  * be set and then we call compute_schedule_wcc on the constructed subgraph.
1898  * Otherwise, we call compute_schedule, which will check whether the subgraph
1899  * is connected.
1900  */
1901 static int compute_sub_schedule(isl_ctx *ctx,
1902         struct isl_sched_graph *graph, int n, int n_edge,
1903         int (*node_pred)(struct isl_sched_node *node, int data),
1904         int (*edge_pred)(struct isl_sched_edge *edge, int data),
1905         int data, int wcc)
1906 {
1907         struct isl_sched_graph split = { 0 };
1908         int t;
1909
1910         if (graph_alloc(ctx, &split, n, n_edge) < 0)
1911                 goto error;
1912         if (copy_nodes(&split, graph, node_pred, data) < 0)
1913                 goto error;
1914         if (graph_init_table(ctx, &split) < 0)
1915                 goto error;
1916         for (t = 0; t <= isl_edge_last; ++t)
1917                 split.max_edge[t] = graph->max_edge[t];
1918         if (graph_init_edge_tables(ctx, &split) < 0)
1919                 goto error;
1920         if (copy_edges(ctx, &split, graph, edge_pred, data) < 0)
1921                 goto error;
1922         split.n_row = graph->n_row;
1923         split.n_total_row = graph->n_total_row;
1924         split.n_band = graph->n_band;
1925         split.band_start = graph->band_start;
1926
1927         if (wcc && compute_schedule_wcc(ctx, &split) < 0)
1928                 goto error;
1929         if (!wcc && compute_schedule(ctx, &split) < 0)
1930                 goto error;
1931
1932         copy_schedule(graph, &split, node_pred, data);
1933
1934         graph_free(ctx, &split);
1935         return 0;
1936 error:
1937         graph_free(ctx, &split);
1938         return -1;
1939 }
1940
1941 static int node_scc_exactly(struct isl_sched_node *node, int scc)
1942 {
1943         return node->scc == scc;
1944 }
1945
1946 static int node_scc_at_most(struct isl_sched_node *node, int scc)
1947 {
1948         return node->scc <= scc;
1949 }
1950
1951 static int node_scc_at_least(struct isl_sched_node *node, int scc)
1952 {
1953         return node->scc >= scc;
1954 }
1955
1956 static int edge_scc_exactly(struct isl_sched_edge *edge, int scc)
1957 {
1958         return edge->src->scc == scc && edge->dst->scc == scc;
1959 }
1960
1961 static int edge_dst_scc_at_most(struct isl_sched_edge *edge, int scc)
1962 {
1963         return edge->dst->scc <= scc;
1964 }
1965
1966 static int edge_src_scc_at_least(struct isl_sched_edge *edge, int scc)
1967 {
1968         return edge->src->scc >= scc;
1969 }
1970
1971 /* Pad the schedules of all nodes with zero rows such that in the end
1972  * they all have graph->n_total_row rows.
1973  * The extra rows don't belong to any band, so they get assigned band number -1.
1974  */
1975 static int pad_schedule(struct isl_sched_graph *graph)
1976 {
1977         int i, j;
1978
1979         for (i = 0; i < graph->n; ++i) {
1980                 struct isl_sched_node *node = &graph->node[i];
1981                 int row = isl_mat_rows(node->sched);
1982                 if (graph->n_total_row > row) {
1983                         isl_map_free(node->sched_map);
1984                         node->sched_map = NULL;
1985                 }
1986                 node->sched = isl_mat_add_zero_rows(node->sched,
1987                                                     graph->n_total_row - row);
1988                 if (!node->sched)
1989                         return -1;
1990                 for (j = row; j < graph->n_total_row; ++j)
1991                         node->band[j] = -1;
1992         }
1993
1994         return 0;
1995 }
1996
1997 /* Split the current graph into two parts and compute a schedule for each
1998  * part individually.  In particular, one part consists of all SCCs up
1999  * to and including graph->src_scc, while the other part contains the other
2000  * SCCS.
2001  *
2002  * The split is enforced in the schedule by constant rows with two different
2003  * values (0 and 1).  These constant rows replace the previously computed rows
2004  * in the current band.
2005  * It would be possible to reuse them as the first rows in the next
2006  * band, but recomputing them may result in better rows as we are looking
2007  * at a smaller part of the dependence graph.
2008  * compute_split_schedule is only called when no zero-distance schedule row
2009  * could be found on the entire graph, so we wark the splitting row as
2010  * non zero-distance.
2011  *
2012  * The band_id of the second group is set to n, where n is the number
2013  * of nodes in the first group.  This ensures that the band_ids over
2014  * the two groups remain disjoint, even if either or both of the two
2015  * groups contain independent components.
2016  */
2017 static int compute_split_schedule(isl_ctx *ctx, struct isl_sched_graph *graph)
2018 {
2019         int i, j, n, e1, e2;
2020         int n_total_row, orig_total_row;
2021         int n_band, orig_band;
2022         int drop;
2023
2024         drop = graph->n_total_row - graph->band_start;
2025         graph->n_total_row -= drop;
2026         graph->n_row -= drop;
2027
2028         n = 0;
2029         for (i = 0; i < graph->n; ++i) {
2030                 struct isl_sched_node *node = &graph->node[i];
2031                 int row = isl_mat_rows(node->sched) - drop;
2032                 int cols = isl_mat_cols(node->sched);
2033                 int before = node->scc <= graph->src_scc;
2034
2035                 if (before)
2036                         n++;
2037
2038                 isl_map_free(node->sched_map);
2039                 node->sched_map = NULL;
2040                 node->sched = isl_mat_drop_rows(node->sched,
2041                                                 graph->band_start, drop);
2042                 node->sched = isl_mat_add_rows(node->sched, 1);
2043                 if (!node->sched)
2044                         return -1;
2045                 node->sched = isl_mat_set_element_si(node->sched, row, 0,
2046                                                      !before);
2047                 for (j = 1; j < cols; ++j)
2048                         node->sched = isl_mat_set_element_si(node->sched,
2049                                                              row, j, 0);
2050                 node->band[graph->n_total_row] = graph->n_band;
2051                 node->zero[graph->n_total_row] = 0;
2052         }
2053
2054         e1 = e2 = 0;
2055         for (i = 0; i < graph->n_edge; ++i) {
2056                 if (graph->edge[i].dst->scc <= graph->src_scc)
2057                         e1++;
2058                 if (graph->edge[i].src->scc > graph->src_scc)
2059                         e2++;
2060         }
2061
2062         graph->n_total_row++;
2063         next_band(graph);
2064
2065         for (i = 0; i < graph->n; ++i) {
2066                 struct isl_sched_node *node = &graph->node[i];
2067                 if (node->scc > graph->src_scc)
2068                         node->band_id[graph->n_band] = n;
2069         }
2070
2071         orig_total_row = graph->n_total_row;
2072         orig_band = graph->n_band;
2073         if (compute_sub_schedule(ctx, graph, n, e1,
2074                                 &node_scc_at_most, &edge_dst_scc_at_most,
2075                                 graph->src_scc, 0) < 0)
2076                 return -1;
2077         n_total_row = graph->n_total_row;
2078         graph->n_total_row = orig_total_row;
2079         n_band = graph->n_band;
2080         graph->n_band = orig_band;
2081         if (compute_sub_schedule(ctx, graph, graph->n - n, e2,
2082                                 &node_scc_at_least, &edge_src_scc_at_least,
2083                                 graph->src_scc + 1, 0) < 0)
2084                 return -1;
2085         if (n_total_row > graph->n_total_row)
2086                 graph->n_total_row = n_total_row;
2087         if (n_band > graph->n_band)
2088                 graph->n_band = n_band;
2089
2090         return pad_schedule(graph);
2091 }
2092
2093 /* Compute the next band of the schedule after updating the dependence
2094  * relations based on the the current schedule.
2095  */
2096 static int compute_next_band(isl_ctx *ctx, struct isl_sched_graph *graph)
2097 {
2098         if (update_edges(ctx, graph) < 0)
2099                 return -1;
2100         next_band(graph);
2101                 
2102         return compute_schedule(ctx, graph);
2103 }
2104
2105 /* Add constraints to graph->lp that force the dependence "map" (which
2106  * is part of the dependence relation of "edge")
2107  * to be respected and attempt to carry it, where the edge is one from
2108  * a node j to itself.  "pos" is the sequence number of the given map.
2109  * That is, add constraints that enforce
2110  *
2111  *      (c_j_0 + c_j_n n + c_j_x y) - (c_j_0 + c_j_n n + c_j_x x)
2112  *      = c_j_x (y - x) >= e_i
2113  *
2114  * for each (x,y) in R.
2115  * We obtain general constraints on coefficients (c_0, c_n, c_x)
2116  * of valid constraints for (y - x) and then plug in (-e_i, 0, c_j_x),
2117  * with each coefficient in c_j_x represented as a pair of non-negative
2118  * coefficients.
2119  */
2120 static int add_intra_constraints(struct isl_sched_graph *graph,
2121         struct isl_sched_edge *edge, __isl_take isl_map *map, int pos)
2122 {
2123         unsigned total;
2124         isl_ctx *ctx = isl_map_get_ctx(map);
2125         isl_space *dim;
2126         isl_dim_map *dim_map;
2127         isl_basic_set *coef;
2128         struct isl_sched_node *node = edge->src;
2129
2130         coef = intra_coefficients(graph, map);
2131
2132         dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
2133
2134         total = isl_basic_set_total_dim(graph->lp);
2135         dim_map = isl_dim_map_alloc(ctx, total);
2136         isl_dim_map_range(dim_map, 3 + pos, 0, 0, 0, 1, -1);
2137         isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 1, 2,
2138                           isl_space_dim(dim, isl_dim_set), 1,
2139                           node->nvar, -1);
2140         isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 2, 2,
2141                           isl_space_dim(dim, isl_dim_set), 1,
2142                           node->nvar, 1);
2143         graph->lp = isl_basic_set_extend_constraints(graph->lp,
2144                         coef->n_eq, coef->n_ineq);
2145         graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
2146                                                            coef, dim_map);
2147         isl_space_free(dim);
2148
2149         return 0;
2150 }
2151
2152 /* Add constraints to graph->lp that force the dependence "map" (which
2153  * is part of the dependence relation of "edge")
2154  * to be respected and attempt to carry it, where the edge is one from
2155  * node j to node k.  "pos" is the sequence number of the given map.
2156  * That is, add constraints that enforce
2157  *
2158  *      (c_k_0 + c_k_n n + c_k_x y) - (c_j_0 + c_j_n n + c_j_x x) >= e_i
2159  *
2160  * for each (x,y) in R.
2161  * We obtain general constraints on coefficients (c_0, c_n, c_x)
2162  * of valid constraints for R and then plug in
2163  * (-e_i + c_k_0 - c_j_0, c_k_n - c_j_n, c_k_x - c_j_x)
2164  * with each coefficient (except e_i, c_k_0 and c_j_0)
2165  * represented as a pair of non-negative coefficients.
2166  */
2167 static int add_inter_constraints(struct isl_sched_graph *graph,
2168         struct isl_sched_edge *edge, __isl_take isl_map *map, int pos)
2169 {
2170         unsigned total;
2171         isl_ctx *ctx = isl_map_get_ctx(map);
2172         isl_space *dim;
2173         isl_dim_map *dim_map;
2174         isl_basic_set *coef;
2175         struct isl_sched_node *src = edge->src;
2176         struct isl_sched_node *dst = edge->dst;
2177
2178         coef = inter_coefficients(graph, map);
2179
2180         dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
2181
2182         total = isl_basic_set_total_dim(graph->lp);
2183         dim_map = isl_dim_map_alloc(ctx, total);
2184
2185         isl_dim_map_range(dim_map, 3 + pos, 0, 0, 0, 1, -1);
2186
2187         isl_dim_map_range(dim_map, dst->start, 0, 0, 0, 1, 1);
2188         isl_dim_map_range(dim_map, dst->start + 1, 2, 1, 1, dst->nparam, -1);
2189         isl_dim_map_range(dim_map, dst->start + 2, 2, 1, 1, dst->nparam, 1);
2190         isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 1, 2,
2191                           isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
2192                           dst->nvar, -1);
2193         isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 2, 2,
2194                           isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
2195                           dst->nvar, 1);
2196
2197         isl_dim_map_range(dim_map, src->start, 0, 0, 0, 1, -1);
2198         isl_dim_map_range(dim_map, src->start + 1, 2, 1, 1, src->nparam, 1);
2199         isl_dim_map_range(dim_map, src->start + 2, 2, 1, 1, src->nparam, -1);
2200         isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 1, 2,
2201                           isl_space_dim(dim, isl_dim_set), 1,
2202                           src->nvar, 1);
2203         isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 2, 2,
2204                           isl_space_dim(dim, isl_dim_set), 1,
2205                           src->nvar, -1);
2206
2207         graph->lp = isl_basic_set_extend_constraints(graph->lp,
2208                         coef->n_eq, coef->n_ineq);
2209         graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
2210                                                            coef, dim_map);
2211         isl_space_free(dim);
2212
2213         return 0;
2214 }
2215
2216 /* Add constraints to graph->lp that force all validity dependences
2217  * to be respected and attempt to carry them.
2218  */
2219 static int add_all_constraints(struct isl_sched_graph *graph)
2220 {
2221         int i, j;
2222         int pos;
2223
2224         pos = 0;
2225         for (i = 0; i < graph->n_edge; ++i) {
2226                 struct isl_sched_edge *edge= &graph->edge[i];
2227
2228                 if (!edge->validity)
2229                         continue;
2230
2231                 for (j = 0; j < edge->map->n; ++j) {
2232                         isl_basic_map *bmap;
2233                         isl_map *map;
2234
2235                         bmap = isl_basic_map_copy(edge->map->p[j]);
2236                         map = isl_map_from_basic_map(bmap);
2237
2238                         if (edge->src == edge->dst &&
2239                             add_intra_constraints(graph, edge, map, pos) < 0)
2240                                 return -1;
2241                         if (edge->src != edge->dst &&
2242                             add_inter_constraints(graph, edge, map, pos) < 0)
2243                                 return -1;
2244                         ++pos;
2245                 }
2246         }
2247
2248         return 0;
2249 }
2250
2251 /* Count the number of equality and inequality constraints
2252  * that will be added to the carry_lp problem.
2253  * We count each edge exactly once.
2254  */
2255 static int count_all_constraints(struct isl_sched_graph *graph,
2256         int *n_eq, int *n_ineq)
2257 {
2258         int i, j;
2259
2260         *n_eq = *n_ineq = 0;
2261         for (i = 0; i < graph->n_edge; ++i) {
2262                 struct isl_sched_edge *edge= &graph->edge[i];
2263                 for (j = 0; j < edge->map->n; ++j) {
2264                         isl_basic_map *bmap;
2265                         isl_map *map;
2266
2267                         bmap = isl_basic_map_copy(edge->map->p[j]);
2268                         map = isl_map_from_basic_map(bmap);
2269
2270                         if (count_map_constraints(graph, edge, map,
2271                                                   n_eq, n_ineq, 1) < 0)
2272                                     return -1;
2273                 }
2274         }
2275
2276         return 0;
2277 }
2278
2279 /* Construct an LP problem for finding schedule coefficients
2280  * such that the schedule carries as many dependences as possible.
2281  * In particular, for each dependence i, we bound the dependence distance
2282  * from below by e_i, with 0 <= e_i <= 1 and then maximize the sum
2283  * of all e_i's.  Dependence with e_i = 0 in the solution are simply
2284  * respected, while those with e_i > 0 (in practice e_i = 1) are carried.
2285  * Note that if the dependence relation is a union of basic maps,
2286  * then we have to consider each basic map individually as it may only
2287  * be possible to carry the dependences expressed by some of those
2288  * basic maps and not all off them.
2289  * Below, we consider each of those basic maps as a separate "edge".
2290  *
2291  * All variables of the LP are non-negative.  The actual coefficients
2292  * may be negative, so each coefficient is represented as the difference
2293  * of two non-negative variables.  The negative part always appears
2294  * immediately before the positive part.
2295  * Other than that, the variables have the following order
2296  *
2297  *      - sum of (1 - e_i) over all edges
2298  *      - sum of positive and negative parts of all c_n coefficients
2299  *              (unconstrained when computing non-parametric schedules)
2300  *      - sum of positive and negative parts of all c_x coefficients
2301  *      - for each edge
2302  *              - e_i
2303  *      - for each node
2304  *              - c_i_0
2305  *              - positive and negative parts of c_i_n (if parametric)
2306  *              - positive and negative parts of c_i_x
2307  *
2308  * The constraints are those from the (validity) edges plus three equalities
2309  * to express the sums and n_edge inequalities to express e_i <= 1.
2310  */
2311 static int setup_carry_lp(isl_ctx *ctx, struct isl_sched_graph *graph)
2312 {
2313         int i, j;
2314         int k;
2315         isl_space *dim;
2316         unsigned total;
2317         int n_eq, n_ineq;
2318         int n_edge;
2319
2320         n_edge = 0;
2321         for (i = 0; i < graph->n_edge; ++i)
2322                 n_edge += graph->edge[i].map->n;
2323
2324         total = 3 + n_edge;
2325         for (i = 0; i < graph->n; ++i) {
2326                 struct isl_sched_node *node = &graph->node[graph->sorted[i]];
2327                 node->start = total;
2328                 total += 1 + 2 * (node->nparam + node->nvar);
2329         }
2330
2331         if (count_all_constraints(graph, &n_eq, &n_ineq) < 0)
2332                 return -1;
2333
2334         dim = isl_space_set_alloc(ctx, 0, total);
2335         isl_basic_set_free(graph->lp);
2336         n_eq += 3;
2337         n_ineq += n_edge;
2338         graph->lp = isl_basic_set_alloc_space(dim, 0, n_eq, n_ineq);
2339         graph->lp = isl_basic_set_set_rational(graph->lp);
2340
2341         k = isl_basic_set_alloc_equality(graph->lp);
2342         if (k < 0)
2343                 return -1;
2344         isl_seq_clr(graph->lp->eq[k], 1 +  total);
2345         isl_int_set_si(graph->lp->eq[k][0], -n_edge);
2346         isl_int_set_si(graph->lp->eq[k][1], 1);
2347         for (i = 0; i < n_edge; ++i)
2348                 isl_int_set_si(graph->lp->eq[k][4 + i], 1);
2349
2350         k = isl_basic_set_alloc_equality(graph->lp);
2351         if (k < 0)
2352                 return -1;
2353         isl_seq_clr(graph->lp->eq[k], 1 +  total);
2354         isl_int_set_si(graph->lp->eq[k][2], -1);
2355         for (i = 0; i < graph->n; ++i) {
2356                 int pos = 1 + graph->node[i].start + 1;
2357
2358                 for (j = 0; j < 2 * graph->node[i].nparam; ++j)
2359                         isl_int_set_si(graph->lp->eq[k][pos + j], 1);
2360         }
2361
2362         k = isl_basic_set_alloc_equality(graph->lp);
2363         if (k < 0)
2364                 return -1;
2365         isl_seq_clr(graph->lp->eq[k], 1 +  total);
2366         isl_int_set_si(graph->lp->eq[k][3], -1);
2367         for (i = 0; i < graph->n; ++i) {
2368                 struct isl_sched_node *node = &graph->node[i];
2369                 int pos = 1 + node->start + 1 + 2 * node->nparam;
2370
2371                 for (j = 0; j < 2 * node->nvar; ++j)
2372                         isl_int_set_si(graph->lp->eq[k][pos + j], 1);
2373         }
2374
2375         for (i = 0; i < n_edge; ++i) {
2376                 k = isl_basic_set_alloc_inequality(graph->lp);
2377                 if (k < 0)
2378                         return -1;
2379                 isl_seq_clr(graph->lp->ineq[k], 1 +  total);
2380                 isl_int_set_si(graph->lp->ineq[k][4 + i], -1);
2381                 isl_int_set_si(graph->lp->ineq[k][0], 1);
2382         }
2383
2384         if (add_all_constraints(graph) < 0)
2385                 return -1;
2386
2387         return 0;
2388 }
2389
2390 /* If the schedule_split_scaled option is set and if the linear
2391  * parts of the scheduling rows for all nodes in the graphs have
2392  * non-trivial common divisor, then split off the constant term
2393  * from the linear part.
2394  * The constant term is then placed in a separate band and
2395  * the linear part is reduced.
2396  */
2397 static int split_scaled(isl_ctx *ctx, struct isl_sched_graph *graph)
2398 {
2399         int i;
2400         int row;
2401         isl_int gcd, gcd_i;
2402
2403         if (!ctx->opt->schedule_split_scaled)
2404                 return 0;
2405         if (graph->n <= 1)
2406                 return 0;
2407
2408         isl_int_init(gcd);
2409         isl_int_init(gcd_i);
2410
2411         isl_int_set_si(gcd, 0);
2412
2413         row = isl_mat_rows(graph->node[0].sched) - 1;
2414
2415         for (i = 0; i < graph->n; ++i) {
2416                 struct isl_sched_node *node = &graph->node[i];
2417                 int cols = isl_mat_cols(node->sched);
2418
2419                 isl_seq_gcd(node->sched->row[row] + 1, cols - 1, &gcd_i);
2420                 isl_int_gcd(gcd, gcd, gcd_i);
2421         }
2422
2423         isl_int_clear(gcd_i);
2424
2425         if (isl_int_cmp_si(gcd, 1) <= 0) {
2426                 isl_int_clear(gcd);
2427                 return 0;
2428         }
2429
2430         next_band(graph);
2431
2432         for (i = 0; i < graph->n; ++i) {
2433                 struct isl_sched_node *node = &graph->node[i];
2434
2435                 isl_map_free(node->sched_map);
2436                 node->sched_map = NULL;
2437                 node->sched = isl_mat_add_zero_rows(node->sched, 1);
2438                 if (!node->sched)
2439                         goto error;
2440                 isl_int_fdiv_r(node->sched->row[row + 1][0],
2441                                node->sched->row[row][0], gcd);
2442                 isl_int_fdiv_q(node->sched->row[row][0],
2443                                node->sched->row[row][0], gcd);
2444                 isl_int_mul(node->sched->row[row][0],
2445                             node->sched->row[row][0], gcd);
2446                 node->sched = isl_mat_scale_down_row(node->sched, row, gcd);
2447                 if (!node->sched)
2448                         goto error;
2449                 node->band[graph->n_total_row] = graph->n_band;
2450         }
2451
2452         graph->n_total_row++;
2453
2454         isl_int_clear(gcd);
2455         return 0;
2456 error:
2457         isl_int_clear(gcd);
2458         return -1;
2459 }
2460
2461 /* Construct a schedule row for each node such that as many dependences
2462  * as possible are carried and then continue with the next band.
2463  */
2464 static int carry_dependences(isl_ctx *ctx, struct isl_sched_graph *graph)
2465 {
2466         int i;
2467         int n_edge;
2468         isl_vec *sol;
2469         isl_basic_set *lp;
2470
2471         n_edge = 0;
2472         for (i = 0; i < graph->n_edge; ++i)
2473                 n_edge += graph->edge[i].map->n;
2474
2475         if (setup_carry_lp(ctx, graph) < 0)
2476                 return -1;
2477
2478         lp = isl_basic_set_copy(graph->lp);
2479         sol = isl_tab_basic_set_non_neg_lexmin(lp);
2480         if (!sol)
2481                 return -1;
2482
2483         if (sol->size == 0) {
2484                 isl_vec_free(sol);
2485                 isl_die(ctx, isl_error_internal,
2486                         "error in schedule construction", return -1);
2487         }
2488
2489         if (isl_int_cmp_si(sol->el[1], n_edge) >= 0) {
2490                 isl_vec_free(sol);
2491                 isl_die(ctx, isl_error_unknown,
2492                         "unable to carry dependences", return -1);
2493         }
2494
2495         if (update_schedule(graph, sol, 0, 0) < 0)
2496                 return -1;
2497
2498         if (split_scaled(ctx, graph) < 0)
2499                 return -1;
2500
2501         return compute_next_band(ctx, graph);
2502 }
2503
2504 /* Are there any (non-empty) validity edges in the graph?
2505  */
2506 static int has_validity_edges(struct isl_sched_graph *graph)
2507 {
2508         int i;
2509
2510         for (i = 0; i < graph->n_edge; ++i) {
2511                 int empty;
2512
2513                 empty = isl_map_plain_is_empty(graph->edge[i].map);
2514                 if (empty < 0)
2515                         return -1;
2516                 if (empty)
2517                         continue;
2518                 if (graph->edge[i].validity)
2519                         return 1;
2520         }
2521
2522         return 0;
2523 }
2524
2525 /* Should we apply a Feautrier step?
2526  * That is, did the user request the Feautrier algorithm and are
2527  * there any validity dependences (left)?
2528  */
2529 static int need_feautrier_step(isl_ctx *ctx, struct isl_sched_graph *graph)
2530 {
2531         if (ctx->opt->schedule_algorithm != ISL_SCHEDULE_ALGORITHM_FEAUTRIER)
2532                 return 0;
2533
2534         return has_validity_edges(graph);
2535 }
2536
2537 /* Compute a schedule for a connected dependence graph using Feautrier's
2538  * multi-dimensional scheduling algorithm.
2539  * The original algorithm is described in [1].
2540  * The main idea is to minimize the number of scheduling dimensions, by
2541  * trying to satisfy as many dependences as possible per scheduling dimension.
2542  *
2543  * [1] P. Feautrier, Some Efficient Solutions to the Affine Scheduling
2544  *     Problem, Part II: Multi-Dimensional Time.
2545  *     In Intl. Journal of Parallel Programming, 1992.
2546  */
2547 static int compute_schedule_wcc_feautrier(isl_ctx *ctx,
2548         struct isl_sched_graph *graph)
2549 {
2550         return carry_dependences(ctx, graph);
2551 }
2552
2553 /* Compute a schedule for a connected dependence graph.
2554  * We try to find a sequence of as many schedule rows as possible that result
2555  * in non-negative dependence distances (independent of the previous rows
2556  * in the sequence, i.e., such that the sequence is tilable).
2557  * If we can't find any more rows we either
2558  * - split between SCCs and start over (assuming we found an interesting
2559  *      pair of SCCs between which to split)
2560  * - continue with the next band (assuming the current band has at least
2561  *      one row)
2562  * - try to carry as many dependences as possible and continue with the next
2563  *      band
2564  *
2565  * If Feautrier's algorithm is selected, we first recursively try to satisfy
2566  * as many validity dependences as possible. When all validity dependences
2567  * are satisfied we extend the schedule to a full-dimensional schedule.
2568  *
2569  * If we manage to complete the schedule, we finish off by topologically
2570  * sorting the statements based on the remaining dependences.
2571  *
2572  * If ctx->opt->schedule_outer_zero_distance is set, then we force the
2573  * outermost dimension in the current band to be zero distance.  If this
2574  * turns out to be impossible, we fall back on the general scheme above
2575  * and try to carry as many dependences as possible.
2576  */
2577 static int compute_schedule_wcc(isl_ctx *ctx, struct isl_sched_graph *graph)
2578 {
2579         int force_zero = 0;
2580
2581         if (detect_sccs(graph) < 0)
2582                 return -1;
2583         sort_sccs(graph);
2584
2585         if (compute_maxvar(graph) < 0)
2586                 return -1;
2587
2588         if (need_feautrier_step(ctx, graph))
2589                 return compute_schedule_wcc_feautrier(ctx, graph);
2590
2591         if (ctx->opt->schedule_outer_zero_distance)
2592                 force_zero = 1;
2593
2594         while (graph->n_row < graph->maxvar) {
2595                 isl_vec *sol;
2596
2597                 graph->src_scc = -1;
2598                 graph->dst_scc = -1;
2599
2600                 if (setup_lp(ctx, graph, force_zero) < 0)
2601                         return -1;
2602                 sol = solve_lp(graph);
2603                 if (!sol)
2604                         return -1;
2605                 if (sol->size == 0) {
2606                         isl_vec_free(sol);
2607                         if (!ctx->opt->schedule_maximize_band_depth &&
2608                             graph->n_total_row > graph->band_start)
2609                                 return compute_next_band(ctx, graph);
2610                         if (graph->src_scc >= 0)
2611                                 return compute_split_schedule(ctx, graph);
2612                         if (graph->n_total_row > graph->band_start)
2613                                 return compute_next_band(ctx, graph);
2614                         return carry_dependences(ctx, graph);
2615                 }
2616                 if (update_schedule(graph, sol, 1, 1) < 0)
2617                         return -1;
2618                 force_zero = 0;
2619         }
2620
2621         if (graph->n_total_row > graph->band_start)
2622                 next_band(graph);
2623         return sort_statements(ctx, graph);
2624 }
2625
2626 /* Add a row to the schedules that separates the SCCs and move
2627  * to the next band.
2628  */
2629 static int split_on_scc(struct isl_sched_graph *graph)
2630 {
2631         int i;
2632
2633         for (i = 0; i < graph->n; ++i) {
2634                 struct isl_sched_node *node = &graph->node[i];
2635                 int row = isl_mat_rows(node->sched);
2636
2637                 isl_map_free(node->sched_map);
2638                 node->sched_map = NULL;
2639                 node->sched = isl_mat_add_zero_rows(node->sched, 1);
2640                 node->sched = isl_mat_set_element_si(node->sched, row, 0,
2641                                                      node->scc);
2642                 if (!node->sched)
2643                         return -1;
2644                 node->band[graph->n_total_row] = graph->n_band;
2645         }
2646
2647         graph->n_total_row++;
2648         next_band(graph);
2649
2650         return 0;
2651 }
2652
2653 /* Compute a schedule for each component (identified by node->scc)
2654  * of the dependence graph separately and then combine the results.
2655  * Depending on the setting of schedule_fuse, a component may be
2656  * either weakly or strongly connected.
2657  *
2658  * The band_id is adjusted such that each component has a separate id.
2659  * Note that the band_id may have already been set to a value different
2660  * from zero by compute_split_schedule.
2661  */
2662 static int compute_component_schedule(isl_ctx *ctx,
2663         struct isl_sched_graph *graph)
2664 {
2665         int wcc, i;
2666         int n, n_edge;
2667         int n_total_row, orig_total_row;
2668         int n_band, orig_band;
2669
2670         if (ctx->opt->schedule_fuse == ISL_SCHEDULE_FUSE_MIN)
2671                 split_on_scc(graph);
2672
2673         n_total_row = 0;
2674         orig_total_row = graph->n_total_row;
2675         n_band = 0;
2676         orig_band = graph->n_band;
2677         for (i = 0; i < graph->n; ++i)
2678                 graph->node[i].band_id[graph->n_band] += graph->node[i].scc;
2679         for (wcc = 0; wcc < graph->scc; ++wcc) {
2680                 n = 0;
2681                 for (i = 0; i < graph->n; ++i)
2682                         if (graph->node[i].scc == wcc)
2683                                 n++;
2684                 n_edge = 0;
2685                 for (i = 0; i < graph->n_edge; ++i)
2686                         if (graph->edge[i].src->scc == wcc &&
2687                             graph->edge[i].dst->scc == wcc)
2688                                 n_edge++;
2689
2690                 if (compute_sub_schedule(ctx, graph, n, n_edge,
2691                                     &node_scc_exactly,
2692                                     &edge_scc_exactly, wcc, 1) < 0)
2693                         return -1;
2694                 if (graph->n_total_row > n_total_row)
2695                         n_total_row = graph->n_total_row;
2696                 graph->n_total_row = orig_total_row;
2697                 if (graph->n_band > n_band)
2698                         n_band = graph->n_band;
2699                 graph->n_band = orig_band;
2700         }
2701
2702         graph->n_total_row = n_total_row;
2703         graph->n_band = n_band;
2704
2705         return pad_schedule(graph);
2706 }
2707
2708 /* Compute a schedule for the given dependence graph.
2709  * We first check if the graph is connected (through validity dependences)
2710  * and, if not, compute a schedule for each component separately.
2711  * If schedule_fuse is set to minimal fusion, then we check for strongly
2712  * connected components instead and compute a separate schedule for
2713  * each such strongly connected component.
2714  */
2715 static int compute_schedule(isl_ctx *ctx, struct isl_sched_graph *graph)
2716 {
2717         if (ctx->opt->schedule_fuse == ISL_SCHEDULE_FUSE_MIN) {
2718                 if (detect_sccs(graph) < 0)
2719                         return -1;
2720         } else {
2721                 if (detect_wccs(graph) < 0)
2722                         return -1;
2723         }
2724
2725         if (graph->scc > 1)
2726                 return compute_component_schedule(ctx, graph);
2727
2728         return compute_schedule_wcc(ctx, graph);
2729 }
2730
2731 /* Compute a schedule for the given union of domains that respects
2732  * all the validity dependences.
2733  * If the default isl scheduling algorithm is used, it tries to minimize
2734  * the dependence distances over the proximity dependences.
2735  * If Feautrier's scheduling algorithm is used, the proximity dependence
2736  * distances are only minimized during the extension to a full-dimensional
2737  * schedule.
2738  */
2739 __isl_give isl_schedule *isl_union_set_compute_schedule(
2740         __isl_take isl_union_set *domain,
2741         __isl_take isl_union_map *validity,
2742         __isl_take isl_union_map *proximity)
2743 {
2744         isl_ctx *ctx = isl_union_set_get_ctx(domain);
2745         isl_space *dim;
2746         struct isl_sched_graph graph = { 0 };
2747         isl_schedule *sched;
2748         struct isl_extract_edge_data data;
2749
2750         domain = isl_union_set_align_params(domain,
2751                                             isl_union_map_get_space(validity));
2752         domain = isl_union_set_align_params(domain,
2753                                             isl_union_map_get_space(proximity));
2754         dim = isl_union_set_get_space(domain);
2755         validity = isl_union_map_align_params(validity, isl_space_copy(dim));
2756         proximity = isl_union_map_align_params(proximity, dim);
2757
2758         if (!domain)
2759                 goto error;
2760
2761         graph.n = isl_union_set_n_set(domain);
2762         if (graph.n == 0)
2763                 goto empty;
2764         if (graph_alloc(ctx, &graph, graph.n,
2765             isl_union_map_n_map(validity) + isl_union_map_n_map(proximity)) < 0)
2766                 goto error;
2767         graph.root = 1;
2768         graph.n = 0;
2769         if (isl_union_set_foreach_set(domain, &extract_node, &graph) < 0)
2770                 goto error;
2771         if (graph_init_table(ctx, &graph) < 0)
2772                 goto error;
2773         graph.max_edge[isl_edge_validity] = isl_union_map_n_map(validity);
2774         graph.max_edge[isl_edge_proximity] = isl_union_map_n_map(proximity);
2775         if (graph_init_edge_tables(ctx, &graph) < 0)
2776                 goto error;
2777         graph.n_edge = 0;
2778         data.graph = &graph;
2779         data.type = isl_edge_validity;
2780         if (isl_union_map_foreach_map(validity, &extract_edge, &data) < 0)
2781                 goto error;
2782         data.type = isl_edge_proximity;
2783         if (isl_union_map_foreach_map(proximity, &extract_edge, &data) < 0)
2784                 goto error;
2785
2786         if (compute_schedule(ctx, &graph) < 0)
2787                 goto error;
2788
2789 empty:
2790         sched = extract_schedule(&graph, isl_union_set_get_space(domain));
2791
2792         graph_free(ctx, &graph);
2793         isl_union_set_free(domain);
2794         isl_union_map_free(validity);
2795         isl_union_map_free(proximity);
2796
2797         return sched;
2798 error:
2799         graph_free(ctx, &graph);
2800         isl_union_set_free(domain);
2801         isl_union_map_free(validity);
2802         isl_union_map_free(proximity);
2803         return NULL;
2804 }
2805
2806 void *isl_schedule_free(__isl_take isl_schedule *sched)
2807 {
2808         int i;
2809         if (!sched)
2810                 return NULL;
2811
2812         if (--sched->ref > 0)
2813                 return NULL;
2814
2815         for (i = 0; i < sched->n; ++i) {
2816                 isl_map_free(sched->node[i].sched);
2817                 free(sched->node[i].band_end);
2818                 free(sched->node[i].band_id);
2819                 free(sched->node[i].zero);
2820         }
2821         isl_space_free(sched->dim);
2822         isl_band_list_free(sched->band_forest);
2823         free(sched);
2824         return NULL;
2825 }
2826
2827 isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *schedule)
2828 {
2829         return schedule ? isl_space_get_ctx(schedule->dim) : NULL;
2830 }
2831
2832 __isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched)
2833 {
2834         int i;
2835         isl_union_map *umap;
2836
2837         if (!sched)
2838                 return NULL;
2839
2840         umap = isl_union_map_empty(isl_space_copy(sched->dim));
2841         for (i = 0; i < sched->n; ++i)
2842                 umap = isl_union_map_add_map(umap,
2843                                             isl_map_copy(sched->node[i].sched));
2844
2845         return umap;
2846 }
2847
2848 static __isl_give isl_band_list *construct_band_list(
2849         __isl_keep isl_schedule *schedule, __isl_keep isl_band *parent,
2850         int band_nr, int *parent_active, int n_active);
2851
2852 /* Construct an isl_band structure for the band in the given schedule
2853  * with sequence number band_nr for the n_active nodes marked by active.
2854  * If the nodes don't have a band with the given sequence number,
2855  * then a band without members is created.
2856  *
2857  * Because of the way the schedule is constructed, we know that
2858  * the position of the band inside the schedule of a node is the same
2859  * for all active nodes.
2860  */
2861 static __isl_give isl_band *construct_band(__isl_keep isl_schedule *schedule,
2862         __isl_keep isl_band *parent,
2863         int band_nr, int *active, int n_active)
2864 {
2865         int i, j;
2866         isl_ctx *ctx = isl_schedule_get_ctx(schedule);
2867         isl_band *band;
2868         unsigned start, end;
2869
2870         band = isl_calloc_type(ctx, isl_band);
2871         if (!band)
2872                 return NULL;
2873
2874         band->ref = 1;
2875         band->schedule = schedule;
2876         band->parent = parent;
2877
2878         for (i = 0; i < schedule->n; ++i)
2879                 if (active[i] && schedule->node[i].n_band > band_nr + 1)
2880                         break;
2881
2882         if (i < schedule->n) {
2883                 band->children = construct_band_list(schedule, band,
2884                                                 band_nr + 1, active, n_active);
2885                 if (!band->children)
2886                         goto error;
2887         }
2888
2889         for (i = 0; i < schedule->n; ++i)
2890                 if (active[i])
2891                         break;
2892
2893         if (i >= schedule->n)
2894                 isl_die(ctx, isl_error_internal,
2895                         "band without active statements", goto error);
2896
2897         start = band_nr ? schedule->node[i].band_end[band_nr - 1] : 0;
2898         end = band_nr < schedule->node[i].n_band ?
2899                 schedule->node[i].band_end[band_nr] : start;
2900         band->n = end - start;
2901
2902         band->zero = isl_alloc_array(ctx, int, band->n);
2903         if (!band->zero)
2904                 goto error;
2905
2906         for (j = 0; j < band->n; ++j)
2907                 band->zero[j] = schedule->node[i].zero[start + j];
2908
2909         band->map = isl_union_map_empty(isl_space_copy(schedule->dim));
2910         for (i = 0; i < schedule->n; ++i) {
2911                 isl_map *map;
2912                 unsigned n_out;
2913
2914                 if (!active[i])
2915                         continue;
2916
2917                 map = isl_map_copy(schedule->node[i].sched);
2918                 n_out = isl_map_dim(map, isl_dim_out);
2919                 map = isl_map_project_out(map, isl_dim_out, end, n_out - end);
2920                 map = isl_map_project_out(map, isl_dim_out, 0, start);
2921                 band->map = isl_union_map_union(band->map,
2922                                                 isl_union_map_from_map(map));
2923         }
2924         if (!band->map)
2925                 goto error;
2926
2927         return band;
2928 error:
2929         isl_band_free(band);
2930         return NULL;
2931 }
2932
2933 /* Construct a list of bands that start at the same position (with
2934  * sequence number band_nr) in the schedules of the nodes that
2935  * were active in the parent band.
2936  *
2937  * A separate isl_band structure is created for each band_id
2938  * and for each node that does not have a band with sequence
2939  * number band_nr.  In the latter case, a band without members
2940  * is created.
2941  * This ensures that if a band has any children, then each node
2942  * that was active in the band is active in exactly one of the children.
2943  */
2944 static __isl_give isl_band_list *construct_band_list(
2945         __isl_keep isl_schedule *schedule, __isl_keep isl_band *parent,
2946         int band_nr, int *parent_active, int n_active)
2947 {
2948         int i, j;
2949         isl_ctx *ctx = isl_schedule_get_ctx(schedule);
2950         int *active;
2951         int n_band;
2952         isl_band_list *list;
2953
2954         n_band = 0;
2955         for (i = 0; i < n_active; ++i) {
2956                 for (j = 0; j < schedule->n; ++j) {
2957                         if (!parent_active[j])
2958                                 continue;
2959                         if (schedule->node[j].n_band <= band_nr)
2960                                 continue;
2961                         if (schedule->node[j].band_id[band_nr] == i) {
2962                                 n_band++;
2963                                 break;
2964                         }
2965                 }
2966         }
2967         for (j = 0; j < schedule->n; ++j)
2968                 if (schedule->node[j].n_band <= band_nr)
2969                         n_band++;
2970
2971         if (n_band == 1) {
2972                 isl_band *band;
2973                 list = isl_band_list_alloc(ctx, n_band);
2974                 band = construct_band(schedule, parent, band_nr,
2975                                         parent_active, n_active);
2976                 return isl_band_list_add(list, band);
2977         }
2978
2979         active = isl_alloc_array(ctx, int, schedule->n);
2980         if (!active)
2981                 return NULL;
2982
2983         list = isl_band_list_alloc(ctx, n_band);
2984
2985         for (i = 0; i < n_active; ++i) {
2986                 int n = 0;
2987                 isl_band *band;
2988
2989                 for (j = 0; j < schedule->n; ++j) {
2990                         active[j] = parent_active[j] &&
2991                                         schedule->node[j].n_band > band_nr &&
2992                                         schedule->node[j].band_id[band_nr] == i;
2993                         if (active[j])
2994                                 n++;
2995                 }
2996                 if (n == 0)
2997                         continue;
2998
2999                 band = construct_band(schedule, parent, band_nr, active, n);
3000
3001                 list = isl_band_list_add(list, band);
3002         }
3003         for (i = 0; i < schedule->n; ++i) {
3004                 isl_band *band;
3005                 if (!parent_active[i])
3006                         continue;
3007                 if (schedule->node[i].n_band > band_nr)
3008                         continue;
3009                 for (j = 0; j < schedule->n; ++j)
3010                         active[j] = j == i;
3011                 band = construct_band(schedule, parent, band_nr, active, 1);
3012                 list = isl_band_list_add(list, band);
3013         }
3014
3015         free(active);
3016
3017         return list;
3018 }
3019
3020 /* Construct a band forest representation of the schedule and
3021  * return the list of roots.
3022  */
3023 static __isl_give isl_band_list *construct_forest(
3024         __isl_keep isl_schedule *schedule)
3025 {
3026         int i;
3027         isl_ctx *ctx = isl_schedule_get_ctx(schedule);
3028         isl_band_list *forest;
3029         int *active;
3030
3031         active = isl_alloc_array(ctx, int, schedule->n);
3032         if (!active)
3033                 return NULL;
3034
3035         for (i = 0; i < schedule->n; ++i)
3036                 active[i] = 1;
3037
3038         forest = construct_band_list(schedule, NULL, 0, active, schedule->n);
3039
3040         free(active);
3041
3042         return forest;
3043 }
3044
3045 /* Return the roots of a band forest representation of the schedule.
3046  */
3047 __isl_give isl_band_list *isl_schedule_get_band_forest(
3048         __isl_keep isl_schedule *schedule)
3049 {
3050         if (!schedule)
3051                 return NULL;
3052         if (!schedule->band_forest)
3053                 schedule->band_forest = construct_forest(schedule);
3054         return isl_band_list_dup(schedule->band_forest);
3055 }
3056
3057 static __isl_give isl_printer *print_band_list(__isl_take isl_printer *p,
3058         __isl_keep isl_band_list *list);
3059
3060 static __isl_give isl_printer *print_band(__isl_take isl_printer *p,
3061         __isl_keep isl_band *band)
3062 {
3063         isl_band_list *children;
3064
3065         p = isl_printer_start_line(p);
3066         p = isl_printer_print_union_map(p, band->map);
3067         p = isl_printer_end_line(p);
3068
3069         if (!isl_band_has_children(band))
3070                 return p;
3071
3072         children = isl_band_get_children(band);
3073
3074         p = isl_printer_indent(p, 4);
3075         p = print_band_list(p, children);
3076         p = isl_printer_indent(p, -4);
3077
3078         isl_band_list_free(children);
3079
3080         return p;
3081 }
3082
3083 static __isl_give isl_printer *print_band_list(__isl_take isl_printer *p,
3084         __isl_keep isl_band_list *list)
3085 {
3086         int i, n;
3087
3088         n = isl_band_list_n_band(list);
3089         for (i = 0; i < n; ++i) {
3090                 isl_band *band;
3091                 band = isl_band_list_get_band(list, i);
3092                 p = print_band(p, band);
3093                 isl_band_free(band);
3094         }
3095
3096         return p;
3097 }
3098
3099 __isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
3100         __isl_keep isl_schedule *schedule)
3101 {
3102         isl_band_list *forest;
3103
3104         forest = isl_schedule_get_band_forest(schedule);
3105
3106         p = print_band_list(p, forest);
3107
3108         isl_band_list_free(forest);
3109
3110         return p;
3111 }
3112
3113 void isl_schedule_dump(__isl_keep isl_schedule *schedule)
3114 {
3115         isl_printer *printer;
3116
3117         if (!schedule)
3118                 return;
3119
3120         printer = isl_printer_to_file(isl_schedule_get_ctx(schedule), stderr);
3121         printer = isl_printer_print_schedule(printer, schedule);
3122
3123         isl_printer_free(printer);
3124 }