/// @brief Create an isl constraint from a row of OpenScop integers. /// /// @param row An array of isl/OpenScop integers. /// @param Space An isl space object, describing how to spilt the dimensions. /// /// @return An isl constraint representing this integer array. isl_constraint *constraintFromMatrixRowFull(isl_int *row, __isl_take isl_space *Space) { isl_constraint *c; unsigned NbOut = isl_space_dim(Space, isl_dim_out); unsigned NbIn = isl_space_dim(Space, isl_dim_in); unsigned NbParam = isl_space_dim(Space, isl_dim_param); isl_local_space *LSpace = isl_local_space_from_space(Space); if (isl_int_is_zero(row[0])) c = isl_equality_alloc(LSpace); else c = isl_inequality_alloc(LSpace); unsigned current_column = 1; for (unsigned j = 0; j < NbOut; ++j) isl_constraint_set_coefficient(c, isl_dim_out, j, row[current_column++]); for (unsigned j = 0; j < NbIn; ++j) isl_constraint_set_coefficient(c, isl_dim_in, j, row[current_column++]); for (unsigned j = 0; j < NbParam; ++j) isl_constraint_set_coefficient(c, isl_dim_param, j, row[current_column++]); isl_constraint_set_constant(c, row[current_column]); return c; }
/* Construct a contraction from "prefix" and "domain" for a new group * in "grouping". * * The values of the prefix schedule "prefix" are used as instances * of the new group. The identifier of the group is constructed * in such a way that it does not conflict with those of earlier * groups nor with statements in the domain of the original * schedule constraints. * The isl_multi_union_pw_aff "prefix" then simply needs to be * converted to an isl_union_pw_multi_aff. However, this is not * possible if "prefix" is zero-dimensional, so in this case, * a contraction is constructed from "domain" instead. */ static isl_union_pw_multi_aff *group_contraction_from_prefix_and_domain( struct ppcg_grouping *grouping, __isl_keep isl_multi_union_pw_aff *prefix, __isl_keep isl_union_set *domain) { isl_id *id; isl_space *space; int dim; space = isl_multi_union_pw_aff_get_space(prefix); if (!space) return NULL; dim = isl_space_dim(space, isl_dim_set); id = construct_group_id(grouping, space); if (dim == 0) { isl_multi_val *mv; space = isl_multi_union_pw_aff_get_space(prefix); space = isl_space_set_tuple_id(space, isl_dim_set, id); mv = isl_multi_val_zero(space); domain = isl_union_set_copy(domain); return isl_union_pw_multi_aff_multi_val_on_domain(domain, mv); } prefix = isl_multi_union_pw_aff_copy(prefix); prefix = isl_multi_union_pw_aff_set_tuple_id(prefix, isl_dim_out, id); return isl_union_pw_multi_aff_from_multi_union_pw_aff(prefix); }
/* Return a function that projects "space" onto its first "n" dimensions, * with anonymous target space. */ __isl_give isl_multi_aff *pet_prefix_projection(__isl_take isl_space *space, int n) { int dim; dim = isl_space_dim(space, isl_dim_set); return isl_multi_aff_project_out_map(space, isl_dim_set, n, dim - n); }
/* Set the arguments of the OpenCL kernel by printing a call to the OpenCL * clSetKernelArg() function for each kernel argument. */ static __isl_give isl_printer *opencl_set_kernel_arguments( __isl_take isl_printer *p, struct gpu_prog *prog, struct ppcg_kernel *kernel) { int i, n, ro; unsigned nparam; isl_space *space; int arg_index = 0; for (i = 0; i < prog->n_array; ++i) { int required; required = ppcg_kernel_requires_array_argument(kernel, i); if (required < 0) return isl_printer_free(p); if (!required) continue; ro = gpu_array_is_read_only_scalar(&prog->array[i]); opencl_set_kernel_argument(p, kernel->id, prog->array[i].name, arg_index, ro); arg_index++; } space = isl_union_set_get_space(kernel->arrays); nparam = isl_space_dim(space, isl_dim_param); for (i = 0; i < nparam; ++i) { const char *name; name = isl_space_get_dim_name(space, isl_dim_param, i); opencl_set_kernel_argument(p, kernel->id, name, arg_index, 1); arg_index++; } isl_space_free(space); n = isl_space_dim(kernel->space, isl_dim_set); for (i = 0; i < n; ++i) { const char *name; name = isl_space_get_dim_name(kernel->space, isl_dim_set, i); opencl_set_kernel_argument(p, kernel->id, name, arg_index, 1); arg_index++; } return p; }
/* Add a specific constraint of bmap (or its opposite) to tab. * The position of the constraint is specified by "c", where * the equalities of bmap are counted twice, once for the inequality * that is equal to the equality, and once for its negation. * * Each of these constraints has been added to "tab" before by * tab_add_constraints (and later removed again), so there should * already be a row available for the constraint. */ static int tab_add_constraint(struct isl_tab *tab, __isl_keep isl_basic_map *bmap, int *div_map, int c, int oppose) { unsigned dim; unsigned tab_total; unsigned bmap_total; isl_vec *v; int r; if (!tab || !bmap) return -1; tab_total = isl_basic_map_total_dim(tab->bmap); bmap_total = isl_basic_map_total_dim(bmap); dim = isl_space_dim(tab->bmap->dim, isl_dim_all); v = isl_vec_alloc(bmap->ctx, 1 + tab_total); if (!v) return -1; if (c < 2 * bmap->n_eq) { if ((c % 2) != oppose) isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2], 1 + bmap_total); if (oppose) isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1); expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div); r = isl_tab_add_ineq(tab, v->el); if (oppose) isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1); if ((c % 2) != oppose) isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2], 1 + bmap_total); } else { c -= 2 * bmap->n_eq; if (oppose) { isl_seq_neg(bmap->ineq[c], bmap->ineq[c], 1 + bmap_total); isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1); } expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div); r = isl_tab_add_ineq(tab, v->el); if (oppose) { isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1); isl_seq_neg(bmap->ineq[c], bmap->ineq[c], 1 + bmap_total); } } isl_vec_free(v); return r; }
/* Add all constraints of bmap to tab. The equalities of bmap * are added as a pair of inequalities. */ static int tab_add_constraints(struct isl_tab *tab, __isl_keep isl_basic_map *bmap, int *div_map) { int i; unsigned dim; unsigned tab_total; unsigned bmap_total; isl_vec *v; if (!tab || !bmap) return -1; tab_total = isl_basic_map_total_dim(tab->bmap); bmap_total = isl_basic_map_total_dim(bmap); dim = isl_space_dim(tab->bmap->dim, isl_dim_all); if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0) return -1; v = isl_vec_alloc(bmap->ctx, 1 + tab_total); if (!v) return -1; for (i = 0; i < bmap->n_eq; ++i) { expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div); if (isl_tab_add_ineq(tab, v->el) < 0) goto error; isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total); expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div); if (isl_tab_add_ineq(tab, v->el) < 0) goto error; isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total); if (tab->empty) break; } for (i = 0; i < bmap->n_ineq; ++i) { expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div); if (isl_tab_add_ineq(tab, v->el) < 0) goto error; if (tab->empty) break; } isl_vec_free(v); return 0; error: isl_vec_free(v); return -1; }
/* Extend length of ids array to the total number of dimensions. */ static __isl_give isl_space *extend_ids(__isl_take isl_space *dim) { isl_id **ids; int i; if (isl_space_dim(dim, isl_dim_all) <= dim->n_id) return dim; if (!dim->ids) { dim->ids = isl_calloc_array(dim->ctx, isl_id *, isl_space_dim(dim, isl_dim_all)); if (!dim->ids) goto error; } else {
/* Extend "set" with unconstrained coordinates to a total length of "dst_len". */ __isl_give isl_set *extend(__isl_take isl_set *set, int dst_len) { int n_set; isl_space *dim; isl_map *map; dim = isl_set_get_space(set); n_set = isl_space_dim(dim, isl_dim_set); dim = isl_space_drop_dims(dim, isl_dim_set, 0, n_set); map = projection(dim, dst_len, n_set); map = isl_map_reverse(map); return isl_set_apply(set, map); }
/* Construct an isl_multi_val living in "space" with all values equal to "val". */ __isl_give isl_multi_val *ppcg_multi_val_from_int(__isl_take isl_space *space, int val) { int i, n; isl_ctx *ctx; isl_val *v; isl_multi_val *mv; if (!space) return NULL; ctx = isl_space_get_ctx(space); n = isl_space_dim(space, isl_dim_set); mv = isl_multi_val_zero(space); v = isl_val_int_from_si(ctx, val); for (i = 0; i < n; ++i) mv = isl_multi_val_set_val(mv, i, isl_val_copy(v)); isl_val_free(v); return mv; }
/* Construct an isl_multi_val living in "space" with values specified * by "list". "list" is assumed to have at least as many entries * as the set dimension of "space". */ __isl_give isl_multi_val *ppcg_multi_val_from_int_list( __isl_take isl_space *space, int *list) { int i, n; isl_ctx *ctx; isl_multi_val *mv; if (!space) return NULL; ctx = isl_space_get_ctx(space); n = isl_space_dim(space, isl_dim_set); mv = isl_multi_val_zero(space); for (i = 0; i < n; ++i) { isl_val *v; v = isl_val_int_from_si(ctx, list[i]); mv = isl_multi_val_set_val(mv, i, v); } return mv; }
static unsigned global_pos(__isl_keep isl_space *dim, enum isl_dim_type type, unsigned pos) { struct isl_ctx *ctx = dim->ctx; switch (type) { case isl_dim_param: isl_assert(ctx, pos < dim->nparam, return isl_space_dim(dim, isl_dim_all)); return pos; case isl_dim_in: isl_assert(ctx, pos < dim->n_in, return isl_space_dim(dim, isl_dim_all)); return pos + dim->nparam; case isl_dim_out: isl_assert(ctx, pos < dim->n_out, return isl_space_dim(dim, isl_dim_all)); return pos + dim->nparam + dim->n_in; default: isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all)); } return isl_space_dim(dim, isl_dim_all); }
/// @brief Create a new scattering for PollyStmt. /// /// @param m The matrix describing the new scattering. /// @param PollyStmt The statement to create the scattering for. /// /// @return An isl_map describing the scattering. isl_map *scatteringForStmt(scoplib_matrix_p m, ScopStmt *PollyStmt, int scatteringDims) { unsigned NbParam = PollyStmt->getNumParams(); unsigned NbIterators = PollyStmt->getNumIterators(); unsigned NbScattering; if (scatteringDims == -1) NbScattering = m->NbColumns - 2 - NbParam - NbIterators; else NbScattering = scatteringDims; isl_ctx *ctx = PollyStmt->getParent()->getIslCtx(); isl_space *Space = isl_dim_alloc(ctx, NbParam, NbIterators, NbScattering); isl_space *ParamSpace = PollyStmt->getParent()->getParamSpace(); // We need to copy the isl_ids for the parameter dimensions to the new // map. Without doing this the current map would have different // ids then the new one, even though both are named identically. for (unsigned i = 0; i < isl_space_dim(Space, isl_dim_param); i++) { isl_id *id = isl_space_get_dim_id(ParamSpace, isl_dim_param, i); Space = isl_space_set_dim_id(Space, isl_dim_param, i, id); } isl_space_free(ParamSpace); Space = isl_space_set_tuple_name(Space, isl_dim_out, "scattering"); Space = isl_space_set_tuple_id(Space, isl_dim_in, PollyStmt->getDomainId()); if (scatteringDims == -1) return mapFromMatrix(m, Space); return mapFromMatrix(m, Space, scatteringDims); }
/* Print the arguments to a kernel declaration or call. If "types" is set, * then print a declaration (including the types of the arguments). * * The arguments are printed in the following order * - the arrays accessed by the kernel * - the parameters * - the host loop iterators */ static __isl_give isl_printer *print_kernel_arguments(__isl_take isl_printer *p, struct gpu_prog *prog, struct ppcg_kernel *kernel, int types) { int i, n; int first = 1; unsigned nparam; isl_space *space; const char *type; for (i = 0; i < prog->n_array; ++i) { int required; required = ppcg_kernel_requires_array_argument(kernel, i); if (required < 0) return isl_printer_free(p); if (!required) continue; if(!print_device_arrays_or_not(&prog->array[i])) continue; if (!first) p = isl_printer_print_str(p, ", "); if (types) p = gpu_array_info_print_declaration_argument(p, &prog->array[i], NULL); else p = gpu_array_info_print_call_argument(p, &prog->array[i]); first = 0; } space = isl_union_set_get_space(kernel->arrays); nparam = isl_space_dim(space, isl_dim_param); for (i = 0; i < nparam; ++i) { const char *name; name = isl_space_get_dim_name(space, isl_dim_param, i); if (!first) p = isl_printer_print_str(p, ", "); if (types) p = isl_printer_print_str(p, "int "); p = isl_printer_print_str(p, name); first = 0; } isl_space_free(space); n = isl_space_dim(kernel->space, isl_dim_set); type = isl_options_get_ast_iterator_type(prog->ctx); for (i = 0; i < n; ++i) { const char *name; if (!first) p = isl_printer_print_str(p, ", "); name = isl_space_get_dim_name(kernel->space, isl_dim_set, i); if (types) { p = isl_printer_print_str(p, type); p = isl_printer_print_str(p, " "); } p = isl_printer_print_str(p, name); first = 0; } return p; }