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