pet_tree: support return statements
[pet.git] / tree.c
blob79db5b66d5f5cd7d91eb8de6678aee80ac6e046f
1 /*
2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 2014 Ecole Normale Superieure. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY LEIDEN UNIVERSITY ''AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEIDEN UNIVERSITY OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation
30 * are those of the authors and should not be interpreted as
31 * representing official policies, either expressed or implied, of
32 * Leiden University.
35 #include <string.h>
37 #include <isl/ctx.h>
38 #include <isl/id.h>
39 #include <isl/val.h>
40 #include <isl/space.h>
41 #include <isl/aff.h>
43 #include "expr.h"
44 #include "loc.h"
45 #include "tree.h"
47 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
49 static const char *type_str[] = {
50 [pet_tree_block] = "block",
51 [pet_tree_break] = "break",
52 [pet_tree_continue] = "continue",
53 [pet_tree_decl] = "declaration",
54 [pet_tree_decl_init] = "declaration-init",
55 [pet_tree_expr] = "expression",
56 [pet_tree_for] = "for",
57 [pet_tree_infinite_loop] = "infinite-loop",
58 [pet_tree_if] = "if",
59 [pet_tree_if_else] = "if-else",
60 [pet_tree_while] = "while",
61 [pet_tree_return] = "return",
64 /* Return a textual representation of the type "type".
66 const char *pet_tree_type_str(enum pet_tree_type type)
68 if (type < 0)
69 return "error";
70 return type_str[type];
73 /* Extract a type from its textual representation "str".
75 enum pet_tree_type pet_tree_str_type(const char *str)
77 int i;
79 for (i = 0; i < ARRAY_SIZE(type_str); ++i)
80 if (!strcmp(type_str[i], str))
81 return i;
83 return pet_tree_error;
86 /* Return a new pet_tree of the given type.
88 * The location is initializaed to pet_loc_dummy.
90 __isl_give pet_tree *pet_tree_alloc(isl_ctx *ctx, enum pet_tree_type type)
92 pet_tree *tree;
94 tree = isl_calloc_type(ctx, struct pet_tree);
95 if (!tree)
96 return NULL;
98 tree->ctx = ctx;
99 isl_ctx_ref(ctx);
100 tree->ref = 1;
101 tree->type = type;
102 tree->loc = &pet_loc_dummy;
104 return tree;
107 /* Return a new pet_tree representing the declaration (without initialization)
108 * of the variable "var".
110 __isl_give pet_tree *pet_tree_new_decl(__isl_take pet_expr *var)
112 isl_ctx *ctx;
113 pet_tree *tree;
115 if (!var)
116 return NULL;
117 ctx = pet_expr_get_ctx(var);
118 tree = pet_tree_alloc(ctx, pet_tree_decl);
119 if (!tree)
120 goto error;
122 tree->u.d.var = var;
124 return tree;
125 error:
126 pet_expr_free(var);
127 return NULL;
130 /* Return a new pet_tree representing the declaration of the variable "var"
131 * with initial value "init".
133 __isl_give pet_tree *pet_tree_new_decl_init(__isl_take pet_expr *var,
134 __isl_take pet_expr *init)
136 isl_ctx *ctx;
137 pet_tree *tree;
139 if (!var || !init)
140 goto error;
141 ctx = pet_expr_get_ctx(var);
142 tree = pet_tree_alloc(ctx, pet_tree_decl_init);
143 if (!tree)
144 goto error;
146 tree->u.d.var = var;
147 tree->u.d.init = init;
149 return tree;
150 error:
151 pet_expr_free(var);
152 pet_expr_free(init);
153 return NULL;
156 /* Return a new pet_tree representing the expression "expr".
158 __isl_give pet_tree *pet_tree_new_expr(__isl_take pet_expr *expr)
160 isl_ctx *ctx;
161 pet_tree *tree;
163 if (!expr)
164 return NULL;
165 ctx = pet_expr_get_ctx(expr);
166 tree = pet_tree_alloc(ctx, pet_tree_expr);
167 if (!tree)
168 goto error;
170 tree->u.e.expr = expr;
172 return tree;
173 error:
174 pet_expr_free(expr);
175 return NULL;
178 /* Return a new pet_tree representing the return of expression "expr".
180 __isl_give pet_tree *pet_tree_new_return(__isl_take pet_expr *expr)
182 isl_ctx *ctx;
183 pet_tree *tree;
185 if (!expr)
186 return NULL;
187 ctx = pet_expr_get_ctx(expr);
188 tree = pet_tree_alloc(ctx, pet_tree_return);
189 if (!tree)
190 goto error;
192 tree->u.e.expr = expr;
194 return tree;
195 error:
196 pet_expr_free(expr);
197 return NULL;
200 /* Return a new pet_tree representing an initially empty sequence
201 * of trees with room for "n" trees.
202 * "block" indicates whether the sequence has its own scope.
204 __isl_give pet_tree *pet_tree_new_block(isl_ctx *ctx, int block, int n)
206 pet_tree *tree;
208 tree = pet_tree_alloc(ctx, pet_tree_block);
209 if (!tree)
210 return NULL;
211 tree->u.b.block = block;
212 tree->u.b.n = 0;
213 tree->u.b.max = n;
214 tree->u.b.child = isl_calloc_array(ctx, pet_tree *, n);
215 if (n && !tree->u.b.child)
216 return pet_tree_free(tree);
218 return tree;
221 /* Return a new pet_tree representing a break statement.
223 __isl_give pet_tree *pet_tree_new_break(isl_ctx *ctx)
225 return pet_tree_alloc(ctx, pet_tree_break);
228 /* Return a new pet_tree representing a continue statement.
230 __isl_give pet_tree *pet_tree_new_continue(isl_ctx *ctx)
232 return pet_tree_alloc(ctx, pet_tree_continue);
235 /* Return a new pet_tree representing a for loop
236 * with induction variable "iv", initial value for the induction
237 * variable "init", loop condition "cond", induction variable increment "inc"
238 * and loop body "body". "declared" indicates whether the induction variable
239 * is declared by the loop. "independent" is set if the for loop is marked
240 * independent.
242 * The location of the loop is initialized to that of the body.
244 __isl_give pet_tree *pet_tree_new_for(int independent, int declared,
245 __isl_take pet_expr *iv, __isl_take pet_expr *init,
246 __isl_take pet_expr *cond, __isl_take pet_expr *inc,
247 __isl_take pet_tree *body)
249 isl_ctx *ctx;
250 pet_tree *tree;
252 if (!iv || !init || !cond || !inc || !body)
253 goto error;
254 ctx = pet_tree_get_ctx(body);
255 tree = pet_tree_alloc(ctx, pet_tree_for);
256 if (!tree)
257 goto error;
259 tree->u.l.independent = independent;
260 tree->u.l.declared = declared;
261 tree->u.l.iv = iv;
262 tree->u.l.init = init;
263 tree->u.l.cond = cond;
264 tree->u.l.inc = inc;
265 tree->u.l.body = body;
266 tree->loc = pet_tree_get_loc(body);
267 if (!tree->loc)
268 return pet_tree_free(tree);
270 return tree;
271 error:
272 pet_expr_free(iv);
273 pet_expr_free(init);
274 pet_expr_free(cond);
275 pet_expr_free(inc);
276 pet_tree_free(body);
277 return NULL;
280 /* Return a new pet_tree representing a while loop
281 * with loop condition "cond" and loop body "body".
283 * The location of the loop is initialized to that of the body.
285 __isl_give pet_tree *pet_tree_new_while(__isl_take pet_expr *cond,
286 __isl_take pet_tree *body)
288 isl_ctx *ctx;
289 pet_tree *tree;
291 if (!cond || !body)
292 goto error;
293 ctx = pet_tree_get_ctx(body);
294 tree = pet_tree_alloc(ctx, pet_tree_while);
295 if (!tree)
296 goto error;
298 tree->u.l.cond = cond;
299 tree->u.l.body = body;
300 tree->loc = pet_tree_get_loc(body);
301 if (!tree->loc)
302 return pet_tree_free(tree);
304 return tree;
305 error:
306 pet_expr_free(cond);
307 pet_tree_free(body);
308 return NULL;
311 /* Return a new pet_tree representing an infinite loop
312 * with loop body "body".
314 * The location of the loop is initialized to that of the body.
316 __isl_give pet_tree *pet_tree_new_infinite_loop(__isl_take pet_tree *body)
318 isl_ctx *ctx;
319 pet_tree *tree;
321 if (!body)
322 return NULL;
323 ctx = pet_tree_get_ctx(body);
324 tree = pet_tree_alloc(ctx, pet_tree_infinite_loop);
325 if (!tree)
326 return pet_tree_free(body);
328 tree->u.l.body = body;
329 tree->loc = pet_tree_get_loc(body);
330 if (!tree->loc)
331 return pet_tree_free(tree);
333 return tree;
336 /* Return a new pet_tree representing an if statement
337 * with condition "cond" and then branch "then_body".
339 * The location of the if statement is initialized to that of the body.
341 __isl_give pet_tree *pet_tree_new_if(__isl_take pet_expr *cond,
342 __isl_take pet_tree *then_body)
344 isl_ctx *ctx;
345 pet_tree *tree;
347 if (!cond || !then_body)
348 goto error;
349 ctx = pet_tree_get_ctx(then_body);
350 tree = pet_tree_alloc(ctx, pet_tree_if);
351 if (!tree)
352 goto error;
354 tree->u.i.cond = cond;
355 tree->u.i.then_body = then_body;
356 tree->loc = pet_tree_get_loc(then_body);
357 if (!tree->loc)
358 return pet_tree_free(tree);
360 return tree;
361 error:
362 pet_expr_free(cond);
363 pet_tree_free(then_body);
364 return NULL;
367 /* Return a new pet_tree representing an if statement
368 * with condition "cond", then branch "then_body" and else branch "else_body".
370 * The location of the if statement is initialized to cover
371 * those of the bodies.
373 __isl_give pet_tree *pet_tree_new_if_else(__isl_take pet_expr *cond,
374 __isl_take pet_tree *then_body, __isl_take pet_tree *else_body)
376 isl_ctx *ctx;
377 pet_tree *tree;
379 if (!cond || !then_body || !else_body)
380 goto error;
381 ctx = pet_tree_get_ctx(then_body);
382 tree = pet_tree_alloc(ctx, pet_tree_if_else);
383 if (!tree)
384 goto error;
386 tree->u.i.cond = cond;
387 tree->u.i.then_body = then_body;
388 tree->u.i.else_body = else_body;
389 tree->loc = pet_tree_get_loc(then_body);
390 tree->loc = pet_loc_update_start_end_from_loc(tree->loc,
391 else_body->loc);
392 if (!tree->loc)
393 return pet_tree_free(tree);
395 return tree;
396 error:
397 pet_expr_free(cond);
398 pet_tree_free(then_body);
399 pet_tree_free(else_body);
400 return NULL;
403 /* Return an independent duplicate of "tree".
405 static __isl_give pet_tree *pet_tree_dup(__isl_keep pet_tree *tree)
407 int i;
408 pet_tree *dup;
410 if (!tree)
411 return NULL;
413 switch (tree->type) {
414 case pet_tree_error:
415 return NULL;
416 case pet_tree_block:
417 dup = pet_tree_new_block(tree->ctx, tree->u.b.block,
418 tree->u.b.n);
419 for (i = 0; i < tree->u.b.n; ++i)
420 dup = pet_tree_block_add_child(dup,
421 pet_tree_copy(tree->u.b.child[i]));
422 break;
423 case pet_tree_break:
424 dup = pet_tree_new_break(tree->ctx);
425 break;
426 case pet_tree_continue:
427 dup = pet_tree_new_continue(tree->ctx);
428 break;
429 case pet_tree_decl:
430 dup = pet_tree_new_decl(pet_expr_copy(tree->u.d.var));
431 break;
432 case pet_tree_decl_init:
433 dup = pet_tree_new_decl_init(pet_expr_copy(tree->u.d.var),
434 pet_expr_copy(tree->u.d.init));
435 break;
436 case pet_tree_expr:
437 dup = pet_tree_new_expr(pet_expr_copy(tree->u.e.expr));
438 break;
439 case pet_tree_return:
440 dup = pet_tree_new_return(pet_expr_copy(tree->u.e.expr));
441 break;
442 case pet_tree_for:
443 dup = pet_tree_new_for(tree->u.l.independent,
444 tree->u.l.declared,
445 pet_expr_copy(tree->u.l.iv), pet_expr_copy(tree->u.l.init),
446 pet_expr_copy(tree->u.l.cond), pet_expr_copy(tree->u.l.inc),
447 pet_tree_copy(tree->u.l.body));
448 break;
449 case pet_tree_while:
450 dup = pet_tree_new_while(pet_expr_copy(tree->u.l.cond),
451 pet_tree_copy(tree->u.l.body));
452 break;
453 case pet_tree_infinite_loop:
454 dup = pet_tree_new_infinite_loop(pet_tree_copy(tree->u.l.body));
455 break;
456 case pet_tree_if:
457 dup = pet_tree_new_if(pet_expr_copy(tree->u.i.cond),
458 pet_tree_copy(tree->u.i.then_body));
459 break;
460 case pet_tree_if_else:
461 dup = pet_tree_new_if_else(pet_expr_copy(tree->u.i.cond),
462 pet_tree_copy(tree->u.i.then_body),
463 pet_tree_copy(tree->u.i.else_body));
464 break;
467 if (!dup)
468 return NULL;
469 pet_loc_free(dup->loc);
470 dup->loc = pet_loc_copy(tree->loc);
471 if (!dup->loc)
472 return pet_tree_free(dup);
473 if (tree->label) {
474 dup->label = isl_id_copy(tree->label);
475 if (!dup->label)
476 return pet_tree_free(dup);
479 return dup;
482 /* Return a pet_tree that is equal to "tree" and that has only one reference.
484 __isl_give pet_tree *pet_tree_cow(__isl_take pet_tree *tree)
486 if (!tree)
487 return NULL;
489 if (tree->ref == 1)
490 return tree;
491 tree->ref--;
492 return pet_tree_dup(tree);
495 /* Return an extra reference to "tree".
497 __isl_give pet_tree *pet_tree_copy(__isl_keep pet_tree *tree)
499 if (!tree)
500 return NULL;
502 tree->ref++;
503 return tree;
506 /* Free a reference to "tree".
508 __isl_null pet_tree *pet_tree_free(__isl_take pet_tree *tree)
510 int i;
512 if (!tree)
513 return NULL;
514 if (--tree->ref > 0)
515 return NULL;
517 pet_loc_free(tree->loc);
518 isl_id_free(tree->label);
520 switch (tree->type) {
521 case pet_tree_error:
522 break;
523 case pet_tree_block:
524 for (i = 0; i < tree->u.b.n; ++i)
525 pet_tree_free(tree->u.b.child[i]);
526 free(tree->u.b.child);
527 break;
528 case pet_tree_break:
529 case pet_tree_continue:
530 break;
531 case pet_tree_decl_init:
532 pet_expr_free(tree->u.d.init);
533 case pet_tree_decl:
534 pet_expr_free(tree->u.d.var);
535 break;
536 case pet_tree_expr:
537 case pet_tree_return:
538 pet_expr_free(tree->u.e.expr);
539 break;
540 case pet_tree_for:
541 pet_expr_free(tree->u.l.iv);
542 pet_expr_free(tree->u.l.init);
543 pet_expr_free(tree->u.l.inc);
544 case pet_tree_while:
545 pet_expr_free(tree->u.l.cond);
546 case pet_tree_infinite_loop:
547 pet_tree_free(tree->u.l.body);
548 break;
549 case pet_tree_if_else:
550 pet_tree_free(tree->u.i.else_body);
551 case pet_tree_if:
552 pet_expr_free(tree->u.i.cond);
553 pet_tree_free(tree->u.i.then_body);
554 break;
557 isl_ctx_deref(tree->ctx);
558 free(tree);
559 return NULL;
562 /* Return the isl_ctx in which "tree" was created.
564 isl_ctx *pet_tree_get_ctx(__isl_keep pet_tree *tree)
566 return tree ? tree->ctx : NULL;
569 /* Return the location of "tree".
571 __isl_give pet_loc *pet_tree_get_loc(__isl_keep pet_tree *tree)
573 return tree ? pet_loc_copy(tree->loc) : NULL;
576 /* Return the type of "tree".
578 enum pet_tree_type pet_tree_get_type(__isl_keep pet_tree *tree)
580 if (!tree)
581 return pet_tree_error;
583 return tree->type;
586 /* Replace the location of "tree" by "loc".
588 __isl_give pet_tree *pet_tree_set_loc(__isl_take pet_tree *tree,
589 __isl_take pet_loc *loc)
591 tree = pet_tree_cow(tree);
592 if (!tree || !loc)
593 goto error;
595 pet_loc_free(tree->loc);
596 tree->loc = loc;
598 return tree;
599 error:
600 pet_loc_free(loc);
601 pet_tree_free(tree);
602 return NULL;
605 /* Replace the label of "tree" by "label".
607 __isl_give pet_tree *pet_tree_set_label(__isl_take pet_tree *tree,
608 __isl_take isl_id *label)
610 tree = pet_tree_cow(tree);
611 if (!tree || !label)
612 goto error;
614 isl_id_free(tree->label);
615 tree->label = label;
617 return tree;
618 error:
619 isl_id_free(label);
620 return pet_tree_free(tree);
623 /* Given an expression tree "tree", return the associated expression.
625 __isl_give pet_expr *pet_tree_expr_get_expr(__isl_keep pet_tree *tree)
627 if (!tree)
628 return NULL;
629 if (pet_tree_get_type(tree) != pet_tree_expr)
630 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
631 "not an expression tree", return NULL);
633 return pet_expr_copy(tree->u.e.expr);
636 /* Given a return tree "tree", return the returned expression.
638 __isl_give pet_expr *pet_tree_return_get_expr(__isl_keep pet_tree *tree)
640 if (!tree)
641 return NULL;
642 if (pet_tree_get_type(tree) != pet_tree_return)
643 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
644 "not a return tree", return NULL);
646 return pet_expr_copy(tree->u.e.expr);
649 /* Given a block tree "tree", return the number of children in the sequence.
651 int pet_tree_block_n_child(__isl_keep pet_tree *tree)
653 if (!tree)
654 return -1;
655 if (pet_tree_get_type(tree) != pet_tree_block)
656 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
657 "not a block tree", return -1);
659 return tree->u.b.n;
662 /* Add "child" to the sequence of trees represented by "block".
664 * Update the location of "block" to include that of "child".
666 __isl_give pet_tree *pet_tree_block_add_child(__isl_take pet_tree *block,
667 __isl_take pet_tree *child)
669 block = pet_tree_cow(block);
670 if (!block || !child)
671 goto error;
672 if (block->type != pet_tree_block)
673 isl_die(pet_tree_get_ctx(block), isl_error_invalid,
674 "not a block tree", goto error);
675 if (block->u.b.n >= block->u.b.max)
676 isl_die(pet_tree_get_ctx(block), isl_error_invalid,
677 "out of space in block", goto error);
679 block->loc = pet_loc_update_start_end_from_loc(block->loc, child->loc);
680 block->u.b.child[block->u.b.n++] = child;
682 if (!block->loc)
683 return pet_tree_free(block);
685 return block;
686 error:
687 pet_tree_free(block);
688 pet_tree_free(child);
689 return NULL;
692 /* Does the block tree "tree" have its own scope?
694 int pet_tree_block_get_block(__isl_keep pet_tree *tree)
696 if (!tree)
697 return -1;
698 if (pet_tree_get_type(tree) != pet_tree_block)
699 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
700 "not a block tree", return -1);
702 return tree->u.b.block;
705 /* Set the block property (whether or not the block tree has its own scope)
706 * of "tree" to "is_block".
708 __isl_give pet_tree *pet_tree_block_set_block(__isl_take pet_tree *tree,
709 int is_block)
711 if (!tree)
712 return NULL;
713 if (tree->type != pet_tree_block)
714 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
715 "not a block tree", return pet_tree_free(tree));
716 if (tree->u.b.block == is_block)
717 return tree;
718 tree = pet_tree_cow(tree);
719 if (!tree)
720 return NULL;
721 tree->u.b.block = is_block;
722 return tree;
725 /* Given a block tree "tree", return the child at position "pos".
727 __isl_give pet_tree *pet_tree_block_get_child(__isl_keep pet_tree *tree,
728 int pos)
730 if (!tree)
731 return NULL;
732 if (pet_tree_get_type(tree) != pet_tree_block)
733 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
734 "not a block tree", return NULL);
735 if (pos < 0 || pos >= tree->u.b.n)
736 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
737 "position out of bounds", return NULL);
739 return pet_tree_copy(tree->u.b.child[pos]);
742 /* Does "tree" represent a declaration (with or without initialization)?
744 int pet_tree_is_decl(__isl_keep pet_tree *tree)
746 if (!tree)
747 return -1;
749 switch (pet_tree_get_type(tree)) {
750 case pet_tree_decl:
751 case pet_tree_decl_init:
752 return 1;
753 default:
754 return 0;
758 /* Given a declaration tree "tree", return the variable that is being
759 * declared.
761 __isl_give pet_expr *pet_tree_decl_get_var(__isl_keep pet_tree *tree)
763 if (!tree)
764 return NULL;
765 if (!pet_tree_is_decl(tree))
766 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
767 "not a decl tree", return NULL);
769 return pet_expr_copy(tree->u.d.var);
772 /* Given a declaration tree with initialization "tree",
773 * return the initial value of the declared variable.
775 __isl_give pet_expr *pet_tree_decl_get_init(__isl_keep pet_tree *tree)
777 if (!tree)
778 return NULL;
779 if (pet_tree_get_type(tree) != pet_tree_decl_init)
780 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
781 "not a decl_init tree", return NULL);
783 return pet_expr_copy(tree->u.d.init);
786 /* Given an if tree "tree", return the if condition.
788 __isl_give pet_expr *pet_tree_if_get_cond(__isl_keep pet_tree *tree)
790 enum pet_tree_type type;
792 if (!tree)
793 return NULL;
794 type = pet_tree_get_type(tree);
795 if (type != pet_tree_if && type != pet_tree_if_else)
796 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
797 "not an if tree", return NULL);
799 return pet_expr_copy(tree->u.i.cond);
802 /* Given an if tree "tree", return the body of the then branch.
804 __isl_give pet_tree *pet_tree_if_get_then(__isl_keep pet_tree *tree)
806 enum pet_tree_type type;
808 if (!tree)
809 return NULL;
810 type = pet_tree_get_type(tree);
811 if (type != pet_tree_if && type != pet_tree_if_else)
812 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
813 "not an if tree", return NULL);
815 return pet_tree_copy(tree->u.i.then_body);
818 /* Given an if tree with an else branch "tree",
819 * return the body of that else branch.
821 __isl_give pet_tree *pet_tree_if_get_else(__isl_keep pet_tree *tree)
823 if (!tree)
824 return NULL;
825 if (pet_tree_get_type(tree) != pet_tree_if_else)
826 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
827 "not an if tree with an else branch", return NULL);
829 return pet_tree_copy(tree->u.i.else_body);
832 /* Does "tree" represent some type of loop?
834 int pet_tree_is_loop(__isl_keep pet_tree *tree)
836 if (!tree)
837 return -1;
839 switch (pet_tree_get_type(tree)) {
840 case pet_tree_for:
841 case pet_tree_infinite_loop:
842 case pet_tree_while:
843 return 1;
844 default:
845 return 0;
849 /* Given a for loop "tree", return the induction variable.
851 __isl_give pet_expr *pet_tree_loop_get_var(__isl_keep pet_tree *tree)
853 if (!tree)
854 return NULL;
855 if (pet_tree_get_type(tree) != pet_tree_for)
856 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
857 "not a for tree", return NULL);
859 return pet_expr_copy(tree->u.l.iv);
862 /* Given a for loop "tree", return the initial value of the induction variable.
864 __isl_give pet_expr *pet_tree_loop_get_init(__isl_keep pet_tree *tree)
866 if (!tree)
867 return NULL;
868 if (pet_tree_get_type(tree) != pet_tree_for)
869 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
870 "not a for tree", return NULL);
872 return pet_expr_copy(tree->u.l.init);
875 /* Given a loop "tree", return the loop condition.
877 * For an infinite loop, the loop condition always holds,
878 * so we simply return "1".
880 __isl_give pet_expr *pet_tree_loop_get_cond(__isl_keep pet_tree *tree)
882 enum pet_tree_type type;
884 if (!tree)
885 return NULL;
886 type = pet_tree_get_type(tree);
887 if (type == pet_tree_infinite_loop)
888 return pet_expr_new_int(isl_val_one(pet_tree_get_ctx(tree)));
889 if (type != pet_tree_for && type != pet_tree_while)
890 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
891 "not a for or while tree", return NULL);
893 return pet_expr_copy(tree->u.l.cond);
896 /* Given a for loop "tree", return the increment of the induction variable.
898 __isl_give pet_expr *pet_tree_loop_get_inc(__isl_keep pet_tree *tree)
900 if (!tree)
901 return NULL;
902 if (pet_tree_get_type(tree) != pet_tree_for)
903 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
904 "not a for tree", return NULL);
906 return pet_expr_copy(tree->u.l.inc);
909 /* Given a loop tree "tree", return the body.
911 __isl_give pet_tree *pet_tree_loop_get_body(__isl_keep pet_tree *tree)
913 if (!tree)
914 return NULL;
916 if (!pet_tree_is_loop(tree))
917 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
918 "not a loop tree", return NULL);
920 return pet_tree_copy(tree->u.l.body);
923 /* Call "fn" on each node of "tree", including "tree" itself.
925 * Return 0 on success and -1 on error, where "fn" returning a negative
926 * value is treated as an error.
928 int pet_tree_foreach_sub_tree(__isl_keep pet_tree *tree,
929 int (*fn)(__isl_keep pet_tree *tree, void *user), void *user)
931 int i;
933 if (!tree)
934 return -1;
936 if (fn(tree, user) < 0)
937 return -1;
939 switch (tree->type) {
940 case pet_tree_error:
941 return -1;
942 case pet_tree_block:
943 for (i = 0; i < tree->u.b.n; ++i)
944 if (pet_tree_foreach_sub_tree(tree->u.b.child[i],
945 fn, user) < 0)
946 return -1;
947 break;
948 case pet_tree_break:
949 case pet_tree_continue:
950 case pet_tree_decl:
951 case pet_tree_decl_init:
952 case pet_tree_expr:
953 case pet_tree_return:
954 break;
955 case pet_tree_if:
956 if (pet_tree_foreach_sub_tree(tree->u.i.then_body,
957 fn, user) < 0)
958 return -1;
959 break;
960 case pet_tree_if_else:
961 if (pet_tree_foreach_sub_tree(tree->u.i.then_body,
962 fn, user) < 0)
963 return -1;
964 if (pet_tree_foreach_sub_tree(tree->u.i.else_body,
965 fn, user) < 0)
966 return -1;
967 break;
968 case pet_tree_while:
969 case pet_tree_for:
970 case pet_tree_infinite_loop:
971 if (pet_tree_foreach_sub_tree(tree->u.l.body, fn, user) < 0)
972 return -1;
973 break;
976 return 0;
979 /* Intermediate data structure for foreach_expr.
981 * "fn" is the function that needs to be called on each expression.
982 * "user" is the user argument to be passed to "fn".
984 struct pet_tree_foreach_expr_data {
985 int (*fn)(__isl_keep pet_expr *expr, void *user);
986 void *user;
989 /* Call data->fn on each expression in the "tree" object.
990 * This function is used as a callback to pet_tree_foreach_sub_tree
991 * to implement pet_tree_foreach_expr.
993 * Return 0 on success and -1 on error, where data->fn returning a negative
994 * value is treated as an error.
996 static int foreach_expr(__isl_keep pet_tree *tree, void *user)
998 struct pet_tree_foreach_expr_data *data = user;
1000 if (!tree)
1001 return -1;
1003 switch (tree->type) {
1004 case pet_tree_error:
1005 return -1;
1006 case pet_tree_block:
1007 case pet_tree_break:
1008 case pet_tree_continue:
1009 case pet_tree_infinite_loop:
1010 break;
1011 case pet_tree_decl:
1012 if (data->fn(tree->u.d.var, data->user) < 0)
1013 return -1;
1014 break;
1015 case pet_tree_decl_init:
1016 if (data->fn(tree->u.d.var, data->user) < 0)
1017 return -1;
1018 if (data->fn(tree->u.d.init, data->user) < 0)
1019 return -1;
1020 break;
1021 case pet_tree_expr:
1022 case pet_tree_return:
1023 if (data->fn(tree->u.e.expr, data->user) < 0)
1024 return -1;
1025 break;
1026 case pet_tree_if:
1027 if (data->fn(tree->u.i.cond, data->user) < 0)
1028 return -1;
1029 break;
1030 case pet_tree_if_else:
1031 if (data->fn(tree->u.i.cond, data->user) < 0)
1032 return -1;
1033 break;
1034 case pet_tree_while:
1035 if (data->fn(tree->u.l.cond, data->user) < 0)
1036 return -1;
1037 break;
1038 case pet_tree_for:
1039 if (data->fn(tree->u.l.iv, data->user) < 0)
1040 return -1;
1041 if (data->fn(tree->u.l.init, data->user) < 0)
1042 return -1;
1043 if (data->fn(tree->u.l.cond, data->user) < 0)
1044 return -1;
1045 if (data->fn(tree->u.l.inc, data->user) < 0)
1046 return -1;
1047 break;
1050 return 0;
1053 /* Call "fn" on each top-level expression in the nodes of "tree"
1055 * Return 0 on success and -1 on error, where "fn" returning a negative
1056 * value is treated as an error.
1058 * We run over all nodes in "tree" and call "fn"
1059 * on each expression in those nodes.
1061 int pet_tree_foreach_expr(__isl_keep pet_tree *tree,
1062 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
1064 struct pet_tree_foreach_expr_data data = { fn, user };
1066 return pet_tree_foreach_sub_tree(tree, &foreach_expr, &data);
1069 /* Intermediate data structure for foreach_access_expr.
1071 * "fn" is the function that needs to be called on each access subexpression.
1072 * "user" is the user argument to be passed to "fn".
1074 struct pet_tree_foreach_access_expr_data {
1075 int (*fn)(__isl_keep pet_expr *expr, void *user);
1076 void *user;
1079 /* Call data->fn on each access subexpression of "expr".
1080 * This function is used as a callback to pet_tree_foreach_expr
1081 * to implement pet_tree_foreach_access_expr.
1083 * Return 0 on success and -1 on error, where data->fn returning a negative
1084 * value is treated as an error.
1086 static int foreach_access_expr(__isl_keep pet_expr *expr, void *user)
1088 struct pet_tree_foreach_access_expr_data *data = user;
1090 return pet_expr_foreach_access_expr(expr, data->fn, data->user);
1093 /* Call "fn" on each access subexpression in the nodes of "tree"
1095 * Return 0 on success and -1 on error, where "fn" returning a negative
1096 * value is treated as an error.
1098 * We run over all expressions in the nodes of "tree" and call "fn"
1099 * on each access subexpression of those expressions.
1101 int pet_tree_foreach_access_expr(__isl_keep pet_tree *tree,
1102 int (*fn)(__isl_keep pet_expr *expr, void *user), void *user)
1104 struct pet_tree_foreach_access_expr_data data = { fn, user };
1106 return pet_tree_foreach_expr(tree, &foreach_access_expr, &data);
1109 /* Modify all top-level expressions in the nodes of "tree"
1110 * by calling "fn" on them.
1112 __isl_give pet_tree *pet_tree_map_expr(__isl_take pet_tree *tree,
1113 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user),
1114 void *user)
1116 int i;
1118 tree = pet_tree_cow(tree);
1119 if (!tree)
1120 return NULL;
1122 switch (tree->type) {
1123 case pet_tree_error:
1124 return pet_tree_free(tree);
1125 case pet_tree_block:
1126 for (i = 0; i < tree->u.b.n; ++i) {
1127 tree->u.b.child[i] =
1128 pet_tree_map_expr(tree->u.b.child[i], fn, user);
1129 if (!tree->u.b.child[i])
1130 return pet_tree_free(tree);
1132 break;
1133 case pet_tree_break:
1134 case pet_tree_continue:
1135 break;
1136 case pet_tree_decl:
1137 tree->u.d.var = fn(tree->u.d.var, user);
1138 if (!tree->u.d.var)
1139 return pet_tree_free(tree);
1140 break;
1141 case pet_tree_decl_init:
1142 tree->u.d.var = fn(tree->u.d.var, user);
1143 tree->u.d.init = fn(tree->u.d.init, user);
1144 if (!tree->u.d.var || !tree->u.d.init)
1145 return pet_tree_free(tree);
1146 break;
1147 case pet_tree_expr:
1148 case pet_tree_return:
1149 tree->u.e.expr = fn(tree->u.e.expr, user);
1150 if (!tree->u.e.expr)
1151 return pet_tree_free(tree);
1152 break;
1153 case pet_tree_if:
1154 tree->u.i.cond = fn(tree->u.i.cond, user);
1155 tree->u.i.then_body =
1156 pet_tree_map_expr(tree->u.i.then_body, fn, user);
1157 if (!tree->u.i.cond || !tree->u.i.then_body)
1158 return pet_tree_free(tree);
1159 break;
1160 case pet_tree_if_else:
1161 tree->u.i.cond = fn(tree->u.i.cond, user);
1162 tree->u.i.then_body =
1163 pet_tree_map_expr(tree->u.i.then_body, fn, user);
1164 tree->u.i.else_body =
1165 pet_tree_map_expr(tree->u.i.else_body, fn, user);
1166 if (!tree->u.i.cond ||
1167 !tree->u.i.then_body || !tree->u.i.else_body)
1168 return pet_tree_free(tree);
1169 break;
1170 case pet_tree_while:
1171 tree->u.l.cond = fn(tree->u.l.cond, user);
1172 tree->u.l.body = pet_tree_map_expr(tree->u.l.body, fn, user);
1173 if (!tree->u.l.cond || !tree->u.l.body)
1174 return pet_tree_free(tree);
1175 break;
1176 case pet_tree_for:
1177 tree->u.l.iv = fn(tree->u.l.iv, user);
1178 tree->u.l.init = fn(tree->u.l.init, user);
1179 tree->u.l.cond = fn(tree->u.l.cond, user);
1180 tree->u.l.inc = fn(tree->u.l.inc, user);
1181 tree->u.l.body = pet_tree_map_expr(tree->u.l.body, fn, user);
1182 if (!tree->u.l.iv || !tree->u.l.init || !tree->u.l.cond ||
1183 !tree->u.l.inc || !tree->u.l.body)
1184 return pet_tree_free(tree);
1185 break;
1186 case pet_tree_infinite_loop:
1187 tree->u.l.body = pet_tree_map_expr(tree->u.l.body, fn, user);
1188 if (!tree->u.l.body)
1189 return pet_tree_free(tree);
1190 break;
1193 return tree;
1196 /* Intermediate data structure for map_expr.
1198 * "map" is a function that modifies subexpressions of a given type.
1199 * "fn" is the function that needs to be called on each of those subexpressions.
1200 * "user" is the user argument to be passed to "fn".
1202 struct pet_tree_map_expr_data {
1203 __isl_give pet_expr *(*map)(__isl_take pet_expr *expr,
1204 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr,
1205 void *user), void *user);
1206 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user);
1207 void *user;
1210 /* This function is called on each top-level expressions in the nodes
1211 * of a tree. Call data->map to modify subexpressions of the top-level
1212 * expression by calling data->fn on them.
1214 * This is a wrapper around data->map for use as a callback
1215 * to pet_tree_map_expr.
1217 static __isl_give pet_expr *map_expr(__isl_take pet_expr *expr,
1218 void *user)
1220 struct pet_tree_map_expr_data *data = user;
1222 return data->map(expr, data->fn, data->user);
1225 /* Modify all access subexpressions in the nodes of "tree"
1226 * by calling "fn" on them.
1228 * We run over all expressions in the nodes of "tree" and call "fn"
1229 * on each access subexpression of those expressions.
1231 __isl_give pet_tree *pet_tree_map_access_expr(__isl_take pet_tree *tree,
1232 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user),
1233 void *user)
1235 struct pet_tree_map_expr_data data = { &pet_expr_map_access, fn, user };
1237 return pet_tree_map_expr(tree, &map_expr, &data);
1240 /* Modify all call subexpressions in the nodes of "tree"
1241 * by calling "fn" on them.
1243 * We run over all expressions in the nodes of "tree" and call "fn"
1244 * on each call subexpression of those expressions.
1246 __isl_give pet_tree *pet_tree_map_call_expr(__isl_take pet_tree *tree,
1247 __isl_give pet_expr *(*fn)(__isl_take pet_expr *expr, void *user),
1248 void *user)
1250 struct pet_tree_map_expr_data data = { &pet_expr_map_call, fn, user };
1252 return pet_tree_map_expr(tree, &map_expr, &data);
1255 /* Wrapper around pet_expr_align_params
1256 * for use as a pet_tree_map_expr callback.
1258 static __isl_give pet_expr *align_params(__isl_take pet_expr *expr,
1259 void *user)
1261 isl_space *space = user;
1263 return pet_expr_align_params(expr, isl_space_copy(space));
1266 /* Add all parameters in "space" to all access relations and index expressions
1267 * in "tree".
1269 __isl_give pet_tree *pet_tree_align_params(__isl_take pet_tree *tree,
1270 __isl_take isl_space *space)
1272 tree = pet_tree_map_expr(tree, &align_params, space);
1273 isl_space_free(space);
1274 return tree;
1277 /* Wrapper around pet_expr_add_ref_ids
1278 * for use as a pet_tree_map_expr callback.
1280 static __isl_give pet_expr *add_ref_ids(__isl_take pet_expr *expr, void *user)
1282 int *n_ref = user;
1284 return pet_expr_add_ref_ids(expr, n_ref);
1287 /* Add reference identifiers to all access expressions in "tree".
1288 * "n_ref" points to an integer that contains the sequence number
1289 * of the next reference.
1291 __isl_give pet_tree *pet_tree_add_ref_ids(__isl_take pet_tree *tree,
1292 int *n_ref)
1294 return pet_tree_map_expr(tree, &add_ref_ids, n_ref);
1297 /* Wrapper around pet_expr_anonymize
1298 * for use as a pet_tree_map_expr callback.
1300 static __isl_give pet_expr *anonymize(__isl_take pet_expr *expr, void *user)
1302 return pet_expr_anonymize(expr);
1305 /* Reset the user pointer on all parameter and tuple ids in "tree".
1307 __isl_give pet_tree *pet_tree_anonymize(__isl_take pet_tree *tree)
1309 return pet_tree_map_expr(tree, &anonymize, NULL);
1312 /* Arguments to be passed to pet_expr_gist from the gist wrapper.
1314 struct pet_tree_gist_data {
1315 isl_set *domain;
1316 isl_union_map *value_bounds;
1319 /* Wrapper around pet_expr_gist for use as a pet_tree_map_expr callback.
1321 static __isl_give pet_expr *gist(__isl_take pet_expr *expr, void *user)
1323 struct pet_tree_gist_data *data = user;
1325 return pet_expr_gist(expr, data->domain, data->value_bounds);
1328 /* Compute the gist of all access relations and index expressions inside
1329 * "tree" based on the constraints on the parameters specified by "context"
1330 * and the constraints on the values of nested accesses specified
1331 * by "value_bounds".
1333 __isl_give pet_tree *pet_tree_gist(__isl_take pet_tree *tree,
1334 __isl_keep isl_set *context, __isl_keep isl_union_map *value_bounds)
1336 struct pet_tree_gist_data data = { context, value_bounds };
1338 return pet_tree_map_expr(tree, &gist, &data);
1341 /* Return 1 if the two pet_tree objects are equivalent.
1343 * We ignore the locations of the trees.
1345 int pet_tree_is_equal(__isl_keep pet_tree *tree1, __isl_keep pet_tree *tree2)
1347 int i;
1348 int equal;
1350 if (!tree1 || !tree2)
1351 return 0;
1353 if (tree1 == tree2)
1354 return 1;
1356 if (tree1->type != tree2->type)
1357 return 0;
1358 if (tree1->label != tree2->label)
1359 return 0;
1361 switch (tree1->type) {
1362 case pet_tree_error:
1363 return -1;
1364 case pet_tree_block:
1365 if (tree1->u.b.block != tree2->u.b.block)
1366 return 0;
1367 if (tree1->u.b.n != tree2->u.b.n)
1368 return 0;
1369 for (i = 0; i < tree1->u.b.n; ++i) {
1370 equal = pet_tree_is_equal(tree1->u.b.child[i],
1371 tree2->u.b.child[i]);
1372 if (equal < 0 || !equal)
1373 return equal;
1375 break;
1376 case pet_tree_break:
1377 case pet_tree_continue:
1378 break;
1379 case pet_tree_decl:
1380 return pet_expr_is_equal(tree1->u.d.var, tree2->u.d.var);
1381 case pet_tree_decl_init:
1382 equal = pet_expr_is_equal(tree1->u.d.var, tree2->u.d.var);
1383 if (equal < 0 || !equal)
1384 return equal;
1385 return pet_expr_is_equal(tree1->u.d.init, tree2->u.d.init);
1386 case pet_tree_expr:
1387 case pet_tree_return:
1388 return pet_expr_is_equal(tree1->u.e.expr, tree2->u.e.expr);
1389 case pet_tree_for:
1390 if (tree1->u.l.declared != tree2->u.l.declared)
1391 return 0;
1392 equal = pet_expr_is_equal(tree1->u.l.iv, tree2->u.l.iv);
1393 if (equal < 0 || !equal)
1394 return equal;
1395 equal = pet_expr_is_equal(tree1->u.l.init, tree2->u.l.init);
1396 if (equal < 0 || !equal)
1397 return equal;
1398 equal = pet_expr_is_equal(tree1->u.l.cond, tree2->u.l.cond);
1399 if (equal < 0 || !equal)
1400 return equal;
1401 equal = pet_expr_is_equal(tree1->u.l.inc, tree2->u.l.inc);
1402 if (equal < 0 || !equal)
1403 return equal;
1404 return pet_tree_is_equal(tree1->u.l.body, tree2->u.l.body);
1405 case pet_tree_while:
1406 equal = pet_expr_is_equal(tree1->u.l.cond, tree2->u.l.cond);
1407 if (equal < 0 || !equal)
1408 return equal;
1409 return pet_tree_is_equal(tree1->u.l.body, tree2->u.l.body);
1410 case pet_tree_infinite_loop:
1411 return pet_tree_is_equal(tree1->u.l.body, tree2->u.l.body);
1412 case pet_tree_if:
1413 equal = pet_expr_is_equal(tree1->u.i.cond, tree2->u.i.cond);
1414 if (equal < 0 || !equal)
1415 return equal;
1416 return pet_tree_is_equal(tree1->u.i.then_body,
1417 tree2->u.i.then_body);
1418 case pet_tree_if_else:
1419 equal = pet_expr_is_equal(tree1->u.i.cond, tree2->u.i.cond);
1420 if (equal < 0 || !equal)
1421 return equal;
1422 equal = pet_tree_is_equal(tree1->u.i.then_body,
1423 tree2->u.i.then_body);
1424 if (equal < 0 || !equal)
1425 return equal;
1426 return pet_tree_is_equal(tree1->u.i.else_body,
1427 tree2->u.i.else_body);
1430 return 1;
1433 /* Is "tree" an expression tree that performs the operation "type"?
1435 static int pet_tree_is_op_of_type(__isl_keep pet_tree *tree,
1436 enum pet_op_type type)
1438 if (!tree)
1439 return 0;
1440 if (tree->type != pet_tree_expr)
1441 return 0;
1442 if (pet_expr_get_type(tree->u.e.expr) != pet_expr_op)
1443 return 0;
1444 return pet_expr_op_get_type(tree->u.e.expr) == type;
1447 /* Is "tree" an expression tree that performs a kill operation?
1449 int pet_tree_is_kill(__isl_keep pet_tree *tree)
1451 return pet_tree_is_op_of_type(tree, pet_op_kill);
1454 /* Is "tree" an expression tree that performs an assignment operation?
1456 int pet_tree_is_assign(__isl_keep pet_tree *tree)
1458 return pet_tree_is_op_of_type(tree, pet_op_assign);
1461 /* Is "tree" an expression tree that performs an assume operation?
1463 int pet_tree_is_assume(__isl_keep pet_tree *tree)
1465 return pet_tree_is_op_of_type(tree, pet_op_assume);
1468 /* Is "tree" an expression tree that performs an assume operation
1469 * such that the assumed expression is affine?
1471 isl_bool pet_tree_is_affine_assume(__isl_keep pet_tree *tree)
1473 if (!pet_tree_is_assume(tree))
1474 return isl_bool_false;
1475 return pet_expr_is_affine(tree->u.e.expr->args[0]);
1478 /* Given a tree that represent an assume operation expression
1479 * with an access as argument (possibly an affine expression),
1480 * return the index expression of that access.
1482 __isl_give isl_multi_pw_aff *pet_tree_assume_get_index(
1483 __isl_keep pet_tree *tree)
1485 if (!tree)
1486 return NULL;
1487 if (!pet_tree_is_assume(tree))
1488 isl_die(pet_tree_get_ctx(tree), isl_error_invalid,
1489 "not an assume tree", return NULL);
1490 return pet_expr_access_get_index(tree->u.e.expr->args[0]);
1493 /* Internal data structure for pet_tree_writes.
1494 * "id" is the identifier that we are looking for.
1495 * "writes" is set if we have found the identifier being written to.
1497 struct pet_tree_writes_data {
1498 isl_id *id;
1499 int writes;
1502 /* Check if expr writes to data->id.
1503 * If so, set data->writes and abort the search.
1505 static int check_write(__isl_keep pet_expr *expr, void *user)
1507 struct pet_tree_writes_data *data = user;
1509 data->writes = pet_expr_writes(expr, data->id);
1510 if (data->writes < 0 || data->writes)
1511 return -1;
1513 return 0;
1516 /* Is there any write access in "tree" that accesses "id"?
1518 int pet_tree_writes(__isl_keep pet_tree *tree, __isl_keep isl_id *id)
1520 struct pet_tree_writes_data data;
1522 data.id = id;
1523 data.writes = 0;
1524 if (pet_tree_foreach_expr(tree, &check_write, &data) < 0 &&
1525 !data.writes)
1526 return -1;
1528 return data.writes;
1531 /* Wrapper around pet_expr_update_domain
1532 * for use as a pet_tree_map_expr callback.
1534 static __isl_give pet_expr *update_domain(__isl_take pet_expr *expr, void *user)
1536 isl_multi_pw_aff *update = user;
1538 return pet_expr_update_domain(expr, isl_multi_pw_aff_copy(update));
1541 /* Modify all access relations in "tree" by precomposing them with
1542 * the given iteration space transformation.
1544 __isl_give pet_tree *pet_tree_update_domain(__isl_take pet_tree *tree,
1545 __isl_take isl_multi_pw_aff *update)
1547 tree = pet_tree_map_expr(tree, &update_domain, update);
1548 isl_multi_pw_aff_free(update);
1549 return tree;
1552 /* Does "tree" contain a continue or break node (not contained in any loop
1553 * subtree of "tree")?
1555 int pet_tree_has_continue_or_break(__isl_keep pet_tree *tree)
1557 int i;
1558 int found;
1560 if (!tree)
1561 return -1;
1563 switch (tree->type) {
1564 case pet_tree_error:
1565 return -1;
1566 case pet_tree_continue:
1567 case pet_tree_break:
1568 return 1;
1569 case pet_tree_decl:
1570 case pet_tree_decl_init:
1571 case pet_tree_expr:
1572 case pet_tree_return:
1573 case pet_tree_for:
1574 case pet_tree_while:
1575 case pet_tree_infinite_loop:
1576 return 0;
1577 case pet_tree_block:
1578 for (i = 0; i < tree->u.b.n; ++i) {
1579 found =
1580 pet_tree_has_continue_or_break(tree->u.b.child[i]);
1581 if (found < 0 || found)
1582 return found;
1584 return 0;
1585 case pet_tree_if:
1586 return pet_tree_has_continue_or_break(tree->u.i.then_body);
1587 case pet_tree_if_else:
1588 found = pet_tree_has_continue_or_break(tree->u.i.then_body);
1589 if (found < 0 || found)
1590 return found;
1591 return pet_tree_has_continue_or_break(tree->u.i.else_body);
1595 static void print_indent(int indent)
1597 fprintf(stderr, "%*s", indent, "");
1600 void pet_tree_dump_with_indent(__isl_keep pet_tree *tree, int indent)
1602 int i;
1604 if (!tree)
1605 return;
1607 print_indent(indent);
1608 fprintf(stderr, "%s\n", pet_tree_type_str(tree->type));
1609 print_indent(indent);
1610 fprintf(stderr, "line: %d\n", pet_loc_get_line(tree->loc));
1611 print_indent(indent);
1612 fprintf(stderr, "start: %d\n", pet_loc_get_start(tree->loc));
1613 print_indent(indent);
1614 fprintf(stderr, "end: %d\n", pet_loc_get_end(tree->loc));
1615 if (tree->label) {
1616 print_indent(indent);
1617 fprintf(stderr, "label: ");
1618 isl_id_dump(tree->label);
1620 switch (tree->type) {
1621 case pet_tree_block:
1622 print_indent(indent);
1623 fprintf(stderr, "block: %d\n", tree->u.b.block);
1624 for (i = 0; i < tree->u.b.n; ++i)
1625 pet_tree_dump_with_indent(tree->u.b.child[i],
1626 indent + 2);
1627 break;
1628 case pet_tree_expr:
1629 pet_expr_dump_with_indent(tree->u.e.expr, indent);
1630 break;
1631 case pet_tree_return:
1632 print_indent(indent);
1633 fprintf(stderr, "return:\n");
1634 pet_expr_dump_with_indent(tree->u.e.expr, indent);
1635 break;
1636 case pet_tree_break:
1637 case pet_tree_continue:
1638 break;
1639 case pet_tree_decl:
1640 case pet_tree_decl_init:
1641 print_indent(indent);
1642 fprintf(stderr, "var:\n");
1643 pet_expr_dump_with_indent(tree->u.d.var, indent + 2);
1644 if (tree->type != pet_tree_decl_init)
1645 break;
1646 print_indent(indent);
1647 fprintf(stderr, "init:\n");
1648 pet_expr_dump_with_indent(tree->u.d.init, indent + 2);
1649 break;
1650 case pet_tree_if:
1651 case pet_tree_if_else:
1652 print_indent(indent);
1653 fprintf(stderr, "condition:\n");
1654 pet_expr_dump_with_indent(tree->u.i.cond, indent + 2);
1655 print_indent(indent);
1656 fprintf(stderr, "then:\n");
1657 pet_tree_dump_with_indent(tree->u.i.then_body, indent + 2);
1658 if (tree->type != pet_tree_if_else)
1659 break;
1660 print_indent(indent);
1661 fprintf(stderr, "else:\n");
1662 pet_tree_dump_with_indent(tree->u.i.else_body, indent + 2);
1663 break;
1664 case pet_tree_for:
1665 print_indent(indent);
1666 fprintf(stderr, "declared: %d\n", tree->u.l.declared);
1667 print_indent(indent);
1668 fprintf(stderr, "var:\n");
1669 pet_expr_dump_with_indent(tree->u.l.iv, indent + 2);
1670 print_indent(indent);
1671 fprintf(stderr, "init:\n");
1672 pet_expr_dump_with_indent(tree->u.l.init, indent + 2);
1673 print_indent(indent);
1674 fprintf(stderr, "inc:\n");
1675 pet_expr_dump_with_indent(tree->u.l.inc, indent + 2);
1676 case pet_tree_while:
1677 print_indent(indent);
1678 fprintf(stderr, "condition:\n");
1679 pet_expr_dump_with_indent(tree->u.l.cond, indent + 2);
1680 case pet_tree_infinite_loop:
1681 print_indent(indent);
1682 fprintf(stderr, "body:\n");
1683 pet_tree_dump_with_indent(tree->u.l.body, indent + 2);
1684 break;
1685 case pet_tree_error:
1686 print_indent(indent);
1687 fprintf(stderr, "ERROR\n");
1688 break;
1692 void pet_tree_dump(__isl_keep pet_tree *tree)
1694 pet_tree_dump_with_indent(tree, 0);