Clan
0.8.0
|
00001 00002 /*+------- <| --------------------------------------------------------** 00003 ** A Clan ** 00004 **--- /.\ -----------------------------------------------------** 00005 ** <| [""M# relation.c ** 00006 **- A | # -----------------------------------------------------** 00007 ** /.\ [""M# First version: 30/04/2008 ** 00008 **- [""M# | # U"U#U -----------------------------------------------** 00009 | # | # \ .:/ 00010 | # | #___| # 00011 ****** | "--' .-" ****************************************************** 00012 * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * 00013 **** | # ## ###### ***************************************************** 00014 * \ .::::'/ * 00015 * \ ::::'/ Copyright (C) 2008 University Paris-Sud 11 * 00016 * :8a| # # ## * 00017 * ::88a ### This is free software; you can redistribute it * 00018 * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * 00019 * ::::::::888a88a[]::: General Public License as published by the Free * 00020 *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * 00021 *::::::::8::::888:Y8888:: License, or (at your option) any later version. * 00022 *::::':::88::::888::Y88a::::::::::::... * 00023 *::'::.. . ..... .. ... . * 00024 * This software is distributed in the hope that it will be useful, but * 00025 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * 00026 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * 00027 * for more details. * 00028 * * 00029 * You should have received a copy of the GNU Lesser General Public License * 00030 * along with software; if not, write to the Free Software Foundation, Inc., * 00031 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 00032 * * 00033 * Clan, the Chunky Loop Analyzer * 00034 * Written by Cedric Bastoul, Cedric.Bastoul@u-psud.fr * 00035 * * 00036 ******************************************************************************/ 00037 00038 00039 #include <stdlib.h> 00040 #include <stdio.h> 00041 #include <string.h> 00042 #include <ctype.h> 00043 00044 #include <osl/macros.h> 00045 #include <osl/int.h> 00046 #include <osl/relation.h> 00047 #include <clan/macros.h> 00048 #include <clan/options.h> 00049 #include <clan/relation.h> 00050 00051 int clan_parser_nb_ld(void); 00052 void clan_parser_add_ld(void); 00053 00054 00055 /*+**************************************************************************** 00056 * Processing functions * 00057 ******************************************************************************/ 00058 00059 00071 void clan_relation_tag_array(osl_relation_p relation, int array) { 00072 if (relation == NULL) 00073 CLAN_error("relation cannot be array-tagged"); 00074 00075 osl_relation_insert_blank_row(relation, 0); 00076 osl_relation_insert_blank_column(relation, 1); 00077 osl_int_set_si(relation->precision, &relation->m[0][1], -1); 00078 osl_int_set_si(relation->precision, 00079 &relation->m[0][relation->nb_columns - 1], array); 00080 relation->nb_output_dims++; 00081 } 00082 00083 00093 osl_relation_p clan_relation_build_context(int nb_parameters, 00094 clan_options_p options) { 00095 int i; 00096 osl_relation_p context = NULL; 00097 00098 if (options->bounded_context) { 00099 context = osl_relation_pmalloc(options->precision, 00100 nb_parameters, nb_parameters + 2); 00101 for (i = 0; i < nb_parameters; i++) { 00102 osl_int_set_si(options->precision, &context->m[i][0], 1); 00103 osl_int_set_si(options->precision, &context->m[i][i + 1], 1); 00104 osl_int_set_si(options->precision, 00105 &context->m[i][context->nb_columns - 1], 1); 00106 } 00107 } else { 00108 context = osl_relation_pmalloc(options->precision, 0, nb_parameters + 2); 00109 } 00110 osl_relation_set_type(context, OSL_TYPE_CONTEXT); 00111 osl_relation_set_attributes(context, 0, 0, 0, nb_parameters); 00112 return context; 00113 } 00114 00115 00133 osl_relation_p clan_relation_scattering(int* vector, int depth, 00134 int precision) { 00135 int i, j, nb_rows, nb_columns; 00136 int beta_col, alpha_col; 00137 osl_relation_p scattering; 00138 00139 nb_rows = (2 * depth + 1); 00140 nb_columns = (2 * depth + 1) + (depth) + (CLAN_MAX_PARAMETERS) + 2; 00141 scattering = osl_relation_pmalloc(precision, nb_rows, nb_columns); 00142 osl_relation_set_type(scattering, OSL_TYPE_SCATTERING); 00143 osl_relation_set_attributes(scattering, 2 * depth + 1, depth, 0, 00144 CLAN_MAX_PARAMETERS); 00145 00146 // The output dimension identity 00147 for (i = 0; i < 2 * depth + 1; i++) 00148 osl_int_set_si(precision, &scattering->m[i][i + 1], -1); 00149 00150 // The beta and alpha. 00151 j = 0; 00152 beta_col = nb_columns - 1; 00153 for (i = 0; i < depth; i++) { 00154 alpha_col = (2 * depth + 1) + i + 1; 00155 osl_int_set_si(precision, &scattering->m[j][beta_col], vector[j]); 00156 osl_int_set_si(precision, &scattering->m[j+1][alpha_col], vector[j+1]); 00157 j += 2; 00158 } 00159 osl_int_set_si(precision, &scattering->m[nb_rows-1][beta_col], vector[j]); 00160 00161 return scattering; 00162 } 00163 00164 00175 void clan_relation_new_output_vector(osl_relation_p relation, 00176 osl_vector_p vector) { 00177 int i, new_col, new_row; 00178 00179 if (relation == NULL) 00180 CLAN_error("cannot add a new output dimension to a NULL relation"); 00181 else if (vector == NULL) 00182 CLAN_error("cannot add a NULL expression of an output dimension"); 00183 else if (relation->precision != vector->precision) 00184 CLAN_error("incompatible precisions"); 00185 00186 if (relation->nb_output_dims == OSL_UNDEFINED) 00187 new_col = 1; 00188 else 00189 new_col = relation->nb_output_dims + 1; 00190 new_row = relation->nb_rows; 00191 00192 if ((relation->nb_columns - (new_col - 1)) != vector->size) 00193 CLAN_error("incompatible sizes"); 00194 else if (!osl_int_zero(vector->precision, vector->v[0])) 00195 CLAN_error("the output dimension expression should be an equality"); 00196 00197 // Prepare the space for the new output dimension and the vector. 00198 osl_relation_insert_blank_column(relation, new_col); 00199 osl_relation_insert_blank_row(relation, new_row); 00200 relation->nb_output_dims = new_col; 00201 00202 // Insert the new output dimension. 00203 osl_int_set_si(relation->precision, &relation->m[new_row][new_col], -1); 00204 for (i = 1; i < vector->size; i++) 00205 osl_int_assign(relation->precision, 00206 &relation->m[new_row][new_col + i], vector->v[i]); 00207 } 00208 00209 00220 void clan_relation_new_output_scalar(osl_relation_p relation, int scalar) { 00221 int new_col, new_row; 00222 00223 if (relation == NULL) 00224 CLAN_error("cannot add a new output dimension to a NULL relation"); 00225 00226 if (relation->nb_output_dims == OSL_UNDEFINED) 00227 new_col = 1; 00228 else 00229 new_col = relation->nb_output_dims + 1; 00230 new_row = relation->nb_rows; 00231 00232 // Prepare the space for the new output dimension and the vector. 00233 osl_relation_insert_blank_column(relation, new_col); 00234 osl_relation_insert_blank_row(relation, new_row); 00235 relation->nb_output_dims = new_col; 00236 00237 // Insert the new output dimension. 00238 osl_int_set_si(relation->precision, &relation->m[new_row][new_col], -1); 00239 osl_int_set_si(relation->precision, 00240 &relation->m[new_row][relation->nb_columns - 1], scalar); 00241 } 00242 00243 00253 void clan_relation_compact(osl_relation_p relation, 00254 int nb_parameters) { 00255 int i, j, nb_columns; 00256 int nb_output_dims, nb_input_dims, nb_local_dims, nb_out_in_loc; 00257 osl_relation_p compacted; 00258 00259 while (relation != NULL) { 00260 nb_output_dims = relation->nb_output_dims; 00261 nb_input_dims = relation->nb_input_dims; 00262 nb_local_dims = relation->nb_local_dims; 00263 nb_out_in_loc = nb_output_dims + nb_input_dims + nb_local_dims; 00264 00265 nb_columns = nb_out_in_loc + nb_parameters + 2; 00266 compacted = osl_relation_pmalloc(relation->precision, 00267 relation->nb_rows, nb_columns); 00268 00269 for (i = 0; i < relation->nb_rows; i++) { 00270 // We copy the equ/inequ tag, the output and input coefficients. 00271 for (j = 0; j <= nb_output_dims + nb_input_dims; j++) 00272 osl_int_assign(relation->precision, 00273 &compacted->m[i][j], relation->m[i][j]); 00274 00275 // Then we copy the local dimension coefficients. 00276 for (j = 0; j < nb_local_dims; j++) 00277 osl_int_assign(relation->precision, 00278 &compacted->m[i][nb_output_dims + nb_input_dims + 1 + j], 00279 relation->m[i][CLAN_MAX_DEPTH + 1 + j]); 00280 00281 // Then we copy the parameter coefficients. 00282 for (j = 0; j < nb_parameters; j++) 00283 osl_int_assign(relation->precision, 00284 &compacted->m[i][j + nb_out_in_loc + 1], 00285 relation->m[i][relation->nb_columns - CLAN_MAX_PARAMETERS -1 + j]); 00286 00287 // Lastly the scalar coefficient. 00288 osl_int_assign(relation->precision, 00289 &compacted->m[i][nb_columns - 1], 00290 relation->m[i][relation->nb_columns - 1]); 00291 } 00292 00293 osl_relation_free_inside(relation); 00294 00295 // Replace the inside of relation. 00296 relation->nb_rows = compacted->nb_rows; 00297 relation->nb_columns = compacted->nb_columns; 00298 relation->m = compacted->m; 00299 relation->nb_parameters = nb_parameters; 00300 00301 // Free the compacted "container". 00302 free(compacted); 00303 00304 relation = relation->next; 00305 } 00306 } 00307 00308 00332 osl_relation_p clan_relation_greater(osl_relation_p min, osl_relation_p max, 00333 int strict) { 00334 int imin, imax, j, precision; 00335 int a, b; 00336 osl_relation_p r; 00337 osl_int_t b_min, a_max; 00338 00339 if ((min == NULL) || (max == NULL) || (strict < 0) || (strict > 1) || 00340 (min->nb_columns != max->nb_columns)) 00341 CLAN_error("cannot compose relations"); 00342 00343 precision = min->precision; 00344 osl_int_init(precision, &a_max); 00345 osl_int_init(precision, &b_min); 00346 r = osl_relation_pmalloc(precision, 00347 min->nb_rows * max->nb_rows, min->nb_columns); 00348 00349 // For each row of min 00350 for (imin = 0; imin < min->nb_rows; imin++) { 00351 // For each row of max 00352 // We have a couple min/a >= max/b to translate to b*min - a*max >= 0 00353 // or a couple min/a > max/b to translate to b*min - a*max - 1 >= 0 00354 // TODO: here a and b are > 0, this may be generalized to avoid a 00355 // problem if the grammar is updated. Plus it's debatable to use 00356 // b*min - a*max -a*b >= 0 in the second case. 00357 00358 // -1. Find a 00359 a = osl_int_get_si(precision, min->m[imin][0]); 00360 a = (a == 0) ? 1 : a; 00361 00362 for (imax = 0; imax < max->nb_rows; imax++) { 00363 // -2. Find b 00364 b = osl_int_get_si(precision, max->m[imax][0]); 00365 b = (b == 0) ? 1 : b; 00366 00367 // -3. Compute b*min - a*max to the new relation. 00368 for (j = 1; j < max->nb_columns; j++) { 00369 // -3.1. Compute b*min 00370 osl_int_mul_si(precision, &b_min, min->m[imin][j], b); 00371 00372 // -3.2. Compute a*max 00373 osl_int_mul_si(precision, &a_max, max->m[imax][j], a); 00374 00375 // -3.3. Compute b*min - a*max 00376 osl_int_sub(precision, 00377 &r->m[imin * max->nb_rows + imax][j], b_min, a_max); 00378 } 00379 00380 // -4. Add -1 if the condition is min/a > max/b, add 0 otherwise. 00381 osl_int_add_si(precision, 00382 &r->m[imin * max->nb_rows + imax][max->nb_columns - 1], 00383 r->m[imin * max->nb_rows + imax][max->nb_columns - 1], 00384 -strict); 00385 // -5. Set the equality/inequality marker to inequality. 00386 osl_int_set_si(precision, &r->m[imin * max->nb_rows + imax][0], 1); 00387 } 00388 } 00389 00390 osl_int_clear(precision, &a_max); 00391 osl_int_clear(precision, &b_min); 00392 return r; 00393 } 00394 00395 00404 static 00405 void clan_relation_negate_inequality(osl_relation_p relation, int row) { 00406 int i; 00407 00408 // Oppose all constraint elements. 00409 for (i = 1; i < relation->nb_columns; i++) 00410 osl_int_oppose(relation->precision, 00411 &relation->m[row][i], relation->m[row][i]); 00412 00413 // The constant term - 1. 00414 osl_int_decrement(relation->precision, 00415 &relation->m[row][relation->nb_columns - 1], 00416 relation->m[row][relation->nb_columns - 1]); 00417 } 00418 00419 00429 static 00430 osl_relation_p clan_relation_extract_constraint(osl_relation_p relation, 00431 int row) { 00432 int i, precision = relation->precision; 00433 osl_relation_p constraint; 00434 00435 constraint = osl_relation_pmalloc(precision, 1, relation->nb_columns); 00436 constraint->type = relation->type; 00437 constraint->nb_output_dims = relation->nb_output_dims; 00438 constraint->nb_input_dims = relation->nb_input_dims; 00439 constraint->nb_local_dims = relation->nb_local_dims; 00440 constraint->nb_parameters = relation->nb_parameters; 00441 00442 for (i = 0; i < relation->nb_columns; i++) 00443 osl_int_assign(precision, &constraint->m[0][i], relation->m[row][i]); 00444 00445 return constraint; 00446 } 00447 00448 00458 static 00459 int clan_relation_is_equality(osl_relation_p relation, int row) { 00460 00461 return (osl_int_zero(relation->precision, relation->m[row][0])) ? 1 : 0; 00462 } 00463 00464 00474 static 00475 void clan_relation_tag_inequality(osl_relation_p relation, int row) { 00476 if ((relation == NULL) || (relation->nb_rows < row)) 00477 CLAN_error("the constraint cannot be inquality-tagged"); 00478 osl_int_set_si(relation->precision, &relation->m[row][0], 1); 00479 } 00480 00481 00491 static 00492 void clan_relation_tag_equality(osl_relation_p relation, int row) { 00493 if ((relation == NULL) || (relation->nb_rows < row)) 00494 CLAN_error("the constraint cannot be equality-tagged"); 00495 osl_int_set_si(relation->precision, &relation->m[row][0], 0); 00496 } 00497 00498 00507 static 00508 osl_relation_p clan_relation_constraint_not(osl_relation_p relation, int row) { 00509 osl_relation_p tmp, tmp_eq = NULL; 00510 00511 if (row > relation->nb_rows) 00512 return NULL; 00513 00514 // Extract the constraint. 00515 tmp = clan_relation_extract_constraint(relation, row); 00516 00517 // Negate it (inequality-style): a >= 0 becomes a < 0, i.e., -a - 1 >= 0. 00518 clan_relation_negate_inequality(tmp, 0); 00519 00520 // If the constraint is an equality we need to build an union. 00521 // a == 0 becomes a > 0 || a < 0, i.e., a - 1 >= 0 || -a - 1 >= 0. 00522 if (clan_relation_is_equality(relation, row)) { 00523 00524 tmp_eq = clan_relation_extract_constraint(relation, row); 00525 osl_int_decrement(relation->precision, 00526 &tmp_eq->m[0][tmp_eq->nb_columns - 1], 00527 tmp_eq->m[0][tmp_eq->nb_columns - 1]); 00528 00529 // Set the two constraints as inequalities and build the union. 00530 clan_relation_tag_inequality(tmp, 0); 00531 clan_relation_tag_inequality(tmp_eq, 0); 00532 tmp->next = tmp_eq; 00533 } 00534 00535 return tmp; 00536 } 00537 00538 00545 osl_relation_p clan_relation_not(osl_relation_p relation) { 00546 int i; 00547 osl_relation_p not_constraint; 00548 osl_relation_p not = NULL, part; 00549 00550 while (relation != NULL) { 00551 // Build the negation of one relation union part. 00552 part = NULL; 00553 for (i = 0; i < relation->nb_rows; i++) { 00554 not_constraint = clan_relation_constraint_not(relation, i); 00555 osl_relation_add(&part, not_constraint); 00556 } 00557 00558 // AND it to the previously negated parts. 00559 if (not == NULL) { 00560 not = part; 00561 } else { 00562 clan_relation_and(not, part); 00563 osl_relation_free(part); 00564 } 00565 relation = relation->next; 00566 } 00567 00568 return not; 00569 } 00570 00571 00580 void clan_relation_and(osl_relation_p dest, osl_relation_p src) { 00581 osl_relation_p next_dest, 00582 next_src, 00583 dup_dest, 00584 next_mem = NULL; 00585 00586 // initializing 00587 next_src = src; 00588 next_dest = dest; 00589 dup_dest = osl_relation_clone(dest); 00590 if (dest == NULL || src == NULL) 00591 return; 00592 00593 // For each union 00594 while (next_src != NULL) { 00595 // Add in each unions 00596 while(next_dest != NULL) { 00597 osl_relation_insert_constraints(next_dest, next_src, next_dest->nb_rows); 00598 next_mem = next_dest; 00599 next_dest = next_dest->next; 00600 } 00601 if (next_src->next != NULL) 00602 next_mem->next = osl_relation_clone(dup_dest); 00603 else 00604 next_mem->next = NULL; 00605 00606 // Next union 00607 next_src = next_src->next; 00608 next_dest = next_mem->next; 00609 } 00610 osl_relation_free(dup_dest); 00611 } 00612 00613 00621 int clan_relation_existential(osl_relation_p relation) { 00622 int i, j; 00623 00624 while (relation != NULL) { 00625 for (i = 0; i < relation->nb_rows; i++) { 00626 for (j = CLAN_MAX_DEPTH + 1; 00627 j < CLAN_MAX_DEPTH + CLAN_MAX_LOCAL_DIMS + 1; 00628 j++) { 00629 if (!osl_int_zero(relation->precision, relation->m[i][j])) 00630 return 1; 00631 } 00632 } 00633 relation = relation->next; 00634 } 00635 00636 return 0; 00637 } 00638 00639 00647 void clan_relation_oppose_row(osl_relation_p r, int row) { 00648 int i; 00649 00650 if (r == NULL) 00651 return; 00652 00653 if ((row < 0) || (row >= r->nb_rows)) 00654 CLAN_error("bad row number"); 00655 00656 for (i = 1; i < r->nb_columns; i++) 00657 osl_int_oppose(r->precision, &r->m[row][i], r->m[row][i]); 00658 } 00659 00660 00675 static 00676 void clan_relation_extract_bounding(osl_relation_p r, 00677 osl_relation_p* bound, 00678 osl_relation_p* notbound, 00679 int depth, int lower) { 00680 int i, precision; 00681 osl_relation_p constraint; 00682 00683 if (r == NULL) 00684 return; 00685 00686 if ((depth < 1) || (depth > CLAN_MAX_DEPTH)) 00687 CLAN_error("bad depth"); 00688 00689 if ((lower < 0) || (lower > 1)) 00690 CLAN_error("lower parameter must be 0 or 1"); 00691 00692 // Create two empty sets bound and notbound. 00693 precision = r->precision; 00694 *bound = osl_relation_pmalloc(precision, 0, r->nb_columns); 00695 osl_relation_set_attributes(*bound, 00696 r->nb_output_dims, 00697 r->nb_input_dims, 00698 r->nb_local_dims, 00699 r->nb_parameters); 00700 *notbound = osl_relation_pmalloc(precision, 0, r->nb_columns); 00701 osl_relation_set_attributes(*notbound, 00702 r->nb_output_dims, 00703 r->nb_input_dims, 00704 r->nb_local_dims, 00705 r->nb_parameters); 00706 00707 // For each constraint in r... 00708 for (i = 0; i < r->nb_rows; i++) { 00709 constraint = clan_relation_extract_constraint(r, i); 00710 00711 if (osl_int_zero(precision, constraint->m[0][depth])) { 00712 // If it does not involve the loop iterator => notbound set. 00713 osl_relation_insert_constraints(*notbound, constraint, -1); 00714 } else if (osl_int_zero(precision, constraint->m[0][0])) { 00715 // If this is an equality, separate it into two inequalities, then 00716 // put one in bound and the other one in notbound conveniently. 00717 osl_int_set_si(precision, &constraint->m[0][0], 1); 00718 osl_relation_insert_constraints(*bound, constraint, -1); 00719 osl_relation_insert_constraints(*notbound, constraint, -1); 00720 if ((lower && osl_int_pos(precision, constraint->m[0][depth])) || 00721 (!lower && osl_int_neg(precision, constraint->m[0][depth]))) { 00722 clan_relation_oppose_row(*notbound, (*notbound)->nb_rows - 1); 00723 } else { 00724 clan_relation_oppose_row(*bound, (*bound)->nb_rows - 1); 00725 } 00726 } else { 00727 // If it is an inequality, drive it to the right set. 00728 if ((lower && osl_int_pos(precision, constraint->m[0][depth])) || 00729 (!lower && osl_int_neg(precision, constraint->m[0][depth]))) { 00730 osl_relation_insert_constraints(*bound, constraint, -1); 00731 } else { 00732 osl_relation_insert_constraints(*notbound, constraint, -1); 00733 } 00734 } 00735 osl_relation_free(constraint); 00736 } 00737 } 00738 00739 00753 static 00754 void clan_relation_to_expressions(osl_relation_p r, int depth) { 00755 int i, coef, mark; 00756 00757 for (i = 0; i < r->nb_rows; i++) { 00758 mark = osl_int_get_si(r->precision, r->m[i][0]); 00759 coef = osl_int_get_si(r->precision, r->m[i][depth]); 00760 if ((mark != 1) || (coef == 0)) 00761 CLAN_error("you found a bug"); 00762 00763 if (coef > 1) 00764 clan_relation_oppose_row(r, i); 00765 00766 coef = (coef > 0) ? coef : -coef; 00767 if (coef > 1) 00768 osl_int_set_si(r->precision, &r->m[i][0], coef); 00769 else 00770 osl_int_set_si(r->precision, &r->m[i][0], 0); 00771 osl_int_set_si(r->precision, &r->m[i][depth], 0); 00772 } 00773 } 00774 00775 00788 osl_relation_p clan_relation_stride(osl_relation_p r, int depth, int stride) { 00789 int i, lower, precision; 00790 osl_relation_p contribution; 00791 osl_relation_p constraint; 00792 osl_relation_p bound, notbound; 00793 osl_relation_p part; 00794 osl_relation_p full = NULL; 00795 00796 if (depth < 1) 00797 CLAN_error("invalid loop depth"); 00798 else if (stride == 0) 00799 CLAN_error("unsupported zero stride"); 00800 00801 precision = r->precision; 00802 lower = (stride > 0) ? 1 : 0; 00803 stride = (stride > 0) ? stride : -stride; 00804 00805 // Each part of the relation union will provide independent contribution. 00806 while (r != NULL) { 00807 part = NULL; 00808 00809 // Separate the bounding constraints (bound) which are impacted by the 00810 // stride from others (notbound) which will be reinjected later. 00811 clan_relation_extract_bounding(r, &bound, ¬bound, depth, lower); 00812 00813 // Change the bounding constraints to a set of linear expressions 00814 // to make it easy to manipulate them through existing functions. 00815 clan_relation_to_expressions(bound, depth); 00816 00817 // Each bound constraint contributes along with the stride. 00818 for (i = 0; i < bound->nb_rows; i++) { 00819 // -1. Extract the contributing constraint c. 00820 constraint = clan_relation_extract_constraint(bound, i); 00821 00822 // -2. For every constaint before c, ensure the comparison at step 3 00823 // will be strictly greater, by adding 1: since the different 00824 // sets must be disjoint, we don't want a >= b then b >= a but 00825 // a >= b then b > a to avoid a == b to be in both sets. 00826 // (Resp. adding -1 for the upper case.) 00827 if (i > 0) { 00828 if (lower) { 00829 osl_int_add_si(precision, 00830 &bound->m[i - 1][bound->nb_columns - 1], 00831 bound->m[i - 1][bound->nb_columns - 1], 1); 00832 } else { 00833 osl_int_add_si(precision, 00834 &bound->m[i - 1][bound->nb_columns - 1], 00835 bound->m[i - 1][bound->nb_columns - 1], -1); 00836 } 00837 } 00838 00839 // -3. Compute c > a && c > b && c >= c && c >= d ... 00840 // We remove the c >= c row which corresponds to a trivial 0 >= 0. 00841 // (Resp. c < a && c <b && c <= c && c <=d ... for the upper case.) 00842 if (lower) 00843 contribution = clan_relation_greater(constraint, bound, 0); 00844 else 00845 contribution = clan_relation_greater(bound, constraint, 0); 00846 osl_relation_remove_row(contribution, i); 00847 00848 // -4. The iterator i of the current depth is i >= c. 00849 // (Resp. c <= i for the upper case.) 00850 // * 4.1 Put c at the end of the constraint set. 00851 osl_relation_insert_constraints(contribution, constraint, -1); 00852 // * 4.2 Oppose so we have -c. 00853 // (Resp. do nothing so we have c for the upper case.) 00854 if (lower) { 00855 clan_relation_oppose_row(contribution, contribution->nb_rows - 1); 00856 } 00857 // * 4.3 Put the loop iterator so we have i - c. 00858 // (Resp. -i + c for the upper case.) 00859 if (lower) { 00860 osl_int_set_si(precision, 00861 &contribution->m[contribution->nb_rows - 1][depth], 1); 00862 } else { 00863 osl_int_set_si(precision, 00864 &contribution->m[contribution->nb_rows - 1][depth], -1); 00865 } 00866 // * 4.4 Set the inequality marker so we have i - c >= 0. 00867 // (Resp. -i + c >= 0 for the upper case.) 00868 osl_int_set_si(precision, 00869 &contribution->m[contribution->nb_rows - 1][0], 1); 00870 00871 // -5. Add the contribution of the stride (same for lower and upper). 00872 // * 5.1 Put c at the end of the constraint set. 00873 osl_relation_insert_constraints(contribution, constraint, -1); 00874 // * 5.2 Put the opposed loop iterator so we have -i + c. 00875 osl_int_set_si(precision, 00876 &contribution->m[contribution->nb_rows - 1][depth], -1); 00877 // * 5.3 Put stride * local dimension so we have -i + c + stride*ld. 00878 // The equality marker is set so we have i == c + stride*ld. 00879 osl_int_set_si(precision, 00880 &contribution->m[contribution->nb_rows - 1] 00881 [CLAN_MAX_DEPTH + 1 + clan_parser_nb_ld()], stride); 00882 00883 osl_relation_free(constraint); 00884 osl_relation_add(&part, contribution); 00885 } 00886 00887 // Re-inject notbound constraints 00888 clan_relation_and(notbound, part); 00889 osl_relation_free(bound); 00890 osl_relation_free(part); 00891 osl_relation_add(&full, notbound); 00892 r = r->next; 00893 } 00894 clan_parser_add_ld(); 00895 00896 return full; 00897 } 00898 00899 00913 static 00914 void clan_relation_gaussian_elimination(osl_relation_p relation, 00915 int pivot_row, int pivot_column) { 00916 int i, j, same_sign, precision, identical; 00917 osl_int_p temp, pivot_coef, current_coef; 00918 00919 if (relation == NULL) 00920 return; 00921 00922 precision = relation->precision; 00923 00924 if (relation->next != NULL) 00925 OSL_debug("gaussian elimination works only on the first part of unions"); 00926 00927 if ((pivot_row >= relation->nb_rows) || (pivot_row < 0) || 00928 (pivot_column >= relation->nb_columns) || (pivot_column < 0)) 00929 OSL_error("bad pivot position"); 00930 00931 if (osl_int_zero(precision, relation->m[pivot_row][pivot_column])) 00932 OSL_error("pivot value is 0"); 00933 00934 if (!osl_int_zero(precision, relation->m[pivot_row][0])) 00935 OSL_warning("pivot not in an equality: non equivalent simplified relation"); 00936 00937 // Achieve the gaussian elimination. 00938 // TODO: (ndCedric) investigate the impact of converting i > 0 to i - 1 >= 0. 00939 // When we multiply with some coefficients, like here, we may run into 00940 // trouble. For instance, let us suppose we want to simplify N > i 00941 // knowing that 2i = N. If we keep the >, we end up with N > 0. If we 00942 // translate to >=, we end up with N >= 2 which is not quite the same. 00943 temp = osl_int_malloc(precision); 00944 pivot_coef = osl_int_malloc(precision); 00945 current_coef = osl_int_malloc(precision); 00946 for (i = 0; i < relation->nb_rows; i++) { 00947 // Do not eliminate if: 00948 // - The current element to eliminate is the pivot, 00949 // - The current element to eliminate is already zero, 00950 // - The pivot lies in an inequality and the element in an equality, 00951 // - The pivot and the current element are described with inequalities and 00952 // their coefficients have the same sign (impossible to eliminate). 00953 same_sign = (osl_int_neg(precision, relation->m[pivot_row][pivot_column])&& 00954 osl_int_neg(precision, relation->m[i][pivot_column])) || 00955 (osl_int_pos(precision, relation->m[pivot_row][pivot_column])&& 00956 osl_int_pos(precision, relation->m[i][pivot_column])); 00957 if ((i != pivot_row) && 00958 (!osl_int_zero(precision, relation->m[i][pivot_column])) && 00959 (osl_int_zero(precision, relation->m[pivot_row][0]) || 00960 !osl_int_zero(precision, relation->m[i][0]))) { 00961 if (osl_int_zero(precision, relation->m[pivot_row][0]) || 00962 osl_int_zero(precision, relation->m[i][0]) || !same_sign) { 00963 // Set the values of coefficients for the pivot and the current rows: 00964 // - if the pivot and the current element do not have the same sign, 00965 // ensure that only an equality can be multiplied by a negative coef, 00966 // - if the signs are different, use positive coefficients. 00967 osl_int_assign(precision, 00968 pivot_coef, relation->m[pivot_row][pivot_column]); 00969 osl_int_assign(precision, 00970 current_coef, relation->m[i][pivot_column]); 00971 if (same_sign) { 00972 if (osl_int_zero(precision, relation->m[pivot_row][0])) { 00973 osl_int_oppose(precision, current_coef, *current_coef); 00974 } else { 00975 osl_int_oppose(precision, pivot_coef, *pivot_coef); 00976 } 00977 } else { 00978 osl_int_abs(precision, pivot_coef, *pivot_coef); 00979 osl_int_abs(precision, current_coef, *current_coef); 00980 } 00981 00982 // element = pivot_coef * element + current_coef * pivot_row_element 00983 for (j = 1; j < relation->nb_columns; j++) { 00984 osl_int_mul(precision, 00985 temp, *current_coef, relation->m[pivot_row][j]); 00986 osl_int_mul(precision, 00987 &relation->m[i][j], *pivot_coef, relation->m[i][j]); 00988 osl_int_add(precision, 00989 &relation->m[i][j], relation->m[i][j], *temp); 00990 } 00991 } else { 00992 // In the case of two inequalities of the same sign, check whether they 00993 // are identical and if yes, zero the current row. 00994 identical = 1; 00995 for (j = 1; j < relation->nb_columns; j++) { 00996 if (osl_int_ne(precision, 00997 relation->m[i][j], relation->m[pivot_row][j])) { 00998 identical = 0; 00999 break; 01000 } 01001 } 01002 if (identical) { 01003 for (j = 1; j < relation->nb_columns; j++) 01004 osl_int_sub(precision, &relation->m[i][j], 01005 relation->m[i][j], relation->m[i][j]); 01006 } 01007 } 01008 } 01009 } 01010 osl_int_free(precision, temp); 01011 osl_int_free(precision, pivot_coef); 01012 osl_int_free(precision, current_coef); 01013 } 01014 01015 01023 static 01024 void clan_relation_simplify_parts(osl_relation_p relation) { 01025 osl_relation_p test, temp; 01026 01027 test = relation->next; 01028 while (relation != NULL) { 01029 while (test != NULL) { 01030 if (osl_relation_part_equal(relation, test)) { 01031 temp = test; 01032 test = test->next; 01033 if (relation->next == temp) 01034 relation->next = test; 01035 temp->next = NULL; 01036 osl_relation_free(temp); 01037 } else { 01038 test = test->next; 01039 } 01040 } 01041 relation = relation->next; 01042 } 01043 } 01044 01045 01054 void clan_relation_simplify(osl_relation_p relation) { 01055 int i, j, k, to_eliminate, offset; 01056 osl_relation_p gauss, reference_gauss, reference = relation; 01057 01058 gauss = osl_relation_clone(relation); 01059 reference_gauss = gauss; 01060 while (relation != NULL) { 01061 // First, try to eliminate columns elements by pivoting. 01062 for (j = 1; j < gauss->nb_columns; j++) { 01063 // Try to find a pivot, hence such that: 01064 // - the pivot is not 0, 01065 // - the constraint including the pivot is an equality, 01066 // - there is no non-zero element in the row before the pivot. 01067 01068 //printf("j = %d\n", j); 01069 //osl_relation_dump(stdout, gauss); 01070 for (i = 0; i < gauss->nb_rows; i++) { 01071 if (!osl_int_zero(gauss->precision, gauss->m[i][j]) && 01072 osl_int_zero(gauss->precision, gauss->m[i][0])) { 01073 to_eliminate = 1; 01074 for (k = 1; k < j; k++) 01075 if (!osl_int_zero(gauss->precision, gauss->m[i][k])) 01076 to_eliminate = 0; 01077 if (to_eliminate) 01078 clan_relation_gaussian_elimination(gauss, i, j); 01079 } 01080 } 01081 //osl_relation_dump(stdout, gauss); 01082 } 01083 01084 // Second, remove trivially duplicated rows. 01085 for (i = 0; i < gauss->nb_rows; i++) { 01086 for (k = i + 1; k < gauss->nb_rows; k++) { 01087 to_eliminate = 1; 01088 for (j = 1; j < gauss->nb_columns; j++) { 01089 if (osl_int_ne(gauss->precision, gauss->m[i][j], gauss->m[k][j])) { 01090 to_eliminate = 0; 01091 break; 01092 } 01093 } 01094 if (to_eliminate) { 01095 for (j = 1; j < gauss->nb_columns; j++) 01096 osl_int_sub(gauss->precision, &gauss->m[k][j], 01097 gauss->m[k][j], gauss->m[k][j]); 01098 } 01099 } 01100 } 01101 01102 // Third, remove positive constant >= 0 constraints (e.g., 42 >= 0) 01103 for (i = 0; i < gauss->nb_rows; i++) { 01104 if (osl_int_pos(gauss->precision, gauss->m[i][gauss->nb_columns - 1]) && 01105 !osl_int_zero(gauss->precision, gauss->m[i][0])) { 01106 to_eliminate = 1; 01107 for (j = 1; j < gauss->nb_columns - 1; j++) { 01108 if (!osl_int_zero(gauss->precision, gauss->m[i][j])) { 01109 to_eliminate = 0; 01110 break; 01111 } 01112 } 01113 if (to_eliminate) 01114 osl_int_sub(gauss->precision, 01115 &gauss->m[i][gauss->nb_columns - 1], 01116 gauss->m[i][gauss->nb_columns - 1], 01117 gauss->m[i][gauss->nb_columns - 1]); 01118 } 01119 } 01120 01121 // Remove the rows in the original relation which correspond to 01122 // zero-rows in the gauss relation since they are redundant. 01123 offset = 0; 01124 for (i = 0; i < gauss->nb_rows; i++) { 01125 to_eliminate = 1; 01126 for (j = 1; j < gauss->nb_columns; j++) { 01127 if (!osl_int_zero(gauss->precision, gauss->m[i][j])) { 01128 to_eliminate = 0; 01129 break; 01130 } 01131 } 01132 if (to_eliminate) { 01133 osl_relation_remove_row(relation, i - offset); 01134 offset++; 01135 } 01136 } 01137 01138 gauss = gauss->next; 01139 relation = relation->next; 01140 } 01141 osl_relation_free(reference_gauss); 01142 clan_relation_simplify_parts(reference); 01143 } 01144 01145 01162 void clan_relation_loop_context(osl_relation_p condition, 01163 osl_relation_p initialization, 01164 int depth) { 01165 int i, j; 01166 osl_relation_p contextual = NULL, temp, first_condition, new_condition; 01167 01168 if ((condition == NULL) || (initialization == NULL)) 01169 return; 01170 01171 if (initialization->next != NULL) 01172 OSL_error("cannot compute the loop context for an initialization union"); 01173 01174 if (initialization->nb_columns != condition->nb_columns) 01175 OSL_error("imcompatible number of columns"); 01176 01177 for (i = 0; i < initialization->nb_rows; i++) 01178 if (osl_int_zero(initialization->precision, initialization->m[i][0])) 01179 OSL_error("no equality is allowed in the initialization relation"); 01180 01181 first_condition = condition; 01182 // For each possible initial value (e.g., in the case of a max): 01183 for (i = 0; i < initialization->nb_rows; i++) { 01184 condition = first_condition; 01185 // For each union part of the condition 01186 while (condition != NULL) { 01187 // Build the loop context (i.e. the loop condition where the 01188 // iterator is replaced by its initial value). 01189 temp = osl_relation_nclone(condition, 1); 01190 osl_relation_insert_blank_row(temp, 0); 01191 for (j = 0; j < temp->nb_columns; j++) 01192 osl_int_assign(temp->precision, 01193 &temp->m[0][j], initialization->m[i][j]); 01194 clan_relation_tag_equality(temp, 0); 01195 clan_relation_gaussian_elimination(temp, 0, depth); 01196 osl_relation_remove_row(temp, 0); 01197 01198 // Intersect the union part of the condition with its loop context. 01199 new_condition = osl_relation_nclone(condition, 1); 01200 osl_relation_insert_constraints(new_condition, temp, -1); 01201 01202 osl_relation_free(temp); 01203 osl_relation_add(&contextual, new_condition); 01204 condition = condition->next; 01205 } 01206 } 01207 01208 condition = first_condition; 01209 osl_relation_free_inside(condition); 01210 osl_relation_free(condition->next); 01211 01212 // Replace the inside of condition. 01213 condition->nb_rows = contextual->nb_rows; 01214 condition->m = contextual->m; 01215 condition->next = contextual->next; 01216 01217 // Free the contextual "shell". 01218 free(contextual); 01219 }