isl_ast_build * ast_gen::set_loop_iterators(isl_ast_build * ast, int count, int parallel_loop) { auto ctx = isl_ast_build_get_ctx(ast); isl_id_list * ids = isl_id_list_alloc(ctx, count); for(int i = 0; i < count; ++i) { auto name = string("c") + to_string(i); if (verbose<ast_gen>::enabled()) cout << "Adding iterator: " << name << endl; void * data = nullptr; if (i == parallel_loop) { if (verbose<ast_gen>::enabled()) cout << "(parallel)" << endl; data = &m_parallel_loop_id; } auto id = isl_id_alloc(ctx, name.c_str(), data); ids = isl_id_list_add(ids, id); } ast = isl_ast_build_set_iterators(ast, ids); return ast; }
/* Insert an if node around "node" testing the condition encoded * in guard "guard". * * If the user does not want any disjunctions in the if conditions * and if "guard" does involve a disjunction, then we make the different * disjuncts disjoint and insert an if node corresponding to each disjunct * around a copy of "node". The result is then a block node containing * this sequence of guarded copies of "node". */ static __isl_give isl_ast_node *ast_node_insert_if( __isl_take isl_ast_node *node, __isl_take isl_set *guard, __isl_keep isl_ast_build *build) { struct isl_insert_if_data data; isl_ctx *ctx; ctx = isl_ast_build_get_ctx(build); if (isl_options_get_ast_build_allow_or(ctx) || isl_set_n_basic_set(guard) <= 1) { isl_ast_node *if_node; isl_ast_expr *expr; expr = isl_ast_build_expr_from_set_internal(build, guard); if_node = isl_ast_node_alloc_if(expr); return isl_ast_node_if_set_then(if_node, node); } guard = isl_set_make_disjoint(guard); data.list = isl_ast_node_list_alloc(ctx, 0); data.node = node; data.build = build; if (isl_set_foreach_basic_set(guard, &insert_if, &data) < 0) data.list = isl_ast_node_list_free(data.list); isl_set_free(guard); isl_ast_node_free(data.node); return isl_ast_node_alloc_block(data.list); }
/* 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); }
/* For each graft in "list", * insert an if node around graft->node testing the condition encoded * in graft->guard, assuming graft->guard involves any conditions. * * We keep track of a list of generated if nodes that can be extended * without changing the order of the elements in "list". * If the guard of a graft is a subset of either the guard or its complement * of one of those if nodes, then the node * of the new graft is inserted into the then or else branch of the last graft * and the current graft is discarded. * The guard of the node is then simplified based on the conditions * enforced at that then or else branch. * Otherwise, the current graft is appended to the list. * * We only construct else branches if allowed by the user. */ static __isl_give isl_ast_graft_list *insert_pending_guard_nodes( __isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build) { int i, j, n, n_if; int allow_else; isl_ctx *ctx; isl_ast_graft_list *res; struct isl_if_node *if_node = NULL; if (!build || !list) return isl_ast_graft_list_free(list); ctx = isl_ast_build_get_ctx(build); n = isl_ast_graft_list_n_ast_graft(list); allow_else = isl_options_get_ast_build_allow_else(ctx); n_if = 0; if (n > 1) { if_node = isl_alloc_array(ctx, struct isl_if_node, n - 1); if (!if_node) return isl_ast_graft_list_free(list); }