15 #include "translation.h"
16 #include "pn_options.h"
25 /* Check whether node is a propagation node
27 * A propagation node simply copies a value from one array to another array.
28 * In principle, a copy node could also copy a value to the same array,
29 * but then we would have to be careful that the node does not recursively
31 * Note that the check is incomplete. If a node performs some additional
32 * operations involving only iterators, then this information is not stored
33 * so we may incorrectly conclude that the node is a copy node.
35 static bool propagation_node(pdg::node
*node
)
37 pdg::statement
*s
= node
->statement
;
38 if (s
->accesses
.size() != 2)
40 if (s
->accesses
[0]->type
!= pdg::access::read
)
42 if (s
->accesses
[1]->type
!= pdg::access::write
)
44 if (s
->accesses
[0]->array
== s
->accesses
[1]->array
)
46 if (s
->accesses
[1]->array
->dims
.size() != 0)
48 if (s
->top_function
&& s
->top_function
->name
&&
49 strcmp(s
->top_function
->name
->s
.c_str(), ""))
54 static pdg::IslMap
*join_input(PDG
*pdg
, pdg::IslMap
*left
,
58 isl_ctx
*ctx
= pdg
->get_isl_ctx();
59 isl_map
*rel
= left
->get_isl_map(ctx
);
60 isl_map
*acc
= right
->get_isl_map(ctx
);
62 acc
= isl_map_apply_domain(acc
, rel
);
64 res
= new pdg::IslMap(acc
);
69 /* Given a dependence relation um_rel that maps iterations from
70 * a propagation node to the current node and an access relation
71 * from the current node, drop those iterations from the domain
72 * of the access relation that have been propagated, i.e.,
73 * that are in the range of the dependence relation.
75 * The original access relation is destroyed and a new one
76 * is returned, provided the new access relation is not empty.
77 * If it is empty, then a NULL pointer is returned.
79 * Note that the input access relation may not have been specialized
80 * to the domain of the node, i.e., the access relation may have
81 * a universe domain. In that case, the new relation is unlikely
82 * to be empty, but it may end up having a domain that is disjoint
83 * from the domain of the node.
85 static pdg::IslMap
*remove_propagated_from_domain(PDG
*pdg
,
86 pdg::IslMap
*um_rel
, pdg::IslMap
*um_acc
)
88 pdg::IslMap
*res
= NULL
;
89 isl_ctx
*ctx
= pdg
->get_isl_ctx();
90 isl_map
*rel
= um_rel
->get_isl_map(ctx
);
91 isl_map
*acc
= um_acc
->get_isl_map(ctx
);
93 isl_set
*rel_ran
= isl_map_range(rel
);
94 isl_set
*acc_dom
= isl_map_domain(isl_map_copy(acc
));
96 acc_dom
= isl_set_subtract(acc_dom
, rel_ran
);
97 acc
= isl_map_intersect_domain(acc
, acc_dom
);
101 if (isl_map_is_empty(acc
))
104 res
= new pdg::IslMap(acc
);
109 /* Recursively replace old_access inside call by new_access.
111 static void replace_access(pdg::function_call
*call
, pdg::access
*old_access
,
112 pdg::call_or_access
*new_coa
)
114 for (int i
= 0; i
< call
->arguments
.size(); ++i
) {
115 pdg::call_or_access
*coa
= call
->arguments
[i
];
116 if (coa
->type
== pdg::call_or_access::t_call
)
117 replace_access(coa
->call
, old_access
, new_coa
);
118 if (coa
->type
== pdg::call_or_access::t_access
&&
119 coa
->access
== old_access
) {
126 /* Replace old_access inside s by new_access.
127 * If empty is not set, then new_access only replaces part of
128 * old_access. This means that old_access is kept in the list
129 * of accesses and that in the parse tree of the statement,
130 * old_access is replaced by a new virtual function call
131 * with old_access and new_access as arguments.
133 static void replace_access(pdg::statement
*s
, pdg::access
*old_access
,
134 pdg::access
*new_access
, bool empty
)
136 pdg::call_or_access coa
;
139 s
->accesses
.erase(old_access
);
140 s
->accesses
.push_back(new_access
);
142 if (!s
->top_function
)
146 coa
.type
= pdg::call_or_access::t_access
;
147 coa
.access
= new_access
;
149 pdg::call_or_access
*old_coa
, *new_coa
;
150 coa
.type
= pdg::call_or_access::t_call
;
151 coa
.call
= new pdg::function_call
;
152 coa
.call
->name
= new str(string("#PHI"));
153 old_coa
= new pdg::call_or_access
;
154 old_coa
->type
= pdg::call_or_access::t_access
;
155 old_coa
->access
= old_access
;
156 coa
.call
->arguments
.push_back(old_coa
);
157 new_coa
= new pdg::call_or_access
;
158 new_coa
->type
= pdg::call_or_access::t_access
;
159 new_coa
->access
= new_access
;
160 coa
.call
->arguments
.push_back(new_coa
);
162 replace_access(s
->top_function
, old_access
, &coa
);
165 static void clear_dependences(PDG
*pdg
)
167 for (int j
= 0; j
< pdg
->dependences
.size(); ++j
) {
168 pdg::dependence
*dep
= pdg
->dependences
[j
];
169 delete dep
->controlled_relation
;
170 delete dep
->relation
;
173 pdg
->dependences
.resize(0);
176 /* Check if there is any node that simply copies the value from an array
177 * to a scalar. If so, perform dependence analysis on the scalar
178 * and replaces read access to the scalar that depend on writes from
179 * a propagation node to reads from the propagated array.
180 * In particular, the propagated iterations are removed from the access
181 * relation and replaced by an access to the propagated array.
182 * Finally, the propagation node is removed.
184 static void copy_propagation(PDG
* pdg
)
186 std::set
<pdg::node
*> to_remove_n
;
187 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
188 pdg::node
*node
= pdg
->nodes
[i
];
189 pdg::statement
*s
= node
->statement
;
190 if (!propagation_node(node
))
192 pdg::array
*a
= s
->accesses
[1]->array
;
193 find_deps(pdg
, a
, flow
);
194 std::set
<pdg::access
*> to_remove
;
195 for (int j
= 0; j
< pdg
->dependences
.size(); ++j
) {
196 pdg::dependence
*dep
= pdg
->dependences
[j
];
197 if (dep
->controlled_relation
)
199 assert(dep
->type
== pdg::dependence::flow
);
200 assert(dep
->from
!= dep
->to
);
201 if (!propagation_node(dep
->from
))
203 to_remove_n
.insert(dep
->from
);
204 pdg::IslMap
*access_map
= dep
->from
->statement
->accesses
[0]->map
;
205 pdg::IslMap
*prop_access
= join_input(pdg
, dep
->relation
, access_map
);
206 access_map
= dep
->to_access
->map
;
207 access_map
= remove_propagated_from_domain(pdg
, dep
->relation
,
209 dep
->to_access
->map
= access_map
;
210 bool empty
= !access_map
;
211 pdg::access
*access
= new pdg::access
;
212 access
->nr
= dep
->to_access
->nr
;
213 access
->array
= dep
->from
->statement
->accesses
[0]->array
;
214 access
->type
= pdg::access::read
;
215 access
->map
= prop_access
;
216 replace_access(dep
->to
->statement
, dep
->to_access
, access
, empty
);
218 to_remove
.insert(dep
->to_access
);
220 std::set
<pdg::access
*>::iterator it
;
221 for (it
= to_remove
.begin(); it
!= to_remove
.end(); ++it
) {
226 clear_dependences(pdg
);
228 if (to_remove_n
.size() == 0)
230 std::set
<pdg::node
*>::iterator itn
;
231 for (itn
= to_remove_n
.begin(); itn
!= to_remove_n
.end(); ++itn
) {
232 (*itn
)->statement
->accesses
[0]->array
= NULL
;
233 (*itn
)->statement
->accesses
[1]->array
= NULL
;
236 pdg
->nodes
.erase(*itn
);
238 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
)
239 pdg
->nodes
[i
]->nr
= i
;
242 /* Check whether dep writes and reads from consecutive iterations of
244 * We check this property by testing whether any other read for the
245 * same access occurs in between.
247 bool is_consecutive_dep(PDG
*pdg
, pdg::dependence
*dep
, isl_map
*map
)
249 isl_ctx
*ctx
= pdg
->get_isl_ctx();
250 assert(dep
->to
== dep
->from
);
251 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
252 pdg::dependence
*other_dep
= pdg
->dependences
[i
];
253 if (other_dep
== dep
)
255 if (other_dep
->to
!= dep
->to
)
257 if (other_dep
->to_access
!= dep
->to_access
)
259 isl_map
*other_map
= other_dep
->relation
->get_isl_map(ctx
);
260 bool consec
= isl_is_consecutive_dep(map
, other_map
);
261 isl_map_free(other_map
);
268 /* An auxiliary class that keeps a reference to an isl_map
269 * and frees it when it goes out of scope.
273 temp_map(isl_map
*m
) : map(m
) {}
274 operator isl_map
*() const { return map
; }
280 /* Set *user to qp of the first call, assuming *user was initialized to NULL.
281 * If this function is called more than once, then return -1.
283 static int extract_single(__isl_take isl_set
*set
,
284 __isl_take isl_qpolynomial
*qp
, void *user
)
286 isl_qpolynomial
**res
= (isl_qpolynomial
**) user
;
291 isl_qpolynomial_free(qp
);
299 /* Check if we can use a shift register for the self-dependence dep
301 * If yes, return the required size of the shift register.
302 * If no, return NULL.
304 * We assume that the register is shifted on every iteration of D.
305 * If the number of shifts between any pair of writes and reads is
306 * constant, then we can use a shift register.
307 * Note that the size of the shift register may be larger than
308 * that of the FIFO, since there may be iterations of the domain
309 * between corresponding writes and reads where nothing is written
310 * to or read from the shift register.
312 * If "ref" is a wrapped map, then the iteration domain
313 * is in the domain of that map.
315 static size::enumerator
*shift_register_size(pdg::PDG
*pdg
,
316 __isl_take isl_set
*ref
, __isl_take isl_map
*dep
)
320 isl_map
*read_after_ref
;
321 isl_map
*write_before_ref
;
322 isl_map
*ref_between
;
323 isl_pw_qpolynomial
*pwqp
;
328 if (isl_set_is_wrapping(ref
))
329 ref
= isl_map_domain(isl_set_unwrap(ref
));
331 dim
= isl_set_dim(ref
, isl_dim_set
);
332 dep
= isl_map_move_dims(dep
, isl_dim_in
, dim
, isl_dim_out
, 0, dim
);
333 dep_set
= isl_map_domain(dep
);
335 read_after_ref
= isl_map_lex_ge(isl_set_get_space(ref
));
336 read_after_ref
= isl_map_insert_dims(read_after_ref
, isl_dim_in
, 0, dim
);
337 write_before_ref
= isl_map_lex_lt(isl_set_get_space(ref
));
338 write_before_ref
= isl_map_add_dims(write_before_ref
, isl_dim_in
, dim
);
339 ref_between
= isl_map_intersect(read_after_ref
, write_before_ref
);
341 ref_between
= isl_map_intersect_range(ref_between
, ref
);
342 ref_between
= isl_map_intersect_domain(ref_between
,
343 isl_set_copy(dep_set
));
345 pwqp
= isl_map_card(ref_between
);
347 pwqp
= isl_pw_qpolynomial_gist(pwqp
, dep_set
);
349 pwqp
= isl_pw_qpolynomial_coalesce(pwqp
);
352 if (isl_pw_qpolynomial_foreach_piece(pwqp
, &extract_single
, &qp
) < 0 ||
354 isl_qpolynomial_involves_dims(qp
, isl_dim_in
, 0, dim
+ dim
)) {
355 isl_qpolynomial_free(qp
);
356 isl_pw_qpolynomial_free(pwqp
);
359 isl_pw_qpolynomial_free(pwqp
);
361 qp
= isl_qpolynomial_project_domain_on_params(qp
);
362 universe
= isl_set_universe(isl_qpolynomial_get_domain_space(qp
));
363 pwqp
= isl_pw_qpolynomial_alloc(universe
, qp
);
365 return new size::enumerator(pwqp
, pdg
);
368 /* isl_access_level_before function used in a context where there
369 * is a single iteration domain. The order is given by the order
370 * of the accesses passed through first and second.
371 * If the first access precedes the second, we return 2 * d + 1,
372 * where d is the dimension of the iteration domain, and otherwise 2 * d.
374 static int precedes_access(void *first
, void *second
)
376 pdg::access
*access1
= (pdg::access
*) first
;
377 pdg::access
*access2
= (pdg::access
*) second
;
378 int d
= isl_map_dim(access1
->map
->map
, isl_dim_in
);
380 return 2 * d
+ (access1
->nr
< access2
->nr
);
383 /* Return true if all input dimensions are constrained to be equal to the
384 * corresponding output dimensions.
386 static bool is_identity_map(__isl_keep isl_map
*map
)
389 isl_space
*space
= isl_map_get_space(map
);
390 isl_map
*id
= isl_map_identity(space
);
392 is_id
= isl_map_is_subset(map
, id
);
399 /* Set buf (of size buf_len) to the prefix of control variables
400 * that correspond to the from and to access of the given "dep"
401 * and return the length of the prefix.
403 static size_t set_local_control_name(char *buf
, size_t buf_len
,
404 pdg::dependence
*dep
)
406 snprintf(buf
, buf_len
, "__last_%s_%d_%s_%d",
407 dep
->from
->name
->s
.c_str(), dep
->from_access
->nr
,
408 dep
->to
->name
->s
.c_str(), dep
->to_access
->nr
);
412 /* Given the name of a binding variable, reset the part that refers
413 * to the sink access by "nr".
415 * The original name is of the form
417 * __last_ND_<source node>_<source access>_ND_<sink node>_<sink access>_*
419 * We simply replace the <sink access> by <nr>.
421 static str
*replace_to_access(isl_ctx
*ctx
, str
*id
, int nr
)
430 name
= id
->s
.c_str();
432 suffix
= strrchr(name
, '_');
434 infix
= (const char *) memrchr(name
, '_', suffix
- name
);
436 len
= infix
+ 1 - name
+ strlen(suffix
) + 20;
437 replaced
= isl_alloc_array(ctx
, char, len
);
439 len
= infix
+ 1 - name
;
440 memcpy(replaced
, name
, len
);
441 snprintf(replaced
+ len
, 20, "%d", nr
);
442 len
+= strlen(replaced
+ len
);
443 strcpy(replaced
+ len
, suffix
);
445 s
= new str(replaced
);
451 /* For each element of controls, replace the part of the name that
452 * refers to the sink access by "nr" and collect the results in
455 static void replace_to_access(isl_ctx
*ctx
, seq
<str
> &renamed_controls
,
456 seq
<str
> &controls
, int nr
)
458 for (int i
= 0; i
< controls
.size(); ++i
)
459 renamed_controls
.push_back(replace_to_access(ctx
,
463 /* Is the i-th parameter of "map" of the form __last_*
464 * but not of the form local_control*?
466 static bool is_foreign_control(__isl_keep isl_map
*map
, int i
,
467 const char *local_control
, size_t len
)
470 const char *prefix
= "__last_";
471 size_t prefix_len
= strlen(prefix
);
473 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
475 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
476 if (strncmp(name
, prefix
, prefix_len
))
478 return strncmp(name
, local_control
, len
) != 0;
481 /* Remove from "dep" all those parameters that are of the form __last_*
482 * but not of the form local_control* and return the result.
484 static __isl_give isl_map
*remove_foreign_controls(__isl_take isl_map
*dep
,
485 const char *local_control
, size_t len
)
489 n_param
= isl_map_dim(dep
, isl_dim_param
);
490 for (int i
= n_param
- 1; i
>= 0; --i
) {
491 if (!is_foreign_control(dep
, i
, local_control
, len
))
493 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
495 dep
= isl_map_coalesce(dep
);
500 /* Is the i-th parameter of "map" a control, i.e., a parameter
501 * introduced by convert_writer()?
502 * In particular, is the parameter of the form __last_*?
504 static bool is_control(__isl_keep isl_map
*map
, int i
)
507 const char *prefix
= "__last_";
508 size_t prefix_len
= strlen(prefix
);
510 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
512 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
513 return strncmp(name
, prefix
, prefix_len
) == 0;
516 /* Remove all parameters that were introduced by convert_writer().
518 static __isl_give isl_map
*remove_all_controls(__isl_take isl_map
*dep
)
522 n_param
= isl_map_dim(dep
, isl_dim_param
);
523 for (int i
= n_param
- 1; i
>= 0; --i
) {
524 if (!is_control(dep
, i
))
526 dep
= isl_map_project_out(dep
, isl_dim_param
, i
, 1);
528 dep
= isl_map_coalesce(dep
);
533 struct add_reuse_data
{
535 pdg::dependence
*dep
;
539 static int add_reuse(__isl_take isl_map
*dep_rel
, int must
,
540 void *dep_user
, void *user
);
543 /* Add a reuse dependence with dependence relation "dep_rel" to
544 * data->pdg->dependences.
545 * data->dep corresponds to the original dependence that is reusing
546 * some value that was previously used by "propagate_access", from
548 * Since "dep_rel" was obtained from a relation with local
549 * control variables, we need to remove them to obtain the
550 * dependence relation on the reuse dependence.
552 * If we are reusing control variables, then we need to rename
553 * the from_control to refer to the access where we are reusing
554 * the control variables from.
556 * If the dependence relations maps iterations to themselves, then
557 * we mark the new reuse dependence as a wire.
559 static int add_reuse(__isl_take isl_map
*dep_rel
, int must
, void *dep_user
,
562 pdg::access
*propagate_access
= (pdg::access
*) dep_user
;
563 add_reuse_data
*data
= (add_reuse_data
*) user
;
564 pdg::dependence
*reuse_dep
;
565 isl_ctx
*ctx
= isl_map_get_ctx(dep_rel
);
567 reuse_dep
= new pdg::dependence
;
568 reuse_dep
->array
= data
->dep
->array
;
569 replace_to_access(ctx
, reuse_dep
->from_controls
,
570 data
->dep
->from_controls
, propagate_access
->nr
);
571 reuse_dep
->to_controls
= data
->dep
->to_controls
;
572 reuse_dep
->from
= data
->dep
->to
;
573 reuse_dep
->to
= data
->dep
->to
;
574 reuse_dep
->from_access
= propagate_access
;
575 reuse_dep
->to_access
= data
->dep
->to_access
;
576 if (reuse_dep
->from
== reuse_dep
->to
&& is_identity_map(dep_rel
))
577 reuse_dep
->type
= pdg::dependence::pn_wire
;
579 reuse_dep
->type
= data
->dep
->type
;
580 if (data
->dep
->controlled_relation
) {
581 pdg::IslMap
*cr
= data
->dep
->controlled_relation
;
582 isl_set
*dom
= isl_map_range(cr
->get_isl_map());
583 isl_map
*control_rel
= isl_map_copy(dep_rel
);
584 control_rel
= isl_map_intersect_range(control_rel
, dom
);
585 reuse_dep
->controlled_relation
= new pdg::IslMap(control_rel
);
587 dep_rel
= remove_all_controls(dep_rel
);
588 reuse_dep
->relation
= new pdg::IslMap(dep_rel
);
589 data
->pdg
->dependences
.push_back(reuse_dep
);
594 /* Detect reuse among the dependences in "deps", adding split off
595 * dependences to pdg->dependences.
596 * Each of the dependences in "deps" originates from the same
597 * write access and ends in the same node.
599 * We look for values, i.e., iterations of the write access,
600 * that are used several times. To do so, we perform dependence
601 * analysis on the inverted dependence relations. That is,
602 * we use these inverted dependence relations as "access relations",
603 * accessing iterations of the write access.
604 * We consider each dependence in turn as a "read", each time taking
605 * all dependences as writes.
606 * In the result of such a dependence analysis, the "uninitialized reads"
607 * correspond to the first use of a result from the original write access,
608 * while all the "dependences" corespond to a propagation of a value
609 * from one original read access to another original read access.
611 * If the dependence has a controlled_relation, then we use this
612 * controlled_relation as the "access relation" after removing all
613 * the foreign controls. This ensures that we only reuse data if
614 * the last iteration hasn't changed.
615 * After restricting the range of the controlled_relation based on
616 * the "uninitialized reads", we recompute the uncontrolled relation
619 * If there is only one dependence in "deps" and if that dependence
620 * is single-valued, then obviously there can be no reuse, so we skip
623 * We currently assume that none of the accesses has an extended_relation.
625 static void detect_reuse(PDG
*pdg
, std::vector
<pdg::dependence
*> &deps
)
627 add_reuse_data data
= { pdg
};
631 if (deps
.size() == 1 &&
632 isl_map_is_single_valued(deps
[0]->relation
->map
))
635 for (int i
= 0; i
< deps
.size(); ++i
) {
642 assert(!deps
[i
]->extended_relation
);
644 if (deps
[i
]->controlled_relation
) {
645 local
= deps
[i
]->controlled_relation
->get_isl_map();
646 len
= set_local_control_name(buf
, sizeof(buf
), deps
[i
]);
647 local
= remove_foreign_controls(local
, buf
, len
);
649 local
= deps
[i
]->relation
->get_isl_map();
650 local
= isl_map_reverse(local
);
653 ai
= isl_access_info_alloc(isl_map_copy(local
),
654 deps
[i
]->to_access
, &precedes_access
, deps
.size());
655 for (int j
= 0; j
< deps
.size(); ++j
) {
658 map
= isl_map_copy(local
);
660 map
= deps
[j
]->relation
->get_isl_map();
661 map
= isl_map_reverse(map
);
663 ai
= isl_access_info_add_source(ai
, map
,
664 1, deps
[j
]->to_access
);
666 flow
= isl_access_info_compute_flow(ai
);
667 isl_flow_foreach(flow
, &add_reuse
, &data
);
668 first
= isl_map_domain(isl_flow_get_no_source(flow
, 1));
671 rel
= deps
[i
]->relation
;
672 if (deps
[i
]->controlled_relation
) {
673 pdg::IslMap
*cr
= deps
[i
]->controlled_relation
;
674 cr
->map
= isl_map_intersect_range(cr
->map
, first
);
675 isl_map_free(rel
->map
);
676 rel
->map
= remove_all_controls(isl_map_copy(cr
->map
));
678 rel
->map
= isl_map_intersect_range(rel
->map
, first
);
684 /* Has this dependence been created during the detection
685 * of multiple assignments? In particular, does this dependence
686 * propagate the values in the source.
688 static bool is_multi_assignment_propagation(pdg::dependence
*dep
)
690 return dep
->to_access
== dep
->from_access
&&
691 dep
->to_access
->type
== pdg::access::write
;
694 typedef std::pair
<pdg::access
*, pdg::node
*> an_pair
;
695 typedef std::pair
<int, an_pair
> nan_triple
;
697 struct nan_triple_cmp
{
698 bool operator()(nan_triple t1
, nan_triple t2
) const {
699 if (t1
.first
!= t2
.first
)
700 return t1
.first
< t2
.first
;
701 if (t1
.second
.first
->nr
!= t2
.second
.first
->nr
)
702 return t1
.second
.first
->nr
< t2
.second
.first
->nr
;
703 return t1
.second
.second
->nr
< t2
.second
.second
->nr
;
707 typedef std::map
<nan_triple
, std::vector
<pdg::dependence
*>, nan_triple_cmp
>
710 /* Detect reuse of the same value (originating from the same
711 * write access) within a node and split the corresponding dependence
712 * into part of the original dependences that use the value for
713 * the first time and internal dependences that propagate the value.
715 * If a scheduling is applied that changes the order of the iterations
716 * within a given node, then this scheduling should be performed
717 * before the reuse detection.
719 * We first collect the dependences that originate in a given access
720 * and end up in a given node and then process each such collection
721 * in turn, in an order that does not depend on pointer values.
722 * While collecting dependences, we skip those that correspond
723 * to the propagation of multiple assignments to the next potential
726 * Dependences that propagate data (those that have a dep->array)
727 * are treated separately from those that propagate control.
729 * If the user has turned off reuse detection, then we do nothing.
731 static void detect_reuse(PDG
*pdg
, struct pn_options
*options
)
733 nan2deps access_deps
;
734 nan2deps control_deps
;
735 nan2deps::iterator it
;
740 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
741 pdg::dependence
*dep
= pdg
->dependences
[i
];
742 if (dep
->type
== pdg::dependence::uninitialized
)
744 if (is_multi_assignment_propagation(dep
))
746 an_pair
p(dep
->from_access
, dep
->to
);
747 nan_triple
t(dep
->from
->nr
, p
);
749 access_deps
[t
].push_back(dep
);
751 control_deps
[t
].push_back(dep
);
754 for (it
= access_deps
.begin(); it
!= access_deps
.end(); ++it
)
755 detect_reuse(pdg
, it
->second
);
756 for (it
= control_deps
.begin(); it
!= control_deps
.end(); ++it
)
757 detect_reuse(pdg
, it
->second
);
760 /* isl_access_level_before function used in a context where the
761 * iteration domains live in a common space. We therefore just
762 * need to retun 2 * the dimension of this space, which is stored
763 * in *first (and *second).
765 static int common_space(void *first
, void *second
)
767 int depth
= *(int *) first
;
771 /* Assign dep to *user. This function is expected to be called
774 static int extract_dep(__isl_take isl_map
*dep
, int must
,
775 void *dep_user
, void *user
)
777 isl_map
**map_p
= (isl_map
**) user
;
784 /* Is the i-th parameter of "set" of the form __last_*
785 * but not of the form local_control*?
787 static bool is_foreign_control(__isl_keep isl_set
*set
, int i
,
788 const char *local_control
, size_t len
)
791 const char *prefix
= "__last_";
792 size_t prefix_len
= strlen(prefix
);
794 if (!isl_set_has_dim_id(set
, isl_dim_param
, i
))
796 name
= isl_set_get_dim_name(set
, isl_dim_param
, i
);
797 if (strncmp(name
, prefix
, prefix_len
))
799 return strncmp(name
, local_control
, len
) != 0;
802 /* Does "set" have any parameters of the form __last_*
803 * that are not of the form local_control*?
805 static __isl_give isl_set
*remove_foreign_controls(__isl_take isl_set
*set
,
806 const char *local_control
, size_t len
)
810 n_param
= isl_set_dim(set
, isl_dim_param
);
811 for (int i
= n_param
- 1; i
>= 0; --i
) {
812 if (!is_foreign_control(set
, i
, local_control
, len
))
814 set
= isl_set_project_out(set
, isl_dim_param
, i
, 1);
816 set
= isl_set_coalesce(set
);
821 /* Given a dependence such that the dependence relation
822 * is not injective, split the dependence into two parts,
823 * one that propagates the value from a potential source iteration
824 * to the next potential source iteration and one that sends
825 * the data from the final potential source iteration to the sink
828 * The dependence may either be a control dependence, propagating
829 * control variables, or a data dependence, in which case it has
830 * a controlled_relation and it is the uncontrolled relation that
833 * To obtain the last potential source iteration, we simply
834 * compute the lexicographic maximum of all potential source iterations.
836 * To obtain the dependence from one potential source iteration
837 * to the next potential source iteration, we apply
838 * dependence analysis on the dependence relation.
839 * In particular, we need a mapping from source iterations to
840 * the next source iteration associated to the same sink iteration,
841 * so we simply treat the original dependence relation as an access relation.
843 * The mapping to the next potential source should not have any controls.
844 * If the input dependence is a control dependence, then it is propagating
845 * control variables itself. If it is a data dependence, then we want
846 * to propagate values to the next potential source independently of
849 * The constraints on the controls for the dependence from the final
850 * potential source iteration should be the same as those on the
851 * original relation, when seen from the destination node.
853 * We currently assume that there is no extended relation associated
856 static void split_multi_assignment(PDG
*pdg
, pdg::dependence
*dep
)
860 isl_map
*next
= NULL
;
864 pdg::dependence
*next_dep
;
868 assert(!dep
->extended_relation
);
870 len
= set_local_control_name(buf
, sizeof(buf
), dep
);
872 depth
= isl_map_dim(dep
->relation
->map
, isl_dim_in
);
873 ai
= isl_access_info_alloc(isl_map_copy(dep
->relation
->map
),
874 &depth
, &common_space
, 1);
875 ai
= isl_access_info_add_source(ai
, isl_map_copy(dep
->relation
->map
),
877 flow
= isl_access_info_compute_flow(ai
);
878 isl_flow_foreach(flow
, &extract_dep
, &next
);
881 last
= isl_map_copy(dep
->relation
->map
);
882 last
= isl_map_reverse(isl_map_lexmax(isl_map_reverse(last
)));
884 next_dep
= new pdg::dependence
;
885 next_dep
->array
= dep
->array
;
886 next_dep
->from_controls
= dep
->from_controls
;
887 next_dep
->to_controls
= dep
->to_controls
;
888 next_dep
->type
= dep
->type
;
889 next_dep
->from
= dep
->from
;
890 next_dep
->to
= dep
->from
;
891 next_dep
->from_access
= dep
->from_access
;
892 next_dep
->to_access
= dep
->from_access
;
893 next_dep
->relation
= new pdg::IslMap(next
);
894 pdg
->dependences
.push_back(next_dep
);
896 dep
->relation
->map
= isl_map_intersect(dep
->relation
->map
, last
);
897 if (dep
->controlled_relation
)
898 dep
->controlled_relation
->map
=
899 isl_map_intersect_range(isl_map_copy(dep
->relation
->map
),
900 isl_map_range(dep
->controlled_relation
->map
));
903 /* If any sink iteration has more than one potential source
904 * iteration, we split off the propagation of the data on the from
905 * node from the transfer of the data to the to node.
907 * We only perform this operation here on (data) dependences
908 * with a "controlled_relation". The corresponding control dependence
909 * has already been handled from within extract_control_dependence.
910 * Other data dependences have an exact dependence relation and
911 * can therefore not exhibit multiple assignments.
913 static void split_multi_assignment(PDG
*pdg
)
915 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
916 pdg::dependence
*dep
= pdg
->dependences
[i
];
917 if (!dep
->controlled_relation
)
919 if (isl_map_is_injective(dep
->relation
->map
))
921 split_multi_assignment(pdg
, dep
);
925 /* Does "dep" have any parameters of the form __last_*?
927 static bool has_controls(__isl_keep isl_map
*dep
)
930 const char *prefix
= "__last_";
931 size_t prefix_len
= strlen(prefix
);
933 n_param
= isl_map_dim(dep
, isl_dim_param
);
934 for (int i
= 0; i
< n_param
; ++i
) {
937 if (!isl_map_has_dim_id(dep
, isl_dim_param
, i
))
939 name
= isl_map_get_dim_name(dep
, isl_dim_param
, i
);
940 if (!strncmp(name
, prefix
, prefix_len
))
947 /* Is the i-th parameter of "map" of the form local_control*?
948 * "len" is the length of "local_control".
950 static bool is_local_control(__isl_keep isl_map
*map
, int i
,
951 const char *local_control
, size_t len
)
955 if (!isl_map_has_dim_id(map
, isl_dim_param
, i
))
957 name
= isl_map_get_dim_name(map
, isl_dim_param
, i
);
958 return strncmp(name
, local_control
, len
) == 0;
961 /* Does "dep" have any parameters of the form __last_*
962 * that are not of the form local_control*?
964 static bool has_foreign_controls(__isl_keep isl_map
*dep
,
965 const char *local_control
, size_t len
)
969 n_param
= isl_map_dim(dep
, isl_dim_param
);
970 for (int i
= 0; i
< n_param
; ++i
)
971 if (is_foreign_control(dep
, i
, local_control
, len
))
977 /* Does "dep" have any parameters of the form local_control*?
978 * "len" is the length of "local_control".
980 static bool has_local_controls(__isl_keep isl_map
*dep
,
981 const char *local_control
, size_t len
)
985 n_param
= isl_map_dim(dep
, isl_dim_param
);
986 for (int i
= 0; i
< n_param
; ++i
)
987 if (is_local_control(dep
, i
, local_control
, len
))
993 /* Extract a control dependence from a dependence with a controlled_relation.
994 * The control dependence transfers the values of the control variables
995 * that correspond to the given dependence, i.e., those that correspond
996 * to the from and to access of the dependence.
997 * We therefore don't need to do anything if the controlled_relation
998 * only involves foreign controls.
1000 * from_controls and to_controls are set from the local control variables
1001 * in dep->controlled_relation.
1003 * The uncontrolled dependence relation may not be injective,
1004 * in which case the initial dependence relation on the control
1005 * dependence is also non-injective. In such cases, the control
1006 * dependence is split using split_multi_assignment in two parts,
1007 * one that propagate the current value of the controls to the next
1008 * iteration of the source and one that sends the final values to the sink.
1009 * The data dependence is split later on.
1011 static void extract_control_dependence(PDG
*pdg
, pdg::dependence
*dep
)
1013 pdg::dependence
*control
;
1019 len
= set_local_control_name(buf
, sizeof(buf
), dep
);
1020 rel
= dep
->controlled_relation
->map
;
1021 if (!has_local_controls(rel
, buf
, len
))
1023 n_param
= isl_map_dim(rel
, isl_dim_param
);
1025 control
= new pdg::dependence
;
1026 control
->type
= dep
->type
;
1027 control
->from
= dep
->from
;
1028 control
->to
= dep
->to
;
1029 control
->from_access
= dep
->from_access
;
1030 control
->to_access
= dep
->to_access
;
1031 control
->relation
= new pdg::IslMap(dep
->relation
->get_isl_map());
1032 for (int i
= 0; i
< n_param
; ++i
) {
1034 if (!isl_map_has_dim_id(rel
, isl_dim_param
, i
))
1036 name
= isl_map_get_dim_name(rel
, isl_dim_param
, i
);
1037 if (strncmp(name
, buf
, len
) != 0)
1039 control
->from_controls
.push_back(new str(name
));
1040 control
->to_controls
.push_back(new str(name
));
1042 pdg
->dependences
.push_back(control
);
1044 if (isl_map_is_injective(control
->relation
->map
))
1046 split_multi_assignment(pdg
, control
);
1049 /* Extract a control dependence from each dependence with a controlled_relation.
1051 static void extract_control_dependences(PDG
*pdg
)
1053 int n_dep
= pdg
->dependences
.size();
1055 for (int i
= 0; i
< n_dep
; ++i
) {
1056 pdg::dependence
*dep
= pdg
->dependences
[i
];
1057 if (!dep
->controlled_relation
)
1059 extract_control_dependence(pdg
, dep
);
1063 /* Split off the communication of data, along with the corresponding
1064 * controls, from selecting the data based on other controls.
1065 * "dep" is modified to only refer to the controls that correspond
1066 * to the given from and to access and an extra wire is introduced
1067 * to select the data.
1068 * If "dep" corresponds to a propagation from one potential source
1069 * to the next potential source, then it already only refers to
1070 * "local" controls. We handle this case separately so that we
1071 * don't have to add a special case to set_local_control_name
1072 * for setting up the right name for local controls on such dependences.
1074 * A new virtual access is created to act as the target of the modified
1075 * communication dependence and the source of the selection dependence.
1076 * If the input "dep" did not refer to the corresponding controls,
1077 * then the output "dep" does not refer to any control and
1078 * controlled_relation is cleared.
1080 static void split_wire(PDG
*pdg
, pdg::dependence
*dep
)
1086 pdg::dependence
*wire
;
1087 pdg::access
*access
;
1091 if (is_multi_assignment_propagation(dep
))
1094 assert(!dep
->extended_relation
);
1096 rel
= dep
->controlled_relation
->map
;
1097 len
= set_local_control_name(buf
, sizeof(buf
), dep
);
1099 if (!has_foreign_controls(rel
, buf
, len
))
1102 space
= isl_map_get_space(dep
->controlled_relation
->map
);
1103 space
= isl_space_range(space
);
1104 space
= isl_space_map_from_set(space
);
1105 id
= isl_map_identity(space
);
1106 dom
= isl_map_range(isl_map_copy(dep
->controlled_relation
->map
));
1107 id
= isl_map_intersect_domain(id
, dom
);
1109 access
= new pdg::access
;
1110 access
->array
= dep
->to_access
->array
;
1111 access
->nr
= dep
->to
->statement
->accesses
.size();
1112 dep
->to
->statement
->accesses
.push_back(access
);
1114 wire
= new pdg::dependence
;
1115 wire
->array
= dep
->array
;
1116 wire
->type
= pdg::dependence::pn_wire
;
1117 wire
->from
= dep
->to
;
1119 wire
->from_access
= access
;
1120 wire
->to_access
= dep
->to_access
;
1121 wire
->relation
= new pdg::IslMap(id
);
1122 pdg
->dependences
.push_back(wire
);
1124 dep
->to_access
= access
;
1125 dep
->controlled_relation
->map
= remove_foreign_controls(rel
, buf
, len
);
1126 if (!has_controls(dep
->controlled_relation
->map
)) {
1127 delete dep
->controlled_relation
;
1128 dep
->controlled_relation
= NULL
;
1132 /* If the dependence involves "foreign" controls, i.e., controls
1133 * that correspond to other dependences, then we split off
1134 * the communication of the data (along with the "local" controls)
1135 * from the selection of the data based on the foreign controls.
1137 static void split_wires(PDG
*pdg
)
1139 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1140 pdg::dependence
*dep
= pdg
->dependences
[i
];
1141 if (!dep
->controlled_relation
)
1143 split_wire(pdg
, dep
);
1147 static void schedule(PDG
*pdg
, struct pn_options
*options
)
1149 translate(pdg
, options
->move
);
1152 /* Compute the size of the dependence "dep" with scheduled dependence
1153 * relation "dep_map".
1155 * If "dep" is of type pn_union, then it may contains parts that read
1156 * from the channel in the same iteration. We therefore need to recombine
1157 * the dependence relations of those parts, but separate them apart.
1158 * In particular, we add an extra inner dimension with a fixed value
1159 * corresponding to the index of the dependence.
1161 static size::enumerator
*compute_size(pdg::PDG
*pdg
, pdg::dependence
*dep
,
1162 __isl_take isl_map
*dep_map
, pn_options
*options
)
1164 dep_map
= isl_map_copy(dep_map
);
1165 if (dep
->type
== pdg::dependence::pn_union
) {
1166 isl_space
*space
= isl_map_get_space(dep_map
);
1169 n_in
= isl_space_dim(space
, isl_dim_in
);
1170 n_out
= isl_space_dim(space
, isl_dim_out
);
1171 space
= isl_space_add_dims(space
, isl_dim_in
, 1);
1172 space
= isl_space_add_dims(space
, isl_dim_out
, 1);
1173 isl_map_free(dep_map
);
1174 dep_map
= isl_map_empty(space
);
1175 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1176 pdg::dependence
*part
= pdg
->dependences
[i
];
1179 if (part
->type
!= pdg::dependence::pn_part
)
1181 if (part
->container
!= dep
)
1183 map_i
= part
->relation
->get_isl_map();
1184 map_i
= isl_map_intersect_params(map_i
,
1185 pdg
->get_context_isl_set());
1186 map_i
= schedule_dependence(pdg
, dep
, map_i
);
1187 map_i
= isl_map_add_dims(map_i
, isl_dim_in
, 1);
1188 map_i
= isl_map_add_dims(map_i
, isl_dim_out
, 1);
1189 map_i
= isl_map_fix_si(map_i
, isl_dim_in
, n_in
, i
);
1190 map_i
= isl_map_fix_si(map_i
, isl_dim_out
, n_out
, i
);
1191 dep_map
= isl_map_union(dep_map
, map_i
);
1194 return selfloop_size(pdg
, dep_map
, options
->size
);
1197 static bool determine_dependence_properties(PDG
*pdg
, pdg::dependence
*dep
,
1198 bool evaluate
, bool scheduled
, struct pn_options
*options
)
1200 if (dep
->type
== pdg::dependence::uninitialized
) {
1202 "access to uninitialized data from %s on line %d\n",
1203 dep
->array
->name
->s
.c_str(), dep
->to
->statement
->line
);
1204 dep
->relation
->Dump(stderr
);
1207 pdg::IslMap
*rel
= dep
->relation
;
1208 if (dep
->type
== pdg::dependence::pn_part
||
1209 dep
->type
== pdg::dependence::pn_wire
) {
1210 dep
->reordering
= 0;
1211 dep
->multiplicity
= 0;
1212 dep
->size
= new pdg::enumerator(0);
1213 dep
->value_size
= new integer(0);
1217 isl_map
*dep_map
= rel
->get_isl_map();
1218 dep_map
= isl_map_intersect_params(dep_map
, pdg
->get_context_isl_set());
1219 dep
->reordering
= isl_map_is_reordering(dep_map
);
1220 dep
->multiplicity
= 0;
1221 if (!options
->reuse
)
1222 dep
->multiplicity
= isl_map_has_multiplicity(dep_map
);
1223 if (dep
->reordering
|| dep
->multiplicity
) {
1224 isl_map_free(dep_map
);
1228 if (dep
->to
!= dep
->from
&& !scheduled
) {
1229 schedule(pdg
, options
);
1233 if (dep
->to
!= dep
->from
)
1234 dep_map
= schedule_dependence(pdg
, dep
, dep_map
);
1236 if (!dep
->controlled_relation
&& isl_is_consecutive_loop(dep_map
)) {
1237 dep
->size
= new pdg::enumerator(1);
1238 dep
->value_size
= new integer(1);
1239 if (dep
->from_access
== dep
->to_access
&&
1240 dep
->to_access
->type
!= pdg::access::write
&&
1241 is_consecutive_dep(pdg
, dep
, dep_map
))
1242 dep
->type
= pdg::dependence::pn_hold
;
1244 size::enumerator
*size
= NULL
;
1245 if (options
->shift_register
&& dep
->to
== dep
->from
&&
1246 !dep
->controlled_relation
) {
1247 isl_set
*ref
= dep
->to
->source
->get_isl_set();
1248 size
= shift_register_size(pdg
, ref
,
1249 isl_map_copy(dep_map
));
1252 dep
->type
= pdg::dependence::pn_shift
;
1254 size
= compute_size(pdg
, dep
, dep_map
, options
);
1258 dep
->value_size
= size
->evaluate();
1263 isl_map_free(dep_map
);
1268 static void determine_dependence_properties(PDG
*pdg
, bool evaluate
,
1269 bool scheduled
, struct pn_options
*options
)
1271 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1272 pdg::dependence
*dep
= pdg
->dependences
[i
];
1273 scheduled
= determine_dependence_properties(pdg
, dep
, evaluate
,
1274 scheduled
, options
);
1278 /* Can we merge "dep1" and "dep2"?
1281 * - do they connect the same from_access to the same to node?
1282 * - is there no reordering in the combined dependence relation?
1284 static bool can_merge(PDG
*pdg
, pdg::dependence
*dep1
, pdg::dependence
*dep2
)
1286 pdg::IslMap
*rel1
= dep1
->relation
;
1287 pdg::IslMap
*rel2
= dep2
->relation
;
1291 if (dep1
->to
!= dep2
->to
)
1293 if (dep1
->from_access
!= dep2
->from_access
)
1295 dep_rel
= isl_map_union(rel1
->get_isl_map(), rel2
->get_isl_map());
1296 dep_rel
= isl_map_intersect_params(dep_rel
, pdg
->get_context_isl_set());
1298 reordering
= isl_map_is_reordering(dep_rel
);
1300 isl_map_free(dep_rel
);
1305 /* Combine the dependences "dep1" and "dep2" into a single pn_union
1306 * dependences with the union dependence relation.
1308 * If "dep2" is already a pn_union, we simply extend it.
1309 * Otherwise, we create a new pn_union modeled after "dep2",
1310 * add it to the list of dependences and turn "dep2" into a pn_part.
1311 * "dep1" is turned into a pn_part in any case.
1313 static void merge_dependences(PDG
*pdg
, pdg::dependence
*dep1
,
1314 pdg::dependence
*dep2
)
1316 pdg::dependence
*dep_union
;
1318 if (dep2
->type
== pdg::dependence::pn_union
)
1322 dep_union
= new pdg::dependence
;
1323 dep_union
->from
= dep2
->from
;
1324 dep_union
->to
= dep2
->to
;
1325 dep_union
->from_access
= dep2
->from_access
;
1326 dep_union
->to_access
= NULL
;
1327 dep_union
->array
= dep2
->array
;
1328 dep_union
->type
= pdg::dependence::pn_union
;
1329 rel
= dep2
->relation
;
1330 dep_union
->relation
= new pdg::IslMap(rel
->get_isl_map());
1331 pdg
->dependences
.push_back(dep_union
);
1333 dep2
->type
= pdg::dependence::pn_part
;
1334 dep2
->container
= dep_union
;
1337 dep1
->type
= pdg::dependence::pn_part
;
1338 dep1
->container
= dep_union
;
1340 dep_union
->relation
->map
= isl_map_union(dep_union
->relation
->map
,
1341 dep1
->relation
->get_isl_map());
1344 /* Try and merge dependences between a given pair of (distinct) nodes.
1345 * A merge is performed only if it the resulting merged dependence
1346 * does not exhibit any reordering.
1347 * The merging needs to be applied before the buffer size computation
1348 * as the buffer sizes are computed on the merged (pn_union) dependences.
1350 * We run through all original dependences and check whether it can
1351 * be combined with any later dependences. If so, we turn the two
1352 * dependences into "pn_part"s and add an extra pn_union dependence
1353 * that combines the two. The inner loop starts from the latest
1354 * dependence so that we compare with any previously added pn_union
1355 * dependences first. If such a previously add pn_union can be combined
1356 * with the current dependence, it is simply extended to include the
1357 * current dependence.
1359 * We currently don't allow any merging of dependences involving control.
1361 * If the user has turned off merging, the we do nothing.
1362 * We do the same if the user has turned off reuse detection, as there
1363 * may in this case be dependences with multiplicity. It is not clear
1364 * if we would want to merge such edges.
1366 static void merge_dependences(PDG
*pdg
, struct pn_options
*options
)
1370 if (!options
->reuse
)
1372 if (!options
->merge
)
1375 n_dep
= pdg
->dependences
.size();
1376 for (int i
= 0; i
< n_dep
; ++i
) {
1377 pdg::dependence
*dep_i
= pdg
->dependences
[i
];
1378 if (dep_i
->type
!= pdg::dependence::flow
)
1380 if (dep_i
->to
== dep_i
->from
)
1382 if (dep_i
->controlled_relation
)
1385 for (int j
= pdg
->dependences
.size() - 1; j
> i
; --j
) {
1386 pdg::dependence
*dep_j
= pdg
->dependences
[j
];
1388 if (dep_j
->type
!= pdg::dependence::flow
&&
1389 dep_j
->type
!= pdg::dependence::pn_union
)
1391 if (dep_j
->controlled_relation
)
1393 if (!can_merge(pdg
, dep_i
, dep_j
))
1396 merge_dependences(pdg
, dep_i
, dep_j
);
1401 /* Is "access" one of the filter accesses of "node"?
1403 static bool is_filter_access(pdg::node
*node
, pdg::access
*access
)
1405 for (int i
= 0; i
< node
->filters
.size(); ++i
) {
1406 pdg::call_or_access
*coa
;
1408 coa
= node
->filters
[i
];
1409 assert(coa
->type
== pdg::call_or_access::t_access
);
1410 if (access
== coa
->access
)
1416 /* Given the (overapproximation of the) dependence relation "dep_rel",
1417 * check whether "to" and "from" represent the same filter, i.e.,
1418 * whether they refer to the same array element written at the same
1421 * We apply the mappings from source/sink iterations
1422 * to filter access relations to both sides of "dep_rel".
1423 * If the result is a subset of the identity relation, then
1424 * we know that the filter element accessed by the source is
1425 * exactly the same as the filter element accessed by
1426 * the courresponding sink(s).
1428 * If we were unable to find the source for one or both of the two filters,
1429 * then the filter access relations live in different spaces and
1430 * the computed relation cannot be a subset of the identity relation.
1432 static bool is_same_filter(pdg::access
*to
, pdg::access
*from
,
1433 __isl_keep isl_map
*dep_rel
)
1435 isl_union_map
*from_access
;
1436 isl_union_map
*to_access
;
1437 isl_union_map
*test
;
1438 isl_union_map
*univ
;
1442 if (to
->array
!= from
->array
)
1445 from_access
= from
->extract_access_map();
1446 to_access
= to
->extract_access_map();
1447 test
= isl_union_map_from_map(isl_map_copy(dep_rel
));
1448 test
= isl_union_map_apply_domain(test
, from_access
);
1449 test
= isl_union_map_apply_range(test
, to_access
);
1450 univ
= isl_union_map_universe(isl_union_map_copy(test
));
1451 id
= isl_union_set_identity(isl_union_map_domain(univ
));
1452 same
= isl_union_map_is_subset(test
, id
);
1453 isl_union_map_free(test
);
1454 isl_union_map_free(id
);
1459 /* Insert equalities between source filters and sink filters
1460 * of dependences, whenever we are able to detect that they are the same.
1462 * We first introduce the constraints on the sink filters in the dependence
1463 * relation and we add unconstrained variables for the source filters.
1464 * Then, for each of the sink filters, we check if we can find
1465 * any source filter that has the same value on the other side
1466 * of the dependence. If so, we can keep the constraints on this
1467 * filter value and we add an equality between the source filter
1468 * and the sink filter so that these constraints will also be
1469 * applied to the source filter.
1470 * Otherwise, we eliminate the sink filter value from the constraints.
1472 static void insert_filter_constraints(pdg::dependence
*dep
)
1481 dep_rel
= isl_map_copy(dep
->relation
->map
);
1482 n_in
= isl_map_dim(dep_rel
, isl_dim_in
);
1483 n_out
= isl_map_dim(dep_rel
, isl_dim_out
);
1485 space
= isl_set_get_space(dep
->from
->source
->set
);
1486 map
= isl_set_unwrap(isl_set_universe(space
));
1487 map
= isl_map_reverse(isl_map_domain_map(map
));
1488 dep_rel
= isl_map_apply_domain(dep_rel
, map
);
1489 map
= isl_set_unwrap(dep
->to
->source
->get_isl_set());
1490 map
= isl_map_reverse(isl_map_domain_map(map
));
1491 dep_rel
= isl_map_apply_range(dep_rel
, map
);
1493 for (int i
= 0; i
< dep
->to
->filters
.size(); ++i
) {
1494 pdg::call_or_access
*coa_i
;
1495 pdg::access
*access_i
;
1498 coa_i
= dep
->to
->filters
[i
];
1499 assert(coa_i
->type
== pdg::call_or_access::t_access
);
1500 access_i
= coa_i
->access
;
1502 for (int j
= 0; j
< dep
->from
->filters
.size(); ++j
) {
1503 pdg::call_or_access
*coa_j
;
1504 pdg::access
*access_j
;
1506 coa_j
= dep
->from
->filters
[j
];
1507 assert(coa_j
->type
== pdg::call_or_access::t_access
);
1508 access_j
= coa_j
->access
;
1510 if (!is_same_filter(access_i
, access_j
,
1511 dep
->relation
->map
))
1513 dep_rel
= isl_map_equate(dep_rel
, isl_dim_in
, n_in
+ j
,
1514 isl_dim_out
, n_out
+ i
);
1520 dep_rel
= isl_map_eliminate(dep_rel
, isl_dim_out
,
1525 isl_map_free(dep
->relation
->map
);
1526 dep
->relation
->map
= dep_rel
;
1528 isl_map_free(dep_rel
);
1531 /* Insert equalities between source filters and sink filters
1532 * of dependences, whenever we are able to detect that they are the same.
1534 * We currently don't introduce any such equalities in dependences
1535 * that involve control variables. Both these control variables and
1536 * the filters will be treated as "dynamic controls" in pn2adg
1537 * and it probably needs to be tweaked to be able to handle two sets
1538 * of dynamic controls.
1540 static void insert_filter_constraints(PDG
*pdg
)
1542 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
1543 pdg::dependence
*dep
= pdg
->dependences
[i
];
1545 if (dep
->type
== pdg::dependence::uninitialized
)
1547 if (dep
->to
== dep
->from
)
1549 if (dep
->controlled_relation
)
1551 if (dep
->to
->filters
.size() == 0)
1553 if (dep
->from
->filters
.size() == 0)
1555 if (is_filter_access(dep
->to
, dep
->to_access
))
1557 insert_filter_constraints(dep
);
1561 int main(int argc
, char * argv
[])
1564 FILE *in
= stdin
, *out
= stdout
;
1567 struct pn_options
*options
= pn_options_new_with_defaults();
1568 bool evaluate
= true;
1570 argc
= pn_options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
1572 if (!options
->reuse
)
1573 options
->propagate
= 0;
1575 if (options
->input
&& strcmp(options
->input
, "-")) {
1576 in
= fopen(options
->input
, "r");
1578 if (!options
->output
) {
1579 int len
= strlen(options
->input
);
1580 if (len
> 5 && !strcmp(options
->input
+len
-5, ".yaml"))
1582 options
->output
= (char *)malloc(len
+9+1);
1583 strncpy(options
->output
, options
->input
, len
);
1584 strcpy(options
->output
+len
, options
->reuse
? "_pn.yaml" : "_cpn.yaml");
1588 ctx
= isl_ctx_alloc_with_options(&pn_options_args
, options
);
1589 pdg
= PDG::Load(in
, ctx
);
1591 int nparam
= pdg
->params
.size();
1593 if (options
->propagate
)
1594 copy_propagation(pdg
);
1596 compute_filter_sources(pdg
);
1597 for (int i
= 0; i
< pdg
->arrays
.size(); ++i
)
1598 find_deps(pdg
, pdg
->arrays
[i
], flow
);
1599 extract_control_dependences(pdg
);
1601 for (int i
= 0; i
< nparam
; ++i
)
1602 if (!pdg
->params
[i
]->value
) {
1608 if (options
->reschedule
) {
1609 common_dimension(pdg
);
1612 set_schedule_from_prefix(pdg
);
1616 detect_reuse(pdg
, options
);
1617 split_multi_assignment(pdg
);
1619 merge_dependences(pdg
, options
);
1620 determine_dependence_properties(pdg
, evaluate
, translated
, options
);
1621 insert_filter_constraints(pdg
);
1623 pdg
->add_history_line("pn", argc
, argv
);
1625 if (options
->output
&& strcmp(options
->output
, "-")) {
1626 out
= fopen(options
->output
, "w");