4 #include <clang/AST/ASTDiagnostic.h>
5 #include <clang/AST/Expr.h>
6 #include <clang/AST/RecursiveASTVisitor.h>
15 #include "scop_plus.h"
20 using namespace clang
;
22 /* Look for any assignments to variables in part of the parse
23 * tree and set assigned_value to NULL for each of them.
25 * This ensures that we won't use any previously stored value
26 * in the current subtree and its parents.
28 struct clear_assignments
: RecursiveASTVisitor
<clear_assignments
> {
29 map
<ValueDecl
*, Expr
*> &assigned_value
;
31 clear_assignments(map
<ValueDecl
*, Expr
*> &assigned_value
) :
32 assigned_value(assigned_value
) {}
34 bool VisitBinaryOperator(BinaryOperator
*expr
) {
39 if (!expr
->isAssignmentOp())
42 if (lhs
->getStmtClass() != Stmt::DeclRefExprClass
)
44 ref
= cast
<DeclRefExpr
>(lhs
);
45 decl
= ref
->getDecl();
46 assigned_value
[decl
] = NULL
;
51 /* Keep a copy of the currently assigned values.
53 * Any variable that is assigned a value inside the current scope
54 * is removed again when we leave the scope (either because it wasn't
55 * stored in the cache or because it has a different value in the cache).
57 struct assigned_value_cache
{
58 map
<ValueDecl
*, Expr
*> &assigned_value
;
59 map
<ValueDecl
*, Expr
*> cache
;
61 assigned_value_cache(map
<ValueDecl
*, Expr
*> &assigned_value
) :
62 assigned_value(assigned_value
), cache(assigned_value
) {}
63 ~assigned_value_cache() {
64 map
<ValueDecl
*, Expr
*>::iterator it
= cache
.begin();
65 for (it
= assigned_value
.begin(); it
!= assigned_value
.end();
68 (cache
.find(it
->first
) != cache
.end() &&
69 cache
[it
->first
] != it
->second
))
70 cache
[it
->first
] = NULL
;
72 assigned_value
= cache
;
76 /* Called if we found something we (currently) cannot handle.
77 * We'll provide more informative warnings later.
79 * We only actually complain if autodetect is false.
81 void PetScan::unsupported(Stmt
*stmt
)
86 SourceLocation loc
= stmt
->getLocStart();
87 Diagnostic
&diag
= PP
.getDiagnostics();
88 unsigned id
= diag
.getCustomDiagID(Diagnostic::Warning
, "unsupported");
89 DiagnosticBuilder B
= diag
.Report(loc
, id
) << stmt
->getSourceRange();
92 /* Extract an integer from "expr" and store it in "v".
94 int PetScan::extract_int(IntegerLiteral
*expr
, isl_int
*v
)
96 const Type
*type
= expr
->getType().getTypePtr();
97 int is_signed
= type
->hasSignedIntegerRepresentation();
100 int64_t i
= expr
->getValue().getSExtValue();
101 isl_int_set_si(*v
, i
);
103 uint64_t i
= expr
->getValue().getZExtValue();
104 isl_int_set_ui(*v
, i
);
110 /* Extract an affine expression from the IntegerLiteral "expr".
112 __isl_give isl_pw_aff
*PetScan::extract_affine(IntegerLiteral
*expr
)
114 isl_dim
*dim
= isl_dim_set_alloc(ctx
, 0, 0);
115 isl_local_space
*ls
= isl_local_space_from_dim(isl_dim_copy(dim
));
116 isl_aff
*aff
= isl_aff_zero(ls
);
117 isl_set
*dom
= isl_set_universe(dim
);
121 extract_int(expr
, &v
);
122 aff
= isl_aff_add_constant(aff
, v
);
125 return isl_pw_aff_alloc(dom
, aff
);
128 /* Extract an affine expression from the APInt "val".
130 __isl_give isl_pw_aff
*PetScan::extract_affine(const llvm::APInt
&val
)
132 isl_dim
*dim
= isl_dim_set_alloc(ctx
, 0, 0);
133 isl_local_space
*ls
= isl_local_space_from_dim(isl_dim_copy(dim
));
134 isl_aff
*aff
= isl_aff_zero(ls
);
135 isl_set
*dom
= isl_set_universe(dim
);
139 isl_int_set_ui(v
, val
.getZExtValue());
140 aff
= isl_aff_add_constant(aff
, v
);
143 return isl_pw_aff_alloc(dom
, aff
);
146 __isl_give isl_pw_aff
*PetScan::extract_affine(ImplicitCastExpr
*expr
)
148 return extract_affine(expr
->getSubExpr());
151 /* Extract an affine expression from the DeclRefExpr "expr".
153 * If we have recorded an expression that was assigned to the variable
154 * before, then we convert this expressoin to an isl_pw_aff if it is
155 * affine and to an extra parameter otherwise (provided nesting_enabled is set).
157 * Otherwise, we simply return an expression that is equal
158 * to a parameter corresponding to the referenced variable.
160 __isl_give isl_pw_aff
*PetScan::extract_affine(DeclRefExpr
*expr
)
162 ValueDecl
*decl
= expr
->getDecl();
163 const Type
*type
= decl
->getType().getTypePtr();
169 if (!type
->isIntegerType()) {
174 if (assigned_value
.find(decl
) != assigned_value
.end() &&
175 assigned_value
[decl
] != NULL
) {
176 if (is_affine(assigned_value
[decl
]))
177 return extract_affine(assigned_value
[decl
]);
179 return non_affine(expr
);
182 id
= isl_id_alloc(ctx
, decl
->getName().str().c_str(), decl
);
183 dim
= isl_dim_set_alloc(ctx
, 1, 0);
185 dim
= isl_dim_set_dim_id(dim
, isl_dim_param
, 0, id
);
187 dom
= isl_set_universe(isl_dim_copy(dim
));
188 aff
= isl_aff_zero(isl_local_space_from_dim(dim
));
189 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_param
, 0, 1);
191 return isl_pw_aff_alloc(dom
, aff
);
194 /* Extract an affine expression from an integer division operation.
195 * In particular, if "expr" is lhs/rhs, then return
197 * lhs >= 0 ? floor(lhs/rhs) : ceil(lhs/rhs)
199 * The second argument (rhs) is required to be a (positive) integer constant.
201 __isl_give isl_pw_aff
*PetScan::extract_affine_div(BinaryOperator
*expr
)
204 isl_pw_aff
*lhs
, *lhs_f
, *lhs_c
;
209 rhs_expr
= expr
->getRHS();
210 if (rhs_expr
->getStmtClass() != Stmt::IntegerLiteralClass
) {
215 lhs
= extract_affine(expr
->getLHS());
216 cond
= isl_pw_aff_nonneg_set(isl_pw_aff_copy(lhs
));
219 extract_int(cast
<IntegerLiteral
>(rhs_expr
), &v
);
220 lhs
= isl_pw_aff_scale_down(lhs
, v
);
223 lhs_f
= isl_pw_aff_floor(isl_pw_aff_copy(lhs
));
224 lhs_c
= isl_pw_aff_ceil(lhs
);
225 res
= isl_pw_aff_cond(cond
, lhs_f
, lhs_c
);
230 /* Extract an affine expression from a modulo operation.
231 * In particular, if "expr" is lhs/rhs, then return
233 * lhs - rhs * (lhs >= 0 ? floor(lhs/rhs) : ceil(lhs/rhs))
235 * The second argument (rhs) is required to be a (positive) integer constant.
237 __isl_give isl_pw_aff
*PetScan::extract_affine_mod(BinaryOperator
*expr
)
240 isl_pw_aff
*lhs
, *lhs_f
, *lhs_c
;
245 rhs_expr
= expr
->getRHS();
246 if (rhs_expr
->getStmtClass() != Stmt::IntegerLiteralClass
) {
251 lhs
= extract_affine(expr
->getLHS());
252 cond
= isl_pw_aff_nonneg_set(isl_pw_aff_copy(lhs
));
255 extract_int(cast
<IntegerLiteral
>(rhs_expr
), &v
);
256 res
= isl_pw_aff_scale_down(isl_pw_aff_copy(lhs
), v
);
258 lhs_f
= isl_pw_aff_floor(isl_pw_aff_copy(res
));
259 lhs_c
= isl_pw_aff_ceil(res
);
260 res
= isl_pw_aff_cond(cond
, lhs_f
, lhs_c
);
262 res
= isl_pw_aff_scale(res
, v
);
265 res
= isl_pw_aff_sub(lhs
, res
);
270 /* Extract an affine expression from a multiplication operation.
271 * This is only allowed if at least one of the two arguments
272 * is a (piecewise) constant.
274 __isl_give isl_pw_aff
*PetScan::extract_affine_mul(BinaryOperator
*expr
)
279 lhs
= extract_affine(expr
->getLHS());
280 rhs
= extract_affine(expr
->getRHS());
282 if (!isl_pw_aff_is_cst(lhs
) && !isl_pw_aff_is_cst(rhs
)) {
283 isl_pw_aff_free(lhs
);
284 isl_pw_aff_free(rhs
);
289 return isl_pw_aff_mul(lhs
, rhs
);
292 /* Extract an affine expression from some binary operations.
294 __isl_give isl_pw_aff
*PetScan::extract_affine(BinaryOperator
*expr
)
300 switch (expr
->getOpcode()) {
305 return extract_affine_div(expr
);
307 return extract_affine_mod(expr
);
309 return extract_affine_mul(expr
);
315 lhs
= extract_affine(expr
->getLHS());
316 rhs
= extract_affine(expr
->getRHS());
318 switch (expr
->getOpcode()) {
320 res
= isl_pw_aff_add(lhs
, rhs
);
323 res
= isl_pw_aff_sub(lhs
, rhs
);
332 /* Extract an affine expression from a negation operation.
334 __isl_give isl_pw_aff
*PetScan::extract_affine(UnaryOperator
*expr
)
336 if (expr
->getOpcode() == UO_Minus
)
337 return isl_pw_aff_neg(extract_affine(expr
->getSubExpr()));
343 __isl_give isl_pw_aff
*PetScan::extract_affine(ParenExpr
*expr
)
345 return extract_affine(expr
->getSubExpr());
348 /* Extract an affine expression from some special function calls.
349 * In particular, we handle "min", "max", "ceild" and "floord".
350 * In case of the latter two, the second argument needs to be
351 * a (positive) integer constant.
353 __isl_give isl_pw_aff
*PetScan::extract_affine(CallExpr
*expr
)
357 isl_pw_aff
*aff1
, *aff2
;
359 fd
= expr
->getDirectCallee();
365 name
= fd
->getDeclName().getAsString();
366 if (!(expr
->getNumArgs() == 2 && name
== "min") &&
367 !(expr
->getNumArgs() == 2 && name
== "max") &&
368 !(expr
->getNumArgs() == 2 && name
== "floord") &&
369 !(expr
->getNumArgs() == 2 && name
== "ceild")) {
374 if (name
== "min" || name
== "max") {
375 aff1
= extract_affine(expr
->getArg(0));
376 aff2
= extract_affine(expr
->getArg(1));
379 aff1
= isl_pw_aff_min(aff1
, aff2
);
381 aff1
= isl_pw_aff_max(aff1
, aff2
);
382 } else if (name
== "floord" || name
== "ceild") {
384 Expr
*arg2
= expr
->getArg(1);
386 if (arg2
->getStmtClass() != Stmt::IntegerLiteralClass
) {
390 aff1
= extract_affine(expr
->getArg(0));
392 extract_int(cast
<IntegerLiteral
>(arg2
), &v
);
393 aff1
= isl_pw_aff_scale_down(aff1
, v
);
395 if (name
== "floord")
396 aff1
= isl_pw_aff_floor(aff1
);
398 aff1
= isl_pw_aff_ceil(aff1
);
408 /* This method is called when we come across a non-affine expression.
409 * If nesting is allowed, we return a new parameter that corresponds
410 * to the non-affine expression. Otherwise, we simply complain.
412 * The new parameter is resolved in resolve_nested.
414 isl_pw_aff
*PetScan::non_affine(Expr
*expr
)
421 if (!nesting_enabled
) {
426 id
= isl_id_alloc(ctx
, NULL
, expr
);
427 dim
= isl_dim_set_alloc(ctx
, 1, 0);
429 dim
= isl_dim_set_dim_id(dim
, isl_dim_param
, 0, id
);
431 dom
= isl_set_universe(isl_dim_copy(dim
));
432 aff
= isl_aff_zero(isl_local_space_from_dim(dim
));
433 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_param
, 0, 1);
435 return isl_pw_aff_alloc(dom
, aff
);
438 /* Affine expressions are not supposed to contain array accesses,
439 * but if nesting is allowed, we return a parameter corresponding
440 * to the array access.
442 __isl_give isl_pw_aff
*PetScan::extract_affine(ArraySubscriptExpr
*expr
)
444 return non_affine(expr
);
447 /* Extract an affine expression from a conditional operation.
449 __isl_give isl_pw_aff
*PetScan::extract_affine(ConditionalOperator
*expr
)
452 isl_pw_aff
*lhs
, *rhs
;
454 cond
= extract_condition(expr
->getCond());
455 lhs
= extract_affine(expr
->getTrueExpr());
456 rhs
= extract_affine(expr
->getFalseExpr());
458 return isl_pw_aff_cond(cond
, lhs
, rhs
);
461 /* Extract an affine expression, if possible, from "expr".
462 * Otherwise return NULL.
464 __isl_give isl_pw_aff
*PetScan::extract_affine(Expr
*expr
)
466 switch (expr
->getStmtClass()) {
467 case Stmt::ImplicitCastExprClass
:
468 return extract_affine(cast
<ImplicitCastExpr
>(expr
));
469 case Stmt::IntegerLiteralClass
:
470 return extract_affine(cast
<IntegerLiteral
>(expr
));
471 case Stmt::DeclRefExprClass
:
472 return extract_affine(cast
<DeclRefExpr
>(expr
));
473 case Stmt::BinaryOperatorClass
:
474 return extract_affine(cast
<BinaryOperator
>(expr
));
475 case Stmt::UnaryOperatorClass
:
476 return extract_affine(cast
<UnaryOperator
>(expr
));
477 case Stmt::ParenExprClass
:
478 return extract_affine(cast
<ParenExpr
>(expr
));
479 case Stmt::CallExprClass
:
480 return extract_affine(cast
<CallExpr
>(expr
));
481 case Stmt::ArraySubscriptExprClass
:
482 return extract_affine(cast
<ArraySubscriptExpr
>(expr
));
483 case Stmt::ConditionalOperatorClass
:
484 return extract_affine(cast
<ConditionalOperator
>(expr
));
491 __isl_give isl_map
*PetScan::extract_access(ImplicitCastExpr
*expr
)
493 return extract_access(expr
->getSubExpr());
496 /* Return the depth of an array of the given type.
498 static int array_depth(const Type
*type
)
500 if (type
->isPointerType())
501 return 1 + array_depth(type
->getPointeeType().getTypePtr());
502 if (type
->isArrayType()) {
503 const ArrayType
*atype
;
504 type
= type
->getCanonicalTypeInternal().getTypePtr();
505 atype
= cast
<ArrayType
>(type
);
506 return 1 + array_depth(atype
->getElementType().getTypePtr());
511 /* Return the element type of the given array type.
513 static QualType
base_type(QualType qt
)
515 const Type
*type
= qt
.getTypePtr();
517 if (type
->isPointerType())
518 return base_type(type
->getPointeeType());
519 if (type
->isArrayType()) {
520 const ArrayType
*atype
;
521 type
= type
->getCanonicalTypeInternal().getTypePtr();
522 atype
= cast
<ArrayType
>(type
);
523 return base_type(atype
->getElementType());
528 /* Check if the element type corresponding to the given array type
529 * has a const qualifier.
531 static bool const_base(QualType qt
)
533 const Type
*type
= qt
.getTypePtr();
535 if (type
->isPointerType())
536 return const_base(type
->getPointeeType());
537 if (type
->isArrayType()) {
538 const ArrayType
*atype
;
539 type
= type
->getCanonicalTypeInternal().getTypePtr();
540 atype
= cast
<ArrayType
>(type
);
541 return const_base(atype
->getElementType());
544 return qt
.isConstQualified();
547 /* Extract an access relation from a reference to a variable.
548 * If the variable has name "A" and its type corresponds to an
549 * array of depth d, then the returned access relation is of the
552 * { [] -> A[i_1,...,i_d] }
554 __isl_give isl_map
*PetScan::extract_access(DeclRefExpr
*expr
)
556 ValueDecl
*decl
= expr
->getDecl();
557 int depth
= array_depth(decl
->getType().getTypePtr());
558 isl_id
*id
= isl_id_alloc(ctx
, decl
->getName().str().c_str(), decl
);
559 isl_dim
*dim
= isl_dim_alloc(ctx
, 0, 0, depth
);
562 dim
= isl_dim_set_tuple_id(dim
, isl_dim_out
, id
);
564 access_rel
= isl_map_universe(dim
);
569 /* Extract an access relation from an integer contant.
570 * If the value of the constant is "v", then the returned access relation
575 __isl_give isl_map
*PetScan::extract_access(IntegerLiteral
*expr
)
577 return isl_map_from_pw_aff(extract_affine(expr
));
580 /* Try and extract an access relation from the given Expr.
581 * Return NULL if it doesn't work out.
583 __isl_give isl_map
*PetScan::extract_access(Expr
*expr
)
585 switch (expr
->getStmtClass()) {
586 case Stmt::ImplicitCastExprClass
:
587 return extract_access(cast
<ImplicitCastExpr
>(expr
));
588 case Stmt::DeclRefExprClass
:
589 return extract_access(cast
<DeclRefExpr
>(expr
));
590 case Stmt::ArraySubscriptExprClass
:
591 return extract_access(cast
<ArraySubscriptExpr
>(expr
));
598 /* Assign the affine expression "index" to the output dimension "pos" of "map"
599 * and return the result.
601 __isl_give isl_map
*set_index(__isl_take isl_map
*map
, int pos
,
602 __isl_take isl_pw_aff
*index
)
605 int len
= isl_map_dim(map
, isl_dim_out
);
608 index_map
= isl_map_from_pw_aff(index
);
609 index_map
= isl_map_insert(index_map
, isl_dim_out
, 0, pos
);
610 index_map
= isl_map_add_dims(index_map
, isl_dim_out
, len
- pos
- 1);
611 id
= isl_map_get_tuple_id(map
, isl_dim_out
);
612 index_map
= isl_map_set_tuple_id(index_map
, isl_dim_out
, id
);
614 map
= isl_map_intersect(map
, index_map
);
619 /* Extract an access relation from the given array subscript expression.
620 * If nesting is allowed in general, then we turn it on while
621 * examining the index expression.
623 * We first extract an access relation from the base.
624 * This will result in an access relation with a range that corresponds
625 * to the array being accessed and with earlier indices filled in already.
626 * We then extract the current index and fill that in as well.
627 * The position of the current index is based on the type of base.
628 * If base is the actual array variable, then the depth of this type
629 * will be the same as the depth of the array and we will fill in
630 * the first array index.
631 * Otherwise, the depth of the base type will be smaller and we will fill
634 __isl_give isl_map
*PetScan::extract_access(ArraySubscriptExpr
*expr
)
636 Expr
*base
= expr
->getBase();
637 Expr
*idx
= expr
->getIdx();
639 isl_map
*base_access
;
641 int depth
= array_depth(base
->getType().getTypePtr());
643 bool save_nesting
= nesting_enabled
;
645 nesting_enabled
= allow_nested
;
647 base_access
= extract_access(base
);
648 index
= extract_affine(idx
);
650 nesting_enabled
= save_nesting
;
652 pos
= isl_map_dim(base_access
, isl_dim_out
) - depth
;
653 access
= set_index(base_access
, pos
, index
);
658 /* Check if "expr" calls function "minmax" with two arguments and if so
659 * make lhs and rhs refer to these two arguments.
661 static bool is_minmax(Expr
*expr
, const char *minmax
, Expr
*&lhs
, Expr
*&rhs
)
667 if (expr
->getStmtClass() != Stmt::CallExprClass
)
670 call
= cast
<CallExpr
>(expr
);
671 fd
= call
->getDirectCallee();
675 if (call
->getNumArgs() != 2)
678 name
= fd
->getDeclName().getAsString();
682 lhs
= call
->getArg(0);
683 rhs
= call
->getArg(1);
688 /* Check if "expr" is of the form min(lhs, rhs) and if so make
689 * lhs and rhs refer to the two arguments.
691 static bool is_min(Expr
*expr
, Expr
*&lhs
, Expr
*&rhs
)
693 return is_minmax(expr
, "min", lhs
, rhs
);
696 /* Check if "expr" is of the form max(lhs, rhs) and if so make
697 * lhs and rhs refer to the two arguments.
699 static bool is_max(Expr
*expr
, Expr
*&lhs
, Expr
*&rhs
)
701 return is_minmax(expr
, "max", lhs
, rhs
);
704 /* Extract a set of values satisfying the comparison "LHS op RHS"
705 * "comp" is the original expression that "LHS op RHS" is derived from
706 * and is used for diagnostics.
708 * If the comparison is of the form
712 * then the set is constructed as the intersection of the set corresponding
717 * A similar optimization is performed for max(a,b) <= c.
718 * We do this because that will lead to simpler representations of the set.
719 * If isl is ever enhanced to explicitly deal with min and max expressions,
720 * this optimization can be removed.
722 __isl_give isl_set
*PetScan::extract_comparison(BinaryOperatorKind op
,
723 Expr
*LHS
, Expr
*RHS
, Expr
*comp
)
730 return extract_comparison(BO_LT
, RHS
, LHS
, comp
);
732 return extract_comparison(BO_LE
, RHS
, LHS
, comp
);
734 if (op
== BO_LT
|| op
== BO_LE
) {
736 isl_set
*set1
, *set2
;
737 if (is_min(RHS
, expr1
, expr2
)) {
738 set1
= extract_comparison(op
, LHS
, expr1
, comp
);
739 set2
= extract_comparison(op
, LHS
, expr2
, comp
);
740 return isl_set_intersect(set1
, set2
);
742 if (is_max(LHS
, expr1
, expr2
)) {
743 set1
= extract_comparison(op
, expr1
, RHS
, comp
);
744 set2
= extract_comparison(op
, expr2
, RHS
, comp
);
745 return isl_set_intersect(set1
, set2
);
749 lhs
= extract_affine(LHS
);
750 rhs
= extract_affine(RHS
);
754 cond
= isl_pw_aff_lt_set(lhs
, rhs
);
757 cond
= isl_pw_aff_le_set(lhs
, rhs
);
760 cond
= isl_pw_aff_eq_set(lhs
, rhs
);
763 cond
= isl_pw_aff_ne_set(lhs
, rhs
);
766 isl_pw_aff_free(lhs
);
767 isl_pw_aff_free(rhs
);
772 cond
= isl_set_coalesce(cond
);
777 __isl_give isl_set
*PetScan::extract_comparison(BinaryOperator
*comp
)
779 return extract_comparison(comp
->getOpcode(), comp
->getLHS(),
780 comp
->getRHS(), comp
);
783 /* Extract a set of values satisfying the negation (logical not)
784 * of a subexpression.
786 __isl_give isl_set
*PetScan::extract_boolean(UnaryOperator
*op
)
790 cond
= extract_condition(op
->getSubExpr());
792 return isl_set_complement(cond
);
795 /* Extract a set of values satisfying the union (logical or)
796 * or intersection (logical and) of two subexpressions.
798 __isl_give isl_set
*PetScan::extract_boolean(BinaryOperator
*comp
)
804 lhs
= extract_condition(comp
->getLHS());
805 rhs
= extract_condition(comp
->getRHS());
807 switch (comp
->getOpcode()) {
809 cond
= isl_set_intersect(lhs
, rhs
);
812 cond
= isl_set_union(lhs
, rhs
);
824 __isl_give isl_set
*PetScan::extract_condition(UnaryOperator
*expr
)
826 switch (expr
->getOpcode()) {
828 return extract_boolean(expr
);
835 /* Extract a set of values satisfying the condition "expr != 0".
837 __isl_give isl_set
*PetScan::extract_implicit_condition(Expr
*expr
)
839 return isl_pw_aff_non_zero_set(extract_affine(expr
));
842 /* Extract a set of values satisfying the condition expressed by "expr".
844 * If the expression doesn't look like a condition, we assume it
845 * is an affine expression and return the condition "expr != 0".
847 __isl_give isl_set
*PetScan::extract_condition(Expr
*expr
)
849 BinaryOperator
*comp
;
852 return isl_set_universe(isl_dim_set_alloc(ctx
, 0, 0));
854 if (expr
->getStmtClass() == Stmt::ParenExprClass
)
855 return extract_condition(cast
<ParenExpr
>(expr
)->getSubExpr());
857 if (expr
->getStmtClass() == Stmt::UnaryOperatorClass
)
858 return extract_condition(cast
<UnaryOperator
>(expr
));
860 if (expr
->getStmtClass() != Stmt::BinaryOperatorClass
)
861 return extract_implicit_condition(expr
);
863 comp
= cast
<BinaryOperator
>(expr
);
864 switch (comp
->getOpcode()) {
871 return extract_comparison(comp
);
874 return extract_boolean(comp
);
876 return extract_implicit_condition(expr
);
880 static enum pet_op_type
UnaryOperatorKind2pet_op_type(UnaryOperatorKind kind
)
890 static enum pet_op_type
BinaryOperatorKind2pet_op_type(BinaryOperatorKind kind
)
894 return pet_op_add_assign
;
896 return pet_op_sub_assign
;
898 return pet_op_mul_assign
;
900 return pet_op_div_assign
;
902 return pet_op_assign
;
922 /* Construct a pet_expr representing a unary operator expression.
924 struct pet_expr
*PetScan::extract_expr(UnaryOperator
*expr
)
926 struct pet_expr
*arg
;
929 op
= UnaryOperatorKind2pet_op_type(expr
->getOpcode());
930 if (op
== pet_op_last
) {
935 arg
= extract_expr(expr
->getSubExpr());
937 return pet_expr_new_unary(ctx
, op
, arg
);
940 /* Construct a pet_expr representing a binary operator expression.
942 * If the top level operator is an assignment and the LHS is an access,
943 * then we mark that access as a write. If the operator is a compound
944 * assignment, the access is marked as both a read and a write.
946 * If "expr" assigns something to a scalar variable, then we keep track
947 * of the assigned expression in assigned_value so that we can plug
948 * it in when we later come across the same variable.
950 struct pet_expr
*PetScan::extract_expr(BinaryOperator
*expr
)
952 struct pet_expr
*lhs
, *rhs
;
955 op
= BinaryOperatorKind2pet_op_type(expr
->getOpcode());
956 if (op
== pet_op_last
) {
961 lhs
= extract_expr(expr
->getLHS());
962 rhs
= extract_expr(expr
->getRHS());
964 if (expr
->isAssignmentOp() && lhs
&& lhs
->type
== pet_expr_access
) {
966 if (!expr
->isCompoundAssignmentOp())
970 if (expr
->getOpcode() == BO_Assign
&&
971 lhs
&& lhs
->type
== pet_expr_access
&&
972 isl_map_dim(lhs
->acc
.access
, isl_dim_out
) == 0) {
973 isl_id
*id
= isl_map_get_tuple_id(lhs
->acc
.access
, isl_dim_out
);
974 ValueDecl
*decl
= (ValueDecl
*) isl_id_get_user(id
);
975 assigned_value
[decl
] = expr
->getRHS();
979 return pet_expr_new_binary(ctx
, op
, lhs
, rhs
);
982 /* Construct a pet_expr representing a conditional operation.
984 struct pet_expr
*PetScan::extract_expr(ConditionalOperator
*expr
)
986 struct pet_expr
*cond
, *lhs
, *rhs
;
988 cond
= extract_expr(expr
->getCond());
989 lhs
= extract_expr(expr
->getTrueExpr());
990 rhs
= extract_expr(expr
->getFalseExpr());
992 return pet_expr_new_ternary(ctx
, cond
, lhs
, rhs
);
995 struct pet_expr
*PetScan::extract_expr(ImplicitCastExpr
*expr
)
997 return extract_expr(expr
->getSubExpr());
1000 /* Construct a pet_expr representing a floating point value.
1002 struct pet_expr
*PetScan::extract_expr(FloatingLiteral
*expr
)
1004 return pet_expr_new_double(ctx
, expr
->getValueAsApproximateDouble());
1007 /* Extract an access relation from "expr" and then convert it into
1010 struct pet_expr
*PetScan::extract_access_expr(Expr
*expr
)
1013 struct pet_expr
*pe
;
1015 switch (expr
->getStmtClass()) {
1016 case Stmt::ArraySubscriptExprClass
:
1017 access
= extract_access(cast
<ArraySubscriptExpr
>(expr
));
1019 case Stmt::DeclRefExprClass
:
1020 access
= extract_access(cast
<DeclRefExpr
>(expr
));
1022 case Stmt::IntegerLiteralClass
:
1023 access
= extract_access(cast
<IntegerLiteral
>(expr
));
1030 pe
= pet_expr_from_access(access
);
1035 struct pet_expr
*PetScan::extract_expr(ParenExpr
*expr
)
1037 return extract_expr(expr
->getSubExpr());
1040 /* Construct a pet_expr representing a function call.
1042 * If we are passing along a pointer to an array element
1043 * or an entire row or even higher dimensional slice of an array,
1044 * then the function being called may write into the array.
1046 * We assume here that if the function is declared to take a pointer
1047 * to a const type, then the function will perform a read
1048 * and that otherwise, it will perform a write.
1050 struct pet_expr
*PetScan::extract_expr(CallExpr
*expr
)
1052 struct pet_expr
*res
= NULL
;
1056 fd
= expr
->getDirectCallee();
1062 name
= fd
->getDeclName().getAsString();
1063 res
= pet_expr_new_call(ctx
, name
.c_str(), expr
->getNumArgs());
1067 for (int i
= 0; i
< expr
->getNumArgs(); ++i
) {
1068 Expr
*arg
= expr
->getArg(i
);
1071 if (arg
->getStmtClass() == Stmt::ImplicitCastExprClass
) {
1072 ImplicitCastExpr
*ice
= cast
<ImplicitCastExpr
>(arg
);
1073 arg
= ice
->getSubExpr();
1075 if (arg
->getStmtClass() == Stmt::UnaryOperatorClass
) {
1076 UnaryOperator
*op
= cast
<UnaryOperator
>(arg
);
1077 if (op
->getOpcode() == UO_AddrOf
) {
1079 arg
= op
->getSubExpr();
1082 res
->args
[i
] = PetScan::extract_expr(arg
);
1085 if (arg
->getStmtClass() == Stmt::ArraySubscriptExprClass
&&
1086 array_depth(arg
->getType().getTypePtr()) > 0)
1088 if (is_addr
&& res
->args
[i
]->type
== pet_expr_access
) {
1089 ParmVarDecl
*parm
= fd
->getParamDecl(i
);
1090 if (!const_base(parm
->getType())) {
1091 res
->args
[i
]->acc
.write
= 1;
1092 res
->args
[i
]->acc
.read
= 0;
1103 /* Try and onstruct a pet_expr representing "expr".
1105 struct pet_expr
*PetScan::extract_expr(Expr
*expr
)
1107 switch (expr
->getStmtClass()) {
1108 case Stmt::UnaryOperatorClass
:
1109 return extract_expr(cast
<UnaryOperator
>(expr
));
1110 case Stmt::CompoundAssignOperatorClass
:
1111 case Stmt::BinaryOperatorClass
:
1112 return extract_expr(cast
<BinaryOperator
>(expr
));
1113 case Stmt::ImplicitCastExprClass
:
1114 return extract_expr(cast
<ImplicitCastExpr
>(expr
));
1115 case Stmt::ArraySubscriptExprClass
:
1116 case Stmt::DeclRefExprClass
:
1117 case Stmt::IntegerLiteralClass
:
1118 return extract_access_expr(expr
);
1119 case Stmt::FloatingLiteralClass
:
1120 return extract_expr(cast
<FloatingLiteral
>(expr
));
1121 case Stmt::ParenExprClass
:
1122 return extract_expr(cast
<ParenExpr
>(expr
));
1123 case Stmt::ConditionalOperatorClass
:
1124 return extract_expr(cast
<ConditionalOperator
>(expr
));
1125 case Stmt::CallExprClass
:
1126 return extract_expr(cast
<CallExpr
>(expr
));
1133 /* Extract the initialization part of a for loop.
1134 * The initialization is required to be an assignment.
1135 * Return this assignment operator.
1137 BinaryOperator
*PetScan::extract_initialization(ForStmt
*stmt
)
1139 Stmt
*init
= stmt
->getInit();
1140 BinaryOperator
*ass
;
1147 if (init
->getStmtClass() != Stmt::BinaryOperatorClass
) {
1152 ass
= cast
<BinaryOperator
>(init
);
1153 if (ass
->getOpcode() != BO_Assign
) {
1161 /* Given the assignment operator in the initialization of a for loop,
1162 * extract the induction variable, i.e., the (integer)variable being
1165 ValueDecl
*PetScan::extract_induction_variable(BinaryOperator
*init
)
1172 lhs
= init
->getLHS();
1173 if (lhs
->getStmtClass() != Stmt::DeclRefExprClass
) {
1178 ref
= cast
<DeclRefExpr
>(lhs
);
1179 decl
= ref
->getDecl();
1180 type
= decl
->getType().getTypePtr();
1182 if (!type
->isIntegerType()) {
1190 /* Check that op is of the form iv++ or iv--.
1191 * "inc" is accordingly set to 1 or -1.
1193 bool PetScan::check_unary_increment(UnaryOperator
*op
, clang::ValueDecl
*iv
,
1199 if (!op
->isIncrementDecrementOp()) {
1204 if (op
->isIncrementOp())
1205 isl_int_set_si(inc
, 1);
1207 isl_int_set_si(inc
, -1);
1209 sub
= op
->getSubExpr();
1210 if (sub
->getStmtClass() != Stmt::DeclRefExprClass
) {
1215 ref
= cast
<DeclRefExpr
>(sub
);
1216 if (ref
->getDecl() != iv
) {
1224 /* If the isl_pw_aff on which isl_pw_aff_foreach_piece is called
1225 * has a single constant expression on a universe domain, then
1226 * put this constant in *user.
1228 static int extract_cst(__isl_take isl_set
*set
, __isl_take isl_aff
*aff
,
1231 isl_int
*inc
= (isl_int
*)user
;
1234 if (!isl_set_plain_is_universe(set
) || !isl_aff_is_cst(aff
))
1237 isl_aff_get_constant(aff
, inc
);
1245 /* Check if op is of the form
1249 * with inc a constant and set "inc" accordingly.
1251 * We extract an affine expression from the RHS and the subtract iv.
1252 * The result should be a constant.
1254 bool PetScan::check_binary_increment(BinaryOperator
*op
, clang::ValueDecl
*iv
,
1264 if (op
->getOpcode() != BO_Assign
) {
1270 if (lhs
->getStmtClass() != Stmt::DeclRefExprClass
) {
1275 ref
= cast
<DeclRefExpr
>(lhs
);
1276 if (ref
->getDecl() != iv
) {
1281 val
= extract_affine(op
->getRHS());
1283 id
= isl_id_alloc(ctx
, iv
->getName().str().c_str(), iv
);
1285 dim
= isl_dim_set_alloc(ctx
, 1, 0);
1286 dim
= isl_dim_set_dim_id(dim
, isl_dim_param
, 0, id
);
1287 aff
= isl_aff_zero(isl_local_space_from_dim(dim
));
1288 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_param
, 0, 1);
1290 val
= isl_pw_aff_sub(val
, isl_pw_aff_from_aff(aff
));
1292 if (isl_pw_aff_foreach_piece(val
, &extract_cst
, &inc
) < 0) {
1293 isl_pw_aff_free(val
);
1298 isl_pw_aff_free(val
);
1303 /* Check that op is of the form iv += cst or iv -= cst.
1304 * "inc" is set to cst or -cst accordingly.
1306 bool PetScan::check_compound_increment(CompoundAssignOperator
*op
,
1307 clang::ValueDecl
*iv
, isl_int
&inc
)
1313 BinaryOperatorKind opcode
;
1315 opcode
= op
->getOpcode();
1316 if (opcode
!= BO_AddAssign
&& opcode
!= BO_SubAssign
) {
1320 if (opcode
== BO_SubAssign
)
1324 if (lhs
->getStmtClass() != Stmt::DeclRefExprClass
) {
1329 ref
= cast
<DeclRefExpr
>(lhs
);
1330 if (ref
->getDecl() != iv
) {
1337 if (rhs
->getStmtClass() == Stmt::UnaryOperatorClass
) {
1338 UnaryOperator
*op
= cast
<UnaryOperator
>(rhs
);
1339 if (op
->getOpcode() != UO_Minus
) {
1346 rhs
= op
->getSubExpr();
1349 if (rhs
->getStmtClass() != Stmt::IntegerLiteralClass
) {
1354 extract_int(cast
<IntegerLiteral
>(rhs
), &inc
);
1356 isl_int_neg(inc
, inc
);
1361 /* Check that the increment of the given for loop increments
1362 * (or decrements) the induction variable "iv".
1363 * "up" is set to true if the induction variable is incremented.
1365 bool PetScan::check_increment(ForStmt
*stmt
, ValueDecl
*iv
, isl_int
&v
)
1367 Stmt
*inc
= stmt
->getInc();
1374 if (inc
->getStmtClass() == Stmt::UnaryOperatorClass
)
1375 return check_unary_increment(cast
<UnaryOperator
>(inc
), iv
, v
);
1376 if (inc
->getStmtClass() == Stmt::CompoundAssignOperatorClass
)
1377 return check_compound_increment(
1378 cast
<CompoundAssignOperator
>(inc
), iv
, v
);
1379 if (inc
->getStmtClass() == Stmt::BinaryOperatorClass
)
1380 return check_binary_increment(cast
<BinaryOperator
>(inc
), iv
, v
);
1386 /* Embed the given iteration domain in an extra outer loop
1387 * with induction variable "var".
1388 * If this variable appeared as a parameter in the constraints,
1389 * it is replaced by the new outermost dimension.
1391 static __isl_give isl_set
*embed(__isl_take isl_set
*set
,
1392 __isl_take isl_id
*var
)
1396 set
= isl_set_insert(set
, isl_dim_set
, 0, 1);
1397 pos
= isl_set_find_dim_by_id(set
, isl_dim_param
, var
);
1399 set
= isl_set_equate(set
, isl_dim_param
, pos
, isl_dim_set
, 0);
1400 set
= isl_set_project_out(set
, isl_dim_param
, pos
, 1);
1407 /* Construct a pet_scop for an infinite loop, i.e., a loop of the form
1412 * We extract a pet_scop for the body and then embed it in a loop with
1421 struct pet_scop
*PetScan::extract_infinite_for(ForStmt
*stmt
)
1427 struct pet_scop
*scop
;
1429 scop
= extract(stmt
->getBody());
1433 id
= isl_id_alloc(ctx
, "t", NULL
);
1434 domain
= isl_set_nat_universe(isl_dim_set_alloc(ctx
, 0, 1));
1435 domain
= isl_set_set_dim_id(domain
, isl_dim_set
, 0, isl_id_copy(id
));
1436 dim
= isl_dim_from_domain(isl_set_get_dim(domain
));
1437 dim
= isl_dim_add(dim
, isl_dim_out
, 1);
1438 sched
= isl_map_universe(dim
);
1439 sched
= isl_map_equate(sched
, isl_dim_in
, 0, isl_dim_out
, 0);
1440 scop
= pet_scop_embed(scop
, domain
, sched
, id
);
1445 /* Check whether "cond" expresses a simple loop bound
1446 * on the only set dimension.
1447 * In particular, if "up" is set then "cond" should contain only
1448 * upper bounds on the set dimension.
1449 * Otherwise, it should contain only lower bounds.
1451 static bool is_simple_bound(__isl_keep isl_set
*cond
, isl_int inc
)
1453 if (isl_int_is_pos(inc
))
1454 return !isl_set_dim_has_lower_bound(cond
, isl_dim_set
, 0);
1456 return !isl_set_dim_has_upper_bound(cond
, isl_dim_set
, 0);
1459 /* Extend a condition on a given iteration of a loop to one that
1460 * imposes the same condition on all previous iterations.
1461 * "domain" expresses the lower [upper] bound on the iterations
1462 * when up is set [not set].
1464 * In particular, we construct the condition (when up is set)
1466 * forall i' : (domain(i') and i' <= i) => cond(i')
1468 * which is equivalent to
1470 * not exists i' : domain(i') and i' <= i and not cond(i')
1472 * We construct this set by negating cond, applying a map
1474 * { [i'] -> [i] : domain(i') and i' <= i }
1476 * and then negating the result again.
1478 static __isl_give isl_set
*valid_for_each_iteration(__isl_take isl_set
*cond
,
1479 __isl_take isl_set
*domain
, isl_int inc
)
1481 isl_map
*previous_to_this
;
1483 if (isl_int_is_pos(inc
))
1484 previous_to_this
= isl_map_lex_le(isl_set_get_dim(domain
));
1486 previous_to_this
= isl_map_lex_ge(isl_set_get_dim(domain
));
1488 previous_to_this
= isl_map_intersect_domain(previous_to_this
, domain
);
1490 cond
= isl_set_complement(cond
);
1491 cond
= isl_set_apply(cond
, previous_to_this
);
1492 cond
= isl_set_complement(cond
);
1497 /* Construct a domain of the form
1499 * [id] -> { [] : exists a: id = init + a * inc and a >= 0 }
1501 static __isl_give isl_set
*strided_domain(__isl_take isl_id
*id
,
1502 __isl_take isl_pw_aff
*init
, isl_int inc
)
1508 init
= isl_pw_aff_insert_dims(init
, isl_dim_set
, 0, 1);
1509 aff
= isl_aff_zero(isl_local_space_from_dim(isl_pw_aff_get_dim(init
)));
1510 aff
= isl_aff_add_coefficient(aff
, isl_dim_set
, 0, inc
);
1511 init
= isl_pw_aff_add(init
, isl_pw_aff_from_aff(aff
));
1513 dim
= isl_dim_set_alloc(isl_pw_aff_get_ctx(init
), 1, 1);
1514 dim
= isl_dim_set_dim_id(dim
, isl_dim_param
, 0, id
);
1515 aff
= isl_aff_zero(isl_local_space_from_dim(dim
));
1516 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_param
, 0, 1);
1518 set
= isl_pw_aff_eq_set(isl_pw_aff_from_aff(aff
), init
);
1520 set
= isl_set_lower_bound_si(set
, isl_dim_set
, 0, 0);
1522 return isl_set_project_out(set
, isl_dim_set
, 0, 1);
1525 /* Construct a pet_scop for a for statement.
1526 * The for loop is required to be of the form
1528 * for (i = init; condition; ++i)
1532 * for (i = init; condition; --i)
1534 * We extract a pet_scop for the body and then embed it in a loop with
1535 * iteration domain and schedule
1537 * { [i] : i >= init and condition' }
1542 * { [i] : i <= init and condition' }
1545 * Where condition' is equal to condition if the latter is
1546 * a simple upper [lower] bound and a condition that is extended
1547 * to apply to all previous iterations otherwise.
1549 * If the stride of the loop is not 1, then "i >= init" is replaced by
1551 * (exists a: i = init + stride * a and a >= 0)
1553 * Before extracting a pet_scop from the body we remove all
1554 * assignments in assigned_value to variables that are assigned
1555 * somewhere in the body of the loop.
1557 struct pet_scop
*PetScan::extract_for(ForStmt
*stmt
)
1559 BinaryOperator
*init
;
1566 struct pet_scop
*scop
;
1567 assigned_value_cache
cache(assigned_value
);
1570 if (!stmt
->getInit() && !stmt
->getCond() && !stmt
->getInc())
1571 return extract_infinite_for(stmt
);
1573 init
= PetScan::extract_initialization(stmt
);
1576 iv
= extract_induction_variable(init
);
1581 if (!check_increment(stmt
, iv
, inc
)) {
1586 assigned_value
[iv
] = NULL
;
1587 clear_assignments
clear(assigned_value
);
1588 clear
.TraverseStmt(stmt
->getBody());
1590 id
= isl_id_alloc(ctx
, iv
->getName().str().c_str(), iv
);
1592 if (isl_int_is_one(inc
) || isl_int_is_negone(inc
))
1593 domain
= extract_comparison(isl_int_is_pos(inc
) ? BO_GE
: BO_LE
,
1594 init
->getLHS(), init
->getRHS(), init
);
1596 isl_pw_aff
*lb
= extract_affine(init
->getRHS());
1597 domain
= strided_domain(isl_id_copy(id
), lb
, inc
);
1600 cond
= extract_condition(stmt
->getCond());
1601 cond
= embed(cond
, isl_id_copy(id
));
1602 domain
= embed(domain
, isl_id_copy(id
));
1603 if (!is_simple_bound(cond
, inc
))
1604 cond
= valid_for_each_iteration(cond
,
1605 isl_set_copy(domain
), inc
);
1606 domain
= isl_set_intersect(domain
, cond
);
1607 domain
= isl_set_set_dim_id(domain
, isl_dim_set
, 0, isl_id_copy(id
));
1608 dim
= isl_dim_from_domain(isl_set_get_dim(domain
));
1609 dim
= isl_dim_add(dim
, isl_dim_out
, 1);
1610 sched
= isl_map_universe(dim
);
1611 if (isl_int_is_pos(inc
))
1612 sched
= isl_map_equate(sched
, isl_dim_in
, 0, isl_dim_out
, 0);
1614 sched
= isl_map_oppose(sched
, isl_dim_in
, 0, isl_dim_out
, 0);
1616 scop
= extract(stmt
->getBody());
1617 scop
= pet_scop_embed(scop
, domain
, sched
, id
);
1623 struct pet_scop
*PetScan::extract(CompoundStmt
*stmt
)
1625 return extract(stmt
->children());
1628 /* Look for parameters in any access relation in "expr" that
1629 * refer to non-affine constructs. In particular, these are
1630 * parameters with no name.
1632 * If there are any such parameters, then the domain of the access
1633 * relation, which is still [] at this point, is replaced by
1634 * [[] -> [t_1,...,t_n]], with n the number of these parameters
1635 * (after identifying identical non-affine constructs).
1636 * The parameters are then equated to the corresponding t dimensions
1637 * and subsequently projected out.
1638 * param2pos maps the position of the parameter to the position
1639 * of the corresponding t dimension.
1641 struct pet_expr
*PetScan::resolve_nested(struct pet_expr
*expr
)
1648 std::map
<int,int> param2pos
;
1653 for (int i
= 0; i
< expr
->n_arg
; ++i
) {
1654 expr
->args
[i
] = resolve_nested(expr
->args
[i
]);
1655 if (!expr
->args
[i
]) {
1656 pet_expr_free(expr
);
1661 if (expr
->type
!= pet_expr_access
)
1664 nparam
= isl_map_dim(expr
->acc
.access
, isl_dim_param
);
1666 for (int i
= 0; i
< nparam
; ++i
) {
1667 isl_id
*id
= isl_map_get_dim_id(expr
->acc
.access
,
1669 if (id
&& isl_id_get_user(id
) && !isl_id_get_name(id
))
1678 expr
->args
= isl_calloc_array(ctx
, struct pet_expr
*, n
);
1682 n_in
= isl_map_dim(expr
->acc
.access
, isl_dim_in
);
1683 for (int i
= 0, pos
= 0; i
< nparam
; ++i
) {
1685 isl_id
*id
= isl_map_get_dim_id(expr
->acc
.access
,
1689 if (!(id
&& isl_id_get_user(id
) && !isl_id_get_name(id
))) {
1694 nested
= (Expr
*) isl_id_get_user(id
);
1695 expr
->args
[pos
] = extract_expr(nested
);
1697 for (j
= 0; j
< pos
; ++j
)
1698 if (pet_expr_is_equal(expr
->args
[j
], expr
->args
[pos
]))
1702 pet_expr_free(expr
->args
[pos
]);
1703 param2pos
[i
] = n_in
+ j
;
1706 param2pos
[i
] = n_in
+ pos
++;
1712 dim
= isl_map_get_dim(expr
->acc
.access
);
1713 dim
= isl_dim_domain(dim
);
1714 dim
= isl_dim_from_domain(dim
);
1715 dim
= isl_dim_add(dim
, isl_dim_out
, n
);
1716 map
= isl_map_universe(dim
);
1717 map
= isl_map_domain_map(map
);
1718 map
= isl_map_reverse(map
);
1719 expr
->acc
.access
= isl_map_apply_domain(expr
->acc
.access
, map
);
1721 for (int i
= nparam
- 1; i
>= 0; --i
) {
1722 isl_id
*id
= isl_map_get_dim_id(expr
->acc
.access
,
1724 if (!(id
&& isl_id_get_user(id
) && !isl_id_get_name(id
))) {
1729 expr
->acc
.access
= isl_map_equate(expr
->acc
.access
,
1730 isl_dim_param
, i
, isl_dim_in
,
1732 expr
->acc
.access
= isl_map_project_out(expr
->acc
.access
,
1733 isl_dim_param
, i
, 1);
1740 pet_expr_free(expr
);
1744 /* Convert a top-level pet_expr to a pet_scop with one statement.
1745 * This mainly involves resolving nested expression parameters
1746 * and setting the name of the iteration space.
1748 struct pet_scop
*PetScan::extract(Stmt
*stmt
, struct pet_expr
*expr
)
1750 struct pet_stmt
*ps
;
1751 SourceLocation loc
= stmt
->getLocStart();
1752 int line
= PP
.getSourceManager().getExpansionLineNumber(loc
);
1754 expr
= resolve_nested(expr
);
1755 ps
= pet_stmt_from_pet_expr(ctx
, line
, n_stmt
++, expr
);
1756 return pet_scop_from_pet_stmt(ctx
, ps
);
1759 /* Check whether "expr" is an affine expression.
1760 * We turn on autodetection so that we won't generate any warnings
1761 * and turn off nesting, so that we won't accept any non-affine constructs.
1763 bool PetScan::is_affine(Expr
*expr
)
1766 int save_autodetect
= autodetect
;
1767 bool save_nesting
= nesting_enabled
;
1770 nesting_enabled
= false;
1772 pwaff
= extract_affine(expr
);
1773 isl_pw_aff_free(pwaff
);
1775 autodetect
= save_autodetect
;
1776 nesting_enabled
= save_nesting
;
1778 return pwaff
!= NULL
;
1781 /* Check whether "expr" is an affine constraint.
1782 * We turn on autodetection so that we won't generate any warnings
1783 * and turn off nesting, so that we won't accept any non-affine constructs.
1785 bool PetScan::is_affine_condition(Expr
*expr
)
1788 int save_autodetect
= autodetect
;
1789 bool save_nesting
= nesting_enabled
;
1792 nesting_enabled
= false;
1794 set
= extract_condition(expr
);
1797 autodetect
= save_autodetect
;
1798 nesting_enabled
= save_nesting
;
1803 /* If the top-level expression of "stmt" is an assignment, then
1804 * return that assignment as a BinaryOperator.
1805 * Otherwise return NULL.
1807 static BinaryOperator
*top_assignment_or_null(Stmt
*stmt
)
1809 BinaryOperator
*ass
;
1813 if (stmt
->getStmtClass() != Stmt::BinaryOperatorClass
)
1816 ass
= cast
<BinaryOperator
>(stmt
);
1817 if(ass
->getOpcode() != BO_Assign
)
1823 /* Check if the given if statement is a conditional assignement
1824 * with a non-affine condition. If so, construct a pet_scop
1825 * corresponding to this conditional assignment. Otherwise return NULL.
1827 * In particular we check if "stmt" is of the form
1834 * where a is some array or scalar access.
1835 * The constructed pet_scop then corresponds to the expression
1837 * a = condition ? f(...) : g(...)
1839 * All access relations in f(...) are intersected with condition
1840 * while all access relation in g(...) are intersected with the complement.
1842 struct pet_scop
*PetScan::extract_conditional_assignment(IfStmt
*stmt
)
1844 BinaryOperator
*ass_then
, *ass_else
;
1845 isl_map
*write_then
, *write_else
;
1846 isl_set
*cond
, *comp
;
1847 isl_map
*map
, *map_true
, *map_false
;
1849 struct pet_expr
*pe_cond
, *pe_then
, *pe_else
, *pe
, *pe_write
;
1850 bool save_nesting
= nesting_enabled
;
1852 ass_then
= top_assignment_or_null(stmt
->getThen());
1853 ass_else
= top_assignment_or_null(stmt
->getElse());
1855 if (!ass_then
|| !ass_else
)
1858 if (is_affine_condition(stmt
->getCond()))
1861 write_then
= extract_access(ass_then
->getLHS());
1862 write_else
= extract_access(ass_else
->getLHS());
1864 equal
= isl_map_is_equal(write_then
, write_else
);
1865 isl_map_free(write_else
);
1866 if (equal
< 0 || !equal
) {
1867 isl_map_free(write_then
);
1871 nesting_enabled
= allow_nested
;
1872 cond
= extract_condition(stmt
->getCond());
1873 nesting_enabled
= save_nesting
;
1874 comp
= isl_set_complement(isl_set_copy(cond
));
1875 map_true
= isl_map_from_domain(isl_set_copy(cond
));
1876 map_true
= isl_map_add_dims(map_true
, isl_dim_out
, 1);
1877 map_true
= isl_map_fix_si(map_true
, isl_dim_out
, 0, 1);
1878 map_false
= isl_map_from_domain(isl_set_copy(comp
));
1879 map_false
= isl_map_add_dims(map_false
, isl_dim_out
, 1);
1880 map_false
= isl_map_fix_si(map_false
, isl_dim_out
, 0, 0);
1881 map
= isl_map_union_disjoint(map_true
, map_false
);
1883 pe_cond
= pet_expr_from_access(map
);
1885 pe_then
= extract_expr(ass_then
->getRHS());
1886 pe_then
= pet_expr_restrict(pe_then
, cond
);
1887 pe_else
= extract_expr(ass_else
->getRHS());
1888 pe_else
= pet_expr_restrict(pe_else
, comp
);
1890 pe
= pet_expr_new_ternary(ctx
, pe_cond
, pe_then
, pe_else
);
1891 pe_write
= pet_expr_from_access(write_then
);
1893 pe_write
->acc
.write
= 1;
1894 pe_write
->acc
.read
= 0;
1896 pe
= pet_expr_new_binary(ctx
, pet_op_assign
, pe_write
, pe
);
1897 return extract(stmt
, pe
);
1900 /* Construct a pet_scop for an if statement.
1902 struct pet_scop
*PetScan::extract(IfStmt
*stmt
)
1905 struct pet_scop
*scop_then
, *scop_else
, *scop
;
1906 assigned_value_cache
cache(assigned_value
);
1908 scop
= extract_conditional_assignment(stmt
);
1912 scop_then
= extract(stmt
->getThen());
1914 if (stmt
->getElse()) {
1915 scop_else
= extract(stmt
->getElse());
1917 if (scop_then
&& !scop_else
) {
1921 if (!scop_then
&& scop_else
) {
1928 cond
= extract_condition(stmt
->getCond());
1929 scop
= pet_scop_restrict(scop_then
, isl_set_copy(cond
));
1931 if (stmt
->getElse()) {
1932 cond
= isl_set_complement(cond
);
1933 scop_else
= pet_scop_restrict(scop_else
, cond
);
1934 scop
= pet_scop_add(ctx
, scop
, scop_else
);
1941 /* Try and construct a pet_scop corresponding to "stmt".
1943 struct pet_scop
*PetScan::extract(Stmt
*stmt
)
1945 if (isa
<Expr
>(stmt
))
1946 return extract(stmt
, extract_expr(cast
<Expr
>(stmt
)));
1948 switch (stmt
->getStmtClass()) {
1949 case Stmt::ForStmtClass
:
1950 return extract_for(cast
<ForStmt
>(stmt
));
1951 case Stmt::IfStmtClass
:
1952 return extract(cast
<IfStmt
>(stmt
));
1953 case Stmt::CompoundStmtClass
:
1954 return extract(cast
<CompoundStmt
>(stmt
));
1962 /* Try and construct a pet_scop corresponding to (part of)
1963 * a sequence of statements.
1965 struct pet_scop
*PetScan::extract(StmtRange stmt_range
)
1970 bool partial_range
= false;
1975 scop
= pet_scop_empty(ctx
);
1976 for (i
= stmt_range
.first
, j
= 0; i
!= stmt_range
.second
; ++i
, ++j
) {
1978 struct pet_scop
*scop_i
;
1979 scop_i
= extract(child
);
1980 if (scop
&& partial
) {
1981 pet_scop_free(scop_i
);
1984 scop_i
= pet_scop_prefix(scop_i
, j
);
1988 partial_range
= true;
1991 scop
= pet_scop_add(ctx
, scop
, scop_i
);
1995 scop
= pet_scop_add(ctx
, scop
, scop_i
);
2001 if (scop
&& partial_range
)
2007 /* Check if the scop marked by the user is exactly this Stmt
2008 * or part of this Stmt.
2009 * If so, return a pet_scop corresponding to the marked region.
2010 * Otherwise, return NULL.
2012 struct pet_scop
*PetScan::scan(Stmt
*stmt
)
2014 SourceManager
&SM
= PP
.getSourceManager();
2015 unsigned start_off
, end_off
;
2017 start_off
= SM
.getFileOffset(stmt
->getLocStart());
2018 end_off
= SM
.getFileOffset(stmt
->getLocEnd());
2020 if (start_off
> loc
.end
)
2022 if (end_off
< loc
.start
)
2024 if (start_off
>= loc
.start
&& end_off
<= loc
.end
) {
2025 return extract(stmt
);
2029 for (start
= stmt
->child_begin(); start
!= stmt
->child_end(); ++start
) {
2030 Stmt
*child
= *start
;
2031 start_off
= SM
.getFileOffset(child
->getLocStart());
2032 end_off
= SM
.getFileOffset(child
->getLocEnd());
2033 if (start_off
< loc
.start
&& end_off
> loc
.end
)
2035 if (start_off
>= loc
.start
)
2040 for (end
= start
; end
!= stmt
->child_end(); ++end
) {
2042 start_off
= SM
.getFileOffset(child
->getLocStart());
2043 if (start_off
>= loc
.end
)
2047 return extract(StmtRange(start
, end
));
2050 /* Set the size of index "pos" of "array" to "size".
2051 * In particular, add a constraint of the form
2055 * to array->extent and a constraint of the form
2059 * to array->context.
2061 static struct pet_array
*update_size(struct pet_array
*array
, int pos
,
2062 __isl_take isl_pw_aff
*size
)
2072 valid
= isl_pw_aff_nonneg_set(isl_pw_aff_copy(size
));
2073 array
->context
= isl_set_intersect(array
->context
, valid
);
2075 dim
= isl_set_get_dim(array
->extent
);
2076 aff
= isl_aff_zero(isl_local_space_from_dim(dim
));
2077 aff
= isl_aff_add_coefficient_si(aff
, isl_dim_set
, pos
, 1);
2078 univ
= isl_set_universe(isl_aff_get_dim(aff
));
2079 index
= isl_pw_aff_alloc(univ
, aff
);
2081 size
= isl_pw_aff_add_dims(size
, isl_dim_set
,
2082 isl_set_dim(array
->extent
, isl_dim_set
));
2083 id
= isl_set_get_tuple_id(array
->extent
);
2084 size
= isl_pw_aff_set_tuple_id(size
, id
);
2085 bound
= isl_pw_aff_lt_set(index
, size
);
2087 array
->extent
= isl_set_intersect(array
->extent
, bound
);
2089 if (!array
->context
|| !array
->extent
)
2094 pet_array_free(array
);
2098 /* Figure out the size of the array at position "pos" and all
2099 * subsequent positions from "type" and update "array" accordingly.
2101 struct pet_array
*PetScan::set_upper_bounds(struct pet_array
*array
,
2102 const Type
*type
, int pos
)
2104 const ArrayType
*atype
;
2107 if (type
->isPointerType()) {
2108 type
= type
->getPointeeType().getTypePtr();
2109 return set_upper_bounds(array
, type
, pos
+ 1);
2111 if (!type
->isArrayType())
2114 type
= type
->getCanonicalTypeInternal().getTypePtr();
2115 atype
= cast
<ArrayType
>(type
);
2117 if (type
->isConstantArrayType()) {
2118 const ConstantArrayType
*ca
= cast
<ConstantArrayType
>(atype
);
2119 size
= extract_affine(ca
->getSize());
2120 array
= update_size(array
, pos
, size
);
2121 } else if (type
->isVariableArrayType()) {
2122 const VariableArrayType
*vla
= cast
<VariableArrayType
>(atype
);
2123 size
= extract_affine(vla
->getSizeExpr());
2124 array
= update_size(array
, pos
, size
);
2127 type
= atype
->getElementType().getTypePtr();
2129 return set_upper_bounds(array
, type
, pos
+ 1);
2132 /* Construct and return a pet_array corresponding to the variable "decl".
2133 * In particular, initialize array->extent to
2135 * { name[i_1,...,i_d] : i_1,...,i_d >= 0 }
2137 * and then call set_upper_bounds to set the upper bounds on the indices
2138 * based on the type of the variable.
2140 struct pet_array
*PetScan::extract_array(isl_ctx
*ctx
, ValueDecl
*decl
)
2142 struct pet_array
*array
;
2143 QualType qt
= decl
->getType();
2144 const Type
*type
= qt
.getTypePtr();
2145 int depth
= array_depth(type
);
2146 QualType base
= base_type(qt
);
2151 array
= isl_calloc_type(ctx
, struct pet_array
);
2155 id
= isl_id_alloc(ctx
, decl
->getName().str().c_str(), decl
);
2156 dim
= isl_dim_set_alloc(ctx
, 0, depth
);
2157 dim
= isl_dim_set_tuple_id(dim
, isl_dim_set
, id
);
2159 array
->extent
= isl_set_nat_universe(dim
);
2161 dim
= isl_dim_set_alloc(ctx
, 0, 0);
2162 array
->context
= isl_set_universe(dim
);
2164 array
= set_upper_bounds(array
, type
, 0);
2168 name
= base
.getAsString();
2169 array
->element_type
= strdup(name
.c_str());
2174 /* Construct a list of pet_arrays, one for each array (or scalar)
2175 * accessed inside "scop" add this list to "scop" and return the result.
2177 * The context of "scop" is updated with the intesection of
2178 * the contexts of all arrays, i.e., constraints on the parameters
2179 * that ensure that the arrays have a valid (non-negative) size.
2181 struct pet_scop
*PetScan::scan_arrays(struct pet_scop
*scop
)
2184 set
<ValueDecl
*> arrays
;
2185 set
<ValueDecl
*>::iterator it
;
2190 pet_scop_collect_arrays(scop
, arrays
);
2192 scop
->n_array
= arrays
.size();
2193 if (scop
->n_array
== 0)
2196 scop
->arrays
= isl_calloc_array(ctx
, struct pet_array
*, scop
->n_array
);
2200 for (it
= arrays
.begin(), i
= 0; it
!= arrays
.end(); ++it
, ++i
) {
2201 struct pet_array
*array
;
2202 scop
->arrays
[i
] = array
= extract_array(ctx
, *it
);
2203 if (!scop
->arrays
[i
])
2205 scop
->context
= isl_set_intersect(scop
->context
,
2206 isl_set_copy(array
->context
));
2213 pet_scop_free(scop
);
2217 /* Construct a pet_scop from the given function.
2219 struct pet_scop
*PetScan::scan(FunctionDecl
*fd
)
2224 stmt
= fd
->getBody();
2227 scop
= extract(stmt
);
2230 scop
= pet_scop_detect_parameter_accesses(scop
);
2231 scop
= scan_arrays(scop
);