c2pdg.cc: extract_node: rename "dim" variable to "space"
[ppn.git] / c2pdg.cc
blob11871154c6cedb75d5a9040711a6f9ff4f665e1e
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
5 #include <isl/ctx.h>
6 #include <isl/aff.h>
7 #include <isl/ilp.h>
8 #include <isl/constraint.h>
9 #include <pet.h>
11 #include <isa/pdg.h>
12 #include "c2pdg_options.h"
14 const char dot_yaml[] = ".yaml";
16 static __isl_give isl_map *isl_map_equal_dims(__isl_take isl_space *dim,
17 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
19 isl_map *map = isl_map_universe(dim);
20 return isl_map_equate(map, type1, pos1, type2, pos2);
23 static __isl_give isl_map *isl_map_opposite_dims(__isl_take isl_space *dim,
24 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
26 isl_map *map = isl_map_universe(dim);
27 return isl_map_oppose(map, type1, pos1, type2, pos2);
30 static pdg::call_or_access *convert_expr(pdg::PDG *pdg,
31 pdg::statement *stat, struct pet_expr *expr,
32 std::map<isl_id *, pdg::array *> &id2array, __isl_keep isl_map *trans);
34 /* Convert the access pet_expr to a pdg::access and return it.
35 * We assume that the pet_expr accesses data in a single space
36 * (in particular, we do not support accesses to different fields
37 * of a struct) and that it is either a write or a read (and not both).
38 * The pdg::access is also added to the list of accesses in "stat".
39 * The pointer to the pdg::array is taken from "id2array" based
40 * on the tuple id on the access relation.
42 * The domain of the access relation is transformed using "trans".
43 * If the access has any arguments then the domain of the access relation
44 * is a wrapped mapping from the iteration space to the space of
45 * argument values. We only need to change the domain of this wrapped
46 * mapping, so we extend the input transformation with an identity mapping
47 * on the space of argument values.
49 static pdg::access *extract_access(pdg::PDG *pdg, pdg::statement *stat,
50 struct pet_expr *expr, std::map<isl_id *, pdg::array *> &id2array,
51 __isl_keep isl_map *trans)
53 pdg::access *access = new pdg::access;
54 isl_id *id = NULL;
55 isl_space *dim;
56 isl_map *map;
57 isl_union_map *umap;
58 unsigned n_index;
59 int n;
61 n = pet_expr_get_n_arg(expr);
62 for (int i = 0; i < n; ++i) {
63 pdg::call_or_access *coa;
64 pet_expr *arg;
65 arg = pet_expr_get_arg(expr, i);
66 coa = convert_expr(pdg, stat, arg, id2array, trans);
67 pet_expr_free(arg);
68 access->nested.push_back(coa);
71 if (pet_expr_access_is_write(expr)) {
72 access->type = pdg::access::write;
73 umap = pet_expr_access_get_dependent_may_write(expr);
74 } else {
75 access->type = pdg::access::read;
76 umap = pet_expr_access_get_dependent_may_read(expr);
79 assert(isl_union_map_n_map(umap) == 1);
81 map = isl_map_from_union_map(umap);
82 trans = isl_map_copy(trans);
84 dim = isl_space_domain(isl_map_get_space(map));
85 if (!isl_space_is_wrapping(dim))
86 isl_space_free(dim);
87 else {
88 isl_map *id;
89 dim = isl_space_unwrap(dim);
90 dim = isl_space_range(dim);
91 dim = isl_space_map_from_set(dim);
92 id = isl_map_identity(dim);
93 trans = isl_map_product(trans, id);
96 map = isl_map_apply_domain(map, trans);
97 if (isl_map_has_tuple_id(map, isl_dim_out))
98 id = isl_map_get_tuple_id(map, isl_dim_out);
99 n_index = isl_map_dim(map, isl_dim_out);
100 for (int i = n_index - 1; i >= 0; --i)
101 if (!isl_map_involves_dims(map, isl_dim_out, i, 1))
102 map = isl_map_project_out(map, isl_dim_out, i, 1);
103 else
104 break;
105 if (id)
106 map = isl_map_set_tuple_id(map, isl_dim_out, id);
107 access->map = new pdg::IslMap(map);
109 if (!pet_expr_is_affine(expr)) {
110 id = pet_expr_access_get_id(expr);
111 access->array = id2array[id];
112 isl_id_free(id);
115 stat->accesses.push_back(access);
117 return access;
120 /* Convert the integer pet_expr to a pdg::access and return this pdg::access.
121 * The pdg::access is also added to the list of accesses in "stat".
123 * The domain of the access relation derived from the integer value
124 * is equal to the range space of "trans".
126 static pdg::access *extract_access_from_int(pdg::PDG *pdg, pdg::statement *stat,
127 struct pet_expr *expr, __isl_keep isl_map *trans)
129 pdg::access *access = new pdg::access;
130 isl_val *v;
131 isl_aff *aff;
132 isl_pw_aff *pa;
133 isl_space *space;
135 access->type = pdg::access::read;
137 v = pet_expr_int_get_val(expr);
138 space = isl_space_range(isl_map_get_space(trans));
139 aff = isl_aff_val_on_domain(isl_local_space_from_space(space), v);
140 pa = isl_pw_aff_from_aff(aff);
142 access->map = new pdg::IslMap(isl_map_from_pw_aff(pa));
144 stat->accesses.push_back(access);
146 return access;
149 static pdg::call_or_access *convert_expr(pdg::PDG *pdg,
150 pdg::statement *stat, struct pet_expr *expr,
151 std::map<isl_id *, pdg::array *> &id2array, __isl_keep isl_map *trans)
153 pdg::call_or_access *coa = new pdg::call_or_access;
154 enum pet_expr_type type;
156 type = pet_expr_get_type(expr);
157 if (type == pet_expr_access) {
158 coa->type = pdg::call_or_access::t_access;
159 coa->access = extract_access(pdg, stat, expr, id2array, trans);
160 } else if (type == pet_expr_int) {
161 coa->type = pdg::call_or_access::t_access;
162 coa->access = extract_access_from_int(pdg, stat, expr, trans);
163 } else {
164 int n;
166 coa->type = pdg::call_or_access::t_call;
167 coa->call = new pdg::function_call;
169 if (type == pet_expr_call)
170 coa->call->name = new str(pet_expr_call_get_name(expr));
171 else if (type == pet_expr_double) {
172 char *s = pet_expr_double_get_str(expr);
173 coa->call->name = new str(s);
174 free(s);
175 } else if (type == pet_expr_op &&
176 pet_expr_op_get_type(expr) == pet_op_cond)
177 coa->call->name = new str("#test");
178 else
179 coa->call->name =
180 new str(pet_op_str(pet_expr_op_get_type(expr)));
182 n = pet_expr_get_n_arg(expr);
183 for (int i = 0; i < n; ++i) {
184 pdg::call_or_access *child;
185 pet_expr *arg;
186 arg = pet_expr_get_arg(expr, i);
187 child = convert_expr(pdg, stat, arg, id2array, trans);
188 pet_expr_free(arg);
189 coa->call->arguments.push_back(child);
193 return coa;
196 static pdg::function_call *extract_top_function(pdg::PDG *pdg,
197 pdg::statement *stat, struct pet_expr *expr,
198 std::map<isl_id *, pdg::array *> &id2array, __isl_keep isl_map *trans)
200 pdg::function_call *call;
201 pdg::call_or_access *coa = convert_expr(pdg, stat, expr, id2array, trans);
203 if (coa->type == pdg::call_or_access::t_access) {
204 call = new pdg::function_call;
205 call->arguments.push_back(coa);
206 call->name = new str(string(""));
207 } else {
208 call = coa->call;
209 delete coa;
212 return call;
215 /* Extract a function call for the top-level function called from "tree".
216 * We currently assume the tree is an expression statement and
217 * extract the function call from the expression.
219 static pdg::function_call *extract_top_function(pdg::PDG *pdg,
220 pdg::statement *stat, __isl_keep pet_tree *tree,
221 std::map<isl_id *, pdg::array *> &id2array, __isl_keep isl_map *trans)
223 pdg::function_call *call;
224 pet_expr *expr;
226 assert(pet_tree_get_type(tree) == pet_tree_expr);
227 expr = pet_tree_expr_get_expr(tree);
228 call = extract_top_function(pdg, stat, expr, id2array, trans);
229 pet_expr_free(expr);
231 return call;
234 /* For each of the filters ("arguments") of "stmt", check if the user
235 * has specified any bounds on the values of the corresponding array
236 * elements. If so, apply those bounds to the filter in the iteration
237 * domain "dom".
238 * Return the (possibly) restricted iteration domain.
240 static __isl_give isl_set *apply_filter_bounds(__isl_take isl_set *dom,
241 struct pet_stmt *stmt, std::map<isl_id *, pdg::array *> &id2array)
243 isl_map *map;
245 if (!isl_set_is_wrapping(dom))
246 return dom;
248 map = isl_set_unwrap(dom);
250 for (int i = 0; i < stmt->n_arg; ++i) {
251 isl_id *id;
252 pdg::array *array;
253 pet_expr *expr = stmt->args[i];
254 isl_set *bound;
256 if (pet_expr_get_type(expr) != pet_expr_access)
257 continue;
259 id = pet_expr_access_get_id(expr);
260 array = id2array[id];
261 isl_id_free(id);
263 if (!array->value_bounds)
264 continue;
265 bound = array->value_bounds->get_isl_set();
266 bound = isl_set_insert_dims(bound, isl_dim_set, 0, i);
267 bound = isl_set_add_dims(bound, isl_dim_set,
268 stmt->n_arg - (i + 1));
269 map = isl_map_intersect_range(map, bound);
272 return isl_map_wrap(map);
275 /* Given a filter access function encoded in "coa" corresponding to
276 * filter "pos" in "domain", extend the function to a filter access
277 * relation by exploiting the implications in "scop".
278 * In particular, if a statement depends on all previous iterations
279 * of some (other) statement (not) having executed, then it is marked
280 * by pet as only depending on the latest iteration of that statement.
281 * The implicit dependence on all previous iterations is encoded
282 * in the implications in "scop".
284 * If the given filter has a fixed filter value that matches the satisfied
285 * field of one of the implications and if that implication also references
286 * the same virtual array, then the corresponding extension is applied
287 * to the original filter access function to extend it to the complete
288 * filter access relation.
289 * Otherwise, we leave the filter access function untouched.
291 static void apply_implications(pdg::call_or_access *coa, struct pet_scop *scop,
292 __isl_keep isl_set *domain, int pos)
294 isl_map *map;
295 isl_map *ext_domain;
296 isl_val *v;
297 isl_id *map_id;
298 int is_int, satisfied;
300 if (scop->n_implication == 0)
301 return;
303 ext_domain = isl_set_unwrap(isl_set_copy(domain));
304 v = isl_map_plain_get_val_if_fixed(ext_domain, isl_dim_out, pos);
305 is_int = isl_val_is_int(v);
306 if (is_int)
307 satisfied = isl_val_get_num_si(v);
308 isl_val_free(v);
309 isl_map_free(ext_domain);
310 if (!is_int)
311 return;
313 assert(coa->type == pdg::call_or_access::t_access);
314 map = coa->access->map->map;
315 map_id = isl_map_get_tuple_id(map, isl_dim_out);
317 for (int i = 0; i < scop->n_implication; ++i) {
318 struct pet_implication *pi;
319 isl_id *pi_id;
321 pi = scop->implications[i];
323 if (pi->satisfied != satisfied)
324 continue;
325 pi_id = isl_map_get_tuple_id(pi->extension, isl_dim_in);
326 isl_id_free(pi_id);
327 if (pi_id != map_id)
328 continue;
330 map = isl_map_apply_range(map, isl_map_copy(pi->extension));
331 break;
334 coa->access->map->map = map;
336 isl_id_free(map_id);
339 /* Does "expr" perform a (possibly compound) assignment?
341 static int is_assignment(__isl_keep pet_expr *expr)
343 pet_expr *arg;
344 int is_access;
346 if (pet_expr_get_type(expr) != pet_expr_op)
347 return 0;
348 if (pet_expr_op_get_type(expr) > pet_op_assign)
349 return 0;
350 arg = pet_expr_get_arg(expr, 0);
351 is_access = pet_expr_get_type(arg) == pet_expr_access;
352 pet_expr_free(arg);
354 return is_access;
357 /* Does "expr" perform an increment or decrement operation?
359 static int is_inc_dec(__isl_keep pet_expr *expr)
361 pet_expr *arg;
362 int is_access;
364 if (pet_expr_get_type(expr) != pet_expr_op)
365 return 0;
366 if (!pet_op_is_inc_dec(pet_expr_op_get_type(expr)))
367 return 0;
368 arg = pet_expr_get_arg(expr, 0);
369 is_access = pet_expr_get_type(arg) == pet_expr_access;
370 pet_expr_free(arg);
372 return is_access;
375 /* Is "tree" an expression statement that satisfies "fn"?
377 static int is_expr_tree(__isl_keep pet_tree *tree,
378 int (*fn)(__isl_keep pet_expr *expr))
380 pet_expr *expr;
381 int res;
383 if (pet_tree_get_type(tree) != pet_tree_expr)
384 return 0;
385 expr = pet_tree_expr_get_expr(tree);
386 res = fn(expr);
387 pet_expr_free(expr);
389 return res;
392 /* Does "tree" perform a (possibly compound) assignment?
394 static int is_assignment(__isl_keep pet_tree *tree)
396 return is_expr_tree(tree, &is_assignment);
399 /* Does "tree" perform an increment or decrement operation?
401 static int is_inc_dec(__isl_keep pet_tree *tree)
403 return is_expr_tree(tree, &is_inc_dec);
406 /* Create and return a pdg::node correspondingto stmt.
407 * Since isa uses the "prefix" field in a pdg::node to represent the
408 * original schedule, we try to extract such a prefix from the schedule.
409 * If one of the original for loops had a decrement, then the corresponding
410 * part of the schedule will be of the form [i] -> [-i]. Since such
411 * an inverse cannot be represented by "prefix", we invert the corresponding
412 * dimension of the iteration domain instead, taking care to also
413 * change the domains of all access relations accordingly.
415 * If 'stmt" has any arguments, then stmt->domain is a wrapped map
416 * and the transformation on the iteration domain only applies
417 * to the domain of that map. We therefore need to combine that
418 * transformation with an identity mapping on the range before
419 * applying it to the domain.
420 * Any arguments found are also converted into filters on the node
421 * domain. The original filter access functions are extended to
422 * filter access relations using the implications in "scop".
424 static pdg::node *extract_node(pdg::PDG *pdg, struct pet_scop *scop,
425 struct pet_stmt *stmt, std::map<isl_id *, pdg::array *> &id2array)
427 pdg::node *node = new pdg::node;
428 pdg::statement *stat;
429 int nr;
430 int n_out;
431 isl_val *v;
432 isl_space *space;
433 isl_set *dom;
434 isl_map *trans, *trans_dom;
436 space = isl_set_get_space(stmt->domain);
437 if (isl_space_is_wrapping(space))
438 space = isl_space_domain(isl_space_unwrap(space));
439 trans = isl_map_universe(isl_space_map_from_set(space));
441 n_out = isl_map_dim(stmt->schedule, isl_dim_out);
442 for (int i = 0, j = 0; i < n_out; ++i) {
443 v = isl_map_plain_get_val_if_fixed(stmt->schedule,
444 isl_dim_out, i);
445 if (!isl_val_is_nan(v))
446 node->prefix.push_back(isl_val_get_num_si(v));
447 else {
448 isl_map *test;
449 isl_space *dim;
450 dim = isl_map_get_space(stmt->schedule);
451 test = isl_map_equal_dims(dim, isl_dim_in, j,
452 isl_dim_out, i);
453 if (isl_map_is_subset(stmt->schedule, test)) {
454 trans = isl_map_equate(trans, isl_dim_in, j,
455 isl_dim_out, j);
456 } else {
457 isl_map_free(test);
458 dim = isl_map_get_space(stmt->schedule);
459 test = isl_map_opposite_dims(dim, isl_dim_in, j,
460 isl_dim_out, i);
461 assert(isl_map_is_subset(stmt->schedule, test));
462 trans = isl_map_oppose(trans, isl_dim_in, j,
463 isl_dim_out, j);
465 isl_map_free(test);
466 j++;
467 node->prefix.push_back(-1);
469 isl_val_free(v);
472 dom = isl_set_copy(stmt->domain);
473 trans_dom = isl_map_copy(trans);
474 if (isl_set_is_wrapping(dom)) {
475 isl_space *space = isl_set_get_space(dom);
476 isl_map *id;
477 space = isl_space_range(isl_space_unwrap(space));
478 id = isl_map_identity(isl_space_map_from_set(space));
479 trans_dom = isl_map_product(trans_dom, id);
481 dom = isl_set_apply(dom, trans_dom);
482 dom = apply_filter_bounds(dom, stmt, id2array);
483 node->source = new pdg::IslSet(dom);
484 node->name = new str(isl_map_get_tuple_name(stmt->schedule,
485 isl_dim_in));
487 stat = new pdg::statement;
488 node->statement = stat;
490 stat->line = pet_loc_get_line(stmt->loc);
492 for (int i = 0; i < stmt->n_arg; ++i) {
493 pdg::call_or_access *coa;
494 coa = convert_expr(pdg, stat, stmt->args[i], id2array, trans);
495 apply_implications(coa, scop, node->source->set, i);
496 node->filters.push_back(coa);
499 if (is_assignment(stmt->body)) {
500 pdg::access *access;
501 pet_expr *expr, *arg;
502 expr = pet_tree_expr_get_expr(stmt->body);
503 if (pet_expr_op_get_type(expr) != pet_op_assign) {
504 arg = pet_expr_get_arg(expr, 0);
505 access = extract_access(pdg, stat,
506 arg, id2array, trans);
507 pet_expr_free(arg);
508 access->type = pdg::access::read;
510 arg = pet_expr_get_arg(expr, 1);
511 stat->top_function = extract_top_function(pdg, stat,
512 arg, id2array, trans);
513 pet_expr_free(arg);
514 arg = pet_expr_get_arg(expr, 0);
515 access = extract_access(pdg, stat, arg, id2array, trans);
516 pet_expr_free(arg);
517 stat->top_outputs.push_back(access);
518 pet_expr_free(expr);
519 } else if (is_inc_dec(stmt->body)) {
520 pdg::access *access;
521 pet_expr *expr, *arg;
522 expr = pet_tree_expr_get_expr(stmt->body);
523 arg = pet_expr_get_arg(expr, 0);
524 access = extract_access(pdg, stat, arg, id2array, trans);
525 access->type = pdg::access::read;
526 stat->top_function = new pdg::function_call;
527 stat->top_function->name =
528 new str(pet_op_str(pet_expr_op_get_type(expr)));
529 access = extract_access(pdg, stat, arg, id2array, trans);
530 stat->top_outputs.push_back(access);
531 pet_expr_free(arg);
532 pet_expr_free(expr);
533 } else
534 stat->top_function = extract_top_function(pdg, stat,
535 stmt->body, id2array, trans);
537 nr = 0;
538 for (int i = 0; i < stat->accesses.size(); ++i)
539 if (stat->accesses[i]->type == pdg::access::read)
540 stat->accesses[i]->nr = nr++;
541 for (int i = 0; i < stat->accesses.size(); ++i)
542 if (stat->accesses[i]->type != pdg::access::read)
543 stat->accesses[i]->nr = nr++;
545 isl_map_free(trans);
547 return node;
550 /* Create and return a pdg::array corresponding to pa and add it
551 * to id2array.
553 static pdg::array *extract_array(pdg::PDG *pdg, struct pet_array *pa,
554 std::map<isl_id *, pdg::array *> &id2array)
556 isl_id *id = isl_set_get_tuple_id(pa->extent);
557 pdg::array *array = new pdg::array;
558 int dim = isl_set_dim(pa->extent, isl_dim_set);
560 array->name = new str(isl_id_get_name(id));
561 array->element_type = new str(pa->element_type);
562 for (int j = 0; j < dim; ++j) {
563 isl_space *dim;
564 isl_aff *obj;
565 isl_val *v;
567 dim = isl_set_get_space(pa->extent);
568 obj = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
569 obj = isl_aff_add_coefficient_si(obj, isl_dim_in, j, 1);
570 v = isl_set_max_val(pa->extent, obj);
571 isl_aff_free(obj);
572 if (isl_val_is_int(v))
573 array->dims.push_back(isl_val_get_num_si(v) + 1);
574 else
575 array->dims.push_back(-1);
576 isl_val_free(v);
578 if (pa->value_bounds)
579 array->value_bounds =
580 new pdg::IslSet(isl_set_copy(pa->value_bounds));
581 array->uniquely_defined = pa->uniquely_defined;
583 id2array[id] = array;
585 isl_id_free(id);
587 return array;
590 /* Assign a default value to parameter "p", which corresponds
591 * to the parameter at position "i" in scop->context.
593 * If the parameter appears in scop->context_value and if
594 * it has a fixed value, then use that value.
595 * Otherwise find the minimual value of "p" in scop->context.
596 * It there is no minimal value, then we currently leave p->value unset.
598 static void set_default_parameter_value(pdg::parameter *p,
599 __isl_keep isl_id *id, struct pet_scop *scop, int i)
601 isl_space *space;
602 isl_aff *obj;
603 isl_val *v;
604 int pos;
606 pos = isl_set_find_dim_by_id(scop->context_value, isl_dim_param, id);
607 if (pos >= 0) {
608 v = isl_set_plain_get_val_if_fixed(scop->context_value,
609 isl_dim_param, pos);
610 if (isl_val_is_int(v)) {
611 p->value = new integer(isl_val_get_num_si(v));
612 isl_val_free(v);
613 return;
615 isl_val_free(v);
618 space = isl_set_get_space(scop->context);
619 obj = isl_aff_zero_on_domain(isl_local_space_from_space(space));
620 obj = isl_aff_add_coefficient_si(obj, isl_dim_param, i, 1);
621 v = isl_set_min_val(scop->context, obj);
622 isl_aff_free(obj);
623 if (isl_val_is_int(v))
624 p->value = new integer(isl_val_get_num_si(v));
626 isl_val_free(v);
629 int main(int argc, char **argv)
631 isl_ctx *ctx;
632 struct options *options = options_new_with_defaults();
633 struct pet_scop *scop;
634 pdg::PDG *pdg;
635 int len;
636 char *output_name;
637 FILE *output;
638 int nparam;
639 char *slash;
640 std::map<isl_id *, pdg::array *> id2array;
642 ctx = isl_ctx_alloc_with_options(&options_args, options);
643 if (!ctx) {
644 fprintf(stderr, "Unable to allocate ctx\n");
645 return -1;
648 pdg = new pdg::PDG(ctx);
649 pdg->add_history_line("c2pdg", argc, argv);
650 pdg->placement = new str(string("original"));
652 pet_options_set_autodetect(ctx, 1);
653 argc = options_parse(options, argc, argv, ISL_ARG_ALL);
655 len = strlen(options->input);
656 if (len > 2 && !strcmp(options->input + len - 2, ".c"))
657 len -= 2;
658 output_name = isl_alloc_array(ctx, char, len + sizeof(dot_yaml));
659 assert(output_name);
660 memcpy(output_name, options->input, len);
661 memcpy(output_name + len, dot_yaml, sizeof(dot_yaml));
662 output = fopen(output_name, "w");
663 assert(output);
665 scop = pet_scop_extract_from_C_source(ctx, options->input,
666 options->function);
667 scop = pet_scop_align_params(scop);
668 assert(scop);
670 output_name[len] = '\0';
671 slash = strrchr(output_name, '/');
672 if (!slash)
673 slash = output_name;
674 pdg->name = new str(output_name);
676 nparam = isl_set_dim(scop->context, isl_dim_param);
677 for (int i = 0; i < nparam; ++i) {
678 isl_id *id = isl_set_get_dim_id(scop->context, isl_dim_param, i);
679 pdg::parameter *p = new pdg::parameter;
681 p->name = new str(isl_id_get_name(id));
682 set_default_parameter_value(p, id, scop, i);
684 pdg->params.push_back(p);
685 isl_id_free(id);
688 pdg->context = new pdg::IslSet(isl_set_copy(scop->context));
690 for (int i = 0; i < scop->n_array; ++i) {
691 pdg::array *array;
692 array = extract_array(pdg, scop->arrays[i], id2array);
693 pdg->arrays.push_back(array);
696 for (int i = 0, nodenr = 0; i < scop->n_stmt; ++i) {
697 pdg::node *node;
698 if (isl_set_is_empty(scop->stmts[i]->domain))
699 continue;
700 node = extract_node(pdg, scop, scop->stmts[i], id2array);
701 node->nr = nodenr++;
702 pdg->nodes.push_back(node);
705 pdg->Dump(output);
706 pdg->free();
707 delete pdg;
709 pet_scop_free(scop);
711 fclose(output);
712 free(output_name);
714 isl_ctx_free(ctx);
715 return 0;