/* Return an array of "n" elements with information extracted from * the "n" children of "node" starting at "first", all of which * are known to be filtered leaves. */ struct ppcg_grouping_leaf *extract_leaves(__isl_keep isl_schedule_node *node, int first, int n) { int i; isl_ctx *ctx; struct ppcg_grouping_leaf *leaves; if (!node) return NULL; ctx = isl_schedule_node_get_ctx(node); leaves = isl_calloc_array(ctx, struct ppcg_grouping_leaf, n); if (!leaves) return NULL; for (i = 0; i < n; ++i) { isl_schedule_node *child; isl_union_set *domain; child = isl_schedule_node_get_child(node, first + i); child = isl_schedule_node_child(child, 0); domain = isl_schedule_node_get_domain(child); leaves[i].domain = isl_union_set_copy(domain); leaves[i].list = isl_union_set_list_from_union_set(domain); leaves[i].prefix = get_prefix(child); isl_schedule_node_free(child); } return leaves; }
/* Construct a schedule with "domain" as domain, that executes * the elements of "list" in order (as a sequence). */ static __isl_give isl_schedule *schedule_from_domain_and_list( __isl_keep isl_union_set *domain, __isl_keep isl_union_set_list *list) { isl_schedule *schedule; isl_schedule_node *node; schedule = isl_schedule_from_domain(isl_union_set_copy(domain)); node = isl_schedule_get_root(schedule); isl_schedule_free(schedule); node = isl_schedule_node_child(node, 0); list = isl_union_set_list_copy(list); node = isl_schedule_node_insert_sequence(node, list); schedule = isl_schedule_node_get_schedule(node); isl_schedule_node_free(node); return schedule; }
/* If "node" is a sequence, then check if it has any consecutive * leaves that should be merged together and store the results * in "grouping". * * In particular, call group_subsequence on each consecutive * sequence of (filtered) leaves among the children of "node". */ static isl_bool detect_groups(__isl_keep isl_schedule_node *node, void *user) { int i, n, first; isl_bool has_only_leaves; struct ppcg_grouping *grouping = user; if (isl_schedule_node_get_type(node) != isl_schedule_node_sequence) return isl_bool_true; n = isl_schedule_node_n_children(node); if (n < 0) return isl_bool_error; first = -1; for (i = 0; i < n; ++i) { isl_schedule_node *child; enum isl_schedule_node_type type; child = isl_schedule_node_get_child(node, i); child = isl_schedule_node_child(child, 0); type = isl_schedule_node_get_type(child); isl_schedule_node_free(child); if (first >= 0 && type != isl_schedule_node_leaf) { if (group_subsequence(node, first, i - first, grouping) < 0) return isl_bool_error; first = -1; } if (first < 0 && type == isl_schedule_node_leaf) first = i; } if (first >= 0) { if (group_subsequence(node, first, n - first, grouping) < 0) return isl_bool_error; } return isl_bool_true; }
ast_isl ast_gen::generate() { auto ctx = m_model.context; if (verbose<ast_gen>::enabled()) print_isl_ast_options(ctx); if (true) { //isl_options_set_ast_build_separation_bounds //(ctx.get(), ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT); //isl_options_set_ast_build_scale_strides(ctx, 0); } ast_isl output; auto build = isl_ast_build_from_context(m_schedule.params.copy()); if (m_options.separate_loops) { if (m_schedule.tree.get()) { auto root = isl_schedule_get_root(m_schedule.prelude_tree.get()); root = mark_loop_type_separate(ctx, root); m_schedule.tree = isl_schedule_node_get_schedule(root); isl_schedule_node_free(root); } if (m_schedule.prelude_tree.get()) { auto root = isl_schedule_get_root(m_schedule.prelude_tree.get()); root = mark_loop_type_separate(ctx, root); m_schedule.prelude_tree = isl_schedule_node_get_schedule(root); isl_schedule_node_free(root); } if (m_schedule.period_tree.get()) { auto root = isl_schedule_get_root(m_schedule.period_tree.get()); root = mark_loop_type_separate(ctx, root); m_schedule.period_tree = isl_schedule_node_get_schedule(root); isl_schedule_node_free(root); } } build = isl_ast_build_set_before_each_for(build, &ast_gen::invoke_before_for, this); build = isl_ast_build_set_after_each_for(build, &ast_gen::invoke_after_for, this); // Initialize parallel accesses to empty map m_model.parallel_accesses = isl::union_map(m_model.context); if (m_schedule.tree.get()) { if (verbose<ast_gen>::enabled()) cout << endl << "** Building AST for entire program." << endl; m_allow_parallel_for = false; output.full = isl_ast_build_node_from_schedule(build, m_schedule.tree.copy()); } if (m_schedule.prelude_tree.get()) { if (verbose<ast_gen>::enabled()) cout << endl << "** Building AST for prelude." << endl; m_allow_parallel_for = false; output.prelude = isl_ast_build_node_from_schedule(build, m_schedule.prelude_tree.copy()); } if (m_schedule.period_tree.get()) { if (verbose<ast_gen>::enabled()) cout << endl << "** Building AST for period." << endl; m_allow_parallel_for = m_options.parallel | m_options.vectorize; int num_sched_dim = 0; m_schedule.period.for_each([&](const isl::map & m){ num_sched_dim = m.get_space().dimension(isl::space::output); return false; }); build = set_loop_iterators(build, num_sched_dim, m_options.parallel_dim); output.period = isl_ast_build_node_from_schedule(build, m_schedule.period_tree.copy()); } isl_ast_build_free(build); return output; }