/* Merge pairs of consecutive leaves in "leaves" taking into account * the intersection of validity and proximity schedule constraints "dep". * * If a leaf has been merged with the next leaf, then the combination * is checked again for merging with the next leaf. * That is, if the leaves are A, B and C, then B may not have been * merged with C, but after merging A and B, it could still be useful * to merge the combination AB with C. * * Two leaves A and B are merged if there are instances of at least * one pair of statements, one statement in A and one B, such that * the validity and proximity schedule constraints between them * make them suitable for merging according to check_merge. * * Return the final number of leaves in the sequence, or -1 on error. */ static int merge_leaves(int n, struct ppcg_grouping_leaf leaves[n], __isl_keep isl_union_map *dep) { int i; struct ppcg_merge_leaves_data data; for (i = n - 1; i >= 0; --i) { isl_union_map *dep_i; isl_stat ok; if (i + 1 >= n) continue; dep_i = isl_union_map_copy(dep); dep_i = isl_union_map_intersect_domain(dep_i, isl_union_set_copy(leaves[i].domain)); dep_i = isl_union_map_intersect_range(dep_i, isl_union_set_copy(leaves[i + 1].domain)); data.merge = 0; data.src = &leaves[i]; data.dst = &leaves[i + 1]; ok = isl_union_map_foreach_map(dep_i, &check_merge, &data); isl_union_map_free(dep_i); if (ok < 0 && !data.merge) return -1; if (!data.merge) continue; if (merge_pair(n, leaves, i) < 0) return -1; --n; ++i; } return n; }
/* Given a relation "map" between instances of two statements A and B, * are pairs of related instances executed together in the input schedule? * That is, is each pair of instances assigned the same value * by the corresponding prefix schedules? * * In particular, select the subset of "map" that has pairs of elements * with the same value for the prefix schedules and then check * if "map" is still a subset of the result. */ static isl_bool matches_prefix(__isl_keep isl_map *map, struct ppcg_grouping_leaf *src, struct ppcg_grouping_leaf *dst) { isl_union_map *umap, *equal; isl_multi_union_pw_aff *src_prefix, *dst_prefix, *prefix; isl_bool is_subset; src_prefix = isl_multi_union_pw_aff_copy(src->prefix); dst_prefix = isl_multi_union_pw_aff_copy(dst->prefix); prefix = isl_multi_union_pw_aff_union_add(src_prefix, dst_prefix); umap = isl_union_map_from_map(isl_map_copy(map)); equal = isl_union_map_copy(umap); equal = isl_union_map_eq_at_multi_union_pw_aff(equal, prefix); is_subset = isl_union_map_is_subset(umap, equal); isl_union_map_free(umap); isl_union_map_free(equal); return is_subset; }
static void *isl_obj_union_map_copy(void *v) { return isl_union_map_copy((isl_union_map *)v); }
/** * Converts a SCoP as extracted by PolyOpt's auto-scop detection * into ISL representation. * * bugs/limitations: * (a) not robust to union of iteration domains in scoplib * (b) code is leaking, need proper copy constructor that duplicates all * ISL structures. */ int PolyOptISLRepresentation::convertScoplibToISL (scoplib_scop_p scop) { int i; isl_union_map* all_reads = NULL; isl_union_map* all_writes = NULL; isl_union_map* all_scheds = NULL; isl_ctx* ctxt = isl_ctx_alloc(); // 1. Prepare the arrays of unique names for statements and arrays. char buffer[32]; int nb_statements; scoplib_statement_p s; for (nb_statements = 0, s = scop->statement; s; s = s->next, nb_statements++) ; char* stmt_names[nb_statements]; for (i = 0; i < nb_statements; ++i) { sprintf (buffer, "S_%d", i); stmt_names[i] = strdup (buffer); } char* array_names[scop->nb_arrays]; for (i = 0; i < scop->nb_arrays; ++i) array_names[i] = strdup (((SgVariableSymbol*)(scop->arrays[i]))->get_name().str()); isl_union_map* umap; int stmt_id; for (s = scop->statement, stmt_id = 0; s; s = s->next, ++stmt_id) { isl_union_map* all_reads_stmt = NULL; isl_union_map* all_writes_stmt = NULL; isl_space* sp = NULL; for (i = 0; i < scop->nb_arrays; ++i) { sp = build_isl_space (scop, s, i+1, ctxt); // 1. Handle access matrices. scoplib_matrix_p m; int k; for (k = 0, m = s->read, umap = all_reads_stmt; k < 2; k++, m = s->write, umap = all_writes_stmt) { isl_map* acc_map = NULL; int row_pos = 0; do { acc_map = build_access_function (scop, s, m, sp, ctxt, &row_pos, i+1); if (acc_map) { acc_map = isl_map_set_tuple_name (acc_map, isl_dim_in, stmt_names[stmt_id]); acc_map = isl_map_set_tuple_name (acc_map, isl_dim_out, array_names[i]); if (umap == NULL) umap = isl_union_map_from_map (isl_map_copy (acc_map)); else umap = isl_union_map_union (umap, isl_union_map_from_map (isl_map_copy (acc_map))); isl_map_free (acc_map); } } while (acc_map != NULL); if (k == 0) all_reads_stmt = umap; else all_writes_stmt = umap; } } // Store the union of access functions of statement i. stmt_accfunc_read.push_back (all_reads_stmt); stmt_accfunc_write.push_back (all_writes_stmt); // 2. Handle iteration domains. isl_set* dom = build_iteration_domain (scop, s, sp, ctxt); dom = isl_set_set_tuple_name (dom, stmt_names[stmt_id]); if (all_reads_stmt != NULL) all_reads_stmt = isl_union_map_intersect_domain (isl_union_map_copy (all_reads_stmt), isl_union_set_from_set (isl_set_copy (dom))); if (all_writes_stmt != NULL) all_writes_stmt = isl_union_map_intersect_domain (all_writes_stmt, isl_union_set_from_set (isl_set_copy (dom))); // Store the iteration domain of statement i. stmt_iterdom.push_back (dom); // Store the union of access functions of statement i after intersection by domain. stmt_read_domain.push_back (all_reads_stmt); stmt_write_domain.push_back (all_writes_stmt); // Unionize the result. if (all_reads == NULL) all_reads = isl_union_map_copy (all_reads_stmt); else all_reads = isl_union_map_union (all_reads, isl_union_map_copy (all_reads_stmt)); if (all_writes == NULL) all_writes = isl_union_map_copy (all_writes_stmt); else all_writes = isl_union_map_union (all_writes, isl_union_map_copy (all_writes_stmt)); // isl_union_map_free (all_reads_stmt); // isl_union_map_free (all_writes_stmt); // 3. Handle schedules. isl_map* sched = build_schedule (scop, s, sp, ctxt); sched = isl_map_set_tuple_name (sched, isl_dim_in, stmt_names[stmt_id]); if (all_scheds == NULL) all_scheds = isl_union_map_from_map (isl_map_copy (sched)); else all_scheds = isl_union_map_union (all_scheds, isl_union_map_from_map (isl_map_copy (sched))); // Store the schedule of statement i. stmt_schedule.push_back (sched); // 4. Finalize info about the statement. stmt_body.push_back (((SgNode*)(s->body))->unparseToCompleteString()); stmt_body_ir.push_back ((SgNode*)(s->body)); } // // Debug. // isl_printer* pr = isl_printer_to_file (ctxt, stdout); // std::cout << "UNION MAP READS" << std::endl; // isl_printer_print_union_map(pr, all_reads); // printf ("\n"); // std::cout << "UNION MAP WRITES" << std::endl; // isl_printer_print_union_map(pr, all_writes); // printf ("\n"); // std::cout << "UNION MAP SCHEDULES" << std::endl; // isl_printer_print_union_map(pr, all_scheds); // printf ("\n"); for (std::vector<std::string>::iterator i = stmt_body.begin(); i != stmt_body.end(); ++i) std::cout << "stmt body: " << *i << std::endl; // Finalize SCoP representation. scop_nb_arrays = scop->nb_arrays; scop_nb_statements = stmt_schedule.size(); scop_reads = all_reads; scop_writes = all_writes; scop_scheds = all_scheds; return EXIT_SUCCESS; }