c2pdg.cc: extract_node: extract statement name from domain instead of schedule
[ppn.git] / c2pdg.cc
blob98d1278960d5db056751cbf41c1702e334f66b09
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, *space_dom;
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 space_dom = isl_space_copy(space);
440 trans = isl_map_universe(isl_space_map_from_set(space));
442 n_out = isl_map_dim(stmt->schedule, isl_dim_out);
443 for (int i = 0, j = 0; i < n_out; ++i) {
444 v = isl_map_plain_get_val_if_fixed(stmt->schedule,
445 isl_dim_out, i);
446 if (!isl_val_is_nan(v))
447 node->prefix.push_back(isl_val_get_num_si(v));
448 else {
449 isl_map *test;
450 isl_space *dim;
451 dim = isl_map_get_space(stmt->schedule);
452 test = isl_map_equal_dims(dim, isl_dim_in, j,
453 isl_dim_out, i);
454 if (isl_map_is_subset(stmt->schedule, test)) {
455 trans = isl_map_equate(trans, isl_dim_in, j,
456 isl_dim_out, j);
457 } else {
458 isl_map_free(test);
459 dim = isl_map_get_space(stmt->schedule);
460 test = isl_map_opposite_dims(dim, isl_dim_in, j,
461 isl_dim_out, i);
462 assert(isl_map_is_subset(stmt->schedule, test));
463 trans = isl_map_oppose(trans, isl_dim_in, j,
464 isl_dim_out, j);
466 isl_map_free(test);
467 j++;
468 node->prefix.push_back(-1);
470 isl_val_free(v);
473 dom = isl_set_copy(stmt->domain);
474 trans_dom = isl_map_copy(trans);
475 if (isl_set_is_wrapping(dom)) {
476 isl_space *space = isl_set_get_space(dom);
477 isl_map *id;
478 space = isl_space_range(isl_space_unwrap(space));
479 id = isl_map_identity(isl_space_map_from_set(space));
480 trans_dom = isl_map_product(trans_dom, id);
482 dom = isl_set_apply(dom, trans_dom);
483 dom = apply_filter_bounds(dom, stmt, id2array);
484 node->source = new pdg::IslSet(dom);
485 node->name = new str(isl_space_get_tuple_name(space_dom, isl_dim_set));
486 isl_space_free(space_dom);
488 stat = new pdg::statement;
489 node->statement = stat;
491 stat->line = pet_loc_get_line(stmt->loc);
493 for (int i = 0; i < stmt->n_arg; ++i) {
494 pdg::call_or_access *coa;
495 coa = convert_expr(pdg, stat, stmt->args[i], id2array, trans);
496 apply_implications(coa, scop, node->source->set, i);
497 node->filters.push_back(coa);
500 if (is_assignment(stmt->body)) {
501 pdg::access *access;
502 pet_expr *expr, *arg;
503 expr = pet_tree_expr_get_expr(stmt->body);
504 if (pet_expr_op_get_type(expr) != pet_op_assign) {
505 arg = pet_expr_get_arg(expr, 0);
506 access = extract_access(pdg, stat,
507 arg, id2array, trans);
508 pet_expr_free(arg);
509 access->type = pdg::access::read;
511 arg = pet_expr_get_arg(expr, 1);
512 stat->top_function = extract_top_function(pdg, stat,
513 arg, id2array, trans);
514 pet_expr_free(arg);
515 arg = pet_expr_get_arg(expr, 0);
516 access = extract_access(pdg, stat, arg, id2array, trans);
517 pet_expr_free(arg);
518 stat->top_outputs.push_back(access);
519 pet_expr_free(expr);
520 } else if (is_inc_dec(stmt->body)) {
521 pdg::access *access;
522 pet_expr *expr, *arg;
523 expr = pet_tree_expr_get_expr(stmt->body);
524 arg = pet_expr_get_arg(expr, 0);
525 access = extract_access(pdg, stat, arg, id2array, trans);
526 access->type = pdg::access::read;
527 stat->top_function = new pdg::function_call;
528 stat->top_function->name =
529 new str(pet_op_str(pet_expr_op_get_type(expr)));
530 access = extract_access(pdg, stat, arg, id2array, trans);
531 stat->top_outputs.push_back(access);
532 pet_expr_free(arg);
533 pet_expr_free(expr);
534 } else
535 stat->top_function = extract_top_function(pdg, stat,
536 stmt->body, id2array, trans);
538 nr = 0;
539 for (int i = 0; i < stat->accesses.size(); ++i)
540 if (stat->accesses[i]->type == pdg::access::read)
541 stat->accesses[i]->nr = nr++;
542 for (int i = 0; i < stat->accesses.size(); ++i)
543 if (stat->accesses[i]->type != pdg::access::read)
544 stat->accesses[i]->nr = nr++;
546 isl_map_free(trans);
548 return node;
551 /* Create and return a pdg::array corresponding to pa and add it
552 * to id2array.
554 static pdg::array *extract_array(pdg::PDG *pdg, struct pet_array *pa,
555 std::map<isl_id *, pdg::array *> &id2array)
557 isl_id *id = isl_set_get_tuple_id(pa->extent);
558 pdg::array *array = new pdg::array;
559 int dim = isl_set_dim(pa->extent, isl_dim_set);
561 array->name = new str(isl_id_get_name(id));
562 array->element_type = new str(pa->element_type);
563 for (int j = 0; j < dim; ++j) {
564 isl_space *dim;
565 isl_aff *obj;
566 isl_val *v;
568 dim = isl_set_get_space(pa->extent);
569 obj = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
570 obj = isl_aff_add_coefficient_si(obj, isl_dim_in, j, 1);
571 v = isl_set_max_val(pa->extent, obj);
572 isl_aff_free(obj);
573 if (isl_val_is_int(v))
574 array->dims.push_back(isl_val_get_num_si(v) + 1);
575 else
576 array->dims.push_back(-1);
577 isl_val_free(v);
579 if (pa->value_bounds)
580 array->value_bounds =
581 new pdg::IslSet(isl_set_copy(pa->value_bounds));
582 array->uniquely_defined = pa->uniquely_defined;
584 id2array[id] = array;
586 isl_id_free(id);
588 return array;
591 /* Assign a default value to parameter "p", which corresponds
592 * to the parameter at position "i" in scop->context.
594 * If the parameter appears in scop->context_value and if
595 * it has a fixed value, then use that value.
596 * Otherwise find the minimual value of "p" in scop->context.
597 * It there is no minimal value, then we currently leave p->value unset.
599 static void set_default_parameter_value(pdg::parameter *p,
600 __isl_keep isl_id *id, struct pet_scop *scop, int i)
602 isl_space *space;
603 isl_aff *obj;
604 isl_val *v;
605 int pos;
607 pos = isl_set_find_dim_by_id(scop->context_value, isl_dim_param, id);
608 if (pos >= 0) {
609 v = isl_set_plain_get_val_if_fixed(scop->context_value,
610 isl_dim_param, pos);
611 if (isl_val_is_int(v)) {
612 p->value = new integer(isl_val_get_num_si(v));
613 isl_val_free(v);
614 return;
616 isl_val_free(v);
619 space = isl_set_get_space(scop->context);
620 obj = isl_aff_zero_on_domain(isl_local_space_from_space(space));
621 obj = isl_aff_add_coefficient_si(obj, isl_dim_param, i, 1);
622 v = isl_set_min_val(scop->context, obj);
623 isl_aff_free(obj);
624 if (isl_val_is_int(v))
625 p->value = new integer(isl_val_get_num_si(v));
627 isl_val_free(v);
630 int main(int argc, char **argv)
632 isl_ctx *ctx;
633 struct options *options = options_new_with_defaults();
634 struct pet_scop *scop;
635 pdg::PDG *pdg;
636 int len;
637 char *output_name;
638 FILE *output;
639 int nparam;
640 char *slash;
641 std::map<isl_id *, pdg::array *> id2array;
643 ctx = isl_ctx_alloc_with_options(&options_args, options);
644 if (!ctx) {
645 fprintf(stderr, "Unable to allocate ctx\n");
646 return -1;
649 pdg = new pdg::PDG(ctx);
650 pdg->add_history_line("c2pdg", argc, argv);
651 pdg->placement = new str(string("original"));
653 pet_options_set_autodetect(ctx, 1);
654 argc = options_parse(options, argc, argv, ISL_ARG_ALL);
656 len = strlen(options->input);
657 if (len > 2 && !strcmp(options->input + len - 2, ".c"))
658 len -= 2;
659 output_name = isl_alloc_array(ctx, char, len + sizeof(dot_yaml));
660 assert(output_name);
661 memcpy(output_name, options->input, len);
662 memcpy(output_name + len, dot_yaml, sizeof(dot_yaml));
663 output = fopen(output_name, "w");
664 assert(output);
666 scop = pet_scop_extract_from_C_source(ctx, options->input,
667 options->function);
668 scop = pet_scop_align_params(scop);
669 assert(scop);
671 output_name[len] = '\0';
672 slash = strrchr(output_name, '/');
673 if (!slash)
674 slash = output_name;
675 pdg->name = new str(output_name);
677 nparam = isl_set_dim(scop->context, isl_dim_param);
678 for (int i = 0; i < nparam; ++i) {
679 isl_id *id = isl_set_get_dim_id(scop->context, isl_dim_param, i);
680 pdg::parameter *p = new pdg::parameter;
682 p->name = new str(isl_id_get_name(id));
683 set_default_parameter_value(p, id, scop, i);
685 pdg->params.push_back(p);
686 isl_id_free(id);
689 pdg->context = new pdg::IslSet(isl_set_copy(scop->context));
691 for (int i = 0; i < scop->n_array; ++i) {
692 pdg::array *array;
693 array = extract_array(pdg, scop->arrays[i], id2array);
694 pdg->arrays.push_back(array);
697 for (int i = 0, nodenr = 0; i < scop->n_stmt; ++i) {
698 pdg::node *node;
699 if (isl_set_is_empty(scop->stmts[i]->domain))
700 continue;
701 node = extract_node(pdg, scop, scop->stmts[i], id2array);
702 node->nr = nodenr++;
703 pdg->nodes.push_back(node);
706 pdg->Dump(output);
707 pdg->free();
708 delete pdg;
710 pet_scop_free(scop);
712 fclose(output);
713 free(output_name);
715 isl_ctx_free(ctx);
716 return 0;