/* * Converts a PIP quast to a union of polyhedra */ osl_relation_p pip_quast_to_polyhedra(PipQuast *quast, int nvar, int npar) { // originaly used for lastwriter // july 5th 2012 : extracted from dependence.c osl_relation_p ep; osl_relation_p tp; osl_relation_p qp; osl_relation_p iter; int precision; int j; if (quast == NULL) return NULL; #if defined(CANDL_LINEAR_VALUE_IS_INT) precision = OSL_PRECISION_SP; #elif defined(CANDL_LINEAR_VALUE_IS_LONGLONG) precision = OSL_PRECISION_DP; #elif defined(CANDL_LINEAR_VALUE_IS_MP) precision = OSL_PRECISION_MP; #endif if (quast->condition != NULL) { tp = pip_quast_to_polyhedra(quast->next_then, nvar, npar); ep = pip_quast_to_polyhedra(quast->next_else, nvar, npar); /* Each of the matrices in the then tree needs to be augmented with * the condition */ for (iter = tp ; iter != NULL ; iter = iter->next) { int nrows = iter->nb_rows; osl_int_set_si(precision, &iter->m[nrows][0], 1); for (j = 1; j < 1 + nvar; j++) osl_int_set_si(precision, &iter->m[nrows][j], 0); for (j = 0; j < npar + 1; j++) osl_int_set_si(precision, &iter->m[nrows][1 + nvar + j], CANDL_get_si(quast->condition->the_vector[j])); (iter->nb_rows)++; } /* JP : july 5th 2012: * Fix negation of a constraint in adding -1 to the constant */ for (iter = ep; iter != NULL ; iter = iter->next) { int nrows = iter->nb_rows; /* Inequality */ osl_int_set_si(precision, &iter->m[nrows][0], 5); for (j = 1; j < 1 + nvar; j++) osl_int_set_si(precision, &iter->m[nrows][j], 0); for (j = 0; j < npar + 1; j++) osl_int_set_si(precision, &iter->m[nrows][1 + nvar + j], -CANDL_get_si(quast->condition->the_vector[j])); osl_int_decrement(precision, &iter->m[nrows][iter->nb_columns - 1], iter->m[nrows][iter->nb_columns - 1]); (iter->nb_rows)++; } /* union of tp and ep */ if (tp) { qp = tp; for (iter = tp ; iter->next != NULL ; iter = iter->next) ; iter->next = ep; } else { qp = ep; } return qp; } else { /* quast condition is NULL */ osl_relation_p lwmatrix = osl_relation_pmalloc(precision, nvar+npar+1, nvar+npar+2); PipList *vecList = quast->list; int count=0; while (vecList != NULL) { /* Equality */ osl_int_set_si(precision, &lwmatrix->m[count][0], 0); for (j=0; j < nvar; j++) if (j == count) osl_int_set_si(precision, &lwmatrix->m[count][j + 1], 1); else osl_int_set_si(precision, &lwmatrix->m[count][j + 1], 0); for (j=0; j < npar; j++) osl_int_set_si(precision, &lwmatrix->m[count][j + 1 + nvar], -CANDL_get_si(vecList->vector->the_vector[j])); /* Constant portion */ if (quast->newparm != NULL) /* Don't handle newparm for now */ osl_int_set_si(precision, &lwmatrix->m[count][npar + 1 + nvar], -CANDL_get_si(vecList->vector->the_vector[npar+1])); else osl_int_set_si(precision, &lwmatrix->m[count][npar + 1 + nvar], -CANDL_get_si(vecList->vector->the_vector[npar])); count++; vecList = vecList->next; } lwmatrix->nb_rows = count; lwmatrix->nb_parameters = npar; return lwmatrix; } }
candl_program_p candl_program_convert_scop(scoplib_scop_p scop, int** indices) { int i, j, k, l; candl_program_p res = candl_program_malloc(); scoplib_statement_p s = scop->statement; /* Duplicate the context. */ res->context = (CandlMatrix*) scoplib_matrix_copy(scop->context); if (res->context == NULL) res->context = candl_matrix_malloc(0, 2); /* Count the number of statements. */ for (res->nb_statements = 0; s; s = s->next, res->nb_statements++) ; /* Allocate the statements array. */ res->statement = (CandlStatement**) malloc(res->nb_statements * sizeof(CandlStatement*)); /* Initialize structures used in iterator indices computation. */ int max = 0; int max_loop_depth = 128; int cur_index[max_loop_depth]; int last[max_loop_depth]; for (i = 0; i < max_loop_depth; ++i) { cur_index[i] = i; last[i] = 0; } /* Create the statements. */ for (i = 0, s = scop->statement; s; s = s->next, ++i) { CandlStatement* statement = candl_statement_malloc(); statement->label = i; statement->ref = s; if (s->domain->next != NULL) CANDL_FAIL("Error: union of domains not supported"); statement->domain = (CandlMatrix*) scoplib_matrix_copy(s->domain->elt); /* For the moment, we do not parse the statement to extract its type. */ statement->type = CANDL_ASSIGNMENT; statement->depth = statement->domain->NbColumns - 2 - scop->nb_parameters; statement->written = (CandlMatrix*) scoplib_matrix_copy(s->write); if (statement->written == NULL) statement->written = candl_matrix_malloc(0, statement->domain->NbColumns); statement->read = (CandlMatrix*) scoplib_matrix_copy(s->read); if (statement->read == NULL) statement->read = candl_matrix_malloc(0, statement->domain->NbColumns); statement->index = (int*) malloc(statement->depth * sizeof(int)); if (indices != NULL) /* Iterator indices are provided. */ for (j = 0; j < statement->depth; ++j) statement->index[j] = indices[i][j]; else { /* Iterator indices must be computed from the scattering matrix. */ scoplib_matrix_p m = s->schedule; if (m == NULL) CANDL_FAIL("Error: No scheduling matrix and no loop " "indices specification"); /* FIXME: Sort the statements in their execution order. */ /* It must be a 2d+1 identity scheduling matrix, and statements must be sorted in their execution order. */ /* Check that it is a identity matrix. */ int error = 0; if (m->NbRows != 2 * statement->depth + 1) error = 1; /*else for (l = 0; l < m->NbRows; ++l) { for (k = 1; k < m->NbColumns - 1; ++k){ switch (CANDL_get_si(m->p[l][k])) { case 0: if (l % 2 && k == (l / 2) + 1) error = 1; break; case 1: if ((l % 2 && k != (l / 2) + 1) || (! l % 2)) error = 1; break; default: error = 1; break; } } if (l % 2 && CANDL_get_si(m->p[l][k])) error = 1; }*/ if (error) CANDL_FAIL("Error: schedule is not identity 2d+1 shaped.\n" "Consider using the <indices> option tag to declare " " iterator indices"); /* Compute the value of the iterator indices. */ for (j = 0; j < statement->depth; ++j) { int val = CANDL_get_si(m->p[2 * j][m->NbColumns - 1]); if (last[j] < val) { last[j] = val; for (k = j + 1; k < max_loop_depth; ++k) last[k] = 0; for (k = j; k < max_loop_depth; ++k) cur_index[k] = max + (k - j) + 1; break; } } for (j = 0; j < statement->depth; ++j) statement->index[j] = cur_index[j]; max = max < cur_index[j - 1] ? cur_index[j - 1] : max; } /* Store the statement. */ res->statement[i] = statement; } return res; }
/* * Converts all conditions where the path does not lead to a solution * The return is a upip_quast_to_polyhedranion of polyhedra * extracted from pip_quast_to_polyhedra */ osl_relation_p pip_quast_no_solution_to_polyhedra(PipQuast *quast, int nvar, int npar) { osl_relation_p ep; osl_relation_p tp; osl_relation_p qp; osl_relation_p iter; int precision; int j; if (quast == NULL) return NULL; #if defined(CANDL_LINEAR_VALUE_IS_INT) precision = OSL_PRECISION_SP; #elif defined(CANDL_LINEAR_VALUE_IS_LONGLONG) precision = OSL_PRECISION_DP; #elif defined(CANDL_LINEAR_VALUE_IS_MP) precision = OSL_PRECISION_MP; #endif if (quast->condition != NULL) { tp = pip_quast_no_solution_to_polyhedra(quast->next_then, nvar, npar); ep = pip_quast_no_solution_to_polyhedra(quast->next_else, nvar, npar); /* Each of the matrices in the then tree needs to be augmented with * the condition */ for (iter = tp ; iter != NULL ; iter = iter->next) { int nrows = iter->nb_rows; osl_int_set_si(precision, &iter->m[nrows][0], 1); for (j = 1; j < 1 + nvar; j++) osl_int_set_si(precision, &iter->m[nrows][j], 0); for (j = 0; j < npar + 1; j++) osl_int_set_si(precision, &iter->m[nrows][1 + nvar + j], CANDL_get_si(quast->condition->the_vector[j])); (iter->nb_rows)++; } for (iter = ep; iter != NULL ; iter = iter->next) { int nrows = iter->nb_rows; /* Inequality */ osl_int_set_si(precision, &iter->m[nrows][0], 1); for (j = 1; j < 1 + nvar; j++) osl_int_set_si(precision, &iter->m[nrows][j], 0); for (j = 0; j < npar + 1; j++) osl_int_set_si(precision, &iter->m[nrows][1 + nvar + j], -CANDL_get_si(quast->condition->the_vector[j])); osl_int_decrement(precision, &iter->m[nrows][iter->nb_columns - 1], iter->m[nrows][iter->nb_columns - 1]); (iter->nb_rows)++; } /* union of tp and ep */ if (tp) { qp = tp; for (iter = tp ; iter->next != NULL ; iter = iter->next) ; iter->next = ep; } else { qp = ep; } return qp; } if (quast->list != NULL) return NULL; /* quast condition is NULL */ osl_relation_p lwmatrix = osl_relation_pmalloc(precision, nvar+npar+1, nvar+npar+2); lwmatrix->nb_rows = 0; lwmatrix->nb_parameters = npar; return lwmatrix; }
/** * candl_ddv_constant_val: returns true iff all possible values of the * minimization of the first variable of the system is a scalar constant * (not parametric), and has the same value for all conditions of the QUAST. * The scalar constant is put in the 'val' argument. * */ static int candl_ddv_constant_val(osl_relation_p system, int* val, int nb_par) { PipOptions * options; PipQuast * solution; osl_relation_p context; int is_constant_val = 1; int cst; int cst_base = 42; int first = 1; int i, j; int precision = system->precision; // 1- Comute the lexmin of the system, to get a QUAST. options = pip_options_init(); options->Simplify = 1; options->Urs_parms = -1; options->Urs_unknowns = -1; options->Nq = 0; context = osl_relation_pmalloc(precision, 0, nb_par + 2); solution = pip_solve_osl(system, context, -1, options); if ((solution != NULL) && ((solution->list != NULL) || (solution->condition != NULL))) { // 2- Traverse all leaves, ensure they have the same value. int nb_leaves = count_quast_leaves(solution); PipList* leaveslist[nb_leaves + 1]; for (i = 0; i < nb_leaves + 1; ++i) leaveslist[i] = NULL; get_quast_leaves(solution, leaveslist); for (i = 0; i < nb_leaves; ++i) { PipList* list = leaveslist[i]; if (list && list->vector) { PipVector* vect = list->vector; // FIXME : check if precision is correct to use piplib for (j = 0; j < nb_par; ++j) if (!CANDL_zero_p(vect->the_vector[j])) { is_constant_val = 0; break; } if (is_constant_val) { cst = CANDL_get_si(vect->the_vector[vect->nb_elements-1]); if (first) { first = 0; cst_base = cst; } else if (! first && cst != cst_base) { is_constant_val = 0; break; } } else break; } } } pip_quast_free(solution); pip_options_free(options); osl_relation_free(context); if (is_constant_val) *val = cst_base; return is_constant_val; }