pn: allow specification of isl options
[ppn.git] / da.cc
blob3bc014055b3ca4ca01555faba6c2d83da5f215a3
1 #include <set>
2 #include <vector>
3 #include <iostream>
5 #include <isa/yaml.h>
6 #include <isa/pdg.h>
7 #include "da.h"
9 extern "C" {
10 #include "isl_util.h"
12 #include "isl/constraint.h"
13 #include <isl/set.h>
14 #include <isl/flow.h>
16 using pdg::PDG;
17 using namespace std;
19 namespace da {
21 /* A pair of a node and an access from that node.
22 * "map" is the converted access relation.
23 * "projected_map" represents the converted access relation without
24 * any embedded access relation or access filters
26 struct na_pair {
27 pdg::node *node;
28 pdg::access *access;
29 isl_map *map;
30 isl_map *projected_map;
31 void project_out_access_filters(void);
32 na_pair(pdg::node *n, pdg::access *a) : node(n), access(a), map(NULL),
33 projected_map(NULL) {}
34 ~na_pair() {
35 isl_map_free(map);
36 isl_map_free(projected_map);
40 /* If the access has any embedded filters, then project them out
41 * from "projected_map", initializing "projected_map" from "map"
42 * if there is no "projected_map" yet.
44 void na_pair::project_out_access_filters(void)
46 isl_space *space;
47 isl_map *proj;
49 if (access->nested.size() == 0)
50 return;
52 if (!projected_map)
53 projected_map = isl_map_copy(map);
55 space = isl_space_domain(isl_map_get_space(projected_map));
56 space = isl_space_unwrap(space);
57 proj = isl_map_domain_map(isl_map_universe(space));
59 projected_map = isl_map_apply_domain(projected_map, proj);
62 static int precedes_level_nodes(na_pair *first, na_pair *second);
63 static int precedes_level_accesses(na_pair *first, na_pair *second);
65 /* Given a map from a domain to an orthogonal projection of an array
66 * (say, the rows of an array), mapping i to m(i), this function
67 * extends the range of the mapping to the original array and extends
68 * the domain of the mapping correspondingly such that (i,j) maps
69 * to (m(i),j), with (m(i),j) identifying an element of the array.
70 * The bounds on j are taken from the size of the array.
72 * The mapping from i to (i,j) is stored in the "extension" field
73 * of the access.
75 * The dependences computed using these extended access mappings,
76 * will map a (possibly) extended source domain to a (possibly)
77 * extended sink domain. One or both of these domains need to
78 * be transformed back to the original domains using the inverse
79 * of the corresponding extensions.
81 static isl_map *extend_access(isl_map *map, na_pair *na)
83 pdg::array *array = na->access->array;
84 assert(isl_map_n_out(map) < array->dims.size());
85 unsigned s_dim = array->dims.size() - isl_map_n_out(map);
86 isl_id *array_id = NULL;
87 if (isl_map_has_tuple_id(map, isl_dim_out))
88 array_id = isl_map_get_tuple_id(map, isl_dim_out);
89 isl_space *dim = isl_map_get_space(map);
90 dim = isl_space_drop_dims(dim, isl_dim_in,
91 0, isl_space_dim(dim, isl_dim_in));
92 dim = isl_space_drop_dims(dim, isl_dim_out,
93 0, isl_space_dim(dim, isl_dim_out));
94 dim = isl_space_add_dims(dim, isl_dim_in, s_dim);
95 dim = isl_space_add_dims(dim, isl_dim_out, s_dim);
96 isl_basic_map *id = isl_basic_map_identity(isl_space_copy(dim));
97 isl_local_space *ls = isl_local_space_from_space(dim);
98 isl_int v;
99 isl_int_init(v);
100 for (int i = 0; i < s_dim; ++i) {
101 isl_constraint *c;
102 c = isl_inequality_alloc(isl_local_space_copy(ls));
103 isl_int_set_si(v, 1);
104 isl_constraint_set_coefficient(c, isl_dim_out, 0, v);
105 id = isl_basic_map_add_constraint(id, c);
106 c = isl_inequality_alloc(isl_local_space_copy(ls));
107 isl_int_set_si(v, -1);
108 isl_constraint_set_coefficient(c, isl_dim_out, 0, v);
109 isl_int_set_si(v, array->dims[isl_map_n_out(map)+i]-1);
110 isl_constraint_set_constant(c, v);
111 id = isl_basic_map_add_constraint(id, c);
113 isl_local_space_free(ls);
114 isl_int_clear(v);
115 map = isl_map_product(map, isl_map_from_basic_map(id));
116 map = isl_map_flatten_range(map);
117 if (array_id)
118 map = isl_map_set_tuple_id(map, isl_dim_out, array_id);
119 if (!na->access->extension) {
120 isl_map *ext = isl_map_copy(map);
121 ext = isl_set_unwrap(isl_map_domain(ext));
122 ext = isl_map_reverse(isl_map_domain_map(ext));
123 na->access->extension = new pdg::IslMap(ext);
125 if (!na->access->extended_map)
126 na->access->extended_map = new pdg::IslMap(isl_map_copy(map));
127 return map;
130 /* If access "access" contains any nested accesses, then the domain
131 * of the access relation contains extra dimensions corresponding to
132 * the values of the nested accesses.
133 * Add these extra dimensions, with ranges given by the value_bounds
134 * of the corresponding array to domain "dom".
135 * If a nested access array does not have value_bounds, then we assume
136 * an infinite interval.
138 static isl_set *append_nested_value_domains(isl_set *dom, pdg::access *access)
140 isl_ctx *ctx;
142 ctx = isl_set_get_ctx(dom);
143 for (int i = 0; i < access->nested.size(); ++i) {
144 pdg::call_or_access *coa = access->nested[i];
145 assert(coa->type == pdg::call_or_access::t_access);
146 pdg::access *nested = coa->access;
147 isl_set *bounds;
148 if (nested->array->value_bounds)
149 bounds = nested->array->value_bounds->get_isl_set(ctx);
150 else {
151 isl_space *dim = isl_set_get_space(dom);
152 dim = isl_space_drop_dims(dim, isl_dim_set,
153 0, isl_space_dim(dim, isl_dim_set));
154 dim = isl_space_add_dims(dim, isl_dim_set, 1);
155 bounds = isl_set_universe(dim);
157 dom = isl_set_product(dom, bounds);
159 return dom;
162 /* Combine constraints of the "pure" mapping with the constraints
163 * on the domain. If the range of the mapping is of a dimension
164 * that is lower than the dimension of the accessed array,
165 * we extend the dimension of both domain and range of the mapping
166 * with the missing dimension. The size of domain and range
167 * in these dimensions is set to the extent of the array in the
168 * corresponding missing dimension. Each point in the original
169 * domain is therefore expanded to a hyperrectangle and each point
170 * in this hyperrectangle is mapped onto a single point in the array.
172 * If node->source is a wrapped map, then the iteration domain
173 * is the domain of this map.
175 static isl_map *convert_access(na_pair *na)
177 isl_map *map = na->access->map->get_isl_map();
178 isl_set *dom = na->node->source->get_isl_set();
180 if (isl_set_is_wrapping(dom)) {
181 dom = isl_map_domain(isl_set_unwrap(dom));
182 dom = isl_set_coalesce(dom);
185 dom = append_nested_value_domains(dom, na->access);
186 if (isl_map_n_in(map) != isl_set_dim(dom, isl_dim_set))
187 assert(0);
188 map = isl_map_intersect_domain(map, dom);
189 if (isl_map_n_out(map) != na->access->array->dims.size())
190 map = extend_access(map, na);
191 return map;
194 typedef std::map<na_pair *, isl_map *> na_pair2map;
196 struct add_dep_info {
197 PDG *pdg;
198 pdg::array *a;
199 type t;
200 enum pdg::dependence::type dtype;
201 /* The sink. */
202 na_pair *read_na_pair;
203 /* The comparison routine that was used during
204 * the dependence analysis.
206 isl_access_level_before precedes_level;
207 /* Cache of memory based dependence relations.
208 * The key of the map refers to the write.
210 na_pair2map mem_dep;
212 /* Potential sources that are actually used. */
213 std::set<na_pair *> used;
215 __isl_give isl_map *get_mem_dep(na_pair *write_na);
216 void clear_mem_dep();
217 void set_read_na(na_pair *read_na);
219 ~add_dep_info();
222 /* Create an id
224 * __last_<stmt>_<access_nr>_valid
226 * corresponding to "na", with "na" attached as user pointer.
228 static __isl_give isl_id *valid_bit_id(isl_ctx *ctx, na_pair *na)
230 char name[60];
232 snprintf(name, sizeof(name), "__last_%s_%d_valid",
233 na->node->name->s.c_str(), na->access->nr);
234 return isl_id_alloc(ctx, name, na);
237 /* Project out all the dimensions of the given type from "map" except "pos".
239 static __isl_give isl_map *project_on(__isl_take isl_map *map,
240 enum isl_dim_type type, unsigned pos)
242 unsigned n = isl_map_dim(map, type);
244 map = isl_map_project_out(map, type, pos + 1, n - (pos + 1));
245 map = isl_map_project_out(map, type, 0, pos);
247 return map;
250 /* Does output dimension "pos" have a fixed value in terms of the
251 * input dimensions (and parameters)?
253 static int has_fixed_value(__isl_keep isl_map *map, int pos)
255 int sv;
257 map = isl_map_copy(map);
258 map = project_on(map, isl_dim_out, pos);
259 sv = isl_map_is_single_valued(map);
260 isl_map_free(map);
262 return sv;
265 /* Add parameters to "set" identifying the last iteration of the access
266 * identified by "na".
268 * In particular, we add a parameter
270 * __last_<stmt>_<access_nr>_valid = 1
272 * and parameters
274 * __last_<stmt>_<access_nr>_<i> = it_<i>
276 * with i ranging over the iterators that are affected by the filters,
277 * except those that have a fixed value according to the memory based
278 * dependence.
279 * "na" is attached to the first parameter, so that it can be recovered
280 * in refine_controls(). If the set already references some of these
281 * parameters, then we don't add the parameter again, but instead
282 * simply add the corresponding constraint.
284 static __isl_give isl_set *add_parametrization(__isl_take isl_set *set,
285 na_pair *na, add_dep_info *info)
287 int pos;
288 isl_ctx *ctx;
289 isl_id *id;
290 char name[60];
291 int depth;
292 isl_map *mem;
294 depth = na->node->get_filter_depth();
295 mem = info->get_mem_dep(na);
296 mem = isl_map_reverse(mem);
298 ctx = isl_set_get_ctx(set);
299 id = valid_bit_id(ctx, na);
300 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
301 if (pos < 0) {
302 pos = isl_set_dim(set, isl_dim_param);
303 set = isl_set_add_dims(set, isl_dim_param, 1);
304 set = isl_set_set_dim_id(set, isl_dim_param, pos, id);
305 } else
306 isl_id_free(id);
307 set = isl_set_fix_si(set, isl_dim_param, pos, 1);
309 for (int i = 0; i < depth; ++i) {
310 if (has_fixed_value(mem, i))
311 continue;
313 snprintf(name, sizeof(name), "__last_%s_%d_%d",
314 na->node->name->s.c_str(), na->access->nr, i);
316 pos = isl_set_find_dim_by_name(set, isl_dim_param, name);
317 if (pos < 0) {
318 id = isl_id_alloc(ctx, name, NULL);
319 pos = isl_set_dim(set, isl_dim_param);
320 set = isl_set_add_dims(set, isl_dim_param, 1);
321 set = isl_set_set_dim_id(set, isl_dim_param, pos, id);
324 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
327 isl_map_free(mem);
328 return set;
331 /* Is the i-th parameter of "map" a control, i.e., a parameter
332 * introduced by add_parametrization()?
333 * In particular, is the parameter of the form __last_*?
335 static bool is_control(__isl_keep isl_map *map, int i)
337 const char *name;
338 const char *prefix = "__last_";
339 size_t prefix_len = strlen(prefix);
341 if (!isl_map_has_dim_id(map, isl_dim_param, i))
342 return false;
343 name = isl_map_get_dim_name(map, isl_dim_param, i);
344 return strncmp(name, prefix, prefix_len) == 0;
347 /* Is the i-th parameter of "set" a control, i.e., a parameter
348 * introduced by add_parametrization()?
349 * In particular, is the parameter of the form __last_*?
351 static bool is_control(__isl_keep isl_set *set, int i)
353 const char *name;
354 const char *prefix = "__last_";
355 size_t prefix_len = strlen(prefix);
357 if (!isl_set_has_dim_id(set, isl_dim_param, i))
358 return false;
359 name = isl_set_get_dim_name(set, isl_dim_param, i);
360 return strncmp(name, prefix, prefix_len) == 0;
363 /* Remove all controls that are redundant, i.e., that do not appear
364 * in any of the constraints.
365 * Set *has_controls to true if there are any controls that are not redundant.
367 static __isl_give isl_map *remove_redundant_controls(__isl_take isl_map *dep,
368 bool *has_controls)
370 int i;
371 int n_param;
373 *has_controls = false;
375 n_param = isl_map_dim(dep, isl_dim_param);
376 for (i = n_param - 1; i >= 0; --i) {
377 if (!is_control(dep, i))
378 continue;
379 if (isl_map_involves_dims(dep, isl_dim_param, i, 1))
380 *has_controls = true;
381 else
382 dep = isl_map_project_out(dep, isl_dim_param, i, 1);
385 return dep;
388 /* Rename controls of "dep" from
390 * __last_<source_stmt>_<source_acc_nr>_*
392 * to
394 * __last_<source_stmt>_<source_acc_nr>_<sink_stmt>_<sink_acc_nr>_*
396 * "na" represents the sink.
398 static __isl_give isl_map *rename_controls(__isl_take isl_map *dep, na_pair *na)
400 char buf[100];
401 int n_param;
402 const char *name;
403 const char *underscore;
405 n_param = isl_map_dim(dep, isl_dim_param);
406 for (int i = 0; i < n_param; ++i) {
407 int len;
408 if (!is_control(dep, i))
409 continue;
410 name = isl_map_get_dim_name(dep, isl_dim_param, i);
411 underscore = strrchr(name, '_');
412 assert(underscore);
413 len = underscore + 1 - name;
414 memcpy(buf, name, len);
415 snprintf(buf + len, sizeof(buf) - len, "%s_%d_%s",
416 na->node->name->s.c_str(), na->access->nr, name + len);
417 dep = isl_map_set_dim_name(dep, isl_dim_param, i, buf);
420 return dep;
423 extern "C" {
424 static int extract_dep(__isl_take isl_map *dep, int must,
425 void *dep_user, void *user);
428 /* Extract the single dependence relation from the result of
429 * dataflow analyis and assign it to *user.
431 static int extract_dep(__isl_take isl_map *dep, int must, void *dep_user,
432 void *user)
434 isl_map **dep_p = (isl_map **) user;
435 assert(!*dep_p);
436 *dep_p = dep;
437 return 0;
440 /* Return the memory based dependence relation from write_na
441 * to read_na_pair. If the "projected_map"
442 * fields are not NULL, then use the "projected_map"
443 * instead of the "map" of write_na and this->read_na_pair.
445 __isl_give isl_map *add_dep_info::get_mem_dep(na_pair *write_na)
447 isl_access_info *acc;
448 isl_flow *deps;
449 isl_map *read_map, *write_map;
450 isl_map *dep = NULL;
452 if (mem_dep.find(write_na) != mem_dep.end())
453 return isl_map_copy(mem_dep[write_na]);
455 if (read_na_pair->projected_map)
456 read_map = isl_map_copy(read_na_pair->projected_map);
457 else
458 read_map = isl_map_copy(read_na_pair->map);
459 acc = isl_access_info_alloc(read_map, read_na_pair, precedes_level, 1);
460 if (write_na->projected_map)
461 write_map = isl_map_copy(write_na->projected_map);
462 else
463 write_map = isl_map_copy(write_na->map);
464 acc = isl_access_info_add_source(acc, write_map, 0, write_na);
465 deps = isl_access_info_compute_flow(acc);
466 isl_flow_foreach(deps, &extract_dep, &dep);
467 isl_flow_free(deps);
469 mem_dep[write_na] = isl_map_copy(dep);
471 return dep;
474 /* Clear the cache of memory based dependence relations.
476 void add_dep_info::clear_mem_dep()
478 na_pair2map::iterator it;
480 for (it = mem_dep.begin(); it != mem_dep.end(); ++it)
481 isl_map_free(it->second);
482 mem_dep.clear();
485 /* Set read_na_pair to read_na.
487 * If the cache of memory based dependence relations contains any
488 * elements then they refer to a different read, so we need to clear
489 * the cache.
491 * We also clear the set of used potential sources.
493 void add_dep_info::set_read_na(na_pair *read_na)
495 used.clear();
496 clear_mem_dep();
497 read_na_pair = read_na;
500 add_dep_info::~add_dep_info()
502 clear_mem_dep();
505 /* Is parameter "i" of "space" such that it is called __last_*
506 * and has a non-NULL user field?
507 * In practice, those are the parameters __last_*_valid, created
508 * in add_parametrization().
510 static bool is_valid_bit(__isl_keep isl_space *space, int i)
512 const char *prefix = "__last_";
513 size_t prefix_len = strlen(prefix);
514 const char *name;
515 isl_id *id;
516 na_pair *write_na;
518 if (!isl_space_has_dim_id(space, isl_dim_param, i))
519 return false;
520 name = isl_space_get_dim_name(space, isl_dim_param, i);
521 if (strncmp(name, prefix, prefix_len))
522 return false;
523 id = isl_space_get_dim_id(space, isl_dim_param, i);
524 write_na = (na_pair *) isl_id_get_user(id);
525 isl_id_free(id);
526 if (!write_na)
527 return false;
529 return true;
532 /* Assuming "coa" is a (read) access, return the array being
533 * accessed.
535 static pdg::array *get_filter_array(pdg::call_or_access *coa)
537 assert(coa->type == pdg::call_or_access::t_access);
538 return coa->access->array;
541 /* Given two filter access relations, return a mapping between the domain
542 * elements of these access relations such that they access "the same filter".
543 * In particular, any pair of elements in the returned relation
544 * accesses at least one element in common, but if subset1 is set,
545 * then the set of elements accessed by the first is a subset of the
546 * set of elements accessed by the second. Similarly, if subset2 is set,
547 * then the set of elements accessed by the second is a subset of the
548 * set of elements accessed by the first. If both are set, then we further
549 * impose that both should access exactly one element.
551 * Call the given maps A and B.
553 * If the range spaces of the two maps are different, then the filter
554 * is obviously never the same.
556 * A relation between domains elements of A and B that access at least
557 * one element in common can be obtained as
559 * A . B^-1
561 * To ensure that all elements accessed through A form a subset of
562 * the elements accessed through B, we need to impose that
564 * \forall j : i -> j \in A => j -> k \in B
566 * In other words
568 * \not \exists j : i -> j \in A and j -> k \not\in B
570 * We therefore need to remove the elements i -> k that belong to the relation
572 * A . (\bar{B})^-1
574 * where \bar{B} is the complement of B.
576 * Note that if A is single-valued, then we don't need to perform
577 * this computation. Each iteration accesses only a single element
578 * and we already know that at least one element is accessed in common,
579 * so this single element must be a subset of the elements accessed
580 * through B.
582 * Ensuring that all elements accessed through B form a subset of
583 * the elements accessed through A is handled in a similar way.
585 * To remove those iterations that access more that one element,
586 * let A be of the form { S[..] -> F[..] }. We first construct the
587 * mapping { S[..] -> [F[..] -> F[..]] } and remove from the range
588 * of this mapping identical pairs of F indices. What is left
589 * is a mapping from iterations to pairs of different F indices.
590 * Any element in the domain of this mapping accesses more than one
591 * element and is therefore removed.
593 static __isl_give isl_map *compute_common_filter(__isl_keep isl_map *map1,
594 bool subset1, __isl_keep isl_map *map2, bool subset2)
596 isl_space *space1, *space2;
597 isl_map *reverse, *common, *bad;
598 int equal;
600 space1 = isl_space_range(isl_map_get_space(map1));
601 space2 = isl_space_range(isl_map_get_space(map2));
602 equal = isl_space_is_equal(space1, space2);
603 isl_space_free(space1);
604 isl_space_free(space2);
605 if (!equal) {
606 space1 = isl_space_domain(isl_map_get_space(map1));
607 space2 = isl_space_domain(isl_map_get_space(map2));
608 space1 = isl_space_map_from_domain_and_range(space1, space2);
609 return isl_map_empty(space1);
612 reverse = isl_map_reverse(isl_map_copy(map2));
613 common = isl_map_apply_range(isl_map_copy(map1), isl_map_copy(reverse));
614 if (subset1 && !subset2 && !isl_map_plain_is_single_valued(map1)) {
615 bad = isl_map_apply_range(isl_map_copy(map1),
616 isl_map_complement(isl_map_copy(reverse)));
617 common = isl_map_subtract(common, bad);
619 if (subset2 && !subset1 && !isl_map_plain_is_single_valued(map2)) {
620 bad = isl_map_apply_range(
621 isl_map_complement(isl_map_copy(map1)),
622 isl_map_copy(reverse));
623 common = isl_map_subtract(common, bad);
625 if (subset1 && subset2 && !isl_map_plain_is_single_valued(map1)) {
626 bad = isl_map_range_product(isl_map_copy(map1),
627 isl_map_copy(map1));
628 space1 = isl_space_range(isl_map_get_space(bad));
629 space1 = isl_space_unwrap(space1);
630 bad = isl_map_subtract_range(bad,
631 isl_map_wrap(isl_map_universe(space1)));
632 common = isl_map_subtract_domain(common, isl_map_domain(bad));
634 if (subset1 && subset2 && !isl_map_plain_is_single_valued(map2)) {
635 bad = isl_map_range_product(isl_map_copy(map2),
636 isl_map_copy(map2));
637 space1 = isl_space_range(isl_map_get_space(bad));
638 space1 = isl_space_unwrap(space1);
639 bad = isl_map_subtract_range(bad,
640 isl_map_wrap(isl_map_universe(space1)));
641 common = isl_map_subtract_range(common, isl_map_domain(bad));
643 isl_map_free(reverse);
645 return common;
648 /* Assuming "coa" is a (read) access, construct a map from the domain
649 * of the access relation to the access relation of the corresponding
650 * write. If we are unable to determine the corresponding write, then
651 * return the empty map.
653 static __isl_give isl_map *extract_access_map(pdg::call_or_access *coa)
655 assert(coa->type == pdg::call_or_access::t_access);
656 return coa->access->extract_access_map();
659 /* Return a set that contains all possible filter values,
660 * where the possible values for a given filter is either as specified
661 * by the value_bounds property of the corresponding array or the universe.
663 static __isl_give isl_set *compute_filter_bounds(pdg::node *node)
665 isl_ctx *ctx;
666 isl_set *bounds;
668 ctx = isl_set_get_ctx(node->source->set);
670 bounds = isl_set_universe(isl_space_set_alloc(ctx, 0, 0));
671 for (int i = 0; i < node->filters.size(); ++i) {
672 isl_set *bnd;
673 pdg::array *array;
674 pdg::call_or_access *coa = node->filters[i];
675 assert(coa->type == pdg::call_or_access::t_access);
676 array = coa->access->array;
677 if (array->value_bounds)
678 bnd = array->value_bounds->get_isl_set();
679 else
680 bnd = isl_set_universe(isl_space_set_alloc(ctx, 0, 1));
681 bounds = isl_set_flat_product(bounds, bnd);
684 return bounds;
687 /* Return either the filter values themselves or their complement,
688 * taken with respect to the bounds on the filter values.
690 static __isl_give isl_map *compute_filter_values(pdg::node *node,
691 bool complement)
693 isl_set *bounds;
694 isl_map *value;
695 isl_map *res;
697 value = isl_set_unwrap(node->source->get_isl_set());
698 if (!complement)
699 return value;
701 bounds = compute_filter_bounds(node);
702 res = isl_map_from_domain_and_range(
703 isl_map_domain(isl_map_copy(value)), bounds);
704 res = isl_map_subtract(res, value);
706 return res;
709 /* Return the set of source iterations of "na" either at the last
710 * iteration (if valid is set) or after the last iteration
711 * (if valid is not set). "id" represents the control variable
712 * corresponding to the valid bit (__last_<na>_valid).
714 * In particlar, if valid is set, we return the set
716 * { S[i] : i = __last_<na> and __last_<na>_valid >= 1 }
718 * If valid is not set, we return the set
720 * { S[i] : (i >> __last_<na> and __last_<na>_valid >= 1) or
721 * __last_<na>_valid <= 0 }
723 * That is, the iterations after the last if there is a last iteration
724 * or just any iteration if there is no last iteration.
726 * The lexicographic order i >> __last_<na> is imposed on the loop iterators
727 * that are affected by any filters.
729 static __isl_give isl_set *source_iterations(na_pair *na,
730 __isl_keep isl_id *id, bool valid, add_dep_info *info)
732 isl_space *space;
733 isl_set *set, *invalid;
734 isl_map *map_after;
735 int pos;
736 int depth;
738 space = isl_set_get_space(na->node->source->set);
739 space = isl_space_domain(isl_space_unwrap(space));
741 set = isl_set_universe(space);
742 set = add_parametrization(set, na, info);
744 if (valid)
745 return set;
747 depth = na->node->get_filter_depth();
749 space = isl_space_map_from_set(isl_set_get_space(set));
750 map_after = isl_map_lex_lt_first(space, depth);
751 map_after = isl_map_intersect_domain(map_after, set);
752 set = isl_map_range(map_after);
754 invalid = isl_set_universe(isl_set_get_space(set));
755 pos = isl_set_find_dim_by_id(invalid, isl_dim_param, id);
756 assert(pos >= 0);
757 invalid = isl_set_upper_bound_si(invalid, isl_dim_param, pos, 0);
758 set = isl_set_union(set, invalid);
760 return set;
763 /* Look for a matching between the filters of node1 and those of node2.
764 * That is look for pairs of filters of the two nodes that are "the same".
765 * Return true if any such matching can be found. The correspondence between
766 * the filters is returned in *same_value_p, while the pairs of iterations
767 * where the filters are the same is returned in *same_filter_p.
769 * Two filter accesses are considered "the same" if they access at least
770 * one element in common. Moreover, if valid1 is false then the set
771 * of elements accessed by an element from node1 should be a subset
772 * of the set of elements accessed by the corresponding element from node2.
773 * Similarly for valid2.
775 * We perform a greedy search, checking if two filters could possibly
776 * match given the matchings we have performed before and updating
777 * the matching if it is indeed possible.
779 * Note that this function only computes one of the possibly many matchings.
781 static bool compute_matching(pdg::node *node1, bool valid1,
782 pdg::node *node2, bool valid2, __isl_give isl_map **same_filter_p,
783 __isl_give isl_map **same_value_p)
785 bool any = false;
786 isl_space *space1, *space2;
787 isl_map *same_filter;
788 isl_map *same_value;
790 space1 = isl_space_unwrap(isl_set_get_space(node1->source->set));
791 space2 = isl_space_unwrap(isl_set_get_space(node2->source->set));
792 space1 = isl_space_product(space1, space2);
793 space2 = isl_space_unwrap(isl_space_range(isl_space_copy(space1)));
794 space1 = isl_space_unwrap(isl_space_domain(space1));
796 same_filter = isl_map_universe(space1);
797 same_value = isl_map_universe(space2);
799 for (int i = 0; i < node1->filters.size(); ++i) {
800 isl_map *map_i;
801 pdg::call_or_access *filter_i = node1->filters[i];
802 pdg::array *array_i = get_filter_array(filter_i);
804 map_i = extract_access_map(node1->filters[i]);
805 if (isl_map_is_empty(map_i)) {
806 isl_map_free(map_i);
807 continue;
810 for (int j = 0; j < node2->filters.size(); ++j) {
811 pdg::call_or_access *filter_j;
812 filter_j = node2->filters[j];
813 pdg::array *array_j = get_filter_array(filter_j);
814 isl_map *map_j;
815 isl_map *same_filter_ij;
817 if (array_i != array_j)
818 continue;
820 map_j = extract_access_map(node2->filters[j]);
821 same_filter_ij = compute_common_filter(map_i, !valid1,
822 map_j, !valid2);
823 same_filter_ij = isl_map_intersect(same_filter_ij,
824 isl_map_copy(same_filter));
825 if (isl_map_is_empty(same_filter_ij))
826 isl_map_free(same_filter_ij);
827 else {
828 any = true;
829 isl_map_free(same_filter);
830 same_filter = same_filter_ij;
831 same_value = isl_map_equate(same_value,
832 isl_dim_in, i,
833 isl_dim_out, j);
835 isl_map_free(map_j);
838 isl_map_free(map_i);
841 if (any) {
842 *same_value_p = same_value;
843 *same_filter_p = same_filter;
844 } else {
845 isl_map_free(same_value);
846 isl_map_free(same_filter);
847 *same_value_p = NULL;
848 *same_filter_p = NULL;
851 return any;
854 /* Given a set of sink iterations "sink", mappings "map1" and "map2"
855 * from two potential sources to this sink,
856 * the possible filter values "value1" and "value2" at those
857 * potential sources, a relation "same_filter" between the two
858 * potential sources expressing when some filters of the two
859 * potential sources are the same and the correponding matching
860 * "same_value" between the filter values,
861 * remove those elements from the sink that have
862 * corresponding pairs of potential source iterations that should
863 * have the same filter values but do not.
865 * Let us call the sink S, the potential sources A and B and the
866 * corresponding filters F and G.
868 * We start from the mappings A[..] -> S[..] and B[..] -> S[..],
869 * combine them into
871 * S[..] -> [A[..] -> B[..]]
873 * and intersect the range with the condition "same_filter" on A and B,
874 * resulting in a mapping from sink iterations to pairs of potential
875 * source iterations that should have the same filter values
876 * (as specified by "same_value").
878 * We subtract from the range of this mapping those pairs of
879 * potential source iterations that actually have the same filter values.
880 * The result is a mapping from sink iterations to pairs of potential
881 * source iterations that should have the same filter values but do not.
883 * The mapping between potential source iterations that have the
884 * same filter values is obtained by combining the mappings
885 * A[..] -> F[..] and B[..] -> G[..] into
887 * [A[..] -> B[..]] -> [F[..] -> G[..]]
889 * intersecting the range with "same_value" and then computing the domain.
891 static __isl_give isl_set *remove_conflict(__isl_take isl_set *sink,
892 __isl_take isl_map *map1, __isl_take isl_map *value1,
893 __isl_take isl_map *map2, __isl_take isl_map *value2,
894 __isl_take isl_map *same_filter, __isl_take isl_map *same_value)
896 isl_map *value, *conflict;
897 isl_set *conflict_set;
899 conflict = isl_map_domain_product(map1, map2);
900 conflict = isl_map_reverse(conflict);
902 conflict = isl_map_intersect_range(conflict, isl_map_wrap(same_filter));
904 value = isl_map_product(value1, value2);
905 value = isl_map_intersect_range(value, isl_map_wrap(same_value));
906 conflict = isl_map_subtract_range(conflict, isl_map_domain(value));
908 conflict_set = isl_map_domain(conflict);
910 sink = isl_set_subtract(sink, conflict_set);
912 return sink;
915 /* Remove inconsistencies from the set of sink iterations "sink"
916 * based on two potential sources identified by "id1" and "id2",
917 * in particular, on either the last iteration where the filters hold
918 * (if valid? is set) or on later iterations (if valid? is not set).
920 * Let us first consider the case where both "valid1" and "valid2" are set.
921 * If the last iterations of the corresponding sources access the same
922 * filters, then these filters should have the same value.
923 * If a filter access accesses more than one element, then these elements
924 * should all have the same value. It is therefore sufficient for the
925 * two last iterations to access at least one element in common for there
926 * to be a requirement that the corresponding values should be the same.
927 * We therefore obtain the filter values, the mappings from the sink
928 * to the last iterations, a matching between the
929 * the filters of the corresponding sources and remove conflicts from "dep".
931 * If one or both of the valid bits are not set, then we need to make
932 * some changes. First the inconsistencies now do not arise from
933 * the filter values at the last iteration, but from the filter values
934 * lying _outside_ of the possible values for all iterations _after_
935 * the "last" (i.e., the last iteration satisfying the filter constraints).
936 * In case there is no last iteration, then the filter values should
937 * lie outside of the possible values for any potential source iteration.
938 * Note however, that it if the filter access relation accesses several
939 * elements, then it is sufficient for one of those to have a value
940 * outside of the possible values. We can therefore only consider
941 * any inconsistencies for those cases where the set of accessed elements
942 * forms a subset of the set of accessed elements through the other potential
943 * source. If valid1 is not set, but valid2 is set, then we consider
944 * those pairs of potential source iterations where the first accesses
945 * a subset of the second and we impose that at least one of those
946 * accessed elements has a valid outside the possible values.
947 * Since those accessed elements form a subset of the elements accessed
948 * by the other potential source, there is at least one element that
949 * has a value outside of the posssible values on the first potential source
950 * and a value belonging to the posssible values on the second potential source.
951 * We can therefore impose that this value should exist.
953 * If both valid1 and valid2 are not set, then we can only
954 * impose a constraint on those pairs of iterations that access the same
955 * single element. We then know that the value of this single element
956 * accessed by both potential sources should lie outside of the possible
957 * values on both sides.
959 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
960 add_dep_info *info, __isl_keep isl_id *id1, bool valid1,
961 __isl_keep isl_id *id2, bool valid2)
963 na_pair *write1_na, *write2_na;
964 isl_set *source;
965 isl_map *value1, *value2;
966 isl_map *same_filter;
967 isl_map *same_value;
968 isl_map *mem1, *mem2;
970 write1_na = (na_pair *) isl_id_get_user(id1);
971 write2_na = (na_pair *) isl_id_get_user(id2);
973 if (!compute_matching(write1_na->node, valid1, write2_na->node, valid2,
974 &same_filter, &same_value))
975 return sink;
977 value1 = compute_filter_values(write1_na->node, !valid1);
978 value2 = compute_filter_values(write2_na->node, !valid2);
980 mem1 = info->get_mem_dep(write1_na);
981 source = source_iterations(write1_na, id1, valid1, info);
982 mem1 = isl_map_intersect_domain(mem1, source);
984 mem2 = info->get_mem_dep(write2_na);
985 source = source_iterations(write2_na, id2, valid2, info);
986 mem2 = isl_map_intersect_domain(mem2, source);
988 sink = remove_conflict(sink, mem1, value1, mem2, value2,
989 same_filter, same_value);
991 return sink;
994 /* Remove inconsistencies from the set of sink iterations "sink"
995 * based on two potential sources identified by "id1" and "id2".
997 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
998 add_dep_info *info, __isl_keep isl_id *id1, __isl_keep isl_id *id2)
1000 sink = remove_inconsistencies(sink, info, id1, false, id2, false);
1001 sink = remove_inconsistencies(sink, info, id1, false, id2, true);
1002 sink = remove_inconsistencies(sink, info, id1, true, id2, false);
1003 sink = remove_inconsistencies(sink, info, id1, true, id2, true);
1004 return sink;
1007 /* Remove inconsistencies from the set of sink iterations "sink"
1008 * based on the potential source identified by "id",
1009 * in particular, on either the last iteration where the filters hold
1010 * (if valid is set) or on later iterations (if valid is not set).
1012 * This function is very similar to the remove_inconsistencies
1013 * function above that considers two potential sources instead
1014 * of the sink and one potential source. The main differences
1015 * are for the sink, the filters always hold and that the mapping
1016 * from sink iterations to sink iterations is computed in a different
1017 * (and fairly trivial) way.
1019 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
1020 add_dep_info *info, __isl_keep isl_id *id, bool valid)
1022 na_pair *read_na, *write_na;
1023 isl_set *after;
1024 isl_map *value1, *value2;
1025 isl_map *same_filter;
1026 isl_map *same_value;
1027 isl_map *id_map, *mem;
1029 read_na = info->read_na_pair;
1030 write_na = (na_pair *) isl_id_get_user(id);
1032 if (!compute_matching(read_na->node, true, write_na->node, valid,
1033 &same_filter, &same_value))
1034 return sink;
1036 value1 = compute_filter_values(read_na->node, false);
1037 value2 = compute_filter_values(write_na->node, !valid);
1039 id_map = isl_set_identity(isl_set_copy(sink));
1041 mem = info->get_mem_dep(write_na);
1042 after = source_iterations(write_na, id, valid, info);
1043 mem = isl_map_intersect_domain(mem, after);
1045 sink = remove_conflict(sink, id_map, value1, mem, value2,
1046 same_filter, same_value);
1048 return sink;
1051 /* Remove inconsistencies from the set of sink iterations "sink"
1052 * based on the potential source identified by "id".
1054 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
1055 add_dep_info *info, __isl_keep isl_id *id)
1057 sink = remove_inconsistencies(sink, info, id, false);
1058 sink = remove_inconsistencies(sink, info, id, true);
1059 return sink;
1062 /* Remove all parameters that were introduced by add_parametrization().
1064 static __isl_give isl_map *remove_all_controls(__isl_take isl_map *dep)
1066 int i;
1067 int n_param;
1068 const char *name;
1070 n_param = isl_map_dim(dep, isl_dim_param);
1071 for (i = n_param - 1; i >= 0; --i) {
1072 if (!is_control(dep, i))
1073 continue;
1074 dep = isl_map_project_out(dep, isl_dim_param, i, 1);
1076 dep = isl_map_coalesce(dep);
1078 return dep;
1081 /* Remove all parameters that were introduced by add_parametrization().
1083 static __isl_give isl_set *remove_all_controls(__isl_take isl_set *set)
1085 int i;
1086 int n_param;
1087 const char *name;
1089 n_param = isl_set_dim(set, isl_dim_param);
1090 for (i = n_param - 1; i >= 0; --i) {
1091 if (!is_control(set, i))
1092 continue;
1093 set = isl_set_project_out(set, isl_dim_param, i, 1);
1095 set = isl_set_coalesce(set);
1097 return set;
1100 /* Simplify the constraints on the parameters introduced
1101 * in add_parametrization().
1102 * We first remove all those parameters that turn out not be needed.
1103 * If there are any of those parameters left, then we rename
1104 * the parameters to also include a reference to the sink.
1105 * The resulting relation is assigned to controlled_relation,
1106 * while the relation field is assigned the result of projecting out
1107 * all those parameters.
1109 static __isl_give isl_map *simplify_controls(__isl_take isl_map *dep,
1110 add_dep_info *info, bool *has_controls)
1112 bool hs;
1114 if (!has_controls)
1115 has_controls = &hs;
1116 dep = remove_redundant_controls(dep, has_controls);
1117 if (*has_controls)
1118 dep = rename_controls(dep, info->read_na_pair);
1120 return dep;
1123 /* Extract a single dependence from the result of dataflow analysis.
1125 * We first simplify the constraints on the parameters introduced
1126 * in add_parametrization().
1128 * If the dependence relation turns out to be empty, we simply return.
1129 * Otherwise, we create a corresponding pdg::dependence and keep track
1130 * of the fact that the potential source is actually used
1131 * so that we can remove any reference to potential sources that are
1132 * never used from the dependence relations.
1134 static int add_dep(__isl_take isl_map *dep, int must, void *dep_user, void *user)
1136 bool has_controls;
1137 na_pair *write_na = (na_pair *) dep_user;
1138 add_dep_info *info = (struct add_dep_info *)user;
1139 isl_ctx *ctx = info->pdg->get_isl_ctx();
1140 pdg::dependence *d;
1142 dep = isl_map_coalesce(dep);
1143 dep = simplify_controls(dep, info, &has_controls);
1144 if (isl_map_is_empty(dep)) {
1145 isl_map_free(dep);
1146 return 0;
1149 info->used.insert(write_na);
1151 d = new pdg::dependence;
1152 d->array = info->a;
1153 d->type = info->dtype;
1154 d->from = write_na->node;
1155 d->to = info->read_na_pair->node;
1156 d->from_access = write_na->access;
1157 d->to_access = info->read_na_pair->access;
1159 if (d->from_access->extension || d->to_access->extension)
1160 d->extended_relation =
1161 new pdg::IslMap(remove_all_controls(isl_map_copy(dep)));
1162 if (d->from_access->extension)
1163 dep = isl_map_apply_domain(dep,
1164 isl_map_reverse(
1165 d->from_access->extension->get_isl_map(ctx)));
1166 if (d->to_access->extension)
1167 dep = isl_map_apply_range(dep,
1168 isl_map_reverse(
1169 d->to_access->extension->get_isl_map(ctx)));
1170 if (has_controls)
1171 d->controlled_relation = new pdg::IslMap(isl_map_copy(dep));
1172 d->relation = new pdg::IslMap(remove_all_controls(isl_map_copy(dep)));
1173 info->pdg->dependences.push_back(d);
1174 isl_map_free(dep);
1175 return 0;
1178 /* This structure represents a set of filter index expressions
1179 * along with bounds on the correponding filter values.
1180 * The number of output dimensions in "value" is the same as
1181 * the number of elements in the "index" vector.
1183 struct da_filter {
1184 std::vector<isl_map *> index;
1185 isl_map *value;
1188 /* Construct a da_filter object representing the filters in
1189 * na->node and na->access.
1191 static struct da_filter *extract_filter(na_pair *na)
1193 da_filter *filter = new da_filter;
1194 isl_set *domain;
1195 pdg::node *node = na->node;
1196 pdg::access *access = na->access;
1198 domain = node->source->get_isl_set();
1199 if (isl_set_is_wrapping(domain))
1200 filter->value = isl_set_unwrap(domain);
1201 else
1202 filter->value = isl_map_from_domain(domain);
1204 for (int i = 0; i < node->filters.size(); ++i)
1205 filter->index.push_back(extract_access_map(node->filters[i]));
1207 if (access->nested.size() == 0)
1208 return filter;
1210 domain = isl_map_domain(access->map->get_isl_map());
1211 filter->value = isl_map_flat_range_product(filter->value,
1212 isl_set_unwrap(domain));
1214 for (int i = 0; i < access->nested.size(); ++i)
1215 filter->index.push_back(extract_access_map(access->nested[i]));
1217 return filter;
1220 static struct da_filter *da_filter_free(struct da_filter *filter)
1222 if (!filter)
1223 return NULL;
1224 for (int i = 0; i < filter->index.size(); ++i)
1225 isl_map_free(filter->index[i]);
1226 isl_map_free(filter->value);
1227 delete filter;
1228 return NULL;
1231 static void da_filter_dump(struct da_filter *filter)
1233 isl_printer *p;
1235 if (!filter)
1236 return;
1238 p = isl_printer_to_file(isl_map_get_ctx(filter->value), stderr);
1239 p = isl_printer_start_line(p);
1240 p = isl_printer_print_str(p, "value(");
1241 for (int i = 0; i < filter->index.size(); ++i) {
1242 if (i)
1243 p = isl_printer_print_str(p, ", ");
1244 p = isl_printer_print_map(p, filter->index[i]);
1246 p = isl_printer_print_str(p, ") in ");
1247 p = isl_printer_print_map(p, filter->value);
1248 p = isl_printer_end_line(p);
1250 isl_printer_free(p);
1253 /* Look for a filter index expression in "filter" that is identical
1254 * to "index". Return the index of this index expression if it is
1255 * found and the number of elements in filter->index otherwise.
1257 static int da_filter_find_exact_match(struct da_filter *filter,
1258 __isl_keep isl_map *index)
1260 for (int i = 0; i < filter->index.size(); ++i) {
1261 int equal;
1263 equal = isl_map_is_equal(filter->index[i], index);
1264 if (equal < 0)
1265 return -1;
1266 if (equal)
1267 return i;
1270 return filter->index.size();
1273 /* Add the index expression "index" to "filter" with an unconstrained
1274 * filter value. To ease debugging we set the name of the new filter
1275 * value dimension to that of the array being accessed by "index".
1277 static struct da_filter *da_filter_add(struct da_filter *filter,
1278 __isl_take isl_map *index)
1280 isl_id *id;
1281 isl_space *space;
1283 if (!filter || !index)
1284 goto error;
1286 filter->value = isl_map_add_dims(filter->value, isl_dim_out, 1);
1287 space = isl_space_range(isl_map_get_space(index));
1288 if (isl_space_is_wrapping(space))
1289 space = isl_space_range(isl_space_unwrap(space));
1290 id = isl_space_get_tuple_id(space, isl_dim_set);
1291 isl_space_free(space);
1292 filter->value = isl_map_set_dim_id(filter->value, isl_dim_out,
1293 filter->index.size(), id);
1294 if (!filter->value)
1295 goto error;
1296 filter->index.push_back(index);
1298 return filter;
1299 error:
1300 isl_map_free(index);
1301 da_filter_free(filter);
1302 return NULL;
1305 /* Intersect the set of possible filter values in "filter" with "value".
1307 static struct da_filter *da_filter_restrict(struct da_filter *filter,
1308 __isl_take isl_map *value)
1310 if (!filter || !value)
1311 goto error;
1313 filter->value = isl_map_intersect(filter->value, value);
1314 if (!filter->value)
1315 return da_filter_free(filter);
1317 return filter;
1318 error:
1319 isl_map_free(value);
1320 da_filter_free(filter);
1321 return NULL;
1324 /* Does "map" represent a total filter on "domain", i.e., one that is defined
1325 * on every element of "domain"?
1327 static int is_total_filter(__isl_keep isl_map *map, __isl_keep isl_set *domain)
1329 isl_set *map_domain;
1330 int total;
1332 map_domain = isl_map_domain(isl_map_copy(map));
1333 total = isl_set_is_subset(domain, map_domain);
1334 isl_set_free(map_domain);
1336 return total;
1339 /* Does "node" have any total filters?
1341 static int any_total_filter(pdg::node *node, __isl_keep isl_set *domain)
1343 for (int i = 0; i < node->filters.size(); ++i) {
1344 isl_map *map = extract_access_map(node->filters[i]);
1345 int total;
1347 total = is_total_filter(map, domain);
1348 isl_map_free(map);
1350 if (total)
1351 return total;
1354 return 0;
1357 /* Construct a mapping from the source iterations to all source filter values
1358 * that allow some corresponding sink iteration(s) (according to "source_map")
1359 * to be executed. In other words, if any sink iteration is executed,
1360 * then we know that the filters of the corresponding source iterations
1361 * satisfy the returned relation.
1363 * The "filter" input represents what is known about the filter
1364 * values at the sink.
1366 * The "source" domain of the source is a wrapped map,
1367 * mapping iteration vectors to filter values.
1368 * We first construct a relation between the sink filter values (available
1369 * in "filter") * and the source filter values. The purpose of this relation
1370 * is to find as much information about the source filter values
1371 * as possible. We can start with the value bounds on the arrays
1372 * accessed in the filters as they always hold.
1373 * Next, we loop over the source filters and check whether there
1374 * is any sink filter that covers the source filter.
1375 * In particular, for each source filter, we construct a map
1376 * from the source iteration domain to a wrapped access relation,
1377 * representing the write access relation that corresponds to
1378 * the filter read access. If we are unable to determine this
1379 * write access, then we continue with the next source filter.
1380 * Otherwise we combine the constructed map with the proto-dependence
1381 * (source_map) to obtain a mapping from sink iterations to
1382 * access relations such that there is some source iteration that
1383 * may be the source of the given sink iteration (based on source_map)
1384 * and that the filter value at this source iteration was written by
1385 * that access. If the result is a subset of the mapping from the
1386 * sink iterations to the corresponding write access relation for some filter,
1387 * then we know that any constraint on this filter value also applies
1388 * to the source filter value. We therefore introduce an equality
1389 * in our mapping from sink filter values to source filter values.
1391 * When we apply the mapping from sink filter values to source filter values
1392 * to the mapping from source iterations to sink filter values, we
1393 * obtain a mapping from sink iterations to source filter values
1394 * that represents what we know about the source filter values.
1395 * That is, for each sink iteration in the domain of this map, if this
1396 * sink iteration is executed, then the actual source filter values
1397 * are an element of the image of the sink iteration.
1398 * In other words, the sink iteration is only executed if the source
1399 * filter values are an element of the image.
1400 * Mapping this relation back to the source through the proto-dependence
1401 * source_map, we obtain a relation from source iterations to all source
1402 * filter values for which any sink iteration is executed.
1403 * In particular, for values of the filters outside this relation,
1404 * no corresponding (according to source_map) sink is executed.
1406 static __isl_give isl_map *known_filter_values(struct da_filter *filter,
1407 na_pair *source_na, __isl_keep isl_map *source_map)
1409 isl_space *space;
1410 isl_map *source_value, *sink_value;
1411 isl_map *filter_map;
1412 isl_set *bounds;
1414 sink_value = isl_map_copy(filter->value);
1416 space = isl_set_get_space(source_na->node->source->set);
1417 space = isl_space_range(isl_space_unwrap(space));
1418 space = isl_space_map_from_domain_and_range(
1419 isl_space_range(isl_map_get_space(sink_value)), space);
1420 filter_map = isl_map_universe(space);
1422 bounds = compute_filter_bounds(source_na->node);
1423 filter_map = isl_map_intersect_range(filter_map, bounds);
1425 for (int i = 0; i < source_na->node->filters.size(); ++i) {
1426 isl_map *map_i;
1427 map_i = extract_access_map(source_na->node->filters[i]);
1428 if (isl_map_is_empty(map_i)) {
1429 isl_map_free(map_i);
1430 continue;
1432 map_i = isl_map_apply_range(isl_map_copy(source_map), map_i);
1433 for (int j = 0; j < filter->index.size(); ++j) {
1434 if (isl_map_is_subset(map_i, filter->index[j]))
1435 filter_map = isl_map_equate(filter_map,
1436 isl_dim_in, j, isl_dim_out, i);
1438 isl_map_free(map_i);
1441 source_value = isl_map_apply_range(sink_value, filter_map);
1442 source_value = isl_map_apply_domain(source_value,
1443 isl_map_copy(source_map));
1444 source_value = isl_map_coalesce(source_value);
1446 return source_value;
1449 /* Compute a map between domain elements (i) of "map1" and range elements
1450 * of "map2" (j) such that all the images of i in "map1" map to j through
1451 * "map2" and such that there is at least one such image element.
1453 * In other words, the result contains those pairs of elements such that
1454 * map1(i) \cap map2^-1(j) is non-empty and map1(i) \subseteq map2^-1(j).
1456 * Equivalently, compute
1458 * (map1 . map2) \cap {i -> \cap_{k \in map1(i)} map2(k)}
1460 * If map1 is single valued, then we can do a simple join.
1462 static __isl_give isl_map *join_non_empty_subset(__isl_take isl_map *map1,
1463 __isl_take isl_map *map2)
1465 isl_map *res;
1467 if (isl_map_plain_is_single_valued(map1))
1468 return isl_map_apply_range(map1, map2);
1470 res = isl_map_apply_range(isl_map_copy(map1), isl_map_copy(map2));
1471 map2 = isl_map_complement(map2);
1472 map1 = isl_map_apply_range(map1, map2);
1473 res = isl_map_subtract(res, map1);
1475 return res;
1478 /* Add a new output dimension to "map" with constraints that are the
1479 * same as those on output dimension "pos".
1481 * Given map { [i] -> [j] }, we first and an extra dimension,
1483 * { [i] -> [j,*] }
1485 * extract out j_pos,
1487 * { [[i] -> [j_0,...,j_{pos-1},*,j_{pos+1},...,*]] -> [j_pos] }
1489 * create a copy
1491 * { [[i] -> [j_0,...,j_{pos-1},*,j_{pos+1},...,*]] -> [j_pos,j_pos'] }
1493 * and then move the dimensions back
1495 * { [i] -> [j,j_pos'] }
1497 static __isl_give isl_map *copy_dim(__isl_take isl_map *map, int pos)
1499 int pos_new;
1501 pos_new = isl_map_dim(map, isl_dim_out);
1502 pos += isl_map_dim(map, isl_dim_in);
1503 pos_new += isl_map_dim(map, isl_dim_in);
1504 map = isl_map_add_dims(map, isl_dim_out, 1);
1505 map = isl_map_from_domain(isl_map_wrap(map));
1506 map = isl_map_add_dims(map, isl_dim_out, 1);
1507 map = isl_map_equate(map, isl_dim_in, pos, isl_dim_out, 0);
1508 map = isl_map_eliminate(map, isl_dim_in, pos, 1);
1509 map = isl_map_range_product(map, isl_map_copy(map));
1510 map = isl_map_equate(map, isl_dim_in, pos, isl_dim_out, 0);
1511 map = isl_map_equate(map, isl_dim_in, pos_new, isl_dim_out, 1);
1512 map = isl_set_unwrap(isl_map_domain(map));
1514 return map;
1517 /* Given constraints on the filter values "filter" at the sink iterations
1518 * "sink", derive additional constraints from the filter values of source
1519 * node "source_na". In particular, consider the iterations of "source_na"
1520 * that have _not_ been executed based on the constraints of the corresponding
1521 * last iteration parameters in "sink" and what this implies about the
1522 * filter values at those iterations.
1524 * Essentially, we consider all pairs of sink iterations and filter
1525 * elements, together with the corresponding non-executed source iterations
1526 * and the possible values of those filters. We universally quantify
1527 * the non-executed source iterations so that we obtain the intersection
1528 * of the constraints on the filter values over all those source iterations
1529 * and then existentially quantify the filter elements to obtain constraints
1530 * that are valid for all filter elements.
1532 * In more details, the computation is performed as follows.
1534 * Compute a mapping from potential last iterations of the other source
1535 * to sink iterations, taking into account the contraints on
1536 * the last executed iterations encoded in the parameters of "sink",
1537 * but projecting out all parameters encoding last iterations from the result.
1538 * Include all earlier iterations of the other source, resulting in
1539 * a mapping with a domain that includes all potential iterations of the
1540 * other source.
1542 * Subtract these iterations from all possible iterations of the other
1543 * source for a given sink iteration, resulting in a mapping from
1544 * potential source iterations that are definitely not executed
1545 * to the corresponding sink iteration.
1547 * If this map is empty, then this means we can't find any iterations
1548 * of the other source that are certainly not executed and then we
1549 * can't derive any further information.
1550 * Otherwise, keep track of those sink iterations without any corresponding
1551 * non-executed other source iterations. We will lose these sink iterations
1552 * in subsequent computations, so we need to add them back in at the end.
1554 * Compute bounds on the filter values at the non executed iterations
1555 * based on what we know about filters at the sink and the fact that
1556 * the iterations are not executed, meaning that the filter values
1557 * do not satisfy the constraints that allow the iteration to be executed.
1558 * The result is a mapping T -> V.
1560 * Project out those dimensions that correspond to filters with
1561 * an access function that is not total, i.e., one that does not
1562 * access any element for some of the non-executed iterations.
1563 * If there are no total filters, then we can skip the rest of
1564 * the computation.
1566 * Construct a mapping [K -> F] -> T, with K the sink iterations,
1567 * T the corresponding non-executed iterations of the other source and
1568 * F the filters accessed at those iterations.
1570 * Combine the above two mappings into a mapping [K -> F] -> V
1571 * such that the set of possible filter values (V) is the intersection
1572 * over all iterations of the other source that access the filter,
1573 * and such that there is at least one such iteration.
1574 * In other words, ensure that [K -> F] -> T is a non-empty subset of V -> T.
1575 * We require a non-empty subset to ensure that the domain of
1576 * [K -> F] -> V is equal to the result of composing K -> T with T -> F.
1577 * Projecting out F from [K -> F] -> V, we obtain a map K -> V that is
1578 * the union of all possible values of the filters K -> F, i.e.,
1579 * the constraints that the values of K -> F satisfy.
1580 * If we didn't impose non-emptiness above, then the domain of [K -> F] -> V
1581 * would also include pairs that we are not interested in, related to
1582 * arbitrary values. Projecting out F would then also lead to arbitrary
1583 * values.
1585 * Compose the mapping K -> T with the index expressions, pulling them
1586 * back to the sink.
1587 * For each of these pulled back index expressions, we check if it
1588 * is equal to one of the sink filter index expressions. If not, we
1589 * add it to the sink filter index expressions.
1590 * In both cases, we keep track of the fact that this sink filter
1591 * should have a value that satisfies the constraints in K -> V.
1592 * We further check if there is any sink filter index expression
1593 * that is a (strict) subset of the pulled back index expression.
1594 * The value of any such sink filter should also satisfy those
1595 * constraints, so we duplicate the filter value in K -> V.
1597 * Finally, we intersect the possible filter values with the constraints
1598 * obtained above on the affected sink iterations and a universe range
1599 * on the unaffected sink iterations.
1601 static struct da_filter *include_other_source(struct da_filter *filter,
1602 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
1604 isl_space *space;
1605 isl_set *source_domain;
1606 isl_map *mem;
1607 isl_map *may_run, *not_run;
1608 isl_map *source_value;
1609 std::vector<isl_map *> index;
1610 isl_map *index_product;
1611 isl_map *map;
1612 isl_map *filter_map;
1613 isl_set *unaffected_sink;
1614 isl_map *unaffected_value;
1615 isl_set *domain;
1617 if (source_na->node->filters.size() == 0)
1618 return filter;
1620 space = isl_set_get_space(source_na->node->source->set);
1621 space = isl_space_domain(isl_space_unwrap(space));
1622 source_domain = isl_set_universe(space);
1623 source_domain = add_parametrization(source_domain, source_na, info);
1624 may_run = isl_map_from_domain_and_range(source_domain,
1625 isl_set_copy(sink));
1627 may_run = remove_all_controls(may_run);
1628 mem = info->get_mem_dep(source_na);
1629 space = isl_space_domain(isl_map_get_space(may_run));
1630 may_run = isl_map_apply_domain(may_run, isl_map_lex_ge(space));
1631 not_run = isl_map_subtract(mem, may_run);
1633 domain = isl_map_domain(isl_map_copy(not_run));
1635 if (isl_map_is_empty(not_run) ||
1636 !any_total_filter(source_na->node, domain)) {
1637 isl_set_free(domain);
1638 isl_map_free(not_run);
1639 return filter;
1642 not_run = isl_map_reverse(not_run);
1643 source_value = known_filter_values(filter, source_na, not_run);
1644 source_value = isl_map_subtract(source_value,
1645 isl_set_unwrap(source_na->node->source->get_isl_set()));
1646 unaffected_sink = isl_set_copy(sink);
1647 unaffected_sink = remove_all_controls(unaffected_sink);
1648 unaffected_sink = isl_set_subtract(unaffected_sink,
1649 isl_map_domain(isl_map_copy(not_run)));
1651 for (int i = 0; i < source_na->node->filters.size(); ++i) {
1652 isl_map *map = extract_access_map(source_na->node->filters[i]);
1653 int sv;
1655 sv = is_total_filter(map, domain);
1656 if (sv) {
1657 index.push_back(map);
1658 } else {
1659 isl_map_free(map);
1660 source_value = isl_map_project_out(source_value,
1661 isl_dim_out, index.size(), 1);
1665 index_product = isl_map_copy(index[0]);
1666 for (int i = 1; i < index.size(); ++i)
1667 index_product = isl_map_range_product(index_product,
1668 isl_map_copy(index[1]));
1669 index_product = isl_map_reverse(index_product);
1670 index_product = isl_map_domain_product(isl_map_copy(not_run),
1671 index_product);
1673 source_value = join_non_empty_subset(index_product, source_value);
1674 space = isl_space_domain(isl_map_get_space(source_value));
1675 map = isl_map_domain_map(isl_map_universe(isl_space_unwrap(space)));
1676 source_value = isl_map_apply_domain(source_value, map);
1678 for (int i = 0; i < index.size(); ++i)
1679 index[i] = isl_map_apply_range(isl_map_copy(not_run), index[i]);
1681 space = isl_space_map_from_domain_and_range(
1682 isl_space_range(isl_map_get_space(source_value)),
1683 isl_space_range(isl_map_get_space(filter->value)));
1684 filter_map = isl_map_universe(space);
1686 for (int i = 0; i < index.size(); ++i) {
1687 int exact = da_filter_find_exact_match(filter, index[i]);
1688 assert(exact >= 0);
1689 if (exact == filter->index.size()) {
1690 filter = da_filter_add(filter, isl_map_copy(index[i]));
1691 filter_map = isl_map_add_dims(filter_map,
1692 isl_dim_out, 1);
1694 filter_map = isl_map_equate(filter_map, isl_dim_in, i,
1695 isl_dim_out, exact);
1696 for (int j = 0; j < filter->index.size(); ++j) {
1697 int pos;
1699 if (j == exact)
1700 continue;
1701 if (!isl_map_is_subset(filter->index[j], index[i]))
1702 continue;
1703 pos = isl_map_dim(source_value, isl_dim_out);
1704 source_value = copy_dim(source_value, i);
1705 filter_map = isl_map_add_dims(filter_map,
1706 isl_dim_in, 1);
1707 filter_map = isl_map_equate(filter_map, isl_dim_in, pos,
1708 isl_dim_out, j);
1712 source_value = isl_map_apply_range(source_value, filter_map);
1713 source_value = isl_map_coalesce(source_value);
1714 unaffected_value = isl_map_from_domain(unaffected_sink);
1715 unaffected_value = isl_map_add_dims(unaffected_value, isl_dim_out,
1716 filter->index.size());
1717 source_value = isl_map_union(source_value, unaffected_value);
1718 filter = da_filter_restrict(filter, source_value);
1720 for (int i = 0; i < index.size(); ++i)
1721 isl_map_free(index[i]);
1722 isl_set_free(domain);
1723 isl_map_free(not_run);
1725 return filter;
1728 /* Given constraints on the filter values "filter" at the sink iterations
1729 * "sink", derive additional constraints from the filter values of those
1730 * source nodes for which "sink" contains a reference to its last iteration.
1731 * In particular, we try and derive extra information from the fact that
1732 * some iterations of those source nodes have _not_ been executed.
1734 static struct da_filter *include_other_sources(struct da_filter *filter,
1735 __isl_keep isl_set *sink, add_dep_info *info)
1737 isl_space *space;
1738 int n_param;
1740 space = isl_set_get_space(sink);
1741 n_param = isl_space_dim(space, isl_dim_param);
1742 for (int i = 0; i < n_param; ++i) {
1743 isl_id *id;
1744 na_pair *na;
1746 if (!is_valid_bit(space, i))
1747 continue;
1749 id = isl_space_get_dim_id(space, isl_dim_param, i);
1750 na = (na_pair *) isl_id_get_user(id);
1751 isl_id_free(id);
1753 filter = include_other_source(filter, sink, na, info);
1755 isl_space_free(space);
1757 return filter;
1760 #define RESTRICT_NO 0
1761 #define RESTRICT_EMPTY 1
1762 #define RESTRICT_INPUT 2
1763 #define RESTRICT_OUTPUT 3
1765 /* Given a map from sinks to potential sources (source_map)
1766 * and the set of sink iterations (sink),
1767 * check if any parametrization is needed on the sources.
1768 * That is, check whether the possible filter values at the sink
1769 * imply that the filter values at the source are always valid.
1770 * If so, the source is executed whenever the sink is executed
1771 * and no parametrization is required.
1773 * Return RESTRICT_NO if no parametrization is required.
1774 * Return RESTRICT_INPUT if parametrization is required on the input
1775 * of the computation of the last iteration.
1776 * Return RESTRICT_OUTPUT if parametrization is required on the output
1777 * of the computation of the last iteration. This means that we know
1778 * that the source will be executed, but we want to introduce a parameter
1779 * to represent the last iteration anyway, because the knowledge depends
1780 * on the parameters representing last iterations of other nodes.
1781 * Return RESTRICT_EMPTY if the potential sources cannot possibly
1782 * be executed.
1784 * If there are no filters on the source, then obviously the source
1785 * is always executed.
1787 * We first construct a mapping from source iterations to source filter
1788 * values that allow some corresponding sink iteration(s) (according to
1789 * "source_map") to be executed.
1790 * If this relation is a subset of the actual mapping from iteration
1791 * vectors to filter values at the source, then we know that a corresponding
1792 * sink is only executed when the source is executed and no parametrization
1793 * is required.
1794 * If, moreover, the relation is empty then the filters cannot have any value,
1795 * meaning that the sources cannot have executed.
1797 * Otherwise, we check if we can find out more information by considering
1798 * information derived from knowledge about the last iterations of other
1799 * nodes. If, by considering this extract information, we can find
1800 * that the sources are necessarily executed, then we return RESTRICT_OUTPUT.
1801 * Otherwise, we return RESTRICT_INPUT.
1803 static int need_parametrization(__isl_keep isl_map *source_map,
1804 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
1806 bool filtered_source;
1807 isl_space *space;
1808 isl_map *source_value, *sink_value;
1809 da_filter *filter;
1810 na_pair *sink_na = info->read_na_pair;
1811 int res;
1813 if (isl_map_plain_is_empty(source_map) ||
1814 isl_set_plain_is_empty(sink))
1815 return RESTRICT_NO;
1817 filtered_source = isl_set_is_wrapping(source_na->node->source->set);
1819 if (!filtered_source)
1820 return RESTRICT_NO;
1822 filter = extract_filter(sink_na);
1823 res = -1;
1824 if (filter->index.size() != 0) {
1825 sink_value = known_filter_values(filter, source_na, source_map);
1826 source_value = isl_set_unwrap(
1827 source_na->node->source->get_isl_set());
1829 if (isl_map_is_empty(sink_value))
1830 res = RESTRICT_EMPTY;
1831 else if (isl_map_is_subset(sink_value, source_value))
1832 res = RESTRICT_NO;
1833 isl_map_free(source_value);
1834 isl_map_free(sink_value);
1837 if (res == RESTRICT_EMPTY) {
1838 da_filter_free(filter);
1839 return res;
1842 filter = include_other_sources(filter, sink, info);
1844 if (filter->index.size() == 0) {
1845 da_filter_free(filter);
1846 return RESTRICT_INPUT;
1849 sink_value = known_filter_values(filter, source_na, source_map);
1850 source_value = isl_set_unwrap(source_na->node->source->get_isl_set());
1852 if (isl_map_is_empty(sink_value))
1853 res = RESTRICT_EMPTY;
1854 else if (res == RESTRICT_NO)
1856 else if (isl_map_is_subset(sink_value, source_value))
1857 res = RESTRICT_OUTPUT;
1858 else
1859 res = RESTRICT_INPUT;
1861 isl_map_free(source_value);
1862 isl_map_free(sink_value);
1863 da_filter_free(filter);
1865 return res;
1868 extern "C" {
1869 static __isl_give isl_restriction *do_restrict(
1870 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
1871 void *source_user, void *user);
1874 /* Add parameters corresponding to the last iteration of "na" to "set"
1875 * (assuming they don't already appear in "set")
1876 * and add constraints to them to express that there either is no
1877 * last iteration (__last_<na>_valid = 0) or that there is a last
1878 * iteration (__last_<na>_valid = 1) and that the iteration is a possible
1879 * source of the current sink (based on the memory dependence between
1880 * the source and the sink).
1882 static __isl_give isl_set *set_parameter_bounds(__isl_take isl_set *set,
1883 na_pair *na, add_dep_info *info)
1885 isl_map *mem;
1886 isl_id *id;
1887 isl_set *valid;
1888 isl_set *invalid;
1889 isl_set *domain;
1890 int pos;
1892 id = valid_bit_id(isl_set_get_ctx(set), na);
1893 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
1895 if (pos < 0) {
1896 pos = isl_set_dim(set, isl_dim_param);
1897 set = isl_set_add_dims(set, isl_dim_param, 1);
1898 set = isl_set_set_dim_id(set, isl_dim_param, pos, id);
1899 } else
1900 isl_id_free(id);
1902 valid = isl_set_copy(set);
1903 invalid = set;
1905 valid = isl_set_fix_si(valid, isl_dim_param, pos, 1);
1907 mem = info->get_mem_dep(na);
1908 domain = isl_set_universe(isl_space_domain(isl_map_get_space(mem)));
1909 domain = add_parametrization(domain, na, info);
1910 mem = isl_map_intersect_domain(mem, domain);
1911 valid = isl_set_intersect(valid, isl_map_range(mem));
1913 invalid = isl_set_fix_si(invalid, isl_dim_param, pos, 0);
1915 return isl_set_union(valid, invalid);
1918 /* Check if there are any iterations of "source_na" in "source_map"
1919 * that are definitely executed, based solely on the possible filter values.
1920 * If so, add * constraints to "sink" to indicate that the last execution
1921 * cannot be earlier than those definitely executed iterations.
1923 * We first compute the set of source iterations that are definitely
1924 * executed because there are no filter values that would prohibit
1925 * their execution. If there are no such source iterations then we are done.
1927 * Then we construct a map from sink iterations to associated (through
1928 * "source_map") definitely executed source iterations and compute the
1929 * last of these definitely executed source iterations.
1931 * For those sink iterations that have a corresponding last definitely
1932 * executed source iteration, we add constraints that express that
1933 * this last definitely executed source iteration is lexicographically
1934 * smaller than or equal to the last executed source iteration
1935 * (and that there definitely is a last executed source iteration).
1937 static __isl_give isl_set *mark_definite_source(__isl_take isl_set *sink,
1938 add_dep_info *info, na_pair *source_na, __isl_keep isl_map *source_map)
1940 isl_space *space;
1941 isl_set *dom;
1942 isl_map *invalid;
1943 isl_map *definite_source_map;
1944 isl_set *with_source;
1945 isl_map *map_after;
1946 int depth;
1948 dom = source_na->node->source->get_isl_set();
1949 dom = isl_map_domain(isl_set_unwrap(dom));
1950 invalid = compute_filter_values(source_na->node, true);
1951 dom = isl_set_subtract(dom, isl_map_domain(invalid));
1953 if (isl_set_is_empty(dom)) {
1954 isl_set_free(dom);
1955 return sink;
1958 space = isl_set_get_space(dom);
1960 definite_source_map = isl_map_copy(source_map);
1961 definite_source_map = isl_map_intersect_range(source_map, dom);
1962 definite_source_map = isl_map_lexmax(definite_source_map);
1964 dom = isl_map_domain(isl_map_copy(definite_source_map));
1966 with_source = isl_set_copy(sink);
1967 with_source = isl_set_intersect(with_source, isl_set_copy(dom));
1968 sink = isl_set_subtract(sink, dom);
1970 dom = isl_set_universe(isl_space_copy(space));
1971 dom = add_parametrization(dom, source_na, info);
1973 depth = source_na->node->get_filter_depth();
1975 space = isl_space_map_from_set(space);
1976 map_after = isl_map_lex_le_first(space, depth);
1977 map_after = isl_map_intersect_range(map_after, dom);
1979 definite_source_map = isl_map_apply_range(definite_source_map,
1980 map_after);
1982 dom = isl_map_domain(definite_source_map);
1983 with_source = isl_set_intersect(with_source, dom);
1985 sink = isl_set_union(sink, with_source);
1987 return sink;
1990 /* Remove inconsistencies from the set of sink iterations "sink"
1991 * based on the current potential source "source_na" and other
1992 * potential sources referenced by "sink".
1994 * We first identify those iterations of "source_na" that are
1995 * definitely executed based solely on the possible filter values.
1997 * If the sink has filters, then we remove inconsistencies based
1998 * on the sink and the current potential source.
2000 * Finally, we go through the references to other potential sources
2001 * in "sink" and remove inconsistencies based on this other potential
2002 * source and the current potential source.
2004 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
2005 add_dep_info *info, na_pair *source_na, __isl_keep isl_map *source_map)
2007 isl_space *space;
2008 isl_id *source_id;
2009 int n_param;
2011 source_id = valid_bit_id(isl_map_get_ctx(source_map), source_na);
2013 sink = mark_definite_source(sink, info, source_na, source_map);
2015 if (isl_set_is_wrapping(info->read_na_pair->node->source->set))
2016 sink = remove_inconsistencies(sink, info, source_id);
2018 space = isl_map_get_space(source_map);
2019 n_param = isl_space_dim(space, isl_dim_param);
2020 for (int i = 0; i < n_param; ++i) {
2021 isl_id *other_id;
2023 if (!is_valid_bit(space, i))
2024 continue;
2025 other_id = isl_space_get_dim_id(space, isl_dim_param, i);
2027 if (other_id != source_id) {
2028 na_pair *other_na;
2030 other_na = (na_pair *) isl_id_get_user(other_id);
2031 sink = set_parameter_bounds(sink, other_na, info);
2032 sink = remove_inconsistencies(sink, info, other_id,
2033 source_id);
2036 isl_id_free(other_id);
2038 isl_space_free(space);
2040 isl_id_free(source_id);
2041 return sink;
2044 /* Compute a restriction for the given sink.
2045 * That is, add constraints to the parameters expressing
2046 * that the source is either not executed (*_valid = 0)
2047 * or it is executed (*_valid = 1) and then the last iteration
2048 * satisfies the corresponding memory based dependence.
2050 * Only do this for that part of "sink" that has any corresponding
2051 * sources in "source_map". The remaining part of "sink" is not affected.
2053 static __isl_give isl_set *compute_sink_restriction(
2054 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2055 na_pair *source_na, add_dep_info *info)
2057 isl_set *with_source, *without_source;
2059 with_source = isl_map_domain(isl_map_copy(source_map));
2060 without_source = isl_set_subtract(isl_set_copy(sink),
2061 isl_set_copy(with_source));
2063 with_source = set_parameter_bounds(with_source, source_na, info);
2064 with_source = remove_inconsistencies(with_source, info, source_na,
2065 source_map);
2067 return isl_set_union(with_source, without_source);
2070 /* Given a map from sinks to potential sources (sink2source),
2071 * check if any parametrization is needed.
2072 * Depending on the result, return either a universe restriction,
2073 * an empty restriction (if the sources cannot have executed),
2074 * a restriction that parametrizes the source and the sink
2075 * of the input of the computation of the last source
2076 * or a restriction that parametrizes the source of the output.
2078 * sink_map maps the domain of sink2source to the sink iteration domain.
2079 * source_map maps the range of sink2source to the source iteration domain.
2081 static __isl_give isl_restriction *compute_restriction_core(
2082 __isl_keep isl_map *sink2source,
2083 __isl_take isl_map *sink_map, __isl_take isl_map *source_map,
2084 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
2086 isl_space *space;
2087 isl_set *source_restr;
2088 isl_set *sink_restr;
2089 int need;
2091 sink2source = isl_map_copy(sink2source);
2092 sink = isl_set_copy(sink);
2094 sink2source = isl_map_apply_range(sink2source,
2095 isl_map_copy(source_map));
2096 sink2source = isl_map_apply_domain(sink2source,
2097 isl_map_copy(sink_map));
2098 sink = isl_set_apply(sink, isl_map_copy(sink_map));
2100 need = need_parametrization(sink2source, sink, source_na, info);
2101 if (need == RESTRICT_NO || need == RESTRICT_EMPTY) {
2102 isl_map_free(source_map);
2103 isl_map_free(sink_map);
2104 isl_set_free(sink);
2105 if (need == RESTRICT_NO)
2106 return isl_restriction_none(sink2source);
2107 else
2108 return isl_restriction_empty(sink2source);
2111 space = isl_map_get_space(source_map);
2112 source_restr = isl_set_universe(isl_space_range(space));
2114 source_restr = add_parametrization(source_restr, source_na, info);
2115 source_restr = isl_set_apply(source_restr, isl_map_reverse(source_map));
2117 if (need == RESTRICT_OUTPUT) {
2118 isl_map_free(sink_map);
2119 isl_set_free(sink);
2120 isl_map_free(sink2source);
2121 return isl_restriction_output(source_restr);
2124 sink_restr = compute_sink_restriction(sink2source, sink,
2125 source_na, info);
2126 sink_restr = isl_set_apply(sink_restr, isl_map_reverse(sink_map));
2128 isl_set_free(sink);
2129 isl_map_free(sink2source);
2131 return isl_restriction_input(source_restr, sink_restr);
2134 /* Compute a restriction for the given map from sinks to potential sources
2135 * (sink2source).
2137 * First check if the sink access has any filters. If so, compose the original
2138 * sink_map with a mapping that projects out these access filters.
2139 * Then call compute_restriction_core to perform the main computation.
2141 static __isl_give isl_restriction *compute_restriction(
2142 __isl_keep isl_map *sink2source,
2143 __isl_take isl_map *sink_map, __isl_take isl_map *source_map,
2144 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
2146 na_pair *sink_na = info->read_na_pair;
2148 if (sink_na->access->nested.size() > 0) {
2149 isl_space *space;
2150 isl_map *map;
2152 space = isl_space_range(isl_map_get_space(sink_map));
2153 space = isl_space_unwrap(space);
2154 map = isl_map_domain_map(isl_map_universe(space));
2156 sink_map = isl_map_apply_range(sink_map, map);
2159 return compute_restriction_core(sink2source, sink_map,source_map,
2160 sink, source_na, info);
2163 /* Compute a restriction for the given map from sinks to potential sources
2164 * (sink2source). We simply call compute_restriction to compute the
2165 * restriction. Since, unlike the case of do_restrict_domain_map bewloe,
2166 * we didn't encode the entire access relation in the domains of the input
2167 * to isl_access_info_compute_flow, we pass identity mappings on the source
2168 * and sink to compute_restriction.
2170 static __isl_give isl_restriction *do_restrict(__isl_keep isl_map *sink2source,
2171 __isl_keep isl_set *sink, void *source_user, void *user)
2173 na_pair *source_na = (na_pair *) source_user;
2174 add_dep_info *info = (struct add_dep_info *) user;
2175 isl_space *space;
2176 isl_map *source_map;
2177 isl_map *sink_map;
2179 space = isl_space_domain(isl_map_get_space(sink2source));
2180 sink_map = isl_map_identity(isl_space_map_from_set(space));
2181 space = isl_space_range(isl_map_get_space(sink2source));
2182 source_map = isl_map_identity(isl_space_map_from_set(space));
2184 return compute_restriction(sink2source, sink_map, source_map,
2185 sink, source_na, info);
2188 /* Does the iteration domain of any of the writes involve any filters?
2190 static bool any_filters(vector<na_pair> &writers)
2192 for (int i = 0; i < writers.size(); ++i)
2193 if (isl_set_is_wrapping(writers[i].node->source->set))
2194 return true;
2195 return false;
2198 /* Does any of the dependences starting at "first" have
2199 * controlled dependence relation?
2201 static bool any_controlled_dependences(PDG *pdg, int first)
2203 for (int i = first; i < pdg->dependences.size(); ++i)
2204 if (pdg->dependences[i]->controlled_relation)
2205 return true;
2207 return false;
2210 /* Remove parameters from "map" that start with "prefix".
2212 static __isl_give isl_map *remove_source(__isl_take isl_map *map,
2213 const char *prefix)
2215 int n = isl_map_dim(map, isl_dim_param);
2216 size_t len = strlen(prefix);
2218 for (int i = n - 1; i >= 0; --i) {
2219 const char *name;
2221 name = isl_map_get_dim_name(map, isl_dim_param, i);
2222 if (strncmp(name, prefix, len))
2223 continue;
2225 map = isl_map_project_out(map, isl_dim_param, i, 1);
2228 map = isl_map_coalesce(map);
2230 return map;
2233 /* Remove parameters from the dependences starting at "first"
2234 * that refer to any of the unused potential sources, i.e.,
2235 * those potential sources that are in writers, but not in info->used.
2237 * Since the current sink does not depend on those unused potential sources,
2238 * the corresponding dependence relations cannot depend on them and
2239 * any reference to them can simply be projected out.
2241 static void remove_unused_sources(PDG *pdg, int first,
2242 vector<na_pair> &writers, add_dep_info *info)
2244 char name[60];
2245 std::vector<na_pair *> unused;
2247 for (int i = 0; i < writers.size(); ++i) {
2248 if (info->used.find(&writers[i]) == info->used.end())
2249 unused.push_back(&writers[i]);
2252 if (unused.size() == 0)
2253 return;
2254 if (!any_controlled_dependences(pdg, first))
2255 return;
2257 for (int i = 0; i < unused.size(); ++i) {
2258 na_pair *na = unused[i];
2260 snprintf(name, sizeof(name), "__last_%s_%d_",
2261 na->node->name->s.c_str(), na->access->nr);
2263 for (int j = first; j < pdg->dependences.size(); ++j) {
2264 pdg::dependence *dep = pdg->dependences[j];
2265 isl_map *map;
2267 if (!dep->controlled_relation)
2268 continue;
2270 map = dep->controlled_relation->map;
2271 map = remove_source(map, name);
2272 dep->controlled_relation->map = map;
2277 void find_deps(PDG* pdg, pdg::array *a, type t)
2279 isl_ctx *ctx = pdg->get_isl_ctx();
2280 int nparam = pdg->params.size();
2281 int selfinput = 0;
2282 int reuse = 0;
2283 int firstuse = 0;
2284 add_dep_info info = { pdg, a, t };
2285 isl_set *context;
2286 bool need_parametrization;
2288 switch (t) {
2289 case flow:
2290 info.dtype = pdg::dependence::flow;
2291 firstuse = 1;
2292 break;
2293 case anti:
2294 info.dtype = pdg::dependence::anti;
2295 break;
2296 case data_reuse:
2297 info.dtype = pdg::dependence::reuse;
2298 reuse = 1;
2299 firstuse = 1;
2300 break;
2301 case reuse_pair:
2302 info.dtype = pdg::dependence::reuse_pair;
2303 break;
2304 case output:
2305 info.dtype = pdg::dependence::output;
2306 break;
2309 a->analysis_performed.push_back(new pdg::dependence_type(info.dtype));
2311 vector<na_pair> readers;
2312 vector<na_pair> writers;
2313 for (int i = 0; i < pdg->nodes.size(); ++i) {
2314 pdg::node *node = pdg->nodes[i];
2315 pdg::statement *s = pdg->nodes[i]->statement;
2316 for (int j = 0; j < s->accesses.size(); ++j) {
2317 pdg::access *access = s->accesses[j];
2318 if (access->array != a)
2319 continue;
2320 switch (t) {
2321 case flow:
2322 case data_reuse:
2323 case anti:
2324 if ((access->type == pdg::access::read) ^ (t == anti))
2325 readers.push_back(na_pair(node, access));
2326 else
2327 writers.push_back(na_pair(node, access));
2328 break;
2329 case output:
2330 if (access->type == pdg::access::read)
2331 continue;
2332 case reuse_pair:
2333 readers.push_back(na_pair(node, access));
2334 writers.push_back(na_pair(node, access));
2335 break;
2340 int maxsize = (selfinput || reuse) ? writers.size() + readers.size()
2341 : writers.size();
2342 context = pdg->get_context_isl_set();
2343 info.precedes_level = (isl_access_level_before)
2344 ((t == reuse_pair) ? precedes_level_accesses
2345 : precedes_level_nodes);
2346 need_parametrization = any_filters(writers);
2347 for (int i = 0; i < writers.size(); ++i) {
2348 writers[i].map = convert_access(&writers[i]);
2350 for (int i = 0; i < readers.size(); ++i) {
2351 readers[i].map = convert_access(&readers[i]);
2352 readers[i].map = isl_map_intersect_params(readers[i].map,
2353 isl_set_copy(context));
2354 readers[i].project_out_access_filters();
2356 for (int i = 0; i < readers.size(); ++i) {
2357 isl_access_info *acc;
2358 int n_dep = pdg->dependences.size();
2360 acc = isl_access_info_alloc(isl_map_copy(readers[i].map),
2361 &readers[i], info.precedes_level, maxsize);
2362 if (need_parametrization)
2363 acc = isl_access_info_set_restrict(acc, &do_restrict, &info);
2364 for (int j = 0; j < writers.size(); ++j)
2365 acc = isl_access_info_add_source(acc,
2366 isl_map_copy(writers[j].map), 1, &writers[j]);
2367 if (selfinput && writers.size()) {
2368 pdg::node *readnode = readers[i].node;
2369 for (int j = 0; j < readers.size(); ++j) {
2370 if (readers[j].node == readnode)
2371 acc = isl_access_info_add_source(acc,
2372 isl_map_copy(readers[j].map), 1, &readers[j]);
2375 if (reuse) {
2376 for (int j = 0; j < readers.size(); ++j)
2377 acc = isl_access_info_add_source(acc,
2378 isl_map_copy(readers[j].map), 1, &readers[j]);
2380 info.set_read_na(&readers[i]);
2381 isl_flow *deps = isl_access_info_compute_flow(acc);
2382 isl_flow_foreach(deps, add_dep, &info);
2383 isl_map *no_source;
2384 no_source = isl_flow_get_no_source(deps, 1);
2385 no_source = isl_map_from_range(isl_map_domain(no_source));
2386 no_source = simplify_controls(no_source, &info, NULL);
2387 if (!isl_map_fast_is_empty(no_source) && firstuse) {
2388 pdg::dependence *d = new pdg::dependence;
2389 d->array = a;
2390 d->type = pdg::dependence::uninitialized;
2391 d->to = readers[i].node;
2392 d->to_access = readers[i].access;
2393 if (d->to_access->extension) {
2394 d->extended_relation = new pdg::IslMap(isl_map_copy(no_source));
2395 no_source = isl_map_apply_range(no_source,
2396 isl_map_reverse(
2397 d->to_access->extension->get_isl_map(ctx)));
2399 d->relation = new pdg::IslMap(isl_map_copy(no_source));
2400 pdg->dependences.push_back(d);
2402 isl_map_free(no_source);
2403 isl_flow_free(deps);
2404 remove_unused_sources(pdg, n_dep, writers, &info);
2406 isl_set_free(context);
2409 /* Add a dependence from "write" to "a" to a->sources.
2411 static void add_unique_source(pdg::access *a, pdg::access *write)
2413 isl_map *dep;
2414 isl_map *read;
2416 dep = isl_map_range_map(write->map->get_isl_map());
2417 read = isl_map_range_map(a->map->get_isl_map());
2418 dep = isl_map_apply_range(dep, isl_map_reverse(read));
2420 a->sources.push_back(new pdg::IslMap(dep));
2423 /* Look for the unique write access that writes to the array accessed
2424 * by "a" and then add a dependence from that write to a->sources.
2426 static void find_unique_source(pdg::PDG* pdg, pdg::access *a)
2428 for (int i = 0; i < pdg->nodes.size(); ++i) {
2429 pdg::node *node = pdg->nodes[i];
2430 pdg::statement *s = pdg->nodes[i]->statement;
2431 for (int j = 0; j < s->accesses.size(); ++j) {
2432 pdg::access *access = s->accesses[j];
2433 if (access->array != a->array)
2434 continue;
2435 if (access->type != pdg::access::write)
2436 continue;
2437 add_unique_source(a, access);
2438 return;
2442 assert(0);
2445 extern "C" {
2446 static int add_source(__isl_take isl_map *dep, int must, void *dep_user,
2447 void *user);
2450 /* Add "dep" to a->sources, provided it is exact, and return 0.
2451 * Otherwise, return -1.
2453 static int add_source(__isl_take isl_map *dep, int must, void *dep_user,
2454 void *user)
2456 bool has_controls;
2457 pdg::access *a = (pdg::access *) user;
2459 dep = remove_redundant_controls(dep, &has_controls);
2460 if (has_controls) {
2461 isl_map_free(dep);
2462 return -1;
2465 a->sources.push_back(new pdg::IslMap(dep));
2467 return 0;
2470 extern "C" {
2471 static __isl_give isl_restriction *do_restrict_domain_map(
2472 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2473 void *source_user, void *user);
2476 /* Compute a restriction for the given map from sinks to potential sources
2477 * (sink2source). We simply call compute_restriction to compute the
2478 * restriction. This function is used from within find_sources,
2479 * which encodes the entire access relation into the domains of
2480 * the access relations passed to isl_access_info_compute_flow.
2481 * That is, the access relations passed to isl_access_info_compute_flow
2482 * are the result of applying isl_map_range_map to the original access
2483 * relations. We therefore pass mappings that undo this encoding
2484 * to compute_restriction.
2486 static __isl_give isl_restriction *do_restrict_domain_map(
2487 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2488 void *source_user, void *user)
2490 na_pair *source_na = (na_pair *) source_user;
2491 add_dep_info *info = (struct add_dep_info *) user;
2492 isl_space *space;
2493 isl_map *source_domain_map, *sink_domain_map;
2495 space = isl_space_range(isl_map_get_space(source_map));
2496 space = isl_space_unwrap(space);
2497 source_domain_map = isl_map_domain_map(isl_map_universe(space));
2498 space = isl_space_domain(isl_map_get_space(source_map));
2499 space = isl_space_unwrap(space);
2500 sink_domain_map = isl_map_domain_map(isl_map_universe(space));
2502 return compute_restriction(source_map, sink_domain_map,
2503 source_domain_map, sink, source_na, info);
2506 /* Find the sources of (read) access "a" in node "node".
2507 * If they are complete (no uninitialized accesses) and exact,
2508 * then put them in a->sources. Otherwise, discard them.
2510 * If the array is marked uniquely_defined, then we simply look
2511 * for the defining write in find_unique_source.
2513 * Otherwise, we look for all writes that write to the same array,
2514 * perform dependence analysis and then check whether
2515 * the result is complete and exact.
2517 * The sources record not only the node iteration, but also
2518 * the index of the array element. We therefore apply
2519 * isl_map_range_map to the access relations, to obtain
2520 * a relation from the access (iteration -> element)
2521 * to the array element and feed that to the dependence analysis engine.
2523 void find_sources(pdg::PDG* pdg, pdg::node *node, pdg::access *a)
2525 isl_set *context;
2526 isl_map *no_source;
2527 isl_access_info *acc;
2528 isl_flow *deps;
2529 vector<na_pair> writers;
2530 na_pair reader(node, a);
2531 add_dep_info info = { pdg, a->array, flow, pdg::dependence::flow };
2533 if (a->array->uniquely_defined) {
2534 find_unique_source(pdg, a);
2535 return;
2538 info.precedes_level = (isl_access_level_before) precedes_level_nodes;
2540 for (int i = 0; i < pdg->nodes.size(); ++i) {
2541 pdg::node *node = pdg->nodes[i];
2542 pdg::statement *s = pdg->nodes[i]->statement;
2543 for (int j = 0; j < s->accesses.size(); ++j) {
2544 pdg::access *access = s->accesses[j];
2545 if (access->array != a->array)
2546 continue;
2547 if (access->type != pdg::access::write)
2548 continue;
2549 writers.push_back(na_pair(node, access));
2553 context = pdg->get_context_isl_set();
2554 for (int i = 0; i < writers.size(); ++i) {
2555 writers[i].projected_map = convert_access(&writers[i]);
2556 writers[i].map = isl_map_copy(writers[i].projected_map);
2557 writers[i].map = isl_map_range_map(writers[i].map);
2559 reader.projected_map = convert_access(&reader);
2560 reader.projected_map = isl_map_intersect_params(reader.projected_map,
2561 context);
2562 reader.map = isl_map_range_map(isl_map_copy(reader.projected_map));
2563 reader.project_out_access_filters();
2565 acc = isl_access_info_alloc(isl_map_copy(reader.map),
2566 &reader, info.precedes_level, writers.size());
2567 for (int j = 0; j < writers.size(); ++j)
2568 acc = isl_access_info_add_source(acc,
2569 isl_map_copy(writers[j].map), 1, &writers[j]);
2571 if (any_filters(writers))
2572 acc = isl_access_info_set_restrict(acc,
2573 &do_restrict_domain_map, &info);
2575 info.set_read_na(&reader);
2576 deps = isl_access_info_compute_flow(acc);
2577 no_source = isl_flow_get_no_source(deps, 1);
2578 if (isl_map_plain_is_empty(no_source)) {
2579 if (isl_flow_foreach(deps, add_source, a) < 0) {
2580 for (int i = 0; i < a->sources.size(); ++i)
2581 delete a->sources[i];
2582 a->sources.resize(0);
2585 isl_map_free(no_source);
2586 isl_flow_free(deps);
2589 /* Find the source (if possible) of the filter "coa" in node "node".
2590 * We assume that the filter is an access rather than a function call.
2592 static void find_sources(pdg::PDG *pdg, pdg::node *node,
2593 pdg::call_or_access *coa)
2595 pdg::access *access;
2597 assert(coa->type == pdg::call_or_access::t_access);
2598 access = coa->access;
2600 find_sources(pdg, node, access);
2603 /* Compute the sources (if possible) for all the filters in all the
2604 * nodes and accesses in "pdg".
2606 void compute_filter_sources(pdg::PDG *pdg)
2608 for (int i = 0; i < pdg->nodes.size(); ++i) {
2609 pdg::node *node = pdg->nodes[i];
2610 pdg::statement *s = pdg->nodes[i]->statement;
2611 int n_filter = node->filters.size();
2613 for (int j = 0; j < n_filter; ++j)
2614 find_sources(pdg, node, node->filters[j]);
2616 for (int j = 0; j < s->accesses.size(); ++j) {
2617 pdg::access *access = s->accesses[j];
2619 for (int k = 0; k < access->nested.size(); ++k)
2620 find_sources(pdg, node, access->nested[k]);
2625 static int precedes_level_nodes(na_pair *first, na_pair *second)
2627 int d = 0;
2628 int cmp = 0;
2629 for (int i = 0; i < first->node->prefix.size(); ++i) {
2630 if (i >= second->node->prefix.size())
2631 break;
2632 cmp = first->node->prefix[i] - second->node->prefix[i];
2633 if (cmp)
2634 break;
2635 if (first->node->prefix[i] == -1)
2636 ++d;
2638 return 2*d + (cmp<0);
2641 static int precedes_level_accesses(na_pair *first, na_pair *second)
2643 int cmp = 0;
2644 int d = 0;
2645 for (int i = 0; i < first->node->prefix.size(); ++i) {
2646 if (i >= second->node->prefix.size())
2647 break;
2648 cmp = first->node->prefix[i] - second->node->prefix[i];
2649 if (cmp)
2650 break;
2651 if (first->node->prefix[i] == -1)
2652 ++d;
2654 /* same node; now compare accesses */
2655 if (!cmp)
2656 cmp = first->access->nr - second->access->nr;
2657 return 2*d + (cmp<0);