12 #include "isl/constraint.h"
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
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
) {}
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)
49 if (access
->nested
.size() == 0)
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
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
);
100 for (int i
= 0; i
< s_dim
; ++i
) {
102 c
= isl_inequality_alloc(isl_local_space_copy(ls
));
103 isl_int_set_si(v
, 1);
104 isl_constraint_set_coefficient(c
, isl_dim_out
, 0, v
);
105 id
= isl_basic_map_add_constraint(id
, c
);
106 c
= isl_inequality_alloc(isl_local_space_copy(ls
));
107 isl_int_set_si(v
, -1);
108 isl_constraint_set_coefficient(c
, isl_dim_out
, 0, v
);
109 isl_int_set_si(v
, array
->dims
[isl_map_n_out(map
)+i
]-1);
110 isl_constraint_set_constant(c
, v
);
111 id
= isl_basic_map_add_constraint(id
, c
);
113 isl_local_space_free(ls
);
115 map
= isl_map_product(map
, isl_map_from_basic_map(id
));
116 map
= isl_map_flatten_range(map
);
118 map
= isl_map_set_tuple_id(map
, isl_dim_out
, array_id
);
119 if (!na
->access
->extension
) {
120 isl_map
*ext
= isl_map_copy(map
);
121 ext
= isl_set_unwrap(isl_map_domain(ext
));
122 ext
= isl_map_reverse(isl_map_domain_map(ext
));
123 na
->access
->extension
= new pdg::IslMap(ext
);
125 if (!na
->access
->extended_map
)
126 na
->access
->extended_map
= new pdg::IslMap(isl_map_copy(map
));
130 /* If access "access" contains any nested accesses, then the domain
131 * of the access relation contains extra dimensions corresponding to
132 * the values of the nested accesses.
133 * Add these extra dimensions, with ranges given by the value_bounds
134 * of the corresponding array to domain "dom".
135 * If a nested access array does not have value_bounds, then we assume
136 * an infinite interval.
138 static isl_set
*append_nested_value_domains(isl_set
*dom
, pdg::access
*access
)
142 ctx
= isl_set_get_ctx(dom
);
143 for (int i
= 0; i
< access
->nested
.size(); ++i
) {
144 pdg::call_or_access
*coa
= access
->nested
[i
];
145 assert(coa
->type
== pdg::call_or_access::t_access
);
146 pdg::access
*nested
= coa
->access
;
148 if (nested
->array
->value_bounds
)
149 bounds
= nested
->array
->value_bounds
->get_isl_set(ctx
);
151 isl_space
*dim
= isl_set_get_space(dom
);
152 dim
= isl_space_drop_dims(dim
, isl_dim_set
,
153 0, isl_space_dim(dim
, isl_dim_set
));
154 dim
= isl_space_add_dims(dim
, isl_dim_set
, 1);
155 bounds
= isl_set_universe(dim
);
157 dom
= isl_set_product(dom
, bounds
);
162 /* Combine constraints of the "pure" mapping with the constraints
163 * on the domain. If the range of the mapping is of a dimension
164 * that is lower than the dimension of the accessed array,
165 * we extend the dimension of both domain and range of the mapping
166 * with the missing dimension. The size of domain and range
167 * in these dimensions is set to the extent of the array in the
168 * corresponding missing dimension. Each point in the original
169 * domain is therefore expanded to a hyperrectangle and each point
170 * in this hyperrectangle is mapped onto a single point in the array.
172 * If node->source is a wrapped map, then the iteration domain
173 * is the domain of this map.
175 static isl_map
*convert_access(na_pair
*na
)
177 isl_map
*map
= na
->access
->map
->get_isl_map();
178 isl_set
*dom
= na
->node
->source
->get_isl_set();
180 if (isl_set_is_wrapping(dom
)) {
181 dom
= isl_map_domain(isl_set_unwrap(dom
));
182 dom
= isl_set_coalesce(dom
);
185 dom
= append_nested_value_domains(dom
, na
->access
);
186 if (isl_map_n_in(map
) != isl_set_dim(dom
, isl_dim_set
))
188 map
= isl_map_intersect_domain(map
, dom
);
189 if (isl_map_n_out(map
) != na
->access
->array
->dims
.size())
190 map
= extend_access(map
, na
);
194 typedef std::map
<na_pair
*, isl_map
*> na_pair2map
;
196 struct add_dep_info
{
200 enum pdg::dependence::type dtype
;
202 na_pair
*read_na_pair
;
203 /* The comparison routine that was used during
204 * the dependence analysis.
206 isl_access_level_before precedes_level
;
207 /* Cache of memory based dependence relations.
208 * The key of the map refers to the write.
211 /* How many loops are shared by the current sink and source?
215 /* For each potential source, what's (up to now) the minimal
216 * and maximal number of shared loops?
217 * If not set, then we don't know yet.
219 std::map
<na_pair
*, int> min_n_shared
;
220 std::map
<na_pair
*, int> max_n_shared
;
222 /* Potential sources that are actually used. */
223 std::set
<na_pair
*> used
;
225 __isl_give isl_map
*get_mem_dep(na_pair
*write_na
);
226 void clear_mem_dep();
227 void set_read_na(na_pair
*read_na
);
228 void update_min_n_shared(na_pair
*source_na
);
233 /* Update min_n_shared of "source_na" to the current number of shared loops.
234 * The new value is always smaller than or equal to the old value (if any).
235 * If max_n_shared hasn't been set yet, then set it as well.
237 void add_dep_info::update_min_n_shared(na_pair
*source_na
)
239 if (max_n_shared
.find(source_na
) == max_n_shared
.end())
240 max_n_shared
[source_na
] = n_shared
;
241 min_n_shared
[source_na
] = n_shared
;
246 * __last_<stmt>_<access_nr>_valid
248 * corresponding to "na", with "na" attached as user pointer.
250 static __isl_give isl_id
*valid_bit_id(isl_ctx
*ctx
, na_pair
*na
)
254 snprintf(name
, sizeof(name
), "__last_%s_%d_valid",
255 na
->node
->name
->s
.c_str(), na
->access
->nr
);
256 return isl_id_alloc(ctx
, name
, na
);
261 * __last_<stmt>_<access_nr>_shared
263 * corresponding to "na", with "na" attached as user pointer.
265 static __isl_give isl_id
*create_shared_id(isl_ctx
*ctx
, na_pair
*na
)
269 snprintf(name
, sizeof(name
), "__last_%s_%d_shared",
270 na
->node
->name
->s
.c_str(), na
->access
->nr
);
271 return isl_id_alloc(ctx
, name
, na
);
274 /* Project out all the dimensions of the given type from "map" except "pos".
276 static __isl_give isl_map
*project_on(__isl_take isl_map
*map
,
277 enum isl_dim_type type
, unsigned pos
)
279 unsigned n
= isl_map_dim(map
, type
);
281 map
= isl_map_project_out(map
, type
, pos
+ 1, n
- (pos
+ 1));
282 map
= isl_map_project_out(map
, type
, 0, pos
);
287 /* Does output dimension "pos" have a fixed value in terms of the
288 * input dimensions (and parameters)?
290 static int has_fixed_value(__isl_keep isl_map
*map
, int pos
)
294 map
= isl_map_copy(map
);
295 map
= project_on(map
, isl_dim_out
, pos
);
296 sv
= isl_map_is_single_valued(map
);
302 /* Return the position of the parameter with the given "id" in "set",
303 * adding it if it wasn't there already.
305 static int find_or_add_param(__isl_keep isl_set
**set
, __isl_take isl_id
*id
)
309 pos
= isl_set_find_dim_by_id(*set
, isl_dim_param
, id
);
315 pos
= isl_set_dim(*set
, isl_dim_param
);
316 *set
= isl_set_add_dims(*set
, isl_dim_param
, 1);
317 *set
= isl_set_set_dim_id(*set
, isl_dim_param
, pos
, id
);
322 /* Add parameters to "set" identifying the last iteration of the access
323 * identified by "na".
325 * In particular, we add a parameter
327 * __last_<stmt>_<access_nr>_shared >= info->n_shared
331 * __last_<stmt>_<access_nr>_<i> = it_<i>
333 * with i ranging over the iterators, starting at info->n_shared,
334 * that are affected by the filters,
335 * except those that have a fixed value according to the memory based
337 * "na" is attached to the first two parameters, so that it can be recovered
338 * in refine_controls(). If the set already references some of these
339 * parameters, then we don't add the parameter again, but instead
340 * simply add the corresponding constraint.
342 static __isl_give isl_set
*add_parametrization(__isl_take isl_set
*set
,
343 na_pair
*na
, add_dep_info
*info
)
352 depth
= na
->node
->get_filter_depth();
353 mem
= info
->get_mem_dep(na
);
354 mem
= isl_map_reverse(mem
);
356 ctx
= isl_set_get_ctx(set
);
357 id
= create_shared_id(ctx
, na
);
358 pos
= find_or_add_param(&set
, id
);
359 set
= isl_set_lower_bound_si(set
, isl_dim_param
, pos
, info
->n_shared
);
361 for (int i
= info
->n_shared
; i
< depth
; ++i
) {
362 if (has_fixed_value(mem
, i
))
365 snprintf(name
, sizeof(name
), "__last_%s_%d_%d",
366 na
->node
->name
->s
.c_str(), na
->access
->nr
, i
);
368 id
= isl_id_alloc(ctx
, name
, NULL
);
369 pos
= find_or_add_param(&set
, id
);
371 set
= isl_set_equate(set
, isl_dim_param
, pos
, isl_dim_set
, i
);
378 /* Is the i-th parameter of "map" a control, i.e., a parameter
379 * introduced by add_parametrization()?
380 * In particular, is the parameter of the form __last_*?
382 static bool is_control(__isl_keep isl_map
*map
, int i
)
385 const char *prefix
= "__last_";
386 size_t prefix_len
= strlen(prefix
);
388 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
390 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
391 return strncmp(name
, prefix
, prefix_len
) == 0;
394 /* Is the i-th parameter of "set" a control, i.e., a parameter
395 * introduced by add_parametrization()?
396 * In particular, is the parameter of the form __last_*?
398 static bool is_control(__isl_keep isl_set
*set
, int i
)
401 const char *prefix
= "__last_";
402 size_t prefix_len
= strlen(prefix
);
404 if (!isl_set_has_dim_id(set
, isl_dim_param
, i
))
406 name
= isl_set_get_dim_name(set
, isl_dim_param
, i
);
407 return strncmp(name
, prefix
, prefix_len
) == 0;
410 /* Remove all controls that are redundant, i.e., that do not appear
411 * in any of the constraints.
412 * Set *has_controls to true if there are any controls that are not redundant.
414 static __isl_give isl_map
*remove_redundant_controls(__isl_take isl_map
*dep
,
420 *has_controls
= false;
422 n_param
= isl_map_dim(dep
, isl_dim_param
);
423 for (i
= n_param
- 1; i
>= 0; --i
) {
424 if (!is_control(dep
, i
))
426 if (isl_map_involves_dims(dep
, isl_dim_param
, i
, 1))
427 *has_controls
= true;
429 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
435 /* Rename controls of "dep" from
437 * __last_<source_stmt>_<source_acc_nr>_*
441 * __last_<source_stmt>_<source_acc_nr>_<sink_stmt>_<sink_acc_nr>_*
443 * "na" represents the sink.
445 static __isl_give isl_map
*rename_controls(__isl_take isl_map
*dep
, na_pair
*na
)
450 const char *underscore
;
452 n_param
= isl_map_dim(dep
, isl_dim_param
);
453 for (int i
= 0; i
< n_param
; ++i
) {
455 if (!is_control(dep
, i
))
457 name
= isl_map_get_dim_name(dep
, isl_dim_param
, i
);
458 underscore
= strrchr(name
, '_');
460 len
= underscore
+ 1 - name
;
461 memcpy(buf
, name
, len
);
462 snprintf(buf
+ len
, sizeof(buf
) - len
, "%s_%d_%s",
463 na
->node
->name
->s
.c_str(), na
->access
->nr
, name
+ len
);
464 dep
= isl_map_set_dim_name(dep
, isl_dim_param
, i
, buf
);
471 static int extract_dep(__isl_take isl_map
*dep
, int must
,
472 void *dep_user
, void *user
);
475 /* Extract the single dependence relation from the result of
476 * dataflow analyis and assign it to *user.
478 static int extract_dep(__isl_take isl_map
*dep
, int must
, void *dep_user
,
481 isl_map
**dep_p
= (isl_map
**) user
;
487 /* Return the memory based dependence relation from write_na
488 * to read_na_pair. If the "projected_map"
489 * fields are not NULL, then use the "projected_map"
490 * instead of the "map" of write_na and this->read_na_pair.
492 __isl_give isl_map
*add_dep_info::get_mem_dep(na_pair
*write_na
)
494 isl_access_info
*acc
;
496 isl_map
*read_map
, *write_map
;
499 if (mem_dep
.find(write_na
) != mem_dep
.end())
500 return isl_map_copy(mem_dep
[write_na
]);
502 if (read_na_pair
->projected_map
)
503 read_map
= isl_map_copy(read_na_pair
->projected_map
);
505 read_map
= isl_map_copy(read_na_pair
->map
);
506 acc
= isl_access_info_alloc(read_map
, read_na_pair
, precedes_level
, 1);
507 if (write_na
->projected_map
)
508 write_map
= isl_map_copy(write_na
->projected_map
);
510 write_map
= isl_map_copy(write_na
->map
);
511 acc
= isl_access_info_add_source(acc
, write_map
, 0, write_na
);
512 deps
= isl_access_info_compute_flow(acc
);
513 isl_flow_foreach(deps
, &extract_dep
, &dep
);
516 mem_dep
[write_na
] = isl_map_copy(dep
);
521 /* Clear the cache of memory based dependence relations.
523 void add_dep_info::clear_mem_dep()
525 na_pair2map::iterator it
;
527 for (it
= mem_dep
.begin(); it
!= mem_dep
.end(); ++it
)
528 isl_map_free(it
->second
);
532 /* Set read_na_pair to read_na.
534 * If the cache of memory based dependence relations contains any
535 * elements then they refer to a different read, so we need to clear
538 * We also clear the set of used potential sources and reset
539 * the data that keeps track of the number of shared loops between
540 * the sink (read_na_pair) and the sources.
542 void add_dep_info::set_read_na(na_pair
*read_na
)
547 min_n_shared
.clear();
548 max_n_shared
.clear();
549 read_na_pair
= read_na
;
552 add_dep_info::~add_dep_info()
557 /* Is the name of parameter "i" of "space" of the form __last_*_suffix?
559 static bool is_last_with_suffix(__isl_keep isl_space
*space
, int i
,
560 const char *suffix
, size_t suffix_len
)
562 const char *prefix
= "__last_";
563 size_t prefix_len
= strlen(prefix
);
567 if (!isl_space_has_dim_id(space
, isl_dim_param
, i
))
569 name
= isl_space_get_dim_name(space
, isl_dim_param
, i
);
570 if (strncmp(name
, prefix
, prefix_len
))
573 return len
> suffix_len
&& !strcmp(name
+ len
- suffix_len
, suffix
);
576 /* Is the name of parameter "i" of "space" of the form __last_*_valid?
577 * In practice, those are the parameters __last_*_valid, created
578 * in add_parametrization().
580 static bool is_valid_bit(__isl_keep isl_space
*space
, int i
)
582 const char *suffix
= "_valid";
584 return is_last_with_suffix(space
, i
, suffix
, strlen(suffix
));
587 /* Is the name of parameter "i" of "space" of the form __last_*_shared?
588 * In practice, those are the parameters __last_*_shared, created
589 * in add_parametrization().
591 static bool is_shared(__isl_keep isl_space
*space
, int i
)
593 const char *suffix
= "_shared";
594 size_t suffix_len
= strlen(suffix
);
596 return is_last_with_suffix(space
, i
, suffix
, strlen(suffix
));
599 /* Assuming "coa" is a (read) access, return the array being
602 static pdg::array
*get_filter_array(pdg::call_or_access
*coa
)
604 assert(coa
->type
== pdg::call_or_access::t_access
);
605 return coa
->access
->array
;
608 /* Compute a map between domain elements (i) of "map1" and range elements
609 * of "map2" (j) such that all the images of i in "map1" map to j through
610 * "map2" and such that there is at least one such image element.
612 * In other words, the result contains those pairs of elements such that
613 * map1(i) \cap map2^-1(j) is non-empty and map1(i) \subseteq map2^-1(j).
615 * Equivalently, compute
617 * (map1 . map2) \setminus
618 * (map1 . ((\range map1 \to \range map2) \setminus map2))
620 * If map1 is single valued, then we can do a simple join.
622 static __isl_give isl_union_map
*join_non_empty_subset(
623 __isl_take isl_union_map
*umap1
, __isl_take isl_union_map
*umap2
)
625 isl_union_set
*dom
, *ran
;
629 if (isl_union_map_is_single_valued(umap1
))
630 return isl_union_map_apply_range(umap1
, umap2
);
632 res
= isl_union_map_apply_range(isl_union_map_copy(umap1
),
633 isl_union_map_copy(umap2
));
634 dom
= isl_union_map_range(isl_union_map_copy(umap1
));
635 ran
= isl_union_map_range(isl_union_map_copy(umap2
));
636 univ
= isl_union_map_from_domain_and_range(dom
, ran
);
637 umap2
= isl_union_map_subtract(univ
, umap2
);
638 umap1
= isl_union_map_apply_range(umap1
, umap2
);
639 res
= isl_union_map_subtract(res
, umap1
);
644 /* Compute a map between domain elements (i) of "map1" and range elements
645 * of "map2" (j) such that the images of i in "map1" include all those
646 * elements that map to j through "map2" and such that there is
647 * at least one such image element.
649 * In other words, the result contains those pairs of elements such that
650 * map1(i) \cap map2^-1(j) is non-empty and map1(i) \supseteq map2^-1(j).
652 * Equivalently, compute
654 * (map1 . map2) \setminus
655 * (((\domain map1 \to \domain map2) \setminus map1) . map2)
657 * If map1 is single valued, then we can do a simple join.
659 static __isl_give isl_union_map
*join_non_empty_superset(
660 __isl_take isl_union_map
*umap1
, __isl_take isl_union_map
*umap2
)
662 isl_union_set
*dom
, *ran
;
666 if (isl_union_map_is_single_valued(umap2
))
667 return isl_union_map_apply_range(umap1
, umap2
);
669 res
= isl_union_map_apply_range(isl_union_map_copy(umap1
),
670 isl_union_map_copy(umap2
));
671 dom
= isl_union_map_domain(isl_union_map_copy(umap1
));
672 ran
= isl_union_map_domain(isl_union_map_copy(umap2
));
673 univ
= isl_union_map_from_domain_and_range(dom
, ran
);
674 umap1
= isl_union_map_subtract(univ
, umap1
);
675 umap1
= isl_union_map_apply_range(umap1
, umap2
);
676 res
= isl_union_map_subtract(res
, umap1
);
681 /* Return those elements in the domain of "umap" where "umap" is multi-valued.
683 * In particular, construct a mapping between domain elements of "umap"
684 * and pairs of corresponding image elements.
685 * Remove pairs of identical image elements from the range of this mapping.
686 * The result is a mapping between domain elements and pairs of different
687 * corresponding image elements. The domain of this mapping contains those
688 * domain elements of "umap" with at least two images.
690 static __isl_give isl_union_set
*multi_valued(__isl_keep isl_union_map
*umap
)
692 isl_union_map
*multi
, *id
;
694 multi
= isl_union_map_range_product(isl_union_map_copy(umap
),
695 isl_union_map_copy(umap
));
696 id
= isl_union_map_universe(isl_union_map_copy(multi
));
697 id
= isl_union_set_unwrap(isl_union_map_range(id
));
698 id
= isl_union_set_identity(isl_union_map_domain(id
));
699 multi
= isl_union_map_subtract_range(multi
, isl_union_map_wrap(id
));
700 return isl_union_map_domain(multi
);
703 /* Given two filter access relations, return a mapping between the domain
704 * elements of these access relations such that they access "the same filter".
705 * In particular, any pair of elements in the returned relation
706 * accesses at least one element in common, but if subset1 is set,
707 * then the set of elements accessed by the first is a subset of the
708 * set of elements accessed by the second. Similarly, if subset2 is set,
709 * then the set of elements accessed by the second is a subset of the
710 * set of elements accessed by the first. If both are set, then we further
711 * impose that both should access exactly one element.
712 * "space" is the space in which the result should live.
713 * Although "map1" and "map2" are allowed to have ranges in multiple spaces,
714 * their domains should live in a single space. "space" is the space
715 * of the relation between those two domains.
717 * Call the given maps A and B.
719 * A relation between domains elements of A and B that access at least
720 * one element in common can be obtained as
724 * To ensure that all elements accessed through A form a subset of
725 * the elements accessed through B, we compute join_non_empty_subset(A, B^-1).
727 * Ensuring that all elements accessed through B form a subset of
728 * the elements accessed through A is handled in a similar way.
730 * To remove those iterations that access more that one element,
731 * we compute those parts of the domains where A and B are multi-valued
732 * and subtract them from domain and range of the result.
734 static __isl_give isl_map
*compute_common_filter(__isl_keep isl_union_map
*map1
,
735 bool subset1
, __isl_keep isl_union_map
*map2
, bool subset2
,
736 __isl_keep isl_space
*space
)
738 isl_union_map
*reverse
, *common
;
742 reverse
= isl_union_map_reverse(isl_union_map_copy(map2
));
744 if (subset1
&& !subset2
) {
745 common
= join_non_empty_subset(isl_union_map_copy(map1
),
747 } else if (!subset1
&& subset2
) {
748 common
= join_non_empty_superset(isl_union_map_copy(map1
),
751 common
= isl_union_map_apply_range(isl_union_map_copy(map1
),
753 if (subset1
&& subset2
) {
754 bad
= multi_valued(map1
);
755 common
= isl_union_map_subtract_domain(common
, bad
);
756 bad
= multi_valued(map2
);
757 common
= isl_union_map_subtract_range(common
, bad
);
761 res
= isl_union_map_extract_map(common
, isl_space_copy(space
));
762 isl_union_map_free(common
);
766 /* Assuming "coa" is a (read) access, construct a union map from the domain
767 * of the access relation to the access relations of the corresponding
768 * writes. If we are unable to determine the corresponding writes, then
769 * return a map to the read access relation.
771 static __isl_give isl_union_map
*extract_access_map(pdg::call_or_access
*coa
)
773 assert(coa
->type
== pdg::call_or_access::t_access
);
774 return coa
->access
->extract_access_map();
777 /* Return a set that contains all possible filter values,
778 * where the possible values for a given filter is either as specified
779 * by the value_bounds property of the corresponding array or the universe.
781 static __isl_give isl_set
*compute_filter_bounds(pdg::node
*node
)
786 ctx
= isl_set_get_ctx(node
->source
->set
);
788 bounds
= isl_set_universe(isl_space_set_alloc(ctx
, 0, 0));
789 for (int i
= 0; i
< node
->filters
.size(); ++i
) {
792 pdg::call_or_access
*coa
= node
->filters
[i
];
793 assert(coa
->type
== pdg::call_or_access::t_access
);
794 array
= coa
->access
->array
;
795 if (array
->value_bounds
)
796 bnd
= array
->value_bounds
->get_isl_set();
798 bnd
= isl_set_universe(isl_space_set_alloc(ctx
, 0, 1));
799 bounds
= isl_set_flat_product(bounds
, bnd
);
805 /* Return either the filter values themselves or their complement,
806 * taken with respect to the bounds on the filter values.
808 static __isl_give isl_map
*compute_filter_values(pdg::node
*node
,
815 value
= isl_set_unwrap(node
->source
->get_isl_set());
819 bounds
= compute_filter_bounds(node
);
820 res
= isl_map_from_domain_and_range(
821 isl_map_domain(isl_map_copy(value
)), bounds
);
822 res
= isl_map_subtract(res
, value
);
827 /* Equate the first "n" input and output dimensions of "map"
828 * and return the result.
830 static __isl_give isl_map
*share(__isl_take isl_map
*map
, int n
)
832 for (int i
= 0; i
< n
; ++i
)
833 map
= isl_map_equate(map
, isl_dim_in
, i
, isl_dim_out
, i
);
838 /* Return the set of source iterations of "na" either at the last
839 * iteration (if valid is set) or after the last iteration
840 * (if valid is not set). "id" represents the control variable
841 * corresponding to the number of shared loops (__last_<na>_shared).
843 * In particlar, if valid is set, we return the set
845 * { S[i] : i = __last_<na> and
846 * __last_<na>_shared >= info->n_shared }
848 * If valid is not set, we return the set
850 * { S[i] : (i >> __last_<na> and __last_<na>_shared >= info->n_shared) or
851 * __last_<na>_shared < info->n_shared }
853 * That is, the iterations after the last if there is a last iteration
854 * with at least info->n_shared shared loops
855 * or just any iteration if there is no such last iteration.
857 * The lexicographic order i >> __last_<na> is imposed on the loop iterators
858 * that are affected by any filters.
860 static __isl_give isl_set
*source_iterations(na_pair
*na
,
861 __isl_keep isl_id
*id
, bool valid
, add_dep_info
*info
)
864 isl_set
*set
, *invalid
;
869 space
= isl_set_get_space(na
->node
->source
->set
);
870 space
= isl_space_domain(isl_space_unwrap(space
));
872 set
= isl_set_universe(space
);
873 set
= add_parametrization(set
, na
, info
);
878 depth
= na
->node
->get_filter_depth();
880 space
= isl_space_map_from_set(isl_set_get_space(set
));
881 map_after
= isl_map_lex_lt_first(space
, depth
);
882 map_after
= share(map_after
, info
->n_shared
);
883 map_after
= isl_map_intersect_domain(map_after
, set
);
884 set
= isl_map_range(map_after
);
886 invalid
= isl_set_universe(isl_set_get_space(set
));
887 pos
= isl_set_find_dim_by_id(invalid
, isl_dim_param
, id
);
889 invalid
= isl_set_upper_bound_si(invalid
,
890 isl_dim_param
, pos
, info
->n_shared
- 1);
891 set
= isl_set_union(set
, invalid
);
896 /* Look for a matching between the filters of node1 and those of node2.
897 * That is look for pairs of filters of the two nodes that are "the same".
898 * Return true if any such matching can be found. The correspondence between
899 * the filters is returned in *same_value_p, while the pairs of iterations
900 * where the filters are the same is returned in *same_filter_p.
901 * The first "n_shared" dimensions of these iterations are guaranteed
902 * to be equal to each other.
904 * Two filter accesses are considered "the same" if they access at least
905 * one element in common. Moreover, if valid1 is false then the set
906 * of elements accessed by an element from node1 should be a subset
907 * of the set of elements accessed by the corresponding element from node2.
908 * Similarly for valid2.
910 * We perform a greedy search, checking if two filters could possibly
911 * match given the matchings we have performed before and updating
912 * the matching if it is indeed possible.
914 * Note that this function only computes one of the possibly many matchings.
916 static bool compute_matching(pdg::node
*node1
, bool valid1
,
917 pdg::node
*node2
, bool valid2
, __isl_give isl_map
**same_filter_p
,
918 __isl_give isl_map
**same_value_p
, int n_shared
)
921 isl_space
*space1
, *space2
;
922 isl_map
*same_filter
;
925 space1
= isl_space_unwrap(isl_set_get_space(node1
->source
->set
));
926 space2
= isl_space_unwrap(isl_set_get_space(node2
->source
->set
));
927 space1
= isl_space_product(space1
, space2
);
928 space2
= isl_space_unwrap(isl_space_range(isl_space_copy(space1
)));
929 space1
= isl_space_unwrap(isl_space_domain(space1
));
931 same_filter
= isl_map_universe(isl_space_copy(space1
));
932 same_filter
= share(same_filter
, n_shared
);
933 same_value
= isl_map_universe(space2
);
935 for (int i
= 0; i
< node1
->filters
.size(); ++i
) {
936 isl_union_map
*map_i
;
937 pdg::call_or_access
*filter_i
= node1
->filters
[i
];
938 pdg::array
*array_i
= get_filter_array(filter_i
);
940 map_i
= extract_access_map(node1
->filters
[i
]);
942 for (int j
= 0; j
< node2
->filters
.size(); ++j
) {
943 pdg::call_or_access
*filter_j
;
944 filter_j
= node2
->filters
[j
];
945 pdg::array
*array_j
= get_filter_array(filter_j
);
946 isl_union_map
*map_j
;
947 isl_map
*same_filter_ij
;
949 if (array_i
!= array_j
)
952 map_j
= extract_access_map(node2
->filters
[j
]);
953 same_filter_ij
= compute_common_filter(map_i
, !valid1
,
956 same_filter_ij
= isl_map_intersect(same_filter_ij
,
957 isl_map_copy(same_filter
));
958 if (isl_map_is_empty(same_filter_ij
))
959 isl_map_free(same_filter_ij
);
962 isl_map_free(same_filter
);
963 same_filter
= same_filter_ij
;
964 same_value
= isl_map_equate(same_value
,
968 isl_union_map_free(map_j
);
971 isl_union_map_free(map_i
);
973 isl_space_free(space1
);
976 *same_value_p
= same_value
;
977 *same_filter_p
= same_filter
;
979 isl_map_free(same_value
);
980 isl_map_free(same_filter
);
981 *same_value_p
= NULL
;
982 *same_filter_p
= NULL
;
988 /* Given a set of sink iterations "sink", mappings "map1" and "map2"
989 * from two potential sources to this sink,
990 * the possible filter values "value1" and "value2" at those
991 * potential sources, a relation "same_filter" between the two
992 * potential sources expressing when some filters of the two
993 * potential sources are the same and the correponding matching
994 * "same_value" between the filter values,
995 * remove those elements from the sink that have
996 * corresponding pairs of potential source iterations that should
997 * have the same filter values but do not.
999 * Let us call the sink S, the potential sources A and B and the
1000 * corresponding filters F and G.
1002 * We start from the mappings A[..] -> S[..] and B[..] -> S[..],
1005 * S[..] -> [A[..] -> B[..]]
1007 * and intersect the range with the condition "same_filter" on A and B,
1008 * resulting in a mapping from sink iterations to pairs of potential
1009 * source iterations that should have the same filter values
1010 * (as specified by "same_value").
1012 * We subtract from the range of this mapping those pairs of
1013 * potential source iterations that actually have the same filter values.
1014 * The result is a mapping from sink iterations to pairs of potential
1015 * source iterations that should have the same filter values but do not.
1017 * The mapping between potential source iterations that have the
1018 * same filter values is obtained by combining the mappings
1019 * A[..] -> F[..] and B[..] -> G[..] into
1021 * [A[..] -> B[..]] -> [F[..] -> G[..]]
1023 * intersecting the range with "same_value" and then computing the domain.
1025 static __isl_give isl_set
*remove_conflict(__isl_take isl_set
*sink
,
1026 __isl_take isl_map
*map1
, __isl_take isl_map
*value1
,
1027 __isl_take isl_map
*map2
, __isl_take isl_map
*value2
,
1028 __isl_take isl_map
*same_filter
, __isl_take isl_map
*same_value
)
1030 isl_map
*value
, *conflict
;
1031 isl_set
*conflict_set
;
1033 conflict
= isl_map_domain_product(map1
, map2
);
1034 conflict
= isl_map_reverse(conflict
);
1036 conflict
= isl_map_intersect_range(conflict
, isl_map_wrap(same_filter
));
1038 value
= isl_map_product(value1
, value2
);
1039 value
= isl_map_intersect_range(value
, isl_map_wrap(same_value
));
1040 conflict
= isl_map_subtract_range(conflict
, isl_map_domain(value
));
1042 conflict_set
= isl_map_domain(conflict
);
1044 sink
= isl_set_subtract(sink
, conflict_set
);
1049 /* Remove inconsistencies from the set of sink iterations "sink"
1050 * based on two potential sources identified by "id1" and "id2"
1051 * (representing the number of shared loops),
1052 * in particular, on either the last iteration where the filters hold
1053 * (if valid? is set) or on later iterations (if valid? is not set).
1055 * Let us first consider the case where both "valid1" and "valid2" are set.
1056 * If the last iterations of the corresponding sources access the same
1057 * filters, then these filters should have the same value.
1058 * If a filter access accesses more than one element, then these elements
1059 * should all have the same value. It is therefore sufficient for the
1060 * two last iterations to access at least one element in common for there
1061 * to be a requirement that the corresponding values should be the same.
1062 * We therefore obtain the filter values, the mappings from the sink
1063 * to the last iterations, a matching between the
1064 * the filters of the corresponding sources and remove conflicts from "dep".
1066 * If one or both of the valid bits are not set, then we need to make
1067 * some changes. First the inconsistencies now do not arise from
1068 * the filter values at the last iteration, but from the filter values
1069 * lying _outside_ of the possible values for all iterations _after_
1070 * the "last" (i.e., the last iteration satisfying the filter constraints).
1071 * In case there is no last iteration with at least info->n_shared shared loops,
1072 * then the filter values should lie outside of the possible values
1073 * for any potential source iteration with info->n_shared shared loops.
1074 * Note however, that if the filter access relation accesses several
1075 * elements, then it is sufficient for one of those to have a value
1076 * outside of the possible values. We can therefore only consider
1077 * any inconsistencies for those cases where the set of accessed elements
1078 * forms a subset of the set of accessed elements through the other potential
1079 * source. If valid1 is not set, but valid2 is set, then we consider
1080 * those pairs of potential source iterations where the first accesses
1081 * a subset of the second and we impose that at least one of those
1082 * accessed elements has a valid outside the possible values.
1083 * Since those accessed elements form a subset of the elements accessed
1084 * by the other potential source, there is at least one element that
1085 * has a value outside of the posssible values on the first potential source
1086 * and a value belonging to the posssible values on the second potential source.
1087 * We can therefore impose that this value should exist.
1089 * If both valid1 and valid2 are not set, then we can only
1090 * impose a constraint on those pairs of iterations that access the same
1091 * single element. We then know that the value of this single element
1092 * accessed by both potential sources should lie outside of the possible
1093 * values on both sides.
1095 static __isl_give isl_set
*remove_inconsistencies(__isl_take isl_set
*sink
,
1096 add_dep_info
*info
, __isl_keep isl_id
*id1
, bool valid1
,
1097 __isl_keep isl_id
*id2
, bool valid2
)
1099 na_pair
*write1_na
, *write2_na
;
1101 isl_map
*value1
, *value2
;
1102 isl_map
*same_filter
;
1103 isl_map
*same_value
;
1104 isl_map
*mem1
, *mem2
;
1106 write1_na
= (na_pair
*) isl_id_get_user(id1
);
1107 write2_na
= (na_pair
*) isl_id_get_user(id2
);
1109 if (!compute_matching(write1_na
->node
, valid1
, write2_na
->node
, valid2
,
1110 &same_filter
, &same_value
, info
->n_shared
))
1113 value1
= compute_filter_values(write1_na
->node
, !valid1
);
1114 value2
= compute_filter_values(write2_na
->node
, !valid2
);
1116 mem1
= info
->get_mem_dep(write1_na
);
1117 source
= source_iterations(write1_na
, id1
, valid1
, info
);
1118 mem1
= share(mem1
, info
->n_shared
);
1119 mem1
= isl_map_intersect_domain(mem1
, source
);
1121 mem2
= info
->get_mem_dep(write2_na
);
1122 source
= source_iterations(write2_na
, id2
, valid2
, info
);
1123 mem2
= share(mem2
, info
->n_shared
);
1124 mem2
= isl_map_intersect_domain(mem2
, source
);
1126 sink
= remove_conflict(sink
, mem1
, value1
, mem2
, value2
,
1127 same_filter
, same_value
);
1132 /* Remove inconsistencies from the set of sink iterations "sink"
1133 * based on two potential sources identified by "id1" and "id2",
1134 * (representing the number of shared loops).
1136 static __isl_give isl_set
*remove_inconsistencies(__isl_take isl_set
*sink
,
1137 add_dep_info
*info
, __isl_keep isl_id
*id1
, __isl_keep isl_id
*id2
)
1139 sink
= remove_inconsistencies(sink
, info
, id1
, false, id2
, false);
1140 sink
= remove_inconsistencies(sink
, info
, id1
, false, id2
, true);
1141 sink
= remove_inconsistencies(sink
, info
, id1
, true, id2
, false);
1142 sink
= remove_inconsistencies(sink
, info
, id1
, true, id2
, true);
1146 /* Remove inconsistencies from the set of sink iterations "sink"
1147 * based on the potential source identified by "id"
1148 * (representing the number of shared loops),
1149 * in particular, on either the last iteration where the filters hold
1150 * (if valid is set) or on later iterations (if valid is not set).
1152 * This function is very similar to the remove_inconsistencies
1153 * function above that considers two potential sources instead
1154 * of the sink and one potential source. The main differences
1155 * are that for the sink, the filters always hold and that the mapping
1156 * from sink iterations to sink iterations is computed in a different
1157 * (and fairly trivial) way.
1159 static __isl_give isl_set
*remove_inconsistencies(__isl_take isl_set
*sink
,
1160 add_dep_info
*info
, __isl_keep isl_id
*id
, bool valid
)
1162 na_pair
*read_na
, *write_na
;
1164 isl_map
*value1
, *value2
;
1165 isl_map
*same_filter
;
1166 isl_map
*same_value
;
1167 isl_map
*id_map
, *mem
;
1169 read_na
= info
->read_na_pair
;
1170 write_na
= (na_pair
*) isl_id_get_user(id
);
1172 if (!compute_matching(read_na
->node
, true, write_na
->node
, valid
,
1173 &same_filter
, &same_value
, info
->n_shared
))
1176 value1
= compute_filter_values(read_na
->node
, false);
1177 value2
= compute_filter_values(write_na
->node
, !valid
);
1179 id_map
= isl_set_identity(isl_set_copy(sink
));
1181 mem
= info
->get_mem_dep(write_na
);
1182 after
= source_iterations(write_na
, id
, valid
, info
);
1183 mem
= share(mem
, info
->n_shared
);
1184 mem
= isl_map_intersect_domain(mem
, after
);
1186 sink
= remove_conflict(sink
, id_map
, value1
, mem
, value2
,
1187 same_filter
, same_value
);
1192 /* Remove inconsistencies from the set of sink iterations "sink"
1193 * based on the potential source identified by "id"
1194 * (representing the number of shared loops).
1196 static __isl_give isl_set
*remove_inconsistencies(__isl_take isl_set
*sink
,
1197 add_dep_info
*info
, __isl_keep isl_id
*id
)
1199 sink
= remove_inconsistencies(sink
, info
, id
, false);
1200 sink
= remove_inconsistencies(sink
, info
, id
, true);
1204 /* Remove all parameters that were introduced by add_parametrization().
1206 static __isl_give isl_map
*remove_all_controls(__isl_take isl_map
*dep
)
1212 n_param
= isl_map_dim(dep
, isl_dim_param
);
1213 for (i
= n_param
- 1; i
>= 0; --i
) {
1214 if (!is_control(dep
, i
))
1216 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
1218 dep
= isl_map_coalesce(dep
);
1223 /* Remove all parameters that were introduced by add_parametrization().
1225 static __isl_give isl_set
*remove_all_controls(__isl_take isl_set
*set
)
1231 n_param
= isl_set_dim(set
, isl_dim_param
);
1232 for (i
= n_param
- 1; i
>= 0; --i
) {
1233 if (!is_control(set
, i
))
1235 set
= isl_set_project_out(set
, isl_dim_param
, i
, 1);
1237 set
= isl_set_coalesce(set
);
1244 * { a -> b : (shared >= max and
1245 * the first max iterators are equal) or
1246 * (shared = max - 1 and
1247 * the first max - 1 iterators are equal and
1248 * dimension max - 1 of a is smaller than that of b) or
1251 * the first min iterators are equal and
1252 * dimension min of a is smaller than that of b) }
1254 static __isl_give isl_map
*compute_shared_map(__isl_take isl_space
*space
,
1255 __isl_keep isl_id
*shared_id
, int min
, int max
)
1257 isl_map
*shared_map
;
1260 shared_pos
= isl_space_find_dim_by_id(space
, isl_dim_param
, shared_id
);
1261 shared_map
= isl_map_universe(isl_space_copy(space
));
1262 shared_map
= isl_map_lower_bound_si(shared_map
, isl_dim_param
,
1264 shared_map
= share(shared_map
, max
);
1266 for (int i
= min
; i
< max
; ++i
) {
1267 isl_map
*shared_map_i
;
1269 shared_map_i
= isl_map_universe(isl_space_copy(space
));
1270 shared_map_i
= isl_map_fix_si(shared_map_i
, isl_dim_param
,
1272 shared_map_i
= share(shared_map_i
, i
);
1273 shared_map_i
= isl_map_order_lt(shared_map_i
, isl_dim_in
, i
,
1276 shared_map
= isl_map_union(shared_map
, shared_map_i
);
1279 isl_space_free(space
);
1284 /* Different parts of the final dependence relations may have been
1285 * created at different depths and may therefore have a different
1286 * number of dimensions of the last iterator. The __last_<na>_shared
1287 * value determines how many of the dimensions are implicitly equal
1288 * to those of the sink iteration. This function creates a set that
1289 * makes these equalities explicit, so that we can later remove
1290 * the __last_<na>_shared parameter. It also marks those parts
1291 * that have a number of shared iterators that is smaller than the minimum
1292 * as not having any last iteration.
1294 * In particular, we create a set in the space of the sink of the form
1296 * { s : __last_<na>_valid = 0 or
1297 * (__last_<na>_valid = 1 and
1298 * __last_<na>_<i> is a potential source iteration and
1299 * ((__last_<na>_shared >= max_shared and
1300 * the first max_shared iterators are equal) or
1301 * (__last_<na>_shared = max_shared - 1 and
1302 * the first max_shared - 1 iterators are equal and
1303 * iterator max_shared - 1 of the source is smaller) or
1305 * (__last_<na>_shared = min_shared and
1306 * the first min_shared iterators are equal and
1307 * iterator min_shared of the source is smaller))) }
1309 * That is, for those parts with __last_<na>_shared smaller than
1310 * max_n_shared[source_na], intersection with the set will introduce
1311 * __last_<na>_<i> parameters (assuming they don't have a known fixed value)
1312 * up until __last_<na>_shared and equate them to the corresponding iterators
1315 static __isl_give isl_set
*shared_refinement(__isl_keep isl_id
*shared_id
,
1322 isl_map
*shared_map
;
1323 int valid_pos
, shared_pos
;
1329 ctx
= isl_id_get_ctx(shared_id
);
1331 source_na
= (na_pair
*) isl_id_get_user(shared_id
);
1332 valid_id
= valid_bit_id(ctx
, source_na
);
1334 mem
= info
->get_mem_dep(source_na
);
1335 space
= isl_map_get_space(mem
);
1338 shared_pos
= isl_space_dim(space
, isl_dim_param
);
1339 space
= isl_space_add_dims(space
, isl_dim_param
, 1);
1340 space
= isl_space_set_dim_id(space
, isl_dim_param
,
1341 shared_pos
, isl_id_copy(shared_id
));
1343 shared_map
= compute_shared_map(isl_space_copy(space
), shared_id
,
1344 info
->min_n_shared
[source_na
], info
->max_n_shared
[source_na
]);
1346 domain
= isl_set_universe(isl_space_domain(space
));
1347 valid_pos
= find_or_add_param(&domain
, isl_id_copy(valid_id
));
1348 domain
= isl_set_fix_si(domain
, isl_dim_param
, valid_pos
, 1);
1349 domain
= add_parametrization(domain
, source_na
, info
);
1350 shared_map
= isl_map_intersect_domain(shared_map
, domain
);
1352 valid
= isl_map_range(shared_map
);
1353 invalid
= isl_set_universe(isl_set_get_space(valid
));
1354 shared_pos
= isl_set_find_dim_by_id(invalid
, isl_dim_param
, shared_id
);
1355 invalid
= isl_set_upper_bound_si(invalid
, isl_dim_param
, shared_pos
,
1356 info
->n_shared
- 1);
1358 valid_pos
= find_or_add_param(&invalid
, valid_id
);
1359 invalid
= isl_set_fix_si(invalid
, isl_dim_param
, valid_pos
, 0);
1361 return isl_set_union(valid
, invalid
);
1364 /* Different parts of the final dependence relations may have been
1365 * created at different depths and may therefore have a different
1366 * number of dimensions of the last iterator. The __last_*_shared
1367 * value determines how many of the dimensions are implicitly equal
1368 * to those of the sink iteration.
1370 * For each of the __last_*_shared parameters, explicitly add
1371 * the implicitly equal __last_*_i iterators by intersecting
1372 * the sink with the set computed by shared_refinement.
1373 * Finally, remove the __last_*_shared parameters.
1375 static __isl_give isl_map
*refine_shared(__isl_take isl_map
*dep
,
1379 isl_set
*refinement
;
1382 space
= isl_map_get_space(dep
);
1383 n_param
= isl_space_dim(space
, isl_dim_param
);
1385 refinement
= isl_set_universe(isl_space_range(isl_space_copy(space
)));
1387 for (int i
= 0; i
< n_param
; ++i
) {
1391 if (!is_shared(space
, i
))
1393 if (!isl_map_involves_dims(dep
, isl_dim_param
, i
, 1))
1396 id
= isl_space_get_dim_id(space
, isl_dim_param
, i
);
1397 ref_i
= shared_refinement(id
, info
);
1400 if (isl_set_is_wrapping(refinement
)) {
1401 isl_map
*map
= isl_set_unwrap(refinement
);
1402 map
= isl_map_intersect_domain(map
, ref_i
);
1403 refinement
= isl_map_wrap(map
);
1405 refinement
= isl_set_intersect(refinement
, ref_i
);
1407 dep
= isl_map_intersect_range(dep
, refinement
);
1409 isl_space_free(space
);
1411 space
= isl_map_get_space(dep
);
1412 n_param
= isl_space_dim(space
, isl_dim_param
);
1413 for (int i
= n_param
- 1; i
>= 0; --i
) {
1414 if (!is_shared(space
, i
))
1416 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
1418 isl_space_free(space
);
1420 dep
= isl_map_coalesce(dep
);
1425 /* Compute the gist of "dep" with respect to the fact that
1427 * 0 <= __last_*_valid <= 1
1429 static __isl_give isl_map
*gist_valid(__isl_take isl_map
*dep
)
1435 space
= isl_space_params(isl_map_get_space(dep
));
1436 n_param
= isl_space_dim(space
, isl_dim_param
);
1438 valid
= isl_set_universe(isl_space_copy(space
));
1439 for (int i
= 0; i
< n_param
; ++i
) {
1440 if (!is_valid_bit(space
, i
))
1443 valid
= isl_set_lower_bound_si(valid
, isl_dim_param
, i
, 0);
1444 valid
= isl_set_upper_bound_si(valid
, isl_dim_param
, i
, 1);
1447 isl_space_free(space
);
1449 dep
= isl_map_gist_params(dep
, valid
);
1454 /* Simplify the constraints on the parameters introduced
1455 * in add_parametrization().
1456 * We first add __last_*_i iterators that are only implicitly referred
1457 * to through the __last_*_shared parameters.
1458 * Then, we remove all those parameters that turn out not be needed.
1459 * If there are any of those parameters left, then we compute the gist
1460 * with respect to the valid bit being either 0 or 1 and rename
1461 * the parameters to also include a reference to the sink.
1462 * The resulting relation is assigned to controlled_relation,
1463 * while the relation field is assigned the result of projecting out
1464 * all those parameters.
1466 static __isl_give isl_map
*simplify_controls(__isl_take isl_map
*dep
,
1467 add_dep_info
*info
, bool *has_controls
)
1473 dep
= refine_shared(dep
, info
);
1474 dep
= remove_redundant_controls(dep
, has_controls
);
1475 if (*has_controls
) {
1476 dep
= gist_valid(dep
);
1477 dep
= rename_controls(dep
, info
->read_na_pair
);
1483 /* Extract a single dependence from the result of dataflow analysis.
1485 * We first simplify the constraints on the parameters introduced
1486 * in add_parametrization().
1488 * If the dependence relation turns out to be empty, we simply return.
1489 * Otherwise, we create a corresponding pdg::dependence and keep track
1490 * of the fact that the potential source is actually used
1491 * so that we can remove any reference to potential sources that are
1492 * never used from the dependence relations.
1494 static int add_dep(__isl_take isl_map
*dep
, int must
, void *dep_user
, void *user
)
1497 na_pair
*write_na
= (na_pair
*) dep_user
;
1498 add_dep_info
*info
= (struct add_dep_info
*)user
;
1499 isl_ctx
*ctx
= info
->pdg
->get_isl_ctx();
1502 dep
= isl_map_coalesce(dep
);
1503 dep
= simplify_controls(dep
, info
, &has_controls
);
1504 if (isl_map_is_empty(dep
)) {
1509 info
->used
.insert(write_na
);
1511 d
= new pdg::dependence
;
1513 d
->type
= info
->dtype
;
1514 d
->from
= write_na
->node
;
1515 d
->to
= info
->read_na_pair
->node
;
1516 d
->from_access
= write_na
->access
;
1517 d
->to_access
= info
->read_na_pair
->access
;
1519 if (d
->from_access
->extension
|| d
->to_access
->extension
)
1520 d
->extended_relation
=
1521 new pdg::IslMap(remove_all_controls(isl_map_copy(dep
)));
1522 if (d
->from_access
->extension
)
1523 dep
= isl_map_apply_domain(dep
,
1525 d
->from_access
->extension
->get_isl_map(ctx
)));
1526 if (d
->to_access
->extension
)
1527 dep
= isl_map_apply_range(dep
,
1529 d
->to_access
->extension
->get_isl_map(ctx
)));
1531 d
->controlled_relation
= new pdg::IslMap(isl_map_copy(dep
));
1532 d
->relation
= new pdg::IslMap(remove_all_controls(isl_map_copy(dep
)));
1533 info
->pdg
->dependences
.push_back(d
);
1538 /* This structure represents a set of filter index expressions
1539 * along with bounds on the correponding filter values.
1540 * The number of output dimensions in "value" is the same as
1541 * the number of elements in the "index" vector.
1544 std::vector
<isl_union_map
*> index
;
1548 /* Construct a da_filter object representing the filters in
1549 * na->node and na->access.
1551 static struct da_filter
*extract_filter(na_pair
*na
)
1553 da_filter
*filter
= new da_filter
;
1555 pdg::node
*node
= na
->node
;
1556 pdg::access
*access
= na
->access
;
1558 domain
= node
->source
->get_isl_set();
1559 if (isl_set_is_wrapping(domain
))
1560 filter
->value
= isl_set_unwrap(domain
);
1562 filter
->value
= isl_map_from_domain(domain
);
1564 for (int i
= 0; i
< node
->filters
.size(); ++i
)
1565 filter
->index
.push_back(extract_access_map(node
->filters
[i
]));
1567 if (access
->nested
.size() == 0)
1570 domain
= isl_map_domain(access
->map
->get_isl_map());
1571 filter
->value
= isl_map_flat_range_product(filter
->value
,
1572 isl_set_unwrap(domain
));
1574 for (int i
= 0; i
< access
->nested
.size(); ++i
)
1575 filter
->index
.push_back(extract_access_map(access
->nested
[i
]));
1580 static struct da_filter
*da_filter_free(struct da_filter
*filter
)
1584 for (int i
= 0; i
< filter
->index
.size(); ++i
)
1585 isl_union_map_free(filter
->index
[i
]);
1586 isl_map_free(filter
->value
);
1591 static void da_filter_dump(struct da_filter
*filter
)
1598 p
= isl_printer_to_file(isl_map_get_ctx(filter
->value
), stderr
);
1599 p
= isl_printer_start_line(p
);
1600 p
= isl_printer_print_str(p
, "value(");
1601 for (int i
= 0; i
< filter
->index
.size(); ++i
) {
1603 p
= isl_printer_print_str(p
, ", ");
1604 p
= isl_printer_print_union_map(p
, filter
->index
[i
]);
1606 p
= isl_printer_print_str(p
, ") in ");
1607 p
= isl_printer_print_map(p
, filter
->value
);
1608 p
= isl_printer_end_line(p
);
1610 isl_printer_free(p
);
1613 /* Look for a filter index expression in "filter" that is identical
1614 * to "index". Return the index of this index expression if it is
1615 * found and the number of elements in filter->index otherwise.
1617 static int da_filter_find_exact_match(struct da_filter
*filter
,
1618 __isl_keep isl_union_map
*index
)
1620 for (int i
= 0; i
< filter
->index
.size(); ++i
) {
1623 equal
= isl_union_map_is_equal(filter
->index
[i
], index
);
1630 return filter
->index
.size();
1633 /* Add the index expression "index" to "filter" with an unconstrained
1634 * filter value. To ease debugging we set the name of the new filter
1635 * value dimension to that of the array being accessed by "index".
1636 * Although the range of "index" is allowed to live in more than
1637 * one space, we assume that they are all wrapped maps to the same
1640 static struct da_filter
*da_filter_add(struct da_filter
*filter
,
1641 __isl_take isl_union_map
*index
)
1644 isl_union_map
*univ
;
1647 if (!filter
|| !index
)
1650 filter
->value
= isl_map_add_dims(filter
->value
, isl_dim_out
, 1);
1651 univ
= isl_union_map_universe(isl_union_map_copy(index
));
1652 univ
= isl_union_set_unwrap(isl_union_map_range(univ
));
1653 set
= isl_set_from_union_set(isl_union_map_range(univ
));
1654 id
= isl_set_get_tuple_id(set
);
1656 filter
->value
= isl_map_set_dim_id(filter
->value
, isl_dim_out
,
1657 filter
->index
.size(), id
);
1660 filter
->index
.push_back(index
);
1664 isl_union_map_free(index
);
1665 da_filter_free(filter
);
1669 /* Intersect the set of possible filter values in "filter" with "value".
1671 static struct da_filter
*da_filter_restrict(struct da_filter
*filter
,
1672 __isl_take isl_map
*value
)
1674 if (!filter
|| !value
)
1677 filter
->value
= isl_map_intersect(filter
->value
, value
);
1679 return da_filter_free(filter
);
1683 isl_map_free(value
);
1684 da_filter_free(filter
);
1688 /* Does "map" represent a total filter on "domain", i.e., one that is defined
1689 * on every element of "domain"?
1691 * Although the range of "map" may live in different spaces, we assume
1692 * that the domain of "map" lives in a single space.
1694 static int is_total_filter(__isl_keep isl_union_map
*map
,
1695 __isl_keep isl_set
*domain
)
1697 isl_union_set
*map_domain
;
1701 map_domain
= isl_union_map_domain(isl_union_map_copy(map
));
1702 set
= isl_set_from_union_set(map_domain
);
1703 total
= isl_set_is_subset(domain
, set
);
1709 /* Does "node" have only total filters on "domain"?
1711 static int all_total_filters(pdg::node
*node
, __isl_take isl_set
*domain
)
1715 for (int i
= 0; i
< node
->filters
.size(); ++i
) {
1716 isl_union_map
*map
= extract_access_map(node
->filters
[i
]);
1718 total
= is_total_filter(map
, domain
);
1719 isl_union_map_free(map
);
1725 isl_set_free(domain
);
1729 /* Does "node" have only total filters on the domain of "map"?
1731 static bool filters_total_on_domain(pdg::node
*node
, __isl_keep isl_map
*map
)
1733 return all_total_filters(node
, isl_map_domain(isl_map_copy(map
)));
1736 /* Does "node" have only total filters on the range of "map"?
1738 static bool filters_total_on_range(pdg::node
*node
, __isl_keep isl_map
*map
)
1740 return all_total_filters(node
, isl_map_range(isl_map_copy(map
)));
1743 /* Are the filters of "source_node" total on the range of "source_map"
1744 * and those of "sink_node" (if any) total on the domain of "soruce_map"?
1746 static bool total_filters(pdg::node
*source_node
, pdg::node
*sink_node
,
1747 __isl_keep isl_map
*source_map
)
1751 total
= filters_total_on_range(source_node
, source_map
);
1755 if (!isl_set_is_wrapping(sink_node
->source
->set
))
1758 total
= filters_total_on_domain(sink_node
, source_map
);
1765 /* Does "node" have any single valued filters?
1767 static int any_single_valued_filter(pdg::node
*node
)
1769 for (int i
= 0; i
< node
->filters
.size(); ++i
) {
1770 isl_union_map
*map
= extract_access_map(node
->filters
[i
]);
1773 sv
= isl_union_map_is_single_valued(map
);
1774 isl_union_map_free(map
);
1783 /* Construct a mapping from the source iterations to all source filter values
1784 * that allow some corresponding sink iteration(s) (according to "source_map")
1785 * to be executed. In other words, if any sink iteration is executed,
1786 * then we know that the filters of the corresponding source iterations
1787 * satisfy the returned relation.
1789 * The "filter" input represents what is known about the filter
1790 * values at the sink.
1792 * The "source" domain of the source is a wrapped map,
1793 * mapping iteration vectors to filter values.
1794 * We first construct a relation between the sink filter values (available
1795 * in "filter") and the source filter values. The purpose of this relation
1796 * is to find as much information about the source filter values
1797 * as possible. We can start with the value bounds on the arrays
1798 * accessed in the filters as they always hold.
1799 * Next, we loop over the source filters and check whether there
1800 * is any sink filter that covers the source filter.
1801 * In particular, for each source filter, we construct a map
1802 * from the source iteration domain to a wrapped access relation,
1803 * representing the write access relation that corresponds to
1804 * the filter read access. Note that if we were unable to determine this
1805 * write access, then the mapping returned by extract_access_map
1806 * maps to the original read access, which will not match with
1807 * any filter access relations of the sink.
1808 * We combine the constructed map with the proto-dependence
1809 * (source_map) to obtain a mapping from sink iterations to
1810 * access relations such that there is some source iteration that
1811 * may be the source of the given sink iteration (based on source_map)
1812 * and that the filter value at this source iteration was written by
1813 * that access. If the result is a subset of the mapping from the
1814 * sink iterations to the corresponding write access relation for some filter,
1815 * then we know that any constraint on this filter value also applies
1816 * to the source filter value. We therefore introduce an equality
1817 * in our mapping from sink filter values to source filter values.
1819 * When we apply the mapping from sink filter values to source filter values
1820 * to the mapping from source iterations to sink filter values, we
1821 * obtain a mapping from sink iterations to source filter values
1822 * that represents what we know about the source filter values.
1823 * That is, for each sink iteration in the domain of this map, if this
1824 * sink iteration is executed, then the actual source filter values
1825 * are an element of the image of the sink iteration.
1826 * In other words, the sink iteration is only executed if the source
1827 * filter values are an element of the image.
1828 * Mapping this relation back to the source through the proto-dependence
1829 * source_map, we obtain a relation from source iterations to all source
1830 * filter values for which any sink iteration is executed.
1831 * In particular, for values of the filters outside this relation,
1832 * no corresponding (according to source_map) sink is executed.
1834 static __isl_give isl_map
*known_filter_values(struct da_filter
*filter
,
1835 na_pair
*source_na
, __isl_keep isl_map
*source_map
)
1837 isl_space
*space
, *space2
;
1838 isl_map
*source_value
, *sink_value
;
1839 isl_map
*filter_map
;
1842 sink_value
= isl_map_copy(filter
->value
);
1844 space
= isl_set_get_space(source_na
->node
->source
->set
);
1845 space
= isl_space_range(isl_space_unwrap(space
));
1846 space2
= isl_space_range(isl_map_get_space(sink_value
));
1847 space
= isl_space_align_params(space
, isl_space_copy(space2
));
1848 space2
= isl_space_align_params(space2
, isl_space_copy(space
));
1849 space
= isl_space_map_from_domain_and_range(space2
, space
);
1850 filter_map
= isl_map_universe(space
);
1852 bounds
= compute_filter_bounds(source_na
->node
);
1853 filter_map
= isl_map_intersect_range(filter_map
, bounds
);
1855 for (int i
= 0; i
< source_na
->node
->filters
.size(); ++i
) {
1856 isl_union_map
*map_i
;
1857 map_i
= extract_access_map(source_na
->node
->filters
[i
]);
1858 map_i
= isl_union_map_apply_range(
1859 isl_union_map_from_map(isl_map_copy(source_map
)), map_i
);
1860 for (int j
= 0; j
< filter
->index
.size(); ++j
) {
1861 if (isl_union_map_is_subset(map_i
, filter
->index
[j
]))
1862 filter_map
= isl_map_equate(filter_map
,
1863 isl_dim_in
, j
, isl_dim_out
, i
);
1865 isl_union_map_free(map_i
);
1868 source_value
= isl_map_apply_range(sink_value
, filter_map
);
1869 source_value
= isl_map_apply_domain(source_value
,
1870 isl_map_copy(source_map
));
1871 source_value
= isl_map_coalesce(source_value
);
1873 return source_value
;
1876 /* Add a new output dimension to "map" with constraints that are the
1877 * same as those on output dimension "pos".
1879 * Given map { [i] -> [j] }, we first and an extra dimension,
1883 * extract out j_pos,
1885 * { [[i] -> [j_0,...,j_{pos-1},*,j_{pos+1},...,*]] -> [j_pos] }
1889 * { [[i] -> [j_0,...,j_{pos-1},*,j_{pos+1},...,*]] -> [j_pos,j_pos'] }
1891 * and then move the dimensions back
1893 * { [i] -> [j,j_pos'] }
1895 static __isl_give isl_map
*copy_dim(__isl_take isl_map
*map
, int pos
)
1899 pos_new
= isl_map_dim(map
, isl_dim_out
);
1900 pos
+= isl_map_dim(map
, isl_dim_in
);
1901 pos_new
+= isl_map_dim(map
, isl_dim_in
);
1902 map
= isl_map_add_dims(map
, isl_dim_out
, 1);
1903 map
= isl_map_from_domain(isl_map_wrap(map
));
1904 map
= isl_map_add_dims(map
, isl_dim_out
, 1);
1905 map
= isl_map_equate(map
, isl_dim_in
, pos
, isl_dim_out
, 0);
1906 map
= isl_map_eliminate(map
, isl_dim_in
, pos
, 1);
1907 map
= isl_map_range_product(map
, isl_map_copy(map
));
1908 map
= isl_map_equate(map
, isl_dim_in
, pos
, isl_dim_out
, 0);
1909 map
= isl_map_equate(map
, isl_dim_in
, pos_new
, isl_dim_out
, 1);
1910 map
= isl_set_unwrap(isl_map_domain(map
));
1915 /* Given constraints on the filter values "filter" at the sink iterations
1916 * "sink", derive additional constraints from the filter values of source
1917 * node "source_na". In particular, consider the iterations of "source_na"
1918 * that have _not_ been executed based on the constraints of the corresponding
1919 * last iteration parameters in "sink" and what this implies about the
1920 * filter values at those iterations.
1922 * Essentially, we consider all pairs of sink iterations and filter
1923 * elements, together with the corresponding non-executed source iterations
1924 * and the possible values of those filters. We universally quantify
1925 * the non-executed source iterations so that we obtain the intersection
1926 * of the constraints on the filter values over all those source iterations
1927 * and then existentially quantify the filter elements to obtain constraints
1928 * that are valid for all filter elements.
1930 * In more details, the computation is performed as follows.
1932 * Compute a mapping from potential last iterations of the other source
1933 * to sink iterations, taking into account the contraints on
1934 * the last executed iterations encoded in the parameters of "sink",
1935 * but projecting out all parameters encoding last iterations from the result.
1936 * Include all earlier iterations of the other source, resulting in
1937 * a mapping with a domain that includes all potential iterations of the
1940 * Subtract these iterations from all possible iterations of the other
1941 * source for a given sink iteration, resulting in a mapping from
1942 * potential source iterations that are definitely not executed
1943 * to the corresponding sink iteration.
1945 * If this map is empty, then this means we can't find any iterations
1946 * of the other source that are certainly not executed and then we
1947 * can't derive any further information.
1948 * Similarly, if the filters of source_na->node are not total
1949 * on the set of non-executed iterations, then we cannot draw any conclusions.
1950 * (Note that we already tested that the filters on sink->node are total
1951 * on the domain of "source_map". By intersecting the set of corresponding
1952 * sink iterations with this domain, we ensure that this property also holds
1953 * on those sink iterations.)
1954 * Otherwise, keep track of those sink iterations without any corresponding
1955 * non-executed other source iterations. We will lose these sink iterations
1956 * in subsequent computations, so we need to add them back in at the end.
1958 * Compute bounds on the filter values at the non executed iterations
1959 * based on what we know about filters at the sink and the fact that
1960 * the iterations are not executed, meaning that the filter values
1961 * do not satisfy the constraints that allow the iteration to be executed.
1962 * The result is a mapping T -> V.
1964 * Note that we only know that there is some accessed filter element
1965 * that does not satisfy the constraints that allow the iteration to be
1966 * executed. We therefore project out those dimensions that correspond
1967 * to filters with an access relation that is not single-valued, i.e.,
1968 * one that may access more than one element for some iterations.
1969 * If there are no single-valued filters, then we can skip the rest of
1972 * Construct a mapping [K -> F] -> T, with K the sink iterations,
1973 * T the corresponding non-executed iterations of the other source and
1974 * F the filters accessed at those iterations.
1976 * Combine the above two mappings into a mapping [K -> F] -> V
1977 * such that the set of possible filter values (V) is the intersection
1978 * over all iterations of the other source that access the filter,
1979 * and such that there is at least one such iteration.
1980 * In other words, ensure that the range of [K -> F] -> T
1981 * is a non-empty subset of the range of V -> T.
1982 * We require a non-empty subset to ensure that the domain of
1983 * [K -> F] -> V is equal to the result of composing K -> T with T -> F.
1984 * Projecting out F from [K -> F] -> V, we obtain a map K -> V that is
1985 * the union of all possible values of the filters K -> F, i.e.,
1986 * the constraints that the values of K -> F satisfy.
1987 * If we didn't impose non-emptiness above, then the domain of [K -> F] -> V
1988 * would also include pairs that we are not interested in, related to
1989 * arbitrary values. Projecting out F would then also lead to arbitrary
1992 * Compose the mapping K -> T with the index expressions, pulling them
1994 * For each of these pulled back index expressions, we check if it
1995 * is equal to one of the sink filter index expressions. If not, we
1996 * add it to the sink filter index expressions.
1997 * In both cases, we keep track of the fact that this sink filter
1998 * should have a value that satisfies the constraints in K -> V.
1999 * We further check if there is any sink filter index expression
2000 * that is a (strict) subset of the pulled back index expression.
2001 * The value of any such sink filter should also satisfy those
2002 * constraints, so we duplicate the filter value in K -> V.
2004 * Finally, we intersect the possible filter values with the constraints
2005 * obtained above on the affected sink iterations and a universe range
2006 * on the unaffected sink iterations.
2008 static struct da_filter
*include_other_source(struct da_filter
*filter
,
2009 __isl_keep isl_map
*source_map
, __isl_keep isl_set
*sink
,
2010 na_pair
*source_na
, add_dep_info
*info
)
2012 isl_space
*space
, *space2
;
2013 isl_set
*source_domain
;
2015 isl_map
*may_run
, *not_run
;
2016 isl_map
*source_value
;
2017 isl_union_map
*usource
, *umap
;
2018 std::vector
<isl_union_map
*> index
;
2019 isl_union_map
*index_product
;
2021 isl_map
*filter_map
;
2022 isl_set
*unaffected_sink
;
2023 isl_map
*unaffected_value
;
2025 if (source_na
->node
->filters
.size() == 0)
2028 space
= isl_set_get_space(source_na
->node
->source
->set
);
2029 space
= isl_space_domain(isl_space_unwrap(space
));
2030 source_domain
= isl_set_universe(space
);
2031 source_domain
= add_parametrization(source_domain
, source_na
, info
);
2032 may_run
= isl_map_from_domain_and_range(source_domain
,
2033 isl_set_copy(sink
));
2034 may_run
= share(may_run
, info
->n_shared
);
2036 may_run
= remove_all_controls(may_run
);
2037 mem
= info
->get_mem_dep(source_na
);
2038 mem
= share(mem
, info
->n_shared
);
2039 mem
= isl_map_intersect_range(mem
,
2040 isl_map_domain(remove_all_controls(isl_map_copy(source_map
))));
2041 space
= isl_space_domain(isl_map_get_space(may_run
));
2042 may_run
= isl_map_apply_domain(may_run
, isl_map_lex_ge(space
));
2043 not_run
= isl_map_subtract(mem
, may_run
);
2045 if (isl_map_is_empty(not_run
) ||
2046 !any_single_valued_filter(source_na
->node
) ||
2047 !filters_total_on_domain(source_na
->node
, not_run
)) {
2048 isl_map_free(not_run
);
2052 not_run
= isl_map_reverse(not_run
);
2053 source_value
= known_filter_values(filter
, source_na
, not_run
);
2054 source_value
= isl_map_subtract(source_value
,
2055 isl_set_unwrap(source_na
->node
->source
->get_isl_set()));
2056 unaffected_sink
= isl_set_copy(sink
);
2057 unaffected_sink
= remove_all_controls(unaffected_sink
);
2058 unaffected_sink
= isl_set_subtract(unaffected_sink
,
2059 isl_map_domain(isl_map_copy(not_run
)));
2061 for (int i
= 0; i
< source_na
->node
->filters
.size(); ++i
) {
2065 map
= extract_access_map(source_na
->node
->filters
[i
]);
2066 sv
= isl_union_map_is_single_valued(map
);
2068 index
.push_back(map
);
2070 isl_union_map_free(map
);
2071 source_value
= isl_map_project_out(source_value
,
2072 isl_dim_out
, index
.size(), 1);
2076 index_product
= isl_union_map_copy(index
[0]);
2077 for (int i
= 1; i
< index
.size(); ++i
)
2078 index_product
= isl_union_map_range_product(index_product
,
2079 isl_union_map_copy(index
[1]));
2080 index_product
= isl_union_map_reverse(index_product
);
2081 index_product
= isl_union_map_domain_product(
2082 isl_union_map_from_map(isl_map_copy(not_run
)), index_product
);
2084 usource
= isl_union_map_from_map(source_value
);
2085 usource
= join_non_empty_subset(index_product
, usource
);
2086 umap
= isl_union_map_universe(isl_union_map_copy(usource
));
2087 umap
= isl_union_set_unwrap(isl_union_map_domain(umap
));
2088 umap
= isl_union_map_domain_map(umap
);
2089 usource
= isl_union_map_apply_domain(usource
, umap
);
2090 source_value
= isl_map_from_union_map(usource
);
2092 for (int i
= 0; i
< index
.size(); ++i
)
2093 index
[i
] = isl_union_map_apply_range(
2094 isl_union_map_from_map(isl_map_copy(not_run
)), index
[i
]);
2096 space
= isl_space_range(isl_map_get_space(source_value
));
2097 space2
= isl_space_range(isl_map_get_space(filter
->value
));
2098 space
= isl_space_align_params(space
, isl_space_copy(space2
));
2099 space2
= isl_space_align_params(space2
, isl_space_copy(space
));
2100 space
= isl_space_map_from_domain_and_range(space
, space2
);
2101 filter_map
= isl_map_universe(space
);
2103 for (int i
= 0; i
< index
.size(); ++i
) {
2104 int exact
= da_filter_find_exact_match(filter
, index
[i
]);
2106 if (exact
== filter
->index
.size()) {
2107 filter
= da_filter_add(filter
,
2108 isl_union_map_copy(index
[i
]));
2109 filter_map
= isl_map_add_dims(filter_map
,
2112 filter_map
= isl_map_equate(filter_map
, isl_dim_in
, i
,
2113 isl_dim_out
, exact
);
2114 for (int j
= 0; j
< filter
->index
.size(); ++j
) {
2119 if (!isl_union_map_is_subset(filter
->index
[j
],
2122 pos
= isl_map_dim(source_value
, isl_dim_out
);
2123 source_value
= copy_dim(source_value
, i
);
2124 filter_map
= isl_map_add_dims(filter_map
,
2126 filter_map
= isl_map_equate(filter_map
, isl_dim_in
, pos
,
2131 source_value
= isl_map_apply_range(source_value
, filter_map
);
2132 source_value
= isl_map_coalesce(source_value
);
2133 unaffected_value
= isl_map_from_domain(unaffected_sink
);
2134 unaffected_value
= isl_map_add_dims(unaffected_value
, isl_dim_out
,
2135 filter
->index
.size());
2136 source_value
= isl_map_union(source_value
, unaffected_value
);
2137 filter
= da_filter_restrict(filter
, source_value
);
2139 for (int i
= 0; i
< index
.size(); ++i
)
2140 isl_union_map_free(index
[i
]);
2141 isl_map_free(not_run
);
2146 /* Given constraints on the filter values "filter" at the sink iterations
2147 * "sink", derive additional constraints from the filter values of those
2148 * source nodes for which "sink" contains a reference to its last iteration,
2149 * for use in determining whether parametrization is needed on "source_map".
2150 * In particular, we try and derive extra information from the fact that
2151 * some iterations of those source nodes have _not_ been executed.
2153 static struct da_filter
*include_other_sources(struct da_filter
*filter
,
2154 __isl_keep isl_map
*source_map
, __isl_keep isl_set
*sink
,
2160 space
= isl_set_get_space(sink
);
2161 n_param
= isl_space_dim(space
, isl_dim_param
);
2162 for (int i
= 0; i
< n_param
; ++i
) {
2166 if (!is_shared(space
, i
))
2169 id
= isl_space_get_dim_id(space
, isl_dim_param
, i
);
2170 na
= (na_pair
*) isl_id_get_user(id
);
2173 filter
= include_other_source(filter
, source_map
, sink
,
2176 isl_space_free(space
);
2181 #define RESTRICT_ERROR -1
2182 #define RESTRICT_NO 0
2183 #define RESTRICT_EMPTY 1
2184 #define RESTRICT_INPUT 2
2185 #define RESTRICT_OUTPUT 3
2187 /* Given a map from sinks to potential sources (source_map)
2188 * and the set of sink iterations (sink),
2189 * check if any parametrization is needed on the sources.
2190 * That is, check whether the possible filter values at the sink
2191 * imply that the filter values at the source are always valid.
2192 * If so, the source is executed whenever the sink is executed
2193 * and no parametrization is required.
2195 * Return RESTRICT_NO if no parametrization is required.
2196 * Return RESTRICT_INPUT if parametrization is required on the input
2197 * of the computation of the last iteration.
2198 * Return RESTRICT_OUTPUT if parametrization is required on the output
2199 * of the computation of the last iteration. This means that we know
2200 * that the source will be executed, but we want to introduce a parameter
2201 * to represent the last iteration anyway, because the knowledge depends
2202 * on the parameters representing last iterations of other nodes.
2203 * Return RESTRICT_EMPTY if the potential sources cannot possibly
2204 * be executed, assuming that the sink is executed.
2206 * If there are no filters on the source, then obviously the source
2207 * is always executed.
2209 * If the filters of the sink and the source are not all total
2210 * on domain and range of "source_map", then we cannot draw any conclusion.
2211 * In principle, we could split up "source_map" according to whether
2212 * the filters would be total on the domain and range.
2214 * We first construct a mapping from source iterations to source filter
2215 * values that allow some corresponding sink iteration(s) (according to
2216 * "source_map") to be executed.
2217 * If this relation is a subset of the actual mapping from iteration
2218 * vectors to filter values at the source, then we know that a corresponding
2219 * sink is only executed when the source is executed and no parametrization
2220 * is required. However, we postpone the decision until we have considered
2221 * the other potential sources below.
2222 * If, on the other hand, the constructed relation is disjoint
2223 * from the source filter relation, then the sources cannot have
2224 * executed if the sink is executed. If so, we return
2225 * RESTRICT_EMPTY immediately.
2227 * Otherwise, we check if we can find out more information by considering
2228 * information derived from knowledge about the last iterations of other
2229 * nodes. If, by considering this extract information, we can find
2230 * that the potential source is never executed (given that the sink
2231 * is executed), then we return RESTRICT_EMPTY.
2232 * Otherwise, if we had already determined that the relation based
2233 * on only the sink is a subset of the filter values, then we return
2234 * RESTRICT_NO. If we can only draw this conclusion when taking into
2235 * account the other potential sources, then we return RESTRICT_OUTPUT.
2236 * Otherwise, we return RESTRICT_INPUT.
2238 static int need_parametrization(__isl_keep isl_map
*source_map
,
2239 __isl_keep isl_set
*sink
, na_pair
*source_na
, add_dep_info
*info
)
2241 bool filtered_source
;
2243 isl_map
*source_value
, *sink_value
;
2245 na_pair
*sink_na
= info
->read_na_pair
;
2248 if (isl_map_plain_is_empty(source_map
) ||
2249 isl_set_plain_is_empty(sink
))
2252 filtered_source
= isl_set_is_wrapping(source_na
->node
->source
->set
);
2254 if (!filtered_source
)
2257 if (!total_filters(source_na
->node
, sink_na
->node
, source_map
))
2258 return RESTRICT_INPUT
;
2260 filter
= extract_filter(sink_na
);
2262 if (filter
->index
.size() != 0) {
2263 sink_value
= known_filter_values(filter
, source_na
, source_map
);
2264 source_value
= isl_set_unwrap(
2265 source_na
->node
->source
->get_isl_set());
2267 if (isl_map_is_disjoint(sink_value
, source_value
))
2268 res
= RESTRICT_EMPTY
;
2269 else if (isl_map_is_subset(sink_value
, source_value
))
2271 isl_map_free(source_value
);
2272 isl_map_free(sink_value
);
2275 if (res
== RESTRICT_EMPTY
) {
2276 da_filter_free(filter
);
2280 filter
= include_other_sources(filter
, source_map
, sink
, info
);
2283 return RESTRICT_ERROR
;
2284 if (filter
->index
.size() == 0) {
2285 da_filter_free(filter
);
2286 return RESTRICT_INPUT
;
2289 sink_value
= known_filter_values(filter
, source_na
, source_map
);
2290 source_value
= isl_set_unwrap(source_na
->node
->source
->get_isl_set());
2292 if (isl_map_is_disjoint(sink_value
, source_value
))
2293 res
= RESTRICT_EMPTY
;
2294 else if (res
== RESTRICT_NO
)
2296 else if (isl_map_is_subset(sink_value
, source_value
))
2297 res
= RESTRICT_OUTPUT
;
2299 res
= RESTRICT_INPUT
;
2301 isl_map_free(source_value
);
2302 isl_map_free(sink_value
);
2303 da_filter_free(filter
);
2309 static __isl_give isl_restriction
*do_restrict(
2310 __isl_keep isl_map
*source_map
, __isl_keep isl_set
*sink
,
2311 void *source_user
, void *user
);
2314 /* Add parameters corresponding to the last iteration of "na" to "set"
2315 * (assuming they don't already appear in "set")
2316 * and add constraints to them to express that there either is no
2317 * last iteration with info->n_shared shared loops
2318 * (__last_<na>_shared < info->n_shared) or that there is a last
2319 * iteration with at least info->n_shared shared loops
2320 * (__last_<na>_shared >= info->n_shared) and that the iteration is a possible
2321 * source of the current sink (based on the memory dependence between
2322 * the source and the sink).
2324 static __isl_give isl_set
*set_parameter_bounds(__isl_take isl_set
*set
,
2325 na_pair
*na
, add_dep_info
*info
)
2334 id
= create_shared_id(isl_set_get_ctx(set
), na
);
2335 shared_pos
= find_or_add_param(&set
, id
);
2337 valid
= isl_set_copy(set
);
2340 valid
= isl_set_lower_bound_si(valid
, isl_dim_param
, shared_pos
,
2343 mem
= info
->get_mem_dep(na
);
2344 domain
= isl_set_universe(isl_space_domain(isl_map_get_space(mem
)));
2345 domain
= add_parametrization(domain
, na
, info
);
2346 mem
= isl_map_intersect_domain(mem
, domain
);
2347 valid
= isl_set_intersect(valid
, isl_map_range(mem
));
2349 invalid
= isl_set_upper_bound_si(invalid
, isl_dim_param
, shared_pos
,
2350 info
->n_shared
- 1);
2352 return isl_set_union(valid
, invalid
);
2355 /* Check if there are any iterations of "source_na" in "source_map"
2356 * that are definitely executed, based solely on the possible filter values.
2357 * If so, add constraints to "sink" to indicate that the last execution
2358 * cannot be earlier than those definitely executed iterations.
2360 * We first compute the set of source iterations that are definitely
2361 * executed because there are no filter values that would prohibit
2362 * their execution. If there are no such source iterations then we are done.
2364 * Then we construct a map from sink iterations to associated (through
2365 * "source_map") definitely executed source iterations.
2367 * For those sink iterations that have a corresponding definitely
2368 * executed source iteration, we add constraints that express that
2369 * this last definitely executed source iteration is lexicographically
2370 * smaller than or equal to the last executed source iteration
2371 * (and that there definitely is a last executed source iteration).
2373 static __isl_give isl_set
*mark_definite_source(__isl_take isl_set
*sink
,
2374 add_dep_info
*info
, na_pair
*source_na
, __isl_keep isl_map
*source_map
)
2379 isl_map
*definite_source_map
;
2380 isl_set
*with_source
;
2384 dom
= source_na
->node
->source
->get_isl_set();
2385 dom
= isl_map_domain(isl_set_unwrap(dom
));
2386 invalid
= compute_filter_values(source_na
->node
, true);
2387 dom
= isl_set_subtract(dom
, isl_map_domain(invalid
));
2389 if (isl_set_is_empty(dom
)) {
2394 space
= isl_set_get_space(dom
);
2396 definite_source_map
= isl_map_copy(source_map
);
2397 definite_source_map
= isl_map_intersect_range(source_map
, dom
);
2399 dom
= isl_map_domain(isl_map_copy(definite_source_map
));
2401 with_source
= isl_set_copy(sink
);
2402 with_source
= isl_set_intersect(with_source
, isl_set_copy(dom
));
2403 sink
= isl_set_subtract(sink
, dom
);
2405 dom
= isl_set_universe(isl_space_copy(space
));
2406 dom
= add_parametrization(dom
, source_na
, info
);
2408 depth
= source_na
->node
->get_filter_depth();
2410 space
= isl_space_map_from_set(space
);
2411 map_after
= isl_map_lex_ge_first(space
, depth
);
2412 dom
= isl_set_apply(dom
, map_after
);
2414 definite_source_map
= isl_map_intersect_range(definite_source_map
, dom
);
2416 dom
= isl_map_domain(definite_source_map
);
2417 with_source
= isl_set_intersect(with_source
, dom
);
2419 sink
= isl_set_union(sink
, with_source
);
2424 /* Remove inconsistencies from the set of sink iterations "sink"
2425 * based on the current potential source "source_na" and other
2426 * potential sources referenced by "sink".
2428 * We first identify those iterations of "source_na" that are
2429 * definitely executed based solely on the possible filter values.
2431 * If the sink has filters, then we remove inconsistencies based
2432 * on the sink and the current potential source.
2434 * Finally, we go through the references to other potential sources
2435 * in "sink" and remove inconsistencies based on this other potential
2436 * source and the current potential source.
2438 static __isl_give isl_set
*remove_inconsistencies(__isl_take isl_set
*sink
,
2439 add_dep_info
*info
, na_pair
*source_na
, __isl_keep isl_map
*source_map
)
2445 source_id
= create_shared_id(isl_map_get_ctx(source_map
), source_na
);
2447 sink
= mark_definite_source(sink
, info
, source_na
, source_map
);
2449 if (isl_set_is_wrapping(info
->read_na_pair
->node
->source
->set
))
2450 sink
= remove_inconsistencies(sink
, info
, source_id
);
2452 space
= isl_set_get_space(sink
);
2453 n_param
= isl_space_dim(space
, isl_dim_param
);
2454 for (int i
= 0; i
< n_param
; ++i
) {
2457 if (!is_shared(space
, i
))
2459 other_id
= isl_space_get_dim_id(space
, isl_dim_param
, i
);
2461 if (other_id
!= source_id
) {
2464 other_na
= (na_pair
*) isl_id_get_user(other_id
);
2465 sink
= set_parameter_bounds(sink
, other_na
, info
);
2466 sink
= remove_inconsistencies(sink
, info
, other_id
,
2470 isl_id_free(other_id
);
2472 isl_space_free(space
);
2474 isl_id_free(source_id
);
2478 /* Compute a restriction for the given sink.
2479 * That is, add constraints to the parameters expressing
2480 * that the source is either not executed with info->n_shared shared
2481 * iterators (*_shared < info->n_shared)
2482 * or it is executed (*_shared >= info->n_shared) and then the last iteration
2483 * satisfies the corresponding memory based dependence.
2485 * Only do this for that part of "sink" that has any corresponding
2486 * sources in "source_map". The remaining part of "sink" is not affected.
2488 * Note that the "sink" set may have undergone a refinement based
2489 * on the _shared parameters and we want this refinement to also
2490 * be present in the sink restriction. We therefore need
2491 * to intersect the affected part with "sink".
2493 static __isl_give isl_set
*compute_sink_restriction(
2494 __isl_keep isl_map
*source_map
, __isl_keep isl_set
*sink
,
2495 na_pair
*source_na
, add_dep_info
*info
)
2497 isl_set
*with_source
, *without_source
;
2499 with_source
= isl_map_domain(isl_map_copy(source_map
));
2500 without_source
= isl_set_subtract(isl_set_copy(sink
),
2501 isl_set_copy(with_source
));
2502 with_source
= isl_set_intersect(with_source
, isl_set_copy(sink
));
2504 with_source
= set_parameter_bounds(with_source
, source_na
, info
);
2505 with_source
= remove_inconsistencies(with_source
, info
, source_na
,
2508 return isl_set_union(with_source
, without_source
);
2511 /* How many loops do "node1" and "node2" share?
2513 static int max_shared(pdg::node
*node1
, pdg::node
*node2
)
2516 int size
= node1
->prefix
.size();
2518 if (node2
->prefix
.size() < size
)
2519 size
= node2
->prefix
.size();
2521 for (int i
= 0; i
< size
&& node1
->prefix
[i
] == node2
->prefix
[i
]; ++i
)
2522 if (node1
->prefix
[i
] == -1)
2528 /* Determine the number of shared loop iterators between sink
2529 * and source domains in "sink2source". That is, find out how
2530 * many of the initial input and output dimensions are equal
2531 * to each other. Return the result.
2533 * The first time this function is called for a given sink access
2534 * (info->n_shared is set to -1 in add_dep_info::set_read_na),
2535 * we check for equal dimensions up to the shared nesting depth.
2536 * Later call check dimensions up to the result of the previous call.
2538 static int extract_shared_levels(__isl_keep isl_map
*sink2source
,
2539 na_pair
*source_na
, add_dep_info
*info
)
2545 max
= info
->n_shared
;
2547 max
= max_shared(source_na
->node
, info
->read_na_pair
->node
);
2550 return info
->n_shared
= 0;
2552 space
= isl_map_get_space(sink2source
);
2553 for (i
= 0; i
< max
; ++i
) {
2557 test
= isl_map_universe(isl_space_copy(space
));
2558 test
= isl_map_equate(test
, isl_dim_in
, i
, isl_dim_out
, i
);
2559 subset
= isl_map_is_subset(sink2source
, test
);
2565 isl_space_free(space
);
2570 /* The last iteration referred to by the sink may have been added
2571 * at a different nesting level. This means that __last_<na>_shared
2572 * is greater than or equal to a value greater than info->n_shared
2573 * and that therefore the iterators between info->n_shared and
2574 * __last_<na>_shared are not represented as they are implicitly
2575 * considered to be equal to the corresponding sink iterator.
2576 * For consistency, we need to explicitly add those iterators
2577 * and set them to be equal to the corresponding sink iterator.
2579 * In particular, we create a set in the space of the sink of the form
2581 * { s : __last_<na>_shared < info->n_shared or
2582 * (__last_<na>_<i> is a potential source iteration for s and
2583 * (__last_<na>_shared >= max_shared or
2584 * (__last_<na>_shared = max_shared - 1 and
2585 * the first max_shared - 1 iterators are equal and
2586 * iterator max_shared - 1 of the source is smaller) or
2588 * (__last_<na>_shared = info->n_shared and
2589 * the first n_shared iterators are equal and
2590 * iterator n_shared of the source is smaller))) }
2592 * That is, for those parts with __last_<na>_shared smaller than
2593 * max_n_shared[source_na], intersection with the set will introduce
2594 * __last_<na>_<i> parameters (assuming they don't have a known fixed value)
2595 * up until __last_<na>_shared and equate them to the corresponding iterators
2598 static __isl_give isl_set
*internal_shared_refinement(
2599 __isl_keep isl_id
*shared_id
, add_dep_info
*info
)
2604 isl_map
*shared_map
;
2609 source_na
= (na_pair
*) isl_id_get_user(shared_id
);
2611 mem
= info
->get_mem_dep(source_na
);
2612 domain
= isl_set_universe(isl_space_domain(isl_map_get_space(mem
)));
2613 domain
= add_parametrization(domain
, source_na
, info
);
2614 mem
= isl_map_intersect_domain(mem
, domain
);
2616 shared_map
= compute_shared_map(isl_map_get_space(mem
), shared_id
,
2617 info
->n_shared
, info
->max_n_shared
[source_na
]);
2619 mem
= isl_map_intersect(mem
, shared_map
);
2621 valid
= isl_map_range(mem
);
2622 invalid
= isl_set_universe(isl_set_get_space(valid
));
2623 shared_pos
= isl_set_find_dim_by_id(invalid
, isl_dim_param
, shared_id
);
2624 invalid
= isl_set_upper_bound_si(invalid
, isl_dim_param
, shared_pos
,
2625 info
->n_shared
- 1);
2627 return isl_set_union(valid
, invalid
);
2630 /* The last iteration of some source referred to by the sink may have been
2631 * added at a different nesting level. This means that __last_*_shared
2632 * is greater than or equal to a value greater than info->n_shared
2633 * and that therefore the iterators between info->n_shared and
2634 * __last_*_shared are not represented as they are implicitly
2635 * considered to be equal to the corresponding sink iterator.
2636 * For consistency, we need to explicitly add those iterators
2637 * and set them to be equal to the corresponding sink iterator.
2639 * For each of the __last_*_shared parameters, explicitly add
2640 * the implicitly equal __last_*_i iterators by intersecting
2641 * the sink with the set computed by internal_shared_refinement.
2643 static __isl_give isl_set
*refine_shared_internal(__isl_take isl_set
*sink
,
2647 isl_set
*refinement
;
2650 space
= isl_set_get_space(sink
);
2651 refinement
= isl_set_universe(isl_space_copy(space
));
2653 n_param
= isl_space_dim(space
, isl_dim_param
);
2654 for (int i
= 0; i
< n_param
; ++i
) {
2658 if (!is_shared(space
, i
))
2661 id
= isl_space_get_dim_id(space
, isl_dim_param
, i
);
2662 ref_i
= internal_shared_refinement(id
, info
);
2664 refinement
= isl_set_intersect(refinement
, ref_i
);
2666 isl_space_free(space
);
2668 sink
= isl_set_intersect(sink
, refinement
);
2673 /* Given a map from sinks to potential sources (sink2source),
2674 * check if any parametrization is needed.
2675 * Depending on the result, return either a universe restriction,
2676 * an empty restriction (if the sources cannot have executed),
2677 * a restriction that parametrizes the source and the sink
2678 * of the input of the computation of the last source
2679 * or a restriction that parametrizes the source of the output.
2681 * sink_map maps the domain of sink2source to the sink iteration domain.
2682 * source_map maps the range of sink2source to the source iteration domain.
2684 * Before we check if we need any parametrization, we update the number of
2685 * shared loop levels and add possibly missing __last_*_i iterators
2686 * (in refine_shared_internal). If parametrization turns out to be required,
2687 * we also update the minimal number of shared loop levels for the given
2690 static __isl_give isl_restriction
*compute_restriction_core(
2691 __isl_keep isl_map
*sink2source
,
2692 __isl_take isl_map
*sink_map
, __isl_take isl_map
*source_map
,
2693 __isl_keep isl_set
*sink
, na_pair
*source_na
, add_dep_info
*info
)
2696 isl_set
*source_restr
;
2697 isl_set
*sink_restr
;
2700 sink2source
= isl_map_copy(sink2source
);
2701 sink
= isl_set_copy(sink
);
2703 sink2source
= isl_map_apply_range(sink2source
,
2704 isl_map_copy(source_map
));
2705 sink2source
= isl_map_apply_domain(sink2source
,
2706 isl_map_copy(sink_map
));
2707 sink
= isl_set_apply(sink
, isl_map_copy(sink_map
));
2709 info
->n_shared
= extract_shared_levels(sink2source
, source_na
, info
);
2710 sink
= refine_shared_internal(sink
, info
);
2712 need
= need_parametrization(sink2source
, sink
, source_na
, info
);
2713 if (need
== RESTRICT_ERROR
||
2714 need
== RESTRICT_NO
|| need
== RESTRICT_EMPTY
) {
2715 isl_map_free(source_map
);
2716 isl_map_free(sink_map
);
2718 if (need
== RESTRICT_ERROR
) {
2719 isl_map_free(sink2source
);
2721 } else if (need
== RESTRICT_NO
)
2722 return isl_restriction_none(sink2source
);
2724 return isl_restriction_empty(sink2source
);
2727 info
->update_min_n_shared(source_na
);
2729 space
= isl_map_get_space(source_map
);
2730 source_restr
= isl_set_universe(isl_space_range(space
));
2732 source_restr
= add_parametrization(source_restr
, source_na
, info
);
2733 source_restr
= isl_set_apply(source_restr
, isl_map_reverse(source_map
));
2735 if (need
== RESTRICT_OUTPUT
) {
2736 isl_map_free(sink_map
);
2738 isl_map_free(sink2source
);
2739 return isl_restriction_output(source_restr
);
2742 sink_restr
= compute_sink_restriction(sink2source
, sink
,
2744 sink_restr
= isl_set_apply(sink_restr
, isl_map_reverse(sink_map
));
2747 isl_map_free(sink2source
);
2749 return isl_restriction_input(source_restr
, sink_restr
);
2752 /* Compute a restriction for the given map from sinks to potential sources
2755 * First check if the sink access has any filters. If so, compose the original
2756 * sink_map with a mapping that projects out these access filters.
2757 * Handle the source access similarly.
2758 * Then call compute_restriction_core to perform the main computation.
2760 static __isl_give isl_restriction
*compute_restriction(
2761 __isl_keep isl_map
*sink2source
,
2762 __isl_take isl_map
*sink_map
, __isl_take isl_map
*source_map
,
2763 __isl_keep isl_set
*sink
, na_pair
*source_na
, add_dep_info
*info
)
2765 na_pair
*sink_na
= info
->read_na_pair
;
2767 if (sink_na
->access
->nested
.size() > 0) {
2771 space
= isl_space_range(isl_map_get_space(sink_map
));
2772 space
= isl_space_unwrap(space
);
2773 map
= isl_map_domain_map(isl_map_universe(space
));
2775 sink_map
= isl_map_apply_range(sink_map
, map
);
2778 if (source_na
->access
->nested
.size() > 0) {
2782 space
= isl_space_range(isl_map_get_space(source_map
));
2783 space
= isl_space_unwrap(space
);
2784 map
= isl_map_domain_map(isl_map_universe(space
));
2786 source_map
= isl_map_apply_range(source_map
, map
);
2789 return compute_restriction_core(sink2source
, sink_map
, source_map
,
2790 sink
, source_na
, info
);
2793 /* Compute a restriction for the given map from sinks to potential sources
2794 * (sink2source). We simply call compute_restriction to compute the
2795 * restriction. Since, unlike the case of do_restrict_domain_map bewloe,
2796 * we didn't encode the entire access relation in the domains of the input
2797 * to isl_access_info_compute_flow, we pass identity mappings on the source
2798 * and sink to compute_restriction.
2800 static __isl_give isl_restriction
*do_restrict(__isl_keep isl_map
*sink2source
,
2801 __isl_keep isl_set
*sink
, void *source_user
, void *user
)
2803 na_pair
*source_na
= (na_pair
*) source_user
;
2804 add_dep_info
*info
= (struct add_dep_info
*) user
;
2806 isl_map
*source_map
;
2809 space
= isl_space_domain(isl_map_get_space(sink2source
));
2810 sink_map
= isl_map_identity(isl_space_map_from_set(space
));
2811 space
= isl_space_range(isl_map_get_space(sink2source
));
2812 source_map
= isl_map_identity(isl_space_map_from_set(space
));
2814 return compute_restriction(sink2source
, sink_map
, source_map
,
2815 sink
, source_na
, info
);
2818 /* Does the iteration domain of any of the writes involve any filters?
2820 static bool any_filters(vector
<na_pair
> &writers
)
2822 for (int i
= 0; i
< writers
.size(); ++i
)
2823 if (isl_set_is_wrapping(writers
[i
].node
->source
->set
))
2828 /* Does any of the dependences starting at "first" have
2829 * controlled dependence relation?
2831 static bool any_controlled_dependences(PDG
*pdg
, int first
)
2833 for (int i
= first
; i
< pdg
->dependences
.size(); ++i
)
2834 if (pdg
->dependences
[i
]->controlled_relation
)
2840 /* Remove parameters from "map" that start with "prefix".
2842 static __isl_give isl_map
*remove_source(__isl_take isl_map
*map
,
2845 int n
= isl_map_dim(map
, isl_dim_param
);
2846 size_t len
= strlen(prefix
);
2848 for (int i
= n
- 1; i
>= 0; --i
) {
2851 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
2852 if (strncmp(name
, prefix
, len
))
2855 map
= isl_map_project_out(map
, isl_dim_param
, i
, 1);
2858 map
= isl_map_coalesce(map
);
2863 /* Remove parameters from the dependences starting at "first"
2864 * that refer to any of the unused potential sources, i.e.,
2865 * those potential sources that are in writers, but not in info->used.
2867 * Since the current sink does not depend on those unused potential sources,
2868 * the corresponding dependence relations cannot depend on them and
2869 * any reference to them can simply be projected out.
2871 static void remove_unused_sources(PDG
*pdg
, int first
,
2872 vector
<na_pair
> &writers
, add_dep_info
*info
)
2875 std::vector
<na_pair
*> unused
;
2877 for (int i
= 0; i
< writers
.size(); ++i
) {
2878 if (info
->used
.find(&writers
[i
]) == info
->used
.end())
2879 unused
.push_back(&writers
[i
]);
2882 if (unused
.size() == 0)
2884 if (!any_controlled_dependences(pdg
, first
))
2887 for (int i
= 0; i
< unused
.size(); ++i
) {
2888 na_pair
*na
= unused
[i
];
2890 snprintf(name
, sizeof(name
), "__last_%s_%d_",
2891 na
->node
->name
->s
.c_str(), na
->access
->nr
);
2893 for (int j
= first
; j
< pdg
->dependences
.size(); ++j
) {
2894 pdg::dependence
*dep
= pdg
->dependences
[j
];
2897 if (!dep
->controlled_relation
)
2900 map
= dep
->controlled_relation
->map
;
2901 map
= remove_source(map
, name
);
2902 dep
->controlled_relation
->map
= map
;
2907 /* Look for the unique write access that writes to the array accessed
2908 * by "a" and return an na_pair consisting of the node in which the
2909 * access is performed and the access itself.
2911 static na_pair
find_unique_source(pdg::PDG
* pdg
, pdg::array
*a
)
2913 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
2914 pdg::node
*node
= pdg
->nodes
[i
];
2915 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
2916 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
2917 pdg::access
*access
= s
->accesses
[j
];
2918 if (access
->array
!= a
)
2920 if (access
->type
!= pdg::access::write
)
2922 return na_pair(node
, access
);
2929 /* Add a dependence from (source_node, source_access) to
2930 * (sink_node, sink_access) to pdg->dependences, for the
2931 * case where the array being accessed is marked uniquely_defined.
2933 * Since the array is marked uniquely_defined, the value based
2934 * dependence is equal to the memory based dependence, so we
2935 * simply need to compose the access relations to obtain
2936 * the dependence relation.
2937 * This dependence relation is then specialized with respect to
2938 * the context and the iteration domain of the sink.
2940 static void add_unique_dep(PDG
*pdg
, pdg::node
*source_node
,
2941 pdg::access
*source_access
, pdg::node
*sink_node
,
2942 pdg::access
*sink_access
)
2949 d
= new pdg::dependence
;
2950 d
->array
= source_access
->array
;
2951 d
->type
= pdg::dependence::flow
;
2952 d
->from
= source_node
;
2954 d
->from_access
= source_access
;
2955 d
->to_access
= sink_access
;
2957 dep
= source_access
->map
->get_isl_map();
2958 read
= sink_access
->map
->get_isl_map();
2959 dep
= isl_map_apply_range(dep
, isl_map_reverse(read
));
2960 dom
= sink_node
->source
->get_isl_set();
2961 if (isl_set_is_wrapping(dom
))
2962 dom
= isl_map_domain(isl_set_unwrap(dom
));
2963 dep
= isl_map_intersect_range(dep
, dom
);
2964 dep
= isl_map_intersect_params(dep
, pdg
->get_context_isl_set());
2965 d
->relation
= new pdg::IslMap(dep
);
2967 pdg
->dependences
.push_back(d
);
2970 /* Find the flow dependences associated to the array "a", which is marked
2971 * uniquely_defined, and add them to pdg->dependences.
2973 * First determine the unique source and then iterate through all the reads,
2974 * adding dependences from the unique source to each of the reads.
2976 static void find_unique_deps(PDG
*pdg
, pdg::array
*a
)
2978 na_pair na
= find_unique_source(pdg
, a
);
2980 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
2981 pdg::node
*node
= pdg
->nodes
[i
];
2982 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
2983 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
2984 pdg::access
*access
= s
->accesses
[j
];
2985 if (access
->array
!= a
)
2987 if (access
->type
!= pdg::access::read
)
2989 add_unique_dep(pdg
, na
.node
, na
.access
, node
, access
);
2994 /* Find the dependence of type "t" associated to array "a" and add them
2995 * to pdg->dependences.
2997 * If we are looking for flow dependences for an array that is marked
2998 * uniquely_defined, then we do not need to compute anything, but instead
2999 * can simply read off the dependences in find_unique_deps.
3001 void find_deps(PDG
* pdg
, pdg::array
*a
, type t
)
3003 isl_ctx
*ctx
= pdg
->get_isl_ctx();
3004 int nparam
= pdg
->params
.size();
3008 add_dep_info info
= { pdg
, a
, t
};
3010 bool need_parametrization
;
3014 info
.dtype
= pdg::dependence::flow
;
3018 info
.dtype
= pdg::dependence::anti
;
3021 info
.dtype
= pdg::dependence::reuse
;
3026 info
.dtype
= pdg::dependence::reuse_pair
;
3029 info
.dtype
= pdg::dependence::output
;
3033 a
->analysis_performed
.push_back(new pdg::dependence_type(info
.dtype
));
3035 if (t
== flow
&& a
->uniquely_defined
) {
3036 find_unique_deps(pdg
, a
);
3040 vector
<na_pair
> readers
;
3041 vector
<na_pair
> writers
;
3042 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
3043 pdg::node
*node
= pdg
->nodes
[i
];
3044 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
3045 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
3046 pdg::access
*access
= s
->accesses
[j
];
3047 if (access
->array
!= a
)
3053 if ((access
->type
== pdg::access::read
) ^ (t
== anti
))
3054 readers
.push_back(na_pair(node
, access
));
3056 writers
.push_back(na_pair(node
, access
));
3059 if (access
->type
== pdg::access::read
)
3062 readers
.push_back(na_pair(node
, access
));
3063 writers
.push_back(na_pair(node
, access
));
3069 int maxsize
= (selfinput
|| reuse
) ? writers
.size() + readers
.size()
3071 context
= pdg
->get_context_isl_set();
3072 info
.precedes_level
= (isl_access_level_before
)
3073 ((t
== reuse_pair
) ? precedes_level_accesses
3074 : precedes_level_nodes
);
3075 need_parametrization
= any_filters(writers
);
3076 for (int i
= 0; i
< writers
.size(); ++i
) {
3077 writers
[i
].map
= convert_access(&writers
[i
]);
3078 writers
[i
].project_out_access_filters();
3080 for (int i
= 0; i
< readers
.size(); ++i
) {
3081 readers
[i
].map
= convert_access(&readers
[i
]);
3082 readers
[i
].map
= isl_map_intersect_params(readers
[i
].map
,
3083 isl_set_copy(context
));
3084 readers
[i
].project_out_access_filters();
3086 for (int i
= 0; i
< readers
.size(); ++i
) {
3087 isl_access_info
*acc
;
3088 int n_dep
= pdg
->dependences
.size();
3090 acc
= isl_access_info_alloc(isl_map_copy(readers
[i
].map
),
3091 &readers
[i
], info
.precedes_level
, maxsize
);
3092 if (need_parametrization
)
3093 acc
= isl_access_info_set_restrict(acc
, &do_restrict
, &info
);
3094 for (int j
= 0; j
< writers
.size(); ++j
)
3095 acc
= isl_access_info_add_source(acc
,
3096 isl_map_copy(writers
[j
].map
), 1, &writers
[j
]);
3097 if (selfinput
&& writers
.size()) {
3098 pdg::node
*readnode
= readers
[i
].node
;
3099 for (int j
= 0; j
< readers
.size(); ++j
) {
3100 if (readers
[j
].node
== readnode
)
3101 acc
= isl_access_info_add_source(acc
,
3102 isl_map_copy(readers
[j
].map
), 1, &readers
[j
]);
3106 for (int j
= 0; j
< readers
.size(); ++j
)
3107 acc
= isl_access_info_add_source(acc
,
3108 isl_map_copy(readers
[j
].map
), 1, &readers
[j
]);
3110 info
.set_read_na(&readers
[i
]);
3111 isl_flow
*deps
= isl_access_info_compute_flow(acc
);
3112 isl_flow_foreach(deps
, add_dep
, &info
);
3114 no_source
= isl_flow_get_no_source(deps
, 1);
3115 no_source
= isl_map_from_range(isl_map_domain(no_source
));
3116 no_source
= simplify_controls(no_source
, &info
, NULL
);
3117 if (!isl_map_fast_is_empty(no_source
) && firstuse
) {
3118 pdg::dependence
*d
= new pdg::dependence
;
3120 d
->type
= pdg::dependence::uninitialized
;
3121 d
->to
= readers
[i
].node
;
3122 d
->to_access
= readers
[i
].access
;
3123 if (d
->to_access
->extension
) {
3124 d
->extended_relation
= new pdg::IslMap(isl_map_copy(no_source
));
3125 no_source
= isl_map_apply_range(no_source
,
3127 d
->to_access
->extension
->get_isl_map(ctx
)));
3129 d
->relation
= new pdg::IslMap(isl_map_copy(no_source
));
3130 pdg
->dependences
.push_back(d
);
3132 isl_map_free(no_source
);
3133 isl_flow_free(deps
);
3134 remove_unused_sources(pdg
, n_dep
, writers
, &info
);
3136 isl_set_free(context
);
3139 /* Add a dependence from "write" to "a" to a->sources.
3141 static void add_unique_source(pdg::access
*a
, pdg::access
*write
)
3146 dep
= isl_map_range_map(write
->map
->get_isl_map());
3147 read
= isl_map_range_map(a
->map
->get_isl_map());
3148 dep
= isl_map_apply_range(dep
, isl_map_reverse(read
));
3150 a
->sources
.push_back(new pdg::IslMap(dep
));
3153 /* Look for the unique write access that writes to the array accessed
3154 * by "a" and then add a dependence from that write to a->sources.
3156 static void add_unique_source(pdg::PDG
* pdg
, pdg::access
*a
)
3158 na_pair na
= find_unique_source(pdg
, a
->array
);
3159 add_unique_source(a
, na
.access
);
3163 static int add_source(__isl_take isl_map
*dep
, int must
, void *dep_user
,
3167 /* Add "dep" to a->sources, provided it is exact, and return 0.
3168 * Otherwise, return -1.
3170 static int add_source(__isl_take isl_map
*dep
, int must
, void *dep_user
,
3174 pdg::access
*a
= (pdg::access
*) user
;
3176 dep
= remove_redundant_controls(dep
, &has_controls
);
3182 a
->sources
.push_back(new pdg::IslMap(dep
));
3188 static __isl_give isl_restriction
*do_restrict_domain_map(
3189 __isl_keep isl_map
*source_map
, __isl_keep isl_set
*sink
,
3190 void *source_user
, void *user
);
3193 /* Compute a restriction for the given map from sinks to potential sources
3194 * (sink2source). We simply call compute_restriction to compute the
3195 * restriction. This function is used from within find_sources,
3196 * which encodes the entire access relation into the domains of
3197 * the access relations passed to isl_access_info_compute_flow.
3198 * That is, the access relations passed to isl_access_info_compute_flow
3199 * are the result of applying isl_map_range_map to the original access
3200 * relations. We therefore pass mappings that undo this encoding
3201 * to compute_restriction.
3203 static __isl_give isl_restriction
*do_restrict_domain_map(
3204 __isl_keep isl_map
*source_map
, __isl_keep isl_set
*sink
,
3205 void *source_user
, void *user
)
3207 na_pair
*source_na
= (na_pair
*) source_user
;
3208 add_dep_info
*info
= (struct add_dep_info
*) user
;
3210 isl_map
*source_domain_map
, *sink_domain_map
;
3212 space
= isl_space_range(isl_map_get_space(source_map
));
3213 space
= isl_space_unwrap(space
);
3214 source_domain_map
= isl_map_domain_map(isl_map_universe(space
));
3215 space
= isl_space_domain(isl_map_get_space(source_map
));
3216 space
= isl_space_unwrap(space
);
3217 sink_domain_map
= isl_map_domain_map(isl_map_universe(space
));
3219 return compute_restriction(source_map
, sink_domain_map
,
3220 source_domain_map
, sink
, source_na
, info
);
3223 /* Find the sources of (read) access "a" in node "node".
3224 * If they are complete (no uninitialized accesses) and exact,
3225 * then put them in a->sources. Otherwise, discard them.
3227 * If the array is marked uniquely_defined, then we simply look
3228 * for the defining write in find_unique_source.
3230 * Otherwise, we look for all writes that write to the same array,
3231 * perform dependence analysis and then check whether
3232 * the result is complete and exact.
3234 * The sources record not only the node iteration, but also
3235 * the index of the array element. We therefore apply
3236 * isl_map_range_map to the access relations, to obtain
3237 * a relation from the access (iteration -> element)
3238 * to the array element and feed that to the dependence analysis engine.
3240 void find_sources(pdg::PDG
* pdg
, pdg::node
*node
, pdg::access
*a
)
3244 isl_access_info
*acc
;
3246 vector
<na_pair
> writers
;
3247 na_pair
reader(node
, a
);
3248 add_dep_info info
= { pdg
, a
->array
, flow
, pdg::dependence::flow
};
3250 if (a
->array
->uniquely_defined
) {
3251 add_unique_source(pdg
, a
);
3255 info
.precedes_level
= (isl_access_level_before
) precedes_level_nodes
;
3257 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
3258 pdg::node
*node
= pdg
->nodes
[i
];
3259 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
3260 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
3261 pdg::access
*access
= s
->accesses
[j
];
3262 if (access
->array
!= a
->array
)
3264 if (access
->type
!= pdg::access::write
)
3266 writers
.push_back(na_pair(node
, access
));
3270 context
= pdg
->get_context_isl_set();
3271 for (int i
= 0; i
< writers
.size(); ++i
) {
3272 writers
[i
].projected_map
= convert_access(&writers
[i
]);
3273 writers
[i
].map
= isl_map_copy(writers
[i
].projected_map
);
3274 writers
[i
].map
= isl_map_range_map(writers
[i
].map
);
3275 writers
[i
].project_out_access_filters();
3277 reader
.projected_map
= convert_access(&reader
);
3278 reader
.projected_map
= isl_map_intersect_params(reader
.projected_map
,
3280 reader
.map
= isl_map_range_map(isl_map_copy(reader
.projected_map
));
3281 reader
.project_out_access_filters();
3283 acc
= isl_access_info_alloc(isl_map_copy(reader
.map
),
3284 &reader
, info
.precedes_level
, writers
.size());
3285 for (int j
= 0; j
< writers
.size(); ++j
)
3286 acc
= isl_access_info_add_source(acc
,
3287 isl_map_copy(writers
[j
].map
), 1, &writers
[j
]);
3289 if (any_filters(writers
))
3290 acc
= isl_access_info_set_restrict(acc
,
3291 &do_restrict_domain_map
, &info
);
3293 info
.set_read_na(&reader
);
3294 deps
= isl_access_info_compute_flow(acc
);
3295 no_source
= isl_flow_get_no_source(deps
, 1);
3296 if (isl_map_plain_is_empty(no_source
)) {
3297 if (isl_flow_foreach(deps
, add_source
, a
) < 0) {
3298 for (int i
= 0; i
< a
->sources
.size(); ++i
)
3299 delete a
->sources
[i
];
3300 a
->sources
.resize(0);
3303 isl_map_free(no_source
);
3304 isl_flow_free(deps
);
3307 /* Find the source (if possible) of the filter "coa" in node "node".
3308 * We assume that the filter is an access rather than a function call.
3310 static void find_sources(pdg::PDG
*pdg
, pdg::node
*node
,
3311 pdg::call_or_access
*coa
)
3313 pdg::access
*access
;
3315 assert(coa
->type
== pdg::call_or_access::t_access
);
3316 access
= coa
->access
;
3318 find_sources(pdg
, node
, access
);
3321 /* Compute the sources (if possible) for all the filters in all the
3322 * nodes and accesses in "pdg".
3324 void compute_filter_sources(pdg::PDG
*pdg
)
3326 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
3327 pdg::node
*node
= pdg
->nodes
[i
];
3328 pdg::statement
*s
= pdg
->nodes
[i
]->statement
;
3329 int n_filter
= node
->filters
.size();
3331 for (int j
= 0; j
< n_filter
; ++j
)
3332 find_sources(pdg
, node
, node
->filters
[j
]);
3334 for (int j
= 0; j
< s
->accesses
.size(); ++j
) {
3335 pdg::access
*access
= s
->accesses
[j
];
3337 for (int k
= 0; k
< access
->nested
.size(); ++k
)
3338 find_sources(pdg
, node
, access
->nested
[k
]);
3343 static int precedes_level_nodes(na_pair
*first
, na_pair
*second
)
3347 for (int i
= 0; i
< first
->node
->prefix
.size(); ++i
) {
3348 if (i
>= second
->node
->prefix
.size())
3350 cmp
= first
->node
->prefix
[i
] - second
->node
->prefix
[i
];
3353 if (first
->node
->prefix
[i
] == -1)
3356 return 2*d
+ (cmp
<0);
3359 static int precedes_level_accesses(na_pair
*first
, na_pair
*second
)
3363 for (int i
= 0; i
< first
->node
->prefix
.size(); ++i
) {
3364 if (i
>= second
->node
->prefix
.size())
3366 cmp
= first
->node
->prefix
[i
] - second
->node
->prefix
[i
];
3369 if (first
->node
->prefix
[i
] == -1)
3372 /* same node; now compare accesses */
3374 cmp
= first
->access
->nr
- second
->access
->nr
;
3375 return 2*d
+ (cmp
<0);