Rename headers from isl_header.h to isl/header.h
[platform/upstream/isl.git] / isl_flow.c
1 /*
2  * Copyright 2005-2007 Universiteit Leiden
3  * Copyright 2008-2009 Katholieke Universiteit Leuven
4  * Copyright 2010      INRIA Saclay
5  *
6  * Use of this software is governed by the GNU LGPLv2.1 license
7  *
8  * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
9  * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
10  * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
11  * B-3001 Leuven, Belgium
12  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
13  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
14  */
15
16 #include <isl/flow.h>
17
18 /* A private structure to keep track of a mapping together with
19  * a user-specified identifier and a boolean indicating whether
20  * the map represents a must or may access/dependence.
21  */
22 struct isl_labeled_map {
23         struct isl_map  *map;
24         void            *data;
25         int             must;
26 };
27
28 /* A structure containing the input for dependence analysis:
29  * - a sink
30  * - n_must + n_may (<= max_source) sources
31  * - a function for determining the relative order of sources and sink
32  * The must sources are placed before the may sources.
33  */
34 struct isl_access_info {
35         struct isl_labeled_map  sink;
36         isl_access_level_before level_before;
37         int                     max_source;
38         int                     n_must;
39         int                     n_may;
40         struct isl_labeled_map  source[1];
41 };
42
43 /* A structure containing the output of dependence analysis:
44  * - n_source dependences
45  * - a subset of the sink for which definitely no source could be found
46  * - a subset of the sink for which possibly no source could be found
47  */
48 struct isl_flow {
49         isl_set                 *must_no_source;
50         isl_set                 *may_no_source;
51         int                     n_source;
52         struct isl_labeled_map  *dep;
53 };
54
55 /* Construct an isl_access_info structure and fill it up with
56  * the given data.  The number of sources is set to 0.
57  */
58 __isl_give isl_access_info *isl_access_info_alloc(__isl_take isl_map *sink,
59         void *sink_user, isl_access_level_before fn, int max_source)
60 {
61         struct isl_access_info *acc;
62
63         if (!sink)
64                 return NULL;
65
66         isl_assert(sink->ctx, max_source >= 0, goto error);
67
68         acc = isl_alloc(sink->ctx, struct isl_access_info,
69                         sizeof(struct isl_access_info) +
70                         (max_source - 1) * sizeof(struct isl_labeled_map));
71         if (!acc)
72                 goto error;
73
74         acc->sink.map = sink;
75         acc->sink.data = sink_user;
76         acc->level_before = fn;
77         acc->max_source = max_source;
78         acc->n_must = 0;
79         acc->n_may = 0;
80
81         return acc;
82 error:
83         isl_map_free(sink);
84         return NULL;
85 }
86
87 /* Free the given isl_access_info structure.
88  */
89 void isl_access_info_free(__isl_take isl_access_info *acc)
90 {
91         int i;
92
93         if (!acc)
94                 return;
95         isl_map_free(acc->sink.map);
96         for (i = 0; i < acc->n_must + acc->n_may; ++i)
97                 isl_map_free(acc->source[i].map);
98         free(acc);
99 }
100
101 /* Add another source to an isl_access_info structure, making
102  * sure the "must" sources are placed before the "may" sources.
103  * This function may be called at most max_source times on a
104  * given isl_access_info structure, with max_source as specified
105  * in the call to isl_access_info_alloc that constructed the structure.
106  */
107 __isl_give isl_access_info *isl_access_info_add_source(
108         __isl_take isl_access_info *acc, __isl_take isl_map *source,
109         int must, void *source_user)
110 {
111         if (!acc)
112                 return NULL;
113         isl_assert(acc->sink.map->ctx,
114                     acc->n_must + acc->n_may < acc->max_source, goto error);
115         
116         if (must) {
117                 if (acc->n_may)
118                         acc->source[acc->n_must + acc->n_may] =
119                                 acc->source[acc->n_must];
120                 acc->source[acc->n_must].map = source;
121                 acc->source[acc->n_must].data = source_user;
122                 acc->source[acc->n_must].must = 1;
123                 acc->n_must++;
124         } else {
125                 acc->source[acc->n_must + acc->n_may].map = source;
126                 acc->source[acc->n_must + acc->n_may].data = source_user;
127                 acc->source[acc->n_must + acc->n_may].must = 0;
128                 acc->n_may++;
129         }
130
131         return acc;
132 error:
133         isl_map_free(source);
134         isl_access_info_free(acc);
135         return NULL;
136 }
137
138 /* A temporary structure used while sorting the accesses in an isl_access_info.
139  */
140 struct isl_access_sort_info {
141         struct isl_map          *source_map;
142         void                    *source_data;
143         struct isl_access_info  *acc;
144 };
145
146 /* Return -n, 0 or n (with n a positive value), depending on whether
147  * the source access identified by p1 should be sorted before, together
148  * or after that identified by p2.
149  *
150  * If p1 and p2 share a different number of levels with the sink,
151  * then the one with the lowest number of shared levels should be
152  * sorted first.
153  * If they both share no levels, then the order is irrelevant.
154  * Otherwise, if p1 appears before p2, then it should be sorted first.
155  */
156 static int access_sort_cmp(const void *p1, const void *p2)
157 {
158         const struct isl_access_sort_info *i1, *i2;
159         int level1, level2;
160         i1 = (const struct isl_access_sort_info *) p1;
161         i2 = (const struct isl_access_sort_info *) p2;
162
163         level1 = i1->acc->level_before(i1->source_data, i1->acc->sink.data);
164         level2 = i2->acc->level_before(i2->source_data, i2->acc->sink.data);
165
166         if (level1 != level2 || !level1)
167                 return level1 - level2;
168
169         level1 = i1->acc->level_before(i1->source_data, i2->source_data);
170
171         return (level1 % 2) ? -1 : 1;
172 }
173
174 /* Sort the must source accesses in order of increasing number of shared
175  * levels with the sink access.
176  * Source accesses with the same number of shared levels are sorted
177  * in their textual order.
178  */
179 static __isl_give isl_access_info *isl_access_info_sort_sources(
180         __isl_take isl_access_info *acc)
181 {
182         int i;
183         struct isl_access_sort_info *array;
184
185         if (!acc)
186                 return NULL;
187         if (acc->n_must <= 1)
188                 return acc;
189
190         array = isl_alloc_array(acc->sink.map->ctx,
191                                 struct isl_access_sort_info, acc->n_must);
192         if (!array)
193                 goto error;
194
195         for (i = 0; i < acc->n_must; ++i) {
196                 array[i].source_map = acc->source[i].map;
197                 array[i].source_data = acc->source[i].data;
198                 array[i].acc = acc;
199         }
200
201         qsort(array, acc->n_must, sizeof(struct isl_access_sort_info),
202                 access_sort_cmp);
203
204         for (i = 0; i < acc->n_must; ++i) {
205                 acc->source[i].map = array[i].source_map;
206                 acc->source[i].data = array[i].source_data;
207         }
208
209         free(array);
210
211         return acc;
212 error:
213         isl_access_info_free(acc);
214         return NULL;
215 }
216
217 /* Initialize an empty isl_flow structure corresponding to a given
218  * isl_access_info structure.
219  * For each must access, two dependences are created (initialized
220  * to the empty relation), one for the resulting must dependences
221  * and one for the resulting may dependences.  May accesses can
222  * only lead to may dependences, so only one dependence is created
223  * for each of them.
224  * This function is private as isl_flow structures are only supposed
225  * to be created by isl_access_info_compute_flow.
226  */
227 static __isl_give isl_flow *isl_flow_alloc(__isl_keep isl_access_info *acc)
228 {
229         int i;
230         struct isl_ctx *ctx;
231         struct isl_flow *dep;
232
233         if (!acc)
234                 return NULL;
235
236         ctx = acc->sink.map->ctx;
237         dep = isl_calloc_type(ctx, struct isl_flow);
238         if (!dep)
239                 return NULL;
240
241         dep->dep = isl_calloc_array(ctx, struct isl_labeled_map,
242                                         2 * acc->n_must + acc->n_may);
243         if (!dep->dep)
244                 goto error;
245
246         dep->n_source = 2 * acc->n_must + acc->n_may;
247         for (i = 0; i < acc->n_must; ++i) {
248                 struct isl_dim *dim;
249                 dim = isl_dim_join(isl_map_get_dim(acc->source[i].map),
250                             isl_dim_reverse(isl_map_get_dim(acc->sink.map)));
251                 dep->dep[2 * i].map = isl_map_empty(dim);
252                 dep->dep[2 * i + 1].map = isl_map_copy(dep->dep[2 * i].map);
253                 dep->dep[2 * i].data = acc->source[i].data;
254                 dep->dep[2 * i + 1].data = acc->source[i].data;
255                 dep->dep[2 * i].must = 1;
256                 dep->dep[2 * i + 1].must = 0;
257                 if (!dep->dep[2 * i].map || !dep->dep[2 * i + 1].map)
258                         goto error;
259         }
260         for (i = acc->n_must; i < acc->n_must + acc->n_may; ++i) {
261                 struct isl_dim *dim;
262                 dim = isl_dim_join(isl_map_get_dim(acc->source[i].map),
263                             isl_dim_reverse(isl_map_get_dim(acc->sink.map)));
264                 dep->dep[acc->n_must + i].map = isl_map_empty(dim);
265                 dep->dep[acc->n_must + i].data = acc->source[i].data;
266                 dep->dep[acc->n_must + i].must = 0;
267                 if (!dep->dep[acc->n_must + i].map)
268                         goto error;
269         }
270
271         return dep;
272 error:
273         isl_flow_free(dep);
274         return NULL;
275 }
276
277 /* Iterate over all sources and for each resulting flow dependence
278  * that is not empty, call the user specfied function.
279  * The second argument in this function call identifies the source,
280  * while the third argument correspond to the final argument of
281  * the isl_flow_foreach call.
282  */
283 int isl_flow_foreach(__isl_keep isl_flow *deps,
284         int (*fn)(__isl_take isl_map *dep, int must, void *dep_user, void *user),
285         void *user)
286 {
287         int i;
288
289         if (!deps)
290                 return -1;
291
292         for (i = 0; i < deps->n_source; ++i) {
293                 if (isl_map_fast_is_empty(deps->dep[i].map))
294                         continue;
295                 if (fn(isl_map_copy(deps->dep[i].map), deps->dep[i].must,
296                                 deps->dep[i].data, user) < 0)
297                         return -1;
298         }
299
300         return 0;
301 }
302
303 /* Return a copy of the subset of the sink for which no source could be found.
304  */
305 __isl_give isl_set *isl_flow_get_no_source(__isl_keep isl_flow *deps, int must)
306 {
307         if (!deps)
308                 return NULL;
309         
310         if (must)
311                 return isl_set_copy(deps->must_no_source);
312         else
313                 return isl_set_copy(deps->may_no_source);
314 }
315
316 void isl_flow_free(__isl_take isl_flow *deps)
317 {
318         int i;
319
320         if (!deps)
321                 return;
322         isl_set_free(deps->must_no_source);
323         isl_set_free(deps->may_no_source);
324         if (deps->dep) {
325                 for (i = 0; i < deps->n_source; ++i)
326                         isl_map_free(deps->dep[i].map);
327                 free(deps->dep);
328         }
329         free(deps);
330 }
331
332 /* Return a map that enforces that the domain iteration occurs after
333  * the range iteration at the given level.
334  * If level is odd, then the domain iteration should occur after
335  * the target iteration in their shared level/2 outermost loops.
336  * In this case we simply need to enforce that these outermost
337  * loop iterations are the same.
338  * If level is even, then the loop iterator of the domain should
339  * be greater than the loop iterator of the range at the last
340  * of the level/2 shared loops, i.e., loop level/2 - 1.
341  */
342 static __isl_give isl_map *after_at_level(struct isl_dim *dim, int level)
343 {
344         struct isl_basic_map *bmap;
345
346         if (level % 2)
347                 bmap = isl_basic_map_equal(dim, level/2);
348         else
349                 bmap = isl_basic_map_more_at(dim, level/2 - 1);
350
351         return isl_map_from_basic_map(bmap);
352 }
353
354 /* Compute the last iteration of must source j that precedes the sink
355  * at the given level for sink iterations in set_C.
356  * The subset of set_C for which no such iteration can be found is returned
357  * in *empty.
358  */
359 static struct isl_map *last_source(struct isl_access_info *acc, 
360                                     struct isl_set *set_C,
361                                     int j, int level, struct isl_set **empty)
362 {
363         struct isl_map *read_map;
364         struct isl_map *write_map;
365         struct isl_map *dep_map;
366         struct isl_map *after;
367         struct isl_map *result;
368
369         read_map = isl_map_copy(acc->sink.map);
370         write_map = isl_map_copy(acc->source[j].map);
371         write_map = isl_map_reverse(write_map);
372         dep_map = isl_map_apply_range(read_map, write_map);
373         after = after_at_level(isl_map_get_dim(dep_map), level);
374         dep_map = isl_map_intersect(dep_map, after);
375         result = isl_map_partial_lexmax(dep_map, set_C, empty);
376         result = isl_map_reverse(result);
377
378         return result;
379 }
380
381 /* For a given mapping between iterations of must source j and iterations
382  * of the sink, compute the last iteration of must source k preceding
383  * the sink at level before_level for any of the sink iterations,
384  * but following the corresponding iteration of must source j at level
385  * after_level.
386  */
387 static struct isl_map *last_later_source(struct isl_access_info *acc,
388                                          struct isl_map *old_map,
389                                          int j, int before_level,
390                                          int k, int after_level,
391                                          struct isl_set **empty)
392 {
393         struct isl_dim *dim;
394         struct isl_set *set_C;
395         struct isl_map *read_map;
396         struct isl_map *write_map;
397         struct isl_map *dep_map;
398         struct isl_map *after_write;
399         struct isl_map *before_read;
400         struct isl_map *result;
401
402         set_C = isl_map_range(isl_map_copy(old_map));
403         read_map = isl_map_copy(acc->sink.map);
404         write_map = isl_map_copy(acc->source[k].map);
405
406         write_map = isl_map_reverse(write_map);
407         dep_map = isl_map_apply_range(read_map, write_map);
408         dim = isl_dim_join(isl_map_get_dim(acc->source[k].map),
409                     isl_dim_reverse(isl_map_get_dim(acc->source[j].map)));
410         after_write = after_at_level(dim, after_level);
411         after_write = isl_map_apply_range(after_write, old_map);
412         after_write = isl_map_reverse(after_write);
413         dep_map = isl_map_intersect(dep_map, after_write);
414         before_read = after_at_level(isl_map_get_dim(dep_map), before_level);
415         dep_map = isl_map_intersect(dep_map, before_read);
416         result = isl_map_partial_lexmax(dep_map, set_C, empty);
417         result = isl_map_reverse(result);
418
419         return result;
420 }
421
422 /* Given a shared_level between two accesses, return 1 if the
423  * the first can precede the second at the requested target_level.
424  * If the target level is odd, i.e., refers to a statement level
425  * dimension, then first needs to precede second at the requested
426  * level, i.e., shared_level must be equal to target_level.
427  * If the target level is odd, then the two loops should share
428  * at least the requested number of outer loops.
429  */
430 static int can_precede_at_level(int shared_level, int target_level)
431 {
432         if (shared_level < target_level)
433                 return 0;
434         if ((target_level % 2) && shared_level > target_level)
435                 return 0;
436         return 1;
437 }
438
439 /* Given a possible flow dependence temp_rel[j] between source j and the sink
440  * at level sink_level, remove those elements for which
441  * there is an iteration of another source k < j that is closer to the sink.
442  * The flow dependences temp_rel[k] are updated with the improved sources.
443  * Any improved source needs to precede the sink at the same level
444  * and needs to follow source j at the same or a deeper level.
445  * The lower this level, the later the execution date of source k.
446  * We therefore consider lower levels first.
447  *
448  * If temp_rel[j] is empty, then there can be no improvement and
449  * we return immediately.
450  */
451 static int intermediate_sources(__isl_keep isl_access_info *acc,
452         struct isl_map **temp_rel, int j, int sink_level)
453 {
454         int k, level;
455         int depth = 2 * isl_map_dim(acc->source[j].map, isl_dim_in) + 1;
456
457         if (isl_map_fast_is_empty(temp_rel[j]))
458                 return 0;
459
460         for (k = j - 1; k >= 0; --k) {
461                 int plevel, plevel2;
462                 plevel = acc->level_before(acc->source[k].data, acc->sink.data);
463                 if (!can_precede_at_level(plevel, sink_level))
464                         continue;
465
466                 plevel2 = acc->level_before(acc->source[j].data,
467                                                 acc->source[k].data);
468
469                 for (level = sink_level; level <= depth; ++level) {
470                         struct isl_map *T;
471                         struct isl_set *trest;
472                         struct isl_map *copy;
473
474                         if (!can_precede_at_level(plevel2, level))
475                                 continue;
476
477                         copy = isl_map_copy(temp_rel[j]);
478                         T = last_later_source(acc, copy, j, sink_level, k,
479                                               level, &trest);
480                         if (isl_map_fast_is_empty(T)) {
481                                 isl_set_free(trest);
482                                 isl_map_free(T);
483                                 continue;
484                         }
485                         temp_rel[j] = isl_map_intersect_range(temp_rel[j], trest);
486                         temp_rel[k] = isl_map_union_disjoint(temp_rel[k], T);
487                 }
488         }
489
490         return 0;
491 }
492
493 /* Compute all iterations of may source j that precedes the sink at the given
494  * level for sink iterations in set_C.
495  */
496 static __isl_give isl_map *all_sources(__isl_keep isl_access_info *acc,
497                                     __isl_take isl_set *set_C, int j, int level)
498 {
499         isl_map *read_map;
500         isl_map *write_map;
501         isl_map *dep_map;
502         isl_map *after;
503
504         read_map = isl_map_copy(acc->sink.map);
505         read_map = isl_map_intersect_domain(read_map, set_C);
506         write_map = isl_map_copy(acc->source[acc->n_must + j].map);
507         write_map = isl_map_reverse(write_map);
508         dep_map = isl_map_apply_range(read_map, write_map);
509         after = after_at_level(isl_map_get_dim(dep_map), level);
510         dep_map = isl_map_intersect(dep_map, after);
511
512         return isl_map_reverse(dep_map);
513 }
514
515 /* For a given mapping between iterations of must source k and iterations
516  * of the sink, compute the all iteration of may source j preceding
517  * the sink at level before_level for any of the sink iterations,
518  * but following the corresponding iteration of must source k at level
519  * after_level.
520  */
521 static __isl_give isl_map *all_later_sources(__isl_keep isl_access_info *acc,
522         __isl_keep isl_map *old_map,
523         int j, int before_level, int k, int after_level)
524 {
525         isl_dim *dim;
526         isl_set *set_C;
527         isl_map *read_map;
528         isl_map *write_map;
529         isl_map *dep_map;
530         isl_map *after_write;
531         isl_map *before_read;
532
533         set_C = isl_map_range(isl_map_copy(old_map));
534         read_map = isl_map_copy(acc->sink.map);
535         read_map = isl_map_intersect_domain(read_map, set_C);
536         write_map = isl_map_copy(acc->source[acc->n_must + j].map);
537
538         write_map = isl_map_reverse(write_map);
539         dep_map = isl_map_apply_range(read_map, write_map);
540         dim = isl_dim_join(isl_map_get_dim(acc->source[acc->n_must + j].map),
541                     isl_dim_reverse(isl_map_get_dim(acc->source[k].map)));
542         after_write = after_at_level(dim, after_level);
543         after_write = isl_map_apply_range(after_write, old_map);
544         after_write = isl_map_reverse(after_write);
545         dep_map = isl_map_intersect(dep_map, after_write);
546         before_read = after_at_level(isl_map_get_dim(dep_map), before_level);
547         dep_map = isl_map_intersect(dep_map, before_read);
548         return isl_map_reverse(dep_map);
549 }
550
551 /* Given the must and may dependence relations for the must accesses
552  * for level sink_level, check if there are any accesses of may access j
553  * that occur in between and return their union.
554  * If some of these accesses are intermediate with respect to
555  * (previously thought to be) must dependences, then these
556  * must dependences are turned into may dependences.
557  */
558 static __isl_give isl_map *all_intermediate_sources(
559         __isl_keep isl_access_info *acc, __isl_take isl_map *map,
560         struct isl_map **must_rel, struct isl_map **may_rel,
561         int j, int sink_level)
562 {
563         int k, level;
564         int depth = 2 * isl_map_dim(acc->source[acc->n_must + j].map,
565                                         isl_dim_in) + 1;
566
567         for (k = 0; k < acc->n_must; ++k) {
568                 int plevel;
569
570                 if (isl_map_fast_is_empty(may_rel[k]) &&
571                     isl_map_fast_is_empty(must_rel[k]))
572                         continue;
573
574                 plevel = acc->level_before(acc->source[k].data,
575                                         acc->source[acc->n_must + j].data);
576
577                 for (level = sink_level; level <= depth; ++level) {
578                         isl_map *T;
579                         isl_map *copy;
580                         isl_set *ran;
581
582                         if (!can_precede_at_level(plevel, level))
583                                 continue;
584
585                         copy = isl_map_copy(may_rel[k]);
586                         T = all_later_sources(acc, copy, j, sink_level, k, level);
587                         map = isl_map_union(map, T);
588
589                         copy = isl_map_copy(must_rel[k]);
590                         T = all_later_sources(acc, copy, j, sink_level, k, level);
591                         ran = isl_map_range(isl_map_copy(T));
592                         map = isl_map_union(map, T);
593                         may_rel[k] = isl_map_union_disjoint(may_rel[k],
594                             isl_map_intersect_range(isl_map_copy(must_rel[k]),
595                                                     isl_set_copy(ran)));
596                         T = isl_map_from_domain_and_range(
597                             isl_set_universe(
598                                 isl_dim_domain(isl_map_get_dim(must_rel[k]))),
599                             ran);
600                         must_rel[k] = isl_map_subtract(must_rel[k], T);
601                 }
602         }
603
604         return map;
605 }
606
607 /* Compute dependences for the case where all accesses are "may"
608  * accesses, which boils down to computing memory based dependences.
609  * The generic algorithm would also work in this case, but it would
610  * be overkill to use it.
611  */
612 static __isl_give isl_flow *compute_mem_based_dependences(
613         __isl_take isl_access_info *acc)
614 {
615         int i;
616         isl_set *mustdo;
617         isl_set *maydo;
618         isl_flow *res;
619
620         res = isl_flow_alloc(acc);
621         if (!res)
622                 goto error;
623
624         mustdo = isl_map_domain(isl_map_copy(acc->sink.map));
625         maydo = isl_set_copy(mustdo);
626
627         for (i = 0; i < acc->n_may; ++i) {
628                 int plevel;
629                 int is_before;
630                 isl_dim *dim;
631                 isl_map *before;
632                 isl_map *dep;
633
634                 plevel = acc->level_before(acc->source[i].data, acc->sink.data);
635                 is_before = plevel & 1;
636                 plevel >>= 1;
637
638                 dim = isl_map_get_dim(res->dep[i].map);
639                 if (is_before)
640                         before = isl_map_lex_le_first(dim, plevel);
641                 else
642                         before = isl_map_lex_lt_first(dim, plevel);
643                 dep = isl_map_apply_range(isl_map_copy(acc->source[i].map),
644                         isl_map_reverse(isl_map_copy(acc->sink.map)));
645                 dep = isl_map_intersect(dep, before);
646                 mustdo = isl_set_subtract(mustdo,
647                                             isl_map_range(isl_map_copy(dep)));
648                 res->dep[i].map = isl_map_union(res->dep[i].map, dep);
649         }
650
651         res->may_no_source = isl_set_subtract(maydo, isl_set_copy(mustdo));
652         res->must_no_source = mustdo;
653
654         isl_access_info_free(acc);
655
656         return res;
657 error:
658         isl_access_info_free(acc);
659         return NULL;
660 }
661
662 /* Compute dependences for the case where there is at least one
663  * "must" access.
664  *
665  * The core algorithm considers all levels in which a source may precede
666  * the sink, where a level may either be a statement level or a loop level.
667  * The outermost statement level is 1, the first loop level is 2, etc...
668  * The algorithm basically does the following:
669  * for all levels l of the read access from innermost to outermost
670  *      for all sources w that may precede the sink access at that level
671  *          compute the last iteration of the source that precedes the sink access
672  *                                          at that level
673  *          add result to possible last accesses at level l of source w
674  *          for all sources w2 that we haven't considered yet at this level that may
675  *                                          also precede the sink access
676  *              for all levels l2 of w from l to innermost
677  *                  for all possible last accesses dep of w at l
678  *                      compute last iteration of w2 between the source and sink
679  *                                                              of dep
680  *                      add result to possible last accesses at level l of write w2
681  *                      and replace possible last accesses dep by the remainder
682  *
683  *
684  * The above algorithm is applied to the must access.  During the course
685  * of the algorithm, we keep track of sink iterations that still
686  * need to be considered.  These iterations are split into those that
687  * haven't been matched to any source access (mustdo) and those that have only
688  * been matched to may accesses (maydo).
689  * At the end of each level, we also consider the may accesses.
690  * In particular, we consider may accesses that precede the remaining
691  * sink iterations, moving elements from mustdo to maydo when appropriate,
692  * and may accesses that occur between a must source and a sink of any 
693  * dependences found at the current level, turning must dependences into
694  * may dependences when appropriate.
695  * 
696  */
697 static __isl_give isl_flow *compute_val_based_dependences(
698         __isl_take isl_access_info *acc)
699 {
700         isl_ctx *ctx;
701         isl_flow *res;
702         isl_set *mustdo = NULL;
703         isl_set *maydo = NULL;
704         int level, j;
705         int depth;
706         isl_map **must_rel = NULL;
707         isl_map **may_rel = NULL;
708
709         acc = isl_access_info_sort_sources(acc);
710         if (!acc)
711                 return NULL;
712
713         res = isl_flow_alloc(acc);
714         if (!res)
715                 goto error;
716         ctx = acc->sink.map->ctx;
717
718         depth = 2 * isl_map_dim(acc->sink.map, isl_dim_in) + 1;
719         mustdo = isl_map_domain(isl_map_copy(acc->sink.map));
720         maydo = isl_set_empty_like(mustdo);
721         if (!mustdo || !maydo)
722                 goto error;
723         if (isl_set_fast_is_empty(mustdo))
724                 goto done;
725
726         must_rel = isl_alloc_array(ctx, struct isl_map *, acc->n_must);
727         may_rel = isl_alloc_array(ctx, struct isl_map *, acc->n_must);
728         if (!must_rel || !may_rel)
729                 goto error;
730
731         for (level = depth; level >= 1; --level) {
732                 for (j = acc->n_must-1; j >=0; --j) {
733                         must_rel[j] = isl_map_empty_like(res->dep[j].map);
734                         may_rel[j] = isl_map_copy(must_rel[j]);
735                 }
736
737                 for (j = acc->n_must - 1; j >= 0; --j) {
738                         struct isl_map *T;
739                         struct isl_set *rest;
740                         int plevel;
741
742                         plevel = acc->level_before(acc->source[j].data,
743                                                      acc->sink.data);
744                         if (!can_precede_at_level(plevel, level))
745                                 continue;
746
747                         T = last_source(acc, mustdo, j, level, &rest);
748                         must_rel[j] = isl_map_union_disjoint(must_rel[j], T);
749                         mustdo = rest;
750
751                         intermediate_sources(acc, must_rel, j, level);
752
753                         T = last_source(acc, maydo, j, level, &rest);
754                         may_rel[j] = isl_map_union_disjoint(may_rel[j], T);
755                         maydo = rest;
756
757                         intermediate_sources(acc, may_rel, j, level);
758
759                         if (isl_set_fast_is_empty(mustdo) &&
760                             isl_set_fast_is_empty(maydo))
761                                 break;
762                 }
763                 for (j = j - 1; j >= 0; --j) {
764                         int plevel;
765
766                         plevel = acc->level_before(acc->source[j].data,
767                                                      acc->sink.data);
768                         if (!can_precede_at_level(plevel, level))
769                                 continue;
770
771                         intermediate_sources(acc, must_rel, j, level);
772                         intermediate_sources(acc, may_rel, j, level);
773                 }
774
775                 for (j = 0; j < acc->n_may; ++j) {
776                         int plevel;
777                         isl_map *T;
778                         isl_set *ran;
779
780                         plevel = acc->level_before(acc->source[acc->n_must + j].data,
781                                                      acc->sink.data);
782                         if (!can_precede_at_level(plevel, level))
783                                 continue;
784
785                         T = all_sources(acc, isl_set_copy(maydo), j, level);
786                         res->dep[2 * acc->n_must + j].map =
787                             isl_map_union(res->dep[2 * acc->n_must + j].map, T);
788                         T = all_sources(acc, isl_set_copy(mustdo), j, level);
789                         ran = isl_map_range(isl_map_copy(T));
790                         res->dep[2 * acc->n_must + j].map =
791                             isl_map_union(res->dep[2 * acc->n_must + j].map, T);
792                         mustdo = isl_set_subtract(mustdo, isl_set_copy(ran));
793                         maydo = isl_set_union_disjoint(maydo, ran);
794
795                         T = res->dep[2 * acc->n_must + j].map;
796                         T = all_intermediate_sources(acc, T, must_rel, may_rel,
797                                                         j, level);
798                         res->dep[2 * acc->n_must + j].map = T;
799                 }
800
801                 for (j = acc->n_must - 1; j >= 0; --j) {
802                         res->dep[2 * j].map =
803                                 isl_map_union_disjoint(res->dep[2 * j].map,
804                                                              must_rel[j]);
805                         res->dep[2 * j + 1].map =
806                                 isl_map_union_disjoint(res->dep[2 * j + 1].map,
807                                                              may_rel[j]);
808                 }
809
810                 if (isl_set_fast_is_empty(mustdo) &&
811                     isl_set_fast_is_empty(maydo))
812                         break;
813         }
814
815         free(must_rel);
816         free(may_rel);
817 done:
818         res->must_no_source = mustdo;
819         res->may_no_source = maydo;
820         isl_access_info_free(acc);
821         return res;
822 error:
823         isl_access_info_free(acc);
824         isl_flow_free(res);
825         isl_set_free(mustdo);
826         isl_set_free(maydo);
827         free(must_rel);
828         free(may_rel);
829         return NULL;
830 }
831
832 /* Given a "sink" access, a list of n "source" accesses,
833  * compute for each iteration of the sink access
834  * and for each element accessed by that iteration,
835  * the source access in the list that last accessed the
836  * element accessed by the sink access before this sink access.
837  * Each access is given as a map from the loop iterators
838  * to the array indices.
839  * The result is a list of n relations between source and sink
840  * iterations and a subset of the domain of the sink access,
841  * corresponding to those iterations that access an element
842  * not previously accessed.
843  *
844  * To deal with multi-valued sink access relations, the sink iteration
845  * domain is first extended with dimensions that correspond to the data
846  * space.  After the computation is finished, these extra dimensions are
847  * projected out again.
848  */
849 __isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *acc)
850 {
851         int j;
852         struct isl_flow *res;
853         isl_map *domain_map = NULL;
854
855         if (!acc)
856                 return NULL;
857
858         domain_map = isl_map_domain_map(isl_map_copy(acc->sink.map));
859         acc->sink.map = isl_map_range_map(acc->sink.map);
860         if (!acc->sink.map)
861                 goto error;
862
863         if (acc->n_must == 0)
864                 res = compute_mem_based_dependences(acc);
865         else
866                 res = compute_val_based_dependences(acc);
867         if (!res)
868                 return NULL;
869
870         for (j = 0; j < res->n_source; ++j) {
871                 res->dep[j].map = isl_map_apply_range(res->dep[j].map,
872                                         isl_map_copy(domain_map));
873                 if (!res->dep[j].map)
874                         goto error2;
875         }
876         res->must_no_source = isl_set_apply(res->must_no_source,
877                                         isl_map_copy(domain_map));
878         res->may_no_source = isl_set_apply(res->may_no_source,
879                                         isl_map_copy(domain_map));
880         if (!res->must_no_source || !res->may_no_source)
881                 goto error2;
882
883         isl_map_free(domain_map);
884         return res;
885 error:
886         isl_map_free(domain_map);
887         isl_access_info_free(acc);
888         return NULL;
889 error2:
890         isl_map_free(domain_map);
891         isl_flow_free(res);
892         return NULL;
893 }
894
895
896 struct isl_compute_flow_data {
897         isl_union_map *must_source;
898         isl_union_map *may_source;
899         isl_union_map *must_dep;
900         isl_union_map *may_dep;
901         isl_union_set *must_no_source;
902         isl_union_set *may_no_source;
903
904         int count;
905         int must;
906         isl_dim *dim;
907         isl_dim *sink_dim;
908         isl_dim **source_dim;
909         isl_access_info *accesses;
910 };
911
912 static int count_matching_array(__isl_take isl_map *map, void *user)
913 {
914         int eq;
915         isl_dim *dim;
916         struct isl_compute_flow_data *data;
917
918         data = (struct isl_compute_flow_data *)user;
919
920         dim = isl_dim_range(isl_map_get_dim(map));
921
922         eq = isl_dim_equal(dim, data->dim);
923
924         isl_dim_free(dim);
925         isl_map_free(map);
926
927         if (eq < 0)
928                 return -1;
929         if (eq)
930                 data->count++;
931
932         return 0;
933 }
934
935 static int collect_matching_array(__isl_take isl_map *map, void *user)
936 {
937         int eq;
938         isl_dim *dim;
939         struct isl_compute_flow_data *data;
940
941         data = (struct isl_compute_flow_data *)user;
942
943         dim = isl_dim_range(isl_map_get_dim(map));
944
945         eq = isl_dim_equal(dim, data->dim);
946
947         isl_dim_free(dim);
948
949         if (eq < 0)
950                 goto error;
951         if (!eq) {
952                 isl_map_free(map);
953                 return 0;
954         }
955
956         dim = isl_dim_unwrap(isl_dim_domain(isl_map_get_dim(map)));
957         data->source_dim[data->count] = dim;
958
959         data->accesses = isl_access_info_add_source(data->accesses,
960                                                     map, data->must, dim);
961
962         data->count++;
963
964         return 0;
965 error:
966         isl_map_free(map);
967         return -1;
968 }
969
970 static int before(void *first, void *second)
971 {
972         isl_dim *dim1 = first;
973         isl_dim *dim2 = second;
974         int n1, n2;
975
976         n1 = isl_dim_size(dim1, isl_dim_in);
977         n2 = isl_dim_size(dim2, isl_dim_in);
978
979         if (n2 < n1)
980                 n1 = n2;
981
982         return 2 * n1 + (dim1 < dim2);
983 }
984
985 /* Given a sink access, look for all the source accesses that access
986  * the same array and perform dataflow analysis on them using
987  * isl_access_info_compute_flow.
988  */
989 static int compute_flow(__isl_take isl_map *map, void *user)
990 {
991         int i;
992         isl_ctx *ctx;
993         struct isl_compute_flow_data *data;
994         isl_flow *flow;
995
996         data = (struct isl_compute_flow_data *)user;
997
998         ctx = isl_map_get_ctx(map);
999
1000         data->accesses = NULL;
1001         data->sink_dim = NULL;
1002         data->source_dim = NULL;
1003         data->count = 0;
1004         data->dim = isl_dim_range(isl_map_get_dim(map));
1005
1006         if (isl_union_map_foreach_map(data->must_source,
1007                                         &count_matching_array, data) < 0)
1008                 goto error;
1009         if (isl_union_map_foreach_map(data->may_source,
1010                                         &count_matching_array, data) < 0)
1011                 goto error;
1012
1013         data->sink_dim = isl_dim_unwrap(isl_dim_domain(isl_map_get_dim(map)));
1014         data->source_dim = isl_calloc_array(ctx, isl_dim *, data->count);
1015
1016         data->accesses = isl_access_info_alloc(isl_map_copy(map),
1017                                 data->sink_dim, &before, data->count);
1018         data->count = 0;
1019         data->must = 1;
1020         if (isl_union_map_foreach_map(data->must_source,
1021                                         &collect_matching_array, data) < 0)
1022                 goto error;
1023         data->must = 0;
1024         if (isl_union_map_foreach_map(data->may_source,
1025                                         &collect_matching_array, data) < 0)
1026                 goto error;
1027
1028         flow = isl_access_info_compute_flow(data->accesses);
1029         data->accesses = NULL;
1030
1031         if (!flow)
1032                 goto error;
1033
1034         data->must_no_source = isl_union_set_union(data->must_no_source,
1035                     isl_union_set_from_set(isl_set_copy(flow->must_no_source)));
1036         data->may_no_source = isl_union_set_union(data->may_no_source,
1037                     isl_union_set_from_set(isl_set_copy(flow->may_no_source)));
1038
1039         for (i = 0; i < flow->n_source; ++i) {
1040                 isl_union_map *dep;
1041                 dep = isl_union_map_from_map(isl_map_copy(flow->dep[i].map));
1042                 if (flow->dep[i].must)
1043                         data->must_dep = isl_union_map_union(data->must_dep, dep);
1044                 else
1045                         data->may_dep = isl_union_map_union(data->may_dep, dep);
1046         }
1047
1048         isl_flow_free(flow);
1049
1050         isl_dim_free(data->sink_dim);
1051         if (data->source_dim) {
1052                 for (i = 0; i < data->count; ++i)
1053                         isl_dim_free(data->source_dim[i]);
1054                 free(data->source_dim);
1055         }
1056         isl_dim_free(data->dim);
1057         isl_map_free(map);
1058
1059         return 0;
1060 error:
1061         isl_access_info_free(data->accesses);
1062         isl_dim_free(data->sink_dim);
1063         if (data->source_dim) {
1064                 for (i = 0; i < data->count; ++i)
1065                         isl_dim_free(data->source_dim[i]);
1066                 free(data->source_dim);
1067         }
1068         isl_dim_free(data->dim);
1069         isl_map_free(map);
1070
1071         return -1;
1072 }
1073
1074 /* Given a collection of "sink" and "source" accesses,
1075  * compute for each iteration of a sink access
1076  * and for each element accessed by that iteration,
1077  * the source access in the list that last accessed the
1078  * element accessed by the sink access before this sink access.
1079  * Each access is given as a map from the loop iterators
1080  * to the array indices.
1081  * The result is a relations between source and sink
1082  * iterations and a subset of the domain of the sink accesses,
1083  * corresponding to those iterations that access an element
1084  * not previously accessed.
1085  *
1086  * We first prepend the schedule dimensions to the domain
1087  * of the accesses so that we can easily compare their relative order.
1088  * Then we consider each sink access individually in compute_flow.
1089  */
1090 int isl_union_map_compute_flow(__isl_take isl_union_map *sink,
1091         __isl_take isl_union_map *must_source,
1092         __isl_take isl_union_map *may_source,
1093         __isl_take isl_union_map *schedule,
1094         __isl_give isl_union_map **must_dep, __isl_give isl_union_map **may_dep,
1095         __isl_give isl_union_set **must_no_source,
1096         __isl_give isl_union_set **may_no_source)
1097 {
1098         isl_dim *dim;
1099         isl_union_map *range_map = NULL;
1100         struct isl_compute_flow_data data;
1101
1102         sink = isl_union_map_align_params(sink,
1103                                             isl_union_map_get_dim(must_source));
1104         sink = isl_union_map_align_params(sink,
1105                                             isl_union_map_get_dim(may_source));
1106         sink = isl_union_map_align_params(sink,
1107                                             isl_union_map_get_dim(schedule));
1108         dim = isl_union_map_get_dim(sink);
1109         must_source = isl_union_map_align_params(must_source, isl_dim_copy(dim));
1110         may_source = isl_union_map_align_params(may_source, isl_dim_copy(dim));
1111         schedule = isl_union_map_align_params(schedule, isl_dim_copy(dim));
1112
1113         schedule = isl_union_map_reverse(schedule);
1114         range_map = isl_union_map_range_map(schedule);
1115         schedule = isl_union_map_reverse(isl_union_map_copy(range_map));
1116         sink = isl_union_map_apply_domain(sink, isl_union_map_copy(schedule));
1117         must_source = isl_union_map_apply_domain(must_source,
1118                                                 isl_union_map_copy(schedule));
1119         may_source = isl_union_map_apply_domain(may_source, schedule);
1120
1121         data.must_source = must_source;
1122         data.may_source = may_source;
1123         data.must_dep = must_dep ?
1124                 isl_union_map_empty(isl_dim_copy(dim)) : NULL;
1125         data.may_dep = may_dep ? isl_union_map_empty(isl_dim_copy(dim)) : NULL;
1126         data.must_no_source = must_no_source ?
1127                 isl_union_set_empty(isl_dim_copy(dim)) : NULL;
1128         data.may_no_source = may_no_source ?
1129                 isl_union_set_empty(isl_dim_copy(dim)) : NULL;
1130
1131         isl_dim_free(dim);
1132
1133         if (isl_union_map_foreach_map(sink, &compute_flow, &data) < 0)
1134                 goto error;
1135
1136         isl_union_map_free(sink);
1137         isl_union_map_free(must_source);
1138         isl_union_map_free(may_source);
1139
1140         if (must_dep) {
1141                 data.must_dep = isl_union_map_apply_domain(data.must_dep,
1142                                         isl_union_map_copy(range_map));
1143                 data.must_dep = isl_union_map_apply_range(data.must_dep,
1144                                         isl_union_map_copy(range_map));
1145                 *must_dep = data.must_dep;
1146         }
1147         if (may_dep) {
1148                 data.may_dep = isl_union_map_apply_domain(data.may_dep,
1149                                         isl_union_map_copy(range_map));
1150                 data.may_dep = isl_union_map_apply_range(data.may_dep,
1151                                         isl_union_map_copy(range_map));
1152                 *may_dep = data.may_dep;
1153         }
1154         if (must_no_source) {
1155                 data.must_no_source = isl_union_set_apply(data.must_no_source,
1156                                         isl_union_map_copy(range_map));
1157                 *must_no_source = data.must_no_source;
1158         }
1159         if (may_no_source) {
1160                 data.may_no_source = isl_union_set_apply(data.may_no_source,
1161                                         isl_union_map_copy(range_map));
1162                 *may_no_source = data.may_no_source;
1163         }
1164
1165         isl_union_map_free(range_map);
1166
1167         return 0;
1168 error:
1169         isl_union_map_free(range_map);
1170         isl_union_map_free(sink);
1171         isl_union_map_free(must_source);
1172         isl_union_map_free(may_source);
1173         isl_union_map_free(data.must_dep);
1174         isl_union_map_free(data.may_dep);
1175         isl_union_set_free(data.must_no_source);
1176         isl_union_set_free(data.may_no_source);
1177
1178         if (must_dep)
1179                 *must_dep = NULL;
1180         if (may_dep)
1181                 *may_dep = NULL;
1182         if (must_no_source)
1183                 *must_no_source = NULL;
1184         if (may_no_source)
1185                 *may_no_source = NULL;
1186         return -1;
1187 }