9 #include <isl/local_space.h>
14 #include <isl/constraint.h>
15 #include <isl/schedule.h>
16 #include <isl/schedule_node.h>
17 #include <isl/union_set.h>
18 #include <isl/union_map.h>
22 #include "c2pdg_options.h"
24 const char dot_yaml
[] = ".yaml";
26 static __isl_give isl_map
*isl_map_equal_dims(__isl_take isl_space
*dim
,
27 enum isl_dim_type type1
, int pos1
, enum isl_dim_type type2
, int pos2
)
29 isl_map
*map
= isl_map_universe(dim
);
30 return isl_map_equate(map
, type1
, pos1
, type2
, pos2
);
33 static __isl_give isl_map
*isl_map_opposite_dims(__isl_take isl_space
*dim
,
34 enum isl_dim_type type1
, int pos1
, enum isl_dim_type type2
, int pos2
)
36 isl_map
*map
= isl_map_universe(dim
);
37 return isl_map_oppose(map
, type1
, pos1
, type2
, pos2
);
40 static pdg::call_or_access
*convert_expr(pdg::PDG
*pdg
,
41 pdg::statement
*stat
, struct pet_expr
*expr
,
42 std::map
<isl_id
*, pdg::array
*> &id2array
, __isl_keep isl_map
*trans
);
44 /* Convert the access pet_expr to a pdg::access and return it.
45 * We assume that the pet_expr accesses data in a single space
46 * (in particular, we do not support accesses to different fields
47 * of a struct) and that it is either a write or a read (and not both).
48 * The pdg::access is also added to the list of accesses in "stat".
49 * The pointer to the pdg::array is taken from "id2array" based
50 * on the tuple id on the access relation.
52 * The domain of the access relation is transformed using "trans".
53 * If the access has any arguments then the domain of the access relation
54 * is a wrapped mapping from the iteration space to the space of
55 * argument values. We only need to change the domain of this wrapped
56 * mapping, so we extend the input transformation with an identity mapping
57 * on the space of argument values.
59 static pdg::access
*extract_access(pdg::PDG
*pdg
, pdg::statement
*stat
,
60 struct pet_expr
*expr
, std::map
<isl_id
*, pdg::array
*> &id2array
,
61 __isl_keep isl_map
*trans
)
63 pdg::access
*access
= new pdg::access
;
71 n
= pet_expr_get_n_arg(expr
);
72 for (int i
= 0; i
< n
; ++i
) {
73 pdg::call_or_access
*coa
;
75 arg
= pet_expr_get_arg(expr
, i
);
76 coa
= convert_expr(pdg
, stat
, arg
, id2array
, trans
);
78 access
->nested
.push_back(coa
);
81 if (pet_expr_access_is_write(expr
)) {
82 access
->type
= pdg::access::write
;
83 umap
= pet_expr_access_get_dependent_may_write(expr
);
85 access
->type
= pdg::access::read
;
86 umap
= pet_expr_access_get_dependent_may_read(expr
);
89 assert(isl_union_map_n_map(umap
) == 1);
91 map
= isl_map_from_union_map(umap
);
92 trans
= isl_map_copy(trans
);
94 dim
= isl_space_domain(isl_map_get_space(map
));
95 if (!isl_space_is_wrapping(dim
))
99 dim
= isl_space_unwrap(dim
);
100 dim
= isl_space_range(dim
);
101 dim
= isl_space_map_from_set(dim
);
102 id
= isl_map_identity(dim
);
103 trans
= isl_map_product(trans
, id
);
106 map
= isl_map_apply_domain(map
, trans
);
107 if (isl_map_has_tuple_id(map
, isl_dim_out
))
108 id
= isl_map_get_tuple_id(map
, isl_dim_out
);
109 n_index
= isl_map_dim(map
, isl_dim_out
);
110 for (int i
= n_index
- 1; i
>= 0; --i
)
111 if (!isl_map_involves_dims(map
, isl_dim_out
, i
, 1))
112 map
= isl_map_project_out(map
, isl_dim_out
, i
, 1);
116 map
= isl_map_set_tuple_id(map
, isl_dim_out
, id
);
117 access
->map
= new pdg::IslMap(map
);
119 if (!pet_expr_is_affine(expr
)) {
120 id
= pet_expr_access_get_id(expr
);
121 access
->array
= id2array
[id
];
125 stat
->accesses
.push_back(access
);
130 /* Convert the integer pet_expr to a pdg::access and return this pdg::access.
131 * The pdg::access is also added to the list of accesses in "stat".
133 * The domain of the access relation derived from the integer value
134 * is equal to the range space of "trans".
136 static pdg::access
*extract_access_from_int(pdg::PDG
*pdg
, pdg::statement
*stat
,
137 struct pet_expr
*expr
, __isl_keep isl_map
*trans
)
139 pdg::access
*access
= new pdg::access
;
145 access
->type
= pdg::access::read
;
147 v
= pet_expr_int_get_val(expr
);
148 space
= isl_space_range(isl_map_get_space(trans
));
149 aff
= isl_aff_val_on_domain(isl_local_space_from_space(space
), v
);
150 pa
= isl_pw_aff_from_aff(aff
);
152 access
->map
= new pdg::IslMap(isl_map_from_pw_aff(pa
));
154 stat
->accesses
.push_back(access
);
159 static pdg::call_or_access
*convert_expr(pdg::PDG
*pdg
,
160 pdg::statement
*stat
, struct pet_expr
*expr
,
161 std::map
<isl_id
*, pdg::array
*> &id2array
, __isl_keep isl_map
*trans
)
163 pdg::call_or_access
*coa
= new pdg::call_or_access
;
164 enum pet_expr_type type
;
166 type
= pet_expr_get_type(expr
);
167 if (type
== pet_expr_access
) {
168 coa
->type
= pdg::call_or_access::t_access
;
169 coa
->access
= extract_access(pdg
, stat
, expr
, id2array
, trans
);
170 } else if (type
== pet_expr_int
) {
171 coa
->type
= pdg::call_or_access::t_access
;
172 coa
->access
= extract_access_from_int(pdg
, stat
, expr
, trans
);
176 coa
->type
= pdg::call_or_access::t_call
;
177 coa
->call
= new pdg::function_call
;
179 if (type
== pet_expr_call
)
180 coa
->call
->name
= new str(pet_expr_call_get_name(expr
));
181 else if (type
== pet_expr_double
) {
182 char *s
= pet_expr_double_get_str(expr
);
183 coa
->call
->name
= new str(s
);
185 } else if (type
== pet_expr_op
&&
186 pet_expr_op_get_type(expr
) == pet_op_cond
)
187 coa
->call
->name
= new str("#test");
190 new str(pet_op_str(pet_expr_op_get_type(expr
)));
192 n
= pet_expr_get_n_arg(expr
);
193 for (int i
= 0; i
< n
; ++i
) {
194 pdg::call_or_access
*child
;
196 arg
= pet_expr_get_arg(expr
, i
);
197 child
= convert_expr(pdg
, stat
, arg
, id2array
, trans
);
199 coa
->call
->arguments
.push_back(child
);
206 static pdg::function_call
*extract_top_function(pdg::PDG
*pdg
,
207 pdg::statement
*stat
, struct pet_expr
*expr
,
208 std::map
<isl_id
*, pdg::array
*> &id2array
, __isl_keep isl_map
*trans
)
210 pdg::function_call
*call
;
211 pdg::call_or_access
*coa
= convert_expr(pdg
, stat
, expr
, id2array
, trans
);
213 if (coa
->type
== pdg::call_or_access::t_access
) {
214 call
= new pdg::function_call
;
215 call
->arguments
.push_back(coa
);
216 call
->name
= new str(string(""));
225 /* Extract a function call for the top-level function called from "tree".
226 * We currently assume the tree is an expression statement and
227 * extract the function call from the expression.
229 static pdg::function_call
*extract_top_function(pdg::PDG
*pdg
,
230 pdg::statement
*stat
, __isl_keep pet_tree
*tree
,
231 std::map
<isl_id
*, pdg::array
*> &id2array
, __isl_keep isl_map
*trans
)
233 pdg::function_call
*call
;
236 assert(pet_tree_get_type(tree
) == pet_tree_expr
);
237 expr
= pet_tree_expr_get_expr(tree
);
238 call
= extract_top_function(pdg
, stat
, expr
, id2array
, trans
);
244 /* For each of the filters ("arguments") of "stmt", check if the user
245 * has specified any bounds on the values of the corresponding array
246 * elements. If so, apply those bounds to the filter in the iteration
248 * Return the (possibly) restricted iteration domain.
250 static __isl_give isl_set
*apply_filter_bounds(__isl_take isl_set
*dom
,
251 struct pet_stmt
*stmt
, std::map
<isl_id
*, pdg::array
*> &id2array
)
255 if (!isl_set_is_wrapping(dom
))
258 map
= isl_set_unwrap(dom
);
260 for (int i
= 0; i
< stmt
->n_arg
; ++i
) {
263 pet_expr
*expr
= stmt
->args
[i
];
266 if (pet_expr_get_type(expr
) != pet_expr_access
)
269 id
= pet_expr_access_get_id(expr
);
270 array
= id2array
[id
];
273 if (!array
->value_bounds
)
275 bound
= array
->value_bounds
->get_isl_set();
276 bound
= isl_set_insert_dims(bound
, isl_dim_set
, 0, i
);
277 bound
= isl_set_add_dims(bound
, isl_dim_set
,
278 stmt
->n_arg
- (i
+ 1));
279 map
= isl_map_intersect_range(map
, bound
);
282 return isl_map_wrap(map
);
285 /* Given a filter access function encoded in "coa" corresponding to
286 * filter "pos" in "domain", extend the function to a filter access
287 * relation by exploiting the implications in "scop".
288 * In particular, if a statement depends on all previous iterations
289 * of some (other) statement (not) having executed, then it is marked
290 * by pet as only depending on the latest iteration of that statement.
291 * The implicit dependence on all previous iterations is encoded
292 * in the implications in "scop".
294 * If the given filter has a fixed filter value that matches the satisfied
295 * field of one of the implications and if that implication also references
296 * the same virtual array, then the corresponding extension is applied
297 * to the original filter access function to extend it to the complete
298 * filter access relation.
299 * Otherwise, we leave the filter access function untouched.
301 static void apply_implications(pdg::call_or_access
*coa
, struct pet_scop
*scop
,
302 __isl_keep isl_set
*domain
, int pos
)
308 int is_int
, satisfied
;
310 if (scop
->n_implication
== 0)
313 ext_domain
= isl_set_unwrap(isl_set_copy(domain
));
314 v
= isl_map_plain_get_val_if_fixed(ext_domain
, isl_dim_out
, pos
);
315 is_int
= isl_val_is_int(v
);
317 satisfied
= isl_val_get_num_si(v
);
319 isl_map_free(ext_domain
);
323 assert(coa
->type
== pdg::call_or_access::t_access
);
324 map
= coa
->access
->map
->map
;
325 map_id
= isl_map_get_tuple_id(map
, isl_dim_out
);
327 for (int i
= 0; i
< scop
->n_implication
; ++i
) {
328 struct pet_implication
*pi
;
331 pi
= scop
->implications
[i
];
333 if (pi
->satisfied
!= satisfied
)
335 pi_id
= isl_map_get_tuple_id(pi
->extension
, isl_dim_in
);
340 map
= isl_map_apply_range(map
, isl_map_copy(pi
->extension
));
344 coa
->access
->map
->map
= map
;
349 /* Does "expr" perform a (possibly compound) assignment?
351 static int is_assignment(__isl_keep pet_expr
*expr
)
356 if (pet_expr_get_type(expr
) != pet_expr_op
)
358 if (pet_expr_op_get_type(expr
) > pet_op_assign
)
360 arg
= pet_expr_get_arg(expr
, 0);
361 is_access
= pet_expr_get_type(arg
) == pet_expr_access
;
367 /* Does "expr" perform an increment or decrement operation?
369 static int is_inc_dec(__isl_keep pet_expr
*expr
)
374 if (pet_expr_get_type(expr
) != pet_expr_op
)
376 if (!pet_op_is_inc_dec(pet_expr_op_get_type(expr
)))
378 arg
= pet_expr_get_arg(expr
, 0);
379 is_access
= pet_expr_get_type(arg
) == pet_expr_access
;
385 /* Is "tree" an expression statement that satisfies "fn"?
387 static int is_expr_tree(__isl_keep pet_tree
*tree
,
388 int (*fn
)(__isl_keep pet_expr
*expr
))
393 if (pet_tree_get_type(tree
) != pet_tree_expr
)
395 expr
= pet_tree_expr_get_expr(tree
);
402 /* Does "tree" perform a (possibly compound) assignment?
404 static int is_assignment(__isl_keep pet_tree
*tree
)
406 return is_expr_tree(tree
, &is_assignment
);
409 /* Does "tree" perform an increment or decrement operation?
411 static int is_inc_dec(__isl_keep pet_tree
*tree
)
413 return is_expr_tree(tree
, &is_inc_dec
);
416 /* Find the position of the filter node among the children of "node"
417 * that contains elements in "space".
418 * It is assumed that there is exactly one such node.
420 static int get_filter_pos(__isl_keep isl_schedule_node
*node
,
421 __isl_keep isl_space
*space
)
425 n
= isl_schedule_node_n_children(node
);
426 for (i
= 0; i
< n
; ++i
) {
427 isl_schedule_node
*child
;
428 isl_union_set
*filter
;
432 child
= isl_schedule_node_get_child(node
, i
);
433 filter
= isl_schedule_node_filter_get_filter(child
);
434 set
= isl_union_set_extract_set(filter
, isl_space_copy(space
));
435 empty
= isl_set_is_empty(set
);
437 isl_union_set_free(filter
);
438 isl_schedule_node_free(child
);
447 /* Create and return a pdg::node correspondingto stmt.
448 * Since isa uses the "prefix" field in a pdg::node to represent the
449 * original schedule, we try to extract such a prefix from the schedule.
450 * If one of the original for loops had a decrement, then the corresponding
451 * part of the schedule will be of the form [i] -> [-i]. Since such
452 * an inverse cannot be represented by "prefix", we invert the corresponding
453 * dimension of the iteration domain instead, taking care to also
454 * change the domains of all access relations accordingly.
456 * If 'stmt" has any arguments, then stmt->domain is a wrapped map
457 * and the transformation on the iteration domain only applies
458 * to the domain of that map. We therefore need to combine that
459 * transformation with an identity mapping on the range before
460 * applying it to the domain.
461 * Any arguments found are also converted into filters on the node
462 * domain. The original filter access functions are extended to
463 * filter access relations using the implications in "scop".
465 static pdg::node
*extract_node(pdg::PDG
*pdg
, struct pet_scop
*scop
,
466 struct pet_stmt
*stmt
, std::map
<isl_id
*, pdg::array
*> &id2array
)
468 pdg::node
*node
= new pdg::node
;
469 pdg::statement
*stat
;
471 isl_space
*space
, *space_dom
;
473 isl_map
*trans
, *trans_dom
;
474 isl_schedule_node
*snode
;
475 isl_union_set
*universe
;
476 enum isl_schedule_node_type type
;
479 space
= isl_set_get_space(stmt
->domain
);
480 if (isl_space_is_wrapping(space
))
481 space
= isl_space_domain(isl_space_unwrap(space
));
482 space_dom
= isl_space_copy(space
);
483 trans
= isl_map_universe(isl_space_map_from_set(space
));
485 snode
= isl_schedule_get_root(scop
->schedule
);
486 space
= isl_space_copy(space_dom
);
487 universe
= isl_union_set_from_set(isl_set_universe(space
));
490 type
= isl_schedule_node_get_type(snode
);
491 assert(type
!= isl_schedule_node_error
);
492 if (type
== isl_schedule_node_leaf
)
494 if (type
== isl_schedule_node_band
) {
497 assert(isl_schedule_node_band_n_member(snode
) == 1);
499 isl_schedule_node_band_get_partial_schedule_union_map(
501 umap
= isl_union_map_intersect_domain(umap
,
502 isl_union_set_copy(universe
));
503 map
= isl_map_from_union_map(umap
);
504 space
= isl_map_get_space(map
);
505 test
= isl_map_equal_dims(space
, isl_dim_in
, i
,
507 if (isl_map_is_subset(map
, test
)) {
508 trans
= isl_map_equate(trans
, isl_dim_in
, i
,
512 space
= isl_map_get_space(map
);
513 test
= isl_map_opposite_dims(space
,
514 isl_dim_in
, i
, isl_dim_out
, 0);
515 assert(isl_map_is_subset(map
, test
));
516 trans
= isl_map_oppose(trans
, isl_dim_in
, i
,
521 node
->prefix
.push_back(-1);
524 if (type
== isl_schedule_node_sequence
||
525 type
== isl_schedule_node_set
) {
528 pos
= get_filter_pos(snode
, space_dom
);
529 node
->prefix
.push_back(pos
);
530 snode
= isl_schedule_node_child(snode
, pos
);
532 snode
= isl_schedule_node_child(snode
, 0);
535 isl_schedule_node_free(snode
);
536 isl_union_set_free(universe
);
538 dom
= isl_set_copy(stmt
->domain
);
539 trans_dom
= isl_map_copy(trans
);
540 if (isl_set_is_wrapping(dom
)) {
541 isl_space
*space
= isl_set_get_space(dom
);
543 space
= isl_space_range(isl_space_unwrap(space
));
544 id
= isl_map_identity(isl_space_map_from_set(space
));
545 trans_dom
= isl_map_product(trans_dom
, id
);
547 dom
= isl_set_apply(dom
, trans_dom
);
548 dom
= apply_filter_bounds(dom
, stmt
, id2array
);
549 node
->source
= new pdg::IslSet(dom
);
550 node
->name
= new str(isl_space_get_tuple_name(space_dom
, isl_dim_set
));
551 isl_space_free(space_dom
);
553 stat
= new pdg::statement
;
554 node
->statement
= stat
;
556 stat
->line
= pet_loc_get_line(stmt
->loc
);
558 for (int i
= 0; i
< stmt
->n_arg
; ++i
) {
559 pdg::call_or_access
*coa
;
560 coa
= convert_expr(pdg
, stat
, stmt
->args
[i
], id2array
, trans
);
561 apply_implications(coa
, scop
, node
->source
->set
, i
);
562 node
->filters
.push_back(coa
);
565 if (is_assignment(stmt
->body
)) {
567 pet_expr
*expr
, *arg
;
568 expr
= pet_tree_expr_get_expr(stmt
->body
);
569 if (pet_expr_op_get_type(expr
) != pet_op_assign
) {
570 arg
= pet_expr_get_arg(expr
, 0);
571 access
= extract_access(pdg
, stat
,
572 arg
, id2array
, trans
);
574 access
->type
= pdg::access::read
;
576 arg
= pet_expr_get_arg(expr
, 1);
577 stat
->top_function
= extract_top_function(pdg
, stat
,
578 arg
, id2array
, trans
);
580 arg
= pet_expr_get_arg(expr
, 0);
581 access
= extract_access(pdg
, stat
, arg
, id2array
, trans
);
583 stat
->top_outputs
.push_back(access
);
585 } else if (is_inc_dec(stmt
->body
)) {
587 pet_expr
*expr
, *arg
;
588 expr
= pet_tree_expr_get_expr(stmt
->body
);
589 arg
= pet_expr_get_arg(expr
, 0);
590 access
= extract_access(pdg
, stat
, arg
, id2array
, trans
);
591 access
->type
= pdg::access::read
;
592 stat
->top_function
= new pdg::function_call
;
593 stat
->top_function
->name
=
594 new str(pet_op_str(pet_expr_op_get_type(expr
)));
595 access
= extract_access(pdg
, stat
, arg
, id2array
, trans
);
596 stat
->top_outputs
.push_back(access
);
600 stat
->top_function
= extract_top_function(pdg
, stat
,
601 stmt
->body
, id2array
, trans
);
604 for (int i
= 0; i
< stat
->accesses
.size(); ++i
)
605 if (stat
->accesses
[i
]->type
== pdg::access::read
)
606 stat
->accesses
[i
]->nr
= nr
++;
607 for (int i
= 0; i
< stat
->accesses
.size(); ++i
)
608 if (stat
->accesses
[i
]->type
!= pdg::access::read
)
609 stat
->accesses
[i
]->nr
= nr
++;
616 /* Create and return a pdg::array corresponding to pa and add it
619 static pdg::array
*extract_array(pdg::PDG
*pdg
, struct pet_array
*pa
,
620 std::map
<isl_id
*, pdg::array
*> &id2array
)
622 isl_id
*id
= isl_set_get_tuple_id(pa
->extent
);
623 pdg::array
*array
= new pdg::array
;
624 int dim
= isl_set_dim(pa
->extent
, isl_dim_set
);
626 array
->name
= new str(isl_id_get_name(id
));
627 array
->element_type
= new str(pa
->element_type
);
628 for (int j
= 0; j
< dim
; ++j
) {
633 dim
= isl_set_get_space(pa
->extent
);
634 obj
= isl_aff_zero_on_domain(isl_local_space_from_space(dim
));
635 obj
= isl_aff_add_coefficient_si(obj
, isl_dim_in
, j
, 1);
636 v
= isl_set_max_val(pa
->extent
, obj
);
638 if (isl_val_is_int(v
))
639 array
->dims
.push_back(isl_val_get_num_si(v
) + 1);
641 array
->dims
.push_back(-1);
644 if (pa
->value_bounds
)
645 array
->value_bounds
=
646 new pdg::IslSet(isl_set_copy(pa
->value_bounds
));
647 array
->uniquely_defined
= pa
->uniquely_defined
;
649 id2array
[id
] = array
;
656 /* Assign a default value to parameter "p", which corresponds
657 * to the parameter at position "i" in scop->context.
659 * If the parameter appears in scop->context_value and if
660 * it has a fixed value, then use that value.
661 * Otherwise find the minimual value of "p" in scop->context.
662 * It there is no minimal value, then we currently leave p->value unset.
664 static void set_default_parameter_value(pdg::parameter
*p
,
665 __isl_keep isl_id
*id
, struct pet_scop
*scop
, int i
)
672 pos
= isl_set_find_dim_by_id(scop
->context_value
, isl_dim_param
, id
);
674 v
= isl_set_plain_get_val_if_fixed(scop
->context_value
,
676 if (isl_val_is_int(v
)) {
677 p
->value
= new integer(isl_val_get_num_si(v
));
684 space
= isl_set_get_space(scop
->context
);
685 obj
= isl_aff_zero_on_domain(isl_local_space_from_space(space
));
686 obj
= isl_aff_add_coefficient_si(obj
, isl_dim_param
, i
, 1);
687 v
= isl_set_min_val(scop
->context
, obj
);
689 if (isl_val_is_int(v
))
690 p
->value
= new integer(isl_val_get_num_si(v
));
696 static isl_bool
kill_array(__isl_keep isl_schedule_node
*node
,
700 /* Internal data structure for kill_array.
701 * "id2kill_stmt" maps the tuple id of the instance set of a kill statement
702 * to the corresponding pet_stmt.
703 * "id2array" maps the array identifier to the corresponding constructed
706 struct kill_array_data
{
707 std::map
<isl_id
*, struct pet_stmt
*> &id2kill_stmt
;
708 std::map
<isl_id
*, pdg::array
*> &id2array
;
711 /* Mark the array "accessed" by "expr" as killed.
712 * The expression is assumed to represent a kill of an entire array.
714 static int kill_array(__isl_keep pet_expr
*expr
, void *user
)
716 kill_array_data
*data
= (kill_array_data
*) user
;
720 id
= pet_expr_access_get_id(expr
);
721 array
= data
->id2array
[id
];
731 /* Mark all arrays "accessed" by the statement with instance set "set"
734 static isl_stat
kill_stmt_arrays(__isl_take isl_set
*set
, void *user
)
736 kill_array_data
*data
= (kill_array_data
*) user
;
738 struct pet_stmt
*stmt
;
740 id
= isl_set_get_tuple_id(set
);
741 stmt
= data
->id2kill_stmt
[id
];
746 return isl_stat_error
;
748 if (pet_tree_foreach_access_expr(stmt
->body
, &kill_array
, data
) < 0)
749 return isl_stat_error
;
754 /* Given a filter node "node", mark all arrays accessed by the statements
755 * corresponding to the instance set in the filter as killed.
756 * "id2kill_stmt" maps the tuple id of the instance set of a kill statement
757 * to the corresponding pet_stmt.
758 * "id2array" maps the array identifier to the corresponding constructed
761 static isl_stat
kill_arrays(__isl_keep isl_schedule_node
*node
,
762 std::map
<isl_id
*, struct pet_stmt
*> &id2kill_stmt
,
763 std::map
<isl_id
*, pdg::array
*> &id2array
)
765 kill_array_data data
= { id2kill_stmt
, id2array
};
766 isl_union_set
*filter
;
769 filter
= isl_schedule_node_filter_get_filter(node
);
770 ok
= isl_union_set_foreach_set(filter
, &kill_stmt_arrays
, &data
);
771 isl_union_set_free(filter
);
776 /* Look for pieces of the schedule "schedule" that are executed after
777 * all other pieces and that consist of only instances in "kills".
778 * If any such pieces can be found, then mark all arrays accessed
779 * by the corresponding statements as killed.
780 * "id2kill_stmt" maps the tuple id of the instance set of a kill statement
781 * to the corresponding pet_stmt.
782 * "id2array" maps the array identifier to the corresponding constructed
785 static void kill_final(__isl_keep isl_schedule
*schedule
,
786 __isl_keep isl_union_set
*kills
,
787 std::map
<isl_id
*, struct pet_stmt
*> &id2kill_stmt
,
788 std::map
<isl_id
*, pdg::array
*> &id2array
)
791 isl_schedule_node
*node
;
793 node
= isl_schedule_get_root(schedule
);
794 node
= isl_schedule_node_child(node
, 0);
795 if (isl_schedule_node_get_type(node
) == isl_schedule_node_context
)
796 node
= isl_schedule_node_child(node
, 0);
797 if (isl_schedule_node_get_type(node
) != isl_schedule_node_sequence
) {
798 isl_schedule_node_free(node
);
802 n
= isl_schedule_node_n_children(node
);
803 node
= isl_schedule_node_child(node
, n
- 1);
805 isl_union_set
*filter
;
808 filter
= isl_schedule_node_filter_get_filter(node
);
809 is_all_kill
= isl_union_set_is_subset(filter
, kills
);
810 isl_union_set_free(filter
);
813 kill_arrays(node
, id2kill_stmt
, id2array
);
814 if (!isl_schedule_node_has_previous_sibling(node
))
816 node
= isl_schedule_node_previous_sibling(node
);
819 isl_schedule_node_free(node
);
822 int main(int argc
, char **argv
)
825 isl_union_set
*kills
;
826 struct options
*options
= options_new_with_defaults();
827 struct pet_scop
*scop
;
834 std::map
<isl_id
*, pdg::array
*> id2array
;
835 std::map
<isl_id
*, struct pet_stmt
*> id2kill_stmt
;
837 ctx
= isl_ctx_alloc_with_options(&options_args
, options
);
839 fprintf(stderr
, "Unable to allocate ctx\n");
843 pdg
= new pdg::PDG(ctx
);
844 pdg
->add_history_line("c2pdg", argc
, argv
);
845 pdg
->placement
= new str(string("original"));
847 pet_options_set_autodetect(ctx
, 1);
848 argc
= options_parse(options
, argc
, argv
, ISL_ARG_ALL
);
850 len
= strlen(options
->input
);
851 if (len
> 2 && !strcmp(options
->input
+ len
- 2, ".c"))
853 output_name
= isl_alloc_array(ctx
, char, len
+ sizeof(dot_yaml
));
855 memcpy(output_name
, options
->input
, len
);
856 memcpy(output_name
+ len
, dot_yaml
, sizeof(dot_yaml
));
857 output
= fopen(output_name
, "w");
860 scop
= pet_scop_extract_from_C_source(ctx
, options
->input
,
862 scop
= pet_scop_align_params(scop
);
865 output_name
[len
] = '\0';
866 slash
= strrchr(output_name
, '/');
869 pdg
->name
= new str(output_name
);
871 nparam
= isl_set_dim(scop
->context
, isl_dim_param
);
872 for (int i
= 0; i
< nparam
; ++i
) {
873 isl_id
*id
= isl_set_get_dim_id(scop
->context
, isl_dim_param
, i
);
874 pdg::parameter
*p
= new pdg::parameter
;
876 p
->name
= new str(isl_id_get_name(id
));
877 set_default_parameter_value(p
, id
, scop
, i
);
879 pdg
->params
.push_back(p
);
883 pdg
->context
= new pdg::IslSet(isl_set_copy(scop
->context
));
885 for (int i
= 0; i
< scop
->n_array
; ++i
) {
887 array
= extract_array(pdg
, scop
->arrays
[i
], id2array
);
888 pdg
->arrays
.push_back(array
);
891 kills
= isl_union_set_empty(isl_set_get_space(scop
->context
));
892 for (int i
= 0, nodenr
= 0; i
< scop
->n_stmt
; ++i
) {
894 if (isl_set_is_empty(scop
->stmts
[i
]->domain
))
896 if (pet_stmt_is_kill(scop
->stmts
[i
])) {
897 isl_set
*domain
= isl_set_copy(scop
->stmts
[i
]->domain
);
898 isl_id
*id
= isl_set_get_tuple_id(domain
);
899 id2kill_stmt
[id
] = scop
->stmts
[i
];
901 kills
= isl_union_set_add_set(kills
, domain
);
904 node
= extract_node(pdg
, scop
, scop
->stmts
[i
], id2array
);
906 pdg
->nodes
.push_back(node
);
908 kill_final(scop
->schedule
, kills
, id2kill_stmt
, id2array
);
909 isl_union_set_free(kills
);