| //===- ScopLib.cpp - ScopLib interface ------------------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // ScopLib Interface |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "polly/LinkAllPasses.h" |
| |
| #ifdef SCOPLIB_FOUND |
| |
| #include "polly/Dependences.h" |
| #include "polly/ScopLib.h" |
| #include "polly/ScopInfo.h" |
| |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Assembly/Writer.h" |
| |
| #include "stdio.h" |
| #include "isl/set.h" |
| #include "isl/map.h" |
| #include "isl/constraint.h" |
| |
| using namespace llvm; |
| |
| namespace polly { |
| |
| ScopLib::ScopLib(Scop *S) : PollyScop(S) { |
| scoplib = scoplib_scop_malloc(); |
| |
| initializeArrays(); |
| initializeParameters(); |
| initializeScattering(); |
| initializeStatements(); |
| } |
| |
| ScopLib::ScopLib(Scop *S, FILE *F, Dependences *dep) : PollyScop(S), D(dep) { |
| scoplib = scoplib_scop_read(F); |
| } |
| |
| void ScopLib::initializeParameters() { |
| scoplib->nb_parameters = PollyScop->getNumParams(); |
| scoplib->parameters = |
| (char **)malloc(sizeof(char *) * scoplib->nb_parameters); |
| |
| for (int i = 0; i < scoplib->nb_parameters; ++i) { |
| scoplib->parameters[i] = (char *)malloc(sizeof(char *) * 20); |
| sprintf(scoplib->parameters[i], "p_%d", i); |
| } |
| } |
| |
| void ScopLib::initializeArrays() { |
| int nb_arrays = 0; |
| |
| for (Scop::iterator SI = PollyScop->begin(), SE = PollyScop->end(); SI != SE; |
| ++SI) |
| for (ScopStmt::memacc_iterator MI = (*SI)->memacc_begin(), |
| ME = (*SI)->memacc_end(); |
| MI != ME; ++MI) { |
| const Value *BaseAddr = (*MI)->getBaseAddr(); |
| if (ArrayMap.find(BaseAddr) == ArrayMap.end()) { |
| ArrayMap.insert(std::make_pair(BaseAddr, nb_arrays)); |
| ++nb_arrays; |
| } |
| } |
| |
| scoplib->nb_arrays = nb_arrays; |
| scoplib->arrays = (char **)malloc(sizeof(char *) * nb_arrays); |
| |
| for (int i = 0; i < nb_arrays; ++i) |
| for (std::map<const Value *, int>::iterator VI = ArrayMap.begin(), |
| VE = ArrayMap.end(); |
| VI != VE; ++VI) |
| if ((*VI).second == i) { |
| const Value *V = (*VI).first; |
| std::string name = V->getName(); |
| scoplib->arrays[i] = (char *)malloc(sizeof(char *) * (name.size() + 1)); |
| strcpy(scoplib->arrays[i], name.c_str()); |
| } |
| } |
| |
| void ScopLib::initializeScattering() {} |
| |
| scoplib_statement_p ScopLib::initializeStatement(ScopStmt *stmt) { |
| scoplib_statement_p Stmt = scoplib_statement_malloc(); |
| |
| // Domain & Schedule |
| Stmt->domain = scoplib_matrix_list_malloc(); |
| Stmt->domain->elt = domainToMatrix(stmt->getDomain()); |
| Stmt->schedule = scatteringToMatrix(stmt->getScattering()); |
| |
| // Statement name |
| std::string entryName; |
| raw_string_ostream OS(entryName); |
| WriteAsOperand(OS, stmt->getBasicBlock(), false); |
| entryName = OS.str(); |
| Stmt->body = (char *)malloc(sizeof(char) * (entryName.size() + 1)); |
| strcpy(Stmt->body, entryName.c_str()); |
| |
| // Iterator names |
| Stmt->nb_iterators = stmt->getNumIterators(); |
| Stmt->iterators = (char **)malloc(sizeof(char *) * Stmt->nb_iterators); |
| |
| for (int i = 0; i < Stmt->nb_iterators; ++i) { |
| Stmt->iterators[i] = (char *)malloc(sizeof(char *) * 20); |
| sprintf(Stmt->iterators[i], "i_%d", i); |
| } |
| |
| // Memory Accesses |
| Stmt->read = createAccessMatrix(stmt, true); |
| Stmt->write = createAccessMatrix(stmt, false); |
| |
| return Stmt; |
| } |
| |
| void ScopLib::initializeStatements() { |
| for (Scop::reverse_iterator SI = PollyScop->rbegin(), SE = PollyScop->rend(); |
| SI != SE; ++SI) { |
| scoplib_statement_p stmt = initializeStatement(*SI); |
| stmt->next = scoplib->statement; |
| scoplib->statement = stmt; |
| } |
| } |
| |
| void ScopLib::freeStatement(scoplib_statement_p stmt) { |
| |
| if (stmt->read) |
| scoplib_matrix_free(stmt->read); |
| stmt->read = NULL; |
| |
| if (stmt->write) |
| scoplib_matrix_free(stmt->write); |
| stmt->write = NULL; |
| |
| scoplib_matrix_list_p current = stmt->domain; |
| while (current) { |
| scoplib_matrix_list_p next = current->next; |
| current->next = NULL; |
| scoplib_matrix_free(current->elt); |
| current->elt = NULL; |
| scoplib_matrix_list_free(current); |
| current = next; |
| } |
| stmt->domain = NULL; |
| |
| if (stmt->schedule) |
| scoplib_matrix_free(stmt->schedule); |
| stmt->schedule = NULL; |
| |
| for (int i = 0; i < stmt->nb_iterators; ++i) |
| free(stmt->iterators[i]); |
| |
| free(stmt->iterators); |
| stmt->iterators = NULL; |
| stmt->nb_iterators = 0; |
| |
| scoplib_statement_free(stmt); |
| } |
| |
| void ScopLib::print(FILE *F) { scoplib_scop_print_dot_scop(F, scoplib); } |
| |
| /// Add an isl constraint to an ScopLib matrix. |
| /// |
| /// @param user The matrix |
| /// @param c The constraint |
| int ScopLib::domainToMatrix_constraint(isl_constraint *c, void *user) { |
| scoplib_matrix_p m = (scoplib_matrix_p) user; |
| |
| int nb_params = isl_constraint_dim(c, isl_dim_param); |
| int nb_vars = isl_constraint_dim(c, isl_dim_set); |
| int nb_div = isl_constraint_dim(c, isl_dim_div); |
| |
| assert(!nb_div && "Existentially quantified variables not yet supported"); |
| |
| scoplib_vector_p vec = scoplib_vector_malloc(nb_params + nb_vars + 2); |
| |
| // Assign type |
| if (isl_constraint_is_equality(c)) |
| scoplib_vector_tag_equality(vec); |
| else |
| scoplib_vector_tag_inequality(vec); |
| |
| isl_int v; |
| isl_int_init(v); |
| |
| // Assign variables |
| for (int i = 0; i < nb_vars; ++i) { |
| isl_constraint_get_coefficient(c, isl_dim_set, i, &v); |
| isl_int_set(vec->p[i + 1], v); |
| } |
| |
| // Assign parameters |
| for (int i = 0; i < nb_params; ++i) { |
| isl_constraint_get_coefficient(c, isl_dim_param, i, &v); |
| isl_int_set(vec->p[nb_vars + i + 1], v); |
| } |
| |
| // Assign constant |
| isl_constraint_get_constant(c, &v); |
| isl_int_set(vec->p[nb_params + nb_vars + 1], v); |
| |
| scoplib_matrix_insert_vector(m, vec, m->NbRows); |
| |
| scoplib_vector_free(vec); |
| isl_constraint_free(c); |
| isl_int_clear(v); |
| |
| return 0; |
| } |
| |
| /// Add an isl basic set to a ScopLib matrix_list |
| /// |
| /// @param bset The basic set to add |
| /// @param user The matrix list we should add the basic set to |
| /// |
| /// XXX: At the moment this function expects just a matrix, as support |
| /// for matrix lists is currently not available in ScopLib. So union of |
| /// polyhedron are not yet supported |
| int ScopLib::domainToMatrix_basic_set(isl_basic_set *bset, void *user) { |
| scoplib_matrix_p m = (scoplib_matrix_p) user; |
| assert(!m->NbRows && "Union of polyhedron not yet supported"); |
| |
| isl_basic_set_foreach_constraint(bset, &domainToMatrix_constraint, user); |
| isl_basic_set_free(bset); |
| return 0; |
| } |
| |
| /// Translate a isl_set to a ScopLib matrix. |
| /// |
| /// @param PS The set to be translated |
| /// @return A ScopLib Matrix |
| scoplib_matrix_p ScopLib::domainToMatrix(__isl_take isl_set *set) { |
| set = isl_set_compute_divs(set); |
| set = isl_set_align_divs(set); |
| |
| // Initialize the matrix. |
| unsigned NbRows, NbColumns; |
| NbRows = 0; |
| NbColumns = isl_set_n_dim(set) + isl_set_n_param(set) + 2; |
| scoplib_matrix_p matrix = scoplib_matrix_malloc(NbRows, NbColumns); |
| |
| // Copy the content into the matrix. |
| isl_set_foreach_basic_set(set, &domainToMatrix_basic_set, matrix); |
| |
| isl_set_free(set); |
| |
| return matrix; |
| } |
| |
| /// Add an isl constraint to an ScopLib matrix. |
| /// |
| /// @param user The matrix |
| /// @param c The constraint |
| int ScopLib::scatteringToMatrix_constraint(isl_constraint *c, void *user) { |
| scoplib_matrix_p m = (scoplib_matrix_p) user; |
| |
| int nb_params = isl_constraint_dim(c, isl_dim_param); |
| int nb_in = isl_constraint_dim(c, isl_dim_in); |
| int nb_div = isl_constraint_dim(c, isl_dim_div); |
| |
| assert(!nb_div && "Existentially quantified variables not yet supported"); |
| |
| scoplib_vector_p vec = scoplib_vector_malloc(nb_params + nb_in + 2); |
| |
| // Assign type |
| if (isl_constraint_is_equality(c)) |
| scoplib_vector_tag_equality(vec); |
| else |
| scoplib_vector_tag_inequality(vec); |
| |
| isl_int v; |
| isl_int_init(v); |
| |
| // Assign variables |
| for (int i = 0; i < nb_in; ++i) { |
| isl_constraint_get_coefficient(c, isl_dim_in, i, &v); |
| isl_int_set(vec->p[i + 1], v); |
| } |
| |
| // Assign parameters |
| for (int i = 0; i < nb_params; ++i) { |
| isl_constraint_get_coefficient(c, isl_dim_param, i, &v); |
| isl_int_set(vec->p[nb_in + i + 1], v); |
| } |
| |
| // Assign constant |
| isl_constraint_get_constant(c, &v); |
| isl_int_set(vec->p[nb_in + nb_params + 1], v); |
| |
| scoplib_vector_p null = scoplib_vector_malloc(nb_params + nb_in + 2); |
| |
| vec = scoplib_vector_sub(null, vec); |
| scoplib_matrix_insert_vector(m, vec, 0); |
| |
| isl_constraint_free(c); |
| isl_int_clear(v); |
| |
| return 0; |
| } |
| |
| /// Add an isl basic map to a ScopLib matrix_list |
| /// |
| /// @param bmap The basic map to add |
| /// @param user The matrix list we should add the basic map to |
| /// |
| /// XXX: At the moment this function expects just a matrix, as support |
| /// for matrix lists is currently not available in ScopLib. So union of |
| /// polyhedron are not yet supported |
| int ScopLib::scatteringToMatrix_basic_map(isl_basic_map *bmap, void *user) { |
| scoplib_matrix_p m = (scoplib_matrix_p) user; |
| assert(!m->NbRows && "Union of polyhedron not yet supported"); |
| |
| isl_basic_map_foreach_constraint(bmap, &scatteringToMatrix_constraint, user); |
| isl_basic_map_free(bmap); |
| return 0; |
| } |
| |
| /// Translate a isl_map to a ScopLib matrix. |
| /// |
| /// @param map The map to be translated |
| /// @return A ScopLib Matrix |
| scoplib_matrix_p ScopLib::scatteringToMatrix(__isl_take isl_map *map) { |
| map = isl_map_compute_divs(map); |
| map = isl_map_align_divs(map); |
| |
| // Initialize the matrix. |
| unsigned NbRows, NbColumns; |
| NbRows = 0; |
| NbColumns = isl_map_n_in(map) + isl_map_n_param(map) + 2; |
| scoplib_matrix_p matrix = scoplib_matrix_malloc(NbRows, NbColumns); |
| |
| // Copy the content into the matrix. |
| isl_map_foreach_basic_map(map, &scatteringToMatrix_basic_map, matrix); |
| |
| // Only keep the relevant rows. |
| scoplib_matrix_p reduced = |
| scoplib_matrix_ncopy(matrix, isl_map_n_in(map) * 2 + 1); |
| |
| scoplib_matrix_free(matrix); |
| isl_map_free(map); |
| |
| return reduced; |
| } |
| |
| /// Add an isl constraint to an ScopLib matrix. |
| /// |
| /// @param user The matrix |
| /// @param c The constraint |
| int ScopLib::accessToMatrix_constraint(isl_constraint *c, void *user) { |
| scoplib_matrix_p m = (scoplib_matrix_p) user; |
| |
| int nb_params = isl_constraint_dim(c, isl_dim_param); |
| int nb_in = isl_constraint_dim(c, isl_dim_in); |
| int nb_div = isl_constraint_dim(c, isl_dim_div); |
| |
| assert(!nb_div && "Existentially quantified variables not yet supported"); |
| |
| scoplib_vector_p vec = scoplib_vector_malloc(nb_params + nb_in + 2); |
| |
| isl_int v; |
| isl_int_init(v); |
| |
| // The access dimension has to be one. |
| isl_constraint_get_coefficient(c, isl_dim_out, 0, &v); |
| assert((isl_int_is_one(v) || isl_int_is_negone(v)) && |
| "Access relations not supported in scoplib"); |
| bool inverse = isl_int_is_one(v); |
| |
| // Assign variables |
| for (int i = 0; i < nb_in; ++i) { |
| isl_constraint_get_coefficient(c, isl_dim_in, i, &v); |
| |
| if (inverse) |
| isl_int_neg(v, v); |
| |
| isl_int_set(vec->p[i + 1], v); |
| } |
| |
| // Assign parameters |
| for (int i = 0; i < nb_params; ++i) { |
| isl_constraint_get_coefficient(c, isl_dim_param, i, &v); |
| |
| if (inverse) |
| isl_int_neg(v, v); |
| |
| isl_int_set(vec->p[nb_in + i + 1], v); |
| } |
| |
| // Assign constant |
| isl_constraint_get_constant(c, &v); |
| |
| if (inverse) |
| isl_int_neg(v, v); |
| |
| isl_int_set(vec->p[nb_in + nb_params + 1], v); |
| |
| scoplib_matrix_insert_vector(m, vec, m->NbRows); |
| |
| isl_constraint_free(c); |
| isl_int_clear(v); |
| |
| return 0; |
| } |
| |
| /// Add an isl basic map to a ScopLib matrix_list |
| /// |
| /// @param bmap The basic map to add |
| /// @param user The matrix list we should add the basic map to |
| /// |
| /// XXX: At the moment this function expects just a matrix, as support |
| /// for matrix lists is currently not available in ScopLib. So union of |
| /// polyhedron are not yet supported |
| int ScopLib::accessToMatrix_basic_map(isl_basic_map *bmap, void *user) { |
| isl_basic_map_foreach_constraint(bmap, &accessToMatrix_constraint, user); |
| isl_basic_map_free(bmap); |
| return 0; |
| } |
| |
| /// Create the memory access matrix for scoplib |
| /// |
| /// @param S The polly statement the access matrix is created for. |
| /// @param isRead Are we looking for read or write accesses? |
| /// @param ArrayMap A map translating from the memory references to the scoplib |
| /// indeces |
| /// |
| /// @return The memory access matrix, as it is required by scoplib. |
| scoplib_matrix_p ScopLib::createAccessMatrix(ScopStmt *S, bool isRead) { |
| |
| unsigned NbColumns = S->getNumIterators() + S->getNumParams() + 2; |
| scoplib_matrix_p m = scoplib_matrix_malloc(0, NbColumns); |
| |
| for (ScopStmt::memacc_iterator MI = S->memacc_begin(), ME = S->memacc_end(); |
| MI != ME; ++MI) |
| if ((*MI)->isRead() == isRead) { |
| // Extract the access function. |
| isl_map *AccessRelation = (*MI)->getAccessRelation(); |
| isl_map_foreach_basic_map(AccessRelation, &accessToMatrix_basic_map, m); |
| isl_map_free(AccessRelation); |
| |
| // Set the index of the memory access base element. |
| std::map<const Value *, int>::iterator BA = |
| ArrayMap.find((*MI)->getBaseAddr()); |
| isl_int_set_si(m->p[m->NbRows - 1][0], (*BA).second + 1); |
| } |
| |
| return m; |
| } |
| |
| ScopLib::~ScopLib() { |
| if (!scoplib) |
| return; |
| |
| // Free array names. |
| for (int i = 0; i < scoplib->nb_arrays; ++i) |
| free(scoplib->arrays[i]); |
| |
| free(scoplib->arrays); |
| scoplib->arrays = NULL; |
| scoplib->nb_arrays = 0; |
| |
| // Free parameters |
| for (int i = 0; i < scoplib->nb_parameters; ++i) |
| free(scoplib->parameters[i]); |
| |
| free(scoplib->parameters); |
| scoplib->parameters = NULL; |
| scoplib->nb_parameters = 0; |
| |
| scoplib_statement_p stmt = scoplib->statement; |
| |
| // Free Statements |
| while (stmt) { |
| scoplib_statement_p TempStmt = stmt->next; |
| stmt->next = NULL; |
| freeStatement(stmt); |
| stmt = TempStmt; |
| } |
| |
| scoplib->statement = NULL; |
| |
| scoplib_scop_free(scoplib); |
| } |
| /// @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 *constraintFromMatrixRow(isl_int *row, |
| __isl_take isl_space *Space) { |
| isl_constraint *c; |
| |
| unsigned NbIn = isl_space_dim(Space, isl_dim_in); |
| unsigned NbParam = isl_space_dim(Space, isl_dim_param); |
| |
| if (isl_int_is_zero(row[0])) |
| c = isl_equality_alloc(isl_local_space_from_space(Space)); |
| else |
| c = isl_inequality_alloc(isl_local_space_from_space(Space)); |
| |
| unsigned current_column = 1; |
| |
| 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; |
| } |
| |
| /// @brief Create an isl map from a OpenScop matrix. |
| /// |
| /// @param m The OpenScop matrix to translate. |
| /// @param Space The dimensions that are contained in the OpenScop matrix. |
| /// |
| /// @return An isl map representing m. |
| isl_map *mapFromMatrix(scoplib_matrix_p m, __isl_take isl_space *Space, |
| unsigned scatteringDims) { |
| isl_basic_map *bmap = isl_basic_map_universe(isl_space_copy(Space)); |
| |
| for (unsigned i = 0; i < m->NbRows; ++i) { |
| isl_constraint *c; |
| |
| c = constraintFromMatrixRow(m->p[i], isl_space_copy(Space)); |
| |
| mpz_t minusOne; |
| mpz_init(minusOne); |
| mpz_set_si(minusOne, -1); |
| isl_constraint_set_coefficient(c, isl_dim_out, i, minusOne); |
| |
| bmap = isl_basic_map_add_constraint(bmap, c); |
| } |
| |
| for (unsigned i = m->NbRows; i < scatteringDims; i++) { |
| isl_constraint *c; |
| |
| c = isl_equality_alloc(isl_local_space_from_space(isl_space_copy(Space))); |
| |
| mpz_t One; |
| mpz_init(One); |
| mpz_set_si(One, 1); |
| isl_constraint_set_coefficient(c, isl_dim_out, i, One); |
| |
| bmap = isl_basic_map_add_constraint(bmap, c); |
| } |
| |
| isl_space_free(Space); |
| |
| return isl_map_from_basic_map(bmap); |
| } |
| /// @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; |
| } |
| |
| /// @brief Create an isl map from a OpenScop matrix. |
| /// |
| /// @param m The OpenScop matrix to translate. |
| /// @param Space The dimensions that are contained in the OpenScop matrix. |
| /// |
| /// @return An isl map representing m. |
| isl_map *mapFromMatrix(scoplib_matrix_p m, __isl_take isl_space *Space) { |
| isl_basic_map *bmap = isl_basic_map_universe(isl_space_copy(Space)); |
| |
| for (unsigned i = 0; i < m->NbRows; ++i) { |
| isl_constraint *c; |
| |
| c = constraintFromMatrixRowFull(m->p[i], isl_space_copy(Space)); |
| bmap = isl_basic_map_add_constraint(bmap, c); |
| } |
| |
| isl_space_free(Space); |
| |
| return isl_map_from_basic_map(bmap); |
| } |
| |
| /// @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); |
| } |
| |
| unsigned maxScattering(scoplib_statement_p stmt) { |
| unsigned max = 0; |
| |
| while (stmt) { |
| max = std::max(max, stmt->schedule->NbRows); |
| stmt = stmt->next; |
| } |
| |
| return max; |
| } |
| |
| typedef Dependences::StatementToIslMapTy StatementToIslMapTy; |
| |
| void freeStmtToIslMap(StatementToIslMapTy *Map) { |
| for (StatementToIslMapTy::iterator MI = Map->begin(), ME = Map->end(); |
| MI != ME; ++MI) |
| isl_map_free(MI->second); |
| |
| delete (Map); |
| } |
| |
| /// @brief Read the new scattering from the scoplib description. |
| /// |
| /// @S The Scop to update |
| /// @OScop The ScopLib data structure describing the new scattering. |
| /// @return A map that contains for each Statement the new scattering. |
| StatementToIslMapTy *readScattering(Scop *S, scoplib_scop_p OScop) { |
| StatementToIslMapTy &NewScattering = *(new StatementToIslMapTy()); |
| |
| scoplib_statement_p stmt = OScop->statement; |
| |
| // Check if we have dimensions for each scattering or if each row |
| // represents a scattering dimension. |
| int numScatteringDims = -1; |
| ScopStmt *pollyStmt = *S->begin(); |
| |
| if (stmt->schedule->NbColumns == |
| 2 + pollyStmt->getNumParams() + pollyStmt->getNumIterators()) { |
| numScatteringDims = maxScattering(stmt); |
| } |
| |
| for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) { |
| if (!stmt) { |
| errs() << "Not enough statements available in OpenScop file\n"; |
| freeStmtToIslMap(&NewScattering); |
| return NULL; |
| } |
| |
| NewScattering[*SI] = |
| scatteringForStmt(stmt->schedule, *SI, numScatteringDims); |
| stmt = stmt->next; |
| } |
| |
| if (stmt) { |
| errs() << "Too many statements in OpenScop file\n"; |
| freeStmtToIslMap(&NewScattering); |
| return NULL; |
| } |
| |
| return &NewScattering; |
| } |
| |
| /// @brief Update the scattering in a Scop using the scoplib description of |
| /// the scattering. |
| bool ScopLib::updateScattering() { |
| if (!scoplib) |
| return false; |
| |
| StatementToIslMapTy *NewScattering = readScattering(PollyScop, scoplib); |
| |
| if (!NewScattering) |
| return false; |
| |
| if (!D->isValidScattering(NewScattering)) { |
| freeStmtToIslMap(NewScattering); |
| errs() << "OpenScop file contains a scattering that changes the " |
| << "dependences. Use -disable-polly-legality to continue anyways\n"; |
| return false; |
| } |
| |
| for (Scop::iterator SI = PollyScop->begin(), SE = PollyScop->end(); SI != SE; |
| ++SI) { |
| ScopStmt *Stmt = *SI; |
| |
| if (NewScattering->find(Stmt) != NewScattering->end()) |
| Stmt->setScattering(isl_map_copy((*NewScattering)[Stmt])); |
| } |
| |
| freeStmtToIslMap(NewScattering); |
| return true; |
| } |
| } |
| |
| #endif |