10 #include <isl/union_map.h>
11 #include <isl/polynomial.h>
21 #include "translation.h"
22 #include "pn_options.h"
31 /* Check whether node is a propagation node
33 * A propagation node simply copies a value from one array to another array.
34 * In principle, a copy node could also copy a value to the same array,
35 * but then we would have to be careful that the node does not recursively
37 * Note that the check is incomplete. If a node performs some additional
38 * operations involving only iterators, then this information is not stored
39 * so we may incorrectly conclude that the node is a copy node.
41 static bool propagation_node(pdg::node
*node
)
43 pdg::statement
*s
= node
->statement
;
44 if (s
->accesses
.size() != 2)
46 if (s
->accesses
[0]->type
!= pdg::access::read
)
48 if (s
->accesses
[1]->type
!= pdg::access::write
)
50 if (s
->accesses
[0]->array
== s
->accesses
[1]->array
)
52 if (s
->accesses
[1]->array
->dims
.size() != 0)
54 if (s
->top_function
&& s
->top_function
->name
&&
55 strcmp(s
->top_function
->name
->s
.c_str(), ""))
60 static pdg::IslMap
*join_input(PDG
*pdg
, pdg::IslMap
*left
,
64 isl_ctx
*ctx
= pdg
->get_isl_ctx();
65 isl_map
*rel
= left
->get_isl_map(ctx
);
66 isl_map
*acc
= right
->get_isl_map(ctx
);
68 acc
= isl_map_apply_domain(acc
, rel
);
70 res
= new pdg::IslMap(acc
);
75 /* Given a dependence relation um_rel that maps iterations from
76 * a propagation node to the current node and an access relation
77 * from the current node, drop those iterations from the domain
78 * of the access relation that have been propagated, i.e.,
79 * that are in the range of the dependence relation.
81 * The original access relation is destroyed and a new one
82 * is returned, provided the new access relation is not empty.
83 * If it is empty, then a NULL pointer is returned.
85 * Note that the input access relation may not have been specialized
86 * to the domain of the node, i.e., the access relation may have
87 * a universe domain. In that case, the new relation is unlikely
88 * to be empty, but it may end up having a domain that is disjoint
89 * from the domain of the node.
91 static pdg::IslMap
*remove_propagated_from_domain(PDG
*pdg
,
92 pdg::IslMap
*um_rel
, pdg::IslMap
*um_acc
)
94 pdg::IslMap
*res
= NULL
;
95 isl_ctx
*ctx
= pdg
->get_isl_ctx();
96 isl_map
*rel
= um_rel
->get_isl_map(ctx
);
97 isl_map
*acc
= um_acc
->get_isl_map(ctx
);
99 isl_set
*rel_ran
= isl_map_range(rel
);
100 isl_set
*acc_dom
= isl_map_domain(isl_map_copy(acc
));
102 acc_dom
= isl_set_subtract(acc_dom
, rel_ran
);
103 acc
= isl_map_intersect_domain(acc
, acc_dom
);
107 if (isl_map_is_empty(acc
))
110 res
= new pdg::IslMap(acc
);
115 /* Recursively replace old_access inside call by new_access.
117 static void replace_access(pdg::function_call
*call
, pdg::access
*old_access
,
118 pdg::call_or_access
*new_coa
)
120 for (int i
= 0; i
< call
->arguments
.size(); ++i
) {
121 pdg::call_or_access
*coa
= call
->arguments
[i
];
122 if (coa
->type
== pdg::call_or_access::t_call
)
123 replace_access(coa
->call
, old_access
, new_coa
);
124 if (coa
->type
== pdg::call_or_access::t_access
&&
125 coa
->access
== old_access
) {
132 /* Replace old_access inside s by new_access.
133 * If empty is not set, then new_access only replaces part of
134 * old_access. This means that old_access is kept in the list
135 * of accesses and that in the parse tree of the statement,
136 * old_access is replaced by a new virtual function call
137 * with old_access and new_access as arguments.
139 static void replace_access(pdg::statement
*s
, pdg::access
*old_access
,
140 pdg::access
*new_access
, bool empty
)
142 pdg::call_or_access coa
;
145 s
->accesses
.erase(old_access
);
146 s
->accesses
.push_back(new_access
);
148 if (!s
->top_function
)
152 coa
.type
= pdg::call_or_access::t_access
;
153 coa
.access
= new_access
;
155 pdg::call_or_access
*old_coa
, *new_coa
;
156 coa
.type
= pdg::call_or_access::t_call
;
157 coa
.call
= new pdg::function_call
;
158 coa
.call
->name
= new str(string("#PHI"));
159 old_coa
= new pdg::call_or_access
;
160 old_coa
->type
= pdg::call_or_access::t_access
;
161 old_coa
->access
= old_access
;
162 coa
.call
->arguments
.push_back(old_coa
);
163 new_coa
= new pdg::call_or_access
;
164 new_coa
->type
= pdg::call_or_access::t_access
;
165 new_coa
->access
= new_access
;
166 coa
.call
->arguments
.push_back(new_coa
);
168 replace_access(s
->top_function
, old_access
, &coa
);
171 static void clear_dependences(PDG
*pdg
)
173 for (int j
= 0; j
< pdg
->dependences
.size(); ++j
) {
174 pdg::dependence
*dep
= pdg
->dependences
[j
];
175 delete dep
->controlled_relation
;
176 delete dep
->relation
;
179 pdg
->dependences
.resize(0);
182 /* Check if there is any node that simply copies the value from an array
183 * to a scalar. If so, perform dependence analysis on the scalar
184 * and replaces read access to the scalar that depend on writes from
185 * a propagation node to reads from the propagated array.
186 * In particular, the propagated iterations are removed from the access
187 * relation and replaced by an access to the propagated array.
188 * Finally, the propagation node is removed.
190 static void copy_propagation(PDG
* pdg
)
192 std::set
<pdg::node
*> to_remove_n
;
193 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
194 pdg::node
*node
= pdg
->nodes
[i
];
195 pdg::statement
*s
= node
->statement
;
196 if (!propagation_node(node
))
198 pdg::array
*a
= s
->accesses
[1]->array
;
199 find_deps(pdg
, a
, flow
);
200 std::set
<pdg::access
*> to_remove
;
201 for (int j
= 0; j
< pdg
->dependences
.size(); ++j
) {
202 pdg::dependence
*dep
= pdg
->dependences
[j
];
203 if (dep
->controlled_relation
)
205 assert(dep
->type
== pdg::dependence::flow
);
206 assert(dep
->from
!= dep
->to
);
207 if (!propagation_node(dep
->from
))
209 to_remove_n
.insert(dep
->from
);
210 pdg::IslMap
*access_map
= dep
->from
->statement
->accesses
[0]->map
;
211 pdg::IslMap
*prop_access
= join_input(pdg
, dep
->relation
, access_map
);
212 access_map
= dep
->to_access
->map
;
213 access_map
= remove_propagated_from_domain(pdg
, dep
->relation
,
215 dep
->to_access
->map
= access_map
;
216 bool empty
= !access_map
;
217 pdg::access
*access
= new pdg::access
;
218 access
->nr
= dep
->to_access
->nr
;
219 access
->array
= dep
->from
->statement
->accesses
[0]->array
;
220 access
->type
= pdg::access::read
;
221 access
->map
= prop_access
;
222 replace_access(dep
->to
->statement
, dep
->to_access
, access
, empty
);
224 to_remove
.insert(dep
->to_access
);
226 std::set
<pdg::access
*>::iterator it
;
227 for (it
= to_remove
.begin(); it
!= to_remove
.end(); ++it
) {
232 clear_dependences(pdg
);
234 if (to_remove_n
.size() == 0)
236 std::set
<pdg::node
*>::iterator itn
;
237 for (itn
= to_remove_n
.begin(); itn
!= to_remove_n
.end(); ++itn
) {
238 (*itn
)->statement
->accesses
[0]->array
= NULL
;
239 (*itn
)->statement
->accesses
[1]->array
= NULL
;
242 pdg
->nodes
.erase(*itn
);
244 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
)
245 pdg
->nodes
[i
]->nr
= i
;
248 /* Check whether dep writes and reads from consecutive iterations of
250 * We check this property by testing whether any other read for the
251 * same access occurs in between.
253 bool is_consecutive_dep(PDG
*pdg
, pdg::dependence
*dep
, isl_map
*map
)
255 isl_ctx
*ctx
= pdg
->get_isl_ctx();
256 assert(dep
->to
== dep
->from
);
257 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
258 pdg::dependence
*other_dep
= pdg
->dependences
[i
];
259 if (other_dep
== dep
)
261 if (other_dep
->to
!= dep
->to
)
263 if (other_dep
->to_access
!= dep
->to_access
)
265 isl_map
*other_map
= other_dep
->relation
->get_isl_map(ctx
);
266 bool consec
= isl_is_consecutive_dep(map
, other_map
);
267 isl_map_free(other_map
);
274 /* An auxiliary class that keeps a reference to an isl_map
275 * and frees it when it goes out of scope.
279 temp_map(isl_map
*m
) : map(m
) {}
280 operator isl_map
*() const { return map
; }
286 /* Set *user to qp of the first call, assuming *user was initialized to NULL.
287 * If this function is called more than once, then return isl_stat_error.
289 static isl_stat
extract_single(__isl_take isl_set
*set
,
290 __isl_take isl_qpolynomial
*qp
, void *user
)
292 isl_qpolynomial
**res
= (isl_qpolynomial
**) user
;
297 isl_qpolynomial_free(qp
);
298 return isl_stat_error
;
305 /* Check if we can use a shift register for the self-dependence dep
307 * If yes, return the required size of the shift register.
308 * If no, return NULL.
310 * We assume that the register is shifted on every iteration of D.
311 * If the number of shifts between any pair of writes and reads is
312 * constant, then we can use a shift register.
313 * Note that the size of the shift register may be larger than
314 * that of the FIFO, since there may be iterations of the domain
315 * between corresponding writes and reads where nothing is written
316 * to or read from the shift register.
318 * If "ref" is a wrapped map, then the iteration domain
319 * is in the domain of that map.
321 static size::enumerator
*shift_register_size(pdg::PDG
*pdg
,
322 __isl_take isl_set
*ref
, __isl_take isl_map
*dep
)
326 isl_map
*read_after_ref
;
327 isl_map
*write_before_ref
;
328 isl_map
*ref_between
;
329 isl_pw_qpolynomial
*pwqp
;
334 if (isl_set_is_wrapping(ref
))
335 ref
= isl_map_domain(isl_set_unwrap(ref
));
337 dim
= isl_set_dim(ref
, isl_dim_set
);
338 dep
= isl_map_move_dims(dep
, isl_dim_in
, dim
, isl_dim_out
, 0, dim
);
339 dep_set
= isl_map_domain(dep
);
341 read_after_ref
= isl_map_lex_ge(isl_set_get_space(ref
));
342 read_after_ref
= isl_map_insert_dims(read_after_ref
, isl_dim_in
, 0, dim
);
343 write_before_ref
= isl_map_lex_lt(isl_set_get_space(ref
));
344 write_before_ref
= isl_map_add_dims(write_before_ref
, isl_dim_in
, dim
);
345 ref_between
= isl_map_intersect(read_after_ref
, write_before_ref
);
347 ref_between
= isl_map_intersect_range(ref_between
, ref
);
348 ref_between
= isl_map_intersect_domain(ref_between
,
349 isl_set_copy(dep_set
));
351 pwqp
= isl_map_card(ref_between
);
353 pwqp
= isl_pw_qpolynomial_gist(pwqp
, dep_set
);
355 pwqp
= isl_pw_qpolynomial_coalesce(pwqp
);
358 if (isl_pw_qpolynomial_foreach_piece(pwqp
, &extract_single
, &qp
) < 0 ||
360 isl_qpolynomial_involves_dims(qp
, isl_dim_in
, 0, dim
+ dim
)) {
361 isl_qpolynomial_free(qp
);
362 isl_pw_qpolynomial_free(pwqp
);
365 isl_pw_qpolynomial_free(pwqp
);
367 qp
= isl_qpolynomial_project_domain_on_params(qp
);
368 universe
= isl_set_universe(isl_qpolynomial_get_domain_space(qp
));
369 pwqp
= isl_pw_qpolynomial_alloc(universe
, qp
);
371 return new size::enumerator(pwqp
, pdg
);
374 /* isl_access_level_before function used in a context where there
375 * is a single iteration domain. The order is given by the order
376 * of the accesses passed through first and second.
377 * If the first access precedes the second, we return 2 * d + 1,
378 * where d is the dimension of the iteration domain, and otherwise 2 * d.
380 static int precedes_access(void *first
, void *second
)
382 pdg::access
*access1
= (pdg::access
*) first
;
383 pdg::access
*access2
= (pdg::access
*) second
;
384 int d
= isl_map_dim(access1
->map
->map
, isl_dim_in
);
386 return 2 * d
+ (access1
->nr
< access2
->nr
);
389 /* Return true if all input dimensions are constrained to be equal to the
390 * corresponding output dimensions.
392 static bool is_identity_map(__isl_keep isl_map
*map
)
395 isl_space
*space
= isl_map_get_space(map
);
396 isl_map
*id
= isl_map_identity(space
);
398 is_id
= isl_map_is_subset(map
, id
);
405 /* Set buf (of size buf_len) to the prefix of control variables
406 * that correspond to the from and to access of the given "dep"
407 * and return the length of the prefix.
409 static size_t set_local_control_name(char *buf
, size_t buf_len
,
410 pdg::dependence
*dep
)
412 snprintf(buf
, buf_len
, "__last_%s_%d_%s_%d",
413 dep
->from
->name
->s
.c_str(), dep
->from_access
->nr
,
414 dep
->to
->name
->s
.c_str(), dep
->to_access
->nr
);
418 /* Given the name of a binding variable, reset the part that refers
419 * to the sink access by "nr".
421 * The original name is of the form
423 * __last_ND_<source node>_<source access>_ND_<sink node>_<sink access>_*
425 * We simply replace the <sink access> by <nr>.
427 static str
*replace_to_access(isl_ctx
*ctx
, str
*id
, int nr
)
436 name
= id
->s
.c_str();
438 suffix
= strrchr(name
, '_');
440 infix
= (const char *) memrchr(name
, '_', suffix
- name
);
442 len
= infix
+ 1 - name
+ strlen(suffix
) + 20;
443 replaced
= isl_alloc_array(ctx
, char, len
);
445 len
= infix
+ 1 - name
;
446 memcpy(replaced
, name
, len
);
447 snprintf(replaced
+ len
, 20, "%d", nr
);
448 len
+= strlen(replaced
+ len
);
449 strcpy(replaced
+ len
, suffix
);
451 s
= new str(replaced
);
457 /* For each element of controls, replace the part of the name that
458 * refers to the sink access by "nr" and collect the results in
461 static void replace_to_access(isl_ctx
*ctx
, seq
<str
> &renamed_controls
,
462 seq
<str
> &controls
, int nr
)
464 for (int i
= 0; i
< controls
.size(); ++i
)
465 renamed_controls
.push_back(replace_to_access(ctx
,
469 /* Is the i-th parameter of "map" of the form __last_*
470 * but not of the form local_control*?
472 static bool is_foreign_control(__isl_keep isl_map
*map
, int i
,
473 const char *local_control
, size_t len
)
476 const char *prefix
= "__last_";
477 size_t prefix_len
= strlen(prefix
);
479 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
481 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
482 if (strncmp(name
, prefix
, prefix_len
))
484 return strncmp(name
, local_control
, len
) != 0;
487 /* Remove from "dep" all those parameters that are of the form __last_*
488 * but not of the form local_control* and return the result.
490 static __isl_give isl_map
*remove_foreign_controls(__isl_take isl_map
*dep
,
491 const char *local_control
, size_t len
)
495 n_param
= isl_map_dim(dep
, isl_dim_param
);
496 for (int i
= n_param
- 1; i
>= 0; --i
) {
497 if (!is_foreign_control(dep
, i
, local_control
, len
))
499 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
501 dep
= isl_map_coalesce(dep
);
506 /* Is the i-th parameter of "map" a control, i.e., a parameter
507 * introduced by convert_writer()?
508 * In particular, is the parameter of the form __last_*?
510 static bool is_control(__isl_keep isl_map
*map
, int i
)
513 const char *prefix
= "__last_";
514 size_t prefix_len
= strlen(prefix
);
516 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
518 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
519 return strncmp(name
, prefix
, prefix_len
) == 0;
522 /* Remove all parameters that were introduced by convert_writer().
524 static __isl_give isl_map
*remove_all_controls(__isl_take isl_map
*dep
)
528 n_param
= isl_map_dim(dep
, isl_dim_param
);
529 for (int i
= n_param
- 1; i
>= 0; --i
) {
530 if (!is_control(dep
, i
))
532 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
534 dep
= isl_map_coalesce(dep
);
539 struct add_reuse_data
{
541 pdg::dependence
*dep
;
545 static isl_stat
add_reuse(__isl_take isl_map
*dep_rel
, int must
,
546 void *dep_user
, void *user
);
549 /* Add a reuse dependence with dependence relation "dep_rel" to
550 * data->pdg->dependences.
551 * data->dep corresponds to the original dependence that is reusing
552 * some value that was previously used by "propagate_access", from
554 * Since "dep_rel" was obtained from a relation with local
555 * control variables, we need to remove them to obtain the
556 * dependence relation on the reuse dependence.
558 * If we are reusing control variables, then we need to rename
559 * the from_control to refer to the access where we are reusing
560 * the control variables from.
562 * If the dependence relations maps iterations to themselves, then
563 * we mark the new reuse dependence as a wire.
565 static isl_stat
add_reuse(__isl_take isl_map
*dep_rel
, int must
, void *dep_user
,
568 pdg::access
*propagate_access
= (pdg::access
*) dep_user
;
569 add_reuse_data
*data
= (add_reuse_data
*) user
;
570 pdg::dependence
*reuse_dep
;
571 isl_ctx
*ctx
= isl_map_get_ctx(dep_rel
);
573 reuse_dep
= new pdg::dependence
;
574 reuse_dep
->array
= data
->dep
->array
;
575 replace_to_access(ctx
, reuse_dep
->from_controls
,
576 data
->dep
->from_controls
, propagate_access
->nr
);
577 reuse_dep
->to_controls
= data
->dep
->to_controls
;
578 reuse_dep
->from
= data
->dep
->to
;
579 reuse_dep
->to
= data
->dep
->to
;
580 reuse_dep
->from_access
= propagate_access
;
581 reuse_dep
->to_access
= data
->dep
->to_access
;
582 if (reuse_dep
->from
== reuse_dep
->to
&& is_identity_map(dep_rel
))
583 reuse_dep
->type
= pdg::dependence::pn_wire
;
585 reuse_dep
->type
= data
->dep
->type
;
586 if (data
->dep
->controlled_relation
) {
587 pdg::IslMap
*cr
= data
->dep
->controlled_relation
;
588 isl_set
*dom
= isl_map_range(cr
->get_isl_map());
589 isl_map
*control_rel
= isl_map_copy(dep_rel
);
590 control_rel
= isl_map_intersect_range(control_rel
, dom
);
591 reuse_dep
->controlled_relation
= new pdg::IslMap(control_rel
);
593 dep_rel
= remove_all_controls(dep_rel
);
594 reuse_dep
->relation
= new pdg::IslMap(dep_rel
);
595 data
->pdg
->dependences
.push_back(reuse_dep
);
600 /* Detect reuse among the dependences in "deps", adding split off
601 * dependences to pdg->dependences.
602 * Each of the dependences in "deps" originates from the same
603 * write access and ends in the same node.
605 * We look for values, i.e., iterations of the write access,
606 * that are used several times. To do so, we perform dependence
607 * analysis on the inverted dependence relations. That is,
608 * we use these inverted dependence relations as "access relations",
609 * accessing iterations of the write access.
610 * We consider each dependence in turn as a "read", each time taking
611 * all dependences as writes.
612 * In the result of such a dependence analysis, the "uninitialized reads"
613 * correspond to the first use of a result from the original write access,
614 * while all the "dependences" corespond to a propagation of a value
615 * from one original read access to another original read access.
617 * If the dependence has a controlled_relation, then we use this
618 * controlled_relation as the "access relation" after removing all
619 * the foreign controls. This ensures that we only reuse data if
620 * the last iteration hasn't changed.
621 * After restricting the range of the controlled_relation based on
622 * the "uninitialized reads", we recompute the uncontrolled relation
625 * If there is only one dependence in "deps" and if that dependence
626 * is single-valued, then obviously there can be no reuse, so we skip
629 * We currently assume that none of the accesses has an extended_relation.
631 static void detect_reuse(PDG
*pdg
, std::vector
<pdg::dependence
*> &deps
)
633 add_reuse_data data
= { pdg
};
637 if (deps
.size() == 1 &&
638 isl_map_is_single_valued(deps
[0]->relation
->map
))
641 for (int i
= 0; i
< deps
.size(); ++i
) {
648 assert(!deps
[i
]->extended_relation
);
650 if (deps
[i
]->controlled_relation
) {
651 local
= deps
[i
]->controlled_relation
->get_isl_map();
652 len
= set_local_control_name(buf
, sizeof(buf
), deps
[i
]);
653 local
= remove_foreign_controls(local
, buf
, len
);
655 local
= deps
[i
]->relation
->get_isl_map();
656 local
= isl_map_reverse(local
);
659 ai
= isl_access_info_alloc(isl_map_copy(local
),
660 deps
[i
]->to_access
, &precedes_access
, deps
.size());
661 for (int j
= 0; j
< deps
.size(); ++j
) {
664 map
= isl_map_copy(local
);
666 map
= deps
[j
]->relation
->get_isl_map();
667 map
= isl_map_reverse(map
);
669 ai
= isl_access_info_add_source(ai
, map
,
670 1, deps
[j
]->to_access
);
672 flow
= isl_access_info_compute_flow(ai
);
673 isl_flow_foreach(flow
, &add_reuse
, &data
);
674 first
= isl_map_domain(isl_flow_get_no_source(flow
, 1));
677 rel
= deps
[i
]->relation
;
678 if (deps
[i
]->controlled_relation
) {
679 pdg::IslMap
*cr
= deps
[i
]->controlled_relation
;
680 cr
->map
= isl_map_intersect_range(cr
->map
, first
);
681 isl_map_free(rel
->map
);
682 rel
->map
= remove_all_controls(isl_map_copy(cr
->map
));
684 rel
->map
= isl_map_intersect_range(rel
->map
, first
);
690 /* Has this dependence been created during the detection
691 * of multiple assignments? In particular, does this dependence
692 * propagate the values in the source.
694 static bool is_multi_assignment_propagation(pdg::dependence
*dep
)
696 return dep
->to_access
== dep
->from_access
&&
697 dep
->to_access
->type
== pdg::access::write
;
700 typedef std::pair
<pdg::access
*, pdg::node
*> an_pair
;
701 typedef std::pair
<int, an_pair
> nan_triple
;
703 struct nan_triple_cmp
{
704 bool operator()(nan_triple t1
, nan_triple t2
) const {
705 if (t1
.first
!= t2
.first
)
706 return t1
.first
< t2
.first
;
707 if (t1
.second
.first
->nr
!= t2
.second
.first
->nr
)
708 return t1
.second
.first
->nr
< t2
.second
.first
->nr
;
709 return t1
.second
.second
->nr
< t2
.second
.second
->nr
;
713 typedef std::map
<nan_triple
, std::vector
<pdg::dependence
*>, nan_triple_cmp
>
716 /* Detect reuse of the same value (originating from the same
717 * write access) within a node and split the corresponding dependence
718 * into part of the original dependences that use the value for
719 * the first time and internal dependences that propagate the value.
721 * If a scheduling is applied that changes the order of the iterations
722 * within a given node, then this scheduling should be performed
723 * before the reuse detection.
725 * We first collect the dependences that originate in a given access
726 * and end up in a given node and then process each such collection
727 * in turn, in an order that does not depend on pointer values.
728 * While collecting dependences, we skip those that correspond
729 * to the propagation of multiple assignments to the next potential
732 * Dependences that propagate data (those that have a dep->array)
733 * are treated separately from those that propagate control.
735 * If the user has turned off reuse detection, then we do nothing.
737 static void detect_reuse(PDG
*pdg
, struct pn_options
*options
)
739 nan2deps access_deps
;
740 nan2deps control_deps
;
741 nan2deps::iterator it
;
746 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
747 pdg::dependence
*dep
= pdg
->dependences
[i
];
748 if (dep
->type
== pdg::dependence::uninitialized
)
750 if (is_multi_assignment_propagation(dep
))
752 an_pair
p(dep
->from_access
, dep
->to
);
753 nan_triple
t(dep
->from
->nr
, p
);
755 access_deps
[t
].push_back(dep
);
757 control_deps
[t
].push_back(dep
);
760 for (it
= access_deps
.begin(); it
!= access_deps
.end(); ++it
)
761 detect_reuse(pdg
, it
->second
);
762 for (it
= control_deps
.begin(); it
!= control_deps
.end(); ++it
)
763 detect_reuse(pdg
, it
->second
);
766 /* isl_access_level_before function used in a context where the
767 * iteration domains live in a common space. We therefore just
768 * need to retun 2 * the dimension of this space, which is stored
769 * in *first (and *second).
771 static int common_space(void *first
, void *second
)
773 int depth
= *(int *) first
;
777 /* Assign dep to *user. This function is expected to be called
780 static isl_stat
extract_dep(__isl_take isl_map
*dep
, int must
,
781 void *dep_user
, void *user
)
783 isl_map
**map_p
= (isl_map
**) user
;
790 /* Is the i-th parameter of "set" of the form __last_*
791 * but not of the form local_control*?
793 static bool is_foreign_control(__isl_keep isl_set
*set
, int i
,
794 const char *local_control
, size_t len
)
797 const char *prefix
= "__last_";
798 size_t prefix_len
= strlen(prefix
);
800 if (!isl_set_has_dim_id(set
, isl_dim_param
, i
))
802 name
= isl_set_get_dim_name(set
, isl_dim_param
, i
);
803 if (strncmp(name
, prefix
, prefix_len
))
805 return strncmp(name
, local_control
, len
) != 0;
808 /* Does "set" have any parameters of the form __last_*
809 * that are not of the form local_control*?
811 static __isl_give isl_set
*remove_foreign_controls(__isl_take isl_set
*set
,
812 const char *local_control
, size_t len
)
816 n_param
= isl_set_dim(set
, isl_dim_param
);
817 for (int i
= n_param
- 1; i
>= 0; --i
) {
818 if (!is_foreign_control(set
, i
, local_control
, len
))
820 set
= isl_set_project_out(set
, isl_dim_param
, i
, 1);
822 set
= isl_set_coalesce(set
);
827 /* Given a dependence such that the dependence relation
828 * is not injective, split the dependence into two parts,
829 * one that propagates the value from a potential source iteration
830 * to the next potential source iteration and one that sends
831 * the data from the final potential source iteration to the sink
834 * The dependence may either be a control dependence, propagating
835 * control variables, or a data dependence, in which case it has
836 * a controlled_relation and it is the uncontrolled relation that
839 * To obtain the last potential source iteration, we simply
840 * compute the lexicographic maximum of all potential source iterations.
842 * To obtain the dependence from one potential source iteration
843 * to the next potential source iteration, we apply
844 * dependence analysis on the dependence relation.
845 * In particular, we need a mapping from source iterations to
846 * the next source iteration associated to the same sink iteration,
847 * so we simply treat the original dependence relation as an access relation.
849 * The mapping to the next potential source should not have any controls.
850 * If the input dependence is a control dependence, then it is propagating
851 * control variables itself. If it is a data dependence, then we want
852 * to propagate values to the next potential source independently of
855 * The constraints on the controls for the dependence from the final
856 * potential source iteration should be the same as those on the
857 * original relation, when seen from the destination node.
859 * We currently assume that there is no extended relation associated
862 static void split_multi_assignment(PDG
*pdg
, pdg::dependence
*dep
)
866 isl_map
*next
= NULL
;
870 pdg::dependence
*next_dep
;
874 assert(!dep
->extended_relation
);
876 len
= set_local_control_name(buf
, sizeof(buf
), dep
);
878 depth
= isl_map_dim(dep
->relation
->map
, isl_dim_in
);
879 ai
= isl_access_info_alloc(isl_map_copy(dep
->relation
->map
),
880 &depth
, &common_space
, 1);
881 ai
= isl_access_info_add_source(ai
, isl_map_copy(dep
->relation
->map
),
883 flow
= isl_access_info_compute_flow(ai
);
884 isl_flow_foreach(flow
, &extract_dep
, &next
);
887 last
= isl_map_copy(dep
->relation
->map
);
888 last
= isl_map_reverse(isl_map_lexmax(isl_map_reverse(last
)));
890 next_dep
= new pdg::dependence
;
891 next_dep
->array
= dep
->array
;
892 next_dep
->from_controls
= dep
->from_controls
;
893 next_dep
->to_controls
= dep
->to_controls
;
894 next_dep
->type
= dep
->type
;
895 next_dep
->from
= dep
->from
;
896 next_dep
->to
= dep
->from
;
897 next_dep
->from_access
= dep
->from_access
;
898 next_dep
->to_access
= dep
->from_access
;
899 next_dep
->relation
= new pdg::IslMap(next
);
900 pdg
->dependences
.push_back(next_dep
);
902 dep
->relation
->map
= isl_map_intersect(dep
->relation
->map
, last
);
903 if (dep
->controlled_relation
)
904 dep
->controlled_relation
->map
=
905 isl_map_intersect_range(isl_map_copy(dep
->relation
->map
),
906 isl_map_range(dep
->controlled_relation
->map
));
909 /* If any sink iteration has more than one potential source
910 * iteration, we split off the propagation of the data on the from
911 * node from the transfer of the data to the to node.
913 * We only perform this operation here on (data) dependences
914 * with a "controlled_relation". The corresponding control dependence
915 * has already been handled from within extract_control_dependence.
916 * Other data dependences have an exact dependence relation and
917 * can therefore not exhibit multiple assignments.
919 static void split_multi_assignment(PDG
*pdg
)
921 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
922 pdg::dependence
*dep
= pdg
->dependences
[i
];
923 if (!dep
->controlled_relation
)
925 if (isl_map_is_injective(dep
->relation
->map
))
927 split_multi_assignment(pdg
, dep
);
931 /* Does "dep" have any parameters of the form __last_*?
933 static bool has_controls(__isl_keep isl_map
*dep
)
936 const char *prefix
= "__last_";
937 size_t prefix_len
= strlen(prefix
);
939 n_param
= isl_map_dim(dep
, isl_dim_param
);
940 for (int i
= 0; i
< n_param
; ++i
) {
943 if (!isl_map_has_dim_id(dep
, isl_dim_param
, i
))
945 name
= isl_map_get_dim_name(dep
, isl_dim_param
, i
);
946 if (!strncmp(name
, prefix
, prefix_len
))
953 /* Is the i-th parameter of "map" of the form local_control*?
954 * "len" is the length of "local_control".
956 static bool is_local_control(__isl_keep isl_map
*map
, int i
,
957 const char *local_control
, size_t len
)
961 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
963 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
964 return strncmp(name
, local_control
, len
) == 0;
967 /* Does "dep" have any parameters of the form __last_*
968 * that are not of the form local_control*?
970 static bool has_foreign_controls(__isl_keep isl_map
*dep
,
971 const char *local_control
, size_t len
)
975 n_param
= isl_map_dim(dep
, isl_dim_param
);
976 for (int i
= 0; i
< n_param
; ++i
)
977 if (is_foreign_control(dep
, i
, local_control
, len
))
983 /* Does "dep" have any parameters of the form local_control*?
984 * "len" is the length of "local_control".
986 static bool has_local_controls(__isl_keep isl_map
*dep
,
987 const char *local_control
, size_t len
)
991 n_param
= isl_map_dim(dep
, isl_dim_param
);
992 for (int i
= 0; i
< n_param
; ++i
)
993 if (is_local_control(dep
, i
, local_control
, len
))
999 /* Extract a control dependence from a dependence with a controlled_relation.
1000 * The control dependence transfers the values of the control variables
1001 * that correspond to the given dependence, i.e., those that correspond
1002 * to the from and to access of the dependence.
1003 * We therefore don't need to do anything if the controlled_relation
1004 * only involves foreign controls.
1006 * from_controls and to_controls are set from the local control variables
1007 * in dep->controlled_relation.
1009 * The uncontrolled dependence relation may not be injective,
1010 * in which case the initial dependence relation on the control
1011 * dependence is also non-injective. In such cases, the control
1012 * dependence is split using split_multi_assignment in two parts,
1013 * one that propagate the current value of the controls to the next
1014 * iteration of the source and one that sends the final values to the sink.
1015 * The data dependence is split later on.
1017 static void extract_control_dependence(PDG
*pdg
, pdg::dependence
*dep
)
1019 pdg::dependence
*control
;
1025 len
= set_local_control_name(buf
, sizeof(buf
), dep
);
1026 rel
= dep
->controlled_relation
->map
;
1027 if (!has_local_controls(rel
, buf
, len
))
1029 n_param
= isl_map_dim(rel
, isl_dim_param
);
1031 control
= new pdg::dependence
;
1032 control
->type
= dep
->type
;
1033 control
->from
= dep
->from
;
1034 control
->to
= dep
->to
;
1035 control
->from_access
= dep
->from_access
;
1036 control
->to_access
= dep
->to_access
;
1037 control
->relation
= new pdg::IslMap(dep
->relation
->get_isl_map());
1038 for (int i
= 0; i
< n_param
; ++i
) {
1040 if (!isl_map_has_dim_id(rel
, isl_dim_param
, i
))
1042 name
= isl_map_get_dim_name(rel
, isl_dim_param
, i
);
1043 if (strncmp(name
, buf
, len
) != 0)
1045 control
->from_controls
.push_back(new str(name
));
1046 control
->to_controls
.push_back(new str(name
));
1048 pdg
->dependences
.push_back(control
);
1050 if (isl_map_is_injective(control
->relation
->map
))
1052 split_multi_assignment(pdg
, control
);
1055 /* Extract a control dependence from each dependence with a controlled_relation.
1057 static void extract_control_dependences(PDG
*pdg
)
1059 int n_dep
= pdg
->dependences
.size();
1061 for (int i
= 0; i
< n_dep
; ++i
) {
1062 pdg::dependence
*dep
= pdg
->dependences
[i
];
1063 if (!dep
->controlled_relation
)
1065 extract_control_dependence(pdg
, dep
);
1069 /* Split off the communication of data, along with the corresponding
1070 * controls, from selecting the data based on other controls.
1071 * "dep" is modified to only refer to the controls that correspond
1072 * to the given from and to access and an extra wire is introduced
1073 * to select the data.
1074 * If "dep" corresponds to a propagation from one potential source
1075 * to the next potential source, then it already only refers to
1076 * "local" controls. We handle this case separately so that we
1077 * don't have to add a special case to set_local_control_name
1078 * for setting up the right name for local controls on such dependences.
1080 * A new virtual access is created to act as the target of the modified
1081 * communication dependence and the source of the selection dependence.
1082 * If the input "dep" did not refer to the corresponding controls,
1083 * then the output "dep" does not refer to any control and
1084 * controlled_relation is cleared.
1086 static void split_wire(PDG
*pdg
, pdg::dependence
*dep
)
1092 pdg::dependence
*wire
;
1093 pdg::access
*access
;
1097 if (is_multi_assignment_propagation(dep
))
1100 assert(!dep
->extended_relation
);
1102 rel
= dep
->controlled_relation
->map
;
1103 len
= set_local_control_name(buf
, sizeof(buf
), dep
);
1105 if (!has_foreign_controls(rel
, buf
, len
))
1108 space
= isl_map_get_space(dep
->controlled_relation
->map
);
1109 space
= isl_space_range(space
);
1110 space
= isl_space_map_from_set(space
);
1111 id
= isl_map_identity(space
);
1112 dom
= isl_map_range(isl_map_copy(dep
->controlled_relation
->map
));
1113 id
= isl_map_intersect_domain(id
, dom
);
1115 access
= new pdg::access
;
1116 access
->array
= dep
->to_access
->array
;
1117 access
->nr
= dep
->to
->statement
->accesses
.size();
1118 dep
->to
->statement
->accesses
.push_back(access
);
1120 wire
= new pdg::dependence
;
1121 wire
->array
= dep
->array
;
1122 wire
->type
= pdg::dependence::pn_wire
;
1123 wire
->from
= dep
->to
;
1125 wire
->from_access
= access
;
1126 wire
->to_access
= dep
->to_access
;
1127 wire
->relation
= new pdg::IslMap(id
);
1128 pdg
->dependences
.push_back(wire
);
1130 dep
->to_access
= access
;
1131 dep
->controlled_relation
->map
= remove_foreign_controls(rel
, buf
, len
);
1132 if (!has_controls(dep
->controlled_relation
->map
)) {
1133 delete dep
->controlled_relation
;
1134 dep
->controlled_relation
= NULL
;
1138 /* If the dependence involves "foreign" controls, i.e., controls
1139 * that correspond to other dependences, then we split off
1140 * the communication of the data (along with the "local" controls)
1141 * from the selection of the data based on the foreign controls.
1143 static void split_wires(PDG
*pdg
)
1145 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1146 pdg::dependence
*dep
= pdg
->dependences
[i
];
1147 if (!dep
->controlled_relation
)
1149 split_wire(pdg
, dep
);
1153 static void schedule(PDG
*pdg
, struct pn_options
*options
)
1155 translate(pdg
, options
->move
);
1158 /* Compute the size of the dependence "dep" with scheduled dependence
1159 * relation "dep_map".
1161 * If "dep" is of type pn_union, then it may contains parts that read
1162 * from the channel in the same iteration. We therefore need to recombine
1163 * the dependence relations of those parts, but separate them apart.
1164 * In particular, we add an extra inner dimension with a fixed value
1165 * corresponding to the index of the dependence.
1167 static size::enumerator
*compute_size(pdg::PDG
*pdg
, pdg::dependence
*dep
,
1168 __isl_take isl_map
*dep_map
, pn_options
*options
)
1170 dep_map
= isl_map_copy(dep_map
);
1171 if (dep
->type
== pdg::dependence::pn_union
) {
1172 isl_space
*space
= isl_map_get_space(dep_map
);
1175 n_in
= isl_space_dim(space
, isl_dim_in
);
1176 n_out
= isl_space_dim(space
, isl_dim_out
);
1177 space
= isl_space_add_dims(space
, isl_dim_in
, 1);
1178 space
= isl_space_add_dims(space
, isl_dim_out
, 1);
1179 isl_map_free(dep_map
);
1180 dep_map
= isl_map_empty(space
);
1181 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1182 pdg::dependence
*part
= pdg
->dependences
[i
];
1185 if (part
->type
!= pdg::dependence::pn_part
)
1187 if (part
->container
!= dep
)
1189 map_i
= part
->relation
->get_isl_map();
1190 map_i
= isl_map_intersect_params(map_i
,
1191 pdg
->get_context_isl_set());
1192 map_i
= schedule_dependence(pdg
, dep
, map_i
);
1193 map_i
= isl_map_add_dims(map_i
, isl_dim_in
, 1);
1194 map_i
= isl_map_add_dims(map_i
, isl_dim_out
, 1);
1195 map_i
= isl_map_fix_si(map_i
, isl_dim_in
, n_in
, i
);
1196 map_i
= isl_map_fix_si(map_i
, isl_dim_out
, n_out
, i
);
1197 dep_map
= isl_map_union(dep_map
, map_i
);
1200 return selfloop_size(pdg
, dep_map
, options
->size
);
1203 static bool determine_dependence_properties(PDG
*pdg
, pdg::dependence
*dep
,
1204 bool evaluate
, bool scheduled
, struct pn_options
*options
)
1206 if (dep
->type
== pdg::dependence::uninitialized
) {
1208 "access to uninitialized data from %s on line %d\n",
1209 dep
->array
->name
->s
.c_str(), dep
->to
->statement
->line
);
1210 dep
->relation
->Dump(stderr
);
1213 pdg::IslMap
*rel
= dep
->relation
;
1214 if (dep
->type
== pdg::dependence::pn_part
||
1215 dep
->type
== pdg::dependence::pn_wire
) {
1216 dep
->reordering
= 0;
1217 dep
->multiplicity
= 0;
1218 dep
->size
= new pdg::enumerator(0);
1219 dep
->value_size
= new integer(0);
1223 isl_map
*dep_map
= rel
->get_isl_map();
1224 dep_map
= isl_map_intersect_params(dep_map
, pdg
->get_context_isl_set());
1225 dep
->reordering
= isl_map_is_reordering(dep_map
);
1226 dep
->multiplicity
= 0;
1227 if (!options
->reuse
)
1228 dep
->multiplicity
= isl_map_has_multiplicity(dep_map
);
1229 if (dep
->reordering
|| dep
->multiplicity
) {
1230 isl_map_free(dep_map
);
1234 if (dep
->to
!= dep
->from
&& !scheduled
) {
1235 schedule(pdg
, options
);
1239 if (dep
->to
!= dep
->from
)
1240 dep_map
= schedule_dependence(pdg
, dep
, dep_map
);
1242 if (!dep
->controlled_relation
&& isl_is_consecutive_loop(dep_map
)) {
1243 dep
->size
= new pdg::enumerator(1);
1244 dep
->value_size
= new integer(1);
1245 if (dep
->from_access
== dep
->to_access
&&
1246 dep
->to_access
->type
!= pdg::access::write
&&
1247 is_consecutive_dep(pdg
, dep
, dep_map
))
1248 dep
->type
= pdg::dependence::pn_hold
;
1250 size::enumerator
*size
= NULL
;
1251 if (options
->shift_register
&& dep
->to
== dep
->from
&&
1252 !dep
->controlled_relation
) {
1253 isl_set
*ref
= dep
->to
->source
->get_isl_set();
1254 size
= shift_register_size(pdg
, ref
,
1255 isl_map_copy(dep_map
));
1258 dep
->type
= pdg::dependence::pn_shift
;
1260 size
= compute_size(pdg
, dep
, dep_map
, options
);
1264 dep
->value_size
= size
->evaluate();
1269 isl_map_free(dep_map
);
1274 static void determine_dependence_properties(PDG
*pdg
, bool evaluate
,
1275 bool scheduled
, struct pn_options
*options
)
1277 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1278 pdg::dependence
*dep
= pdg
->dependences
[i
];
1279 scheduled
= determine_dependence_properties(pdg
, dep
, evaluate
,
1280 scheduled
, options
);
1284 /* Can we merge "dep1" and "dep2"?
1287 * - do they connect the same from_access to the same to node?
1288 * - is there no reordering in the combined dependence relation?
1290 static bool can_merge(PDG
*pdg
, pdg::dependence
*dep1
, pdg::dependence
*dep2
)
1292 pdg::IslMap
*rel1
= dep1
->relation
;
1293 pdg::IslMap
*rel2
= dep2
->relation
;
1297 if (dep1
->to
!= dep2
->to
)
1299 if (dep1
->from_access
!= dep2
->from_access
)
1301 dep_rel
= isl_map_union(rel1
->get_isl_map(), rel2
->get_isl_map());
1302 dep_rel
= isl_map_intersect_params(dep_rel
, pdg
->get_context_isl_set());
1304 reordering
= isl_map_is_reordering(dep_rel
);
1306 isl_map_free(dep_rel
);
1311 /* Combine the dependences "dep1" and "dep2" into a single pn_union
1312 * dependences with the union dependence relation.
1314 * If "dep2" is already a pn_union, we simply extend it.
1315 * Otherwise, we create a new pn_union modeled after "dep2",
1316 * add it to the list of dependences and turn "dep2" into a pn_part.
1317 * "dep1" is turned into a pn_part in any case.
1319 static void merge_dependences(PDG
*pdg
, pdg::dependence
*dep1
,
1320 pdg::dependence
*dep2
)
1322 pdg::dependence
*dep_union
;
1324 if (dep2
->type
== pdg::dependence::pn_union
)
1328 dep_union
= new pdg::dependence
;
1329 dep_union
->from
= dep2
->from
;
1330 dep_union
->to
= dep2
->to
;
1331 dep_union
->from_access
= dep2
->from_access
;
1332 dep_union
->to_access
= NULL
;
1333 dep_union
->array
= dep2
->array
;
1334 dep_union
->type
= pdg::dependence::pn_union
;
1335 rel
= dep2
->relation
;
1336 dep_union
->relation
= new pdg::IslMap(rel
->get_isl_map());
1337 pdg
->dependences
.push_back(dep_union
);
1339 dep2
->type
= pdg::dependence::pn_part
;
1340 dep2
->container
= dep_union
;
1343 dep1
->type
= pdg::dependence::pn_part
;
1344 dep1
->container
= dep_union
;
1346 dep_union
->relation
->map
= isl_map_union(dep_union
->relation
->map
,
1347 dep1
->relation
->get_isl_map());
1350 /* Try and merge dependences between a given pair of (distinct) nodes.
1351 * A merge is performed only if it the resulting merged dependence
1352 * does not exhibit any reordering.
1353 * The merging needs to be applied before the buffer size computation
1354 * as the buffer sizes are computed on the merged (pn_union) dependences.
1356 * We run through all original dependences and check whether it can
1357 * be combined with any later dependences. If so, we turn the two
1358 * dependences into "pn_part"s and add an extra pn_union dependence
1359 * that combines the two. The inner loop starts from the latest
1360 * dependence so that we compare with any previously added pn_union
1361 * dependences first. If such a previously add pn_union can be combined
1362 * with the current dependence, it is simply extended to include the
1363 * current dependence.
1365 * We currently don't allow any merging of dependences involving control.
1367 * If the user has turned off merging, the we do nothing.
1368 * We do the same if the user has turned off reuse detection, as there
1369 * may in this case be dependences with multiplicity. It is not clear
1370 * if we would want to merge such edges.
1372 static void merge_dependences(PDG
*pdg
, struct pn_options
*options
)
1376 if (!options
->reuse
)
1378 if (!options
->merge
)
1381 n_dep
= pdg
->dependences
.size();
1382 for (int i
= 0; i
< n_dep
; ++i
) {
1383 pdg::dependence
*dep_i
= pdg
->dependences
[i
];
1384 if (dep_i
->type
!= pdg::dependence::flow
)
1386 if (dep_i
->to
== dep_i
->from
)
1388 if (dep_i
->controlled_relation
)
1391 for (int j
= pdg
->dependences
.size() - 1; j
> i
; --j
) {
1392 pdg::dependence
*dep_j
= pdg
->dependences
[j
];
1394 if (dep_j
->type
!= pdg::dependence::flow
&&
1395 dep_j
->type
!= pdg::dependence::pn_union
)
1397 if (dep_j
->controlled_relation
)
1399 if (!can_merge(pdg
, dep_i
, dep_j
))
1402 merge_dependences(pdg
, dep_i
, dep_j
);
1407 /* Is "access" one of the filter accesses of "node"?
1409 static bool is_filter_access(pdg::node
*node
, pdg::access
*access
)
1411 for (int i
= 0; i
< node
->filters
.size(); ++i
) {
1412 pdg::call_or_access
*coa
;
1414 coa
= node
->filters
[i
];
1415 assert(coa
->type
== pdg::call_or_access::t_access
);
1416 if (access
== coa
->access
)
1422 /* Given the (overapproximation of the) dependence relation "dep_rel",
1423 * check whether "to" and "from" represent the same filter, i.e.,
1424 * whether they refer to the same array element written at the same
1427 * We apply the mappings from source/sink iterations
1428 * to filter access relations to both sides of "dep_rel".
1429 * If the result is a subset of the identity relation, then
1430 * we know that the filter element accessed by the source is
1431 * exactly the same as the filter element accessed by
1432 * the courresponding sink(s).
1434 * If we were unable to find the source for one or both of the two filters,
1435 * then the filter access relations live in different spaces and
1436 * the computed relation cannot be a subset of the identity relation.
1438 static bool is_same_filter(pdg::access
*to
, pdg::access
*from
,
1439 __isl_keep isl_map
*dep_rel
)
1441 isl_union_map
*from_access
;
1442 isl_union_map
*to_access
;
1443 isl_union_map
*test
;
1444 isl_union_map
*univ
;
1448 if (to
->array
!= from
->array
)
1451 from_access
= from
->extract_access_map();
1452 to_access
= to
->extract_access_map();
1453 test
= isl_union_map_from_map(isl_map_copy(dep_rel
));
1454 test
= isl_union_map_apply_domain(test
, from_access
);
1455 test
= isl_union_map_apply_range(test
, to_access
);
1456 univ
= isl_union_map_universe(isl_union_map_copy(test
));
1457 id
= isl_union_set_identity(isl_union_map_domain(univ
));
1458 same
= isl_union_map_is_subset(test
, id
);
1459 isl_union_map_free(test
);
1460 isl_union_map_free(id
);
1465 /* Insert equalities between source filters and sink filters
1466 * of dependences, whenever we are able to detect that they are the same.
1468 * We first introduce the constraints on the sink filters in the dependence
1469 * relation and we add unconstrained variables for the source filters.
1470 * Then, for each of the sink filters, we check if we can find
1471 * any source filter that has the same value on the other side
1472 * of the dependence. If so, we can keep the constraints on this
1473 * filter value and we add an equality between the source filter
1474 * and the sink filter so that these constraints will also be
1475 * applied to the source filter.
1476 * Otherwise, we eliminate the sink filter value from the constraints.
1478 static void insert_filter_constraints(pdg::dependence
*dep
)
1487 dep_rel
= isl_map_copy(dep
->relation
->map
);
1488 n_in
= isl_map_dim(dep_rel
, isl_dim_in
);
1489 n_out
= isl_map_dim(dep_rel
, isl_dim_out
);
1491 space
= isl_set_get_space(dep
->from
->source
->set
);
1492 map
= isl_set_unwrap(isl_set_universe(space
));
1493 map
= isl_map_reverse(isl_map_domain_map(map
));
1494 dep_rel
= isl_map_apply_domain(dep_rel
, map
);
1495 map
= isl_set_unwrap(dep
->to
->source
->get_isl_set());
1496 map
= isl_map_reverse(isl_map_domain_map(map
));
1497 dep_rel
= isl_map_apply_range(dep_rel
, map
);
1499 for (int i
= 0; i
< dep
->to
->filters
.size(); ++i
) {
1500 pdg::call_or_access
*coa_i
;
1501 pdg::access
*access_i
;
1504 coa_i
= dep
->to
->filters
[i
];
1505 assert(coa_i
->type
== pdg::call_or_access::t_access
);
1506 access_i
= coa_i
->access
;
1508 for (int j
= 0; j
< dep
->from
->filters
.size(); ++j
) {
1509 pdg::call_or_access
*coa_j
;
1510 pdg::access
*access_j
;
1512 coa_j
= dep
->from
->filters
[j
];
1513 assert(coa_j
->type
== pdg::call_or_access::t_access
);
1514 access_j
= coa_j
->access
;
1516 if (!is_same_filter(access_i
, access_j
,
1517 dep
->relation
->map
))
1519 dep_rel
= isl_map_equate(dep_rel
, isl_dim_in
, n_in
+ j
,
1520 isl_dim_out
, n_out
+ i
);
1526 dep_rel
= isl_map_eliminate(dep_rel
, isl_dim_out
,
1531 isl_map_free(dep
->relation
->map
);
1532 dep
->relation
->map
= dep_rel
;
1534 isl_map_free(dep_rel
);
1537 /* Insert equalities between source filters and sink filters
1538 * of dependences, whenever we are able to detect that they are the same.
1540 * We currently don't introduce any such equalities in dependences
1541 * that involve control variables. Both these control variables and
1542 * the filters will be treated as "dynamic controls" in pn2adg
1543 * and it probably needs to be tweaked to be able to handle two sets
1544 * of dynamic controls.
1546 static void insert_filter_constraints(PDG
*pdg
)
1548 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1549 pdg::dependence
*dep
= pdg
->dependences
[i
];
1551 if (dep
->type
== pdg::dependence::uninitialized
)
1553 if (dep
->to
== dep
->from
)
1555 if (dep
->controlled_relation
)
1557 if (dep
->to
->filters
.size() == 0)
1559 if (dep
->from
->filters
.size() == 0)
1561 if (is_filter_access(dep
->to
, dep
->to_access
))
1563 insert_filter_constraints(dep
);
1567 int main(int argc
, char * argv
[])
1570 FILE *in
= stdin
, *out
= stdout
;
1573 struct pn_options
*options
= pn_options_new_with_defaults();
1574 bool evaluate
= true;
1576 argc
= pn_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
1578 if (!options
->reuse
)
1579 options
->propagate
= 0;
1581 if (options
->input
&& strcmp(options
->input
, "-")) {
1582 in
= fopen(options
->input
, "r");
1584 if (!options
->output
) {
1585 int len
= strlen(options
->input
);
1586 if (len
> 5 && !strcmp(options
->input
+len
-5, ".yaml"))
1588 options
->output
= (char *)malloc(len
+9+1);
1589 strncpy(options
->output
, options
->input
, len
);
1590 strcpy(options
->output
+len
, options
->reuse
? "_pn.yaml" : "_cpn.yaml");
1594 ctx
= isl_ctx_alloc_with_options(&pn_options_args
, options
);
1595 pdg
= PDG::Load(in
, ctx
);
1597 int nparam
= pdg
->params
.size();
1599 if (options
->propagate
)
1600 copy_propagation(pdg
);
1602 compute_filter_sources(pdg
);
1603 for (int i
= 0; i
< pdg
->arrays
.size(); ++i
)
1604 find_deps(pdg
, pdg
->arrays
[i
], flow
);
1605 extract_control_dependences(pdg
);
1607 for (int i
= 0; i
< nparam
; ++i
)
1608 if (!pdg
->params
[i
]->value
) {
1614 if (options
->reschedule
) {
1615 common_dimension(pdg
);
1618 set_schedule_from_prefix(pdg
);
1622 detect_reuse(pdg
, options
);
1623 split_multi_assignment(pdg
);
1625 merge_dependences(pdg
, options
);
1626 determine_dependence_properties(pdg
, evaluate
, translated
, options
);
1627 insert_filter_constraints(pdg
);
1629 pdg
->add_history_line("pn", argc
, argv
);
1631 if (options
->output
&& strcmp(options
->output
, "-")) {
1632 out
= fopen(options
->output
, "w");