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
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
40 #include <isl/space.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",
59 [pet_tree_if_else
] = "if-else",
60 [pet_tree_while
] = "while",
63 /* Return a textual representation of the type "type".
65 const char *pet_tree_type_str(enum pet_tree_type type
)
69 return type_str
[type
];
72 /* Extract a type from its textual representation "str".
74 enum pet_tree_type
pet_tree_str_type(const char *str
)
78 for (i
= 0; i
< ARRAY_SIZE(type_str
); ++i
)
79 if (!strcmp(type_str
[i
], str
))
82 return pet_tree_error
;
85 /* Return a new pet_tree of the given type.
87 * The location is initializaed to pet_loc_dummy.
89 __isl_give pet_tree
*pet_tree_alloc(isl_ctx
*ctx
, enum pet_tree_type type
)
93 tree
= isl_calloc_type(ctx
, struct pet_tree
);
101 tree
->loc
= &pet_loc_dummy
;
106 /* Return a new pet_tree representing the declaration (without initialization)
107 * of the variable "var".
109 __isl_give pet_tree
*pet_tree_new_decl(__isl_take pet_expr
*var
)
116 ctx
= pet_expr_get_ctx(var
);
117 tree
= pet_tree_alloc(ctx
, pet_tree_decl
);
129 /* Return a new pet_tree representing the declaration of the variable "var"
130 * with initial value "init".
132 __isl_give pet_tree
*pet_tree_new_decl_init(__isl_take pet_expr
*var
,
133 __isl_take pet_expr
*init
)
140 ctx
= pet_expr_get_ctx(var
);
141 tree
= pet_tree_alloc(ctx
, pet_tree_decl_init
);
146 tree
->u
.d
.init
= init
;
155 /* Return a new pet_tree representing the expression "expr".
157 __isl_give pet_tree
*pet_tree_new_expr(__isl_take pet_expr
*expr
)
164 ctx
= pet_expr_get_ctx(expr
);
165 tree
= pet_tree_alloc(ctx
, pet_tree_expr
);
169 tree
->u
.e
.expr
= expr
;
177 /* Return a new pet_tree representing an intially empty sequence
178 * of trees with room for "n" trees.
179 * "block" indicates whether the sequence has its own scope.
181 __isl_give pet_tree
*pet_tree_new_block(isl_ctx
*ctx
, int block
, int n
)
185 tree
= pet_tree_alloc(ctx
, pet_tree_block
);
188 tree
->u
.b
.block
= block
;
191 tree
->u
.b
.child
= isl_calloc_array(ctx
, pet_tree
*, n
);
192 if (n
&& !tree
->u
.b
.child
)
193 return pet_tree_free(tree
);
198 /* Return a new pet_tree representing a break statement.
200 __isl_give pet_tree
*pet_tree_new_break(isl_ctx
*ctx
)
202 return pet_tree_alloc(ctx
, pet_tree_break
);
205 /* Return a new pet_tree representing a continue statement.
207 __isl_give pet_tree
*pet_tree_new_continue(isl_ctx
*ctx
)
209 return pet_tree_alloc(ctx
, pet_tree_continue
);
212 /* Return a new pet_tree representing a for loop
213 * with induction variable "iv", initial value for the induction
214 * variable "init", loop condition "cond", induction variable increment "inc"
215 * and loop body "body". "declared" indicates whether the induction variable
216 * is declared by the loop. "independent" is set if the for loop is marked
219 * The location of the loop is initialized to that of the body.
221 __isl_give pet_tree
*pet_tree_new_for(int independent
, int declared
,
222 __isl_take pet_expr
*iv
, __isl_take pet_expr
*init
,
223 __isl_take pet_expr
*cond
, __isl_take pet_expr
*inc
,
224 __isl_take pet_tree
*body
)
229 if (!iv
|| !init
|| !cond
|| !inc
|| !body
)
231 ctx
= pet_tree_get_ctx(body
);
232 tree
= pet_tree_alloc(ctx
, pet_tree_for
);
236 tree
->u
.l
.independent
= independent
;
237 tree
->u
.l
.declared
= declared
;
239 tree
->u
.l
.init
= init
;
240 tree
->u
.l
.cond
= cond
;
242 tree
->u
.l
.body
= body
;
243 tree
->loc
= pet_tree_get_loc(body
);
245 return pet_tree_free(tree
);
257 /* Return a new pet_tree representing a while loop
258 * with loop condition "cond" and loop body "body".
260 * The location of the loop is initialized to that of the body.
262 __isl_give pet_tree
*pet_tree_new_while(__isl_take pet_expr
*cond
,
263 __isl_take pet_tree
*body
)
270 ctx
= pet_tree_get_ctx(body
);
271 tree
= pet_tree_alloc(ctx
, pet_tree_while
);
275 tree
->u
.l
.cond
= cond
;
276 tree
->u
.l
.body
= body
;
277 tree
->loc
= pet_tree_get_loc(body
);
279 return pet_tree_free(tree
);
288 /* Return a new pet_tree representing an infinite loop
289 * with loop body "body".
291 * The location of the loop is initialized to that of the body.
293 __isl_give pet_tree
*pet_tree_new_infinite_loop(__isl_take pet_tree
*body
)
300 ctx
= pet_tree_get_ctx(body
);
301 tree
= pet_tree_alloc(ctx
, pet_tree_infinite_loop
);
303 return pet_tree_free(body
);
305 tree
->u
.l
.body
= body
;
306 tree
->loc
= pet_tree_get_loc(body
);
308 return pet_tree_free(tree
);
313 /* Return a new pet_tree representing an if statement
314 * with condition "cond" and then branch "then_body".
316 * The location of the if statement is initialized to that of the body.
318 __isl_give pet_tree
*pet_tree_new_if(__isl_take pet_expr
*cond
,
319 __isl_take pet_tree
*then_body
)
324 if (!cond
|| !then_body
)
326 ctx
= pet_tree_get_ctx(then_body
);
327 tree
= pet_tree_alloc(ctx
, pet_tree_if
);
331 tree
->u
.i
.cond
= cond
;
332 tree
->u
.i
.then_body
= then_body
;
333 tree
->loc
= pet_tree_get_loc(then_body
);
335 return pet_tree_free(tree
);
340 pet_tree_free(then_body
);
344 /* Return a new pet_tree representing an if statement
345 * with condition "cond", then branch "then_body" and else branch "else_body".
347 * The location of the if statement is initialized to cover
348 * those of the bodies.
350 __isl_give pet_tree
*pet_tree_new_if_else(__isl_take pet_expr
*cond
,
351 __isl_take pet_tree
*then_body
, __isl_take pet_tree
*else_body
)
356 if (!cond
|| !then_body
|| !else_body
)
358 ctx
= pet_tree_get_ctx(then_body
);
359 tree
= pet_tree_alloc(ctx
, pet_tree_if_else
);
363 tree
->u
.i
.cond
= cond
;
364 tree
->u
.i
.then_body
= then_body
;
365 tree
->u
.i
.else_body
= else_body
;
366 tree
->loc
= pet_tree_get_loc(then_body
);
367 tree
->loc
= pet_loc_update_start_end_from_loc(tree
->loc
,
370 return pet_tree_free(tree
);
375 pet_tree_free(then_body
);
376 pet_tree_free(else_body
);
380 /* Return an independent duplicate of "tree".
382 static __isl_give pet_tree
*pet_tree_dup(__isl_keep pet_tree
*tree
)
390 switch (tree
->type
) {
394 dup
= pet_tree_new_block(tree
->ctx
, tree
->u
.b
.block
,
396 for (i
= 0; i
< tree
->u
.b
.n
; ++i
)
397 dup
= pet_tree_block_add_child(dup
,
398 pet_tree_copy(tree
->u
.b
.child
[i
]));
401 dup
= pet_tree_new_break(tree
->ctx
);
403 case pet_tree_continue
:
404 dup
= pet_tree_new_continue(tree
->ctx
);
407 dup
= pet_tree_new_decl(pet_expr_copy(tree
->u
.d
.var
));
409 case pet_tree_decl_init
:
410 dup
= pet_tree_new_decl_init(pet_expr_copy(tree
->u
.d
.var
),
411 pet_expr_copy(tree
->u
.d
.init
));
414 dup
= pet_tree_new_expr(pet_expr_copy(tree
->u
.e
.expr
));
417 dup
= pet_tree_new_for(tree
->u
.l
.independent
,
419 pet_expr_copy(tree
->u
.l
.iv
), pet_expr_copy(tree
->u
.l
.init
),
420 pet_expr_copy(tree
->u
.l
.cond
), pet_expr_copy(tree
->u
.l
.inc
),
421 pet_tree_copy(tree
->u
.l
.body
));
424 dup
= pet_tree_new_while(pet_expr_copy(tree
->u
.l
.cond
),
425 pet_tree_copy(tree
->u
.l
.body
));
427 case pet_tree_infinite_loop
:
428 dup
= pet_tree_new_infinite_loop(pet_tree_copy(tree
->u
.l
.body
));
431 dup
= pet_tree_new_if(pet_expr_copy(tree
->u
.i
.cond
),
432 pet_tree_copy(tree
->u
.i
.then_body
));
434 case pet_tree_if_else
:
435 dup
= pet_tree_new_if_else(pet_expr_copy(tree
->u
.i
.cond
),
436 pet_tree_copy(tree
->u
.i
.then_body
),
437 pet_tree_copy(tree
->u
.i
.else_body
));
443 pet_loc_free(dup
->loc
);
444 dup
->loc
= pet_loc_copy(tree
->loc
);
446 return pet_tree_free(dup
);
448 dup
->label
= isl_id_copy(tree
->label
);
450 return pet_tree_free(dup
);
456 /* Return a pet_tree that is equal to "tree" and that has only one reference.
458 __isl_give pet_tree
*pet_tree_cow(__isl_take pet_tree
*tree
)
466 return pet_tree_dup(tree
);
469 /* Return an extra reference to "tree".
471 __isl_give pet_tree
*pet_tree_copy(__isl_keep pet_tree
*tree
)
480 /* Free a reference to "tree".
482 __isl_null pet_tree
*pet_tree_free(__isl_take pet_tree
*tree
)
491 pet_loc_free(tree
->loc
);
492 isl_id_free(tree
->label
);
494 switch (tree
->type
) {
498 for (i
= 0; i
< tree
->u
.b
.n
; ++i
)
499 pet_tree_free(tree
->u
.b
.child
[i
]);
500 free(tree
->u
.b
.child
);
503 case pet_tree_continue
:
505 case pet_tree_decl_init
:
506 pet_expr_free(tree
->u
.d
.init
);
508 pet_expr_free(tree
->u
.d
.var
);
511 pet_expr_free(tree
->u
.e
.expr
);
514 pet_expr_free(tree
->u
.l
.iv
);
515 pet_expr_free(tree
->u
.l
.init
);
516 pet_expr_free(tree
->u
.l
.inc
);
518 pet_expr_free(tree
->u
.l
.cond
);
519 case pet_tree_infinite_loop
:
520 pet_tree_free(tree
->u
.l
.body
);
522 case pet_tree_if_else
:
523 pet_tree_free(tree
->u
.i
.else_body
);
525 pet_expr_free(tree
->u
.i
.cond
);
526 pet_tree_free(tree
->u
.i
.then_body
);
530 isl_ctx_deref(tree
->ctx
);
535 /* Return the isl_ctx in which "tree" was created.
537 isl_ctx
*pet_tree_get_ctx(__isl_keep pet_tree
*tree
)
539 return tree
? tree
->ctx
: NULL
;
542 /* Return the location of "tree".
544 __isl_give pet_loc
*pet_tree_get_loc(__isl_keep pet_tree
*tree
)
546 return tree
? pet_loc_copy(tree
->loc
) : NULL
;
549 /* Return the type of "tree".
551 enum pet_tree_type
pet_tree_get_type(__isl_keep pet_tree
*tree
)
554 return pet_tree_error
;
559 /* Replace the location of "tree" by "loc".
561 __isl_give pet_tree
*pet_tree_set_loc(__isl_take pet_tree
*tree
,
562 __isl_take pet_loc
*loc
)
564 tree
= pet_tree_cow(tree
);
568 pet_loc_free(tree
->loc
);
578 /* Replace the label of "tree" by "label".
580 __isl_give pet_tree
*pet_tree_set_label(__isl_take pet_tree
*tree
,
581 __isl_take isl_id
*label
)
583 tree
= pet_tree_cow(tree
);
587 isl_id_free(tree
->label
);
593 return pet_tree_free(tree
);
596 /* Given an expression tree "tree", return the associated expression.
598 __isl_give pet_expr
*pet_tree_expr_get_expr(__isl_keep pet_tree
*tree
)
602 if (pet_tree_get_type(tree
) != pet_tree_expr
)
603 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
604 "not an expression tree", return NULL
);
606 return pet_expr_copy(tree
->u
.e
.expr
);
609 /* Given a block tree "tree", return the number of children in the sequence.
611 int pet_tree_block_n_child(__isl_keep pet_tree
*tree
)
615 if (pet_tree_get_type(tree
) != pet_tree_block
)
616 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
617 "not a block tree", return -1);
622 /* Add "child" to the sequence of trees represented by "block".
624 * Update the location of "block" to include that of "child".
626 __isl_give pet_tree
*pet_tree_block_add_child(__isl_take pet_tree
*block
,
627 __isl_take pet_tree
*child
)
629 block
= pet_tree_cow(block
);
630 if (!block
|| !child
)
632 if (block
->type
!= pet_tree_block
)
633 isl_die(pet_tree_get_ctx(block
), isl_error_invalid
,
634 "not a block tree", goto error
);
635 if (block
->u
.b
.n
>= block
->u
.b
.max
)
636 isl_die(pet_tree_get_ctx(block
), isl_error_invalid
,
637 "out of space in block", goto error
);
639 block
->loc
= pet_loc_update_start_end_from_loc(block
->loc
, child
->loc
);
640 block
->u
.b
.child
[block
->u
.b
.n
++] = child
;
643 return pet_tree_free(block
);
647 pet_tree_free(block
);
648 pet_tree_free(child
);
652 /* Does the block tree "tree" have its own scope?
654 int pet_tree_block_get_block(__isl_keep pet_tree
*tree
)
658 if (pet_tree_get_type(tree
) != pet_tree_block
)
659 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
660 "not a block tree", return -1);
662 return tree
->u
.b
.block
;
665 /* Set the block property (whether or not the block tree has its own scope)
666 * of "tree" to "is_block".
668 __isl_give pet_tree
*pet_tree_block_set_block(__isl_take pet_tree
*tree
,
673 if (tree
->type
!= pet_tree_block
)
674 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
675 "not a block tree", return pet_tree_free(tree
));
676 if (tree
->u
.b
.block
== is_block
)
678 tree
= pet_tree_cow(tree
);
681 tree
->u
.b
.block
= is_block
;
685 /* Given a block tree "tree", return the child at position "pos".
687 __isl_give pet_tree
*pet_tree_block_get_child(__isl_keep pet_tree
*tree
,
692 if (pet_tree_get_type(tree
) != pet_tree_block
)
693 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
694 "not a block tree", return NULL
);
695 if (pos
< 0 || pos
>= tree
->u
.b
.n
)
696 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
697 "position out of bounds", return NULL
);
699 return pet_tree_copy(tree
->u
.b
.child
[pos
]);
702 /* Does "tree" represent a declaration (with or without initialization)?
704 int pet_tree_is_decl(__isl_keep pet_tree
*tree
)
709 switch (pet_tree_get_type(tree
)) {
711 case pet_tree_decl_init
:
718 /* Given a declaration tree "tree", return the variable that is being
721 __isl_give pet_expr
*pet_tree_decl_get_var(__isl_keep pet_tree
*tree
)
725 if (!pet_tree_is_decl(tree
))
726 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
727 "not a decl tree", return NULL
);
729 return pet_expr_copy(tree
->u
.d
.var
);
732 /* Given a declaration tree with initialization "tree",
733 * return the initial value of the declared variable.
735 __isl_give pet_expr
*pet_tree_decl_get_init(__isl_keep pet_tree
*tree
)
739 if (pet_tree_get_type(tree
) != pet_tree_decl_init
)
740 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
741 "not a decl_init tree", return NULL
);
743 return pet_expr_copy(tree
->u
.d
.init
);
746 /* Given an if tree "tree", return the if condition.
748 __isl_give pet_expr
*pet_tree_if_get_cond(__isl_keep pet_tree
*tree
)
750 enum pet_tree_type type
;
754 type
= pet_tree_get_type(tree
);
755 if (type
!= pet_tree_if
&& type
!= pet_tree_if_else
)
756 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
757 "not an if tree", return NULL
);
759 return pet_expr_copy(tree
->u
.i
.cond
);
762 /* Given an if tree "tree", return the body of the then branch.
764 __isl_give pet_tree
*pet_tree_if_get_then(__isl_keep pet_tree
*tree
)
766 enum pet_tree_type type
;
770 type
= pet_tree_get_type(tree
);
771 if (type
!= pet_tree_if
&& type
!= pet_tree_if_else
)
772 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
773 "not an if tree", return NULL
);
775 return pet_tree_copy(tree
->u
.i
.then_body
);
778 /* Given an if tree with an else branch "tree",
779 * return the body of that else branch.
781 __isl_give pet_tree
*pet_tree_if_get_else(__isl_keep pet_tree
*tree
)
785 if (pet_tree_get_type(tree
) != pet_tree_if_else
)
786 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
787 "not an if tree with an else branch", return NULL
);
789 return pet_tree_copy(tree
->u
.i
.else_body
);
792 /* Does "tree" represent some type of loop?
794 int pet_tree_is_loop(__isl_keep pet_tree
*tree
)
799 switch (pet_tree_get_type(tree
)) {
801 case pet_tree_infinite_loop
:
809 /* Given a for loop "tree", return the induction variable.
811 __isl_give pet_expr
*pet_tree_loop_get_var(__isl_keep pet_tree
*tree
)
815 if (pet_tree_get_type(tree
) != pet_tree_for
)
816 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
817 "not a for tree", return NULL
);
819 return pet_expr_copy(tree
->u
.l
.iv
);
822 /* Given a for loop "tree", return the initial value of the induction variable.
824 __isl_give pet_expr
*pet_tree_loop_get_init(__isl_keep pet_tree
*tree
)
828 if (pet_tree_get_type(tree
) != pet_tree_for
)
829 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
830 "not a for tree", return NULL
);
832 return pet_expr_copy(tree
->u
.l
.init
);
835 /* Given a loop "tree", return the loop condition.
837 * For an infinite loop, the loop condition always holds,
838 * so we simply return "1".
840 __isl_give pet_expr
*pet_tree_loop_get_cond(__isl_keep pet_tree
*tree
)
842 enum pet_tree_type type
;
846 type
= pet_tree_get_type(tree
);
847 if (type
== pet_tree_infinite_loop
)
848 return pet_expr_new_int(isl_val_one(pet_tree_get_ctx(tree
)));
849 if (type
!= pet_tree_for
&& type
!= pet_tree_while
)
850 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
851 "not a for or while tree", return NULL
);
853 return pet_expr_copy(tree
->u
.l
.cond
);
856 /* Given a for loop "tree", return the increment of the induction variable.
858 __isl_give pet_expr
*pet_tree_loop_get_inc(__isl_keep pet_tree
*tree
)
862 if (pet_tree_get_type(tree
) != pet_tree_for
)
863 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
864 "not a for tree", return NULL
);
866 return pet_expr_copy(tree
->u
.l
.inc
);
869 /* Given a loop tree "tree", return the body.
871 __isl_give pet_tree
*pet_tree_loop_get_body(__isl_keep pet_tree
*tree
)
876 if (!pet_tree_is_loop(tree
))
877 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
878 "not a loop tree", return NULL
);
880 return pet_tree_copy(tree
->u
.l
.body
);
883 /* Call "fn" on each node of "tree", including "tree" itself.
885 * Return 0 on success and -1 on error, where "fn" returning a negative
886 * value is treated as an error.
888 int pet_tree_foreach_sub_tree(__isl_keep pet_tree
*tree
,
889 int (*fn
)(__isl_keep pet_tree
*tree
, void *user
), void *user
)
896 if (fn(tree
, user
) < 0)
899 switch (tree
->type
) {
903 for (i
= 0; i
< tree
->u
.b
.n
; ++i
)
904 if (pet_tree_foreach_sub_tree(tree
->u
.b
.child
[i
],
909 case pet_tree_continue
:
911 case pet_tree_decl_init
:
915 if (pet_tree_foreach_sub_tree(tree
->u
.i
.then_body
,
919 case pet_tree_if_else
:
920 if (pet_tree_foreach_sub_tree(tree
->u
.i
.then_body
,
923 if (pet_tree_foreach_sub_tree(tree
->u
.i
.else_body
,
929 case pet_tree_infinite_loop
:
930 if (pet_tree_foreach_sub_tree(tree
->u
.l
.body
, fn
, user
) < 0)
938 /* Intermediate data structure for foreach_expr.
940 * "fn" is the function that needs to be called on each expression.
941 * "user" is the user argument to be passed to "fn".
943 struct pet_tree_foreach_expr_data
{
944 int (*fn
)(__isl_keep pet_expr
*expr
, void *user
);
948 /* Call data->fn on each expression in the "tree" object.
949 * This function is used as a callback to pet_tree_foreach_sub_tree
950 * to implement pet_tree_foreach_expr.
952 * Return 0 on success and -1 on error, where data->fn returning a negative
953 * value is treated as an error.
955 static int foreach_expr(__isl_keep pet_tree
*tree
, void *user
)
957 struct pet_tree_foreach_expr_data
*data
= user
;
962 switch (tree
->type
) {
967 case pet_tree_continue
:
968 case pet_tree_infinite_loop
:
971 if (data
->fn(tree
->u
.d
.var
, data
->user
) < 0)
974 case pet_tree_decl_init
:
975 if (data
->fn(tree
->u
.d
.var
, data
->user
) < 0)
977 if (data
->fn(tree
->u
.d
.init
, data
->user
) < 0)
981 if (data
->fn(tree
->u
.e
.expr
, data
->user
) < 0)
985 if (data
->fn(tree
->u
.i
.cond
, data
->user
) < 0)
988 case pet_tree_if_else
:
989 if (data
->fn(tree
->u
.i
.cond
, data
->user
) < 0)
993 if (data
->fn(tree
->u
.l
.cond
, data
->user
) < 0)
997 if (data
->fn(tree
->u
.l
.iv
, data
->user
) < 0)
999 if (data
->fn(tree
->u
.l
.init
, data
->user
) < 0)
1001 if (data
->fn(tree
->u
.l
.cond
, data
->user
) < 0)
1003 if (data
->fn(tree
->u
.l
.inc
, data
->user
) < 0)
1011 /* Call "fn" on each top-level expression in the nodes of "tree"
1013 * Return 0 on success and -1 on error, where "fn" returning a negative
1014 * value is treated as an error.
1016 * We run over all nodes in "tree" and call "fn"
1017 * on each expression in those nodes.
1019 int pet_tree_foreach_expr(__isl_keep pet_tree
*tree
,
1020 int (*fn
)(__isl_keep pet_expr
*expr
, void *user
), void *user
)
1022 struct pet_tree_foreach_expr_data data
= { fn
, user
};
1024 return pet_tree_foreach_sub_tree(tree
, &foreach_expr
, &data
);
1027 /* Intermediate data structure for foreach_access_expr.
1029 * "fn" is the function that needs to be called on each access subexpression.
1030 * "user" is the user argument to be passed to "fn".
1032 struct pet_tree_foreach_access_expr_data
{
1033 int (*fn
)(__isl_keep pet_expr
*expr
, void *user
);
1037 /* Call data->fn on each access subexpression of "expr".
1038 * This function is used as a callback to pet_tree_foreach_expr
1039 * to implement pet_tree_foreach_access_expr.
1041 * Return 0 on success and -1 on error, where data->fn returning a negative
1042 * value is treated as an error.
1044 static int foreach_access_expr(__isl_keep pet_expr
*expr
, void *user
)
1046 struct pet_tree_foreach_access_expr_data
*data
= user
;
1048 return pet_expr_foreach_access_expr(expr
, data
->fn
, data
->user
);
1051 /* Call "fn" on each access subexpression in the nodes of "tree"
1053 * Return 0 on success and -1 on error, where "fn" returning a negative
1054 * value is treated as an error.
1056 * We run over all expressions in the nodes of "tree" and call "fn"
1057 * on each access subexpression of those expressions.
1059 int pet_tree_foreach_access_expr(__isl_keep pet_tree
*tree
,
1060 int (*fn
)(__isl_keep pet_expr
*expr
, void *user
), void *user
)
1062 struct pet_tree_foreach_access_expr_data data
= { fn
, user
};
1064 return pet_tree_foreach_expr(tree
, &foreach_access_expr
, &data
);
1067 /* Modify all top-level expressions in the nodes of "tree"
1068 * by calling "fn" on them.
1070 __isl_give pet_tree
*pet_tree_map_expr(__isl_take pet_tree
*tree
,
1071 __isl_give pet_expr
*(*fn
)(__isl_take pet_expr
*expr
, void *user
),
1076 tree
= pet_tree_cow(tree
);
1080 switch (tree
->type
) {
1081 case pet_tree_error
:
1082 return pet_tree_free(tree
);
1083 case pet_tree_block
:
1084 for (i
= 0; i
< tree
->u
.b
.n
; ++i
) {
1085 tree
->u
.b
.child
[i
] =
1086 pet_tree_map_expr(tree
->u
.b
.child
[i
], fn
, user
);
1087 if (!tree
->u
.b
.child
[i
])
1088 return pet_tree_free(tree
);
1091 case pet_tree_break
:
1092 case pet_tree_continue
:
1095 tree
->u
.d
.var
= fn(tree
->u
.d
.var
, user
);
1097 return pet_tree_free(tree
);
1099 case pet_tree_decl_init
:
1100 tree
->u
.d
.var
= fn(tree
->u
.d
.var
, user
);
1101 tree
->u
.d
.init
= fn(tree
->u
.d
.init
, user
);
1102 if (!tree
->u
.d
.var
|| !tree
->u
.d
.init
)
1103 return pet_tree_free(tree
);
1106 tree
->u
.e
.expr
= fn(tree
->u
.e
.expr
, user
);
1107 if (!tree
->u
.e
.expr
)
1108 return pet_tree_free(tree
);
1111 tree
->u
.i
.cond
= fn(tree
->u
.i
.cond
, user
);
1112 tree
->u
.i
.then_body
=
1113 pet_tree_map_expr(tree
->u
.i
.then_body
, fn
, user
);
1114 if (!tree
->u
.i
.cond
|| !tree
->u
.i
.then_body
)
1115 return pet_tree_free(tree
);
1117 case pet_tree_if_else
:
1118 tree
->u
.i
.cond
= fn(tree
->u
.i
.cond
, user
);
1119 tree
->u
.i
.then_body
=
1120 pet_tree_map_expr(tree
->u
.i
.then_body
, fn
, user
);
1121 tree
->u
.i
.else_body
=
1122 pet_tree_map_expr(tree
->u
.i
.else_body
, fn
, user
);
1123 if (!tree
->u
.i
.cond
||
1124 !tree
->u
.i
.then_body
|| !tree
->u
.i
.else_body
)
1125 return pet_tree_free(tree
);
1127 case pet_tree_while
:
1128 tree
->u
.l
.cond
= fn(tree
->u
.l
.cond
, user
);
1129 tree
->u
.l
.body
= pet_tree_map_expr(tree
->u
.l
.body
, fn
, user
);
1130 if (!tree
->u
.l
.cond
|| !tree
->u
.l
.body
)
1131 return pet_tree_free(tree
);
1134 tree
->u
.l
.iv
= fn(tree
->u
.l
.iv
, user
);
1135 tree
->u
.l
.init
= fn(tree
->u
.l
.init
, user
);
1136 tree
->u
.l
.cond
= fn(tree
->u
.l
.cond
, user
);
1137 tree
->u
.l
.inc
= fn(tree
->u
.l
.inc
, user
);
1138 tree
->u
.l
.body
= pet_tree_map_expr(tree
->u
.l
.body
, fn
, user
);
1139 if (!tree
->u
.l
.iv
|| !tree
->u
.l
.init
|| !tree
->u
.l
.cond
||
1140 !tree
->u
.l
.inc
|| !tree
->u
.l
.body
)
1141 return pet_tree_free(tree
);
1143 case pet_tree_infinite_loop
:
1144 tree
->u
.l
.body
= pet_tree_map_expr(tree
->u
.l
.body
, fn
, user
);
1145 if (!tree
->u
.l
.body
)
1146 return pet_tree_free(tree
);
1153 /* Intermediate data structure for map_expr.
1155 * "map" is a function that modifies subexpressions of a given type.
1156 * "fn" is the function that needs to be called on each of those subexpressions.
1157 * "user" is the user argument to be passed to "fn".
1159 struct pet_tree_map_expr_data
{
1160 __isl_give pet_expr
*(*map
)(__isl_take pet_expr
*expr
,
1161 __isl_give pet_expr
*(*fn
)(__isl_take pet_expr
*expr
,
1162 void *user
), void *user
);
1163 __isl_give pet_expr
*(*fn
)(__isl_take pet_expr
*expr
, void *user
);
1167 /* This function is called on each top-level expressions in the nodes
1168 * of a tree. Call data->map to modify subexpressions of the top-level
1169 * expression by calling data->fn on them.
1171 * This is a wrapper around data->map for use as a callback
1172 * to pet_tree_map_expr.
1174 static __isl_give pet_expr
*map_expr(__isl_take pet_expr
*expr
,
1177 struct pet_tree_map_expr_data
*data
= user
;
1179 return data
->map(expr
, data
->fn
, data
->user
);
1182 /* Modify all access subexpressions in the nodes of "tree"
1183 * by calling "fn" on them.
1185 * We run over all expressions in the nodes of "tree" and call "fn"
1186 * on each access subexpression of those expressions.
1188 __isl_give pet_tree
*pet_tree_map_access_expr(__isl_take pet_tree
*tree
,
1189 __isl_give pet_expr
*(*fn
)(__isl_take pet_expr
*expr
, void *user
),
1192 struct pet_tree_map_expr_data data
= { &pet_expr_map_access
, fn
, user
};
1194 return pet_tree_map_expr(tree
, &map_expr
, &data
);
1197 /* Modify all call subexpressions in the nodes of "tree"
1198 * by calling "fn" on them.
1200 * We run over all expressions in the nodes of "tree" and call "fn"
1201 * on each call subexpression of those expressions.
1203 __isl_give pet_tree
*pet_tree_map_call_expr(__isl_take pet_tree
*tree
,
1204 __isl_give pet_expr
*(*fn
)(__isl_take pet_expr
*expr
, void *user
),
1207 struct pet_tree_map_expr_data data
= { &pet_expr_map_call
, fn
, user
};
1209 return pet_tree_map_expr(tree
, &map_expr
, &data
);
1212 /* Wrapper around pet_expr_align_params
1213 * for use as a pet_tree_map_expr callback.
1215 static __isl_give pet_expr
*align_params(__isl_take pet_expr
*expr
,
1218 isl_space
*space
= user
;
1220 return pet_expr_align_params(expr
, isl_space_copy(space
));
1223 /* Add all parameters in "space" to all access relations and index expressions
1226 __isl_give pet_tree
*pet_tree_align_params(__isl_take pet_tree
*tree
,
1227 __isl_take isl_space
*space
)
1229 tree
= pet_tree_map_expr(tree
, &align_params
, space
);
1230 isl_space_free(space
);
1234 /* Wrapper around pet_expr_add_ref_ids
1235 * for use as a pet_tree_map_expr callback.
1237 static __isl_give pet_expr
*add_ref_ids(__isl_take pet_expr
*expr
, void *user
)
1241 return pet_expr_add_ref_ids(expr
, n_ref
);
1244 /* Add reference identifiers to all access expressions in "tree".
1245 * "n_ref" points to an integer that contains the sequence number
1246 * of the next reference.
1248 __isl_give pet_tree
*pet_tree_add_ref_ids(__isl_take pet_tree
*tree
,
1251 return pet_tree_map_expr(tree
, &add_ref_ids
, n_ref
);
1254 /* Wrapper around pet_expr_anonymize
1255 * for use as a pet_tree_map_expr callback.
1257 static __isl_give pet_expr
*anonymize(__isl_take pet_expr
*expr
, void *user
)
1259 return pet_expr_anonymize(expr
);
1262 /* Reset the user pointer on all parameter and tuple ids in "tree".
1264 __isl_give pet_tree
*pet_tree_anonymize(__isl_take pet_tree
*tree
)
1266 return pet_tree_map_expr(tree
, &anonymize
, NULL
);
1269 /* Arguments to be passed to pet_expr_gist from the gist wrapper.
1271 struct pet_tree_gist_data
{
1273 isl_union_map
*value_bounds
;
1276 /* Wrapper around pet_expr_gist for use as a pet_tree_map_expr callback.
1278 static __isl_give pet_expr
*gist(__isl_take pet_expr
*expr
, void *user
)
1280 struct pet_tree_gist_data
*data
= user
;
1282 return pet_expr_gist(expr
, data
->domain
, data
->value_bounds
);
1285 /* Compute the gist of all access relations and index expressions inside
1286 * "tree" based on the constraints on the parameters specified by "context"
1287 * and the constraints on the values of nested accesses specified
1288 * by "value_bounds".
1290 __isl_give pet_tree
*pet_tree_gist(__isl_take pet_tree
*tree
,
1291 __isl_keep isl_set
*context
, __isl_keep isl_union_map
*value_bounds
)
1293 struct pet_tree_gist_data data
= { context
, value_bounds
};
1295 return pet_tree_map_expr(tree
, &gist
, &data
);
1298 /* Return 1 if the two pet_tree objects are equivalent.
1300 * We ignore the locations of the trees.
1302 int pet_tree_is_equal(__isl_keep pet_tree
*tree1
, __isl_keep pet_tree
*tree2
)
1307 if (!tree1
|| !tree2
)
1313 if (tree1
->type
!= tree2
->type
)
1315 if (tree1
->label
!= tree2
->label
)
1318 switch (tree1
->type
) {
1319 case pet_tree_error
:
1321 case pet_tree_block
:
1322 if (tree1
->u
.b
.block
!= tree2
->u
.b
.block
)
1324 if (tree1
->u
.b
.n
!= tree2
->u
.b
.n
)
1326 for (i
= 0; i
< tree1
->u
.b
.n
; ++i
) {
1327 equal
= pet_tree_is_equal(tree1
->u
.b
.child
[i
],
1328 tree2
->u
.b
.child
[i
]);
1329 if (equal
< 0 || !equal
)
1333 case pet_tree_break
:
1334 case pet_tree_continue
:
1337 return pet_expr_is_equal(tree1
->u
.d
.var
, tree2
->u
.d
.var
);
1338 case pet_tree_decl_init
:
1339 equal
= pet_expr_is_equal(tree1
->u
.d
.var
, tree2
->u
.d
.var
);
1340 if (equal
< 0 || !equal
)
1342 return pet_expr_is_equal(tree1
->u
.d
.init
, tree2
->u
.d
.init
);
1344 return pet_expr_is_equal(tree1
->u
.e
.expr
, tree2
->u
.e
.expr
);
1346 if (tree1
->u
.l
.declared
!= tree2
->u
.l
.declared
)
1348 equal
= pet_expr_is_equal(tree1
->u
.l
.iv
, tree2
->u
.l
.iv
);
1349 if (equal
< 0 || !equal
)
1351 equal
= pet_expr_is_equal(tree1
->u
.l
.init
, tree2
->u
.l
.init
);
1352 if (equal
< 0 || !equal
)
1354 equal
= pet_expr_is_equal(tree1
->u
.l
.cond
, tree2
->u
.l
.cond
);
1355 if (equal
< 0 || !equal
)
1357 equal
= pet_expr_is_equal(tree1
->u
.l
.inc
, tree2
->u
.l
.inc
);
1358 if (equal
< 0 || !equal
)
1360 return pet_tree_is_equal(tree1
->u
.l
.body
, tree2
->u
.l
.body
);
1361 case pet_tree_while
:
1362 equal
= pet_expr_is_equal(tree1
->u
.l
.cond
, tree2
->u
.l
.cond
);
1363 if (equal
< 0 || !equal
)
1365 return pet_tree_is_equal(tree1
->u
.l
.body
, tree2
->u
.l
.body
);
1366 case pet_tree_infinite_loop
:
1367 return pet_tree_is_equal(tree1
->u
.l
.body
, tree2
->u
.l
.body
);
1369 equal
= pet_expr_is_equal(tree1
->u
.i
.cond
, tree2
->u
.i
.cond
);
1370 if (equal
< 0 || !equal
)
1372 return pet_tree_is_equal(tree1
->u
.i
.then_body
,
1373 tree2
->u
.i
.then_body
);
1374 case pet_tree_if_else
:
1375 equal
= pet_expr_is_equal(tree1
->u
.i
.cond
, tree2
->u
.i
.cond
);
1376 if (equal
< 0 || !equal
)
1378 equal
= pet_tree_is_equal(tree1
->u
.i
.then_body
,
1379 tree2
->u
.i
.then_body
);
1380 if (equal
< 0 || !equal
)
1382 return pet_tree_is_equal(tree1
->u
.i
.else_body
,
1383 tree2
->u
.i
.else_body
);
1389 /* Is "tree" an expression tree that performs the operation "type"?
1391 static int pet_tree_is_op_of_type(__isl_keep pet_tree
*tree
,
1392 enum pet_op_type type
)
1396 if (tree
->type
!= pet_tree_expr
)
1398 if (pet_expr_get_type(tree
->u
.e
.expr
) != pet_expr_op
)
1400 return pet_expr_op_get_type(tree
->u
.e
.expr
) == type
;
1403 /* Is "tree" an expression tree that performs a kill operation?
1405 int pet_tree_is_kill(__isl_keep pet_tree
*tree
)
1407 return pet_tree_is_op_of_type(tree
, pet_op_kill
);
1410 /* Is "tree" an expression tree that performs an assignment operation?
1412 int pet_tree_is_assign(__isl_keep pet_tree
*tree
)
1414 return pet_tree_is_op_of_type(tree
, pet_op_assign
);
1417 /* Is "tree" an expression tree that performs an assume operation?
1419 int pet_tree_is_assume(__isl_keep pet_tree
*tree
)
1421 return pet_tree_is_op_of_type(tree
, pet_op_assume
);
1424 /* Is "tree" an expression tree that performs an assume operation
1425 * such that the assumed expression is affine?
1427 isl_bool
pet_tree_is_affine_assume(__isl_keep pet_tree
*tree
)
1429 if (!pet_tree_is_assume(tree
))
1430 return isl_bool_false
;
1431 return pet_expr_is_affine(tree
->u
.e
.expr
->args
[0]);
1434 /* Given a tree that represent an assume operation expression
1435 * with an access as argument (possibly an affine expression),
1436 * return the index expression of that access.
1438 __isl_give isl_multi_pw_aff
*pet_tree_assume_get_index(
1439 __isl_keep pet_tree
*tree
)
1443 if (!pet_tree_is_assume(tree
))
1444 isl_die(pet_tree_get_ctx(tree
), isl_error_invalid
,
1445 "not an assume tree", return NULL
);
1446 return pet_expr_access_get_index(tree
->u
.e
.expr
->args
[0]);
1449 /* Internal data structure for pet_tree_writes.
1450 * "id" is the identifier that we are looking for.
1451 * "writes" is set if we have found the identifier being written to.
1453 struct pet_tree_writes_data
{
1458 /* Check if expr writes to data->id.
1459 * If so, set data->writes and abort the search.
1461 static int check_write(__isl_keep pet_expr
*expr
, void *user
)
1463 struct pet_tree_writes_data
*data
= user
;
1465 data
->writes
= pet_expr_writes(expr
, data
->id
);
1466 if (data
->writes
< 0 || data
->writes
)
1472 /* Is there any write access in "tree" that accesses "id"?
1474 int pet_tree_writes(__isl_keep pet_tree
*tree
, __isl_keep isl_id
*id
)
1476 struct pet_tree_writes_data data
;
1480 if (pet_tree_foreach_expr(tree
, &check_write
, &data
) < 0 &&
1487 /* Wrapper around pet_expr_update_domain
1488 * for use as a pet_tree_map_expr callback.
1490 static __isl_give pet_expr
*update_domain(__isl_take pet_expr
*expr
, void *user
)
1492 isl_multi_pw_aff
*update
= user
;
1494 return pet_expr_update_domain(expr
, isl_multi_pw_aff_copy(update
));
1497 /* Modify all access relations in "tree" by precomposing them with
1498 * the given iteration space transformation.
1500 __isl_give pet_tree
*pet_tree_update_domain(__isl_take pet_tree
*tree
,
1501 __isl_take isl_multi_pw_aff
*update
)
1503 tree
= pet_tree_map_expr(tree
, &update_domain
, update
);
1504 isl_multi_pw_aff_free(update
);
1508 /* Does "tree" contain a continue or break node (not contained in any loop
1509 * subtree of "tree")?
1511 int pet_tree_has_continue_or_break(__isl_keep pet_tree
*tree
)
1519 switch (tree
->type
) {
1520 case pet_tree_error
:
1522 case pet_tree_continue
:
1523 case pet_tree_break
:
1526 case pet_tree_decl_init
:
1529 case pet_tree_while
:
1530 case pet_tree_infinite_loop
:
1532 case pet_tree_block
:
1533 for (i
= 0; i
< tree
->u
.b
.n
; ++i
) {
1535 pet_tree_has_continue_or_break(tree
->u
.b
.child
[i
]);
1536 if (found
< 0 || found
)
1541 return pet_tree_has_continue_or_break(tree
->u
.i
.then_body
);
1542 case pet_tree_if_else
:
1543 found
= pet_tree_has_continue_or_break(tree
->u
.i
.then_body
);
1544 if (found
< 0 || found
)
1546 return pet_tree_has_continue_or_break(tree
->u
.i
.else_body
);
1550 static void print_indent(int indent
)
1552 fprintf(stderr
, "%*s", indent
, "");
1555 void pet_tree_dump_with_indent(__isl_keep pet_tree
*tree
, int indent
)
1562 print_indent(indent
);
1563 fprintf(stderr
, "%s\n", pet_tree_type_str(tree
->type
));
1564 print_indent(indent
);
1565 fprintf(stderr
, "line: %d\n", pet_loc_get_line(tree
->loc
));
1566 print_indent(indent
);
1567 fprintf(stderr
, "start: %d\n", pet_loc_get_start(tree
->loc
));
1568 print_indent(indent
);
1569 fprintf(stderr
, "end: %d\n", pet_loc_get_end(tree
->loc
));
1571 print_indent(indent
);
1572 fprintf(stderr
, "label: ");
1573 isl_id_dump(tree
->label
);
1575 switch (tree
->type
) {
1576 case pet_tree_block
:
1577 print_indent(indent
);
1578 fprintf(stderr
, "block: %d\n", tree
->u
.b
.block
);
1579 for (i
= 0; i
< tree
->u
.b
.n
; ++i
)
1580 pet_tree_dump_with_indent(tree
->u
.b
.child
[i
],
1584 pet_expr_dump_with_indent(tree
->u
.e
.expr
, indent
);
1586 case pet_tree_break
:
1587 case pet_tree_continue
:
1590 case pet_tree_decl_init
:
1591 print_indent(indent
);
1592 fprintf(stderr
, "var:\n");
1593 pet_expr_dump_with_indent(tree
->u
.d
.var
, indent
+ 2);
1594 if (tree
->type
!= pet_tree_decl_init
)
1596 print_indent(indent
);
1597 fprintf(stderr
, "init:\n");
1598 pet_expr_dump_with_indent(tree
->u
.d
.init
, indent
+ 2);
1601 case pet_tree_if_else
:
1602 print_indent(indent
);
1603 fprintf(stderr
, "condition:\n");
1604 pet_expr_dump_with_indent(tree
->u
.i
.cond
, indent
+ 2);
1605 print_indent(indent
);
1606 fprintf(stderr
, "then:\n");
1607 pet_tree_dump_with_indent(tree
->u
.i
.then_body
, indent
+ 2);
1608 if (tree
->type
!= pet_tree_if_else
)
1610 print_indent(indent
);
1611 fprintf(stderr
, "else:\n");
1612 pet_tree_dump_with_indent(tree
->u
.i
.else_body
, indent
+ 2);
1615 print_indent(indent
);
1616 fprintf(stderr
, "declared: %d\n", tree
->u
.l
.declared
);
1617 print_indent(indent
);
1618 fprintf(stderr
, "var:\n");
1619 pet_expr_dump_with_indent(tree
->u
.l
.iv
, indent
+ 2);
1620 print_indent(indent
);
1621 fprintf(stderr
, "init:\n");
1622 pet_expr_dump_with_indent(tree
->u
.l
.init
, indent
+ 2);
1623 print_indent(indent
);
1624 fprintf(stderr
, "inc:\n");
1625 pet_expr_dump_with_indent(tree
->u
.l
.inc
, indent
+ 2);
1626 case pet_tree_while
:
1627 print_indent(indent
);
1628 fprintf(stderr
, "condition:\n");
1629 pet_expr_dump_with_indent(tree
->u
.l
.cond
, indent
+ 2);
1630 case pet_tree_infinite_loop
:
1631 print_indent(indent
);
1632 fprintf(stderr
, "body:\n");
1633 pet_tree_dump_with_indent(tree
->u
.l
.body
, indent
+ 2);
1635 case pet_tree_error
:
1636 print_indent(indent
);
1637 fprintf(stderr
, "ERROR\n");
1642 void pet_tree_dump(__isl_keep pet_tree
*tree
)
1644 pet_tree_dump_with_indent(tree
, 0);