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; }
/* Create a graft for "node" with no guards and no enforced conditions. */ __isl_give isl_ast_graft *isl_ast_graft_alloc( __isl_take isl_ast_node *node, __isl_keep isl_ast_build *build) { isl_ctx *ctx; isl_space *space; isl_ast_graft *graft; if (!node) return NULL; ctx = isl_ast_node_get_ctx(node); graft = isl_calloc_type(ctx, isl_ast_graft); if (!graft) goto error; space = isl_ast_build_get_space(build, 1); graft->ref = 1; graft->node = node; graft->guard = isl_set_universe(isl_space_copy(space)); graft->enforced = isl_basic_set_universe(space); if (!graft->guard || !graft->enforced) return isl_ast_graft_free(graft); return graft; error: isl_ast_node_free(node); return NULL; }
/* 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; }
// Init void init_solver (void) { context = isl_ctx_alloc (); isl_space * vars = isl_space_set_alloc (context, 0, v_nb ()); ls = isl_local_space_from_space (isl_space_copy (vars)); solutions = isl_set_universe (vars); solution = 0; next_max_var = 0; }
/* 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. * If there is only one graft in the list and if its guard * depends on the current level, then we eliminate this level and * return the result. * * Otherwise, we return the unshifted simple hull of the guards. * In order to be able to hoist as many constraints as possible, * but at the same time avoid hoisting constraints that did not * appear in the guards in the first place, we intersect the guards * with all the information that is available (i.e., the domain * from the build and the enforced constraints of the graft) and * compute the unshifted hull of the result using only constraints * from the original guards. * In particular, intersecting the guards with other known information * allows us to hoist guards that are only explicit is some of * the grafts and implicit in the others. * * 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. */ __isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard( __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build) { int i, n; int equal; isl_ctx *ctx; isl_set *guard; isl_set_list *set_list; isl_basic_set *hull; 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; if (equal || n == 1) { isl_ast_graft *graft_0; graft_0 = isl_ast_graft_list_get_ast_graft(list, 0); if (!graft_0) return NULL; guard = isl_set_copy(graft_0->guard); if (!equal) guard = hoist_guard(guard, build); isl_ast_graft_free(graft_0); return guard; } ctx = isl_ast_build_get_ctx(build); set_list = isl_set_list_alloc(ctx, n); guard = isl_set_empty(isl_ast_build_get_space(build, 1)); for (i = 0; i < n; ++i) { isl_ast_graft *graft; isl_basic_set *enforced; isl_set *guard_i; graft = isl_ast_graft_list_get_ast_graft(list, i); enforced = isl_ast_graft_get_enforced(graft); guard_i = isl_set_copy(graft->guard); isl_ast_graft_free(graft); set_list = isl_set_list_add(set_list, isl_set_copy(guard_i)); guard_i = isl_set_intersect(guard_i, isl_set_from_basic_set(enforced)); guard_i = isl_set_intersect(guard_i, isl_ast_build_get_domain(build)); guard = isl_set_union(guard, guard_i); } hull = isl_set_unshifted_simple_hull_from_set_list(guard, set_list); guard = isl_set_from_basic_set(hull); return hoist_guard(guard, build); }
/* Given a parameter space "space", create a set of dimension "len" * of which the dimensions starting at "first" are equated to * freshly created parameters with identifiers "ids". */ __isl_give isl_set *parametrization(__isl_take isl_space *space, int len, int first, __isl_keep isl_id_list *ids) { isl_set *set; space = isl_space_set_from_params(space); space = isl_space_add_dims(space, isl_dim_set, len); set = isl_set_universe(space); return parametrize(set, first, ids); }
static isl_set* build_iteration_domain (scoplib_scop_p scop, scoplib_statement_p s, isl_space* space, isl_ctx* ctxt) { isl_set* ret = isl_set_universe (isl_space_domain (isl_space_copy (space))); int i; isl_val* tmp = isl_val_int_from_si (ctxt, 0); scoplib_matrix_p m = s->domain->elt; for (i = 0; i < m->NbRows; ++i) { isl_local_space* ls = isl_local_space_from_space (isl_set_get_space (ret)); isl_constraint* cst; if (SCOPVAL_get_si(m->p[i][0]) == 0) cst = isl_equality_alloc (isl_local_space_copy (ls)); else cst = isl_inequality_alloc (isl_local_space_copy (ls)); // Set input dimensions. int k; for (k = 0; k < s->nb_iterators; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_set, k, isl_val_copy (tmp)); } for (k = 0; k < scop->nb_parameters; ++k) { tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][k+1+s->nb_iterators])); cst = isl_constraint_set_coefficient_val (cst, isl_dim_param, k, isl_val_copy (tmp)); } tmp = isl_val_set_si (tmp, SCOPVAL_get_si(m->p[i][m->NbColumns - 1])); cst = isl_constraint_set_constant_val (cst, isl_val_copy (tmp)); // Insert constraint. ret = isl_set_add_constraint (ret, cst); } isl_val_free (tmp); return ret; }