/* Used by libpluto interface */ static int extract_stmt(__isl_take isl_set *set, void *user) { int r; Stmt **stmts; int id, i; stmts = (Stmt **) user; int dim = isl_set_dim(set, isl_dim_all); int npar = isl_set_dim(set, isl_dim_param); PlutoMatrix *trans = pluto_matrix_alloc(dim-npar, dim+1); pluto_matrix_set(trans, 0); trans->nrows = 0; /* A statement's domain (isl_set) should be named S_%d */ const char *name = isl_set_get_tuple_name(set); assert(name); assert(strlen(name) >= 3); assert(name[0] == 'S'); assert(name[1] == '_'); assert(isdigit(name[2])); id = atoi(isl_set_get_tuple_name(set)+2); stmts[id] = pluto_stmt_alloc(dim-npar, NULL, trans); Stmt *stmt = stmts[id]; stmt->type = ORIG; stmt->id = id; for (i=0; i<stmt->dim; i++) { char *iter = malloc(5); sprintf(iter, "i%d", i); stmt->iterators[i] = iter; } struct pluto_extra_stmt_info info = {stmts, id}; r = isl_set_foreach_basic_set(set, &extract_basic_set, &info); pluto_constraints_set_names_range(stmt->domain, stmt->iterators, 0, 0, stmt->dim); for (i=0; i<npar; i++) { char *param = malloc(5); sprintf(param, "p%d", i); stmt->domain->names[stmt->dim+i] = param; } pluto_matrix_free(trans); int j; for (j=0; j<stmt->dim; j++) { stmt->is_orig_loop[j] = true; } isl_set_free(set); return r; }
/* Compute the size of a bounding box around the origin and "set", * where "set" is assumed to contain only non-negative elements. * In particular, compute the maximal value of "set" in each direction * and add one. */ __isl_give isl_multi_pw_aff *ppcg_size_from_extent(__isl_take isl_set *set) { int i, n; isl_multi_pw_aff *mpa; n = isl_set_dim(set, isl_dim_set); mpa = isl_multi_pw_aff_zero(isl_set_get_space(set)); for (i = 0; i < n; ++i) { isl_space *space; isl_aff *one; isl_pw_aff *bound; if (!isl_set_dim_has_upper_bound(set, isl_dim_set, i)) { const char *name; name = isl_set_get_tuple_name(set); if (!name) name = ""; fprintf(stderr, "unable to determine extent of '%s' " "in dimension %d\n", name, i); set = isl_set_free(set); } bound = isl_set_dim_max(isl_set_copy(set), i); space = isl_pw_aff_get_domain_space(bound); one = isl_aff_zero_on_domain(isl_local_space_from_space(space)); one = isl_aff_add_constant_si(one, 1); bound = isl_pw_aff_add(bound, isl_pw_aff_from_aff(one)); mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, bound); } isl_set_free(set); return mpa; }
CloogInput *Cloog::buildCloogInput() { // XXX: We do not copy the context of the scop, but use an unconstrained // context. This 'hack' is necessary as the context may contain bounds // on parameters such as [n] -> {:0 <= n < 2^32}. Those large // integers will cause CLooG to construct a clast that contains // expressions that include these large integers. Such expressions can // possibly not be evaluated correctly with i64 types. The cloog // based code generation backend, however, can not derive types // automatically and just assumes i64 types. Hence, it will break or // generate incorrect code. // This hack does not remove all possibilities of incorrectly generated // code, but it is ensures that for most problems the problems do not // show up. The correct solution, will be to automatically derive the // minimal types for each expression. This could be added to CLooG and it // will be available in the isl based code generation. isl_set *EmptyContext = isl_set_universe(S->getParamSpace()); CloogDomain *Context = cloog_domain_from_isl_set(EmptyContext); CloogUnionDomain *Statements = buildCloogUnionDomain(); isl_set *ScopContext = S->getContext(); for (unsigned i = 0; i < isl_set_dim(ScopContext, isl_dim_param); i++) { isl_id *id = isl_set_get_dim_id(ScopContext, isl_dim_param, i); Statements = cloog_union_domain_set_name(Statements, CLOOG_PARAM, i, isl_id_get_name(id)); isl_id_free(id); } isl_set_free(ScopContext); CloogInput *Input = cloog_input_alloc(Context, Statements); return Input; }
/* Extract a common guard from the grafts in "list" that can be hoisted * out of the current level. If no such guard can be found, then return * a universal set. * * If all the grafts in the list have the same guard and if this guard * is independent of the current level, then it can be hoisted out. * Otherwise, we return the unshifted simple hull of the guards. * * The special case for equal guards is needed in case those guards * are non-convex. Taking the simple hull would remove information * and would not allow for these guards to be hoisted completely. */ static __isl_give isl_set *extract_hoistable_guard( __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build) { int i, n; int depth; isl_ast_graft *graft_0; int equal; isl_set *guard; if (!list || !build) return NULL; n = isl_ast_graft_list_n_ast_graft(list); if (n == 0) return isl_set_universe(isl_ast_build_get_space(build, 1)); equal = equal_independent_guards(list, build); if (equal < 0) return NULL; graft_0 = isl_ast_graft_list_get_ast_graft(list, 0); if (!graft_0) return NULL; guard = isl_set_copy(graft_0->guard); isl_ast_graft_free(graft_0); if (equal) return guard; depth = isl_ast_build_get_depth(build); if (depth < isl_set_dim(guard, isl_dim_set)) { guard = isl_set_remove_divs_involving_dims(guard, isl_dim_set, depth, 1); guard = isl_set_eliminate(guard, isl_dim_set, depth, 1); guard = isl_set_compute_divs(guard); } for (i = 1; i < n; ++i) { isl_ast_graft *graft; isl_basic_set *hull; int is_universe; is_universe = isl_set_plain_is_universe(guard); if (is_universe < 0) guard = isl_set_free(guard); if (is_universe) break; graft = isl_ast_graft_list_get_ast_graft(list, i); if (!graft) { guard = isl_set_free(guard); break; } guard = isl_set_union(guard, isl_set_copy(graft->guard)); hull = isl_set_unshifted_simple_hull(guard); guard = isl_set_from_basic_set(hull); isl_ast_graft_free(graft); } return guard; }
/* Hoist "guard" out of the current level (given by "build"). * * In particular, eliminate the dimension corresponding to the current depth. */ static __isl_give isl_set *hoist_guard(__isl_take isl_set *guard, __isl_keep isl_ast_build *build) { int depth; depth = isl_ast_build_get_depth(build); if (depth < isl_set_dim(guard, isl_dim_set)) { guard = isl_set_remove_divs_involving_dims(guard, isl_dim_set, depth, 1); guard = isl_set_eliminate(guard, isl_dim_set, depth, 1); guard = isl_set_compute_divs(guard); } return guard; }
/* Equate the dimensions of "set" starting at "first" to * freshly created parameters with identifiers "ids". * The number of equated dimensions is equal to the number of elements in "ids". */ static __isl_give isl_set *parametrize(__isl_take isl_set *set, int first, __isl_keep isl_id_list *ids) { int i, n; unsigned nparam; nparam = isl_set_dim(set, isl_dim_param); set = add_params(set, ids); n = isl_id_list_n_id(ids); for (i = 0; i < n; ++i) set = isl_set_equate(set, isl_dim_param, nparam + i, isl_dim_set, first + i); return set; }
/* Add parameters with identifiers "ids" to "set". */ static __isl_give isl_set *add_params(__isl_take isl_set *set, __isl_keep isl_id_list *ids) { int i, n; unsigned nparam; n = isl_id_list_n_id(ids); nparam = isl_set_dim(set, isl_dim_param); set = isl_set_add_dims(set, isl_dim_param, n); for (i = 0; i < n; ++i) { isl_id *id; id = isl_id_list_get_id(ids, i); set = isl_set_set_dim_id(set, isl_dim_param, nparam + i, id); } return set; }
static isl_constraint * build_linearized_memory_access (isl_map *map, poly_dr_p pdr) { isl_constraint *res; isl_local_space *ls = isl_local_space_from_space (isl_map_get_space (map)); unsigned offset, nsubs; int i; isl_int size, subsize; res = isl_equality_alloc (ls); isl_int_init (size); isl_int_set_ui (size, 1); isl_int_init (subsize); isl_int_set_ui (subsize, 1); nsubs = isl_set_dim (pdr->extent, isl_dim_set); /* -1 for the already included L dimension. */ offset = isl_map_dim (map, isl_dim_out) - 1 - nsubs; res = isl_constraint_set_coefficient_si (res, isl_dim_out, offset + nsubs, -1); /* Go through all subscripts from last to first. First dimension is the alias set, ignore it. */ for (i = nsubs - 1; i >= 1; i--) { isl_space *dc; isl_aff *aff; res = isl_constraint_set_coefficient (res, isl_dim_out, offset + i, size); dc = isl_set_get_space (pdr->extent); aff = isl_aff_zero_on_domain (isl_local_space_from_space (dc)); aff = isl_aff_set_coefficient_si (aff, isl_dim_in, i, 1); isl_set_max (pdr->extent, aff, &subsize); isl_aff_free (aff); isl_int_mul (size, size, subsize); } isl_int_clear (subsize); isl_int_clear (size); return res; }
/* Do all the grafts in "list" have the same guard and is this guard * independent of the current depth? */ static int equal_independent_guards(__isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build) { int i, n; int depth; isl_ast_graft *graft_0; int equal = 1; int skip; graft_0 = isl_ast_graft_list_get_ast_graft(list, 0); if (!graft_0) return -1; depth = isl_ast_build_get_depth(build); if (isl_set_dim(graft_0->guard, isl_dim_set) <= depth) skip = 0; else skip = isl_set_involves_dims(graft_0->guard, isl_dim_set, depth, 1); if (skip < 0 || skip) { isl_ast_graft_free(graft_0); return skip < 0 ? -1 : 0; } n = isl_ast_graft_list_n_ast_graft(list); for (i = 1; i < n; ++i) { isl_ast_graft *graft; graft = isl_ast_graft_list_get_ast_graft(list, i); if (!graft) equal = -1; else equal = isl_set_is_equal(graft_0->guard, graft->guard); isl_ast_graft_free(graft); if (equal < 0 || !equal) break; } isl_ast_graft_free(graft_0); return equal; }