update isl for isl_space_domain_factor_domain
[ppn.git] / da.cc
blob46ea47442e9318fee2e562ce0784f631db66c450
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 for (int i = 0; i < s_dim; ++i) {
99 isl_constraint *c;
100 int v;
102 c = isl_inequality_alloc(isl_local_space_copy(ls));
103 c = isl_constraint_set_coefficient_si(c, isl_dim_out, 0, 1);
104 id = isl_basic_map_add_constraint(id, c);
105 c = isl_inequality_alloc(isl_local_space_copy(ls));
106 c = isl_constraint_set_coefficient_si(c, isl_dim_out, 0, -1);
107 v = array->dims[isl_map_n_out(map)+i] - 1;
108 c = isl_constraint_set_constant_si(c, v);
109 id = isl_basic_map_add_constraint(id, c);
111 isl_local_space_free(ls);
112 map = isl_map_product(map, isl_map_from_basic_map(id));
113 map = isl_map_flatten_range(map);
114 if (array_id)
115 map = isl_map_set_tuple_id(map, isl_dim_out, array_id);
116 if (!na->access->extension) {
117 isl_map *ext = isl_map_copy(map);
118 ext = isl_set_unwrap(isl_map_domain(ext));
119 ext = isl_map_reverse(isl_map_domain_map(ext));
120 na->access->extension = new pdg::IslMap(ext);
122 if (!na->access->extended_map)
123 na->access->extended_map = new pdg::IslMap(isl_map_copy(map));
124 return map;
127 /* If access "access" contains any nested accesses, then the domain
128 * of the access relation contains extra dimensions corresponding to
129 * the values of the nested accesses.
130 * Add these extra dimensions, with ranges given by the value_bounds
131 * of the corresponding array to domain "dom".
132 * If a nested access array does not have value_bounds, then we assume
133 * an infinite interval.
135 static isl_set *append_nested_value_domains(isl_set *dom, pdg::access *access)
137 isl_ctx *ctx;
139 ctx = isl_set_get_ctx(dom);
140 for (int i = 0; i < access->nested.size(); ++i) {
141 pdg::call_or_access *coa = access->nested[i];
142 assert(coa->type == pdg::call_or_access::t_access);
143 pdg::access *nested = coa->access;
144 isl_set *bounds;
145 if (nested->array->value_bounds)
146 bounds = nested->array->value_bounds->get_isl_set(ctx);
147 else {
148 isl_space *dim = isl_set_get_space(dom);
149 dim = isl_space_drop_dims(dim, isl_dim_set,
150 0, isl_space_dim(dim, isl_dim_set));
151 dim = isl_space_add_dims(dim, isl_dim_set, 1);
152 bounds = isl_set_universe(dim);
154 dom = isl_set_product(dom, bounds);
156 return dom;
159 /* Combine constraints of the "pure" mapping with the constraints
160 * on the domain. If the range of the mapping is of a dimension
161 * that is lower than the dimension of the accessed array,
162 * we extend the dimension of both domain and range of the mapping
163 * with the missing dimension. The size of domain and range
164 * in these dimensions is set to the extent of the array in the
165 * corresponding missing dimension. Each point in the original
166 * domain is therefore expanded to a hyperrectangle and each point
167 * in this hyperrectangle is mapped onto a single point in the array.
169 * If node->source is a wrapped map, then the iteration domain
170 * is the domain of this map.
172 static isl_map *convert_access(na_pair *na)
174 isl_map *map = na->access->map->get_isl_map();
175 isl_set *dom = na->node->source->get_isl_set();
177 if (isl_set_is_wrapping(dom)) {
178 dom = isl_map_domain(isl_set_unwrap(dom));
179 dom = isl_set_coalesce(dom);
182 dom = append_nested_value_domains(dom, na->access);
183 if (isl_map_n_in(map) != isl_set_dim(dom, isl_dim_set))
184 assert(0);
185 map = isl_map_intersect_domain(map, dom);
186 if (isl_map_n_out(map) != na->access->array->dims.size())
187 map = extend_access(map, na);
188 return map;
191 typedef std::map<na_pair *, isl_map *> na_pair2map;
193 struct add_dep_info {
194 PDG *pdg;
195 pdg::array *a;
196 type t;
197 enum pdg::dependence::type dtype;
198 /* The sink. */
199 na_pair *read_na_pair;
200 /* The comparison routine that was used during
201 * the dependence analysis.
203 isl_access_level_before precedes_level;
204 /* Cache of memory based dependence relations.
205 * The key of the map refers to the write.
207 na_pair2map mem_dep;
208 /* How many loops are shared by the current sink and source?
209 * Initialized to -1.
211 int n_shared;
212 /* For each potential source, what's (up to now) the minimal
213 * and maximal number of shared loops?
214 * If not set, then we don't know yet.
216 std::map<na_pair *, int> min_n_shared;
217 std::map<na_pair *, int> max_n_shared;
219 /* Potential sources that are actually used. */
220 std::set<na_pair *> used;
222 __isl_give isl_map *get_mem_dep(na_pair *write_na);
223 void clear_mem_dep();
224 void set_read_na(na_pair *read_na);
225 void update_min_n_shared(na_pair *source_na);
227 ~add_dep_info();
230 /* Update min_n_shared of "source_na" to the current number of shared loops.
231 * The new value is always smaller than or equal to the old value (if any).
232 * If max_n_shared hasn't been set yet, then set it as well.
234 void add_dep_info::update_min_n_shared(na_pair *source_na)
236 if (max_n_shared.find(source_na) == max_n_shared.end())
237 max_n_shared[source_na] = n_shared;
238 min_n_shared[source_na] = n_shared;
241 /* Create an id
243 * __last_<stmt>_<access_nr>_valid
245 * corresponding to "na", with "na" attached as user pointer.
247 static __isl_give isl_id *valid_bit_id(isl_ctx *ctx, na_pair *na)
249 char name[60];
251 snprintf(name, sizeof(name), "__last_%s_%d_valid",
252 na->node->name->s.c_str(), na->access->nr);
253 return isl_id_alloc(ctx, name, na);
256 /* Create an id
258 * __last_<stmt>_<access_nr>_shared
260 * corresponding to "na", with "na" attached as user pointer.
262 static __isl_give isl_id *create_shared_id(isl_ctx *ctx, na_pair *na)
264 char name[60];
266 snprintf(name, sizeof(name), "__last_%s_%d_shared",
267 na->node->name->s.c_str(), na->access->nr);
268 return isl_id_alloc(ctx, name, na);
271 /* Project out all the dimensions of the given type from "map" except "pos".
273 static __isl_give isl_map *project_on(__isl_take isl_map *map,
274 enum isl_dim_type type, unsigned pos)
276 unsigned n = isl_map_dim(map, type);
278 map = isl_map_project_out(map, type, pos + 1, n - (pos + 1));
279 map = isl_map_project_out(map, type, 0, pos);
281 return map;
284 /* Does output dimension "pos" have a fixed value in terms of the
285 * input dimensions (and parameters)?
287 static int has_fixed_value(__isl_keep isl_map *map, int pos)
289 int sv;
291 map = isl_map_copy(map);
292 map = project_on(map, isl_dim_out, pos);
293 sv = isl_map_is_single_valued(map);
294 isl_map_free(map);
296 return sv;
299 /* Return the position of the parameter with the given "id" in "set",
300 * adding it if it wasn't there already.
302 static int find_or_add_param(__isl_keep isl_set **set, __isl_take isl_id *id)
304 int pos;
306 pos = isl_set_find_dim_by_id(*set, isl_dim_param, id);
307 if (pos >= 0) {
308 isl_id_free(id);
309 return pos;
312 pos = isl_set_dim(*set, isl_dim_param);
313 *set = isl_set_add_dims(*set, isl_dim_param, 1);
314 *set = isl_set_set_dim_id(*set, isl_dim_param, pos, id);
316 return pos;
319 /* Add parameters to "set" identifying the last iteration of the access
320 * identified by "na".
322 * In particular, we add a parameter
324 * __last_<stmt>_<access_nr>_shared >= info->n_shared
326 * and parameters
328 * __last_<stmt>_<access_nr>_<i> = it_<i>
330 * with i ranging over the iterators, starting at info->n_shared,
331 * that are affected by the filters,
332 * except those that have a fixed value according to the memory based
333 * dependence.
334 * "na" is attached to the first two parameters, so that it can be recovered
335 * in refine_controls(). If the set already references some of these
336 * parameters, then we don't add the parameter again, but instead
337 * simply add the corresponding constraint.
339 static __isl_give isl_set *add_parametrization(__isl_take isl_set *set,
340 na_pair *na, add_dep_info *info)
342 int pos;
343 isl_ctx *ctx;
344 isl_id *id;
345 char name[60];
346 int depth;
347 isl_map *mem;
349 depth = na->node->get_filter_depth();
350 mem = info->get_mem_dep(na);
351 mem = isl_map_reverse(mem);
353 ctx = isl_set_get_ctx(set);
354 id = create_shared_id(ctx, na);
355 pos = find_or_add_param(&set, id);
356 set = isl_set_lower_bound_si(set, isl_dim_param, pos, info->n_shared);
358 for (int i = info->n_shared; i < depth; ++i) {
359 if (has_fixed_value(mem, i))
360 continue;
362 snprintf(name, sizeof(name), "__last_%s_%d_%d",
363 na->node->name->s.c_str(), na->access->nr, i);
365 id = isl_id_alloc(ctx, name, NULL);
366 pos = find_or_add_param(&set, id);
368 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
371 isl_map_free(mem);
372 return set;
375 /* Is the i-th parameter of "map" a control, i.e., a parameter
376 * introduced by add_parametrization()?
377 * In particular, is the parameter of the form __last_*?
379 static bool is_control(__isl_keep isl_map *map, int i)
381 const char *name;
382 const char *prefix = "__last_";
383 size_t prefix_len = strlen(prefix);
385 if (!isl_map_has_dim_id(map, isl_dim_param, i))
386 return false;
387 name = isl_map_get_dim_name(map, isl_dim_param, i);
388 return strncmp(name, prefix, prefix_len) == 0;
391 /* Is the i-th parameter of "set" a control, i.e., a parameter
392 * introduced by add_parametrization()?
393 * In particular, is the parameter of the form __last_*?
395 static bool is_control(__isl_keep isl_set *set, int i)
397 const char *name;
398 const char *prefix = "__last_";
399 size_t prefix_len = strlen(prefix);
401 if (!isl_set_has_dim_id(set, isl_dim_param, i))
402 return false;
403 name = isl_set_get_dim_name(set, isl_dim_param, i);
404 return strncmp(name, prefix, prefix_len) == 0;
407 /* Remove all controls that are redundant, i.e., that do not appear
408 * in any of the constraints.
409 * Set *has_controls to true if there are any controls that are not redundant.
411 static __isl_give isl_map *remove_redundant_controls(__isl_take isl_map *dep,
412 bool *has_controls)
414 int i;
415 int n_param;
417 *has_controls = false;
419 n_param = isl_map_dim(dep, isl_dim_param);
420 for (i = n_param - 1; i >= 0; --i) {
421 if (!is_control(dep, i))
422 continue;
423 if (isl_map_involves_dims(dep, isl_dim_param, i, 1))
424 *has_controls = true;
425 else
426 dep = isl_map_project_out(dep, isl_dim_param, i, 1);
429 return dep;
432 /* Rename controls of "dep" from
434 * __last_<source_stmt>_<source_acc_nr>_*
436 * to
438 * __last_<source_stmt>_<source_acc_nr>_<sink_stmt>_<sink_acc_nr>_*
440 * "na" represents the sink.
442 static __isl_give isl_map *rename_controls(__isl_take isl_map *dep, na_pair *na)
444 char buf[100];
445 int n_param;
446 const char *name;
447 const char *underscore;
449 n_param = isl_map_dim(dep, isl_dim_param);
450 for (int i = 0; i < n_param; ++i) {
451 int len;
452 if (!is_control(dep, i))
453 continue;
454 name = isl_map_get_dim_name(dep, isl_dim_param, i);
455 underscore = strrchr(name, '_');
456 assert(underscore);
457 len = underscore + 1 - name;
458 memcpy(buf, name, len);
459 snprintf(buf + len, sizeof(buf) - len, "%s_%d_%s",
460 na->node->name->s.c_str(), na->access->nr, name + len);
461 dep = isl_map_set_dim_name(dep, isl_dim_param, i, buf);
464 return dep;
467 extern "C" {
468 static int extract_dep(__isl_take isl_map *dep, int must,
469 void *dep_user, void *user);
472 /* Extract the single dependence relation from the result of
473 * dataflow analyis and assign it to *user.
475 static int extract_dep(__isl_take isl_map *dep, int must, void *dep_user,
476 void *user)
478 isl_map **dep_p = (isl_map **) user;
479 assert(!*dep_p);
480 *dep_p = dep;
481 return 0;
484 /* Return the memory based dependence relation from write_na
485 * to read_na_pair. If the "projected_map"
486 * fields are not NULL, then use the "projected_map"
487 * instead of the "map" of write_na and this->read_na_pair.
489 __isl_give isl_map *add_dep_info::get_mem_dep(na_pair *write_na)
491 isl_access_info *acc;
492 isl_flow *deps;
493 isl_map *read_map, *write_map;
494 isl_map *dep = NULL;
496 if (mem_dep.find(write_na) != mem_dep.end())
497 return isl_map_copy(mem_dep[write_na]);
499 if (read_na_pair->projected_map)
500 read_map = isl_map_copy(read_na_pair->projected_map);
501 else
502 read_map = isl_map_copy(read_na_pair->map);
503 acc = isl_access_info_alloc(read_map, read_na_pair, precedes_level, 1);
504 if (write_na->projected_map)
505 write_map = isl_map_copy(write_na->projected_map);
506 else
507 write_map = isl_map_copy(write_na->map);
508 acc = isl_access_info_add_source(acc, write_map, 0, write_na);
509 deps = isl_access_info_compute_flow(acc);
510 isl_flow_foreach(deps, &extract_dep, &dep);
511 isl_flow_free(deps);
513 mem_dep[write_na] = isl_map_copy(dep);
515 return dep;
518 /* Clear the cache of memory based dependence relations.
520 void add_dep_info::clear_mem_dep()
522 na_pair2map::iterator it;
524 for (it = mem_dep.begin(); it != mem_dep.end(); ++it)
525 isl_map_free(it->second);
526 mem_dep.clear();
529 /* Set read_na_pair to read_na.
531 * If the cache of memory based dependence relations contains any
532 * elements then they refer to a different read, so we need to clear
533 * the cache.
535 * We also clear the set of used potential sources and reset
536 * the data that keeps track of the number of shared loops between
537 * the sink (read_na_pair) and the sources.
539 void add_dep_info::set_read_na(na_pair *read_na)
541 used.clear();
542 clear_mem_dep();
543 n_shared = -1;
544 min_n_shared.clear();
545 max_n_shared.clear();
546 read_na_pair = read_na;
549 add_dep_info::~add_dep_info()
551 clear_mem_dep();
554 /* Is the name of parameter "i" of "space" of the form __last_*_suffix?
556 static bool is_last_with_suffix(__isl_keep isl_space *space, int i,
557 const char *suffix, size_t suffix_len)
559 const char *prefix = "__last_";
560 size_t prefix_len = strlen(prefix);
561 const char *name;
562 size_t len;
564 if (!isl_space_has_dim_id(space, isl_dim_param, i))
565 return false;
566 name = isl_space_get_dim_name(space, isl_dim_param, i);
567 if (strncmp(name, prefix, prefix_len))
568 return false;
569 len = strlen(name);
570 return len > suffix_len && !strcmp(name + len - suffix_len, suffix);
573 /* Is the name of parameter "i" of "space" of the form __last_*_valid?
574 * In practice, those are the parameters __last_*_valid, created
575 * in add_parametrization().
577 static bool is_valid_bit(__isl_keep isl_space *space, int i)
579 const char *suffix = "_valid";
581 return is_last_with_suffix(space, i, suffix, strlen(suffix));
584 /* Is the name of parameter "i" of "space" of the form __last_*_shared?
585 * In practice, those are the parameters __last_*_shared, created
586 * in add_parametrization().
588 static bool is_shared(__isl_keep isl_space *space, int i)
590 const char *suffix = "_shared";
591 size_t suffix_len = strlen(suffix);
593 return is_last_with_suffix(space, i, suffix, strlen(suffix));
596 /* Assuming "coa" is a (read) access, return the array being
597 * accessed.
599 static pdg::array *get_filter_array(pdg::call_or_access *coa)
601 assert(coa->type == pdg::call_or_access::t_access);
602 return coa->access->array;
605 /* Compute a map between domain elements (i) of "map1" and range elements
606 * of "map2" (j) such that all the images of i in "map1" map to j through
607 * "map2" and such that there is at least one such image element.
609 * In other words, the result contains those pairs of elements such that
610 * map1(i) \cap map2^-1(j) is non-empty and map1(i) \subseteq map2^-1(j).
612 * Equivalently, compute
614 * (map1 . map2) \setminus
615 * (map1 . ((\range map1 \to \range map2) \setminus map2))
617 * If map1 is single valued, then we can do a simple join.
619 static __isl_give isl_union_map *join_non_empty_subset(
620 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
622 isl_union_set *dom, *ran;
623 isl_union_map *univ;
624 isl_union_map *res;
626 if (isl_union_map_is_single_valued(umap1))
627 return isl_union_map_apply_range(umap1, umap2);
629 res = isl_union_map_apply_range(isl_union_map_copy(umap1),
630 isl_union_map_copy(umap2));
631 dom = isl_union_map_range(isl_union_map_copy(umap1));
632 ran = isl_union_map_range(isl_union_map_copy(umap2));
633 univ = isl_union_map_from_domain_and_range(dom, ran);
634 umap2 = isl_union_map_subtract(univ, umap2);
635 umap1 = isl_union_map_apply_range(umap1, umap2);
636 res = isl_union_map_subtract(res, umap1);
638 return res;
641 /* Compute a map between domain elements (i) of "map1" and range elements
642 * of "map2" (j) such that the images of i in "map1" include all those
643 * elements that map to j through "map2" and such that there is
644 * at least one such image element.
646 * In other words, the result contains those pairs of elements such that
647 * map1(i) \cap map2^-1(j) is non-empty and map1(i) \supseteq map2^-1(j).
649 * Equivalently, compute
651 * (map1 . map2) \setminus
652 * (((\domain map1 \to \domain map2) \setminus map1) . map2)
654 * If map1 is single valued, then we can do a simple join.
656 static __isl_give isl_union_map *join_non_empty_superset(
657 __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
659 isl_union_set *dom, *ran;
660 isl_union_map *univ;
661 isl_union_map *res;
663 if (isl_union_map_is_single_valued(umap2))
664 return isl_union_map_apply_range(umap1, umap2);
666 res = isl_union_map_apply_range(isl_union_map_copy(umap1),
667 isl_union_map_copy(umap2));
668 dom = isl_union_map_domain(isl_union_map_copy(umap1));
669 ran = isl_union_map_domain(isl_union_map_copy(umap2));
670 univ = isl_union_map_from_domain_and_range(dom, ran);
671 umap1 = isl_union_map_subtract(univ, umap1);
672 umap1 = isl_union_map_apply_range(umap1, umap2);
673 res = isl_union_map_subtract(res, umap1);
675 return res;
678 /* Return those elements in the domain of "umap" where "umap" is multi-valued.
680 * In particular, construct a mapping between domain elements of "umap"
681 * and pairs of corresponding image elements.
682 * Remove pairs of identical image elements from the range of this mapping.
683 * The result is a mapping between domain elements and pairs of different
684 * corresponding image elements. The domain of this mapping contains those
685 * domain elements of "umap" with at least two images.
687 static __isl_give isl_union_set *multi_valued(__isl_keep isl_union_map *umap)
689 isl_union_map *multi, *id;
691 multi = isl_union_map_range_product(isl_union_map_copy(umap),
692 isl_union_map_copy(umap));
693 id = isl_union_map_universe(isl_union_map_copy(multi));
694 id = isl_union_set_unwrap(isl_union_map_range(id));
695 id = isl_union_set_identity(isl_union_map_domain(id));
696 multi = isl_union_map_subtract_range(multi, isl_union_map_wrap(id));
697 return isl_union_map_domain(multi);
700 /* Given two filter access relations, return a mapping between the domain
701 * elements of these access relations such that they access "the same filter".
702 * In particular, any pair of elements in the returned relation
703 * accesses at least one element in common, but if subset1 is set,
704 * then the set of elements accessed by the first is a subset of the
705 * set of elements accessed by the second. Similarly, if subset2 is set,
706 * then the set of elements accessed by the second is a subset of the
707 * set of elements accessed by the first. If both are set, then we further
708 * impose that both should access exactly one element.
709 * "space" is the space in which the result should live.
710 * Although "map1" and "map2" are allowed to have ranges in multiple spaces,
711 * their domains should live in a single space. "space" is the space
712 * of the relation between those two domains.
714 * Call the given maps A and B.
716 * A relation between domains elements of A and B that access at least
717 * one element in common can be obtained as
719 * A . B^-1
721 * To ensure that all elements accessed through A form a subset of
722 * the elements accessed through B, we compute join_non_empty_subset(A, B^-1).
724 * Ensuring that all elements accessed through B form a subset of
725 * the elements accessed through A is handled in a similar way.
727 * To remove those iterations that access more that one element,
728 * we compute those parts of the domains where A and B are multi-valued
729 * and subtract them from domain and range of the result.
731 static __isl_give isl_map *compute_common_filter(__isl_keep isl_union_map *map1,
732 bool subset1, __isl_keep isl_union_map *map2, bool subset2,
733 __isl_keep isl_space *space)
735 isl_union_map *reverse, *common;
736 isl_union_set *bad;
737 isl_map *res;
739 reverse = isl_union_map_reverse(isl_union_map_copy(map2));
741 if (subset1 && !subset2) {
742 common = join_non_empty_subset(isl_union_map_copy(map1),
743 reverse);
744 } else if (!subset1 && subset2) {
745 common = join_non_empty_superset(isl_union_map_copy(map1),
746 reverse);
747 } else {
748 common = isl_union_map_apply_range(isl_union_map_copy(map1),
749 reverse);
750 if (subset1 && subset2) {
751 bad = multi_valued(map1);
752 common = isl_union_map_subtract_domain(common, bad);
753 bad = multi_valued(map2);
754 common = isl_union_map_subtract_range(common, bad);
758 res = isl_union_map_extract_map(common, isl_space_copy(space));
759 isl_union_map_free(common);
760 return res;
763 /* Assuming "coa" is a (read) access, construct a union map from the domain
764 * of the access relation to the access relations of the corresponding
765 * writes. If we are unable to determine the corresponding writes, then
766 * return a map to the read access relation.
768 static __isl_give isl_union_map *extract_access_map(pdg::call_or_access *coa)
770 assert(coa->type == pdg::call_or_access::t_access);
771 return coa->access->extract_access_map();
774 /* Return a set that contains all possible filter values,
775 * where the possible values for a given filter is either as specified
776 * by the value_bounds property of the corresponding array or the universe.
778 static __isl_give isl_set *compute_filter_bounds(pdg::node *node)
780 isl_ctx *ctx;
781 isl_set *bounds;
783 ctx = isl_set_get_ctx(node->source->set);
785 bounds = isl_set_universe(isl_space_set_alloc(ctx, 0, 0));
786 for (int i = 0; i < node->filters.size(); ++i) {
787 isl_set *bnd;
788 pdg::array *array;
789 pdg::call_or_access *coa = node->filters[i];
790 assert(coa->type == pdg::call_or_access::t_access);
791 array = coa->access->array;
792 if (array->value_bounds)
793 bnd = array->value_bounds->get_isl_set();
794 else
795 bnd = isl_set_universe(isl_space_set_alloc(ctx, 0, 1));
796 bounds = isl_set_flat_product(bounds, bnd);
799 return bounds;
802 /* Return either the filter values themselves or their complement,
803 * taken with respect to the bounds on the filter values.
805 static __isl_give isl_map *compute_filter_values(pdg::node *node,
806 bool complement)
808 isl_set *bounds;
809 isl_map *value;
810 isl_map *res;
812 value = isl_set_unwrap(node->source->get_isl_set());
813 if (!complement)
814 return value;
816 bounds = compute_filter_bounds(node);
817 res = isl_map_from_domain_and_range(
818 isl_map_domain(isl_map_copy(value)), bounds);
819 res = isl_map_subtract(res, value);
821 return res;
824 /* Equate the first "n" input and output dimensions of "map"
825 * and return the result.
827 static __isl_give isl_map *share(__isl_take isl_map *map, int n)
829 for (int i = 0; i < n; ++i)
830 map = isl_map_equate(map, isl_dim_in, i, isl_dim_out, i);
832 return map;
835 /* Return the set of source iterations of "na" either at the last
836 * iteration (if valid is set) or after the last iteration
837 * (if valid is not set). "id" represents the control variable
838 * corresponding to the number of shared loops (__last_<na>_shared).
840 * In particlar, if valid is set, we return the set
842 * { S[i] : i = __last_<na> and
843 * __last_<na>_shared >= info->n_shared }
845 * If valid is not set, we return the set
847 * { S[i] : (i >> __last_<na> and __last_<na>_shared >= info->n_shared) or
848 * __last_<na>_shared < info->n_shared }
850 * That is, the iterations after the last if there is a last iteration
851 * with at least info->n_shared shared loops
852 * or just any iteration if there is no such last iteration.
854 * The lexicographic order i >> __last_<na> is imposed on the loop iterators
855 * that are affected by any filters.
857 static __isl_give isl_set *source_iterations(na_pair *na,
858 __isl_keep isl_id *id, bool valid, add_dep_info *info)
860 isl_space *space;
861 isl_set *set, *invalid;
862 isl_map *map_after;
863 int pos;
864 int depth;
866 space = isl_set_get_space(na->node->source->set);
867 space = isl_space_domain(isl_space_unwrap(space));
869 set = isl_set_universe(space);
870 set = add_parametrization(set, na, info);
872 if (valid)
873 return set;
875 depth = na->node->get_filter_depth();
877 space = isl_space_map_from_set(isl_set_get_space(set));
878 map_after = isl_map_lex_lt_first(space, depth);
879 map_after = share(map_after, info->n_shared);
880 map_after = isl_map_intersect_domain(map_after, set);
881 set = isl_map_range(map_after);
883 invalid = isl_set_universe(isl_set_get_space(set));
884 pos = isl_set_find_dim_by_id(invalid, isl_dim_param, id);
885 assert(pos >= 0);
886 invalid = isl_set_upper_bound_si(invalid,
887 isl_dim_param, pos, info->n_shared - 1);
888 set = isl_set_union(set, invalid);
890 return set;
893 /* Look for a matching between the filters of node1 and those of node2.
894 * That is look for pairs of filters of the two nodes that are "the same".
895 * Return true if any such matching can be found. The correspondence between
896 * the filters is returned in *same_value_p, while the pairs of iterations
897 * where the filters are the same is returned in *same_filter_p.
898 * The first "n_shared" dimensions of these iterations are guaranteed
899 * to be equal to each other.
901 * Two filter accesses are considered "the same" if they access at least
902 * one element in common. Moreover, if valid1 is false then the set
903 * of elements accessed by an element from node1 should be a subset
904 * of the set of elements accessed by the corresponding element from node2.
905 * Similarly for valid2.
907 * We perform a greedy search, checking if two filters could possibly
908 * match given the matchings we have performed before and updating
909 * the matching if it is indeed possible.
911 * Note that this function only computes one of the possibly many matchings.
913 static bool compute_matching(pdg::node *node1, bool valid1,
914 pdg::node *node2, bool valid2, __isl_give isl_map **same_filter_p,
915 __isl_give isl_map **same_value_p, int n_shared)
917 bool any = false;
918 isl_space *space1, *space2;
919 isl_map *same_filter;
920 isl_map *same_value;
922 space1 = isl_space_unwrap(isl_set_get_space(node1->source->set));
923 space2 = isl_space_unwrap(isl_set_get_space(node2->source->set));
924 space1 = isl_space_product(space1, space2);
925 space2 = isl_space_unwrap(isl_space_range(isl_space_copy(space1)));
926 space1 = isl_space_unwrap(isl_space_domain(space1));
928 same_filter = isl_map_universe(isl_space_copy(space1));
929 same_filter = share(same_filter, n_shared);
930 same_value = isl_map_universe(space2);
932 for (int i = 0; i < node1->filters.size(); ++i) {
933 isl_union_map *map_i;
934 pdg::call_or_access *filter_i = node1->filters[i];
935 pdg::array *array_i = get_filter_array(filter_i);
937 map_i = extract_access_map(node1->filters[i]);
939 for (int j = 0; j < node2->filters.size(); ++j) {
940 pdg::call_or_access *filter_j;
941 filter_j = node2->filters[j];
942 pdg::array *array_j = get_filter_array(filter_j);
943 isl_union_map *map_j;
944 isl_map *same_filter_ij;
946 if (array_i != array_j)
947 continue;
949 map_j = extract_access_map(node2->filters[j]);
950 same_filter_ij = compute_common_filter(map_i, !valid1,
951 map_j, !valid2,
952 space1);
953 same_filter_ij = isl_map_intersect(same_filter_ij,
954 isl_map_copy(same_filter));
955 if (isl_map_is_empty(same_filter_ij))
956 isl_map_free(same_filter_ij);
957 else {
958 any = true;
959 isl_map_free(same_filter);
960 same_filter = same_filter_ij;
961 same_value = isl_map_equate(same_value,
962 isl_dim_in, i,
963 isl_dim_out, j);
965 isl_union_map_free(map_j);
968 isl_union_map_free(map_i);
970 isl_space_free(space1);
972 if (any) {
973 *same_value_p = same_value;
974 *same_filter_p = same_filter;
975 } else {
976 isl_map_free(same_value);
977 isl_map_free(same_filter);
978 *same_value_p = NULL;
979 *same_filter_p = NULL;
982 return any;
985 /* Given a set of sink iterations "sink", mappings "map1" and "map2"
986 * from two potential sources to this sink,
987 * the possible filter values "value1" and "value2" at those
988 * potential sources, a relation "same_filter" between the two
989 * potential sources expressing when some filters of the two
990 * potential sources are the same and the correponding matching
991 * "same_value" between the filter values,
992 * remove those elements from the sink that have
993 * corresponding pairs of potential source iterations that should
994 * have the same filter values but do not.
996 * Let us call the sink S, the potential sources A and B and the
997 * corresponding filters F and G.
999 * We start from the mappings A[..] -> S[..] and B[..] -> S[..],
1000 * combine them into
1002 * S[..] -> [A[..] -> B[..]]
1004 * and intersect the range with the condition "same_filter" on A and B,
1005 * resulting in a mapping from sink iterations to pairs of potential
1006 * source iterations that should have the same filter values
1007 * (as specified by "same_value").
1009 * We subtract from the range of this mapping those pairs of
1010 * potential source iterations that actually have the same filter values.
1011 * The result is a mapping from sink iterations to pairs of potential
1012 * source iterations that should have the same filter values but do not.
1014 * The mapping between potential source iterations that have the
1015 * same filter values is obtained by combining the mappings
1016 * A[..] -> F[..] and B[..] -> G[..] into
1018 * [A[..] -> B[..]] -> [F[..] -> G[..]]
1020 * intersecting the range with "same_value" and then computing the domain.
1022 static __isl_give isl_set *remove_conflict(__isl_take isl_set *sink,
1023 __isl_take isl_map *map1, __isl_take isl_map *value1,
1024 __isl_take isl_map *map2, __isl_take isl_map *value2,
1025 __isl_take isl_map *same_filter, __isl_take isl_map *same_value)
1027 isl_map *value, *conflict;
1028 isl_set *conflict_set;
1030 conflict = isl_map_domain_product(map1, map2);
1031 conflict = isl_map_reverse(conflict);
1033 conflict = isl_map_intersect_range(conflict, isl_map_wrap(same_filter));
1035 value = isl_map_product(value1, value2);
1036 value = isl_map_intersect_range(value, isl_map_wrap(same_value));
1037 conflict = isl_map_subtract_range(conflict, isl_map_domain(value));
1039 conflict_set = isl_map_domain(conflict);
1041 sink = isl_set_subtract(sink, conflict_set);
1043 return sink;
1046 /* Remove inconsistencies from the set of sink iterations "sink"
1047 * based on two potential sources identified by "id1" and "id2"
1048 * (representing the number of shared loops),
1049 * in particular, on either the last iteration where the filters hold
1050 * (if valid? is set) or on later iterations (if valid? is not set).
1052 * Let us first consider the case where both "valid1" and "valid2" are set.
1053 * If the last iterations of the corresponding sources access the same
1054 * filters, then these filters should have the same value.
1055 * If a filter access accesses more than one element, then these elements
1056 * should all have the same value. It is therefore sufficient for the
1057 * two last iterations to access at least one element in common for there
1058 * to be a requirement that the corresponding values should be the same.
1059 * We therefore obtain the filter values, the mappings from the sink
1060 * to the last iterations, a matching between the
1061 * the filters of the corresponding sources and remove conflicts from "dep".
1063 * If one or both of the valid bits are not set, then we need to make
1064 * some changes. First the inconsistencies now do not arise from
1065 * the filter values at the last iteration, but from the filter values
1066 * lying _outside_ of the possible values for all iterations _after_
1067 * the "last" (i.e., the last iteration satisfying the filter constraints).
1068 * In case there is no last iteration with at least info->n_shared shared loops,
1069 * then the filter values should lie outside of the possible values
1070 * for any potential source iteration with info->n_shared shared loops.
1071 * Note however, that if the filter access relation accesses several
1072 * elements, then it is sufficient for one of those to have a value
1073 * outside of the possible values. We can therefore only consider
1074 * any inconsistencies for those cases where the set of accessed elements
1075 * forms a subset of the set of accessed elements through the other potential
1076 * source. If valid1 is not set, but valid2 is set, then we consider
1077 * those pairs of potential source iterations where the first accesses
1078 * a subset of the second and we impose that at least one of those
1079 * accessed elements has a valid outside the possible values.
1080 * Since those accessed elements form a subset of the elements accessed
1081 * by the other potential source, there is at least one element that
1082 * has a value outside of the posssible values on the first potential source
1083 * and a value belonging to the posssible values on the second potential source.
1084 * We can therefore impose that this value should exist.
1086 * If both valid1 and valid2 are not set, then we can only
1087 * impose a constraint on those pairs of iterations that access the same
1088 * single element. We then know that the value of this single element
1089 * accessed by both potential sources should lie outside of the possible
1090 * values on both sides.
1092 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
1093 add_dep_info *info, __isl_keep isl_id *id1, bool valid1,
1094 __isl_keep isl_id *id2, bool valid2)
1096 na_pair *write1_na, *write2_na;
1097 isl_set *source;
1098 isl_map *value1, *value2;
1099 isl_map *same_filter;
1100 isl_map *same_value;
1101 isl_map *mem1, *mem2;
1103 write1_na = (na_pair *) isl_id_get_user(id1);
1104 write2_na = (na_pair *) isl_id_get_user(id2);
1106 if (!compute_matching(write1_na->node, valid1, write2_na->node, valid2,
1107 &same_filter, &same_value, info->n_shared))
1108 return sink;
1110 value1 = compute_filter_values(write1_na->node, !valid1);
1111 value2 = compute_filter_values(write2_na->node, !valid2);
1113 mem1 = info->get_mem_dep(write1_na);
1114 source = source_iterations(write1_na, id1, valid1, info);
1115 mem1 = share(mem1, info->n_shared);
1116 mem1 = isl_map_intersect_domain(mem1, source);
1118 mem2 = info->get_mem_dep(write2_na);
1119 source = source_iterations(write2_na, id2, valid2, info);
1120 mem2 = share(mem2, info->n_shared);
1121 mem2 = isl_map_intersect_domain(mem2, source);
1123 sink = remove_conflict(sink, mem1, value1, mem2, value2,
1124 same_filter, same_value);
1126 return sink;
1129 /* Remove inconsistencies from the set of sink iterations "sink"
1130 * based on two potential sources identified by "id1" and "id2",
1131 * (representing the number of shared loops).
1133 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
1134 add_dep_info *info, __isl_keep isl_id *id1, __isl_keep isl_id *id2)
1136 sink = remove_inconsistencies(sink, info, id1, false, id2, false);
1137 sink = remove_inconsistencies(sink, info, id1, false, id2, true);
1138 sink = remove_inconsistencies(sink, info, id1, true, id2, false);
1139 sink = remove_inconsistencies(sink, info, id1, true, id2, true);
1140 return sink;
1143 /* Remove inconsistencies from the set of sink iterations "sink"
1144 * based on the potential source identified by "id"
1145 * (representing the number of shared loops),
1146 * in particular, on either the last iteration where the filters hold
1147 * (if valid is set) or on later iterations (if valid is not set).
1149 * This function is very similar to the remove_inconsistencies
1150 * function above that considers two potential sources instead
1151 * of the sink and one potential source. The main differences
1152 * are that for the sink, the filters always hold and that the mapping
1153 * from sink iterations to sink iterations is computed in a different
1154 * (and fairly trivial) way.
1156 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
1157 add_dep_info *info, __isl_keep isl_id *id, bool valid)
1159 na_pair *read_na, *write_na;
1160 isl_set *after;
1161 isl_map *value1, *value2;
1162 isl_map *same_filter;
1163 isl_map *same_value;
1164 isl_map *id_map, *mem;
1166 read_na = info->read_na_pair;
1167 write_na = (na_pair *) isl_id_get_user(id);
1169 if (!compute_matching(read_na->node, true, write_na->node, valid,
1170 &same_filter, &same_value, info->n_shared))
1171 return sink;
1173 value1 = compute_filter_values(read_na->node, false);
1174 value2 = compute_filter_values(write_na->node, !valid);
1176 id_map = isl_set_identity(isl_set_copy(sink));
1178 mem = info->get_mem_dep(write_na);
1179 after = source_iterations(write_na, id, valid, info);
1180 mem = share(mem, info->n_shared);
1181 mem = isl_map_intersect_domain(mem, after);
1183 sink = remove_conflict(sink, id_map, value1, mem, value2,
1184 same_filter, same_value);
1186 return sink;
1189 /* Remove inconsistencies from the set of sink iterations "sink"
1190 * based on the potential source identified by "id"
1191 * (representing the number of shared loops).
1193 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
1194 add_dep_info *info, __isl_keep isl_id *id)
1196 sink = remove_inconsistencies(sink, info, id, false);
1197 sink = remove_inconsistencies(sink, info, id, true);
1198 return sink;
1201 /* Remove all parameters that were introduced by add_parametrization().
1203 static __isl_give isl_map *remove_all_controls(__isl_take isl_map *dep)
1205 int i;
1206 int n_param;
1207 const char *name;
1209 n_param = isl_map_dim(dep, isl_dim_param);
1210 for (i = n_param - 1; i >= 0; --i) {
1211 if (!is_control(dep, i))
1212 continue;
1213 dep = isl_map_project_out(dep, isl_dim_param, i, 1);
1215 dep = isl_map_coalesce(dep);
1217 return dep;
1220 /* Remove all parameters that were introduced by add_parametrization().
1222 static __isl_give isl_set *remove_all_controls(__isl_take isl_set *set)
1224 int i;
1225 int n_param;
1226 const char *name;
1228 n_param = isl_set_dim(set, isl_dim_param);
1229 for (i = n_param - 1; i >= 0; --i) {
1230 if (!is_control(set, i))
1231 continue;
1232 set = isl_set_project_out(set, isl_dim_param, i, 1);
1234 set = isl_set_coalesce(set);
1236 return set;
1239 /* Create the map
1241 * { a -> b : (shared >= max and
1242 * the first max iterators are equal) or
1243 * (shared = max - 1 and
1244 * the first max - 1 iterators are equal and
1245 * dimension max - 1 of a is smaller than that of b) or
1246 * ...
1247 * (shared = min and
1248 * the first min iterators are equal and
1249 * dimension min of a is smaller than that of b) }
1251 static __isl_give isl_map *compute_shared_map(__isl_take isl_space *space,
1252 __isl_keep isl_id *shared_id, int min, int max)
1254 isl_map *shared_map;
1255 int shared_pos;
1257 shared_pos = isl_space_find_dim_by_id(space, isl_dim_param, shared_id);
1258 shared_map = isl_map_universe(isl_space_copy(space));
1259 shared_map = isl_map_lower_bound_si(shared_map, isl_dim_param,
1260 shared_pos, max);
1261 shared_map = share(shared_map, max);
1263 for (int i = min; i < max; ++i) {
1264 isl_map *shared_map_i;
1266 shared_map_i = isl_map_universe(isl_space_copy(space));
1267 shared_map_i = isl_map_fix_si(shared_map_i, isl_dim_param,
1268 shared_pos, i);
1269 shared_map_i = share(shared_map_i, i);
1270 shared_map_i = isl_map_order_lt(shared_map_i, isl_dim_in, i,
1271 isl_dim_out, i);
1273 shared_map = isl_map_union(shared_map, shared_map_i);
1276 isl_space_free(space);
1278 return shared_map;
1281 /* Different parts of the final dependence relations may have been
1282 * created at different depths and may therefore have a different
1283 * number of dimensions of the last iterator. The __last_<na>_shared
1284 * value determines how many of the dimensions are implicitly equal
1285 * to those of the sink iteration. This function creates a set that
1286 * makes these equalities explicit, so that we can later remove
1287 * the __last_<na>_shared parameter. It also marks those parts
1288 * that have a number of shared iterators that is smaller than the minimum
1289 * as not having any last iteration.
1291 * In particular, we create a set in the space of the sink of the form
1293 * { s : __last_<na>_valid = 0 or
1294 * (__last_<na>_valid = 1 and
1295 * __last_<na>_<i> is a potential source iteration and
1296 * ((__last_<na>_shared >= max_shared and
1297 * the first max_shared iterators are equal) or
1298 * (__last_<na>_shared = max_shared - 1 and
1299 * the first max_shared - 1 iterators are equal and
1300 * iterator max_shared - 1 of the source is smaller) or
1301 * ...
1302 * (__last_<na>_shared = min_shared and
1303 * the first min_shared iterators are equal and
1304 * iterator min_shared of the source is smaller))) }
1306 * That is, for those parts with __last_<na>_shared smaller than
1307 * max_n_shared[source_na], intersection with the set will introduce
1308 * __last_<na>_<i> parameters (assuming they don't have a known fixed value)
1309 * up until __last_<na>_shared and equate them to the corresponding iterators
1310 * of the sink.
1312 static __isl_give isl_set *shared_refinement(__isl_keep isl_id *shared_id,
1313 add_dep_info *info)
1315 isl_ctx *ctx;
1316 isl_space *space;
1317 isl_map *mem;
1318 na_pair *source_na;
1319 isl_map *shared_map;
1320 int valid_pos, shared_pos;
1321 isl_set *valid;
1322 isl_set *invalid;
1323 isl_set *domain;
1324 isl_id *valid_id;
1326 ctx = isl_id_get_ctx(shared_id);
1328 source_na = (na_pair *) isl_id_get_user(shared_id);
1329 valid_id = valid_bit_id(ctx, source_na);
1331 mem = info->get_mem_dep(source_na);
1332 space = isl_map_get_space(mem);
1333 isl_map_free(mem);
1335 shared_pos = isl_space_dim(space, isl_dim_param);
1336 space = isl_space_add_dims(space, isl_dim_param, 1);
1337 space = isl_space_set_dim_id(space, isl_dim_param,
1338 shared_pos, isl_id_copy(shared_id));
1340 shared_map = compute_shared_map(isl_space_copy(space), shared_id,
1341 info->min_n_shared[source_na], info->max_n_shared[source_na]);
1343 domain = isl_set_universe(isl_space_domain(space));
1344 valid_pos = find_or_add_param(&domain, isl_id_copy(valid_id));
1345 domain = isl_set_fix_si(domain, isl_dim_param, valid_pos, 1);
1346 domain = add_parametrization(domain, source_na, info);
1347 shared_map = isl_map_intersect_domain(shared_map, domain);
1349 valid = isl_map_range(shared_map);
1350 invalid = isl_set_universe(isl_set_get_space(valid));
1351 shared_pos = isl_set_find_dim_by_id(invalid, isl_dim_param, shared_id);
1352 invalid = isl_set_upper_bound_si(invalid, isl_dim_param, shared_pos,
1353 info->n_shared - 1);
1355 valid_pos = find_or_add_param(&invalid, valid_id);
1356 invalid = isl_set_fix_si(invalid, isl_dim_param, valid_pos, 0);
1358 return isl_set_union(valid, invalid);
1361 /* Different parts of the final dependence relations may have been
1362 * created at different depths and may therefore have a different
1363 * number of dimensions of the last iterator. The __last_*_shared
1364 * value determines how many of the dimensions are implicitly equal
1365 * to those of the sink iteration.
1367 * For each of the __last_*_shared parameters, explicitly add
1368 * the implicitly equal __last_*_i iterators by intersecting
1369 * the sink with the set computed by shared_refinement.
1370 * Finally, remove the __last_*_shared parameters.
1372 static __isl_give isl_map *refine_shared(__isl_take isl_map *dep,
1373 add_dep_info *info)
1375 isl_space *space;
1376 isl_set *refinement;
1377 int n_param;
1379 space = isl_map_get_space(dep);
1380 n_param = isl_space_dim(space, isl_dim_param);
1382 refinement = isl_set_universe(isl_space_range(isl_space_copy(space)));
1384 for (int i = 0; i < n_param; ++i) {
1385 isl_set *ref_i;
1386 isl_id *id;
1388 if (!is_shared(space, i))
1389 continue;
1390 if (!isl_map_involves_dims(dep, isl_dim_param, i, 1))
1391 continue;
1393 id = isl_space_get_dim_id(space, isl_dim_param, i);
1394 ref_i = shared_refinement(id, info);
1395 isl_id_free(id);
1397 if (isl_set_is_wrapping(refinement)) {
1398 isl_map *map = isl_set_unwrap(refinement);
1399 map = isl_map_intersect_domain(map, ref_i);
1400 refinement = isl_map_wrap(map);
1401 } else
1402 refinement = isl_set_intersect(refinement, ref_i);
1404 dep = isl_map_intersect_range(dep, refinement);
1406 isl_space_free(space);
1408 space = isl_map_get_space(dep);
1409 n_param = isl_space_dim(space, isl_dim_param);
1410 for (int i = n_param - 1; i >= 0; --i) {
1411 if (!is_shared(space, i))
1412 continue;
1413 dep = isl_map_project_out(dep, isl_dim_param, i, 1);
1415 isl_space_free(space);
1417 dep = isl_map_coalesce(dep);
1419 return dep;
1422 /* Compute the gist of "dep" with respect to the fact that
1424 * 0 <= __last_*_valid <= 1
1426 static __isl_give isl_map *gist_valid(__isl_take isl_map *dep)
1428 isl_space *space;
1429 isl_set *valid;
1430 int n_param;
1432 space = isl_space_params(isl_map_get_space(dep));
1433 n_param = isl_space_dim(space, isl_dim_param);
1435 valid = isl_set_universe(isl_space_copy(space));
1436 for (int i = 0; i < n_param; ++i) {
1437 if (!is_valid_bit(space, i))
1438 continue;
1440 valid = isl_set_lower_bound_si(valid, isl_dim_param, i, 0);
1441 valid = isl_set_upper_bound_si(valid, isl_dim_param, i, 1);
1444 isl_space_free(space);
1446 dep = isl_map_gist_params(dep, valid);
1448 return dep;
1451 /* Simplify the constraints on the parameters introduced
1452 * in add_parametrization().
1453 * We first add __last_*_i iterators that are only implicitly referred
1454 * to through the __last_*_shared parameters.
1455 * Then, we remove all those parameters that turn out not be needed.
1456 * If there are any of those parameters left, then we compute the gist
1457 * with respect to the valid bit being either 0 or 1 and rename
1458 * the parameters to also include a reference to the sink.
1459 * The resulting relation is assigned to controlled_relation,
1460 * while the relation field is assigned the result of projecting out
1461 * all those parameters.
1463 static __isl_give isl_map *simplify_controls(__isl_take isl_map *dep,
1464 add_dep_info *info, bool *has_controls)
1466 bool hs;
1468 if (!has_controls)
1469 has_controls = &hs;
1470 dep = refine_shared(dep, info);
1471 dep = remove_redundant_controls(dep, has_controls);
1472 if (*has_controls) {
1473 dep = gist_valid(dep);
1474 dep = rename_controls(dep, info->read_na_pair);
1477 return dep;
1480 /* Extract a single dependence from the result of dataflow analysis.
1482 * We first simplify the constraints on the parameters introduced
1483 * in add_parametrization().
1485 * If the dependence relation turns out to be empty, we simply return.
1486 * Otherwise, we create a corresponding pdg::dependence and keep track
1487 * of the fact that the potential source is actually used
1488 * so that we can remove any reference to potential sources that are
1489 * never used from the dependence relations.
1491 static int add_dep(__isl_take isl_map *dep, int must, void *dep_user, void *user)
1493 bool has_controls;
1494 na_pair *write_na = (na_pair *) dep_user;
1495 add_dep_info *info = (struct add_dep_info *)user;
1496 isl_ctx *ctx = info->pdg->get_isl_ctx();
1497 pdg::dependence *d;
1499 dep = isl_map_coalesce(dep);
1500 dep = simplify_controls(dep, info, &has_controls);
1501 if (isl_map_is_empty(dep)) {
1502 isl_map_free(dep);
1503 return 0;
1506 info->used.insert(write_na);
1508 d = new pdg::dependence;
1509 d->array = info->a;
1510 d->type = info->dtype;
1511 d->from = write_na->node;
1512 d->to = info->read_na_pair->node;
1513 d->from_access = write_na->access;
1514 d->to_access = info->read_na_pair->access;
1516 if (d->from_access->extension || d->to_access->extension)
1517 d->extended_relation =
1518 new pdg::IslMap(remove_all_controls(isl_map_copy(dep)));
1519 if (d->from_access->extension)
1520 dep = isl_map_apply_domain(dep,
1521 isl_map_reverse(
1522 d->from_access->extension->get_isl_map(ctx)));
1523 if (d->to_access->extension)
1524 dep = isl_map_apply_range(dep,
1525 isl_map_reverse(
1526 d->to_access->extension->get_isl_map(ctx)));
1527 if (has_controls)
1528 d->controlled_relation = new pdg::IslMap(isl_map_copy(dep));
1529 d->relation = new pdg::IslMap(remove_all_controls(isl_map_copy(dep)));
1530 info->pdg->dependences.push_back(d);
1531 isl_map_free(dep);
1532 return 0;
1535 /* This structure represents a set of filter index expressions
1536 * along with bounds on the correponding filter values.
1537 * The number of output dimensions in "value" is the same as
1538 * the number of elements in the "index" vector.
1540 struct da_filter {
1541 std::vector<isl_union_map *> index;
1542 isl_map *value;
1545 /* Construct a da_filter object representing the filters in
1546 * na->node and na->access.
1548 static struct da_filter *extract_filter(na_pair *na)
1550 da_filter *filter = new da_filter;
1551 isl_set *domain;
1552 pdg::node *node = na->node;
1553 pdg::access *access = na->access;
1555 domain = node->source->get_isl_set();
1556 if (isl_set_is_wrapping(domain))
1557 filter->value = isl_set_unwrap(domain);
1558 else
1559 filter->value = isl_map_from_domain(domain);
1561 for (int i = 0; i < node->filters.size(); ++i)
1562 filter->index.push_back(extract_access_map(node->filters[i]));
1564 if (access->nested.size() == 0)
1565 return filter;
1567 domain = isl_map_domain(access->map->get_isl_map());
1568 filter->value = isl_map_flat_range_product(filter->value,
1569 isl_set_unwrap(domain));
1571 for (int i = 0; i < access->nested.size(); ++i)
1572 filter->index.push_back(extract_access_map(access->nested[i]));
1574 return filter;
1577 static struct da_filter *da_filter_free(struct da_filter *filter)
1579 if (!filter)
1580 return NULL;
1581 for (int i = 0; i < filter->index.size(); ++i)
1582 isl_union_map_free(filter->index[i]);
1583 isl_map_free(filter->value);
1584 delete filter;
1585 return NULL;
1588 static void da_filter_dump(struct da_filter *filter)
1590 isl_printer *p;
1592 if (!filter)
1593 return;
1595 p = isl_printer_to_file(isl_map_get_ctx(filter->value), stderr);
1596 p = isl_printer_start_line(p);
1597 p = isl_printer_print_str(p, "value(");
1598 for (int i = 0; i < filter->index.size(); ++i) {
1599 if (i)
1600 p = isl_printer_print_str(p, ", ");
1601 p = isl_printer_print_union_map(p, filter->index[i]);
1603 p = isl_printer_print_str(p, ") in ");
1604 p = isl_printer_print_map(p, filter->value);
1605 p = isl_printer_end_line(p);
1607 isl_printer_free(p);
1610 /* Look for a filter index expression in "filter" that is identical
1611 * to "index". Return the index of this index expression if it is
1612 * found and the number of elements in filter->index otherwise.
1614 static int da_filter_find_exact_match(struct da_filter *filter,
1615 __isl_keep isl_union_map *index)
1617 for (int i = 0; i < filter->index.size(); ++i) {
1618 int equal;
1620 equal = isl_union_map_is_equal(filter->index[i], index);
1621 if (equal < 0)
1622 return -1;
1623 if (equal)
1624 return i;
1627 return filter->index.size();
1630 /* Add the index expression "index" to "filter" with an unconstrained
1631 * filter value. To ease debugging we set the name of the new filter
1632 * value dimension to that of the array being accessed by "index".
1633 * Although the range of "index" is allowed to live in more than
1634 * one space, we assume that they are all wrapped maps to the same
1635 * array space.
1637 static struct da_filter *da_filter_add(struct da_filter *filter,
1638 __isl_take isl_union_map *index)
1640 isl_id *id;
1641 isl_union_map *univ;
1642 isl_set *set;
1644 if (!filter || !index)
1645 goto error;
1647 filter->value = isl_map_add_dims(filter->value, isl_dim_out, 1);
1648 univ = isl_union_map_universe(isl_union_map_copy(index));
1649 univ = isl_union_set_unwrap(isl_union_map_range(univ));
1650 set = isl_set_from_union_set(isl_union_map_range(univ));
1651 id = isl_set_get_tuple_id(set);
1652 isl_set_free(set);
1653 filter->value = isl_map_set_dim_id(filter->value, isl_dim_out,
1654 filter->index.size(), id);
1655 if (!filter->value)
1656 goto error;
1657 filter->index.push_back(index);
1659 return filter;
1660 error:
1661 isl_union_map_free(index);
1662 da_filter_free(filter);
1663 return NULL;
1666 /* Intersect the set of possible filter values in "filter" with "value".
1668 static struct da_filter *da_filter_restrict(struct da_filter *filter,
1669 __isl_take isl_map *value)
1671 if (!filter || !value)
1672 goto error;
1674 filter->value = isl_map_intersect(filter->value, value);
1675 if (!filter->value)
1676 return da_filter_free(filter);
1678 return filter;
1679 error:
1680 isl_map_free(value);
1681 da_filter_free(filter);
1682 return NULL;
1685 /* Does "map" represent a total filter on "domain", i.e., one that is defined
1686 * on every element of "domain"?
1688 * Although the range of "map" may live in different spaces, we assume
1689 * that the domain of "map" lives in a single space.
1691 static int is_total_filter(__isl_keep isl_union_map *map,
1692 __isl_keep isl_set *domain)
1694 isl_union_set *map_domain;
1695 isl_set *set;
1696 int total;
1698 map_domain = isl_union_map_domain(isl_union_map_copy(map));
1699 set = isl_set_from_union_set(map_domain);
1700 total = isl_set_is_subset(domain, set);
1701 isl_set_free(set);
1703 return total;
1706 /* Does "node" have only total filters on "domain"?
1708 static int all_total_filters(pdg::node *node, __isl_take isl_set *domain)
1710 int total = 1;
1712 for (int i = 0; i < node->filters.size(); ++i) {
1713 isl_union_map *map = extract_access_map(node->filters[i]);
1715 total = is_total_filter(map, domain);
1716 isl_union_map_free(map);
1718 if (!total)
1719 break;
1722 isl_set_free(domain);
1723 return total;
1726 /* Does "node" have only total filters on the domain of "map"?
1728 static bool filters_total_on_domain(pdg::node *node, __isl_keep isl_map *map)
1730 return all_total_filters(node, isl_map_domain(isl_map_copy(map)));
1733 /* Does "node" have only total filters on the range of "map"?
1735 static bool filters_total_on_range(pdg::node *node, __isl_keep isl_map *map)
1737 return all_total_filters(node, isl_map_range(isl_map_copy(map)));
1740 /* Are the filters of "source_node" total on the range of "source_map"
1741 * and those of "sink_node" (if any) total on the domain of "soruce_map"?
1743 static bool total_filters(pdg::node *source_node, pdg::node *sink_node,
1744 __isl_keep isl_map *source_map)
1746 int total;
1748 total = filters_total_on_range(source_node, source_map);
1749 if (!total)
1750 return false;
1752 if (!isl_set_is_wrapping(sink_node->source->set))
1753 return true;
1755 total = filters_total_on_domain(sink_node, source_map);
1756 if (!total)
1757 return false;
1759 return true;
1762 /* Does "node" have any single valued filters?
1764 static int any_single_valued_filter(pdg::node *node)
1766 for (int i = 0; i < node->filters.size(); ++i) {
1767 isl_union_map *map = extract_access_map(node->filters[i]);
1768 int sv;
1770 sv = isl_union_map_is_single_valued(map);
1771 isl_union_map_free(map);
1773 if (sv)
1774 return sv;
1777 return 0;
1780 /* Construct a mapping from the source iterations to all source filter values
1781 * that allow some corresponding sink iteration(s) (according to "source_map")
1782 * to be executed. In other words, if any sink iteration is executed,
1783 * then we know that the filters of the corresponding source iterations
1784 * satisfy the returned relation.
1786 * The "filter" input represents what is known about the filter
1787 * values at the sink.
1789 * The "source" domain of the source is a wrapped map,
1790 * mapping iteration vectors to filter values.
1791 * We first construct a relation between the sink filter values (available
1792 * in "filter") and the source filter values. The purpose of this relation
1793 * is to find as much information about the source filter values
1794 * as possible. We can start with the value bounds on the arrays
1795 * accessed in the filters as they always hold.
1796 * Next, we loop over the source filters and check whether there
1797 * is any sink filter that covers the source filter.
1798 * In particular, for each source filter, we construct a map
1799 * from the source iteration domain to a wrapped access relation,
1800 * representing the write access relation that corresponds to
1801 * the filter read access. Note that if we were unable to determine this
1802 * write access, then the mapping returned by extract_access_map
1803 * maps to the original read access, which will not match with
1804 * any filter access relations of the sink.
1805 * We combine the constructed map with the proto-dependence
1806 * (source_map) to obtain a mapping from sink iterations to
1807 * access relations such that there is some source iteration that
1808 * may be the source of the given sink iteration (based on source_map)
1809 * and that the filter value at this source iteration was written by
1810 * that access. If the result is a subset of the mapping from the
1811 * sink iterations to the corresponding write access relation for some filter,
1812 * then we know that any constraint on this filter value also applies
1813 * to the source filter value. We therefore introduce an equality
1814 * in our mapping from sink filter values to source filter values.
1816 * When we apply the mapping from sink filter values to source filter values
1817 * to the mapping from source iterations to sink filter values, we
1818 * obtain a mapping from sink iterations to source filter values
1819 * that represents what we know about the source filter values.
1820 * That is, for each sink iteration in the domain of this map, if this
1821 * sink iteration is executed, then the actual source filter values
1822 * are an element of the image of the sink iteration.
1823 * In other words, the sink iteration is only executed if the source
1824 * filter values are an element of the image.
1825 * Mapping this relation back to the source through the proto-dependence
1826 * source_map, we obtain a relation from source iterations to all source
1827 * filter values for which any sink iteration is executed.
1828 * In particular, for values of the filters outside this relation,
1829 * no corresponding (according to source_map) sink is executed.
1831 static __isl_give isl_map *known_filter_values(struct da_filter *filter,
1832 na_pair *source_na, __isl_keep isl_map *source_map)
1834 isl_space *space, *space2;
1835 isl_map *source_value, *sink_value;
1836 isl_map *filter_map;
1837 isl_set *bounds;
1839 sink_value = isl_map_copy(filter->value);
1841 space = isl_set_get_space(source_na->node->source->set);
1842 space = isl_space_range(isl_space_unwrap(space));
1843 space2 = isl_space_range(isl_map_get_space(sink_value));
1844 space = isl_space_align_params(space, isl_space_copy(space2));
1845 space2 = isl_space_align_params(space2, isl_space_copy(space));
1846 space = isl_space_map_from_domain_and_range(space2, space);
1847 filter_map = isl_map_universe(space);
1849 bounds = compute_filter_bounds(source_na->node);
1850 filter_map = isl_map_intersect_range(filter_map, bounds);
1852 for (int i = 0; i < source_na->node->filters.size(); ++i) {
1853 isl_union_map *map_i;
1854 map_i = extract_access_map(source_na->node->filters[i]);
1855 map_i = isl_union_map_apply_range(
1856 isl_union_map_from_map(isl_map_copy(source_map)), map_i);
1857 for (int j = 0; j < filter->index.size(); ++j) {
1858 if (isl_union_map_is_subset(map_i, filter->index[j]))
1859 filter_map = isl_map_equate(filter_map,
1860 isl_dim_in, j, isl_dim_out, i);
1862 isl_union_map_free(map_i);
1865 source_value = isl_map_apply_range(sink_value, filter_map);
1866 source_value = isl_map_apply_domain(source_value,
1867 isl_map_copy(source_map));
1868 source_value = isl_map_coalesce(source_value);
1870 return source_value;
1873 /* Add a new output dimension to "map" with constraints that are the
1874 * same as those on output dimension "pos".
1876 * Given map { [i] -> [j] }, we first and an extra dimension,
1878 * { [i] -> [j,*] }
1880 * extract out j_pos,
1882 * { [[i] -> [j_0,...,j_{pos-1},*,j_{pos+1},...,*]] -> [j_pos] }
1884 * create a copy
1886 * { [[i] -> [j_0,...,j_{pos-1},*,j_{pos+1},...,*]] -> [j_pos,j_pos'] }
1888 * and then move the dimensions back
1890 * { [i] -> [j,j_pos'] }
1892 static __isl_give isl_map *copy_dim(__isl_take isl_map *map, int pos)
1894 int pos_new;
1896 pos_new = isl_map_dim(map, isl_dim_out);
1897 pos += isl_map_dim(map, isl_dim_in);
1898 pos_new += isl_map_dim(map, isl_dim_in);
1899 map = isl_map_add_dims(map, isl_dim_out, 1);
1900 map = isl_map_from_domain(isl_map_wrap(map));
1901 map = isl_map_add_dims(map, isl_dim_out, 1);
1902 map = isl_map_equate(map, isl_dim_in, pos, isl_dim_out, 0);
1903 map = isl_map_eliminate(map, isl_dim_in, pos, 1);
1904 map = isl_map_range_product(map, isl_map_copy(map));
1905 map = isl_map_equate(map, isl_dim_in, pos, isl_dim_out, 0);
1906 map = isl_map_equate(map, isl_dim_in, pos_new, isl_dim_out, 1);
1907 map = isl_set_unwrap(isl_map_domain(map));
1909 return map;
1912 /* Given constraints on the filter values "filter" at the sink iterations
1913 * "sink", derive additional constraints from the filter values of source
1914 * node "source_na". In particular, consider the iterations of "source_na"
1915 * that have _not_ been executed based on the constraints of the corresponding
1916 * last iteration parameters in "sink" and what this implies about the
1917 * filter values at those iterations.
1919 * Essentially, we consider all pairs of sink iterations and filter
1920 * elements, together with the corresponding non-executed source iterations
1921 * and the possible values of those filters. We universally quantify
1922 * the non-executed source iterations so that we obtain the intersection
1923 * of the constraints on the filter values over all those source iterations
1924 * and then existentially quantify the filter elements to obtain constraints
1925 * that are valid for all filter elements.
1927 * In more details, the computation is performed as follows.
1929 * Compute a mapping from potential last iterations of the other source
1930 * to sink iterations, taking into account the contraints on
1931 * the last executed iterations encoded in the parameters of "sink",
1932 * but projecting out all parameters encoding last iterations from the result.
1933 * Include all earlier iterations of the other source, resulting in
1934 * a mapping with a domain that includes all potential iterations of the
1935 * other source.
1937 * Subtract these iterations from all possible iterations of the other
1938 * source for a given sink iteration, resulting in a mapping from
1939 * potential source iterations that are definitely not executed
1940 * to the corresponding sink iteration.
1942 * If this map is empty, then this means we can't find any iterations
1943 * of the other source that are certainly not executed and then we
1944 * can't derive any further information.
1945 * Similarly, if the filters of source_na->node are not total
1946 * on the set of non-executed iterations, then we cannot draw any conclusions.
1947 * (Note that we already tested that the filters on sink->node are total
1948 * on the domain of "source_map". By intersecting the set of corresponding
1949 * sink iterations with this domain, we ensure that this property also holds
1950 * on those sink iterations.)
1951 * Otherwise, keep track of those sink iterations without any corresponding
1952 * non-executed other source iterations. We will lose these sink iterations
1953 * in subsequent computations, so we need to add them back in at the end.
1955 * Compute bounds on the filter values at the non executed iterations
1956 * based on what we know about filters at the sink and the fact that
1957 * the iterations are not executed, meaning that the filter values
1958 * do not satisfy the constraints that allow the iteration to be executed.
1959 * The result is a mapping T -> V.
1961 * Note that we only know that there is some accessed filter element
1962 * that does not satisfy the constraints that allow the iteration to be
1963 * executed. We therefore project out those dimensions that correspond
1964 * to filters with an access relation that is not single-valued, i.e.,
1965 * one that may access more than one element for some iterations.
1966 * If there are no single-valued filters, then we can skip the rest of
1967 * the computation.
1969 * Construct a mapping [K -> F] -> T, with K the sink iterations,
1970 * T the corresponding non-executed iterations of the other source and
1971 * F the filters accessed at those iterations.
1973 * Combine the above two mappings into a mapping [K -> F] -> V
1974 * such that the set of possible filter values (V) is the intersection
1975 * over all iterations of the other source that access the filter,
1976 * and such that there is at least one such iteration.
1977 * In other words, ensure that the range of [K -> F] -> T
1978 * is a non-empty subset of the range of V -> T.
1979 * We require a non-empty subset to ensure that the domain of
1980 * [K -> F] -> V is equal to the result of composing K -> T with T -> F.
1981 * Projecting out F from [K -> F] -> V, we obtain a map K -> V that is
1982 * the union of all possible values of the filters K -> F, i.e.,
1983 * the constraints that the values of K -> F satisfy.
1984 * If we didn't impose non-emptiness above, then the domain of [K -> F] -> V
1985 * would also include pairs that we are not interested in, related to
1986 * arbitrary values. Projecting out F would then also lead to arbitrary
1987 * values.
1989 * Compose the mapping K -> T with the index expressions, pulling them
1990 * back to the sink.
1991 * For each of these pulled back index expressions, we check if it
1992 * is equal to one of the sink filter index expressions. If not, we
1993 * add it to the sink filter index expressions.
1994 * In both cases, we keep track of the fact that this sink filter
1995 * should have a value that satisfies the constraints in K -> V.
1996 * We further check if there is any sink filter index expression
1997 * that is a (strict) subset of the pulled back index expression.
1998 * The value of any such sink filter should also satisfy those
1999 * constraints, so we duplicate the filter value in K -> V.
2001 * Finally, we intersect the possible filter values with the constraints
2002 * obtained above on the affected sink iterations and a universe range
2003 * on the unaffected sink iterations.
2005 static struct da_filter *include_other_source(struct da_filter *filter,
2006 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2007 na_pair *source_na, add_dep_info *info)
2009 isl_space *space, *space2;
2010 isl_set *source_domain;
2011 isl_map *mem;
2012 isl_map *may_run, *not_run;
2013 isl_map *source_value;
2014 isl_union_map *usource, *umap;
2015 std::vector<isl_union_map *> index;
2016 isl_union_map *index_product;
2017 isl_map *map;
2018 isl_map *filter_map;
2019 isl_set *unaffected_sink;
2020 isl_map *unaffected_value;
2022 if (source_na->node->filters.size() == 0)
2023 return filter;
2025 space = isl_set_get_space(source_na->node->source->set);
2026 space = isl_space_domain(isl_space_unwrap(space));
2027 source_domain = isl_set_universe(space);
2028 source_domain = add_parametrization(source_domain, source_na, info);
2029 may_run = isl_map_from_domain_and_range(source_domain,
2030 isl_set_copy(sink));
2031 may_run = share(may_run, info->n_shared);
2033 may_run = remove_all_controls(may_run);
2034 mem = info->get_mem_dep(source_na);
2035 mem = share(mem, info->n_shared);
2036 mem = isl_map_intersect_range(mem,
2037 isl_map_domain(remove_all_controls(isl_map_copy(source_map))));
2038 space = isl_space_domain(isl_map_get_space(may_run));
2039 may_run = isl_map_apply_domain(may_run, isl_map_lex_ge(space));
2040 not_run = isl_map_subtract(mem, may_run);
2042 if (isl_map_is_empty(not_run) ||
2043 !any_single_valued_filter(source_na->node) ||
2044 !filters_total_on_domain(source_na->node, not_run)) {
2045 isl_map_free(not_run);
2046 return filter;
2049 not_run = isl_map_reverse(not_run);
2050 source_value = known_filter_values(filter, source_na, not_run);
2051 source_value = isl_map_subtract(source_value,
2052 isl_set_unwrap(source_na->node->source->get_isl_set()));
2053 unaffected_sink = isl_set_copy(sink);
2054 unaffected_sink = remove_all_controls(unaffected_sink);
2055 unaffected_sink = isl_set_subtract(unaffected_sink,
2056 isl_map_domain(isl_map_copy(not_run)));
2058 for (int i = 0; i < source_na->node->filters.size(); ++i) {
2059 isl_union_map *map;
2060 int sv;
2062 map = extract_access_map(source_na->node->filters[i]);
2063 sv = isl_union_map_is_single_valued(map);
2064 if (sv) {
2065 index.push_back(map);
2066 } else {
2067 isl_union_map_free(map);
2068 source_value = isl_map_project_out(source_value,
2069 isl_dim_out, index.size(), 1);
2073 index_product = isl_union_map_copy(index[0]);
2074 for (int i = 1; i < index.size(); ++i)
2075 index_product = isl_union_map_range_product(index_product,
2076 isl_union_map_copy(index[1]));
2077 index_product = isl_union_map_reverse(index_product);
2078 index_product = isl_union_map_domain_product(
2079 isl_union_map_from_map(isl_map_copy(not_run)), index_product);
2081 usource = isl_union_map_from_map(source_value);
2082 usource = join_non_empty_subset(index_product, usource);
2083 umap = isl_union_map_universe(isl_union_map_copy(usource));
2084 umap = isl_union_set_unwrap(isl_union_map_domain(umap));
2085 umap = isl_union_map_domain_map(umap);
2086 usource = isl_union_map_apply_domain(usource, umap);
2087 source_value = isl_map_from_union_map(usource);
2089 for (int i = 0; i < index.size(); ++i)
2090 index[i] = isl_union_map_apply_range(
2091 isl_union_map_from_map(isl_map_copy(not_run)), index[i]);
2093 space = isl_space_range(isl_map_get_space(source_value));
2094 space2 = isl_space_range(isl_map_get_space(filter->value));
2095 space = isl_space_align_params(space, isl_space_copy(space2));
2096 space2 = isl_space_align_params(space2, isl_space_copy(space));
2097 space = isl_space_map_from_domain_and_range(space, space2);
2098 filter_map = isl_map_universe(space);
2100 for (int i = 0; i < index.size(); ++i) {
2101 int exact = da_filter_find_exact_match(filter, index[i]);
2102 assert(exact >= 0);
2103 if (exact == filter->index.size()) {
2104 filter = da_filter_add(filter,
2105 isl_union_map_copy(index[i]));
2106 filter_map = isl_map_add_dims(filter_map,
2107 isl_dim_out, 1);
2109 filter_map = isl_map_equate(filter_map, isl_dim_in, i,
2110 isl_dim_out, exact);
2111 for (int j = 0; j < filter->index.size(); ++j) {
2112 int pos;
2114 if (j == exact)
2115 continue;
2116 if (!isl_union_map_is_subset(filter->index[j],
2117 index[i]))
2118 continue;
2119 pos = isl_map_dim(source_value, isl_dim_out);
2120 source_value = copy_dim(source_value, i);
2121 filter_map = isl_map_add_dims(filter_map,
2122 isl_dim_in, 1);
2123 filter_map = isl_map_equate(filter_map, isl_dim_in, pos,
2124 isl_dim_out, j);
2128 source_value = isl_map_apply_range(source_value, filter_map);
2129 source_value = isl_map_coalesce(source_value);
2130 unaffected_value = isl_map_from_domain(unaffected_sink);
2131 unaffected_value = isl_map_add_dims(unaffected_value, isl_dim_out,
2132 filter->index.size());
2133 source_value = isl_map_union(source_value, unaffected_value);
2134 filter = da_filter_restrict(filter, source_value);
2136 for (int i = 0; i < index.size(); ++i)
2137 isl_union_map_free(index[i]);
2138 isl_map_free(not_run);
2140 return filter;
2143 /* Given constraints on the filter values "filter" at the sink iterations
2144 * "sink", derive additional constraints from the filter values of those
2145 * source nodes for which "sink" contains a reference to its last iteration,
2146 * for use in determining whether parametrization is needed on "source_map".
2147 * In particular, we try and derive extra information from the fact that
2148 * some iterations of those source nodes have _not_ been executed.
2150 static struct da_filter *include_other_sources(struct da_filter *filter,
2151 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2152 add_dep_info *info)
2154 isl_space *space;
2155 int n_param;
2157 space = isl_set_get_space(sink);
2158 n_param = isl_space_dim(space, isl_dim_param);
2159 for (int i = 0; i < n_param; ++i) {
2160 isl_id *id;
2161 na_pair *na;
2163 if (!is_shared(space, i))
2164 continue;
2166 id = isl_space_get_dim_id(space, isl_dim_param, i);
2167 na = (na_pair *) isl_id_get_user(id);
2168 isl_id_free(id);
2170 filter = include_other_source(filter, source_map, sink,
2171 na, info);
2173 isl_space_free(space);
2175 return filter;
2178 #define RESTRICT_ERROR -1
2179 #define RESTRICT_NO 0
2180 #define RESTRICT_EMPTY 1
2181 #define RESTRICT_INPUT 2
2182 #define RESTRICT_OUTPUT 3
2184 /* Given a map from sinks to potential sources (source_map)
2185 * and the set of sink iterations (sink),
2186 * check if any parametrization is needed on the sources.
2187 * That is, check whether the possible filter values at the sink
2188 * imply that the filter values at the source are always valid.
2189 * If so, the source is executed whenever the sink is executed
2190 * and no parametrization is required.
2192 * Return RESTRICT_NO if no parametrization is required.
2193 * Return RESTRICT_INPUT if parametrization is required on the input
2194 * of the computation of the last iteration.
2195 * Return RESTRICT_OUTPUT if parametrization is required on the output
2196 * of the computation of the last iteration. This means that we know
2197 * that the source will be executed, but we want to introduce a parameter
2198 * to represent the last iteration anyway, because the knowledge depends
2199 * on the parameters representing last iterations of other nodes.
2200 * Return RESTRICT_EMPTY if the potential sources cannot possibly
2201 * be executed, assuming that the sink is executed.
2203 * If there are no filters on the source, then obviously the source
2204 * is always executed.
2206 * If the filters of the sink and the source are not all total
2207 * on domain and range of "source_map", then we cannot draw any conclusion.
2208 * In principle, we could split up "source_map" according to whether
2209 * the filters would be total on the domain and range.
2211 * We first construct a mapping from source iterations to source filter
2212 * values that allow some corresponding sink iteration(s) (according to
2213 * "source_map") to be executed.
2214 * If this relation is a subset of the actual mapping from iteration
2215 * vectors to filter values at the source, then we know that a corresponding
2216 * sink is only executed when the source is executed and no parametrization
2217 * is required. However, we postpone the decision until we have considered
2218 * the other potential sources below.
2219 * If, on the other hand, the constructed relation is disjoint
2220 * from the source filter relation, then the sources cannot have
2221 * executed if the sink is executed. If so, we return
2222 * RESTRICT_EMPTY immediately.
2224 * Otherwise, we check if we can find out more information by considering
2225 * information derived from knowledge about the last iterations of other
2226 * nodes. If, by considering this extract information, we can find
2227 * that the potential source is never executed (given that the sink
2228 * is executed), then we return RESTRICT_EMPTY.
2229 * Otherwise, if we had already determined that the relation based
2230 * on only the sink is a subset of the filter values, then we return
2231 * RESTRICT_NO. If we can only draw this conclusion when taking into
2232 * account the other potential sources, then we return RESTRICT_OUTPUT.
2233 * Otherwise, we return RESTRICT_INPUT.
2235 static int need_parametrization(__isl_keep isl_map *source_map,
2236 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
2238 bool filtered_source;
2239 isl_space *space;
2240 isl_map *source_value, *sink_value;
2241 da_filter *filter;
2242 na_pair *sink_na = info->read_na_pair;
2243 int res;
2245 if (isl_map_plain_is_empty(source_map) ||
2246 isl_set_plain_is_empty(sink))
2247 return RESTRICT_NO;
2249 filtered_source = isl_set_is_wrapping(source_na->node->source->set);
2251 if (!filtered_source)
2252 return RESTRICT_NO;
2254 if (!total_filters(source_na->node, sink_na->node, source_map))
2255 return RESTRICT_INPUT;
2257 filter = extract_filter(sink_na);
2258 res = -1;
2259 if (filter->index.size() != 0) {
2260 sink_value = known_filter_values(filter, source_na, source_map);
2261 source_value = isl_set_unwrap(
2262 source_na->node->source->get_isl_set());
2264 if (isl_map_is_disjoint(sink_value, source_value))
2265 res = RESTRICT_EMPTY;
2266 else if (isl_map_is_subset(sink_value, source_value))
2267 res = RESTRICT_NO;
2268 isl_map_free(source_value);
2269 isl_map_free(sink_value);
2272 if (res == RESTRICT_EMPTY) {
2273 da_filter_free(filter);
2274 return res;
2277 filter = include_other_sources(filter, source_map, sink, info);
2279 if (!filter)
2280 return RESTRICT_ERROR;
2281 if (filter->index.size() == 0) {
2282 da_filter_free(filter);
2283 return RESTRICT_INPUT;
2286 sink_value = known_filter_values(filter, source_na, source_map);
2287 source_value = isl_set_unwrap(source_na->node->source->get_isl_set());
2289 if (isl_map_is_disjoint(sink_value, source_value))
2290 res = RESTRICT_EMPTY;
2291 else if (res == RESTRICT_NO)
2293 else if (isl_map_is_subset(sink_value, source_value))
2294 res = RESTRICT_OUTPUT;
2295 else
2296 res = RESTRICT_INPUT;
2298 isl_map_free(source_value);
2299 isl_map_free(sink_value);
2300 da_filter_free(filter);
2302 return res;
2305 extern "C" {
2306 static __isl_give isl_restriction *do_restrict(
2307 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2308 void *source_user, void *user);
2311 /* Add parameters corresponding to the last iteration of "na" to "set"
2312 * (assuming they don't already appear in "set")
2313 * and add constraints to them to express that there either is no
2314 * last iteration with info->n_shared shared loops
2315 * (__last_<na>_shared < info->n_shared) or that there is a last
2316 * iteration with at least info->n_shared shared loops
2317 * (__last_<na>_shared >= info->n_shared) and that the iteration is a possible
2318 * source of the current sink (based on the memory dependence between
2319 * the source and the sink).
2321 static __isl_give isl_set *set_parameter_bounds(__isl_take isl_set *set,
2322 na_pair *na, add_dep_info *info)
2324 isl_map *mem;
2325 isl_id *id;
2326 isl_set *valid;
2327 isl_set *invalid;
2328 isl_set *domain;
2329 int shared_pos;
2331 id = create_shared_id(isl_set_get_ctx(set), na);
2332 shared_pos = find_or_add_param(&set, id);
2334 valid = isl_set_copy(set);
2335 invalid = set;
2337 valid = isl_set_lower_bound_si(valid, isl_dim_param, shared_pos,
2338 info->n_shared);
2340 mem = info->get_mem_dep(na);
2341 domain = isl_set_universe(isl_space_domain(isl_map_get_space(mem)));
2342 domain = add_parametrization(domain, na, info);
2343 mem = isl_map_intersect_domain(mem, domain);
2344 valid = isl_set_intersect(valid, isl_map_range(mem));
2346 invalid = isl_set_upper_bound_si(invalid, isl_dim_param, shared_pos,
2347 info->n_shared - 1);
2349 return isl_set_union(valid, invalid);
2352 /* Check if there are any iterations of "source_na" in "source_map"
2353 * that are definitely executed, based solely on the possible filter values.
2354 * If so, add constraints to "sink" to indicate that the last execution
2355 * cannot be earlier than those definitely executed iterations.
2357 * We first compute the set of source iterations that are definitely
2358 * executed because there are no filter values that would prohibit
2359 * their execution. If there are no such source iterations then we are done.
2361 * Then we construct a map from sink iterations to associated (through
2362 * "source_map") definitely executed source iterations.
2364 * For those sink iterations that have a corresponding definitely
2365 * executed source iteration, we add constraints that express that
2366 * this last definitely executed source iteration is lexicographically
2367 * smaller than or equal to the last executed source iteration
2368 * (and that there definitely is a last executed source iteration).
2370 static __isl_give isl_set *mark_definite_source(__isl_take isl_set *sink,
2371 add_dep_info *info, na_pair *source_na, __isl_keep isl_map *source_map)
2373 isl_space *space;
2374 isl_set *dom;
2375 isl_map *invalid;
2376 isl_map *definite_source_map;
2377 isl_set *with_source;
2378 isl_map *map_after;
2379 int depth;
2381 dom = source_na->node->source->get_isl_set();
2382 dom = isl_map_domain(isl_set_unwrap(dom));
2383 invalid = compute_filter_values(source_na->node, true);
2384 dom = isl_set_subtract(dom, isl_map_domain(invalid));
2386 if (isl_set_is_empty(dom)) {
2387 isl_set_free(dom);
2388 return sink;
2391 space = isl_set_get_space(dom);
2393 definite_source_map = isl_map_copy(source_map);
2394 definite_source_map = isl_map_intersect_range(source_map, dom);
2396 dom = isl_map_domain(isl_map_copy(definite_source_map));
2398 with_source = isl_set_copy(sink);
2399 with_source = isl_set_intersect(with_source, isl_set_copy(dom));
2400 sink = isl_set_subtract(sink, dom);
2402 dom = isl_set_universe(isl_space_copy(space));
2403 dom = add_parametrization(dom, source_na, info);
2405 depth = source_na->node->get_filter_depth();
2407 space = isl_space_map_from_set(space);
2408 map_after = isl_map_lex_ge_first(space, depth);
2409 dom = isl_set_apply(dom, map_after);
2411 definite_source_map = isl_map_intersect_range(definite_source_map, dom);
2413 dom = isl_map_domain(definite_source_map);
2414 with_source = isl_set_intersect(with_source, dom);
2416 sink = isl_set_union(sink, with_source);
2418 return sink;
2421 /* Remove inconsistencies from the set of sink iterations "sink"
2422 * based on the current potential source "source_na" and other
2423 * potential sources referenced by "sink".
2425 * We first identify those iterations of "source_na" that are
2426 * definitely executed based solely on the possible filter values.
2428 * If the sink has filters, then we remove inconsistencies based
2429 * on the sink and the current potential source.
2431 * Finally, we go through the references to other potential sources
2432 * in "sink" and remove inconsistencies based on this other potential
2433 * source and the current potential source.
2435 static __isl_give isl_set *remove_inconsistencies(__isl_take isl_set *sink,
2436 add_dep_info *info, na_pair *source_na, __isl_keep isl_map *source_map)
2438 isl_space *space;
2439 isl_id *source_id;
2440 int n_param;
2442 source_id = create_shared_id(isl_map_get_ctx(source_map), source_na);
2444 sink = mark_definite_source(sink, info, source_na, source_map);
2446 if (isl_set_is_wrapping(info->read_na_pair->node->source->set))
2447 sink = remove_inconsistencies(sink, info, source_id);
2449 space = isl_set_get_space(sink);
2450 n_param = isl_space_dim(space, isl_dim_param);
2451 for (int i = 0; i < n_param; ++i) {
2452 isl_id *other_id;
2454 if (!is_shared(space, i))
2455 continue;
2456 other_id = isl_space_get_dim_id(space, isl_dim_param, i);
2458 if (other_id != source_id) {
2459 na_pair *other_na;
2461 other_na = (na_pair *) isl_id_get_user(other_id);
2462 sink = set_parameter_bounds(sink, other_na, info);
2463 sink = remove_inconsistencies(sink, info, other_id,
2464 source_id);
2467 isl_id_free(other_id);
2469 isl_space_free(space);
2471 isl_id_free(source_id);
2472 return sink;
2475 /* Compute a restriction for the given sink.
2476 * That is, add constraints to the parameters expressing
2477 * that the source is either not executed with info->n_shared shared
2478 * iterators (*_shared < info->n_shared)
2479 * or it is executed (*_shared >= info->n_shared) and then the last iteration
2480 * satisfies the corresponding memory based dependence.
2482 * Only do this for that part of "sink" that has any corresponding
2483 * sources in "source_map". The remaining part of "sink" is not affected.
2485 * Note that the "sink" set may have undergone a refinement based
2486 * on the _shared parameters and we want this refinement to also
2487 * be present in the sink restriction. We therefore need
2488 * to intersect the affected part with "sink".
2490 static __isl_give isl_set *compute_sink_restriction(
2491 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
2492 na_pair *source_na, add_dep_info *info)
2494 isl_set *with_source, *without_source;
2496 with_source = isl_map_domain(isl_map_copy(source_map));
2497 without_source = isl_set_subtract(isl_set_copy(sink),
2498 isl_set_copy(with_source));
2499 with_source = isl_set_intersect(with_source, isl_set_copy(sink));
2501 with_source = set_parameter_bounds(with_source, source_na, info);
2502 with_source = remove_inconsistencies(with_source, info, source_na,
2503 source_map);
2505 return isl_set_union(with_source, without_source);
2508 /* How many loops do "node1" and "node2" share?
2510 static int max_shared(pdg::node *node1, pdg::node *node2)
2512 int shared = 0;
2513 int size = node1->prefix.size();
2515 if (node2->prefix.size() < size)
2516 size = node2->prefix.size();
2518 for (int i = 0; i < size && node1->prefix[i] == node2->prefix[i]; ++i)
2519 if (node1->prefix[i] == -1)
2520 ++shared;
2522 return shared;
2525 /* Determine the number of shared loop iterators between sink
2526 * and source domains in "sink2source". That is, find out how
2527 * many of the initial input and output dimensions are equal
2528 * to each other. Return the result.
2530 * The first time this function is called for a given sink access
2531 * (info->n_shared is set to -1 in add_dep_info::set_read_na),
2532 * we check for equal dimensions up to the shared nesting depth.
2533 * Later call check dimensions up to the result of the previous call.
2535 static int extract_shared_levels(__isl_keep isl_map *sink2source,
2536 na_pair *source_na, add_dep_info *info)
2538 int i;
2539 int max;
2540 isl_space *space;
2542 max = info->n_shared;
2543 if (max < 0)
2544 max = max_shared(source_na->node, info->read_na_pair->node);
2546 if (max == 0)
2547 return info->n_shared = 0;
2549 space = isl_map_get_space(sink2source);
2550 for (i = 0; i < max; ++i) {
2551 isl_map *test;
2552 int subset;
2554 test = isl_map_universe(isl_space_copy(space));
2555 test = isl_map_equate(test, isl_dim_in, i, isl_dim_out, i);
2556 subset = isl_map_is_subset(sink2source, test);
2557 isl_map_free(test);
2559 if (!subset)
2560 break;
2562 isl_space_free(space);
2564 return i;
2567 /* The last iteration referred to by the sink may have been added
2568 * at a different nesting level. This means that __last_<na>_shared
2569 * is greater than or equal to a value greater than info->n_shared
2570 * and that therefore the iterators between info->n_shared and
2571 * __last_<na>_shared are not represented as they are implicitly
2572 * considered to be equal to the corresponding sink iterator.
2573 * For consistency, we need to explicitly add those iterators
2574 * and set them to be equal to the corresponding sink iterator.
2576 * In particular, we create a set in the space of the sink of the form
2578 * { s : __last_<na>_shared < info->n_shared or
2579 * (__last_<na>_<i> is a potential source iteration for s and
2580 * (__last_<na>_shared >= max_shared or
2581 * (__last_<na>_shared = max_shared - 1 and
2582 * the first max_shared - 1 iterators are equal and
2583 * iterator max_shared - 1 of the source is smaller) or
2584 * ...
2585 * (__last_<na>_shared = info->n_shared and
2586 * the first n_shared iterators are equal and
2587 * iterator n_shared of the source is smaller))) }
2589 * That is, for those parts with __last_<na>_shared smaller than
2590 * max_n_shared[source_na], intersection with the set will introduce
2591 * __last_<na>_<i> parameters (assuming they don't have a known fixed value)
2592 * up until __last_<na>_shared and equate them to the corresponding iterators
2593 * of the sink.
2595 static __isl_give isl_set *internal_shared_refinement(
2596 __isl_keep isl_id *shared_id, add_dep_info *info)
2598 isl_map *mem;
2599 na_pair *source_na;
2600 isl_set *domain;
2601 isl_map *shared_map;
2602 int shared_pos;
2603 isl_set *valid;
2604 isl_set *invalid;
2606 source_na = (na_pair *) isl_id_get_user(shared_id);
2608 mem = info->get_mem_dep(source_na);
2609 domain = isl_set_universe(isl_space_domain(isl_map_get_space(mem)));
2610 domain = add_parametrization(domain, source_na, info);
2611 mem = isl_map_intersect_domain(mem, domain);
2613 shared_map = compute_shared_map(isl_map_get_space(mem), shared_id,
2614 info->n_shared, info->max_n_shared[source_na]);
2616 mem = isl_map_intersect(mem, shared_map);
2618 valid = isl_map_range(mem);
2619 invalid = isl_set_universe(isl_set_get_space(valid));
2620 shared_pos = isl_set_find_dim_by_id(invalid, isl_dim_param, shared_id);
2621 invalid = isl_set_upper_bound_si(invalid, isl_dim_param, shared_pos,
2622 info->n_shared - 1);
2624 return isl_set_union(valid, invalid);
2627 /* The last iteration of some source referred to by the sink may have been
2628 * added at a different nesting level. This means that __last_*_shared
2629 * is greater than or equal to a value greater than info->n_shared
2630 * and that therefore the iterators between info->n_shared and
2631 * __last_*_shared are not represented as they are implicitly
2632 * considered to be equal to the corresponding sink iterator.
2633 * For consistency, we need to explicitly add those iterators
2634 * and set them to be equal to the corresponding sink iterator.
2636 * For each of the __last_*_shared parameters, explicitly add
2637 * the implicitly equal __last_*_i iterators by intersecting
2638 * the sink with the set computed by internal_shared_refinement.
2640 static __isl_give isl_set *refine_shared_internal(__isl_take isl_set *sink,
2641 add_dep_info *info)
2643 isl_space *space;
2644 isl_set *refinement;
2645 int n_param;
2647 space = isl_set_get_space(sink);
2648 refinement = isl_set_universe(isl_space_copy(space));
2650 n_param = isl_space_dim(space, isl_dim_param);
2651 for (int i = 0; i < n_param; ++i) {
2652 isl_set *ref_i;
2653 isl_id *id;
2655 if (!is_shared(space, i))
2656 continue;
2658 id = isl_space_get_dim_id(space, isl_dim_param, i);
2659 ref_i = internal_shared_refinement(id, info);
2660 isl_id_free(id);
2661 refinement = isl_set_intersect(refinement, ref_i);
2663 isl_space_free(space);
2665 sink = isl_set_intersect(sink, refinement);
2667 return sink;
2670 /* Given a map from sinks to potential sources (sink2source),
2671 * check if any parametrization is needed.
2672 * Depending on the result, return either a universe restriction,
2673 * an empty restriction (if the sources cannot have executed),
2674 * a restriction that parametrizes the source and the sink
2675 * of the input of the computation of the last source
2676 * or a restriction that parametrizes the source of the output.
2678 * sink_map maps the domain of sink2source to the sink iteration domain.
2679 * source_map maps the range of sink2source to the source iteration domain.
2681 * Before we check if we need any parametrization, we update the number of
2682 * shared loop levels and add possibly missing __last_*_i iterators
2683 * (in refine_shared_internal). If parametrization turns out to be required,
2684 * we also update the minimal number of shared loop levels for the given
2685 * source.
2687 static __isl_give isl_restriction *compute_restriction_core(
2688 __isl_keep isl_map *sink2source,
2689 __isl_take isl_map *sink_map, __isl_take isl_map *source_map,
2690 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
2692 isl_space *space;
2693 isl_set *source_restr;
2694 isl_set *sink_restr;
2695 int need;
2697 sink2source = isl_map_copy(sink2source);
2698 sink = isl_set_copy(sink);
2700 sink2source = isl_map_apply_range(sink2source,
2701 isl_map_copy(source_map));
2702 sink2source = isl_map_apply_domain(sink2source,
2703 isl_map_copy(sink_map));
2704 sink = isl_set_apply(sink, isl_map_copy(sink_map));
2706 info->n_shared = extract_shared_levels(sink2source, source_na, info);
2707 sink = refine_shared_internal(sink, info);
2709 need = need_parametrization(sink2source, sink, source_na, info);
2710 if (need == RESTRICT_ERROR ||
2711 need == RESTRICT_NO || need == RESTRICT_EMPTY) {
2712 isl_map_free(source_map);
2713 isl_map_free(sink_map);
2714 isl_set_free(sink);
2715 if (need == RESTRICT_ERROR) {
2716 isl_map_free(sink2source);
2717 return NULL;
2718 } else if (need == RESTRICT_NO)
2719 return isl_restriction_none(sink2source);
2720 else
2721 return isl_restriction_empty(sink2source);
2724 info->update_min_n_shared(source_na);
2726 space = isl_map_get_space(source_map);
2727 source_restr = isl_set_universe(isl_space_range(space));
2729 source_restr = add_parametrization(source_restr, source_na, info);
2730 source_restr = isl_set_apply(source_restr, isl_map_reverse(source_map));
2732 if (need == RESTRICT_OUTPUT) {
2733 isl_map_free(sink_map);
2734 isl_set_free(sink);
2735 isl_map_free(sink2source);
2736 return isl_restriction_output(source_restr);
2739 sink_restr = compute_sink_restriction(sink2source, sink,
2740 source_na, info);
2741 sink_restr = isl_set_apply(sink_restr, isl_map_reverse(sink_map));
2743 isl_set_free(sink);
2744 isl_map_free(sink2source);
2746 return isl_restriction_input(source_restr, sink_restr);
2749 /* Compute a restriction for the given map from sinks to potential sources
2750 * (sink2source).
2752 * First check if the sink access has any filters. If so, compose the original
2753 * sink_map with a mapping that projects out these access filters.
2754 * Handle the source access similarly.
2755 * Then call compute_restriction_core to perform the main computation.
2757 static __isl_give isl_restriction *compute_restriction(
2758 __isl_keep isl_map *sink2source,
2759 __isl_take isl_map *sink_map, __isl_take isl_map *source_map,
2760 __isl_keep isl_set *sink, na_pair *source_na, add_dep_info *info)
2762 na_pair *sink_na = info->read_na_pair;
2764 if (sink_na->access->nested.size() > 0) {
2765 isl_space *space;
2766 isl_map *map;
2768 space = isl_space_range(isl_map_get_space(sink_map));
2769 space = isl_space_unwrap(space);
2770 map = isl_map_domain_map(isl_map_universe(space));
2772 sink_map = isl_map_apply_range(sink_map, map);
2775 if (source_na->access->nested.size() > 0) {
2776 isl_space *space;
2777 isl_map *map;
2779 space = isl_space_range(isl_map_get_space(source_map));
2780 space = isl_space_unwrap(space);
2781 map = isl_map_domain_map(isl_map_universe(space));
2783 source_map = isl_map_apply_range(source_map, map);
2786 return compute_restriction_core(sink2source, sink_map, source_map,
2787 sink, source_na, info);
2790 /* Compute a restriction for the given map from sinks to potential sources
2791 * (sink2source). We simply call compute_restriction to compute the
2792 * restriction. Since, unlike the case of do_restrict_domain_map bewloe,
2793 * we didn't encode the entire access relation in the domains of the input
2794 * to isl_access_info_compute_flow, we pass identity mappings on the source
2795 * and sink to compute_restriction.
2797 static __isl_give isl_restriction *do_restrict(__isl_keep isl_map *sink2source,
2798 __isl_keep isl_set *sink, void *source_user, void *user)
2800 na_pair *source_na = (na_pair *) source_user;
2801 add_dep_info *info = (struct add_dep_info *) user;
2802 isl_space *space;
2803 isl_map *source_map;
2804 isl_map *sink_map;
2806 space = isl_space_domain(isl_map_get_space(sink2source));
2807 sink_map = isl_map_identity(isl_space_map_from_set(space));
2808 space = isl_space_range(isl_map_get_space(sink2source));
2809 source_map = isl_map_identity(isl_space_map_from_set(space));
2811 return compute_restriction(sink2source, sink_map, source_map,
2812 sink, source_na, info);
2815 /* Does the iteration domain of any of the writes involve any filters?
2817 static bool any_filters(vector<na_pair> &writers)
2819 for (int i = 0; i < writers.size(); ++i)
2820 if (isl_set_is_wrapping(writers[i].node->source->set))
2821 return true;
2822 return false;
2825 /* Does any of the dependences starting at "first" have
2826 * controlled dependence relation?
2828 static bool any_controlled_dependences(PDG *pdg, int first)
2830 for (int i = first; i < pdg->dependences.size(); ++i)
2831 if (pdg->dependences[i]->controlled_relation)
2832 return true;
2834 return false;
2837 /* Remove parameters from "map" that start with "prefix".
2839 static __isl_give isl_map *remove_source(__isl_take isl_map *map,
2840 const char *prefix)
2842 int n = isl_map_dim(map, isl_dim_param);
2843 size_t len = strlen(prefix);
2845 for (int i = n - 1; i >= 0; --i) {
2846 const char *name;
2848 name = isl_map_get_dim_name(map, isl_dim_param, i);
2849 if (strncmp(name, prefix, len))
2850 continue;
2852 map = isl_map_project_out(map, isl_dim_param, i, 1);
2855 map = isl_map_coalesce(map);
2857 return map;
2860 /* Remove parameters from the dependences starting at "first"
2861 * that refer to any of the unused potential sources, i.e.,
2862 * those potential sources that are in writers, but not in info->used.
2864 * Since the current sink does not depend on those unused potential sources,
2865 * the corresponding dependence relations cannot depend on them and
2866 * any reference to them can simply be projected out.
2868 static void remove_unused_sources(PDG *pdg, int first,
2869 vector<na_pair> &writers, add_dep_info *info)
2871 char name[60];
2872 std::vector<na_pair *> unused;
2874 for (int i = 0; i < writers.size(); ++i) {
2875 if (info->used.find(&writers[i]) == info->used.end())
2876 unused.push_back(&writers[i]);
2879 if (unused.size() == 0)
2880 return;
2881 if (!any_controlled_dependences(pdg, first))
2882 return;
2884 for (int i = 0; i < unused.size(); ++i) {
2885 na_pair *na = unused[i];
2887 snprintf(name, sizeof(name), "__last_%s_%d_",
2888 na->node->name->s.c_str(), na->access->nr);
2890 for (int j = first; j < pdg->dependences.size(); ++j) {
2891 pdg::dependence *dep = pdg->dependences[j];
2892 isl_map *map;
2894 if (!dep->controlled_relation)
2895 continue;
2897 map = dep->controlled_relation->map;
2898 map = remove_source(map, name);
2899 dep->controlled_relation->map = map;
2904 /* Look for the unique write access that writes to the array accessed
2905 * by "a" and return an na_pair consisting of the node in which the
2906 * access is performed and the access itself.
2908 static na_pair find_unique_source(pdg::PDG* pdg, pdg::array *a)
2910 for (int i = 0; i < pdg->nodes.size(); ++i) {
2911 pdg::node *node = pdg->nodes[i];
2912 pdg::statement *s = pdg->nodes[i]->statement;
2913 for (int j = 0; j < s->accesses.size(); ++j) {
2914 pdg::access *access = s->accesses[j];
2915 if (access->array != a)
2916 continue;
2917 if (access->type != pdg::access::write)
2918 continue;
2919 return na_pair(node, access);
2923 assert(0);
2926 /* Add a dependence from (source_node, source_access) to
2927 * (sink_node, sink_access) to pdg->dependences, for the
2928 * case where the array being accessed is marked uniquely_defined.
2930 * Since the array is marked uniquely_defined, the value based
2931 * dependence is equal to the memory based dependence, so we
2932 * simply need to compose the access relations to obtain
2933 * the dependence relation.
2934 * This dependence relation is then specialized with respect to
2935 * the context and the iteration domain of the sink.
2937 static void add_unique_dep(PDG *pdg, pdg::node *source_node,
2938 pdg::access *source_access, pdg::node *sink_node,
2939 pdg::access *sink_access)
2941 pdg::dependence *d;
2942 isl_set *dom;
2943 isl_map *dep;
2944 isl_map *read;
2946 d = new pdg::dependence;
2947 d->array = source_access->array;
2948 d->type = pdg::dependence::flow;
2949 d->from = source_node;
2950 d->to = sink_node;
2951 d->from_access = source_access;
2952 d->to_access = sink_access;
2954 dep = source_access->map->get_isl_map();
2955 read = sink_access->map->get_isl_map();
2956 dep = isl_map_apply_range(dep, isl_map_reverse(read));
2957 dom = sink_node->source->get_isl_set();
2958 if (isl_set_is_wrapping(dom))
2959 dom = isl_map_domain(isl_set_unwrap(dom));
2960 dep = isl_map_intersect_range(dep, dom);
2961 dep = isl_map_intersect_params(dep, pdg->get_context_isl_set());
2962 d->relation = new pdg::IslMap(dep);
2964 pdg->dependences.push_back(d);
2967 /* Find the flow dependences associated to the array "a", which is marked
2968 * uniquely_defined, and add them to pdg->dependences.
2970 * First determine the unique source and then iterate through all the reads,
2971 * adding dependences from the unique source to each of the reads.
2973 static void find_unique_deps(PDG *pdg, pdg::array *a)
2975 na_pair na = find_unique_source(pdg, a);
2977 for (int i = 0; i < pdg->nodes.size(); ++i) {
2978 pdg::node *node = pdg->nodes[i];
2979 pdg::statement *s = pdg->nodes[i]->statement;
2980 for (int j = 0; j < s->accesses.size(); ++j) {
2981 pdg::access *access = s->accesses[j];
2982 if (access->array != a)
2983 continue;
2984 if (access->type != pdg::access::read)
2985 continue;
2986 add_unique_dep(pdg, na.node, na.access, node, access);
2991 /* Find the dependence of type "t" associated to array "a" and add them
2992 * to pdg->dependences.
2994 * If we are looking for flow dependences for an array that is marked
2995 * uniquely_defined, then we do not need to compute anything, but instead
2996 * can simply read off the dependences in find_unique_deps.
2998 void find_deps(PDG* pdg, pdg::array *a, type t)
3000 isl_ctx *ctx = pdg->get_isl_ctx();
3001 int nparam = pdg->params.size();
3002 int selfinput = 0;
3003 int reuse = 0;
3004 int firstuse = 0;
3005 add_dep_info info = { pdg, a, t };
3006 isl_set *context;
3007 bool need_parametrization;
3009 switch (t) {
3010 case flow:
3011 info.dtype = pdg::dependence::flow;
3012 firstuse = 1;
3013 break;
3014 case anti:
3015 info.dtype = pdg::dependence::anti;
3016 break;
3017 case data_reuse:
3018 info.dtype = pdg::dependence::reuse;
3019 reuse = 1;
3020 firstuse = 1;
3021 break;
3022 case reuse_pair:
3023 info.dtype = pdg::dependence::reuse_pair;
3024 break;
3025 case output:
3026 info.dtype = pdg::dependence::output;
3027 break;
3030 a->analysis_performed.push_back(new pdg::dependence_type(info.dtype));
3032 if (t == flow && a->uniquely_defined) {
3033 find_unique_deps(pdg, a);
3034 return;
3037 vector<na_pair> readers;
3038 vector<na_pair> writers;
3039 for (int i = 0; i < pdg->nodes.size(); ++i) {
3040 pdg::node *node = pdg->nodes[i];
3041 pdg::statement *s = pdg->nodes[i]->statement;
3042 for (int j = 0; j < s->accesses.size(); ++j) {
3043 pdg::access *access = s->accesses[j];
3044 if (access->array != a)
3045 continue;
3046 switch (t) {
3047 case flow:
3048 case data_reuse:
3049 case anti:
3050 if ((access->type == pdg::access::read) ^ (t == anti))
3051 readers.push_back(na_pair(node, access));
3052 else
3053 writers.push_back(na_pair(node, access));
3054 break;
3055 case output:
3056 if (access->type == pdg::access::read)
3057 continue;
3058 case reuse_pair:
3059 readers.push_back(na_pair(node, access));
3060 writers.push_back(na_pair(node, access));
3061 break;
3066 int maxsize = (selfinput || reuse) ? writers.size() + readers.size()
3067 : writers.size();
3068 context = pdg->get_context_isl_set();
3069 info.precedes_level = (isl_access_level_before)
3070 ((t == reuse_pair) ? precedes_level_accesses
3071 : precedes_level_nodes);
3072 need_parametrization = any_filters(writers);
3073 for (int i = 0; i < writers.size(); ++i) {
3074 writers[i].map = convert_access(&writers[i]);
3075 writers[i].project_out_access_filters();
3077 for (int i = 0; i < readers.size(); ++i) {
3078 readers[i].map = convert_access(&readers[i]);
3079 readers[i].map = isl_map_intersect_params(readers[i].map,
3080 isl_set_copy(context));
3081 readers[i].project_out_access_filters();
3083 for (int i = 0; i < readers.size(); ++i) {
3084 isl_access_info *acc;
3085 int n_dep = pdg->dependences.size();
3087 acc = isl_access_info_alloc(isl_map_copy(readers[i].map),
3088 &readers[i], info.precedes_level, maxsize);
3089 if (need_parametrization)
3090 acc = isl_access_info_set_restrict(acc, &do_restrict, &info);
3091 for (int j = 0; j < writers.size(); ++j)
3092 acc = isl_access_info_add_source(acc,
3093 isl_map_copy(writers[j].map), 1, &writers[j]);
3094 if (selfinput && writers.size()) {
3095 pdg::node *readnode = readers[i].node;
3096 for (int j = 0; j < readers.size(); ++j) {
3097 if (readers[j].node == readnode)
3098 acc = isl_access_info_add_source(acc,
3099 isl_map_copy(readers[j].map), 1, &readers[j]);
3102 if (reuse) {
3103 for (int j = 0; j < readers.size(); ++j)
3104 acc = isl_access_info_add_source(acc,
3105 isl_map_copy(readers[j].map), 1, &readers[j]);
3107 info.set_read_na(&readers[i]);
3108 isl_flow *deps = isl_access_info_compute_flow(acc);
3109 isl_flow_foreach(deps, add_dep, &info);
3110 isl_map *no_source;
3111 no_source = isl_flow_get_no_source(deps, 1);
3112 no_source = isl_map_from_range(isl_map_domain(no_source));
3113 no_source = simplify_controls(no_source, &info, NULL);
3114 if (!isl_map_fast_is_empty(no_source) && firstuse) {
3115 pdg::dependence *d = new pdg::dependence;
3116 d->array = a;
3117 d->type = pdg::dependence::uninitialized;
3118 d->to = readers[i].node;
3119 d->to_access = readers[i].access;
3120 if (d->to_access->extension) {
3121 d->extended_relation = new pdg::IslMap(isl_map_copy(no_source));
3122 no_source = isl_map_apply_range(no_source,
3123 isl_map_reverse(
3124 d->to_access->extension->get_isl_map(ctx)));
3126 d->relation = new pdg::IslMap(isl_map_copy(no_source));
3127 pdg->dependences.push_back(d);
3129 isl_map_free(no_source);
3130 isl_flow_free(deps);
3131 remove_unused_sources(pdg, n_dep, writers, &info);
3133 isl_set_free(context);
3136 /* Add a dependence from "write" to "a" to a->sources.
3138 static void add_unique_source(pdg::access *a, pdg::access *write)
3140 isl_map *dep;
3141 isl_map *read;
3143 dep = isl_map_range_map(write->map->get_isl_map());
3144 read = isl_map_range_map(a->map->get_isl_map());
3145 dep = isl_map_apply_range(dep, isl_map_reverse(read));
3147 a->sources.push_back(new pdg::IslMap(dep));
3150 /* Look for the unique write access that writes to the array accessed
3151 * by "a" and then add a dependence from that write to a->sources.
3153 static void add_unique_source(pdg::PDG* pdg, pdg::access *a)
3155 na_pair na = find_unique_source(pdg, a->array);
3156 add_unique_source(a, na.access);
3159 extern "C" {
3160 static int add_source(__isl_take isl_map *dep, int must, void *dep_user,
3161 void *user);
3164 /* Add "dep" to a->sources, provided it is exact, and return 0.
3165 * Otherwise, return -1.
3167 static int add_source(__isl_take isl_map *dep, int must, void *dep_user,
3168 void *user)
3170 bool has_controls;
3171 pdg::access *a = (pdg::access *) user;
3173 dep = remove_redundant_controls(dep, &has_controls);
3174 if (has_controls) {
3175 isl_map_free(dep);
3176 return -1;
3179 a->sources.push_back(new pdg::IslMap(dep));
3181 return 0;
3184 extern "C" {
3185 static __isl_give isl_restriction *do_restrict_domain_map(
3186 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
3187 void *source_user, void *user);
3190 /* Compute a restriction for the given map from sinks to potential sources
3191 * (sink2source). We simply call compute_restriction to compute the
3192 * restriction. This function is used from within find_sources,
3193 * which encodes the entire access relation into the domains of
3194 * the access relations passed to isl_access_info_compute_flow.
3195 * That is, the access relations passed to isl_access_info_compute_flow
3196 * are the result of applying isl_map_range_map to the original access
3197 * relations. We therefore pass mappings that undo this encoding
3198 * to compute_restriction.
3200 static __isl_give isl_restriction *do_restrict_domain_map(
3201 __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
3202 void *source_user, void *user)
3204 na_pair *source_na = (na_pair *) source_user;
3205 add_dep_info *info = (struct add_dep_info *) user;
3206 isl_space *space;
3207 isl_map *source_domain_map, *sink_domain_map;
3209 space = isl_space_range(isl_map_get_space(source_map));
3210 space = isl_space_unwrap(space);
3211 source_domain_map = isl_map_domain_map(isl_map_universe(space));
3212 space = isl_space_domain(isl_map_get_space(source_map));
3213 space = isl_space_unwrap(space);
3214 sink_domain_map = isl_map_domain_map(isl_map_universe(space));
3216 return compute_restriction(source_map, sink_domain_map,
3217 source_domain_map, sink, source_na, info);
3220 /* Find the sources of (read) access "a" in node "node".
3221 * If they are complete (no uninitialized accesses) and exact,
3222 * then put them in a->sources. Otherwise, discard them.
3224 * If the array is marked uniquely_defined, then we simply look
3225 * for the defining write in find_unique_source.
3227 * Otherwise, we look for all writes that write to the same array,
3228 * perform dependence analysis and then check whether
3229 * the result is complete and exact.
3231 * The sources record not only the node iteration, but also
3232 * the index of the array element. We therefore apply
3233 * isl_map_range_map to the access relations, to obtain
3234 * a relation from the access (iteration -> element)
3235 * to the array element and feed that to the dependence analysis engine.
3237 void find_sources(pdg::PDG* pdg, pdg::node *node, pdg::access *a)
3239 isl_set *context;
3240 isl_map *no_source;
3241 isl_access_info *acc;
3242 isl_flow *deps;
3243 vector<na_pair> writers;
3244 na_pair reader(node, a);
3245 add_dep_info info = { pdg, a->array, flow, pdg::dependence::flow };
3247 if (a->array->uniquely_defined) {
3248 add_unique_source(pdg, a);
3249 return;
3252 info.precedes_level = (isl_access_level_before) precedes_level_nodes;
3254 for (int i = 0; i < pdg->nodes.size(); ++i) {
3255 pdg::node *node = pdg->nodes[i];
3256 pdg::statement *s = pdg->nodes[i]->statement;
3257 for (int j = 0; j < s->accesses.size(); ++j) {
3258 pdg::access *access = s->accesses[j];
3259 if (access->array != a->array)
3260 continue;
3261 if (access->type != pdg::access::write)
3262 continue;
3263 writers.push_back(na_pair(node, access));
3267 context = pdg->get_context_isl_set();
3268 for (int i = 0; i < writers.size(); ++i) {
3269 writers[i].projected_map = convert_access(&writers[i]);
3270 writers[i].map = isl_map_copy(writers[i].projected_map);
3271 writers[i].map = isl_map_range_map(writers[i].map);
3272 writers[i].project_out_access_filters();
3274 reader.projected_map = convert_access(&reader);
3275 reader.projected_map = isl_map_intersect_params(reader.projected_map,
3276 context);
3277 reader.map = isl_map_range_map(isl_map_copy(reader.projected_map));
3278 reader.project_out_access_filters();
3280 acc = isl_access_info_alloc(isl_map_copy(reader.map),
3281 &reader, info.precedes_level, writers.size());
3282 for (int j = 0; j < writers.size(); ++j)
3283 acc = isl_access_info_add_source(acc,
3284 isl_map_copy(writers[j].map), 1, &writers[j]);
3286 if (any_filters(writers))
3287 acc = isl_access_info_set_restrict(acc,
3288 &do_restrict_domain_map, &info);
3290 info.set_read_na(&reader);
3291 deps = isl_access_info_compute_flow(acc);
3292 no_source = isl_flow_get_no_source(deps, 1);
3293 if (isl_map_plain_is_empty(no_source)) {
3294 if (isl_flow_foreach(deps, add_source, a) < 0) {
3295 for (int i = 0; i < a->sources.size(); ++i)
3296 delete a->sources[i];
3297 a->sources.resize(0);
3300 isl_map_free(no_source);
3301 isl_flow_free(deps);
3304 /* Find the source (if possible) of the filter "coa" in node "node".
3305 * We assume that the filter is an access rather than a function call.
3307 static void find_sources(pdg::PDG *pdg, pdg::node *node,
3308 pdg::call_or_access *coa)
3310 pdg::access *access;
3312 assert(coa->type == pdg::call_or_access::t_access);
3313 access = coa->access;
3315 find_sources(pdg, node, access);
3318 /* Compute the sources (if possible) for all the filters in all the
3319 * nodes and accesses in "pdg".
3321 void compute_filter_sources(pdg::PDG *pdg)
3323 for (int i = 0; i < pdg->nodes.size(); ++i) {
3324 pdg::node *node = pdg->nodes[i];
3325 pdg::statement *s = pdg->nodes[i]->statement;
3326 int n_filter = node->filters.size();
3328 for (int j = 0; j < n_filter; ++j)
3329 find_sources(pdg, node, node->filters[j]);
3331 for (int j = 0; j < s->accesses.size(); ++j) {
3332 pdg::access *access = s->accesses[j];
3334 for (int k = 0; k < access->nested.size(); ++k)
3335 find_sources(pdg, node, access->nested[k]);
3340 static int precedes_level_nodes(na_pair *first, na_pair *second)
3342 int d = 0;
3343 int cmp = 0;
3344 for (int i = 0; i < first->node->prefix.size(); ++i) {
3345 if (i >= second->node->prefix.size())
3346 break;
3347 cmp = first->node->prefix[i] - second->node->prefix[i];
3348 if (cmp)
3349 break;
3350 if (first->node->prefix[i] == -1)
3351 ++d;
3353 return 2*d + (cmp<0);
3356 static int precedes_level_accesses(na_pair *first, na_pair *second)
3358 int cmp = 0;
3359 int d = 0;
3360 for (int i = 0; i < first->node->prefix.size(); ++i) {
3361 if (i >= second->node->prefix.size())
3362 break;
3363 cmp = first->node->prefix[i] - second->node->prefix[i];
3364 if (cmp)
3365 break;
3366 if (first->node->prefix[i] == -1)
3367 ++d;
3369 /* same node; now compare accesses */
3370 if (!cmp)
3371 cmp = first->access->nr - second->access->nr;
3372 return 2*d + (cmp<0);