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