PetScan::set_upper_bounds: gracefully handle errors
[pet.git] / scan.cc
blobcfa4add7ce88800fdb3f7302fd8a13e6a8065872
1 #include <set>
2 #include <map>
3 #include <iostream>
4 #include <clang/AST/ASTDiagnostic.h>
5 #include <clang/AST/Expr.h>
6 #include <clang/AST/RecursiveASTVisitor.h>
8 #include <isl/id.h>
9 #include <isl/space.h>
10 #include <isl/aff.h>
11 #include <isl/set.h>
13 #include "scan.h"
14 #include "scop.h"
15 #include "scop_plus.h"
17 #include "config.h"
19 using namespace std;
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) {
35 Expr *lhs;
36 DeclRefExpr *ref;
37 ValueDecl *decl;
39 if (!expr->isAssignmentOp())
40 return true;
41 lhs = expr->getLHS();
42 if (lhs->getStmtClass() != Stmt::DeclRefExprClass)
43 return true;
44 ref = cast<DeclRefExpr>(lhs);
45 decl = ref->getDecl();
46 assigned_value[decl] = NULL;
47 return true;
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();
66 ++it) {
67 if (!it->second ||
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)
83 if (autodetect)
84 return;
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();
99 if (is_signed) {
100 int64_t i = expr->getValue().getSExtValue();
101 isl_int_set_si(*v, i);
102 } else {
103 uint64_t i = expr->getValue().getZExtValue();
104 isl_int_set_ui(*v, i);
107 return 0;
110 /* Extract an affine expression from the IntegerLiteral "expr".
112 __isl_give isl_pw_aff *PetScan::extract_affine(IntegerLiteral *expr)
114 isl_space *dim = isl_space_set_alloc(ctx, 0, 0);
115 isl_local_space *ls = isl_local_space_from_space(isl_space_copy(dim));
116 isl_aff *aff = isl_aff_zero_on_domain(ls);
117 isl_set *dom = isl_set_universe(dim);
118 isl_int v;
120 isl_int_init(v);
121 extract_int(expr, &v);
122 aff = isl_aff_add_constant(aff, v);
123 isl_int_clear(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_space *dim = isl_space_set_alloc(ctx, 0, 0);
133 isl_local_space *ls = isl_local_space_from_space(isl_space_copy(dim));
134 isl_aff *aff = isl_aff_zero_on_domain(ls);
135 isl_set *dom = isl_set_universe(dim);
136 isl_int v;
138 isl_int_init(v);
139 isl_int_set_ui(v, val.getZExtValue());
140 aff = isl_aff_add_constant(aff, v);
141 isl_int_clear(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();
164 isl_id *id;
165 isl_space *dim;
166 isl_aff *aff;
167 isl_set *dom;
169 if (!type->isIntegerType()) {
170 unsupported(expr);
171 return NULL;
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]);
178 else
179 return non_affine(expr);
182 id = isl_id_alloc(ctx, decl->getName().str().c_str(), decl);
183 dim = isl_space_set_alloc(ctx, 1, 0);
185 dim = isl_space_set_dim_id(dim, isl_dim_param, 0, id);
187 dom = isl_set_universe(isl_space_copy(dim));
188 aff = isl_aff_zero_on_domain(isl_local_space_from_space(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)
203 Expr *rhs_expr;
204 isl_pw_aff *lhs, *lhs_f, *lhs_c;
205 isl_pw_aff *res;
206 isl_int v;
207 isl_set *cond;
209 rhs_expr = expr->getRHS();
210 if (rhs_expr->getStmtClass() != Stmt::IntegerLiteralClass) {
211 unsupported(expr);
212 return NULL;
215 lhs = extract_affine(expr->getLHS());
216 cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(lhs));
218 isl_int_init(v);
219 extract_int(cast<IntegerLiteral>(rhs_expr), &v);
220 lhs = isl_pw_aff_scale_down(lhs, v);
221 isl_int_clear(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);
227 return res;
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)
239 Expr *rhs_expr;
240 isl_pw_aff *lhs, *lhs_f, *lhs_c;
241 isl_pw_aff *res;
242 isl_int v;
243 isl_set *cond;
245 rhs_expr = expr->getRHS();
246 if (rhs_expr->getStmtClass() != Stmt::IntegerLiteralClass) {
247 unsupported(expr);
248 return NULL;
251 lhs = extract_affine(expr->getLHS());
252 cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(lhs));
254 isl_int_init(v);
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);
263 isl_int_clear(v);
265 res = isl_pw_aff_sub(lhs, res);
267 return 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)
276 isl_pw_aff *lhs;
277 isl_pw_aff *rhs;
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);
285 unsupported(expr);
286 return NULL;
289 return isl_pw_aff_mul(lhs, rhs);
292 /* Extract an affine expression from an addition or subtraction operation.
294 __isl_give isl_pw_aff *PetScan::extract_affine_add(BinaryOperator *expr)
296 isl_pw_aff *lhs;
297 isl_pw_aff *rhs;
299 lhs = extract_affine(expr->getLHS());
300 rhs = extract_affine(expr->getRHS());
302 switch (expr->getOpcode()) {
303 case BO_Add:
304 return isl_pw_aff_add(lhs, rhs);
305 case BO_Sub:
306 return isl_pw_aff_sub(lhs, rhs);
307 default:
308 isl_pw_aff_free(lhs);
309 isl_pw_aff_free(rhs);
310 return NULL;
315 /* Compute
317 * pwaff mod 2^width
319 static __isl_give isl_pw_aff *wrap(__isl_take isl_pw_aff *pwaff,
320 unsigned width)
322 isl_int mod;
324 isl_int_init(mod);
325 isl_int_set_si(mod, 1);
326 isl_int_mul_2exp(mod, mod, width);
328 pwaff = isl_pw_aff_mod(pwaff, mod);
330 isl_int_clear(mod);
332 return pwaff;
335 /* Extract an affine expression from some binary operations.
336 * If the result of the expression is unsigned, then we wrap it
337 * based on the size of the type.
339 __isl_give isl_pw_aff *PetScan::extract_affine(BinaryOperator *expr)
341 isl_pw_aff *res;
343 switch (expr->getOpcode()) {
344 case BO_Add:
345 case BO_Sub:
346 res = extract_affine_add(expr);
347 break;
348 case BO_Div:
349 res = extract_affine_div(expr);
350 break;
351 case BO_Rem:
352 res = extract_affine_mod(expr);
353 break;
354 case BO_Mul:
355 res = extract_affine_mul(expr);
356 break;
357 default:
358 unsupported(expr);
359 return NULL;
362 if (expr->getType()->isUnsignedIntegerType())
363 res = wrap(res, ast_context.getIntWidth(expr->getType()));
365 return res;
368 /* Extract an affine expression from a negation operation.
370 __isl_give isl_pw_aff *PetScan::extract_affine(UnaryOperator *expr)
372 if (expr->getOpcode() == UO_Minus)
373 return isl_pw_aff_neg(extract_affine(expr->getSubExpr()));
375 unsupported(expr);
376 return NULL;
379 __isl_give isl_pw_aff *PetScan::extract_affine(ParenExpr *expr)
381 return extract_affine(expr->getSubExpr());
384 /* Extract an affine expression from some special function calls.
385 * In particular, we handle "min", "max", "ceild" and "floord".
386 * In case of the latter two, the second argument needs to be
387 * a (positive) integer constant.
389 __isl_give isl_pw_aff *PetScan::extract_affine(CallExpr *expr)
391 FunctionDecl *fd;
392 string name;
393 isl_pw_aff *aff1, *aff2;
395 fd = expr->getDirectCallee();
396 if (!fd) {
397 unsupported(expr);
398 return NULL;
401 name = fd->getDeclName().getAsString();
402 if (!(expr->getNumArgs() == 2 && name == "min") &&
403 !(expr->getNumArgs() == 2 && name == "max") &&
404 !(expr->getNumArgs() == 2 && name == "floord") &&
405 !(expr->getNumArgs() == 2 && name == "ceild")) {
406 unsupported(expr);
407 return NULL;
410 if (name == "min" || name == "max") {
411 aff1 = extract_affine(expr->getArg(0));
412 aff2 = extract_affine(expr->getArg(1));
414 if (name == "min")
415 aff1 = isl_pw_aff_min(aff1, aff2);
416 else
417 aff1 = isl_pw_aff_max(aff1, aff2);
418 } else if (name == "floord" || name == "ceild") {
419 isl_int v;
420 Expr *arg2 = expr->getArg(1);
422 if (arg2->getStmtClass() != Stmt::IntegerLiteralClass) {
423 unsupported(expr);
424 return NULL;
426 aff1 = extract_affine(expr->getArg(0));
427 isl_int_init(v);
428 extract_int(cast<IntegerLiteral>(arg2), &v);
429 aff1 = isl_pw_aff_scale_down(aff1, v);
430 isl_int_clear(v);
431 if (name == "floord")
432 aff1 = isl_pw_aff_floor(aff1);
433 else
434 aff1 = isl_pw_aff_ceil(aff1);
435 } else {
436 unsupported(expr);
437 return NULL;
440 return aff1;
444 /* This method is called when we come across a non-affine expression.
445 * If nesting is allowed, we return a new parameter that corresponds
446 * to the non-affine expression. Otherwise, we simply complain.
448 * The new parameter is resolved in resolve_nested.
450 isl_pw_aff *PetScan::non_affine(Expr *expr)
452 isl_id *id;
453 isl_space *dim;
454 isl_aff *aff;
455 isl_set *dom;
457 if (!nesting_enabled) {
458 unsupported(expr);
459 return NULL;
462 id = isl_id_alloc(ctx, NULL, expr);
463 dim = isl_space_set_alloc(ctx, 1, 0);
465 dim = isl_space_set_dim_id(dim, isl_dim_param, 0, id);
467 dom = isl_set_universe(isl_space_copy(dim));
468 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
469 aff = isl_aff_add_coefficient_si(aff, isl_dim_param, 0, 1);
471 return isl_pw_aff_alloc(dom, aff);
474 /* Affine expressions are not supposed to contain array accesses,
475 * but if nesting is allowed, we return a parameter corresponding
476 * to the array access.
478 __isl_give isl_pw_aff *PetScan::extract_affine(ArraySubscriptExpr *expr)
480 return non_affine(expr);
483 /* Extract an affine expression from a conditional operation.
485 __isl_give isl_pw_aff *PetScan::extract_affine(ConditionalOperator *expr)
487 isl_set *cond;
488 isl_pw_aff *lhs, *rhs;
490 cond = extract_condition(expr->getCond());
491 lhs = extract_affine(expr->getTrueExpr());
492 rhs = extract_affine(expr->getFalseExpr());
494 return isl_pw_aff_cond(cond, lhs, rhs);
497 /* Extract an affine expression, if possible, from "expr".
498 * Otherwise return NULL.
500 __isl_give isl_pw_aff *PetScan::extract_affine(Expr *expr)
502 switch (expr->getStmtClass()) {
503 case Stmt::ImplicitCastExprClass:
504 return extract_affine(cast<ImplicitCastExpr>(expr));
505 case Stmt::IntegerLiteralClass:
506 return extract_affine(cast<IntegerLiteral>(expr));
507 case Stmt::DeclRefExprClass:
508 return extract_affine(cast<DeclRefExpr>(expr));
509 case Stmt::BinaryOperatorClass:
510 return extract_affine(cast<BinaryOperator>(expr));
511 case Stmt::UnaryOperatorClass:
512 return extract_affine(cast<UnaryOperator>(expr));
513 case Stmt::ParenExprClass:
514 return extract_affine(cast<ParenExpr>(expr));
515 case Stmt::CallExprClass:
516 return extract_affine(cast<CallExpr>(expr));
517 case Stmt::ArraySubscriptExprClass:
518 return extract_affine(cast<ArraySubscriptExpr>(expr));
519 case Stmt::ConditionalOperatorClass:
520 return extract_affine(cast<ConditionalOperator>(expr));
521 default:
522 unsupported(expr);
524 return NULL;
527 __isl_give isl_map *PetScan::extract_access(ImplicitCastExpr *expr)
529 return extract_access(expr->getSubExpr());
532 /* Return the depth of an array of the given type.
534 static int array_depth(const Type *type)
536 if (type->isPointerType())
537 return 1 + array_depth(type->getPointeeType().getTypePtr());
538 if (type->isArrayType()) {
539 const ArrayType *atype;
540 type = type->getCanonicalTypeInternal().getTypePtr();
541 atype = cast<ArrayType>(type);
542 return 1 + array_depth(atype->getElementType().getTypePtr());
544 return 0;
547 /* Return the element type of the given array type.
549 static QualType base_type(QualType qt)
551 const Type *type = qt.getTypePtr();
553 if (type->isPointerType())
554 return base_type(type->getPointeeType());
555 if (type->isArrayType()) {
556 const ArrayType *atype;
557 type = type->getCanonicalTypeInternal().getTypePtr();
558 atype = cast<ArrayType>(type);
559 return base_type(atype->getElementType());
561 return qt;
564 /* Check if the element type corresponding to the given array type
565 * has a const qualifier.
567 static bool const_base(QualType qt)
569 const Type *type = qt.getTypePtr();
571 if (type->isPointerType())
572 return const_base(type->getPointeeType());
573 if (type->isArrayType()) {
574 const ArrayType *atype;
575 type = type->getCanonicalTypeInternal().getTypePtr();
576 atype = cast<ArrayType>(type);
577 return const_base(atype->getElementType());
580 return qt.isConstQualified();
583 /* Extract an access relation from a reference to a variable.
584 * If the variable has name "A" and its type corresponds to an
585 * array of depth d, then the returned access relation is of the
586 * form
588 * { [] -> A[i_1,...,i_d] }
590 __isl_give isl_map *PetScan::extract_access(DeclRefExpr *expr)
592 ValueDecl *decl = expr->getDecl();
593 int depth = array_depth(decl->getType().getTypePtr());
594 isl_id *id = isl_id_alloc(ctx, decl->getName().str().c_str(), decl);
595 isl_space *dim = isl_space_alloc(ctx, 0, 0, depth);
596 isl_map *access_rel;
598 dim = isl_space_set_tuple_id(dim, isl_dim_out, id);
600 access_rel = isl_map_universe(dim);
602 return access_rel;
605 /* Extract an access relation from an integer contant.
606 * If the value of the constant is "v", then the returned access relation
607 * is
609 * { [] -> [v] }
611 __isl_give isl_map *PetScan::extract_access(IntegerLiteral *expr)
613 return isl_map_from_pw_aff(extract_affine(expr));
616 /* Try and extract an access relation from the given Expr.
617 * Return NULL if it doesn't work out.
619 __isl_give isl_map *PetScan::extract_access(Expr *expr)
621 switch (expr->getStmtClass()) {
622 case Stmt::ImplicitCastExprClass:
623 return extract_access(cast<ImplicitCastExpr>(expr));
624 case Stmt::DeclRefExprClass:
625 return extract_access(cast<DeclRefExpr>(expr));
626 case Stmt::ArraySubscriptExprClass:
627 return extract_access(cast<ArraySubscriptExpr>(expr));
628 default:
629 unsupported(expr);
631 return NULL;
634 /* Assign the affine expression "index" to the output dimension "pos" of "map"
635 * and return the result.
637 __isl_give isl_map *set_index(__isl_take isl_map *map, int pos,
638 __isl_take isl_pw_aff *index)
640 isl_map *index_map;
641 int len = isl_map_dim(map, isl_dim_out);
642 isl_id *id;
644 index_map = isl_map_from_pw_aff(index);
645 index_map = isl_map_insert_dims(index_map, isl_dim_out, 0, pos);
646 index_map = isl_map_add_dims(index_map, isl_dim_out, len - pos - 1);
647 id = isl_map_get_tuple_id(map, isl_dim_out);
648 index_map = isl_map_set_tuple_id(index_map, isl_dim_out, id);
650 map = isl_map_intersect(map, index_map);
652 return map;
655 /* Extract an access relation from the given array subscript expression.
656 * If nesting is allowed in general, then we turn it on while
657 * examining the index expression.
659 * We first extract an access relation from the base.
660 * This will result in an access relation with a range that corresponds
661 * to the array being accessed and with earlier indices filled in already.
662 * We then extract the current index and fill that in as well.
663 * The position of the current index is based on the type of base.
664 * If base is the actual array variable, then the depth of this type
665 * will be the same as the depth of the array and we will fill in
666 * the first array index.
667 * Otherwise, the depth of the base type will be smaller and we will fill
668 * in a later index.
670 __isl_give isl_map *PetScan::extract_access(ArraySubscriptExpr *expr)
672 Expr *base = expr->getBase();
673 Expr *idx = expr->getIdx();
674 isl_pw_aff *index;
675 isl_map *base_access;
676 isl_map *access;
677 int depth = array_depth(base->getType().getTypePtr());
678 int pos;
679 bool save_nesting = nesting_enabled;
681 nesting_enabled = allow_nested;
683 base_access = extract_access(base);
684 index = extract_affine(idx);
686 nesting_enabled = save_nesting;
688 pos = isl_map_dim(base_access, isl_dim_out) - depth;
689 access = set_index(base_access, pos, index);
691 return access;
694 /* Check if "expr" calls function "minmax" with two arguments and if so
695 * make lhs and rhs refer to these two arguments.
697 static bool is_minmax(Expr *expr, const char *minmax, Expr *&lhs, Expr *&rhs)
699 CallExpr *call;
700 FunctionDecl *fd;
701 string name;
703 if (expr->getStmtClass() != Stmt::CallExprClass)
704 return false;
706 call = cast<CallExpr>(expr);
707 fd = call->getDirectCallee();
708 if (!fd)
709 return false;
711 if (call->getNumArgs() != 2)
712 return false;
714 name = fd->getDeclName().getAsString();
715 if (name != minmax)
716 return false;
718 lhs = call->getArg(0);
719 rhs = call->getArg(1);
721 return true;
724 /* Check if "expr" is of the form min(lhs, rhs) and if so make
725 * lhs and rhs refer to the two arguments.
727 static bool is_min(Expr *expr, Expr *&lhs, Expr *&rhs)
729 return is_minmax(expr, "min", lhs, rhs);
732 /* Check if "expr" is of the form max(lhs, rhs) and if so make
733 * lhs and rhs refer to the two arguments.
735 static bool is_max(Expr *expr, Expr *&lhs, Expr *&rhs)
737 return is_minmax(expr, "max", lhs, rhs);
740 /* Extract a set of values satisfying the comparison "LHS op RHS"
741 * "comp" is the original statement that "LHS op RHS" is derived from
742 * and is used for diagnostics.
744 * If the comparison is of the form
746 * a <= min(b,c)
748 * then the set is constructed as the intersection of the set corresponding
749 * to the comparisons
751 * a <= b and a <= c
753 * A similar optimization is performed for max(a,b) <= c.
754 * We do this because that will lead to simpler representations of the set.
755 * If isl is ever enhanced to explicitly deal with min and max expressions,
756 * this optimization can be removed.
758 __isl_give isl_set *PetScan::extract_comparison(BinaryOperatorKind op,
759 Expr *LHS, Expr *RHS, Stmt *comp)
761 isl_pw_aff *lhs;
762 isl_pw_aff *rhs;
763 isl_set *cond;
765 if (op == BO_GT)
766 return extract_comparison(BO_LT, RHS, LHS, comp);
767 if (op == BO_GE)
768 return extract_comparison(BO_LE, RHS, LHS, comp);
770 if (op == BO_LT || op == BO_LE) {
771 Expr *expr1, *expr2;
772 isl_set *set1, *set2;
773 if (is_min(RHS, expr1, expr2)) {
774 set1 = extract_comparison(op, LHS, expr1, comp);
775 set2 = extract_comparison(op, LHS, expr2, comp);
776 return isl_set_intersect(set1, set2);
778 if (is_max(LHS, expr1, expr2)) {
779 set1 = extract_comparison(op, expr1, RHS, comp);
780 set2 = extract_comparison(op, expr2, RHS, comp);
781 return isl_set_intersect(set1, set2);
785 lhs = extract_affine(LHS);
786 rhs = extract_affine(RHS);
788 switch (op) {
789 case BO_LT:
790 cond = isl_pw_aff_lt_set(lhs, rhs);
791 break;
792 case BO_LE:
793 cond = isl_pw_aff_le_set(lhs, rhs);
794 break;
795 case BO_EQ:
796 cond = isl_pw_aff_eq_set(lhs, rhs);
797 break;
798 case BO_NE:
799 cond = isl_pw_aff_ne_set(lhs, rhs);
800 break;
801 default:
802 isl_pw_aff_free(lhs);
803 isl_pw_aff_free(rhs);
804 unsupported(comp);
805 return NULL;
808 cond = isl_set_coalesce(cond);
810 return cond;
813 __isl_give isl_set *PetScan::extract_comparison(BinaryOperator *comp)
815 return extract_comparison(comp->getOpcode(), comp->getLHS(),
816 comp->getRHS(), comp);
819 /* Extract a set of values satisfying the negation (logical not)
820 * of a subexpression.
822 __isl_give isl_set *PetScan::extract_boolean(UnaryOperator *op)
824 isl_set *cond;
826 cond = extract_condition(op->getSubExpr());
828 return isl_set_complement(cond);
831 /* Extract a set of values satisfying the union (logical or)
832 * or intersection (logical and) of two subexpressions.
834 __isl_give isl_set *PetScan::extract_boolean(BinaryOperator *comp)
836 isl_set *lhs;
837 isl_set *rhs;
838 isl_set *cond;
840 lhs = extract_condition(comp->getLHS());
841 rhs = extract_condition(comp->getRHS());
843 switch (comp->getOpcode()) {
844 case BO_LAnd:
845 cond = isl_set_intersect(lhs, rhs);
846 break;
847 case BO_LOr:
848 cond = isl_set_union(lhs, rhs);
849 break;
850 default:
851 isl_set_free(lhs);
852 isl_set_free(rhs);
853 unsupported(comp);
854 return NULL;
857 return cond;
860 __isl_give isl_set *PetScan::extract_condition(UnaryOperator *expr)
862 switch (expr->getOpcode()) {
863 case UO_LNot:
864 return extract_boolean(expr);
865 default:
866 unsupported(expr);
867 return NULL;
871 /* Extract a set of values satisfying the condition "expr != 0".
873 __isl_give isl_set *PetScan::extract_implicit_condition(Expr *expr)
875 return isl_pw_aff_non_zero_set(extract_affine(expr));
878 /* Extract a set of values satisfying the condition expressed by "expr".
880 * If the expression doesn't look like a condition, we assume it
881 * is an affine expression and return the condition "expr != 0".
883 __isl_give isl_set *PetScan::extract_condition(Expr *expr)
885 BinaryOperator *comp;
887 if (!expr)
888 return isl_set_universe(isl_space_set_alloc(ctx, 0, 0));
890 if (expr->getStmtClass() == Stmt::ParenExprClass)
891 return extract_condition(cast<ParenExpr>(expr)->getSubExpr());
893 if (expr->getStmtClass() == Stmt::UnaryOperatorClass)
894 return extract_condition(cast<UnaryOperator>(expr));
896 if (expr->getStmtClass() != Stmt::BinaryOperatorClass)
897 return extract_implicit_condition(expr);
899 comp = cast<BinaryOperator>(expr);
900 switch (comp->getOpcode()) {
901 case BO_LT:
902 case BO_LE:
903 case BO_GT:
904 case BO_GE:
905 case BO_EQ:
906 case BO_NE:
907 return extract_comparison(comp);
908 case BO_LAnd:
909 case BO_LOr:
910 return extract_boolean(comp);
911 default:
912 return extract_implicit_condition(expr);
916 static enum pet_op_type UnaryOperatorKind2pet_op_type(UnaryOperatorKind kind)
918 switch (kind) {
919 case UO_Minus:
920 return pet_op_minus;
921 default:
922 return pet_op_last;
926 static enum pet_op_type BinaryOperatorKind2pet_op_type(BinaryOperatorKind kind)
928 switch (kind) {
929 case BO_AddAssign:
930 return pet_op_add_assign;
931 case BO_SubAssign:
932 return pet_op_sub_assign;
933 case BO_MulAssign:
934 return pet_op_mul_assign;
935 case BO_DivAssign:
936 return pet_op_div_assign;
937 case BO_Assign:
938 return pet_op_assign;
939 case BO_Add:
940 return pet_op_add;
941 case BO_Sub:
942 return pet_op_sub;
943 case BO_Mul:
944 return pet_op_mul;
945 case BO_Div:
946 return pet_op_div;
947 case BO_EQ:
948 return pet_op_eq;
949 case BO_LE:
950 return pet_op_le;
951 case BO_LT:
952 return pet_op_lt;
953 case BO_GT:
954 return pet_op_gt;
955 default:
956 return pet_op_last;
960 /* Construct a pet_expr representing a unary operator expression.
962 struct pet_expr *PetScan::extract_expr(UnaryOperator *expr)
964 struct pet_expr *arg;
965 enum pet_op_type op;
967 op = UnaryOperatorKind2pet_op_type(expr->getOpcode());
968 if (op == pet_op_last) {
969 unsupported(expr);
970 return NULL;
973 arg = extract_expr(expr->getSubExpr());
975 return pet_expr_new_unary(ctx, op, arg);
978 /* Construct a pet_expr representing a binary operator expression.
980 * If the top level operator is an assignment and the LHS is an access,
981 * then we mark that access as a write. If the operator is a compound
982 * assignment, the access is marked as both a read and a write.
984 * If "expr" assigns something to a scalar variable, then we keep track
985 * of the assigned expression in assigned_value so that we can plug
986 * it in when we later come across the same variable.
988 struct pet_expr *PetScan::extract_expr(BinaryOperator *expr)
990 struct pet_expr *lhs, *rhs;
991 enum pet_op_type op;
993 op = BinaryOperatorKind2pet_op_type(expr->getOpcode());
994 if (op == pet_op_last) {
995 unsupported(expr);
996 return NULL;
999 lhs = extract_expr(expr->getLHS());
1000 rhs = extract_expr(expr->getRHS());
1002 if (expr->isAssignmentOp() && lhs && lhs->type == pet_expr_access) {
1003 lhs->acc.write = 1;
1004 if (!expr->isCompoundAssignmentOp())
1005 lhs->acc.read = 0;
1008 if (expr->getOpcode() == BO_Assign &&
1009 lhs && lhs->type == pet_expr_access &&
1010 isl_map_dim(lhs->acc.access, isl_dim_out) == 0) {
1011 isl_id *id = isl_map_get_tuple_id(lhs->acc.access, isl_dim_out);
1012 ValueDecl *decl = (ValueDecl *) isl_id_get_user(id);
1013 assigned_value[decl] = expr->getRHS();
1014 isl_id_free(id);
1017 return pet_expr_new_binary(ctx, op, lhs, rhs);
1020 /* Construct a pet_expr representing a conditional operation.
1022 struct pet_expr *PetScan::extract_expr(ConditionalOperator *expr)
1024 struct pet_expr *cond, *lhs, *rhs;
1026 cond = extract_expr(expr->getCond());
1027 lhs = extract_expr(expr->getTrueExpr());
1028 rhs = extract_expr(expr->getFalseExpr());
1030 return pet_expr_new_ternary(ctx, cond, lhs, rhs);
1033 struct pet_expr *PetScan::extract_expr(ImplicitCastExpr *expr)
1035 return extract_expr(expr->getSubExpr());
1038 /* Construct a pet_expr representing a floating point value.
1040 struct pet_expr *PetScan::extract_expr(FloatingLiteral *expr)
1042 return pet_expr_new_double(ctx, expr->getValueAsApproximateDouble());
1045 /* Extract an access relation from "expr" and then convert it into
1046 * a pet_expr.
1048 struct pet_expr *PetScan::extract_access_expr(Expr *expr)
1050 isl_map *access;
1051 struct pet_expr *pe;
1053 switch (expr->getStmtClass()) {
1054 case Stmt::ArraySubscriptExprClass:
1055 access = extract_access(cast<ArraySubscriptExpr>(expr));
1056 break;
1057 case Stmt::DeclRefExprClass:
1058 access = extract_access(cast<DeclRefExpr>(expr));
1059 break;
1060 case Stmt::IntegerLiteralClass:
1061 access = extract_access(cast<IntegerLiteral>(expr));
1062 break;
1063 default:
1064 unsupported(expr);
1065 return NULL;
1068 pe = pet_expr_from_access(access);
1070 return pe;
1073 struct pet_expr *PetScan::extract_expr(ParenExpr *expr)
1075 return extract_expr(expr->getSubExpr());
1078 /* Construct a pet_expr representing a function call.
1080 * If we are passing along a pointer to an array element
1081 * or an entire row or even higher dimensional slice of an array,
1082 * then the function being called may write into the array.
1084 * We assume here that if the function is declared to take a pointer
1085 * to a const type, then the function will perform a read
1086 * and that otherwise, it will perform a write.
1088 struct pet_expr *PetScan::extract_expr(CallExpr *expr)
1090 struct pet_expr *res = NULL;
1091 FunctionDecl *fd;
1092 string name;
1094 fd = expr->getDirectCallee();
1095 if (!fd) {
1096 unsupported(expr);
1097 return NULL;
1100 name = fd->getDeclName().getAsString();
1101 res = pet_expr_new_call(ctx, name.c_str(), expr->getNumArgs());
1102 if (!res)
1103 return NULL;
1105 for (int i = 0; i < expr->getNumArgs(); ++i) {
1106 Expr *arg = expr->getArg(i);
1107 int is_addr = 0;
1109 if (arg->getStmtClass() == Stmt::ImplicitCastExprClass) {
1110 ImplicitCastExpr *ice = cast<ImplicitCastExpr>(arg);
1111 arg = ice->getSubExpr();
1113 if (arg->getStmtClass() == Stmt::UnaryOperatorClass) {
1114 UnaryOperator *op = cast<UnaryOperator>(arg);
1115 if (op->getOpcode() == UO_AddrOf) {
1116 is_addr = 1;
1117 arg = op->getSubExpr();
1120 res->args[i] = PetScan::extract_expr(arg);
1121 if (!res->args[i])
1122 goto error;
1123 if (arg->getStmtClass() == Stmt::ArraySubscriptExprClass &&
1124 array_depth(arg->getType().getTypePtr()) > 0)
1125 is_addr = 1;
1126 if (is_addr && res->args[i]->type == pet_expr_access) {
1127 ParmVarDecl *parm = fd->getParamDecl(i);
1128 if (!const_base(parm->getType())) {
1129 res->args[i]->acc.write = 1;
1130 res->args[i]->acc.read = 0;
1135 return res;
1136 error:
1137 pet_expr_free(res);
1138 return NULL;
1141 /* Try and onstruct a pet_expr representing "expr".
1143 struct pet_expr *PetScan::extract_expr(Expr *expr)
1145 switch (expr->getStmtClass()) {
1146 case Stmt::UnaryOperatorClass:
1147 return extract_expr(cast<UnaryOperator>(expr));
1148 case Stmt::CompoundAssignOperatorClass:
1149 case Stmt::BinaryOperatorClass:
1150 return extract_expr(cast<BinaryOperator>(expr));
1151 case Stmt::ImplicitCastExprClass:
1152 return extract_expr(cast<ImplicitCastExpr>(expr));
1153 case Stmt::ArraySubscriptExprClass:
1154 case Stmt::DeclRefExprClass:
1155 case Stmt::IntegerLiteralClass:
1156 return extract_access_expr(expr);
1157 case Stmt::FloatingLiteralClass:
1158 return extract_expr(cast<FloatingLiteral>(expr));
1159 case Stmt::ParenExprClass:
1160 return extract_expr(cast<ParenExpr>(expr));
1161 case Stmt::ConditionalOperatorClass:
1162 return extract_expr(cast<ConditionalOperator>(expr));
1163 case Stmt::CallExprClass:
1164 return extract_expr(cast<CallExpr>(expr));
1165 default:
1166 unsupported(expr);
1168 return NULL;
1171 /* Check if the given initialization statement is an assignment.
1172 * If so, return that assignment. Otherwise return NULL.
1174 BinaryOperator *PetScan::initialization_assignment(Stmt *init)
1176 BinaryOperator *ass;
1178 if (init->getStmtClass() != Stmt::BinaryOperatorClass)
1179 return NULL;
1181 ass = cast<BinaryOperator>(init);
1182 if (ass->getOpcode() != BO_Assign)
1183 return NULL;
1185 return ass;
1188 /* Check if the given initialization statement is a declaration
1189 * of a single variable.
1190 * If so, return that declaration. Otherwise return NULL.
1192 Decl *PetScan::initialization_declaration(Stmt *init)
1194 DeclStmt *decl;
1196 if (init->getStmtClass() != Stmt::DeclStmtClass)
1197 return NULL;
1199 decl = cast<DeclStmt>(init);
1201 if (!decl->isSingleDecl())
1202 return NULL;
1204 return decl->getSingleDecl();
1207 /* Given the assignment operator in the initialization of a for loop,
1208 * extract the induction variable, i.e., the (integer)variable being
1209 * assigned.
1211 ValueDecl *PetScan::extract_induction_variable(BinaryOperator *init)
1213 Expr *lhs;
1214 DeclRefExpr *ref;
1215 ValueDecl *decl;
1216 const Type *type;
1218 lhs = init->getLHS();
1219 if (lhs->getStmtClass() != Stmt::DeclRefExprClass) {
1220 unsupported(init);
1221 return NULL;
1224 ref = cast<DeclRefExpr>(lhs);
1225 decl = ref->getDecl();
1226 type = decl->getType().getTypePtr();
1228 if (!type->isIntegerType()) {
1229 unsupported(lhs);
1230 return NULL;
1233 return decl;
1236 /* Given the initialization statement of a for loop and the single
1237 * declaration in this initialization statement,
1238 * extract the induction variable, i.e., the (integer) variable being
1239 * declared.
1241 VarDecl *PetScan::extract_induction_variable(Stmt *init, Decl *decl)
1243 VarDecl *vd;
1245 vd = cast<VarDecl>(decl);
1247 const QualType type = vd->getType();
1248 if (!type->isIntegerType()) {
1249 unsupported(init);
1250 return NULL;
1253 if (!vd->getInit()) {
1254 unsupported(init);
1255 return NULL;
1258 return vd;
1261 /* Check that op is of the form iv++ or iv--.
1262 * "inc" is accordingly set to 1 or -1.
1264 bool PetScan::check_unary_increment(UnaryOperator *op, clang::ValueDecl *iv,
1265 isl_int &inc)
1267 Expr *sub;
1268 DeclRefExpr *ref;
1270 if (!op->isIncrementDecrementOp()) {
1271 unsupported(op);
1272 return false;
1275 if (op->isIncrementOp())
1276 isl_int_set_si(inc, 1);
1277 else
1278 isl_int_set_si(inc, -1);
1280 sub = op->getSubExpr();
1281 if (sub->getStmtClass() != Stmt::DeclRefExprClass) {
1282 unsupported(op);
1283 return false;
1286 ref = cast<DeclRefExpr>(sub);
1287 if (ref->getDecl() != iv) {
1288 unsupported(op);
1289 return false;
1292 return true;
1295 /* If the isl_pw_aff on which isl_pw_aff_foreach_piece is called
1296 * has a single constant expression on a universe domain, then
1297 * put this constant in *user.
1299 static int extract_cst(__isl_take isl_set *set, __isl_take isl_aff *aff,
1300 void *user)
1302 isl_int *inc = (isl_int *)user;
1303 int res = 0;
1305 if (!isl_set_plain_is_universe(set) || !isl_aff_is_cst(aff))
1306 res = -1;
1307 else
1308 isl_aff_get_constant(aff, inc);
1310 isl_set_free(set);
1311 isl_aff_free(aff);
1313 return res;
1316 /* Check if op is of the form
1318 * iv = iv + inc
1320 * with inc a constant and set "inc" accordingly.
1322 * We extract an affine expression from the RHS and the subtract iv.
1323 * The result should be a constant.
1325 bool PetScan::check_binary_increment(BinaryOperator *op, clang::ValueDecl *iv,
1326 isl_int &inc)
1328 Expr *lhs;
1329 DeclRefExpr *ref;
1330 isl_id *id;
1331 isl_space *dim;
1332 isl_aff *aff;
1333 isl_pw_aff *val;
1335 if (op->getOpcode() != BO_Assign) {
1336 unsupported(op);
1337 return false;
1340 lhs = op->getLHS();
1341 if (lhs->getStmtClass() != Stmt::DeclRefExprClass) {
1342 unsupported(op);
1343 return false;
1346 ref = cast<DeclRefExpr>(lhs);
1347 if (ref->getDecl() != iv) {
1348 unsupported(op);
1349 return false;
1352 val = extract_affine(op->getRHS());
1354 id = isl_id_alloc(ctx, iv->getName().str().c_str(), iv);
1356 dim = isl_space_set_alloc(ctx, 1, 0);
1357 dim = isl_space_set_dim_id(dim, isl_dim_param, 0, id);
1358 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
1359 aff = isl_aff_add_coefficient_si(aff, isl_dim_param, 0, 1);
1361 val = isl_pw_aff_sub(val, isl_pw_aff_from_aff(aff));
1363 if (isl_pw_aff_foreach_piece(val, &extract_cst, &inc) < 0) {
1364 isl_pw_aff_free(val);
1365 unsupported(op);
1366 return false;
1369 isl_pw_aff_free(val);
1371 return true;
1374 /* Check that op is of the form iv += cst or iv -= cst.
1375 * "inc" is set to cst or -cst accordingly.
1377 bool PetScan::check_compound_increment(CompoundAssignOperator *op,
1378 clang::ValueDecl *iv, isl_int &inc)
1380 Expr *lhs, *rhs;
1381 DeclRefExpr *ref;
1382 bool neg = false;
1384 BinaryOperatorKind opcode;
1386 opcode = op->getOpcode();
1387 if (opcode != BO_AddAssign && opcode != BO_SubAssign) {
1388 unsupported(op);
1389 return false;
1391 if (opcode == BO_SubAssign)
1392 neg = true;
1394 lhs = op->getLHS();
1395 if (lhs->getStmtClass() != Stmt::DeclRefExprClass) {
1396 unsupported(op);
1397 return false;
1400 ref = cast<DeclRefExpr>(lhs);
1401 if (ref->getDecl() != iv) {
1402 unsupported(op);
1403 return false;
1406 rhs = op->getRHS();
1408 if (rhs->getStmtClass() == Stmt::UnaryOperatorClass) {
1409 UnaryOperator *op = cast<UnaryOperator>(rhs);
1410 if (op->getOpcode() != UO_Minus) {
1411 unsupported(op);
1412 return false;
1415 neg = !neg;
1417 rhs = op->getSubExpr();
1420 if (rhs->getStmtClass() != Stmt::IntegerLiteralClass) {
1421 unsupported(op);
1422 return false;
1425 extract_int(cast<IntegerLiteral>(rhs), &inc);
1426 if (neg)
1427 isl_int_neg(inc, inc);
1429 return true;
1432 /* Check that the increment of the given for loop increments
1433 * (or decrements) the induction variable "iv".
1434 * "up" is set to true if the induction variable is incremented.
1436 bool PetScan::check_increment(ForStmt *stmt, ValueDecl *iv, isl_int &v)
1438 Stmt *inc = stmt->getInc();
1440 if (!inc) {
1441 unsupported(stmt);
1442 return false;
1445 if (inc->getStmtClass() == Stmt::UnaryOperatorClass)
1446 return check_unary_increment(cast<UnaryOperator>(inc), iv, v);
1447 if (inc->getStmtClass() == Stmt::CompoundAssignOperatorClass)
1448 return check_compound_increment(
1449 cast<CompoundAssignOperator>(inc), iv, v);
1450 if (inc->getStmtClass() == Stmt::BinaryOperatorClass)
1451 return check_binary_increment(cast<BinaryOperator>(inc), iv, v);
1453 unsupported(inc);
1454 return false;
1457 /* Embed the given iteration domain in an extra outer loop
1458 * with induction variable "var".
1459 * If this variable appeared as a parameter in the constraints,
1460 * it is replaced by the new outermost dimension.
1462 static __isl_give isl_set *embed(__isl_take isl_set *set,
1463 __isl_take isl_id *var)
1465 int pos;
1467 set = isl_set_insert_dims(set, isl_dim_set, 0, 1);
1468 pos = isl_set_find_dim_by_id(set, isl_dim_param, var);
1469 if (pos >= 0) {
1470 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, 0);
1471 set = isl_set_project_out(set, isl_dim_param, pos, 1);
1474 isl_id_free(var);
1475 return set;
1478 /* Construct a pet_scop for an infinite loop around the given body.
1480 * We extract a pet_scop for the body and then embed it in a loop with
1481 * iteration domain
1483 * { [t] : t >= 0 }
1485 * and schedule
1487 * { [t] -> [t] }
1489 struct pet_scop *PetScan::extract_infinite_loop(Stmt *body)
1491 isl_id *id;
1492 isl_space *dim;
1493 isl_set *domain;
1494 isl_map *sched;
1495 struct pet_scop *scop;
1497 scop = extract(body);
1498 if (!scop)
1499 return NULL;
1501 id = isl_id_alloc(ctx, "t", NULL);
1502 domain = isl_set_nat_universe(isl_space_set_alloc(ctx, 0, 1));
1503 domain = isl_set_set_dim_id(domain, isl_dim_set, 0, isl_id_copy(id));
1504 dim = isl_space_from_domain(isl_set_get_space(domain));
1505 dim = isl_space_add_dims(dim, isl_dim_out, 1);
1506 sched = isl_map_universe(dim);
1507 sched = isl_map_equate(sched, isl_dim_in, 0, isl_dim_out, 0);
1508 scop = pet_scop_embed(scop, domain, sched, id);
1510 return scop;
1513 /* Construct a pet_scop for an infinite loop, i.e., a loop of the form
1515 * for (;;)
1516 * body
1519 struct pet_scop *PetScan::extract_infinite_for(ForStmt *stmt)
1521 return extract_infinite_loop(stmt->getBody());
1524 /* Check if the while loop is of the form
1526 * while (1)
1527 * body
1529 * If so, construct a scop for an infinite loop around body.
1530 * Otherwise, fail.
1532 struct pet_scop *PetScan::extract(WhileStmt *stmt)
1534 Expr *cond;
1535 isl_set *set;
1536 int is_universe;
1538 cond = stmt->getCond();
1539 if (!cond) {
1540 unsupported(stmt);
1541 return NULL;
1544 set = extract_condition(cond);
1545 is_universe = isl_set_plain_is_universe(set);
1546 isl_set_free(set);
1548 if (!is_universe) {
1549 unsupported(stmt);
1550 return NULL;
1553 return extract_infinite_loop(stmt->getBody());
1556 /* Check whether "cond" expresses a simple loop bound
1557 * on the only set dimension.
1558 * In particular, if "up" is set then "cond" should contain only
1559 * upper bounds on the set dimension.
1560 * Otherwise, it should contain only lower bounds.
1562 static bool is_simple_bound(__isl_keep isl_set *cond, isl_int inc)
1564 if (isl_int_is_pos(inc))
1565 return !isl_set_dim_has_lower_bound(cond, isl_dim_set, 0);
1566 else
1567 return !isl_set_dim_has_upper_bound(cond, isl_dim_set, 0);
1570 /* Extend a condition on a given iteration of a loop to one that
1571 * imposes the same condition on all previous iterations.
1572 * "domain" expresses the lower [upper] bound on the iterations
1573 * when up is set [not set].
1575 * In particular, we construct the condition (when up is set)
1577 * forall i' : (domain(i') and i' <= i) => cond(i')
1579 * which is equivalent to
1581 * not exists i' : domain(i') and i' <= i and not cond(i')
1583 * We construct this set by negating cond, applying a map
1585 * { [i'] -> [i] : domain(i') and i' <= i }
1587 * and then negating the result again.
1589 static __isl_give isl_set *valid_for_each_iteration(__isl_take isl_set *cond,
1590 __isl_take isl_set *domain, isl_int inc)
1592 isl_map *previous_to_this;
1594 if (isl_int_is_pos(inc))
1595 previous_to_this = isl_map_lex_le(isl_set_get_space(domain));
1596 else
1597 previous_to_this = isl_map_lex_ge(isl_set_get_space(domain));
1599 previous_to_this = isl_map_intersect_domain(previous_to_this, domain);
1601 cond = isl_set_complement(cond);
1602 cond = isl_set_apply(cond, previous_to_this);
1603 cond = isl_set_complement(cond);
1605 return cond;
1608 /* Construct a domain of the form
1610 * [id] -> { [] : exists a: id = init + a * inc and a >= 0 }
1612 static __isl_give isl_set *strided_domain(__isl_take isl_id *id,
1613 __isl_take isl_pw_aff *init, isl_int inc)
1615 isl_aff *aff;
1616 isl_space *dim;
1617 isl_set *set;
1619 init = isl_pw_aff_insert_dims(init, isl_dim_in, 0, 1);
1620 dim = isl_pw_aff_get_domain_space(init);
1621 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
1622 aff = isl_aff_add_coefficient(aff, isl_dim_in, 0, inc);
1623 init = isl_pw_aff_add(init, isl_pw_aff_from_aff(aff));
1625 dim = isl_space_set_alloc(isl_pw_aff_get_ctx(init), 1, 1);
1626 dim = isl_space_set_dim_id(dim, isl_dim_param, 0, id);
1627 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
1628 aff = isl_aff_add_coefficient_si(aff, isl_dim_param, 0, 1);
1630 set = isl_pw_aff_eq_set(isl_pw_aff_from_aff(aff), init);
1632 set = isl_set_lower_bound_si(set, isl_dim_set, 0, 0);
1634 return isl_set_project_out(set, isl_dim_set, 0, 1);
1637 static unsigned get_type_size(ValueDecl *decl)
1639 return decl->getASTContext().getIntWidth(decl->getType());
1642 /* Assuming "cond" represents a simple bound on a loop where the loop
1643 * iterator "iv" is incremented (or decremented) by one, check if wrapping
1644 * is possible.
1646 * Under the given assumptions, wrapping is only possible if "cond" allows
1647 * for the last value before wrapping, i.e., 2^width - 1 in case of an
1648 * increasing iterator and 0 in case of a decreasing iterator.
1650 static bool can_wrap(__isl_keep isl_set *cond, ValueDecl *iv, isl_int inc)
1652 bool cw;
1653 isl_int limit;
1654 isl_set *test;
1656 test = isl_set_copy(cond);
1658 isl_int_init(limit);
1659 if (isl_int_is_neg(inc))
1660 isl_int_set_si(limit, 0);
1661 else {
1662 isl_int_set_si(limit, 1);
1663 isl_int_mul_2exp(limit, limit, get_type_size(iv));
1664 isl_int_sub_ui(limit, limit, 1);
1667 test = isl_set_fix(cond, isl_dim_set, 0, limit);
1668 cw = !isl_set_is_empty(test);
1669 isl_set_free(test);
1671 isl_int_clear(limit);
1673 return cw;
1676 /* Given a one-dimensional space, construct the following mapping on this
1677 * space
1679 * { [v] -> [v mod 2^width] }
1681 * where width is the number of bits used to represent the values
1682 * of the unsigned variable "iv".
1684 static __isl_give isl_map *compute_wrapping(__isl_take isl_space *dim,
1685 ValueDecl *iv)
1687 isl_int mod;
1688 isl_aff *aff;
1689 isl_map *map;
1691 isl_int_init(mod);
1692 isl_int_set_si(mod, 1);
1693 isl_int_mul_2exp(mod, mod, get_type_size(iv));
1695 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
1696 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
1697 aff = isl_aff_mod(aff, mod);
1699 isl_int_clear(mod);
1701 return isl_map_from_basic_map(isl_basic_map_from_aff(aff));
1702 map = isl_map_reverse(map);
1705 /* Construct a pet_scop for a for statement.
1706 * The for loop is required to be of the form
1708 * for (i = init; condition; ++i)
1710 * or
1712 * for (i = init; condition; --i)
1714 * The initialization of the for loop should either be an assignment
1715 * to an integer variable, or a declaration of such a variable with
1716 * initialization.
1718 * We extract a pet_scop for the body and then embed it in a loop with
1719 * iteration domain and schedule
1721 * { [i] : i >= init and condition' }
1722 * { [i] -> [i] }
1724 * or
1726 * { [i] : i <= init and condition' }
1727 * { [i] -> [-i] }
1729 * Where condition' is equal to condition if the latter is
1730 * a simple upper [lower] bound and a condition that is extended
1731 * to apply to all previous iterations otherwise.
1733 * If the stride of the loop is not 1, then "i >= init" is replaced by
1735 * (exists a: i = init + stride * a and a >= 0)
1737 * If the loop iterator i is unsigned, then wrapping may occur.
1738 * During the computation, we work with a virtual iterator that
1739 * does not wrap. However, the condition in the code applies
1740 * to the wrapped value, so we need to change condition(i)
1741 * into condition([i % 2^width]).
1742 * After computing the virtual domain and schedule, we apply
1743 * the function { [v] -> [v % 2^width] } to the domain and the domain
1744 * of the schedule. In order not to lose any information, we also
1745 * need to intersect the domain of the schedule with the virtual domain
1746 * first, since some iterations in the wrapped domain may be scheduled
1747 * several times, typically an infinite number of times.
1748 * Note that there is no need to perform this final wrapping
1749 * if the loop condition (after wrapping) is simple.
1751 * Wrapping on unsigned iterators can be avoided entirely if
1752 * loop condition is simple, the loop iterator is incremented
1753 * [decremented] by one and the last value before wrapping cannot
1754 * possibly satisfy the loop condition.
1756 * Before extracting a pet_scop from the body we remove all
1757 * assignments in assigned_value to variables that are assigned
1758 * somewhere in the body of the loop.
1760 struct pet_scop *PetScan::extract_for(ForStmt *stmt)
1762 BinaryOperator *ass;
1763 Decl *decl;
1764 Stmt *init;
1765 Expr *lhs, *rhs;
1766 ValueDecl *iv;
1767 isl_space *dim;
1768 isl_set *domain;
1769 isl_map *sched;
1770 isl_set *cond;
1771 isl_id *id;
1772 struct pet_scop *scop;
1773 assigned_value_cache cache(assigned_value);
1774 isl_int inc;
1775 bool is_one;
1776 bool is_unsigned;
1777 bool is_simple;
1778 isl_map *wrap = NULL;
1780 if (!stmt->getInit() && !stmt->getCond() && !stmt->getInc())
1781 return extract_infinite_for(stmt);
1783 init = stmt->getInit();
1784 if (!init) {
1785 unsupported(stmt);
1786 return NULL;
1788 if ((ass = initialization_assignment(init)) != NULL) {
1789 iv = extract_induction_variable(ass);
1790 if (!iv)
1791 return NULL;
1792 lhs = ass->getLHS();
1793 rhs = ass->getRHS();
1794 } else if ((decl = initialization_declaration(init)) != NULL) {
1795 VarDecl *var = extract_induction_variable(init, decl);
1796 if (!var)
1797 return NULL;
1798 iv = var;
1799 rhs = var->getInit();
1800 lhs = DeclRefExpr::Create(iv->getASTContext(),
1801 var->getQualifierLoc(), iv, var->getInnerLocStart(),
1802 var->getType(), VK_LValue);
1803 } else {
1804 unsupported(stmt->getInit());
1805 return NULL;
1808 isl_int_init(inc);
1809 if (!check_increment(stmt, iv, inc)) {
1810 isl_int_clear(inc);
1811 return NULL;
1814 is_unsigned = iv->getType()->isUnsignedIntegerType();
1816 assigned_value[iv] = NULL;
1817 clear_assignments clear(assigned_value);
1818 clear.TraverseStmt(stmt->getBody());
1820 id = isl_id_alloc(ctx, iv->getName().str().c_str(), iv);
1822 is_one = isl_int_is_one(inc) || isl_int_is_negone(inc);
1823 if (is_one)
1824 domain = extract_comparison(isl_int_is_pos(inc) ? BO_GE : BO_LE,
1825 lhs, rhs, init);
1826 else {
1827 isl_pw_aff *lb = extract_affine(rhs);
1828 domain = strided_domain(isl_id_copy(id), lb, inc);
1831 cond = extract_condition(stmt->getCond());
1832 cond = embed(cond, isl_id_copy(id));
1833 domain = embed(domain, isl_id_copy(id));
1834 is_simple = is_simple_bound(cond, inc);
1835 if (is_unsigned &&
1836 (!is_simple || !is_one || can_wrap(cond, iv, inc))) {
1837 wrap = compute_wrapping(isl_set_get_space(cond), iv);
1838 cond = isl_set_apply(cond, isl_map_reverse(isl_map_copy(wrap)));
1839 is_simple = is_simple && is_simple_bound(cond, inc);
1841 if (!is_simple)
1842 cond = valid_for_each_iteration(cond,
1843 isl_set_copy(domain), inc);
1844 domain = isl_set_intersect(domain, cond);
1845 domain = isl_set_set_dim_id(domain, isl_dim_set, 0, isl_id_copy(id));
1846 dim = isl_space_from_domain(isl_set_get_space(domain));
1847 dim = isl_space_add_dims(dim, isl_dim_out, 1);
1848 sched = isl_map_universe(dim);
1849 if (isl_int_is_pos(inc))
1850 sched = isl_map_equate(sched, isl_dim_in, 0, isl_dim_out, 0);
1851 else
1852 sched = isl_map_oppose(sched, isl_dim_in, 0, isl_dim_out, 0);
1854 if (is_unsigned && !is_simple) {
1855 wrap = isl_map_set_dim_id(wrap,
1856 isl_dim_out, 0, isl_id_copy(id));
1857 sched = isl_map_intersect_domain(sched, isl_set_copy(domain));
1858 domain = isl_set_apply(domain, isl_map_copy(wrap));
1859 sched = isl_map_apply_domain(sched, wrap);
1860 } else
1861 isl_map_free(wrap);
1863 scop = extract(stmt->getBody());
1864 scop = pet_scop_embed(scop, domain, sched, id);
1866 isl_int_clear(inc);
1867 return scop;
1870 struct pet_scop *PetScan::extract(CompoundStmt *stmt)
1872 return extract(stmt->children());
1875 /* Look for parameters in any access relation in "expr" that
1876 * refer to non-affine constructs. In particular, these are
1877 * parameters with no name.
1879 * If there are any such parameters, then the domain of the access
1880 * relation, which is still [] at this point, is replaced by
1881 * [[] -> [t_1,...,t_n]], with n the number of these parameters
1882 * (after identifying identical non-affine constructs).
1883 * The parameters are then equated to the corresponding t dimensions
1884 * and subsequently projected out.
1885 * param2pos maps the position of the parameter to the position
1886 * of the corresponding t dimension.
1888 struct pet_expr *PetScan::resolve_nested(struct pet_expr *expr)
1890 int n;
1891 int nparam;
1892 int n_in;
1893 isl_space *dim;
1894 isl_map *map;
1895 std::map<int,int> param2pos;
1897 if (!expr)
1898 return expr;
1900 for (int i = 0; i < expr->n_arg; ++i) {
1901 expr->args[i] = resolve_nested(expr->args[i]);
1902 if (!expr->args[i]) {
1903 pet_expr_free(expr);
1904 return NULL;
1908 if (expr->type != pet_expr_access)
1909 return expr;
1911 nparam = isl_map_dim(expr->acc.access, isl_dim_param);
1912 n = 0;
1913 for (int i = 0; i < nparam; ++i) {
1914 isl_id *id = isl_map_get_dim_id(expr->acc.access,
1915 isl_dim_param, i);
1916 if (id && isl_id_get_user(id) && !isl_id_get_name(id))
1917 n++;
1918 isl_id_free(id);
1921 if (n == 0)
1922 return expr;
1924 expr->n_arg = n;
1925 expr->args = isl_calloc_array(ctx, struct pet_expr *, n);
1926 if (!expr->args)
1927 goto error;
1929 n_in = isl_map_dim(expr->acc.access, isl_dim_in);
1930 for (int i = 0, pos = 0; i < nparam; ++i) {
1931 int j;
1932 isl_id *id = isl_map_get_dim_id(expr->acc.access,
1933 isl_dim_param, i);
1934 Expr *nested;
1936 if (!(id && isl_id_get_user(id) && !isl_id_get_name(id))) {
1937 isl_id_free(id);
1938 continue;
1941 nested = (Expr *) isl_id_get_user(id);
1942 expr->args[pos] = extract_expr(nested);
1944 for (j = 0; j < pos; ++j)
1945 if (pet_expr_is_equal(expr->args[j], expr->args[pos]))
1946 break;
1948 if (j < pos) {
1949 pet_expr_free(expr->args[pos]);
1950 param2pos[i] = n_in + j;
1951 n--;
1952 } else
1953 param2pos[i] = n_in + pos++;
1955 isl_id_free(id);
1957 expr->n_arg = n;
1959 dim = isl_map_get_space(expr->acc.access);
1960 dim = isl_space_domain(dim);
1961 dim = isl_space_from_domain(dim);
1962 dim = isl_space_add_dims(dim, isl_dim_out, n);
1963 map = isl_map_universe(dim);
1964 map = isl_map_domain_map(map);
1965 map = isl_map_reverse(map);
1966 expr->acc.access = isl_map_apply_domain(expr->acc.access, map);
1968 for (int i = nparam - 1; i >= 0; --i) {
1969 isl_id *id = isl_map_get_dim_id(expr->acc.access,
1970 isl_dim_param, i);
1971 if (!(id && isl_id_get_user(id) && !isl_id_get_name(id))) {
1972 isl_id_free(id);
1973 continue;
1976 expr->acc.access = isl_map_equate(expr->acc.access,
1977 isl_dim_param, i, isl_dim_in,
1978 param2pos[i]);
1979 expr->acc.access = isl_map_project_out(expr->acc.access,
1980 isl_dim_param, i, 1);
1982 isl_id_free(id);
1985 return expr;
1986 error:
1987 pet_expr_free(expr);
1988 return NULL;
1991 /* Convert a top-level pet_expr to a pet_scop with one statement.
1992 * This mainly involves resolving nested expression parameters
1993 * and setting the name of the iteration space.
1995 struct pet_scop *PetScan::extract(Stmt *stmt, struct pet_expr *expr)
1997 struct pet_stmt *ps;
1998 SourceLocation loc = stmt->getLocStart();
1999 int line = PP.getSourceManager().getExpansionLineNumber(loc);
2001 expr = resolve_nested(expr);
2002 ps = pet_stmt_from_pet_expr(ctx, line, n_stmt++, expr);
2003 return pet_scop_from_pet_stmt(ctx, ps);
2006 /* Check whether "expr" is an affine expression.
2007 * We turn on autodetection so that we won't generate any warnings
2008 * and turn off nesting, so that we won't accept any non-affine constructs.
2010 bool PetScan::is_affine(Expr *expr)
2012 isl_pw_aff *pwaff;
2013 int save_autodetect = autodetect;
2014 bool save_nesting = nesting_enabled;
2016 autodetect = 1;
2017 nesting_enabled = false;
2019 pwaff = extract_affine(expr);
2020 isl_pw_aff_free(pwaff);
2022 autodetect = save_autodetect;
2023 nesting_enabled = save_nesting;
2025 return pwaff != NULL;
2028 /* Check whether "expr" is an affine constraint.
2029 * We turn on autodetection so that we won't generate any warnings
2030 * and turn off nesting, so that we won't accept any non-affine constructs.
2032 bool PetScan::is_affine_condition(Expr *expr)
2034 isl_set *set;
2035 int save_autodetect = autodetect;
2036 bool save_nesting = nesting_enabled;
2038 autodetect = 1;
2039 nesting_enabled = false;
2041 set = extract_condition(expr);
2042 isl_set_free(set);
2044 autodetect = save_autodetect;
2045 nesting_enabled = save_nesting;
2047 return set != NULL;
2050 /* If the top-level expression of "stmt" is an assignment, then
2051 * return that assignment as a BinaryOperator.
2052 * Otherwise return NULL.
2054 static BinaryOperator *top_assignment_or_null(Stmt *stmt)
2056 BinaryOperator *ass;
2058 if (!stmt)
2059 return NULL;
2060 if (stmt->getStmtClass() != Stmt::BinaryOperatorClass)
2061 return NULL;
2063 ass = cast<BinaryOperator>(stmt);
2064 if(ass->getOpcode() != BO_Assign)
2065 return NULL;
2067 return ass;
2070 /* Check if the given if statement is a conditional assignement
2071 * with a non-affine condition. If so, construct a pet_scop
2072 * corresponding to this conditional assignment. Otherwise return NULL.
2074 * In particular we check if "stmt" is of the form
2076 * if (condition)
2077 * a = f(...);
2078 * else
2079 * a = g(...);
2081 * where a is some array or scalar access.
2082 * The constructed pet_scop then corresponds to the expression
2084 * a = condition ? f(...) : g(...)
2086 * All access relations in f(...) are intersected with condition
2087 * while all access relation in g(...) are intersected with the complement.
2089 struct pet_scop *PetScan::extract_conditional_assignment(IfStmt *stmt)
2091 BinaryOperator *ass_then, *ass_else;
2092 isl_map *write_then, *write_else;
2093 isl_set *cond, *comp;
2094 isl_map *map, *map_true, *map_false;
2095 int equal;
2096 struct pet_expr *pe_cond, *pe_then, *pe_else, *pe, *pe_write;
2097 bool save_nesting = nesting_enabled;
2099 ass_then = top_assignment_or_null(stmt->getThen());
2100 ass_else = top_assignment_or_null(stmt->getElse());
2102 if (!ass_then || !ass_else)
2103 return NULL;
2105 if (is_affine_condition(stmt->getCond()))
2106 return NULL;
2108 write_then = extract_access(ass_then->getLHS());
2109 write_else = extract_access(ass_else->getLHS());
2111 equal = isl_map_is_equal(write_then, write_else);
2112 isl_map_free(write_else);
2113 if (equal < 0 || !equal) {
2114 isl_map_free(write_then);
2115 return NULL;
2118 nesting_enabled = allow_nested;
2119 cond = extract_condition(stmt->getCond());
2120 nesting_enabled = save_nesting;
2121 comp = isl_set_complement(isl_set_copy(cond));
2122 map_true = isl_map_from_domain(isl_set_copy(cond));
2123 map_true = isl_map_add_dims(map_true, isl_dim_out, 1);
2124 map_true = isl_map_fix_si(map_true, isl_dim_out, 0, 1);
2125 map_false = isl_map_from_domain(isl_set_copy(comp));
2126 map_false = isl_map_add_dims(map_false, isl_dim_out, 1);
2127 map_false = isl_map_fix_si(map_false, isl_dim_out, 0, 0);
2128 map = isl_map_union_disjoint(map_true, map_false);
2130 pe_cond = pet_expr_from_access(map);
2132 pe_then = extract_expr(ass_then->getRHS());
2133 pe_then = pet_expr_restrict(pe_then, cond);
2134 pe_else = extract_expr(ass_else->getRHS());
2135 pe_else = pet_expr_restrict(pe_else, comp);
2137 pe = pet_expr_new_ternary(ctx, pe_cond, pe_then, pe_else);
2138 pe_write = pet_expr_from_access(write_then);
2139 if (pe_write) {
2140 pe_write->acc.write = 1;
2141 pe_write->acc.read = 0;
2143 pe = pet_expr_new_binary(ctx, pet_op_assign, pe_write, pe);
2144 return extract(stmt, pe);
2147 /* Construct a pet_scop for an if statement.
2149 struct pet_scop *PetScan::extract(IfStmt *stmt)
2151 isl_set *cond;
2152 struct pet_scop *scop_then, *scop_else, *scop;
2153 assigned_value_cache cache(assigned_value);
2155 scop = extract_conditional_assignment(stmt);
2156 if (scop)
2157 return scop;
2159 scop_then = extract(stmt->getThen());
2161 if (stmt->getElse()) {
2162 scop_else = extract(stmt->getElse());
2163 if (autodetect) {
2164 if (scop_then && !scop_else) {
2165 partial = true;
2166 return scop_then;
2168 if (!scop_then && scop_else) {
2169 partial = true;
2170 return scop_else;
2175 cond = extract_condition(stmt->getCond());
2176 scop = pet_scop_restrict(scop_then, isl_set_copy(cond));
2178 if (stmt->getElse()) {
2179 cond = isl_set_complement(cond);
2180 scop_else = pet_scop_restrict(scop_else, cond);
2181 scop = pet_scop_add(ctx, scop, scop_else);
2182 } else
2183 isl_set_free(cond);
2185 return scop;
2188 /* Try and construct a pet_scop corresponding to "stmt".
2190 struct pet_scop *PetScan::extract(Stmt *stmt)
2192 if (isa<Expr>(stmt))
2193 return extract(stmt, extract_expr(cast<Expr>(stmt)));
2195 switch (stmt->getStmtClass()) {
2196 case Stmt::WhileStmtClass:
2197 return extract(cast<WhileStmt>(stmt));
2198 case Stmt::ForStmtClass:
2199 return extract_for(cast<ForStmt>(stmt));
2200 case Stmt::IfStmtClass:
2201 return extract(cast<IfStmt>(stmt));
2202 case Stmt::CompoundStmtClass:
2203 return extract(cast<CompoundStmt>(stmt));
2204 default:
2205 unsupported(stmt);
2208 return NULL;
2211 /* Try and construct a pet_scop corresponding to (part of)
2212 * a sequence of statements.
2214 struct pet_scop *PetScan::extract(StmtRange stmt_range)
2216 pet_scop *scop;
2217 StmtIterator i;
2218 int j;
2219 bool partial_range = false;
2221 scop = pet_scop_empty(ctx);
2222 for (i = stmt_range.first, j = 0; i != stmt_range.second; ++i, ++j) {
2223 Stmt *child = *i;
2224 struct pet_scop *scop_i;
2225 scop_i = extract(child);
2226 if (scop && partial) {
2227 pet_scop_free(scop_i);
2228 break;
2230 scop_i = pet_scop_prefix(scop_i, j);
2231 if (autodetect) {
2232 if (scop_i)
2233 scop = pet_scop_add(ctx, scop, scop_i);
2234 else
2235 partial_range = true;
2236 if (scop->n_stmt != 0 && !scop_i)
2237 partial = true;
2238 } else {
2239 scop = pet_scop_add(ctx, scop, scop_i);
2241 if (partial)
2242 break;
2245 if (scop && partial_range)
2246 partial = true;
2248 return scop;
2251 /* Check if the scop marked by the user is exactly this Stmt
2252 * or part of this Stmt.
2253 * If so, return a pet_scop corresponding to the marked region.
2254 * Otherwise, return NULL.
2256 struct pet_scop *PetScan::scan(Stmt *stmt)
2258 SourceManager &SM = PP.getSourceManager();
2259 unsigned start_off, end_off;
2261 start_off = SM.getFileOffset(stmt->getLocStart());
2262 end_off = SM.getFileOffset(stmt->getLocEnd());
2264 if (start_off > loc.end)
2265 return NULL;
2266 if (end_off < loc.start)
2267 return NULL;
2268 if (start_off >= loc.start && end_off <= loc.end) {
2269 return extract(stmt);
2272 StmtIterator start;
2273 for (start = stmt->child_begin(); start != stmt->child_end(); ++start) {
2274 Stmt *child = *start;
2275 start_off = SM.getFileOffset(child->getLocStart());
2276 end_off = SM.getFileOffset(child->getLocEnd());
2277 if (start_off < loc.start && end_off > loc.end)
2278 return scan(child);
2279 if (start_off >= loc.start)
2280 break;
2283 StmtIterator end;
2284 for (end = start; end != stmt->child_end(); ++end) {
2285 Stmt *child = *end;
2286 start_off = SM.getFileOffset(child->getLocStart());
2287 if (start_off >= loc.end)
2288 break;
2291 return extract(StmtRange(start, end));
2294 /* Set the size of index "pos" of "array" to "size".
2295 * In particular, add a constraint of the form
2297 * i_pos < size
2299 * to array->extent and a constraint of the form
2301 * size >= 0
2303 * to array->context.
2305 static struct pet_array *update_size(struct pet_array *array, int pos,
2306 __isl_take isl_pw_aff *size)
2308 isl_set *valid;
2309 isl_set *univ;
2310 isl_set *bound;
2311 isl_space *dim;
2312 isl_aff *aff;
2313 isl_pw_aff *index;
2314 isl_id *id;
2316 valid = isl_pw_aff_nonneg_set(isl_pw_aff_copy(size));
2317 array->context = isl_set_intersect(array->context, valid);
2319 dim = isl_set_get_space(array->extent);
2320 aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
2321 aff = isl_aff_add_coefficient_si(aff, isl_dim_in, pos, 1);
2322 univ = isl_set_universe(isl_aff_get_domain_space(aff));
2323 index = isl_pw_aff_alloc(univ, aff);
2325 size = isl_pw_aff_add_dims(size, isl_dim_in,
2326 isl_set_dim(array->extent, isl_dim_set));
2327 id = isl_set_get_tuple_id(array->extent);
2328 size = isl_pw_aff_set_tuple_id(size, id);
2329 bound = isl_pw_aff_lt_set(index, size);
2331 array->extent = isl_set_intersect(array->extent, bound);
2333 if (!array->context || !array->extent)
2334 goto error;
2336 return array;
2337 error:
2338 pet_array_free(array);
2339 return NULL;
2342 /* Figure out the size of the array at position "pos" and all
2343 * subsequent positions from "type" and update "array" accordingly.
2345 struct pet_array *PetScan::set_upper_bounds(struct pet_array *array,
2346 const Type *type, int pos)
2348 const ArrayType *atype;
2349 isl_pw_aff *size;
2351 if (!array)
2352 return NULL;
2354 if (type->isPointerType()) {
2355 type = type->getPointeeType().getTypePtr();
2356 return set_upper_bounds(array, type, pos + 1);
2358 if (!type->isArrayType())
2359 return array;
2361 type = type->getCanonicalTypeInternal().getTypePtr();
2362 atype = cast<ArrayType>(type);
2364 if (type->isConstantArrayType()) {
2365 const ConstantArrayType *ca = cast<ConstantArrayType>(atype);
2366 size = extract_affine(ca->getSize());
2367 array = update_size(array, pos, size);
2368 } else if (type->isVariableArrayType()) {
2369 const VariableArrayType *vla = cast<VariableArrayType>(atype);
2370 size = extract_affine(vla->getSizeExpr());
2371 array = update_size(array, pos, size);
2374 type = atype->getElementType().getTypePtr();
2376 return set_upper_bounds(array, type, pos + 1);
2379 /* Construct and return a pet_array corresponding to the variable "decl".
2380 * In particular, initialize array->extent to
2382 * { name[i_1,...,i_d] : i_1,...,i_d >= 0 }
2384 * and then call set_upper_bounds to set the upper bounds on the indices
2385 * based on the type of the variable.
2387 struct pet_array *PetScan::extract_array(isl_ctx *ctx, ValueDecl *decl)
2389 struct pet_array *array;
2390 QualType qt = decl->getType();
2391 const Type *type = qt.getTypePtr();
2392 int depth = array_depth(type);
2393 QualType base = base_type(qt);
2394 string name;
2395 isl_id *id;
2396 isl_space *dim;
2398 array = isl_calloc_type(ctx, struct pet_array);
2399 if (!array)
2400 return NULL;
2402 id = isl_id_alloc(ctx, decl->getName().str().c_str(), decl);
2403 dim = isl_space_set_alloc(ctx, 0, depth);
2404 dim = isl_space_set_tuple_id(dim, isl_dim_set, id);
2406 array->extent = isl_set_nat_universe(dim);
2408 dim = isl_space_params_alloc(ctx, 0);
2409 array->context = isl_set_universe(dim);
2411 array = set_upper_bounds(array, type, 0);
2412 if (!array)
2413 return NULL;
2415 name = base.getAsString();
2416 array->element_type = strdup(name.c_str());
2418 return array;
2421 /* Construct a list of pet_arrays, one for each array (or scalar)
2422 * accessed inside "scop" add this list to "scop" and return the result.
2424 * The context of "scop" is updated with the intesection of
2425 * the contexts of all arrays, i.e., constraints on the parameters
2426 * that ensure that the arrays have a valid (non-negative) size.
2428 struct pet_scop *PetScan::scan_arrays(struct pet_scop *scop)
2430 int i;
2431 set<ValueDecl *> arrays;
2432 set<ValueDecl *>::iterator it;
2434 if (!scop)
2435 return NULL;
2437 pet_scop_collect_arrays(scop, arrays);
2439 scop->n_array = arrays.size();
2440 if (scop->n_array == 0)
2441 return scop;
2443 scop->arrays = isl_calloc_array(ctx, struct pet_array *, scop->n_array);
2444 if (!scop->arrays)
2445 goto error;
2447 for (it = arrays.begin(), i = 0; it != arrays.end(); ++it, ++i) {
2448 struct pet_array *array;
2449 scop->arrays[i] = array = extract_array(ctx, *it);
2450 if (!scop->arrays[i])
2451 goto error;
2452 scop->context = isl_set_intersect(scop->context,
2453 isl_set_copy(array->context));
2454 if (!scop->context)
2455 goto error;
2458 return scop;
2459 error:
2460 pet_scop_free(scop);
2461 return NULL;
2464 /* Construct a pet_scop from the given function.
2466 struct pet_scop *PetScan::scan(FunctionDecl *fd)
2468 pet_scop *scop;
2469 Stmt *stmt;
2471 stmt = fd->getBody();
2473 if (autodetect)
2474 scop = extract(stmt);
2475 else
2476 scop = scan(stmt);
2477 scop = pet_scop_detect_parameter_accesses(scop);
2478 scop = scan_arrays(scop);
2480 return scop;