allow loop increments of the form i = i + cst
[pet.git] / scan.cc
blobdc9f630fe023d1bada1d8a370ed8b3a867ffd34f
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/dim.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_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);
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_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);
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_dim *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_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)
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 some binary operations.
294 __isl_give isl_pw_aff *PetScan::extract_affine(BinaryOperator *expr)
296 isl_pw_aff *lhs;
297 isl_pw_aff *rhs;
298 isl_pw_aff *res;
300 switch (expr->getOpcode()) {
301 case BO_Add:
302 case BO_Sub:
303 break;
304 case BO_Div:
305 return extract_affine_div(expr);
306 case BO_Rem:
307 return extract_affine_mod(expr);
308 case BO_Mul:
309 return extract_affine_mul(expr);
310 default:
311 unsupported(expr);
312 return NULL;
315 lhs = extract_affine(expr->getLHS());
316 rhs = extract_affine(expr->getRHS());
318 switch (expr->getOpcode()) {
319 case BO_Add:
320 res = isl_pw_aff_add(lhs, rhs);
321 break;
322 case BO_Sub:
323 res = isl_pw_aff_sub(lhs, rhs);
324 break;
325 default:
329 return res;
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()));
339 unsupported(expr);
340 return NULL;
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)
355 FunctionDecl *fd;
356 string name;
357 isl_pw_aff *aff1, *aff2;
359 fd = expr->getDirectCallee();
360 if (!fd) {
361 unsupported(expr);
362 return NULL;
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")) {
370 unsupported(expr);
371 return NULL;
374 if (name == "min" || name == "max") {
375 aff1 = extract_affine(expr->getArg(0));
376 aff2 = extract_affine(expr->getArg(1));
378 if (name == "min")
379 aff1 = isl_pw_aff_min(aff1, aff2);
380 else
381 aff1 = isl_pw_aff_max(aff1, aff2);
382 } else if (name == "floord" || name == "ceild") {
383 isl_int v;
384 Expr *arg2 = expr->getArg(1);
386 if (arg2->getStmtClass() != Stmt::IntegerLiteralClass) {
387 unsupported(expr);
388 return NULL;
390 aff1 = extract_affine(expr->getArg(0));
391 isl_int_init(v);
392 extract_int(cast<IntegerLiteral>(arg2), &v);
393 aff1 = isl_pw_aff_scale_down(aff1, v);
394 isl_int_clear(v);
395 if (name == "floord")
396 aff1 = isl_pw_aff_floor(aff1);
397 else
398 aff1 = isl_pw_aff_ceil(aff1);
399 } else {
400 unsupported(expr);
401 return NULL;
404 return 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)
416 isl_id *id;
417 isl_dim *dim;
418 isl_aff *aff;
419 isl_set *dom;
421 if (!nesting_enabled) {
422 unsupported(expr);
423 return NULL;
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)
451 isl_set *cond;
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));
485 default:
486 unsupported(expr);
488 return NULL;
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());
508 return 0;
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());
525 return qt;
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
550 * form
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);
560 isl_map *access_rel;
562 dim = isl_dim_set_tuple_id(dim, isl_dim_out, id);
564 access_rel = isl_map_universe(dim);
566 return access_rel;
569 /* Extract an access relation from an integer contant.
570 * If the value of the constant is "v", then the returned access relation
571 * is
573 * { [] -> [v] }
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));
592 default:
593 unsupported(expr);
595 return NULL;
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)
604 isl_map *index_map;
605 int len = isl_map_dim(map, isl_dim_out);
606 isl_id *id;
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);
616 return 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
632 * in a later index.
634 __isl_give isl_map *PetScan::extract_access(ArraySubscriptExpr *expr)
636 Expr *base = expr->getBase();
637 Expr *idx = expr->getIdx();
638 isl_pw_aff *index;
639 isl_map *base_access;
640 isl_map *access;
641 int depth = array_depth(base->getType().getTypePtr());
642 int pos;
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);
655 return access;
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)
663 CallExpr *call;
664 FunctionDecl *fd;
665 string name;
667 if (expr->getStmtClass() != Stmt::CallExprClass)
668 return false;
670 call = cast<CallExpr>(expr);
671 fd = call->getDirectCallee();
672 if (!fd)
673 return false;
675 if (call->getNumArgs() != 2)
676 return false;
678 name = fd->getDeclName().getAsString();
679 if (name != minmax)
680 return false;
682 lhs = call->getArg(0);
683 rhs = call->getArg(1);
685 return true;
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
710 * a <= min(b,c)
712 * then the set is constructed as the intersection of the set corresponding
713 * to the comparisons
715 * a <= b and a <= c
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)
725 isl_pw_aff *lhs;
726 isl_pw_aff *rhs;
727 isl_set *cond;
729 if (op == BO_GT)
730 return extract_comparison(BO_LT, RHS, LHS, comp);
731 if (op == BO_GE)
732 return extract_comparison(BO_LE, RHS, LHS, comp);
734 if (op == BO_LT || op == BO_LE) {
735 Expr *expr1, *expr2;
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);
752 switch (op) {
753 case BO_LT:
754 cond = isl_pw_aff_lt_set(lhs, rhs);
755 break;
756 case BO_LE:
757 cond = isl_pw_aff_le_set(lhs, rhs);
758 break;
759 case BO_EQ:
760 cond = isl_pw_aff_eq_set(lhs, rhs);
761 break;
762 case BO_NE:
763 cond = isl_pw_aff_ne_set(lhs, rhs);
764 break;
765 default:
766 isl_pw_aff_free(lhs);
767 isl_pw_aff_free(rhs);
768 unsupported(comp);
769 return NULL;
772 cond = isl_set_coalesce(cond);
774 return 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)
788 isl_set *cond;
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)
800 isl_set *lhs;
801 isl_set *rhs;
802 isl_set *cond;
804 lhs = extract_condition(comp->getLHS());
805 rhs = extract_condition(comp->getRHS());
807 switch (comp->getOpcode()) {
808 case BO_LAnd:
809 cond = isl_set_intersect(lhs, rhs);
810 break;
811 case BO_LOr:
812 cond = isl_set_union(lhs, rhs);
813 break;
814 default:
815 isl_set_free(lhs);
816 isl_set_free(rhs);
817 unsupported(comp);
818 return NULL;
821 return cond;
824 __isl_give isl_set *PetScan::extract_condition(UnaryOperator *expr)
826 switch (expr->getOpcode()) {
827 case UO_LNot:
828 return extract_boolean(expr);
829 default:
830 unsupported(expr);
831 return NULL;
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;
851 if (!expr)
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()) {
865 case BO_LT:
866 case BO_LE:
867 case BO_GT:
868 case BO_GE:
869 case BO_EQ:
870 case BO_NE:
871 return extract_comparison(comp);
872 case BO_LAnd:
873 case BO_LOr:
874 return extract_boolean(comp);
875 default:
876 return extract_implicit_condition(expr);
880 static enum pet_op_type UnaryOperatorKind2pet_op_type(UnaryOperatorKind kind)
882 switch (kind) {
883 case UO_Minus:
884 return pet_op_minus;
885 default:
886 return pet_op_last;
890 static enum pet_op_type BinaryOperatorKind2pet_op_type(BinaryOperatorKind kind)
892 switch (kind) {
893 case BO_AddAssign:
894 return pet_op_add_assign;
895 case BO_SubAssign:
896 return pet_op_sub_assign;
897 case BO_MulAssign:
898 return pet_op_mul_assign;
899 case BO_DivAssign:
900 return pet_op_div_assign;
901 case BO_Assign:
902 return pet_op_assign;
903 case BO_Add:
904 return pet_op_add;
905 case BO_Sub:
906 return pet_op_sub;
907 case BO_Mul:
908 return pet_op_mul;
909 case BO_Div:
910 return pet_op_div;
911 case BO_LE:
912 return pet_op_le;
913 case BO_LT:
914 return pet_op_lt;
915 case BO_GT:
916 return pet_op_gt;
917 default:
918 return pet_op_last;
922 /* Construct a pet_expr representing a unary operator expression.
924 struct pet_expr *PetScan::extract_expr(UnaryOperator *expr)
926 struct pet_expr *arg;
927 enum pet_op_type op;
929 op = UnaryOperatorKind2pet_op_type(expr->getOpcode());
930 if (op == pet_op_last) {
931 unsupported(expr);
932 return NULL;
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;
953 enum pet_op_type op;
955 op = BinaryOperatorKind2pet_op_type(expr->getOpcode());
956 if (op == pet_op_last) {
957 unsupported(expr);
958 return NULL;
961 lhs = extract_expr(expr->getLHS());
962 rhs = extract_expr(expr->getRHS());
964 if (expr->isAssignmentOp() && lhs && lhs->type == pet_expr_access) {
965 lhs->acc.write = 1;
966 if (!expr->isCompoundAssignmentOp())
967 lhs->acc.read = 0;
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();
976 isl_id_free(id);
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
1008 * a pet_expr.
1010 struct pet_expr *PetScan::extract_access_expr(Expr *expr)
1012 isl_map *access;
1013 struct pet_expr *pe;
1015 switch (expr->getStmtClass()) {
1016 case Stmt::ArraySubscriptExprClass:
1017 access = extract_access(cast<ArraySubscriptExpr>(expr));
1018 break;
1019 case Stmt::DeclRefExprClass:
1020 access = extract_access(cast<DeclRefExpr>(expr));
1021 break;
1022 case Stmt::IntegerLiteralClass:
1023 access = extract_access(cast<IntegerLiteral>(expr));
1024 break;
1025 default:
1026 unsupported(expr);
1027 return NULL;
1030 pe = pet_expr_from_access(access);
1032 return pe;
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;
1053 FunctionDecl *fd;
1054 string name;
1056 fd = expr->getDirectCallee();
1057 if (!fd) {
1058 unsupported(expr);
1059 return NULL;
1062 name = fd->getDeclName().getAsString();
1063 res = pet_expr_new_call(ctx, name.c_str(), expr->getNumArgs());
1064 if (!res)
1065 return NULL;
1067 for (int i = 0; i < expr->getNumArgs(); ++i) {
1068 Expr *arg = expr->getArg(i);
1069 int is_addr = 0;
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) {
1078 is_addr = 1;
1079 arg = op->getSubExpr();
1082 res->args[i] = PetScan::extract_expr(arg);
1083 if (!res->args[i])
1084 goto error;
1085 if (arg->getStmtClass() == Stmt::ArraySubscriptExprClass &&
1086 array_depth(arg->getType().getTypePtr()) > 0)
1087 is_addr = 1;
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;
1097 return res;
1098 error:
1099 pet_expr_free(res);
1100 return NULL;
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));
1127 default:
1128 unsupported(expr);
1130 return NULL;
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;
1142 if (!init) {
1143 unsupported(stmt);
1144 return NULL;
1147 if (init->getStmtClass() != Stmt::BinaryOperatorClass) {
1148 unsupported(init);
1149 return NULL;
1152 ass = cast<BinaryOperator>(init);
1153 if (ass->getOpcode() != BO_Assign) {
1154 unsupported(init);
1155 return NULL;
1158 return ass;
1161 /* Given the assignment operator in the initialization of a for loop,
1162 * extract the induction variable, i.e., the (integer)variable being
1163 * assigned.
1165 ValueDecl *PetScan::extract_induction_variable(BinaryOperator *init)
1167 Expr *lhs;
1168 DeclRefExpr *ref;
1169 ValueDecl *decl;
1170 const Type *type;
1172 lhs = init->getLHS();
1173 if (lhs->getStmtClass() != Stmt::DeclRefExprClass) {
1174 unsupported(init);
1175 return NULL;
1178 ref = cast<DeclRefExpr>(lhs);
1179 decl = ref->getDecl();
1180 type = decl->getType().getTypePtr();
1182 if (!type->isIntegerType()) {
1183 unsupported(lhs);
1184 return NULL;
1187 return decl;
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,
1194 isl_int &inc)
1196 Expr *sub;
1197 DeclRefExpr *ref;
1199 if (!op->isIncrementDecrementOp()) {
1200 unsupported(op);
1201 return false;
1204 if (op->isIncrementOp())
1205 isl_int_set_si(inc, 1);
1206 else
1207 isl_int_set_si(inc, -1);
1209 sub = op->getSubExpr();
1210 if (sub->getStmtClass() != Stmt::DeclRefExprClass) {
1211 unsupported(op);
1212 return false;
1215 ref = cast<DeclRefExpr>(sub);
1216 if (ref->getDecl() != iv) {
1217 unsupported(op);
1218 return false;
1221 return true;
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,
1229 void *user)
1231 isl_int *inc = (isl_int *)user;
1232 int res = 0;
1234 if (!isl_set_plain_is_universe(set) || !isl_aff_is_cst(aff))
1235 res = -1;
1236 else
1237 isl_aff_get_constant(aff, inc);
1239 isl_set_free(set);
1240 isl_aff_free(aff);
1242 return res;
1245 /* Check if op is of the form
1247 * iv = iv + inc
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,
1255 isl_int &inc)
1257 Expr *lhs;
1258 DeclRefExpr *ref;
1259 isl_id *id;
1260 isl_dim *dim;
1261 isl_aff *aff;
1262 isl_pw_aff *val;
1264 if (op->getOpcode() != BO_Assign) {
1265 unsupported(op);
1266 return false;
1269 lhs = op->getLHS();
1270 if (lhs->getStmtClass() != Stmt::DeclRefExprClass) {
1271 unsupported(op);
1272 return false;
1275 ref = cast<DeclRefExpr>(lhs);
1276 if (ref->getDecl() != iv) {
1277 unsupported(op);
1278 return false;
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);
1294 unsupported(op);
1295 return false;
1298 isl_pw_aff_free(val);
1300 return true;
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)
1309 Expr *lhs, *rhs;
1310 DeclRefExpr *ref;
1311 bool neg = false;
1313 BinaryOperatorKind opcode;
1315 opcode = op->getOpcode();
1316 if (opcode != BO_AddAssign && opcode != BO_SubAssign) {
1317 unsupported(op);
1318 return false;
1320 if (opcode == BO_SubAssign)
1321 neg = true;
1323 lhs = op->getLHS();
1324 if (lhs->getStmtClass() != Stmt::DeclRefExprClass) {
1325 unsupported(op);
1326 return false;
1329 ref = cast<DeclRefExpr>(lhs);
1330 if (ref->getDecl() != iv) {
1331 unsupported(op);
1332 return false;
1335 rhs = op->getRHS();
1337 if (rhs->getStmtClass() == Stmt::UnaryOperatorClass) {
1338 UnaryOperator *op = cast<UnaryOperator>(rhs);
1339 if (op->getOpcode() != UO_Minus) {
1340 unsupported(op);
1341 return false;
1344 neg = !neg;
1346 rhs = op->getSubExpr();
1349 if (rhs->getStmtClass() != Stmt::IntegerLiteralClass) {
1350 unsupported(op);
1351 return false;
1354 extract_int(cast<IntegerLiteral>(rhs), &inc);
1355 if (neg)
1356 isl_int_neg(inc, inc);
1358 return true;
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();
1369 if (!inc) {
1370 unsupported(stmt);
1371 return false;
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);
1382 unsupported(inc);
1383 return false;
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)
1394 int pos;
1396 set = isl_set_insert(set, isl_dim_set, 0, 1);
1397 pos = isl_set_find_dim_by_id(set, isl_dim_param, var);
1398 if (pos >= 0) {
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);
1403 isl_id_free(var);
1404 return set;
1407 /* Construct a pet_scop for an infinite loop, i.e., a loop of the form
1409 * for (;;)
1410 * body
1412 * We extract a pet_scop for the body and then embed it in a loop with
1413 * iteration domain
1415 * { [t] : t >= 0 }
1417 * and schedule
1419 * { [t] -> [t] }
1421 struct pet_scop *PetScan::extract_infinite_for(ForStmt *stmt)
1423 isl_id *id;
1424 isl_dim *dim;
1425 isl_set *domain;
1426 isl_map *sched;
1427 struct pet_scop *scop;
1429 scop = extract(stmt->getBody());
1430 if (!scop)
1431 return NULL;
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);
1442 return scop;
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);
1455 else
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));
1485 else
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);
1494 return 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)
1504 isl_aff *aff;
1505 isl_dim *dim;
1506 isl_set *set;
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)
1530 * or
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' }
1538 * { [i] -> [i] }
1540 * or
1542 * { [i] : i <= init and condition' }
1543 * { [i] -> [-i] }
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;
1560 ValueDecl *iv;
1561 isl_dim *dim;
1562 isl_set *domain;
1563 isl_map *sched;
1564 isl_set *cond;
1565 isl_id *id;
1566 struct pet_scop *scop;
1567 assigned_value_cache cache(assigned_value);
1568 isl_int inc;
1570 if (!stmt->getInit() && !stmt->getCond() && !stmt->getInc())
1571 return extract_infinite_for(stmt);
1573 init = PetScan::extract_initialization(stmt);
1574 if (!init)
1575 return NULL;
1576 iv = extract_induction_variable(init);
1577 if (!iv)
1578 return NULL;
1580 isl_int_init(inc);
1581 if (!check_increment(stmt, iv, inc)) {
1582 isl_int_clear(inc);
1583 return NULL;
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);
1595 else {
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);
1613 else
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);
1619 isl_int_clear(inc);
1620 return scop;
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)
1643 int n;
1644 int nparam;
1645 int n_in;
1646 isl_dim *dim;
1647 isl_map *map;
1648 std::map<int,int> param2pos;
1650 if (!expr)
1651 return expr;
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);
1657 return NULL;
1661 if (expr->type != pet_expr_access)
1662 return expr;
1664 nparam = isl_map_dim(expr->acc.access, isl_dim_param);
1665 n = 0;
1666 for (int i = 0; i < nparam; ++i) {
1667 isl_id *id = isl_map_get_dim_id(expr->acc.access,
1668 isl_dim_param, i);
1669 if (id && isl_id_get_user(id) && !isl_id_get_name(id))
1670 n++;
1671 isl_id_free(id);
1674 if (n == 0)
1675 return expr;
1677 expr->n_arg = n;
1678 expr->args = isl_calloc_array(ctx, struct pet_expr *, n);
1679 if (!expr->args)
1680 goto error;
1682 n_in = isl_map_dim(expr->acc.access, isl_dim_in);
1683 for (int i = 0, pos = 0; i < nparam; ++i) {
1684 int j;
1685 isl_id *id = isl_map_get_dim_id(expr->acc.access,
1686 isl_dim_param, i);
1687 Expr *nested;
1689 if (!(id && isl_id_get_user(id) && !isl_id_get_name(id))) {
1690 isl_id_free(id);
1691 continue;
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]))
1699 break;
1701 if (j < pos) {
1702 pet_expr_free(expr->args[pos]);
1703 param2pos[i] = n_in + j;
1704 n--;
1705 } else
1706 param2pos[i] = n_in + pos++;
1708 isl_id_free(id);
1710 expr->n_arg = n;
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,
1723 isl_dim_param, i);
1724 if (!(id && isl_id_get_user(id) && !isl_id_get_name(id))) {
1725 isl_id_free(id);
1726 continue;
1729 expr->acc.access = isl_map_equate(expr->acc.access,
1730 isl_dim_param, i, isl_dim_in,
1731 param2pos[i]);
1732 expr->acc.access = isl_map_project_out(expr->acc.access,
1733 isl_dim_param, i, 1);
1735 isl_id_free(id);
1738 return expr;
1739 error:
1740 pet_expr_free(expr);
1741 return NULL;
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)
1765 isl_pw_aff *pwaff;
1766 int save_autodetect = autodetect;
1767 bool save_nesting = nesting_enabled;
1769 autodetect = 1;
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)
1787 isl_set *set;
1788 int save_autodetect = autodetect;
1789 bool save_nesting = nesting_enabled;
1791 autodetect = 1;
1792 nesting_enabled = false;
1794 set = extract_condition(expr);
1795 isl_set_free(set);
1797 autodetect = save_autodetect;
1798 nesting_enabled = save_nesting;
1800 return set != NULL;
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;
1811 if (!stmt)
1812 return NULL;
1813 if (stmt->getStmtClass() != Stmt::BinaryOperatorClass)
1814 return NULL;
1816 ass = cast<BinaryOperator>(stmt);
1817 if(ass->getOpcode() != BO_Assign)
1818 return NULL;
1820 return ass;
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
1829 * if (condition)
1830 * a = f(...);
1831 * else
1832 * a = g(...);
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;
1848 int equal;
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)
1856 return NULL;
1858 if (is_affine_condition(stmt->getCond()))
1859 return NULL;
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);
1868 return NULL;
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);
1892 if (pe_write) {
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)
1904 isl_set *cond;
1905 struct pet_scop *scop_then, *scop_else, *scop;
1906 assigned_value_cache cache(assigned_value);
1908 scop = extract_conditional_assignment(stmt);
1909 if (scop)
1910 return scop;
1912 scop_then = extract(stmt->getThen());
1914 if (stmt->getElse()) {
1915 scop_else = extract(stmt->getElse());
1916 if (autodetect) {
1917 if (scop_then && !scop_else) {
1918 partial = true;
1919 return scop_then;
1921 if (!scop_then && scop_else) {
1922 partial = true;
1923 return 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);
1935 } else
1936 isl_set_free(cond);
1938 return scop;
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));
1955 default:
1956 unsupported(stmt);
1959 return NULL;
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)
1967 pet_scop *scop;
1968 StmtIterator i;
1969 int j;
1970 bool partial_range = false;
1972 if (autodetect)
1973 scop = NULL;
1974 else
1975 scop = pet_scop_empty(ctx);
1976 for (i = stmt_range.first, j = 0; i != stmt_range.second; ++i, ++j) {
1977 Stmt *child = *i;
1978 struct pet_scop *scop_i;
1979 scop_i = extract(child);
1980 if (scop && partial) {
1981 pet_scop_free(scop_i);
1982 break;
1984 scop_i = pet_scop_prefix(scop_i, j);
1985 if (autodetect) {
1986 if (!scop) {
1987 if (j != 0)
1988 partial_range = true;
1989 scop = scop_i;
1990 } else if (scop_i)
1991 scop = pet_scop_add(ctx, scop, scop_i);
1992 else
1993 partial = true;
1994 } else {
1995 scop = pet_scop_add(ctx, scop, scop_i);
1997 if (partial)
1998 break;
2001 if (scop && partial_range)
2002 partial = true;
2004 return scop;
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)
2021 return NULL;
2022 if (end_off < loc.start)
2023 return NULL;
2024 if (start_off >= loc.start && end_off <= loc.end) {
2025 return extract(stmt);
2028 StmtIterator start;
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)
2034 return scan(child);
2035 if (start_off >= loc.start)
2036 break;
2039 StmtIterator end;
2040 for (end = start; end != stmt->child_end(); ++end) {
2041 Stmt *child = *end;
2042 start_off = SM.getFileOffset(child->getLocStart());
2043 if (start_off >= loc.end)
2044 break;
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
2053 * i_pos < size
2055 * to array->extent and a constraint of the form
2057 * size >= 0
2059 * to array->context.
2061 static struct pet_array *update_size(struct pet_array *array, int pos,
2062 __isl_take isl_pw_aff *size)
2064 isl_set *valid;
2065 isl_set *univ;
2066 isl_set *bound;
2067 isl_dim *dim;
2068 isl_aff *aff;
2069 isl_pw_aff *index;
2070 isl_id *id;
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)
2090 goto error;
2092 return array;
2093 error:
2094 pet_array_free(array);
2095 return NULL;
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;
2105 isl_pw_aff *size;
2107 if (type->isPointerType()) {
2108 type = type->getPointeeType().getTypePtr();
2109 return set_upper_bounds(array, type, pos + 1);
2111 if (!type->isArrayType())
2112 return array;
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);
2147 string name;
2148 isl_id *id;
2149 isl_dim *dim;
2151 array = isl_calloc_type(ctx, struct pet_array);
2152 if (!array)
2153 return NULL;
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);
2165 if (!array)
2166 return NULL;
2168 name = base.getAsString();
2169 array->element_type = strdup(name.c_str());
2171 return array;
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)
2183 int i;
2184 set<ValueDecl *> arrays;
2185 set<ValueDecl *>::iterator it;
2187 if (!scop)
2188 return NULL;
2190 pet_scop_collect_arrays(scop, arrays);
2192 scop->n_array = arrays.size();
2193 if (scop->n_array == 0)
2194 return scop;
2196 scop->arrays = isl_calloc_array(ctx, struct pet_array *, scop->n_array);
2197 if (!scop->arrays)
2198 goto error;
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])
2204 goto error;
2205 scop->context = isl_set_intersect(scop->context,
2206 isl_set_copy(array->context));
2207 if (!scop->context)
2208 goto error;
2211 return scop;
2212 error:
2213 pet_scop_free(scop);
2214 return NULL;
2217 /* Construct a pet_scop from the given function.
2219 struct pet_scop *PetScan::scan(FunctionDecl *fd)
2221 pet_scop *scop;
2222 Stmt *stmt;
2224 stmt = fd->getBody();
2226 if (autodetect)
2227 scop = extract(stmt);
2228 else
2229 scop = scan(stmt);
2230 scop = pet_scop_detect_parameter_accesses(scop);
2231 scop = scan_arrays(scop);
2233 return scop;