2 * Copyright 2011 Leiden University. All rights reserved.
3 * Copyright 2012-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
36 #include <isl/constraint.h>
37 #include <isl/union_set.h>
47 #include "value_bounds.h"
49 /* pet_scop with extra information that is used during parsing and printing.
51 * In particular, we keep track of conditions under which we want
52 * to skip the rest of the current loop iteration (skip[pet_skip_now])
53 * and of conditions under which we want to skip subsequent
54 * loop iterations (skip[pet_skip_later]).
56 * The conditions are represented as index expressions defined
57 * over the outer loop iterators. The index expression is either
58 * a boolean affine expression or an access to a variable, which
59 * is assumed to attain values zero and one. The condition holds
60 * if the variable has value one or if the affine expression
61 * has value one (typically for only part of the domain).
63 * A missing condition (skip[type] == NULL) means that we don't want
66 * Additionally, we keep track of the original input file
67 * inside pet_transform_C_source.
72 isl_multi_pw_aff
*skip
[2];
76 /* Construct a pet_stmt with given domain and statement number from a pet_tree.
77 * The input domain is anonymous and is the same as the domains
78 * of the access expressions inside "tree".
79 * These domains are modified to include the name of the statement.
80 * This name is given by tree->label if it is non-NULL.
81 * Otherwise, the name is constructed as S_<id>.
83 struct pet_stmt
*pet_stmt_from_pet_tree(__isl_take isl_set
*domain
,
84 int id
, __isl_take pet_tree
*tree
)
86 struct pet_stmt
*stmt
;
92 isl_multi_pw_aff
*add_name
;
98 ctx
= pet_tree_get_ctx(tree
);
99 stmt
= isl_calloc_type(ctx
, struct pet_stmt
);
104 label
= isl_id_copy(tree
->label
);
106 snprintf(name
, sizeof(name
), "S_%d", id
);
107 label
= isl_id_alloc(ctx
, name
, NULL
);
109 domain
= isl_set_set_tuple_id(domain
, label
);
110 space
= isl_set_get_space(domain
);
111 space
= pet_nested_remove_from_space(space
);
112 sched
= isl_map_universe(isl_space_from_domain(isl_space_copy(space
)));
113 ma
= pet_prefix_projection(space
, isl_space_dim(space
, isl_dim_set
));
115 add_name
= isl_multi_pw_aff_from_multi_aff(ma
);
116 tree
= pet_tree_update_domain(tree
, add_name
);
118 stmt
->loc
= pet_tree_get_loc(tree
);
119 stmt
->domain
= domain
;
120 stmt
->schedule
= sched
;
123 if (!stmt
->domain
|| !stmt
->schedule
|| !stmt
->body
)
124 return pet_stmt_free(stmt
);
128 isl_set_free(domain
);
133 void *pet_stmt_free(struct pet_stmt
*stmt
)
140 pet_loc_free(stmt
->loc
);
141 isl_set_free(stmt
->domain
);
142 isl_map_free(stmt
->schedule
);
143 pet_tree_free(stmt
->body
);
145 for (i
= 0; i
< stmt
->n_arg
; ++i
)
146 pet_expr_free(stmt
->args
[i
]);
153 /* Return the iteration space of "stmt".
155 * If the statement has arguments, then stmt->domain is a wrapped map
156 * mapping the iteration domain to the values of the arguments
157 * for which this statement is executed.
158 * In this case, we need to extract the domain space of this wrapped map.
160 __isl_give isl_space
*pet_stmt_get_space(struct pet_stmt
*stmt
)
167 space
= isl_set_get_space(stmt
->domain
);
168 if (isl_space_is_wrapping(space
))
169 space
= isl_space_domain(isl_space_unwrap(space
));
174 static void stmt_dump(struct pet_stmt
*stmt
, int indent
)
181 fprintf(stderr
, "%*s%d\n", indent
, "", pet_loc_get_line(stmt
->loc
));
182 fprintf(stderr
, "%*s", indent
, "");
183 isl_set_dump(stmt
->domain
);
184 fprintf(stderr
, "%*s", indent
, "");
185 isl_map_dump(stmt
->schedule
);
186 pet_tree_dump_with_indent(stmt
->body
, indent
);
187 for (i
= 0; i
< stmt
->n_arg
; ++i
)
188 pet_expr_dump_with_indent(stmt
->args
[i
], indent
+ 2);
191 void pet_stmt_dump(struct pet_stmt
*stmt
)
196 /* Allocate a new pet_type with the given "name" and "definition".
198 struct pet_type
*pet_type_alloc(isl_ctx
*ctx
, const char *name
,
199 const char *definition
)
201 struct pet_type
*type
;
203 type
= isl_alloc_type(ctx
, struct pet_type
);
207 type
->name
= strdup(name
);
208 type
->definition
= strdup(definition
);
210 if (!type
->name
|| !type
->definition
)
211 return pet_type_free(type
);
216 /* Free "type" and return NULL.
218 struct pet_type
*pet_type_free(struct pet_type
*type
)
224 free(type
->definition
);
230 struct pet_array
*pet_array_free(struct pet_array
*array
)
235 isl_set_free(array
->context
);
236 isl_set_free(array
->extent
);
237 isl_set_free(array
->value_bounds
);
238 free(array
->element_type
);
244 void pet_array_dump(struct pet_array
*array
)
249 isl_set_dump(array
->context
);
250 isl_set_dump(array
->extent
);
251 isl_set_dump(array
->value_bounds
);
252 fprintf(stderr
, "%s%s%s\n", array
->element_type
,
253 array
->element_is_record
? " element-is-record" : "",
254 array
->live_out
? " live-out" : "");
257 /* Alloc a pet_scop structure, with extra room for information that
258 * is only used during parsing.
260 struct pet_scop
*pet_scop_alloc(isl_ctx
*ctx
)
262 return &isl_calloc_type(ctx
, struct pet_scop_ext
)->scop
;
265 /* Construct a pet_scop in the given space and with room for n statements.
267 * The context is initialized as a universe set in "space".
269 * Since no information on the location is known at this point,
270 * scop->loc is initialized with pet_loc_dummy.
272 static struct pet_scop
*scop_alloc(__isl_take isl_space
*space
, int n
)
275 struct pet_scop
*scop
;
280 ctx
= isl_space_get_ctx(space
);
281 scop
= pet_scop_alloc(ctx
);
285 scop
->context
= isl_set_universe(isl_space_copy(space
));
286 scop
->context_value
= isl_set_universe(isl_space_params(space
));
287 scop
->stmts
= isl_calloc_array(ctx
, struct pet_stmt
*, n
);
288 if (!scop
->context
|| !scop
->stmts
)
289 return pet_scop_free(scop
);
291 scop
->loc
= &pet_loc_dummy
;
297 /* Construct a pet_scop in the given space containing 0 statements.
299 struct pet_scop
*pet_scop_empty(__isl_take isl_space
*space
)
301 return scop_alloc(space
, 0);
304 /* Given either an iteration domain or a wrapped map with
305 * the iteration domain in the domain and some arguments
306 * in the range, return the iteration domain.
307 * That is, drop the arguments if there are any.
309 static __isl_give isl_set
*drop_arguments(__isl_take isl_set
*domain
)
311 if (isl_set_is_wrapping(domain
))
312 domain
= isl_map_domain(isl_set_unwrap(domain
));
316 /* Update "context" with the constraints imposed on the outer iteration
317 * domain by access expression "expr".
318 * "context" lives in an anonymous space, while the domain of the access
319 * relation of "expr" refers to a particular statement.
320 * This reference therefore needs to be stripped off.
322 static __isl_give isl_set
*access_extract_context(__isl_keep pet_expr
*expr
,
323 __isl_take isl_set
*context
)
325 isl_multi_pw_aff
*mpa
;
328 mpa
= pet_expr_access_get_index(expr
);
329 domain
= drop_arguments(isl_multi_pw_aff_domain(mpa
));
330 domain
= isl_set_reset_tuple_id(domain
);
331 context
= isl_set_intersect(context
, domain
);
335 /* Update "context" with the constraints imposed on the outer iteration
338 * "context" lives in an anonymous space, while the domains of
339 * the access relations in "expr" refer to a particular statement.
340 * This reference therefore needs to be stripped off.
342 * If "expr" represents a conditional operator, then a parameter or outer
343 * iterator value needs to be valid for the condition and
344 * for at least one of the remaining two arguments.
345 * If the condition is an affine expression, then we can be a bit more specific.
346 * The value then has to be valid for the second argument for
347 * non-zero accesses and valid for the third argument for zero accesses.
349 * If "expr" represents a kill statement, then its argument is the entire
350 * extent of the array being killed. Do not update "context" based
351 * on this argument as that would impose constraints that ensure that
352 * the array is non-empty.
354 static __isl_give isl_set
*expr_extract_context(__isl_keep pet_expr
*expr
,
355 __isl_take isl_set
*context
)
359 if (expr
->type
== pet_expr_op
&& expr
->op
== pet_op_kill
)
362 if (expr
->type
== pet_expr_op
&& expr
->op
== pet_op_cond
) {
364 isl_set
*context1
, *context2
;
366 is_aff
= pet_expr_is_affine(expr
->args
[0]);
370 context
= expr_extract_context(expr
->args
[0], context
);
371 context1
= expr_extract_context(expr
->args
[1],
372 isl_set_copy(context
));
373 context2
= expr_extract_context(expr
->args
[2], context
);
376 isl_multi_pw_aff
*mpa
;
380 mpa
= pet_expr_access_get_index(expr
->args
[0]);
381 pa
= isl_multi_pw_aff_get_pw_aff(mpa
, 0);
382 isl_multi_pw_aff_free(mpa
);
383 zero_set
= drop_arguments(isl_pw_aff_zero_set(pa
));
384 zero_set
= isl_set_reset_tuple_id(zero_set
);
385 context1
= isl_set_subtract(context1
,
386 isl_set_copy(zero_set
));
387 context2
= isl_set_intersect(context2
, zero_set
);
390 context
= isl_set_union(context1
, context2
);
391 context
= isl_set_coalesce(context
);
396 for (i
= 0; i
< expr
->n_arg
; ++i
)
397 context
= expr_extract_context(expr
->args
[i
], context
);
399 if (expr
->type
== pet_expr_access
)
400 context
= access_extract_context(expr
, context
);
404 isl_set_free(context
);
408 /* Is "stmt" an assume statement with an affine assumption?
410 int pet_stmt_is_affine_assume(struct pet_stmt
*stmt
)
414 return pet_tree_is_affine_assume(stmt
->body
);
417 /* Given an assume statement "stmt" with an access argument,
418 * return the index expression of the argument.
420 __isl_give isl_multi_pw_aff
*pet_stmt_assume_get_index(struct pet_stmt
*stmt
)
424 return pet_tree_assume_get_index(stmt
->body
);
427 /* Update "context" with the constraints imposed on the outer iteration
430 * If the statement is an assume statement with an affine expression,
431 * then intersect "context" with that expression.
432 * Otherwise, if the statement body is an expression tree,
433 * then intersect "context" with the context of this expression.
434 * Note that we cannot safely extract a context from subtrees
435 * of the statement body since we cannot tell when those subtrees
436 * are executed, if at all.
438 static __isl_give isl_set
*stmt_extract_context(struct pet_stmt
*stmt
,
439 __isl_take isl_set
*context
)
444 if (pet_stmt_is_affine_assume(stmt
)) {
445 isl_multi_pw_aff
*index
;
449 index
= pet_stmt_assume_get_index(stmt
);
450 pa
= isl_multi_pw_aff_get_pw_aff(index
, 0);
451 isl_multi_pw_aff_free(index
);
452 cond
= isl_pw_aff_non_zero_set(pa
);
453 cond
= isl_set_reset_tuple_id(cond
);
454 return isl_set_intersect(context
, cond
);
457 for (i
= 0; i
< stmt
->n_arg
; ++i
)
458 context
= expr_extract_context(stmt
->args
[i
], context
);
460 if (pet_tree_get_type(stmt
->body
) != pet_tree_expr
)
463 body
= pet_tree_expr_get_expr(stmt
->body
);
464 context
= expr_extract_context(body
, context
);
470 /* Construct a pet_scop in the given space that contains the given pet_stmt.
472 struct pet_scop
*pet_scop_from_pet_stmt(__isl_take isl_space
*space
,
473 struct pet_stmt
*stmt
)
475 struct pet_scop
*scop
;
478 space
= isl_space_free(space
);
480 scop
= scop_alloc(space
, 1);
484 scop
->context
= stmt_extract_context(stmt
, scop
->context
);
488 scop
->stmts
[0] = stmt
;
489 scop
->loc
= pet_loc_copy(stmt
->loc
);
492 return pet_scop_free(scop
);
501 /* Does "mpa" represent an access to an element of an unnamed space, i.e.,
502 * does it represent an affine expression?
504 static int multi_pw_aff_is_affine(__isl_keep isl_multi_pw_aff
*mpa
)
508 has_id
= isl_multi_pw_aff_has_tuple_id(mpa
, isl_dim_out
);
515 /* Return the piecewise affine expression "set ? 1 : 0" defined on "dom".
517 static __isl_give isl_pw_aff
*indicator_function(__isl_take isl_set
*set
,
518 __isl_take isl_set
*dom
)
521 pa
= isl_set_indicator_function(set
);
522 pa
= isl_pw_aff_intersect_domain(pa
, dom
);
526 /* Return "lhs || rhs", defined on the shared definition domain.
528 static __isl_give isl_pw_aff
*pw_aff_or(__isl_take isl_pw_aff
*lhs
,
529 __isl_take isl_pw_aff
*rhs
)
534 dom
= isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(lhs
)),
535 isl_pw_aff_domain(isl_pw_aff_copy(rhs
)));
536 cond
= isl_set_union(isl_pw_aff_non_zero_set(lhs
),
537 isl_pw_aff_non_zero_set(rhs
));
538 cond
= isl_set_coalesce(cond
);
539 return indicator_function(cond
, dom
);
542 /* Combine ext1->skip[type] and ext2->skip[type] into ext->skip[type].
543 * ext may be equal to either ext1 or ext2.
545 * The two skips that need to be combined are assumed to be affine expressions.
547 * We need to skip in ext if we need to skip in either ext1 or ext2.
548 * We don't need to skip in ext if we don't need to skip in both ext1 and ext2.
550 static struct pet_scop_ext
*combine_skips(struct pet_scop_ext
*ext
,
551 struct pet_scop_ext
*ext1
, struct pet_scop_ext
*ext2
,
554 isl_pw_aff
*skip
, *skip1
, *skip2
;
558 if (!ext1
->skip
[type
] && !ext2
->skip
[type
])
560 if (!ext1
->skip
[type
]) {
563 ext
->skip
[type
] = ext2
->skip
[type
];
564 ext2
->skip
[type
] = NULL
;
567 if (!ext2
->skip
[type
]) {
570 ext
->skip
[type
] = ext1
->skip
[type
];
571 ext1
->skip
[type
] = NULL
;
575 if (!multi_pw_aff_is_affine(ext1
->skip
[type
]) ||
576 !multi_pw_aff_is_affine(ext2
->skip
[type
]))
577 isl_die(isl_multi_pw_aff_get_ctx(ext1
->skip
[type
]),
578 isl_error_internal
, "can only combine affine skips",
581 skip1
= isl_multi_pw_aff_get_pw_aff(ext1
->skip
[type
], 0);
582 skip2
= isl_multi_pw_aff_get_pw_aff(ext2
->skip
[type
], 0);
583 skip
= pw_aff_or(skip1
, skip2
);
584 isl_multi_pw_aff_free(ext1
->skip
[type
]);
585 ext1
->skip
[type
] = NULL
;
586 isl_multi_pw_aff_free(ext2
->skip
[type
]);
587 ext2
->skip
[type
] = NULL
;
588 ext
->skip
[type
] = isl_multi_pw_aff_from_pw_aff(skip
);
589 if (!ext
->skip
[type
])
594 pet_scop_free(&ext
->scop
);
598 /* Combine scop1->skip[type] and scop2->skip[type] into scop->skip[type],
599 * where type takes on the values pet_skip_now and pet_skip_later.
600 * scop may be equal to either scop1 or scop2.
602 static struct pet_scop
*scop_combine_skips(struct pet_scop
*scop
,
603 struct pet_scop
*scop1
, struct pet_scop
*scop2
)
605 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
606 struct pet_scop_ext
*ext1
= (struct pet_scop_ext
*) scop1
;
607 struct pet_scop_ext
*ext2
= (struct pet_scop_ext
*) scop2
;
609 ext
= combine_skips(ext
, ext1
, ext2
, pet_skip_now
);
610 ext
= combine_skips(ext
, ext1
, ext2
, pet_skip_later
);
614 /* Update start and end of scop->loc to include the region from "start"
615 * to "end". In particular, if scop->loc == &pet_loc_dummy, then "scop"
616 * does not have any offset information yet and we simply take the information
617 * from "start" and "end". Otherwise, we update loc using "start" and "end".
619 struct pet_scop
*pet_scop_update_start_end(struct pet_scop
*scop
,
620 unsigned start
, unsigned end
)
625 if (scop
->loc
== &pet_loc_dummy
)
626 scop
->loc
= pet_loc_alloc(isl_set_get_ctx(scop
->context
),
627 start
, end
, -1, strdup(""));
629 scop
->loc
= pet_loc_update_start_end(scop
->loc
, start
, end
);
632 return pet_scop_free(scop
);
637 /* Update start and end of scop->loc to include the region identified
640 struct pet_scop
*pet_scop_update_start_end_from_loc(struct pet_scop
*scop
,
641 __isl_keep pet_loc
*loc
)
643 return pet_scop_update_start_end(scop
, pet_loc_get_start(loc
),
644 pet_loc_get_end(loc
));
647 /* Replace the location of "scop" by "loc".
649 struct pet_scop
*pet_scop_set_loc(struct pet_scop
*scop
,
650 __isl_take pet_loc
*loc
)
655 pet_loc_free(scop
->loc
);
665 /* Does "implication" appear in the list of implications of "scop"?
667 static int is_known_implication(struct pet_scop
*scop
,
668 struct pet_implication
*implication
)
672 for (i
= 0; i
< scop
->n_implication
; ++i
) {
673 struct pet_implication
*pi
= scop
->implications
[i
];
676 if (pi
->satisfied
!= implication
->satisfied
)
678 equal
= isl_map_is_equal(pi
->extension
, implication
->extension
);
688 /* Store the concatenation of the implications of "scop1" and "scop2"
689 * in "scop", removing duplicates (i.e., implications in "scop2" that
690 * already appear in "scop1").
692 static struct pet_scop
*scop_collect_implications(isl_ctx
*ctx
,
693 struct pet_scop
*scop
, struct pet_scop
*scop1
, struct pet_scop
*scop2
)
700 if (scop2
->n_implication
== 0) {
701 scop
->n_implication
= scop1
->n_implication
;
702 scop
->implications
= scop1
->implications
;
703 scop1
->n_implication
= 0;
704 scop1
->implications
= NULL
;
708 if (scop1
->n_implication
== 0) {
709 scop
->n_implication
= scop2
->n_implication
;
710 scop
->implications
= scop2
->implications
;
711 scop2
->n_implication
= 0;
712 scop2
->implications
= NULL
;
716 scop
->implications
= isl_calloc_array(ctx
, struct pet_implication
*,
717 scop1
->n_implication
+ scop2
->n_implication
);
718 if (!scop
->implications
)
719 return pet_scop_free(scop
);
721 for (i
= 0; i
< scop1
->n_implication
; ++i
) {
722 scop
->implications
[i
] = scop1
->implications
[i
];
723 scop1
->implications
[i
] = NULL
;
726 scop
->n_implication
= scop1
->n_implication
;
727 j
= scop1
->n_implication
;
728 for (i
= 0; i
< scop2
->n_implication
; ++i
) {
731 known
= is_known_implication(scop
, scop2
->implications
[i
]);
733 return pet_scop_free(scop
);
736 scop
->implications
[j
++] = scop2
->implications
[i
];
737 scop2
->implications
[i
] = NULL
;
739 scop
->n_implication
= j
;
744 /* Combine the offset information of "scop1" and "scop2" into "scop".
746 static struct pet_scop
*scop_combine_start_end(struct pet_scop
*scop
,
747 struct pet_scop
*scop1
, struct pet_scop
*scop2
)
749 if (scop1
->loc
!= &pet_loc_dummy
)
750 scop
= pet_scop_update_start_end_from_loc(scop
, scop1
->loc
);
751 if (scop2
->loc
!= &pet_loc_dummy
)
752 scop
= pet_scop_update_start_end_from_loc(scop
, scop2
->loc
);
756 /* Create and return an independence that filters out the dependences
757 * in "filter" with local variables "local".
759 static struct pet_independence
*new_independence(
760 __isl_take isl_union_map
*filter
, __isl_take isl_union_set
*local
)
763 struct pet_independence
*independence
;
765 if (!filter
|| !local
)
767 ctx
= isl_union_map_get_ctx(filter
);
768 independence
= isl_alloc_type(ctx
, struct pet_independence
);
772 independence
->filter
= filter
;
773 independence
->local
= local
;
777 isl_union_map_free(filter
);
778 isl_union_set_free(local
);
782 /* Add an independence that filters out the dependences
783 * in "filter" with local variables "local" to "scop".
785 struct pet_scop
*pet_scop_add_independence(struct pet_scop
*scop
,
786 __isl_take isl_union_map
*filter
, __isl_take isl_union_set
*local
)
789 struct pet_independence
*independence
;
790 struct pet_independence
**independences
;
792 ctx
= isl_union_map_get_ctx(filter
);
793 independence
= new_independence(filter
, local
);
794 if (!scop
|| !independence
)
797 independences
= isl_realloc_array(ctx
, scop
->independences
,
798 struct pet_independence
*,
799 scop
->n_independence
+ 1);
802 scop
->independences
= independences
;
803 scop
->independences
[scop
->n_independence
] = independence
;
804 scop
->n_independence
++;
808 pet_independence_free(independence
);
813 /* Store the concatenation of the independences of "scop1" and "scop2"
816 static struct pet_scop
*scop_collect_independences(isl_ctx
*ctx
,
817 struct pet_scop
*scop
, struct pet_scop
*scop1
, struct pet_scop
*scop2
)
824 if (scop2
->n_independence
== 0) {
825 scop
->n_independence
= scop1
->n_independence
;
826 scop
->independences
= scop1
->independences
;
827 scop1
->n_independence
= 0;
828 scop1
->independences
= NULL
;
832 if (scop1
->n_independence
== 0) {
833 scop
->n_independence
= scop2
->n_independence
;
834 scop
->independences
= scop2
->independences
;
835 scop2
->n_independence
= 0;
836 scop2
->independences
= NULL
;
840 scop
->independences
= isl_calloc_array(ctx
, struct pet_independence
*,
841 scop1
->n_independence
+ scop2
->n_independence
);
842 if (!scop
->independences
)
843 return pet_scop_free(scop
);
845 for (i
= 0; i
< scop1
->n_independence
; ++i
) {
846 scop
->independences
[i
] = scop1
->independences
[i
];
847 scop1
->independences
[i
] = NULL
;
850 off
= scop1
->n_independence
;
851 for (i
= 0; i
< scop2
->n_independence
; ++i
) {
852 scop
->independences
[off
+ i
] = scop2
->independences
[i
];
853 scop2
->independences
[i
] = NULL
;
855 scop
->n_independence
= scop1
->n_independence
+ scop2
->n_independence
;
860 /* Construct a pet_scop that contains the offset information,
861 * arrays, statements and skip information in "scop1" and "scop2".
863 static struct pet_scop
*pet_scop_add(isl_ctx
*ctx
, struct pet_scop
*scop1
,
864 struct pet_scop
*scop2
)
868 struct pet_scop
*scop
= NULL
;
870 if (!scop1
|| !scop2
)
873 if (scop1
->n_stmt
== 0) {
874 scop2
= scop_combine_skips(scop2
, scop1
, scop2
);
875 pet_scop_free(scop1
);
879 if (scop2
->n_stmt
== 0) {
880 scop1
= scop_combine_skips(scop1
, scop1
, scop2
);
881 pet_scop_free(scop2
);
885 space
= isl_set_get_space(scop1
->context
);
886 scop
= scop_alloc(space
, scop1
->n_stmt
+ scop2
->n_stmt
);
890 scop
->arrays
= isl_calloc_array(ctx
, struct pet_array
*,
891 scop1
->n_array
+ scop2
->n_array
);
894 scop
->n_array
= scop1
->n_array
+ scop2
->n_array
;
896 for (i
= 0; i
< scop1
->n_stmt
; ++i
) {
897 scop
->stmts
[i
] = scop1
->stmts
[i
];
898 scop1
->stmts
[i
] = NULL
;
901 for (i
= 0; i
< scop2
->n_stmt
; ++i
) {
902 scop
->stmts
[scop1
->n_stmt
+ i
] = scop2
->stmts
[i
];
903 scop2
->stmts
[i
] = NULL
;
906 for (i
= 0; i
< scop1
->n_array
; ++i
) {
907 scop
->arrays
[i
] = scop1
->arrays
[i
];
908 scop1
->arrays
[i
] = NULL
;
911 for (i
= 0; i
< scop2
->n_array
; ++i
) {
912 scop
->arrays
[scop1
->n_array
+ i
] = scop2
->arrays
[i
];
913 scop2
->arrays
[i
] = NULL
;
916 scop
= scop_collect_implications(ctx
, scop
, scop1
, scop2
);
917 scop
= pet_scop_restrict_context(scop
, isl_set_copy(scop1
->context
));
918 scop
= pet_scop_restrict_context(scop
, isl_set_copy(scop2
->context
));
919 scop
= scop_combine_skips(scop
, scop1
, scop2
);
920 scop
= scop_combine_start_end(scop
, scop1
, scop2
);
921 scop
= scop_collect_independences(ctx
, scop
, scop1
, scop2
);
923 pet_scop_free(scop1
);
924 pet_scop_free(scop2
);
927 pet_scop_free(scop1
);
928 pet_scop_free(scop2
);
933 /* Apply the skip condition "skip" to "scop".
934 * That is, make sure "scop" is not executed when the condition holds.
936 * If "skip" is an affine expression, we add the conditions under
937 * which the expression is zero to the context and the skip conditions
939 * Otherwise, we add a filter on the variable attaining the value zero.
941 static struct pet_scop
*restrict_skip(struct pet_scop
*scop
,
942 __isl_take isl_multi_pw_aff
*skip
)
951 is_aff
= multi_pw_aff_is_affine(skip
);
956 return pet_scop_filter(scop
, skip
, 0);
958 pa
= isl_multi_pw_aff_get_pw_aff(skip
, 0);
959 isl_multi_pw_aff_free(skip
);
960 zero
= isl_pw_aff_zero_set(pa
);
961 scop
= pet_scop_restrict(scop
, zero
);
965 isl_multi_pw_aff_free(skip
);
966 return pet_scop_free(scop
);
969 /* Construct a pet_scop that contains the arrays, statements and
970 * skip information in "scop1" and "scop2", where the two scops
971 * are executed "in sequence". That is, breaks and continues
972 * in scop1 have an effect on scop2.
974 struct pet_scop
*pet_scop_add_seq(isl_ctx
*ctx
, struct pet_scop
*scop1
,
975 struct pet_scop
*scop2
)
977 if (scop1
&& pet_scop_has_skip(scop1
, pet_skip_now
))
978 scop2
= restrict_skip(scop2
,
979 pet_scop_get_skip(scop1
, pet_skip_now
));
980 return pet_scop_add(ctx
, scop1
, scop2
);
983 /* Construct a pet_scop that contains the arrays, statements and
984 * skip information in "scop1" and "scop2", where the two scops
985 * are executed "in parallel". That is, any break or continue
986 * in scop1 has no effect on scop2.
988 struct pet_scop
*pet_scop_add_par(isl_ctx
*ctx
, struct pet_scop
*scop1
,
989 struct pet_scop
*scop2
)
991 return pet_scop_add(ctx
, scop1
, scop2
);
994 void *pet_implication_free(struct pet_implication
*implication
)
1001 isl_map_free(implication
->extension
);
1007 void *pet_independence_free(struct pet_independence
*independence
)
1012 isl_union_map_free(independence
->filter
);
1013 isl_union_set_free(independence
->local
);
1019 struct pet_scop
*pet_scop_free(struct pet_scop
*scop
)
1022 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1026 pet_loc_free(scop
->loc
);
1027 isl_set_free(scop
->context
);
1028 isl_set_free(scop
->context_value
);
1030 for (i
= 0; i
< scop
->n_type
; ++i
)
1031 pet_type_free(scop
->types
[i
]);
1034 for (i
= 0; i
< scop
->n_array
; ++i
)
1035 pet_array_free(scop
->arrays
[i
]);
1038 for (i
= 0; i
< scop
->n_stmt
; ++i
)
1039 pet_stmt_free(scop
->stmts
[i
]);
1041 if (scop
->implications
)
1042 for (i
= 0; i
< scop
->n_implication
; ++i
)
1043 pet_implication_free(scop
->implications
[i
]);
1044 free(scop
->implications
);
1045 if (scop
->independences
)
1046 for (i
= 0; i
< scop
->n_independence
; ++i
)
1047 pet_independence_free(scop
->independences
[i
]);
1048 free(scop
->independences
);
1049 isl_multi_pw_aff_free(ext
->skip
[pet_skip_now
]);
1050 isl_multi_pw_aff_free(ext
->skip
[pet_skip_later
]);
1055 void pet_type_dump(struct pet_type
*type
)
1060 fprintf(stderr
, "%s -> %s\n", type
->name
, type
->definition
);
1063 void pet_implication_dump(struct pet_implication
*implication
)
1068 fprintf(stderr
, "%d\n", implication
->satisfied
);
1069 isl_map_dump(implication
->extension
);
1072 void pet_scop_dump(struct pet_scop
*scop
)
1075 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1080 isl_set_dump(scop
->context
);
1081 isl_set_dump(scop
->context_value
);
1082 for (i
= 0; i
< scop
->n_type
; ++i
)
1083 pet_type_dump(scop
->types
[i
]);
1084 for (i
= 0; i
< scop
->n_array
; ++i
)
1085 pet_array_dump(scop
->arrays
[i
]);
1086 for (i
= 0; i
< scop
->n_stmt
; ++i
)
1087 pet_stmt_dump(scop
->stmts
[i
]);
1088 for (i
= 0; i
< scop
->n_implication
; ++i
)
1089 pet_implication_dump(scop
->implications
[i
]);
1092 fprintf(stderr
, "skip\n");
1093 isl_multi_pw_aff_dump(ext
->skip
[0]);
1094 isl_multi_pw_aff_dump(ext
->skip
[1]);
1098 /* Return 1 if the two pet_arrays are equivalent.
1100 * We don't compare element_size as this may be target dependent.
1102 int pet_array_is_equal(struct pet_array
*array1
, struct pet_array
*array2
)
1104 if (!array1
|| !array2
)
1107 if (!isl_set_is_equal(array1
->context
, array2
->context
))
1109 if (!isl_set_is_equal(array1
->extent
, array2
->extent
))
1111 if (!!array1
->value_bounds
!= !!array2
->value_bounds
)
1113 if (array1
->value_bounds
&&
1114 !isl_set_is_equal(array1
->value_bounds
, array2
->value_bounds
))
1116 if (strcmp(array1
->element_type
, array2
->element_type
))
1118 if (array1
->element_is_record
!= array2
->element_is_record
)
1120 if (array1
->live_out
!= array2
->live_out
)
1122 if (array1
->uniquely_defined
!= array2
->uniquely_defined
)
1124 if (array1
->declared
!= array2
->declared
)
1126 if (array1
->exposed
!= array2
->exposed
)
1132 /* Return 1 if the two pet_stmts are equivalent.
1134 int pet_stmt_is_equal(struct pet_stmt
*stmt1
, struct pet_stmt
*stmt2
)
1138 if (!stmt1
|| !stmt2
)
1141 if (pet_loc_get_line(stmt1
->loc
) != pet_loc_get_line(stmt2
->loc
))
1143 if (!isl_set_is_equal(stmt1
->domain
, stmt2
->domain
))
1145 if (!isl_map_is_equal(stmt1
->schedule
, stmt2
->schedule
))
1147 if (!pet_tree_is_equal(stmt1
->body
, stmt2
->body
))
1149 if (stmt1
->n_arg
!= stmt2
->n_arg
)
1151 for (i
= 0; i
< stmt1
->n_arg
; ++i
) {
1152 if (!pet_expr_is_equal(stmt1
->args
[i
], stmt2
->args
[i
]))
1159 /* Return 1 if the two pet_types are equivalent.
1161 * We only compare the names of the types since the exact representation
1162 * of the definition may depend on the version of clang being used.
1164 int pet_type_is_equal(struct pet_type
*type1
, struct pet_type
*type2
)
1166 if (!type1
|| !type2
)
1169 if (strcmp(type1
->name
, type2
->name
))
1175 /* Return 1 if the two pet_implications are equivalent.
1177 int pet_implication_is_equal(struct pet_implication
*implication1
,
1178 struct pet_implication
*implication2
)
1180 if (!implication1
|| !implication2
)
1183 if (implication1
->satisfied
!= implication2
->satisfied
)
1185 if (!isl_map_is_equal(implication1
->extension
, implication2
->extension
))
1191 /* Return 1 if the two pet_independences are equivalent.
1193 int pet_independence_is_equal(struct pet_independence
*independence1
,
1194 struct pet_independence
*independence2
)
1196 if (!independence1
|| !independence2
)
1199 if (!isl_union_map_is_equal(independence1
->filter
,
1200 independence2
->filter
))
1202 if (!isl_union_set_is_equal(independence1
->local
, independence2
->local
))
1208 /* Return 1 if the two pet_scops are equivalent.
1210 int pet_scop_is_equal(struct pet_scop
*scop1
, struct pet_scop
*scop2
)
1214 if (!scop1
|| !scop2
)
1217 if (!isl_set_is_equal(scop1
->context
, scop2
->context
))
1219 if (!isl_set_is_equal(scop1
->context_value
, scop2
->context_value
))
1222 if (scop1
->n_type
!= scop2
->n_type
)
1224 for (i
= 0; i
< scop1
->n_type
; ++i
)
1225 if (!pet_type_is_equal(scop1
->types
[i
], scop2
->types
[i
]))
1228 if (scop1
->n_array
!= scop2
->n_array
)
1230 for (i
= 0; i
< scop1
->n_array
; ++i
)
1231 if (!pet_array_is_equal(scop1
->arrays
[i
], scop2
->arrays
[i
]))
1234 if (scop1
->n_stmt
!= scop2
->n_stmt
)
1236 for (i
= 0; i
< scop1
->n_stmt
; ++i
)
1237 if (!pet_stmt_is_equal(scop1
->stmts
[i
], scop2
->stmts
[i
]))
1240 if (scop1
->n_implication
!= scop2
->n_implication
)
1242 for (i
= 0; i
< scop1
->n_implication
; ++i
)
1243 if (!pet_implication_is_equal(scop1
->implications
[i
],
1244 scop2
->implications
[i
]))
1247 if (scop1
->n_independence
!= scop2
->n_independence
)
1249 for (i
= 0; i
< scop1
->n_independence
; ++i
)
1250 if (!pet_independence_is_equal(scop1
->independences
[i
],
1251 scop2
->independences
[i
]))
1257 /* Does the set "extent" reference a virtual array, i.e.,
1258 * one with user pointer equal to NULL?
1259 * A virtual array does not have any members.
1261 static int extent_is_virtual_array(__isl_keep isl_set
*extent
)
1266 if (!isl_set_has_tuple_id(extent
))
1268 if (isl_set_is_wrapping(extent
))
1270 id
= isl_set_get_tuple_id(extent
);
1271 is_virtual
= !isl_id_get_user(id
);
1277 /* Intersect the initial dimensions of "array" with "domain", provided
1278 * that "array" represents a virtual array.
1280 * If "array" is virtual, then We take the preimage of "domain"
1281 * over the projection of the extent of "array" onto its initial dimensions
1282 * and intersect this extent with the result.
1284 static struct pet_array
*virtual_array_intersect_domain_prefix(
1285 struct pet_array
*array
, __isl_take isl_set
*domain
)
1291 if (!array
|| !extent_is_virtual_array(array
->extent
)) {
1292 isl_set_free(domain
);
1296 space
= isl_set_get_space(array
->extent
);
1297 n
= isl_set_dim(domain
, isl_dim_set
);
1298 ma
= pet_prefix_projection(space
, n
);
1299 domain
= isl_set_preimage_multi_aff(domain
, ma
);
1301 array
->extent
= isl_set_intersect(array
->extent
, domain
);
1303 return pet_array_free(array
);
1308 /* Intersect the initial dimensions of the domain of "stmt"
1311 * We take the preimage of "domain" over the projection of the
1312 * domain of "stmt" onto its initial dimensions and intersect
1313 * the domain of "stmt" with the result.
1315 static struct pet_stmt
*stmt_intersect_domain_prefix(struct pet_stmt
*stmt
,
1316 __isl_take isl_set
*domain
)
1325 space
= isl_set_get_space(stmt
->domain
);
1326 n
= isl_set_dim(domain
, isl_dim_set
);
1327 ma
= pet_prefix_projection(space
, n
);
1328 domain
= isl_set_preimage_multi_aff(domain
, ma
);
1330 stmt
->domain
= isl_set_intersect(stmt
->domain
, domain
);
1332 return pet_stmt_free(stmt
);
1336 isl_set_free(domain
);
1337 return pet_stmt_free(stmt
);
1340 /* Intersect the initial dimensions of the domain of "implication"
1343 * We take the preimage of "domain" over the projection of the
1344 * domain of "implication" onto its initial dimensions and intersect
1345 * the domain of "implication" with the result.
1347 static struct pet_implication
*implication_intersect_domain_prefix(
1348 struct pet_implication
*implication
, __isl_take isl_set
*domain
)
1357 space
= isl_map_get_space(implication
->extension
);
1358 n
= isl_set_dim(domain
, isl_dim_set
);
1359 ma
= pet_prefix_projection(isl_space_domain(space
), n
);
1360 domain
= isl_set_preimage_multi_aff(domain
, ma
);
1362 implication
->extension
=
1363 isl_map_intersect_domain(implication
->extension
, domain
);
1364 if (!implication
->extension
)
1365 return pet_implication_free(implication
);
1369 isl_set_free(domain
);
1370 return pet_implication_free(implication
);
1373 /* Intersect the initial dimensions of the domains in "scop" with "domain".
1375 * The extents of the virtual arrays match the iteration domains,
1376 * so if the iteration domain changes, we need to change those extents too.
1378 struct pet_scop
*pet_scop_intersect_domain_prefix(struct pet_scop
*scop
,
1379 __isl_take isl_set
*domain
)
1386 for (i
= 0; i
< scop
->n_array
; ++i
) {
1387 scop
->arrays
[i
] = virtual_array_intersect_domain_prefix(
1388 scop
->arrays
[i
], isl_set_copy(domain
));
1389 if (!scop
->arrays
[i
])
1393 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
1394 scop
->stmts
[i
] = stmt_intersect_domain_prefix(scop
->stmts
[i
],
1395 isl_set_copy(domain
));
1396 if (!scop
->stmts
[i
])
1400 for (i
= 0; i
< scop
->n_implication
; ++i
) {
1401 scop
->implications
[i
] =
1402 implication_intersect_domain_prefix(scop
->implications
[i
],
1403 isl_set_copy(domain
));
1404 if (!scop
->implications
[i
])
1405 return pet_scop_free(scop
);
1408 isl_set_free(domain
);
1411 isl_set_free(domain
);
1412 return pet_scop_free(scop
);
1415 /* Prefix the schedule of "stmt" with an extra dimension with constant
1418 struct pet_stmt
*pet_stmt_prefix(struct pet_stmt
*stmt
, int pos
)
1423 stmt
->schedule
= isl_map_insert_dims(stmt
->schedule
, isl_dim_out
, 0, 1);
1424 stmt
->schedule
= isl_map_fix_si(stmt
->schedule
, isl_dim_out
, 0, pos
);
1425 if (!stmt
->schedule
)
1426 return pet_stmt_free(stmt
);
1431 /* Prefix the schedules of all statements in "scop" with an extra
1432 * dimension with constant value "pos".
1434 struct pet_scop
*pet_scop_prefix(struct pet_scop
*scop
, int pos
)
1441 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
1442 scop
->stmts
[i
] = pet_stmt_prefix(scop
->stmts
[i
], pos
);
1443 if (!scop
->stmts
[i
])
1444 return pet_scop_free(scop
);
1450 /* Prefix the schedule of "stmt" with "sched".
1452 * The domain of "sched" refers the current outer loop iterators and
1453 * needs to be mapped to the iteration domain of "stmt" first
1454 * before being prepended to the schedule of "stmt".
1456 static struct pet_stmt
*pet_stmt_embed(struct pet_stmt
*stmt
,
1457 __isl_take isl_map
*sched
)
1466 space
= pet_stmt_get_space(stmt
);
1467 n
= isl_map_dim(sched
, isl_dim_in
);
1468 ma
= pet_prefix_projection(space
, n
);
1469 sched
= isl_map_preimage_domain_multi_aff(sched
, ma
);
1470 stmt
->schedule
= isl_map_flat_range_product(sched
, stmt
->schedule
);
1471 if (!stmt
->schedule
)
1472 return pet_stmt_free(stmt
);
1476 isl_map_free(sched
);
1480 /* Update the context with respect to an embedding into a loop
1481 * with iteration domain "dom".
1482 * The input context lives in the same space as "dom".
1483 * The output context has the inner dimension removed.
1485 * An outer loop iterator value is invalid for the embedding if
1486 * any of the corresponding inner iterator values is invalid.
1487 * That is, an outer loop iterator value is valid only if all the corresponding
1488 * inner iterator values are valid.
1489 * We therefore compute the set of outer loop iterators l
1491 * forall i: dom(l,i) => valid(l,i)
1495 * forall i: not dom(l,i) or valid(l,i)
1499 * not exists i: dom(l,i) and not valid(l,i)
1503 * not exists i: (dom \ valid)(l,i)
1505 * If there are any unnamed parameters in "dom", then we consider
1506 * a parameter value to be valid if it is valid for any value of those
1507 * unnamed parameters. They are therefore projected out at the end.
1509 static __isl_give isl_set
*context_embed(__isl_take isl_set
*context
,
1510 __isl_keep isl_set
*dom
)
1514 pos
= isl_set_dim(context
, isl_dim_set
) - 1;
1515 context
= isl_set_subtract(isl_set_copy(dom
), context
);
1516 context
= isl_set_project_out(context
, isl_dim_set
, pos
, 1);
1517 context
= isl_set_complement(context
);
1518 context
= pet_nested_remove_from_set(context
);
1523 /* Update the implication with respect to an embedding into a loop
1524 * with iteration domain "dom".
1526 * Since embed_access extends virtual arrays along with the domain
1527 * of the access, we need to do the same with domain and range
1528 * of the implication. Since the original implication is only valid
1529 * within a given iteration of the loop, the extended implication
1530 * maps the extra array dimension corresponding to the extra loop
1533 static struct pet_implication
*pet_implication_embed(
1534 struct pet_implication
*implication
, __isl_take isl_set
*dom
)
1542 map
= isl_set_identity(dom
);
1543 id
= isl_map_get_tuple_id(implication
->extension
, isl_dim_in
);
1544 map
= isl_map_flat_product(map
, implication
->extension
);
1545 map
= isl_map_set_tuple_id(map
, isl_dim_in
, isl_id_copy(id
));
1546 map
= isl_map_set_tuple_id(map
, isl_dim_out
, id
);
1547 implication
->extension
= map
;
1548 if (!implication
->extension
)
1549 return pet_implication_free(implication
);
1557 /* Adjust the context and statement schedules according to an embedding
1558 * in a loop with iteration domain "dom" and schedule "sched".
1560 * Any skip conditions within the loop have no effect outside of the loop.
1561 * The caller is responsible for making sure skip[pet_skip_later] has been
1562 * taken into account.
1564 struct pet_scop
*pet_scop_embed(struct pet_scop
*scop
, __isl_take isl_set
*dom
,
1565 __isl_take isl_aff
*sched
)
1570 sched_map
= isl_map_from_aff(sched
);
1575 pet_scop_reset_skip(scop
, pet_skip_now
);
1576 pet_scop_reset_skip(scop
, pet_skip_later
);
1578 scop
->context
= context_embed(scop
->context
, dom
);
1582 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
1583 scop
->stmts
[i
] = pet_stmt_embed(scop
->stmts
[i
],
1584 isl_map_copy(sched_map
));
1585 if (!scop
->stmts
[i
])
1590 isl_map_free(sched_map
);
1594 isl_map_free(sched_map
);
1595 return pet_scop_free(scop
);
1598 /* Add extra conditions to scop->skip[type].
1600 * The new skip condition only holds if it held before
1601 * and the condition is true. It does not hold if it did not hold
1602 * before or the condition is false.
1604 * The skip condition is assumed to be an affine expression.
1606 static struct pet_scop
*pet_scop_restrict_skip(struct pet_scop
*scop
,
1607 enum pet_skip type
, __isl_keep isl_set
*cond
)
1609 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1615 if (!ext
->skip
[type
])
1618 if (!multi_pw_aff_is_affine(ext
->skip
[type
]))
1619 isl_die(isl_multi_pw_aff_get_ctx(ext
->skip
[type
]),
1620 isl_error_internal
, "can only restrict affine skips",
1621 return pet_scop_free(scop
));
1623 skip
= isl_multi_pw_aff_get_pw_aff(ext
->skip
[type
], 0);
1624 dom
= isl_pw_aff_domain(isl_pw_aff_copy(skip
));
1625 cond
= isl_set_copy(cond
);
1626 cond
= isl_set_intersect(cond
, isl_pw_aff_non_zero_set(skip
));
1627 skip
= indicator_function(cond
, dom
);
1628 isl_multi_pw_aff_free(ext
->skip
[type
]);
1629 ext
->skip
[type
] = isl_multi_pw_aff_from_pw_aff(skip
);
1630 if (!ext
->skip
[type
])
1631 return pet_scop_free(scop
);
1636 /* Adjust the context and the skip conditions to the fact that
1637 * the scop was created in a context where "cond" holds.
1639 * An outer loop iterator or parameter value is valid for the result
1640 * if it was valid for the original scop and satisfies "cond" or if it does
1641 * not satisfy "cond" as in this case the scop is not executed
1642 * and the original constraints on these values are irrelevant.
1644 struct pet_scop
*pet_scop_restrict(struct pet_scop
*scop
,
1645 __isl_take isl_set
*cond
)
1649 scop
= pet_scop_restrict_skip(scop
, pet_skip_now
, cond
);
1650 scop
= pet_scop_restrict_skip(scop
, pet_skip_later
, cond
);
1655 scop
->context
= isl_set_intersect(scop
->context
, isl_set_copy(cond
));
1656 scop
->context
= isl_set_union(scop
->context
,
1657 isl_set_complement(isl_set_copy(cond
)));
1658 scop
->context
= isl_set_coalesce(scop
->context
);
1659 scop
->context
= pet_nested_remove_from_set(scop
->context
);
1667 return pet_scop_free(scop
);
1670 /* Insert an argument expression corresponding to "test" in front
1671 * of the list of arguments described by *n_arg and *args.
1673 static int args_insert_access(unsigned *n_arg
, pet_expr
***args
,
1674 __isl_keep isl_multi_pw_aff
*test
)
1677 isl_ctx
*ctx
= isl_multi_pw_aff_get_ctx(test
);
1683 *args
= isl_calloc_array(ctx
, pet_expr
*, 1);
1688 ext
= isl_calloc_array(ctx
, pet_expr
*, 1 + *n_arg
);
1691 for (i
= 0; i
< *n_arg
; ++i
)
1692 ext
[1 + i
] = (*args
)[i
];
1697 (*args
)[0] = pet_expr_from_index(isl_multi_pw_aff_copy(test
));
1704 /* Look through the applications in "scop" for any that can be
1705 * applied to the filter expressed by "map" and "satisified".
1706 * If there is any, then apply it to "map" and return the result.
1707 * Otherwise, return "map".
1708 * "id" is the identifier of the virtual array.
1710 * We only introduce at most one implication for any given virtual array,
1711 * so we can apply the implication and return as soon as we find one.
1713 static __isl_give isl_map
*apply_implications(struct pet_scop
*scop
,
1714 __isl_take isl_map
*map
, __isl_keep isl_id
*id
, int satisfied
)
1718 for (i
= 0; i
< scop
->n_implication
; ++i
) {
1719 struct pet_implication
*pi
= scop
->implications
[i
];
1722 if (pi
->satisfied
!= satisfied
)
1724 pi_id
= isl_map_get_tuple_id(pi
->extension
, isl_dim_in
);
1729 return isl_map_apply_range(map
, isl_map_copy(pi
->extension
));
1735 /* Is the filter expressed by "test" and "satisfied" implied
1736 * by filter "pos" on "domain", with filter "expr", taking into
1737 * account the implications of "scop"?
1739 * For filter on domain implying that expressed by "test" and "satisfied",
1740 * the filter needs to be an access to the same (virtual) array as "test" and
1741 * the filter value needs to be equal to "satisfied".
1742 * Moreover, the filter access relation, possibly extended by
1743 * the implications in "scop" needs to contain "test".
1745 static int implies_filter(struct pet_scop
*scop
,
1746 __isl_keep isl_map
*domain
, int pos
, __isl_keep pet_expr
*expr
,
1747 __isl_keep isl_map
*test
, int satisfied
)
1749 isl_id
*test_id
, *arg_id
;
1756 if (expr
->type
!= pet_expr_access
)
1758 test_id
= isl_map_get_tuple_id(test
, isl_dim_out
);
1759 arg_id
= pet_expr_access_get_id(expr
);
1760 isl_id_free(arg_id
);
1761 isl_id_free(test_id
);
1762 if (test_id
!= arg_id
)
1764 val
= isl_map_plain_get_val_if_fixed(domain
, isl_dim_out
, pos
);
1765 is_int
= isl_val_is_int(val
);
1767 s
= isl_val_get_num_si(val
);
1776 implied
= isl_map_from_multi_pw_aff(pet_expr_access_get_index(expr
));
1777 implied
= apply_implications(scop
, implied
, test_id
, satisfied
);
1778 is_subset
= isl_map_is_subset(test
, implied
);
1779 isl_map_free(implied
);
1784 /* Is the filter expressed by "test" and "satisfied" implied
1785 * by any of the filters on the domain of "stmt", taking into
1786 * account the implications of "scop"?
1788 static int filter_implied(struct pet_scop
*scop
,
1789 struct pet_stmt
*stmt
, __isl_keep isl_multi_pw_aff
*test
, int satisfied
)
1797 if (!scop
|| !stmt
|| !test
)
1799 if (scop
->n_implication
== 0)
1801 if (stmt
->n_arg
== 0)
1804 domain
= isl_set_unwrap(isl_set_copy(stmt
->domain
));
1805 test_map
= isl_map_from_multi_pw_aff(isl_multi_pw_aff_copy(test
));
1808 for (i
= 0; i
< stmt
->n_arg
; ++i
) {
1809 implied
= implies_filter(scop
, domain
, i
, stmt
->args
[i
],
1810 test_map
, satisfied
);
1811 if (implied
< 0 || implied
)
1815 isl_map_free(test_map
);
1816 isl_map_free(domain
);
1820 /* Make the statement "stmt" depend on the value of "test"
1821 * being equal to "satisfied" by adjusting stmt->domain.
1823 * The domain of "test" corresponds to the (zero or more) outer dimensions
1824 * of the iteration domain.
1826 * We first extend "test" to apply to the entire iteration domain and
1827 * then check if the filter that we are about to add is implied
1828 * by any of the current filters, possibly taking into account
1829 * the implications in "scop". If so, we leave "stmt" untouched and return.
1831 * Otherwise, we insert an argument corresponding to a read to "test"
1832 * from the iteration domain of "stmt" in front of the list of arguments.
1833 * We also insert a corresponding output dimension in the wrapped
1834 * map contained in stmt->domain, with value set to "satisfied".
1836 static struct pet_stmt
*stmt_filter(struct pet_scop
*scop
,
1837 struct pet_stmt
*stmt
, __isl_take isl_multi_pw_aff
*test
, int satisfied
)
1843 isl_pw_multi_aff
*pma
;
1844 isl_multi_aff
*add_dom
;
1846 isl_local_space
*ls
;
1852 space
= pet_stmt_get_space(stmt
);
1853 n_test_dom
= isl_multi_pw_aff_dim(test
, isl_dim_in
);
1854 space
= isl_space_from_domain(space
);
1855 space
= isl_space_add_dims(space
, isl_dim_out
, n_test_dom
);
1856 add_dom
= isl_multi_aff_zero(isl_space_copy(space
));
1857 ls
= isl_local_space_from_space(isl_space_domain(space
));
1858 for (i
= 0; i
< n_test_dom
; ++i
) {
1860 aff
= isl_aff_var_on_domain(isl_local_space_copy(ls
),
1862 add_dom
= isl_multi_aff_set_aff(add_dom
, i
, aff
);
1864 isl_local_space_free(ls
);
1865 test
= isl_multi_pw_aff_pullback_multi_aff(test
, add_dom
);
1867 implied
= filter_implied(scop
, stmt
, test
, satisfied
);
1871 isl_multi_pw_aff_free(test
);
1875 id
= isl_multi_pw_aff_get_tuple_id(test
, isl_dim_out
);
1876 pma
= pet_filter_insert_pma(isl_set_get_space(stmt
->domain
),
1878 stmt
->domain
= isl_set_preimage_pw_multi_aff(stmt
->domain
, pma
);
1880 if (args_insert_access(&stmt
->n_arg
, &stmt
->args
, test
) < 0)
1883 isl_multi_pw_aff_free(test
);
1886 isl_multi_pw_aff_free(test
);
1887 return pet_stmt_free(stmt
);
1890 /* Does "scop" have a skip condition of the given "type"?
1892 int pet_scop_has_skip(struct pet_scop
*scop
, enum pet_skip type
)
1894 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1898 return ext
->skip
[type
] != NULL
;
1901 /* Does "scop" have a skip condition of the given "type" that
1902 * is an affine expression?
1904 int pet_scop_has_affine_skip(struct pet_scop
*scop
, enum pet_skip type
)
1906 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1910 if (!ext
->skip
[type
])
1912 return multi_pw_aff_is_affine(ext
->skip
[type
]);
1915 /* Does "scop" have a skip condition of the given "type" that
1916 * is not an affine expression?
1918 int pet_scop_has_var_skip(struct pet_scop
*scop
, enum pet_skip type
)
1920 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1925 if (!ext
->skip
[type
])
1927 aff
= multi_pw_aff_is_affine(ext
->skip
[type
]);
1933 /* Does "scop" have a skip condition of the given "type" that
1934 * is affine and holds on the entire domain?
1936 int pet_scop_has_universal_skip(struct pet_scop
*scop
, enum pet_skip type
)
1938 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1944 is_aff
= pet_scop_has_affine_skip(scop
, type
);
1945 if (is_aff
< 0 || !is_aff
)
1948 pa
= isl_multi_pw_aff_get_pw_aff(ext
->skip
[type
], 0);
1949 set
= isl_pw_aff_non_zero_set(pa
);
1950 is_univ
= isl_set_plain_is_universe(set
);
1956 /* Replace scop->skip[type] by "skip".
1958 struct pet_scop
*pet_scop_set_skip(struct pet_scop
*scop
,
1959 enum pet_skip type
, __isl_take isl_multi_pw_aff
*skip
)
1961 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1966 isl_multi_pw_aff_free(ext
->skip
[type
]);
1967 ext
->skip
[type
] = skip
;
1971 isl_multi_pw_aff_free(skip
);
1972 return pet_scop_free(scop
);
1975 /* Return a copy of scop->skip[type].
1977 __isl_give isl_multi_pw_aff
*pet_scop_get_skip(struct pet_scop
*scop
,
1980 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
1985 return isl_multi_pw_aff_copy(ext
->skip
[type
]);
1988 /* Assuming scop->skip[type] is an affine expression,
1989 * return the constraints on the outer loop domain for which the skip condition
1992 __isl_give isl_set
*pet_scop_get_affine_skip_domain(struct pet_scop
*scop
,
1995 isl_multi_pw_aff
*skip
;
1998 skip
= pet_scop_get_skip(scop
, type
);
1999 pa
= isl_multi_pw_aff_get_pw_aff(skip
, 0);
2000 isl_multi_pw_aff_free(skip
);
2001 return isl_pw_aff_non_zero_set(pa
);
2004 /* Return the identifier of the variable that is accessed by
2005 * the skip condition of the given type.
2007 * The skip condition is assumed not to be an affine condition.
2009 __isl_give isl_id
*pet_scop_get_skip_id(struct pet_scop
*scop
,
2012 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
2017 return isl_multi_pw_aff_get_tuple_id(ext
->skip
[type
], isl_dim_out
);
2020 /* Return an access pet_expr corresponding to the skip condition
2021 * of the given type.
2023 __isl_give pet_expr
*pet_scop_get_skip_expr(struct pet_scop
*scop
,
2026 return pet_expr_from_index(pet_scop_get_skip(scop
, type
));
2029 /* Drop the the skip condition scop->skip[type].
2031 void pet_scop_reset_skip(struct pet_scop
*scop
, enum pet_skip type
)
2033 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
2038 isl_multi_pw_aff_free(ext
->skip
[type
]);
2039 ext
->skip
[type
] = NULL
;
2042 /* Make the skip condition (if any) depend on the value of "test" being
2043 * equal to "satisfied".
2045 * We only support the case where the original skip condition is universal,
2046 * i.e., where skipping is unconditional, and where satisfied == 1.
2047 * In this case, the skip condition is changed to skip only when
2048 * "test" is equal to one.
2050 static struct pet_scop
*pet_scop_filter_skip(struct pet_scop
*scop
,
2051 enum pet_skip type
, __isl_keep isl_multi_pw_aff
*test
, int satisfied
)
2057 if (!pet_scop_has_skip(scop
, type
))
2061 is_univ
= pet_scop_has_universal_skip(scop
, type
);
2063 return pet_scop_free(scop
);
2064 if (satisfied
&& is_univ
) {
2065 isl_multi_pw_aff
*skip
;
2066 skip
= isl_multi_pw_aff_copy(test
);
2067 scop
= pet_scop_set_skip(scop
, type
, skip
);
2071 isl_die(isl_multi_pw_aff_get_ctx(test
), isl_error_internal
,
2072 "skip expression cannot be filtered",
2073 return pet_scop_free(scop
));
2079 /* Make all statements in "scop" depend on the value of "test"
2080 * being equal to "satisfied" by adjusting their domains.
2082 struct pet_scop
*pet_scop_filter(struct pet_scop
*scop
,
2083 __isl_take isl_multi_pw_aff
*test
, int satisfied
)
2087 scop
= pet_scop_filter_skip(scop
, pet_skip_now
, test
, satisfied
);
2088 scop
= pet_scop_filter_skip(scop
, pet_skip_later
, test
, satisfied
);
2093 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2094 scop
->stmts
[i
] = stmt_filter(scop
, scop
->stmts
[i
],
2095 isl_multi_pw_aff_copy(test
), satisfied
);
2096 if (!scop
->stmts
[i
])
2100 isl_multi_pw_aff_free(test
);
2103 isl_multi_pw_aff_free(test
);
2104 return pet_scop_free(scop
);
2107 /* Add the parameters of the access expression "expr" to "space".
2109 static int access_collect_params(__isl_keep pet_expr
*expr
, void *user
)
2112 isl_space
**space
= user
;
2114 *space
= isl_space_align_params(*space
,
2115 isl_map_get_space(expr
->acc
.access
));
2117 return *space
? 0 : -1;
2120 /* Add all parameters in "stmt" to "space" and return the result.
2122 static __isl_give isl_space
*stmt_collect_params(struct pet_stmt
*stmt
,
2123 __isl_take isl_space
*space
)
2128 return isl_space_free(space
);
2130 space
= isl_space_align_params(space
, isl_set_get_space(stmt
->domain
));
2131 space
= isl_space_align_params(space
,
2132 isl_map_get_space(stmt
->schedule
));
2133 for (i
= 0; i
< stmt
->n_arg
; ++i
)
2134 if (pet_expr_foreach_access_expr(stmt
->args
[i
],
2135 &access_collect_params
, &space
) < 0)
2136 space
= isl_space_free(space
);
2137 if (pet_tree_foreach_access_expr(stmt
->body
, &access_collect_params
,
2139 space
= isl_space_free(space
);
2144 /* Add all parameters in "array" to "space" and return the result.
2146 static __isl_give isl_space
*array_collect_params(struct pet_array
*array
,
2147 __isl_take isl_space
*space
)
2150 return isl_space_free(space
);
2152 space
= isl_space_align_params(space
,
2153 isl_set_get_space(array
->context
));
2154 space
= isl_space_align_params(space
, isl_set_get_space(array
->extent
));
2159 /* Add all parameters in "independence" to "space" and return the result.
2161 static __isl_give isl_space
*independence_collect_params(
2162 struct pet_independence
*independence
, __isl_take isl_space
*space
)
2165 return isl_space_free(space
);
2167 space
= isl_space_align_params(space
,
2168 isl_union_map_get_space(independence
->filter
));
2169 space
= isl_space_align_params(space
,
2170 isl_union_set_get_space(independence
->local
));
2175 /* Add all parameters in "scop" to "space" and return the result.
2177 static __isl_give isl_space
*scop_collect_params(struct pet_scop
*scop
,
2178 __isl_take isl_space
*space
)
2183 return isl_space_free(space
);
2185 for (i
= 0; i
< scop
->n_array
; ++i
)
2186 space
= array_collect_params(scop
->arrays
[i
], space
);
2188 for (i
= 0; i
< scop
->n_stmt
; ++i
)
2189 space
= stmt_collect_params(scop
->stmts
[i
], space
);
2191 for (i
= 0; i
< scop
->n_independence
; ++i
)
2192 space
= independence_collect_params(scop
->independences
[i
],
2198 /* Add all parameters in "space" to the domain, schedule and
2199 * all access relations in "stmt".
2201 static struct pet_stmt
*stmt_propagate_params(struct pet_stmt
*stmt
,
2202 __isl_take isl_space
*space
)
2209 stmt
->domain
= isl_set_align_params(stmt
->domain
,
2210 isl_space_copy(space
));
2211 stmt
->schedule
= isl_map_align_params(stmt
->schedule
,
2212 isl_space_copy(space
));
2214 for (i
= 0; i
< stmt
->n_arg
; ++i
) {
2215 stmt
->args
[i
] = pet_expr_align_params(stmt
->args
[i
],
2216 isl_space_copy(space
));
2220 stmt
->body
= pet_tree_align_params(stmt
->body
, isl_space_copy(space
));
2222 if (!stmt
->domain
|| !stmt
->schedule
|| !stmt
->body
)
2225 isl_space_free(space
);
2228 isl_space_free(space
);
2229 return pet_stmt_free(stmt
);
2232 /* Add all parameters in "space" to "array".
2234 static struct pet_array
*array_propagate_params(struct pet_array
*array
,
2235 __isl_take isl_space
*space
)
2240 array
->context
= isl_set_align_params(array
->context
,
2241 isl_space_copy(space
));
2242 array
->extent
= isl_set_align_params(array
->extent
,
2243 isl_space_copy(space
));
2244 if (array
->value_bounds
) {
2245 array
->value_bounds
= isl_set_align_params(array
->value_bounds
,
2246 isl_space_copy(space
));
2247 if (!array
->value_bounds
)
2251 if (!array
->context
|| !array
->extent
)
2254 isl_space_free(space
);
2257 isl_space_free(space
);
2258 return pet_array_free(array
);
2261 /* Add all parameters in "space" to "independence".
2263 static struct pet_independence
*independence_propagate_params(
2264 struct pet_independence
*independence
, __isl_take isl_space
*space
)
2269 independence
->filter
= isl_union_map_align_params(independence
->filter
,
2270 isl_space_copy(space
));
2271 independence
->local
= isl_union_set_align_params(independence
->local
,
2272 isl_space_copy(space
));
2273 if (!independence
->filter
|| !independence
->local
)
2276 isl_space_free(space
);
2277 return independence
;
2279 isl_space_free(space
);
2280 return pet_independence_free(independence
);
2283 /* Add all parameters in "space" to "scop".
2285 static struct pet_scop
*scop_propagate_params(struct pet_scop
*scop
,
2286 __isl_take isl_space
*space
)
2293 for (i
= 0; i
< scop
->n_array
; ++i
) {
2294 scop
->arrays
[i
] = array_propagate_params(scop
->arrays
[i
],
2295 isl_space_copy(space
));
2296 if (!scop
->arrays
[i
])
2300 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2301 scop
->stmts
[i
] = stmt_propagate_params(scop
->stmts
[i
],
2302 isl_space_copy(space
));
2303 if (!scop
->stmts
[i
])
2307 for (i
= 0; i
< scop
->n_independence
; ++i
) {
2308 scop
->independences
[i
] = independence_propagate_params(
2309 scop
->independences
[i
], isl_space_copy(space
));
2310 if (!scop
->independences
[i
])
2314 isl_space_free(space
);
2317 isl_space_free(space
);
2318 return pet_scop_free(scop
);
2321 /* Update all isl_sets and isl_maps in "scop" such that they all
2322 * have the same parameters.
2324 struct pet_scop
*pet_scop_align_params(struct pet_scop
*scop
)
2331 space
= isl_set_get_space(scop
->context
);
2332 space
= scop_collect_params(scop
, space
);
2334 scop
->context
= isl_set_align_params(scop
->context
,
2335 isl_space_copy(space
));
2336 scop
= scop_propagate_params(scop
, space
);
2338 if (scop
&& !scop
->context
)
2339 return pet_scop_free(scop
);
2344 /* Add the access relation of the access expression "expr" to "accesses" and
2345 * return the result.
2346 * The domain of the access relation is intersected with "domain".
2347 * If "tag" is set, then the access relation is tagged with
2348 * the corresponding reference identifier.
2350 static __isl_give isl_union_map
*expr_collect_access(__isl_keep pet_expr
*expr
,
2351 int tag
, __isl_take isl_union_map
*accesses
, __isl_keep isl_set
*domain
)
2355 access
= pet_expr_access_get_may_access(expr
);
2356 access
= isl_map_intersect_domain(access
, isl_set_copy(domain
));
2358 access
= pet_expr_tag_access(expr
, access
);
2359 return isl_union_map_add_map(accesses
, access
);
2362 /* Internal data structure for expr_collect_accesses.
2364 * "read" is set if we want to collect read accesses.
2365 * "write" is set if we want to collect write accesses.
2366 * "must" is set if we only want definite accesses.
2367 * "tag" is set if the access relations should be tagged with
2368 * the corresponding reference identifiers.
2369 * "domain" are constraints on the domain of the access relations.
2370 * "accesses" collects the results.
2372 struct pet_expr_collect_accesses_data
{
2379 isl_union_map
*accesses
;
2382 /* Add the access relation of the access expression "expr"
2383 * to data->accesses if the access expression is a read and data->read is set
2384 * and/or it is a write and data->write is set.
2385 * The domains of the access relations are intersected with data->domain.
2386 * If data->tag is set, then the access relations are tagged with
2387 * the corresponding reference identifiers.
2389 * If data->must is set, then we only add the accesses that are definitely
2390 * performed. Otherwise, we add all potential accesses.
2391 * In particular, if the access has any arguments, then if data->must is
2392 * set we currently skip the access completely. If data->must is not set,
2393 * we project out the values of the access arguments.
2395 static int expr_collect_accesses(__isl_keep pet_expr
*expr
, void *user
)
2397 struct pet_expr_collect_accesses_data
*data
= user
;
2405 if (pet_expr_is_affine(expr
))
2407 if (data
->must
&& expr
->n_arg
!= 0)
2410 if ((data
->read
&& expr
->acc
.read
) || (data
->write
&& expr
->acc
.write
))
2411 data
->accesses
= expr_collect_access(expr
, data
->tag
,
2412 data
->accesses
, data
->domain
);
2414 return data
->accesses
? 0 : -1;
2417 /* Collect and return all read access relations (if "read" is set)
2418 * and/or all write access relations (if "write" is set) in "stmt".
2419 * If "tag" is set, then the access relations are tagged with
2420 * the corresponding reference identifiers.
2421 * If "kill" is set, then "stmt" is a kill statement and we simply
2422 * add the argument of the kill operation.
2424 * If "must" is set, then we only add the accesses that are definitely
2425 * performed. Otherwise, we add all potential accesses.
2426 * In particular, if the statement has any arguments, then if "must" is
2427 * set we currently skip the statement completely. If "must" is not set,
2428 * we project out the values of the statement arguments.
2429 * If the statement body is not an expression tree, then we cannot
2430 * know for sure if/when the accesses inside the tree are performed.
2431 * We therefore ignore such statements when "must" is set.
2433 static __isl_give isl_union_map
*stmt_collect_accesses(struct pet_stmt
*stmt
,
2434 int read
, int write
, int kill
, int must
, int tag
,
2435 __isl_take isl_space
*dim
)
2437 struct pet_expr_collect_accesses_data data
= { read
, write
, must
, tag
};
2442 data
.accesses
= isl_union_map_empty(dim
);
2444 if (must
&& stmt
->n_arg
> 0)
2445 return data
.accesses
;
2446 if (must
&& pet_tree_get_type(stmt
->body
) != pet_tree_expr
)
2447 return data
.accesses
;
2449 data
.domain
= drop_arguments(isl_set_copy(stmt
->domain
));
2452 pet_expr
*body
, *arg
;
2454 body
= pet_tree_expr_get_expr(stmt
->body
);
2455 arg
= pet_expr_get_arg(body
, 0);
2456 data
.accesses
= expr_collect_access(arg
, tag
,
2457 data
.accesses
, data
.domain
);
2459 pet_expr_free(body
);
2460 } else if (pet_tree_foreach_access_expr(stmt
->body
,
2461 &expr_collect_accesses
, &data
) < 0)
2462 data
.accesses
= isl_union_map_free(data
.accesses
);
2464 isl_set_free(data
.domain
);
2466 return data
.accesses
;
2469 /* Is "stmt" an assignment statement?
2471 int pet_stmt_is_assign(struct pet_stmt
*stmt
)
2475 return pet_tree_is_assign(stmt
->body
);
2478 /* Is "stmt" a kill statement?
2480 int pet_stmt_is_kill(struct pet_stmt
*stmt
)
2484 return pet_tree_is_kill(stmt
->body
);
2487 /* Is "stmt" an assume statement?
2489 int pet_stmt_is_assume(struct pet_stmt
*stmt
)
2493 return pet_tree_is_assume(stmt
->body
);
2496 /* Helper function to add a domain gisted copy of "map" (wrt "set") to "umap".
2498 static __isl_give isl_union_map
*add_gisted(__isl_take isl_union_map
*umap
,
2499 __isl_keep isl_map
*map
, __isl_keep isl_set
*set
)
2503 gist
= isl_map_copy(map
);
2504 gist
= isl_map_gist_domain(gist
, isl_set_copy(set
));
2505 return isl_union_map_add_map(umap
, gist
);
2508 /* Compute a mapping from all arrays (of structs) in scop
2511 * If "from_outermost" is set, then the domain only consists
2512 * of outermost arrays.
2513 * If "to_innermost" is set, then the range only consists
2514 * of innermost arrays.
2516 static __isl_give isl_union_map
*compute_to_inner(struct pet_scop
*scop
,
2517 int from_outermost
, int to_innermost
)
2520 isl_union_map
*to_inner
;
2525 to_inner
= isl_union_map_empty(isl_set_get_space(scop
->context
));
2527 for (i
= 0; i
< scop
->n_array
; ++i
) {
2528 struct pet_array
*array
= scop
->arrays
[i
];
2532 if (to_innermost
&& array
->element_is_record
)
2535 set
= isl_set_copy(array
->extent
);
2536 map
= isl_set_identity(isl_set_copy(set
));
2538 while (set
&& isl_set_is_wrapping(set
)) {
2542 if (!from_outermost
)
2543 to_inner
= add_gisted(to_inner
, map
, set
);
2545 id
= isl_set_get_tuple_id(set
);
2546 wrapped
= isl_set_unwrap(set
);
2547 wrapped
= isl_map_domain_map(wrapped
);
2548 wrapped
= isl_map_set_tuple_id(wrapped
, isl_dim_in
, id
);
2549 map
= isl_map_apply_domain(map
, wrapped
);
2550 set
= isl_map_domain(isl_map_copy(map
));
2553 map
= isl_map_gist_domain(map
, set
);
2554 to_inner
= isl_union_map_add_map(to_inner
, map
);
2560 /* Compute a mapping from all arrays (of structs) in scop
2561 * to their innermost arrays.
2563 * In particular, for each array of a primitive type, the result
2564 * contains the identity mapping on that array.
2565 * For each array involving member accesses, the result
2566 * contains a mapping from the elements of any intermediate array of structs
2567 * to all corresponding elements of the innermost nested arrays.
2569 static __isl_give isl_union_map
*pet_scop_compute_any_to_inner(
2570 struct pet_scop
*scop
)
2572 return compute_to_inner(scop
, 0, 1);
2575 /* Compute a mapping from all outermost arrays (of structs) in scop
2576 * to their innermost members.
2578 __isl_give isl_union_map
*pet_scop_compute_outer_to_inner(struct pet_scop
*scop
)
2580 return compute_to_inner(scop
, 1, 1);
2583 /* Compute a mapping from all outermost arrays (of structs) in scop
2584 * to their members, including the outermost arrays themselves.
2586 __isl_give isl_union_map
*pet_scop_compute_outer_to_any(struct pet_scop
*scop
)
2588 return compute_to_inner(scop
, 1, 0);
2591 /* Collect and return all read access relations (if "read" is set)
2592 * and/or all write access relations (if "write" is set) in "scop".
2593 * If "kill" is set, then we only add the arguments of kill operations.
2594 * If "must" is set, then we only add the accesses that are definitely
2595 * performed. Otherwise, we add all potential accesses.
2596 * If "tag" is set, then the access relations are tagged with
2597 * the corresponding reference identifiers.
2598 * For accesses to structures, the returned access relation accesses
2599 * all individual fields in the structures.
2601 static __isl_give isl_union_map
*scop_collect_accesses(struct pet_scop
*scop
,
2602 int read
, int write
, int kill
, int must
, int tag
)
2605 isl_union_map
*accesses
;
2606 isl_union_set
*arrays
;
2607 isl_union_map
*to_inner
;
2612 accesses
= isl_union_map_empty(isl_set_get_space(scop
->context
));
2614 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2615 struct pet_stmt
*stmt
= scop
->stmts
[i
];
2616 isl_union_map
*accesses_i
;
2619 if (kill
&& !pet_stmt_is_kill(stmt
))
2622 space
= isl_set_get_space(scop
->context
);
2623 accesses_i
= stmt_collect_accesses(stmt
, read
, write
, kill
,
2625 accesses
= isl_union_map_union(accesses
, accesses_i
);
2628 arrays
= isl_union_set_empty(isl_union_map_get_space(accesses
));
2629 for (i
= 0; i
< scop
->n_array
; ++i
) {
2630 isl_set
*extent
= isl_set_copy(scop
->arrays
[i
]->extent
);
2631 arrays
= isl_union_set_add_set(arrays
, extent
);
2633 accesses
= isl_union_map_intersect_range(accesses
, arrays
);
2635 to_inner
= pet_scop_compute_any_to_inner(scop
);
2636 accesses
= isl_union_map_apply_range(accesses
, to_inner
);
2641 /* Collect all potential read access relations.
2643 __isl_give isl_union_map
*pet_scop_collect_may_reads(struct pet_scop
*scop
)
2645 return scop_collect_accesses(scop
, 1, 0, 0, 0, 0);
2648 /* Collect all potential write access relations.
2650 __isl_give isl_union_map
*pet_scop_collect_may_writes(struct pet_scop
*scop
)
2652 return scop_collect_accesses(scop
, 0, 1, 0, 0, 0);
2655 /* Collect all definite write access relations.
2657 __isl_give isl_union_map
*pet_scop_collect_must_writes(struct pet_scop
*scop
)
2659 return scop_collect_accesses(scop
, 0, 1, 0, 1, 0);
2662 /* Collect all definite kill access relations.
2664 __isl_give isl_union_map
*pet_scop_collect_must_kills(struct pet_scop
*scop
)
2666 return scop_collect_accesses(scop
, 0, 0, 1, 1, 0);
2669 /* Collect all tagged potential read access relations.
2671 __isl_give isl_union_map
*pet_scop_collect_tagged_may_reads(
2672 struct pet_scop
*scop
)
2674 return scop_collect_accesses(scop
, 1, 0, 0, 0, 1);
2677 /* Collect all tagged potential write access relations.
2679 __isl_give isl_union_map
*pet_scop_collect_tagged_may_writes(
2680 struct pet_scop
*scop
)
2682 return scop_collect_accesses(scop
, 0, 1, 0, 0, 1);
2685 /* Collect all tagged definite write access relations.
2687 __isl_give isl_union_map
*pet_scop_collect_tagged_must_writes(
2688 struct pet_scop
*scop
)
2690 return scop_collect_accesses(scop
, 0, 1, 0, 1, 1);
2693 /* Collect all tagged definite kill access relations.
2695 __isl_give isl_union_map
*pet_scop_collect_tagged_must_kills(
2696 struct pet_scop
*scop
)
2698 return scop_collect_accesses(scop
, 0, 0, 1, 1, 1);
2701 /* Collect and return the union of iteration domains in "scop".
2703 __isl_give isl_union_set
*pet_scop_collect_domains(struct pet_scop
*scop
)
2707 isl_union_set
*domain
;
2712 domain
= isl_union_set_empty(isl_set_get_space(scop
->context
));
2714 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2715 domain_i
= isl_set_copy(scop
->stmts
[i
]->domain
);
2716 domain
= isl_union_set_add_set(domain
, domain_i
);
2722 /* Collect and return the schedules of the statements in "scop".
2723 * The range is normalized to the maximal number of scheduling
2726 __isl_give isl_union_map
*pet_scop_collect_schedule(struct pet_scop
*scop
)
2729 isl_map
*schedule_i
;
2730 isl_union_map
*schedule
;
2731 int depth
, max_depth
= 0;
2736 schedule
= isl_union_map_empty(isl_set_get_space(scop
->context
));
2738 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2739 depth
= isl_map_dim(scop
->stmts
[i
]->schedule
, isl_dim_out
);
2740 if (depth
> max_depth
)
2744 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2745 schedule_i
= isl_map_copy(scop
->stmts
[i
]->schedule
);
2746 depth
= isl_map_dim(schedule_i
, isl_dim_out
);
2747 schedule_i
= isl_map_add_dims(schedule_i
, isl_dim_out
,
2749 for (j
= depth
; j
< max_depth
; ++j
)
2750 schedule_i
= isl_map_fix_si(schedule_i
,
2752 schedule
= isl_union_map_add_map(schedule
, schedule_i
);
2758 /* Add a reference identifier to all access expressions in "stmt".
2759 * "n_ref" points to an integer that contains the sequence number
2760 * of the next reference.
2762 static struct pet_stmt
*stmt_add_ref_ids(struct pet_stmt
*stmt
, int *n_ref
)
2769 for (i
= 0; i
< stmt
->n_arg
; ++i
) {
2770 stmt
->args
[i
] = pet_expr_add_ref_ids(stmt
->args
[i
], n_ref
);
2772 return pet_stmt_free(stmt
);
2775 stmt
->body
= pet_tree_add_ref_ids(stmt
->body
, n_ref
);
2777 return pet_stmt_free(stmt
);
2782 /* Add a reference identifier to all access expressions in "scop".
2784 struct pet_scop
*pet_scop_add_ref_ids(struct pet_scop
*scop
)
2793 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2794 scop
->stmts
[i
] = stmt_add_ref_ids(scop
->stmts
[i
], &n_ref
);
2795 if (!scop
->stmts
[i
])
2796 return pet_scop_free(scop
);
2802 /* Reset the user pointer on all parameter ids in "array".
2804 static struct pet_array
*array_anonymize(struct pet_array
*array
)
2809 array
->context
= isl_set_reset_user(array
->context
);
2810 array
->extent
= isl_set_reset_user(array
->extent
);
2811 if (!array
->context
|| !array
->extent
)
2812 return pet_array_free(array
);
2817 /* Reset the user pointer on all parameter and tuple ids in "stmt".
2819 static struct pet_stmt
*stmt_anonymize(struct pet_stmt
*stmt
)
2828 stmt
->domain
= isl_set_reset_user(stmt
->domain
);
2829 stmt
->schedule
= isl_map_reset_user(stmt
->schedule
);
2830 if (!stmt
->domain
|| !stmt
->schedule
)
2831 return pet_stmt_free(stmt
);
2833 for (i
= 0; i
< stmt
->n_arg
; ++i
) {
2834 stmt
->args
[i
] = pet_expr_anonymize(stmt
->args
[i
]);
2836 return pet_stmt_free(stmt
);
2839 stmt
->body
= pet_tree_anonymize(stmt
->body
);
2841 return pet_stmt_free(stmt
);
2846 /* Reset the user pointer on the tuple ids and all parameter ids
2849 static struct pet_implication
*implication_anonymize(
2850 struct pet_implication
*implication
)
2855 implication
->extension
= isl_map_reset_user(implication
->extension
);
2856 if (!implication
->extension
)
2857 return pet_implication_free(implication
);
2862 /* Reset the user pointer on the tuple ids and all parameter ids
2863 * in "independence".
2865 static struct pet_independence
*independence_anonymize(
2866 struct pet_independence
*independence
)
2871 independence
->filter
= isl_union_map_reset_user(independence
->filter
);
2872 independence
->local
= isl_union_set_reset_user(independence
->local
);
2873 if (!independence
->filter
|| !independence
->local
)
2874 return pet_independence_free(independence
);
2876 return independence
;
2879 /* Reset the user pointer on all parameter and tuple ids in "scop".
2881 struct pet_scop
*pet_scop_anonymize(struct pet_scop
*scop
)
2888 scop
->context
= isl_set_reset_user(scop
->context
);
2889 scop
->context_value
= isl_set_reset_user(scop
->context_value
);
2890 if (!scop
->context
|| !scop
->context_value
)
2891 return pet_scop_free(scop
);
2893 for (i
= 0; i
< scop
->n_array
; ++i
) {
2894 scop
->arrays
[i
] = array_anonymize(scop
->arrays
[i
]);
2895 if (!scop
->arrays
[i
])
2896 return pet_scop_free(scop
);
2899 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
2900 scop
->stmts
[i
] = stmt_anonymize(scop
->stmts
[i
]);
2901 if (!scop
->stmts
[i
])
2902 return pet_scop_free(scop
);
2905 for (i
= 0; i
< scop
->n_implication
; ++i
) {
2906 scop
->implications
[i
] =
2907 implication_anonymize(scop
->implications
[i
]);
2908 if (!scop
->implications
[i
])
2909 return pet_scop_free(scop
);
2912 for (i
= 0; i
< scop
->n_independence
; ++i
) {
2913 scop
->independences
[i
] =
2914 independence_anonymize(scop
->independences
[i
]);
2915 if (!scop
->independences
[i
])
2916 return pet_scop_free(scop
);
2922 /* Compute the gist of the iteration domain and all access relations
2923 * of "stmt" based on the constraints on the parameters specified by "context"
2924 * and the constraints on the values of nested accesses specified
2925 * by "value_bounds".
2927 static struct pet_stmt
*stmt_gist(struct pet_stmt
*stmt
,
2928 __isl_keep isl_set
*context
, __isl_keep isl_union_map
*value_bounds
)
2936 domain
= isl_set_copy(stmt
->domain
);
2937 if (stmt
->n_arg
> 0)
2938 domain
= isl_map_domain(isl_set_unwrap(domain
));
2940 domain
= isl_set_intersect_params(domain
, isl_set_copy(context
));
2942 for (i
= 0; i
< stmt
->n_arg
; ++i
) {
2943 stmt
->args
[i
] = pet_expr_gist(stmt
->args
[i
],
2944 domain
, value_bounds
);
2949 stmt
->body
= pet_tree_gist(stmt
->body
, domain
, value_bounds
);
2953 isl_set_free(domain
);
2955 domain
= isl_set_universe(pet_stmt_get_space(stmt
));
2956 domain
= isl_set_intersect_params(domain
, isl_set_copy(context
));
2957 if (stmt
->n_arg
> 0)
2958 domain
= pet_value_bounds_apply(domain
, stmt
->n_arg
, stmt
->args
,
2960 stmt
->domain
= isl_set_gist(stmt
->domain
, domain
);
2962 return pet_stmt_free(stmt
);
2966 isl_set_free(domain
);
2967 return pet_stmt_free(stmt
);
2970 /* Compute the gist of the extent of the array
2971 * based on the constraints on the parameters specified by "context".
2973 static struct pet_array
*array_gist(struct pet_array
*array
,
2974 __isl_keep isl_set
*context
)
2979 array
->extent
= isl_set_gist_params(array
->extent
,
2980 isl_set_copy(context
));
2982 return pet_array_free(array
);
2987 /* Compute the gist of all sets and relations in "scop"
2988 * based on the constraints on the parameters specified by "scop->context"
2989 * and the constraints on the values of nested accesses specified
2990 * by "value_bounds".
2992 struct pet_scop
*pet_scop_gist(struct pet_scop
*scop
,
2993 __isl_keep isl_union_map
*value_bounds
)
3000 scop
->context
= isl_set_coalesce(scop
->context
);
3002 return pet_scop_free(scop
);
3004 for (i
= 0; i
< scop
->n_array
; ++i
) {
3005 scop
->arrays
[i
] = array_gist(scop
->arrays
[i
], scop
->context
);
3006 if (!scop
->arrays
[i
])
3007 return pet_scop_free(scop
);
3010 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
3011 scop
->stmts
[i
] = stmt_gist(scop
->stmts
[i
], scop
->context
,
3013 if (!scop
->stmts
[i
])
3014 return pet_scop_free(scop
);
3020 /* Intersect the context of "scop" with "context".
3021 * To ensure that we don't introduce any unnamed parameters in
3022 * the context of "scop", we first remove the unnamed parameters
3025 struct pet_scop
*pet_scop_restrict_context(struct pet_scop
*scop
,
3026 __isl_take isl_set
*context
)
3031 context
= pet_nested_remove_from_set(context
);
3032 scop
->context
= isl_set_intersect(scop
->context
, context
);
3034 return pet_scop_free(scop
);
3038 isl_set_free(context
);
3039 return pet_scop_free(scop
);
3042 /* Drop the current context of "scop". That is, replace the context
3043 * by a universal set.
3045 struct pet_scop
*pet_scop_reset_context(struct pet_scop
*scop
)
3052 space
= isl_set_get_space(scop
->context
);
3053 isl_set_free(scop
->context
);
3054 scop
->context
= isl_set_universe(space
);
3056 return pet_scop_free(scop
);
3061 /* Append "array" to the arrays of "scop".
3063 struct pet_scop
*pet_scop_add_array(struct pet_scop
*scop
,
3064 struct pet_array
*array
)
3067 struct pet_array
**arrays
;
3069 if (!array
|| !scop
)
3072 ctx
= isl_set_get_ctx(scop
->context
);
3073 arrays
= isl_realloc_array(ctx
, scop
->arrays
, struct pet_array
*,
3077 scop
->arrays
= arrays
;
3078 scop
->arrays
[scop
->n_array
] = array
;
3083 pet_array_free(array
);
3084 return pet_scop_free(scop
);
3087 /* Create an index expression for an access to a virtual array
3088 * representing the result of a condition.
3089 * Unlike other accessed data, the id of the array is NULL as
3090 * there is no ValueDecl in the program corresponding to the virtual
3092 * The index expression is created as an identity mapping on "space".
3093 * That is, the dimension of the array is the same as that of "space".
3095 __isl_give isl_multi_pw_aff
*pet_create_test_index(__isl_take isl_space
*space
,
3101 snprintf(name
, sizeof(name
), "__pet_test_%d", test_nr
);
3102 id
= isl_id_alloc(isl_space_get_ctx(space
), name
, NULL
);
3103 space
= isl_space_map_from_set(space
);
3104 space
= isl_space_set_tuple_id(space
, isl_dim_out
, id
);
3105 return isl_multi_pw_aff_identity(space
);
3108 /* Add an array with the given extent to the list
3109 * of arrays in "scop" and return the extended pet_scop.
3110 * Specifically, the extent is determined by the image of "domain"
3112 * "int_size" is the number of bytes needed to represent values of type "int".
3113 * The array is marked as attaining values 0 and 1 only and
3114 * as each element being assigned at most once.
3116 struct pet_scop
*pet_scop_add_boolean_array(struct pet_scop
*scop
,
3117 __isl_take isl_set
*domain
, __isl_take isl_multi_pw_aff
*index
,
3122 struct pet_array
*array
;
3125 if (!scop
|| !domain
|| !index
)
3128 ctx
= isl_multi_pw_aff_get_ctx(index
);
3129 array
= isl_calloc_type(ctx
, struct pet_array
);
3133 access
= isl_map_from_multi_pw_aff(index
);
3134 access
= isl_map_intersect_domain(access
, domain
);
3135 array
->extent
= isl_map_range(access
);
3136 space
= isl_space_params_alloc(ctx
, 0);
3137 array
->context
= isl_set_universe(space
);
3138 space
= isl_space_set_alloc(ctx
, 0, 1);
3139 array
->value_bounds
= isl_set_universe(space
);
3140 array
->value_bounds
= isl_set_lower_bound_si(array
->value_bounds
,
3142 array
->value_bounds
= isl_set_upper_bound_si(array
->value_bounds
,
3144 array
->element_type
= strdup("int");
3145 array
->element_size
= int_size
;
3146 array
->uniquely_defined
= 1;
3148 if (!array
->extent
|| !array
->context
)
3149 array
= pet_array_free(array
);
3151 scop
= pet_scop_add_array(scop
, array
);
3155 isl_set_free(domain
);
3156 isl_multi_pw_aff_free(index
);
3157 return pet_scop_free(scop
);
3160 /* Create and return an implication on filter values equal to "satisfied"
3161 * with extension "map".
3163 static struct pet_implication
*new_implication(__isl_take isl_map
*map
,
3167 struct pet_implication
*implication
;
3171 ctx
= isl_map_get_ctx(map
);
3172 implication
= isl_alloc_type(ctx
, struct pet_implication
);
3176 implication
->extension
= map
;
3177 implication
->satisfied
= satisfied
;
3185 /* Add an implication on filter values equal to "satisfied"
3186 * with extension "map" to "scop".
3188 struct pet_scop
*pet_scop_add_implication(struct pet_scop
*scop
,
3189 __isl_take isl_map
*map
, int satisfied
)
3192 struct pet_implication
*implication
;
3193 struct pet_implication
**implications
;
3195 implication
= new_implication(map
, satisfied
);
3196 if (!scop
|| !implication
)
3199 ctx
= isl_set_get_ctx(scop
->context
);
3200 implications
= isl_realloc_array(ctx
, scop
->implications
,
3201 struct pet_implication
*,
3202 scop
->n_implication
+ 1);
3205 scop
->implications
= implications
;
3206 scop
->implications
[scop
->n_implication
] = implication
;
3207 scop
->n_implication
++;
3211 pet_implication_free(implication
);
3212 return pet_scop_free(scop
);
3215 /* Create and return a function that maps the iteration domains
3216 * of the statements in "scop" onto their outer "n" dimensions.
3217 * "space" is the parameters space of the created function.
3219 static __isl_give isl_union_pw_multi_aff
*outer_projection(
3220 struct pet_scop
*scop
, __isl_take isl_space
*space
, int n
)
3223 isl_union_pw_multi_aff
*res
;
3225 res
= isl_union_pw_multi_aff_empty(space
);
3228 return isl_union_pw_multi_aff_free(res
);
3230 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
3231 struct pet_stmt
*stmt
= scop
->stmts
[i
];
3234 isl_pw_multi_aff
*pma
;
3236 space
= pet_stmt_get_space(stmt
);
3237 ma
= pet_prefix_projection(space
, n
);
3238 pma
= isl_pw_multi_aff_from_multi_aff(ma
);
3239 res
= isl_union_pw_multi_aff_add_pw_multi_aff(res
, pma
);
3245 /* Add an independence to "scop" for the inner iterator of "domain"
3246 * with local variables "local", where "domain" represents the outer
3247 * loop iterators of all statements in "scop".
3248 * If "sign" is positive, then the inner iterator increases.
3249 * Otherwise it decreases.
3251 * The independence is supposed to filter out any dependence of
3252 * an iteration of domain on a previous iteration along the inner dimension.
3253 * We therefore create a mapping from an iteration to later iterations and
3254 * then plug in the projection of the iterations domains of "scop"
3255 * onto the outer loop iterators.
3257 struct pet_scop
*pet_scop_set_independent(struct pet_scop
*scop
,
3258 __isl_keep isl_set
*domain
, __isl_take isl_union_set
*local
, int sign
)
3263 isl_union_map
*independence
;
3264 isl_union_pw_multi_aff
*proj
;
3266 if (!scop
|| !domain
|| !local
)
3269 dim
= isl_set_dim(domain
, isl_dim_set
);
3270 space
= isl_space_map_from_set(isl_set_get_space(domain
));
3271 map
= isl_map_universe(space
);
3272 for (i
= 0; i
+ 1 < dim
; ++i
)
3273 map
= isl_map_equate(map
, isl_dim_in
, i
, isl_dim_out
, i
);
3275 map
= isl_map_order_lt(map
,
3276 isl_dim_in
, dim
- 1, isl_dim_out
, dim
- 1);
3278 map
= isl_map_order_gt(map
,
3279 isl_dim_in
, dim
- 1, isl_dim_out
, dim
- 1);
3281 independence
= isl_union_map_from_map(map
);
3282 space
= isl_space_params(isl_set_get_space(domain
));
3283 proj
= outer_projection(scop
, space
, dim
);
3284 independence
= isl_union_map_preimage_domain_union_pw_multi_aff(
3285 independence
, isl_union_pw_multi_aff_copy(proj
));
3286 independence
= isl_union_map_preimage_range_union_pw_multi_aff(
3287 independence
, proj
);
3289 scop
= pet_scop_add_independence(scop
, independence
, local
);
3293 isl_union_set_free(local
);
3294 return pet_scop_free(scop
);
3297 /* Given an access expression, check if it is data dependent.
3298 * If so, set *found and abort the search.
3300 static int is_data_dependent(__isl_keep pet_expr
*expr
, void *user
)
3304 if (pet_expr_get_n_arg(expr
) > 0) {
3312 /* Does "scop" contain any data dependent accesses?
3314 * Check the body of each statement for such accesses.
3316 int pet_scop_has_data_dependent_accesses(struct pet_scop
*scop
)
3324 for (i
= 0; i
< scop
->n_stmt
; ++i
) {
3325 int r
= pet_tree_foreach_access_expr(scop
->stmts
[i
]->body
,
3326 &is_data_dependent
, &found
);
3327 if (r
< 0 && !found
)
3336 /* Does "scop" contain and data dependent conditions?
3338 int pet_scop_has_data_dependent_conditions(struct pet_scop
*scop
)
3345 for (i
= 0; i
< scop
->n_stmt
; ++i
)
3346 if (scop
->stmts
[i
]->n_arg
> 0)
3352 /* Keep track of the "input" file inside the (extended) "scop".
3354 struct pet_scop
*pet_scop_set_input_file(struct pet_scop
*scop
, FILE *input
)
3356 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
3366 /* Print the original code corresponding to "scop" to printer "p".
3368 * pet_scop_print_original can only be called from
3369 * a pet_transform_C_source callback. This means that the input
3370 * file is stored in the extended scop and that the printer prints
3373 __isl_give isl_printer
*pet_scop_print_original(struct pet_scop
*scop
,
3374 __isl_take isl_printer
*p
)
3376 struct pet_scop_ext
*ext
= (struct pet_scop_ext
*) scop
;
3378 unsigned start
, end
;
3381 return isl_printer_free(p
);
3384 isl_die(isl_printer_get_ctx(p
), isl_error_invalid
,
3385 "no input file stored in scop",
3386 return isl_printer_free(p
));
3388 output
= isl_printer_get_file(p
);
3390 return isl_printer_free(p
);
3392 start
= pet_loc_get_start(scop
->loc
);
3393 end
= pet_loc_get_end(scop
->loc
);
3394 if (copy(ext
->input
, output
, start
, end
) < 0)
3395 return isl_printer_free(p
);