Clan  0.8.1
relation.c
Go to the documentation of this file.
1 
2  /*+------- <| --------------------------------------------------------**
3  ** A Clan **
4  **--- /.\ -----------------------------------------------------**
5  ** <| [""M# relation.c **
6  **- A | # -----------------------------------------------------**
7  ** /.\ [""M# First version: 30/04/2008 **
8  **- [""M# | # U"U#U -----------------------------------------------**
9  | # | # \ .:/
10  | # | #___| #
11  ****** | "--' .-" ******************************************************
12  * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) *
13  **** | # ## ###### *****************************************************
14  * \ .::::'/ *
15  * \ ::::'/ Copyright (C) 2008 University Paris-Sud 11 *
16  * :8a| # # ## *
17  * ::88a ### This is free software; you can redistribute it *
18  * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser *
19  * ::::::::888a88a[]::: General Public License as published by the Free *
20  *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the *
21  *::::::::8::::888:Y8888:: License, or (at your option) any later version. *
22  *::::':::88::::888::Y88a::::::::::::... *
23  *::'::.. . ..... .. ... . *
24  * This software is distributed in the hope that it will be useful, but *
25  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
26  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27  * for more details. *
28  * *
29  * You should have received a copy of the GNU Lesser General Public License *
30  * along with software; if not, write to the Free Software Foundation, Inc., *
31  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
32  * *
33  * Clan, the Chunky Loop Analyzer *
34  * Written by Cedric Bastoul, Cedric.Bastoul@u-psud.fr *
35  * *
36  ******************************************************************************/
37 
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <ctype.h>
43 
44 #include <osl/macros.h>
45 #include <osl/int.h>
46 #include <osl/relation.h>
47 #include <clan/macros.h>
48 #include <clan/options.h>
49 #include <clan/relation.h>
50 
51 int clan_parser_nb_ld(void);
52 void clan_parser_add_ld(void);
53 
54 
55 /*+****************************************************************************
56  * Processing functions *
57  ******************************************************************************/
58 
59 
71 void clan_relation_tag_array(osl_relation_p relation, int array) {
72  if (relation == NULL)
73  CLAN_error("relation cannot be array-tagged");
74 
75  osl_relation_insert_blank_row(relation, 0);
76  osl_relation_insert_blank_column(relation, 1);
77  osl_int_set_si(relation->precision, &relation->m[0][1], -1);
78  osl_int_set_si(relation->precision,
79  &relation->m[0][relation->nb_columns - 1], array);
80  relation->nb_output_dims++;
81 }
82 
83 
93 osl_relation_p clan_relation_build_context(int nb_parameters,
94  clan_options_p options) {
95  int i;
96  osl_relation_p context = NULL;
97 
98  if (options->bounded_context) {
99  context = osl_relation_pmalloc(options->precision,
100  nb_parameters, nb_parameters + 2);
101  for (i = 0; i < nb_parameters; i++) {
102  osl_int_set_si(options->precision, &context->m[i][0], 1);
103  osl_int_set_si(options->precision, &context->m[i][i + 1], 1);
104  osl_int_set_si(options->precision,
105  &context->m[i][context->nb_columns - 1], 1);
106  }
107  } else {
108  context = osl_relation_pmalloc(options->precision, 0, nb_parameters + 2);
109  }
110  osl_relation_set_type(context, OSL_TYPE_CONTEXT);
111  osl_relation_set_attributes(context, 0, 0, 0, nb_parameters);
112  return context;
113 }
114 
115 
133 osl_relation_p clan_relation_scattering(int* vector, int depth,
134  int precision) {
135  int i, j, nb_rows, nb_columns;
136  int beta_col, alpha_col;
137  osl_relation_p scattering;
138 
139  nb_rows = (2 * depth + 1);
140  nb_columns = (2 * depth + 1) + (depth) + (CLAN_MAX_PARAMETERS) + 2;
141  scattering = osl_relation_pmalloc(precision, nb_rows, nb_columns);
142  osl_relation_set_type(scattering, OSL_TYPE_SCATTERING);
143  osl_relation_set_attributes(scattering, 2 * depth + 1, depth, 0,
144  CLAN_MAX_PARAMETERS);
145 
146  // The output dimension identity
147  for (i = 0; i < 2 * depth + 1; i++)
148  osl_int_set_si(precision, &scattering->m[i][i + 1], -1);
149 
150  // The beta and alpha.
151  j = 0;
152  beta_col = nb_columns - 1;
153  for (i = 0; i < depth; i++) {
154  alpha_col = (2 * depth + 1) + i + 1;
155  osl_int_set_si(precision, &scattering->m[j][beta_col], vector[j]);
156  osl_int_set_si(precision, &scattering->m[j+1][alpha_col], vector[j+1]);
157  j += 2;
158  }
159  osl_int_set_si(precision, &scattering->m[nb_rows-1][beta_col], vector[j]);
160 
161  return scattering;
162 }
163 
164 
175 void clan_relation_new_output_vector(osl_relation_p relation,
176  osl_vector_p vector) {
177  int i, new_col, new_row;
178 
179  if (relation == NULL)
180  CLAN_error("cannot add a new output dimension to a NULL relation");
181  else if (vector == NULL)
182  CLAN_error("cannot add a NULL expression of an output dimension");
183  else if (relation->precision != vector->precision)
184  CLAN_error("incompatible precisions");
185 
186  if (relation->nb_output_dims == OSL_UNDEFINED)
187  new_col = 1;
188  else
189  new_col = relation->nb_output_dims + 1;
190  new_row = relation->nb_rows;
191 
192  if ((relation->nb_columns - (new_col - 1)) != vector->size)
193  CLAN_error("incompatible sizes");
194  else if (!osl_int_zero(vector->precision, vector->v[0]))
195  CLAN_error("the output dimension expression should be an equality");
196 
197  // Prepare the space for the new output dimension and the vector.
198  osl_relation_insert_blank_column(relation, new_col);
199  osl_relation_insert_blank_row(relation, new_row);
200  relation->nb_output_dims = new_col;
201 
202  // Insert the new output dimension.
203  osl_int_set_si(relation->precision, &relation->m[new_row][new_col], -1);
204  for (i = 1; i < vector->size; i++)
205  osl_int_assign(relation->precision,
206  &relation->m[new_row][new_col + i], vector->v[i]);
207 }
208 
209 
220 void clan_relation_new_output_scalar(osl_relation_p relation, int scalar) {
221  int new_col, new_row;
222 
223  if (relation == NULL)
224  CLAN_error("cannot add a new output dimension to a NULL relation");
225 
226  if (relation->nb_output_dims == OSL_UNDEFINED)
227  new_col = 1;
228  else
229  new_col = relation->nb_output_dims + 1;
230  new_row = relation->nb_rows;
231 
232  // Prepare the space for the new output dimension and the vector.
233  osl_relation_insert_blank_column(relation, new_col);
234  osl_relation_insert_blank_row(relation, new_row);
235  relation->nb_output_dims = new_col;
236 
237  // Insert the new output dimension.
238  osl_int_set_si(relation->precision, &relation->m[new_row][new_col], -1);
239  osl_int_set_si(relation->precision,
240  &relation->m[new_row][relation->nb_columns - 1], scalar);
241 }
242 
243 
253 void clan_relation_compact(osl_relation_p relation,
254  int nb_parameters) {
255  int i, j, nb_columns;
256  int nb_output_dims, nb_input_dims, nb_local_dims, nb_out_in_loc;
257  osl_relation_p compacted;
258 
259  while (relation != NULL) {
260  nb_output_dims = relation->nb_output_dims;
261  nb_input_dims = relation->nb_input_dims;
262  nb_local_dims = relation->nb_local_dims;
263  nb_out_in_loc = nb_output_dims + nb_input_dims + nb_local_dims;
264 
265  nb_columns = nb_out_in_loc + nb_parameters + 2;
266  compacted = osl_relation_pmalloc(relation->precision,
267  relation->nb_rows, nb_columns);
268 
269  for (i = 0; i < relation->nb_rows; i++) {
270  // We copy the equ/inequ tag, the output and input coefficients.
271  for (j = 0; j <= nb_output_dims + nb_input_dims; j++)
272  osl_int_assign(relation->precision,
273  &compacted->m[i][j], relation->m[i][j]);
274 
275  // Then we copy the local dimension coefficients.
276  for (j = 0; j < nb_local_dims; j++)
277  osl_int_assign(relation->precision,
278  &compacted->m[i][nb_output_dims + nb_input_dims + 1 + j],
279  relation->m[i][CLAN_MAX_DEPTH + 1 + j]);
280 
281  // Then we copy the parameter coefficients.
282  for (j = 0; j < nb_parameters; j++)
283  osl_int_assign(relation->precision,
284  &compacted->m[i][j + nb_out_in_loc + 1],
285  relation->m[i][relation->nb_columns - CLAN_MAX_PARAMETERS -1 + j]);
286 
287  // Lastly the scalar coefficient.
288  osl_int_assign(relation->precision,
289  &compacted->m[i][nb_columns - 1],
290  relation->m[i][relation->nb_columns - 1]);
291  }
292 
293  osl_relation_free_inside(relation);
294 
295  // Replace the inside of relation.
296  relation->nb_rows = compacted->nb_rows;
297  relation->nb_columns = compacted->nb_columns;
298  relation->m = compacted->m;
299  relation->nb_parameters = nb_parameters;
300 
301  // Free the compacted "container".
302  free(compacted);
303 
304  relation = relation->next;
305  }
306 }
307 
308 
332 osl_relation_p clan_relation_greater(osl_relation_p min, osl_relation_p max,
333  int strict) {
334  int imin, imax, j, precision;
335  int a, b;
336  osl_relation_p r;
337  osl_int_t b_min, a_max;
338 
339  if ((min == NULL) || (max == NULL) || (strict < 0) || (strict > 1) ||
340  (min->nb_columns != max->nb_columns))
341  CLAN_error("cannot compose relations");
342 
343  precision = min->precision;
344  osl_int_init(precision, &a_max);
345  osl_int_init(precision, &b_min);
346  r = osl_relation_pmalloc(precision,
347  min->nb_rows * max->nb_rows, min->nb_columns);
348 
349  // For each row of min
350  for (imin = 0; imin < min->nb_rows; imin++) {
351  // For each row of max
352  // We have a couple min/a >= max/b to translate to b*min - a*max >= 0
353  // or a couple min/a > max/b to translate to b*min - a*max - 1 >= 0
354  // TODO: here a and b are > 0, this may be generalized to avoid a
355  // problem if the grammar is updated. Plus it's debatable to use
356  // b*min - a*max -a*b >= 0 in the second case.
357 
358  // -1. Find a
359  a = osl_int_get_si(precision, min->m[imin][0]);
360  a = (a == 0) ? 1 : a;
361 
362  for (imax = 0; imax < max->nb_rows; imax++) {
363  // -2. Find b
364  b = osl_int_get_si(precision, max->m[imax][0]);
365  b = (b == 0) ? 1 : b;
366 
367  // -3. Compute b*min - a*max to the new relation.
368  for (j = 1; j < max->nb_columns; j++) {
369  // -3.1. Compute b*min
370  osl_int_mul_si(precision, &b_min, min->m[imin][j], b);
371 
372  // -3.2. Compute a*max
373  osl_int_mul_si(precision, &a_max, max->m[imax][j], a);
374 
375  // -3.3. Compute b*min - a*max
376  osl_int_sub(precision,
377  &r->m[imin * max->nb_rows + imax][j], b_min, a_max);
378  }
379 
380  // -4. Add -1 if the condition is min/a > max/b, add 0 otherwise.
381  osl_int_add_si(precision,
382  &r->m[imin * max->nb_rows + imax][max->nb_columns - 1],
383  r->m[imin * max->nb_rows + imax][max->nb_columns - 1],
384  -strict);
385  // -5. Set the equality/inequality marker to inequality.
386  osl_int_set_si(precision, &r->m[imin * max->nb_rows + imax][0], 1);
387  }
388  }
389 
390  osl_int_clear(precision, &a_max);
391  osl_int_clear(precision, &b_min);
392  return r;
393 }
394 
395 
404 static
405 void clan_relation_negate_inequality(osl_relation_p relation, int row) {
406  int i;
407 
408  // Oppose all constraint elements.
409  for (i = 1; i < relation->nb_columns; i++)
410  osl_int_oppose(relation->precision,
411  &relation->m[row][i], relation->m[row][i]);
412 
413  // The constant term - 1.
414  osl_int_decrement(relation->precision,
415  &relation->m[row][relation->nb_columns - 1],
416  relation->m[row][relation->nb_columns - 1]);
417 }
418 
419 
429 static
430 osl_relation_p clan_relation_extract_constraint(osl_relation_p relation,
431  int row) {
432  int i, precision = relation->precision;
433  osl_relation_p constraint;
434 
435  constraint = osl_relation_pmalloc(precision, 1, relation->nb_columns);
436  constraint->type = relation->type;
437  constraint->nb_output_dims = relation->nb_output_dims;
438  constraint->nb_input_dims = relation->nb_input_dims;
439  constraint->nb_local_dims = relation->nb_local_dims;
440  constraint->nb_parameters = relation->nb_parameters;
441 
442  for (i = 0; i < relation->nb_columns; i++)
443  osl_int_assign(precision, &constraint->m[0][i], relation->m[row][i]);
444 
445  return constraint;
446 }
447 
448 
458 static
459 int clan_relation_is_equality(osl_relation_p relation, int row) {
460 
461  return (osl_int_zero(relation->precision, relation->m[row][0])) ? 1 : 0;
462 }
463 
464 
474 static
475 void clan_relation_tag_inequality(osl_relation_p relation, int row) {
476  if ((relation == NULL) || (relation->nb_rows < row))
477  CLAN_error("the constraint cannot be inquality-tagged");
478  osl_int_set_si(relation->precision, &relation->m[row][0], 1);
479 }
480 
481 
491 static
492 void clan_relation_tag_equality(osl_relation_p relation, int row) {
493  if ((relation == NULL) || (relation->nb_rows < row))
494  CLAN_error("the constraint cannot be equality-tagged");
495  osl_int_set_si(relation->precision, &relation->m[row][0], 0);
496 }
497 
498 
507 static
508 osl_relation_p clan_relation_constraint_not(osl_relation_p relation, int row) {
509  osl_relation_p tmp, tmp_eq = NULL;
510 
511  if (row > relation->nb_rows)
512  return NULL;
513 
514  // Extract the constraint.
515  tmp = clan_relation_extract_constraint(relation, row);
516 
517  // Negate it (inequality-style): a >= 0 becomes a < 0, i.e., -a - 1 >= 0.
519 
520  // If the constraint is an equality we need to build an union.
521  // a == 0 becomes a > 0 || a < 0, i.e., a - 1 >= 0 || -a - 1 >= 0.
522  if (clan_relation_is_equality(relation, row)) {
523 
524  tmp_eq = clan_relation_extract_constraint(relation, row);
525  osl_int_decrement(relation->precision,
526  &tmp_eq->m[0][tmp_eq->nb_columns - 1],
527  tmp_eq->m[0][tmp_eq->nb_columns - 1]);
528 
529  // Set the two constraints as inequalities and build the union.
531  clan_relation_tag_inequality(tmp_eq, 0);
532  tmp->next = tmp_eq;
533  }
534 
535  return tmp;
536 }
537 
538 
545 osl_relation_p clan_relation_not(osl_relation_p relation) {
546  int i;
547  osl_relation_p not_constraint;
548  osl_relation_p not = NULL, part;
549 
550  while (relation != NULL) {
551  // Build the negation of one relation union part.
552  part = NULL;
553  for (i = 0; i < relation->nb_rows; i++) {
554  not_constraint = clan_relation_constraint_not(relation, i);
555  osl_relation_add(&part, not_constraint);
556  }
557 
558  // AND it to the previously negated parts.
559  if (not == NULL) {
560  not = part;
561  } else {
562  clan_relation_and(not, part);
563  osl_relation_free(part);
564  }
565  relation = relation->next;
566  }
567 
568  return not;
569 }
570 
571 
580 void clan_relation_and(osl_relation_p dest, osl_relation_p src) {
581  osl_relation_p next_dest,
582  next_src,
583  dup_dest,
584  next_mem = NULL;
585 
586  // initializing
587  next_src = src;
588  next_dest = dest;
589  dup_dest = osl_relation_clone(dest);
590  if (dest == NULL || src == NULL)
591  return;
592 
593  // For each union
594  while (next_src != NULL) {
595  // Add in each unions
596  while(next_dest != NULL) {
597  osl_relation_insert_constraints(next_dest, next_src, next_dest->nb_rows);
598  next_mem = next_dest;
599  next_dest = next_dest->next;
600  }
601  if (next_src->next != NULL)
602  next_mem->next = osl_relation_clone(dup_dest);
603  else
604  next_mem->next = NULL;
605 
606  // Next union
607  next_src = next_src->next;
608  next_dest = next_mem->next;
609  }
610  osl_relation_free(dup_dest);
611 }
612 
613 
621 int clan_relation_existential(osl_relation_p relation) {
622  int i, j;
623 
624  while (relation != NULL) {
625  for (i = 0; i < relation->nb_rows; i++) {
626  for (j = CLAN_MAX_DEPTH + 1;
627  j < CLAN_MAX_DEPTH + CLAN_MAX_LOCAL_DIMS + 1;
628  j++) {
629  if (!osl_int_zero(relation->precision, relation->m[i][j]))
630  return 1;
631  }
632  }
633  relation = relation->next;
634  }
635 
636  return 0;
637 }
638 
639 
647 void clan_relation_oppose_row(osl_relation_p r, int row) {
648  int i;
649 
650  if (r == NULL)
651  return;
652 
653  if ((row < 0) || (row >= r->nb_rows))
654  CLAN_error("bad row number");
655 
656  for (i = 1; i < r->nb_columns; i++)
657  osl_int_oppose(r->precision, &r->m[row][i], r->m[row][i]);
658 }
659 
660 
675 static
676 void clan_relation_extract_bounding(osl_relation_p r,
677  osl_relation_p* bound,
678  osl_relation_p* notbound,
679  int depth, int lower) {
680  int i, precision;
681  osl_relation_p constraint;
682 
683  if (r == NULL)
684  return;
685 
686  if ((depth < 1) || (depth > CLAN_MAX_DEPTH))
687  CLAN_error("bad depth");
688 
689  if ((lower < 0) || (lower > 1))
690  CLAN_error("lower parameter must be 0 or 1");
691 
692  // Create two empty sets bound and notbound.
693  precision = r->precision;
694  *bound = osl_relation_pmalloc(precision, 0, r->nb_columns);
695  osl_relation_set_attributes(*bound,
696  r->nb_output_dims,
697  r->nb_input_dims,
698  r->nb_local_dims,
699  r->nb_parameters);
700  *notbound = osl_relation_pmalloc(precision, 0, r->nb_columns);
701  osl_relation_set_attributes(*notbound,
702  r->nb_output_dims,
703  r->nb_input_dims,
704  r->nb_local_dims,
705  r->nb_parameters);
706 
707  // For each constraint in r...
708  for (i = 0; i < r->nb_rows; i++) {
709  constraint = clan_relation_extract_constraint(r, i);
710 
711  if (osl_int_zero(precision, constraint->m[0][depth])) {
712  // If it does not involve the loop iterator => notbound set.
713  osl_relation_insert_constraints(*notbound, constraint, -1);
714  } else if (osl_int_zero(precision, constraint->m[0][0])) {
715  // If this is an equality, separate it into two inequalities, then
716  // put one in bound and the other one in notbound conveniently.
717  osl_int_set_si(precision, &constraint->m[0][0], 1);
718  osl_relation_insert_constraints(*bound, constraint, -1);
719  osl_relation_insert_constraints(*notbound, constraint, -1);
720  if ((lower && osl_int_pos(precision, constraint->m[0][depth])) ||
721  (!lower && osl_int_neg(precision, constraint->m[0][depth]))) {
722  clan_relation_oppose_row(*notbound, (*notbound)->nb_rows - 1);
723  } else {
724  clan_relation_oppose_row(*bound, (*bound)->nb_rows - 1);
725  }
726  } else {
727  // If it is an inequality, drive it to the right set.
728  if ((lower && osl_int_pos(precision, constraint->m[0][depth])) ||
729  (!lower && osl_int_neg(precision, constraint->m[0][depth]))) {
730  osl_relation_insert_constraints(*bound, constraint, -1);
731  } else {
732  osl_relation_insert_constraints(*notbound, constraint, -1);
733  }
734  }
735  osl_relation_free(constraint);
736  }
737 }
738 
739 
753 static
754 void clan_relation_to_expressions(osl_relation_p r, int depth) {
755  int i, coef, mark;
756 
757  for (i = 0; i < r->nb_rows; i++) {
758  mark = osl_int_get_si(r->precision, r->m[i][0]);
759  coef = osl_int_get_si(r->precision, r->m[i][depth]);
760  if ((mark != 1) || (coef == 0))
761  CLAN_error("you found a bug");
762 
763  if (coef > 0)
765 
766  coef = (coef > 0) ? coef : -coef;
767  if (coef > 1)
768  osl_int_set_si(r->precision, &r->m[i][0], coef);
769  else
770  osl_int_set_si(r->precision, &r->m[i][0], 0);
771  osl_int_set_si(r->precision, &r->m[i][depth], 0);
772  }
773 }
774 
775 
788 osl_relation_p clan_relation_stride(osl_relation_p r, int depth, int stride) {
789  int i, lower, precision;
790  osl_relation_p contribution;
791  osl_relation_p constraint;
792  osl_relation_p bound, notbound;
793  osl_relation_p part;
794  osl_relation_p full = NULL;
795 
796  if (depth < 1)
797  CLAN_error("invalid loop depth");
798  else if (stride == 0)
799  CLAN_error("unsupported zero stride");
800 
801  precision = r->precision;
802  lower = (stride > 0) ? 1 : 0;
803  stride = (stride > 0) ? stride : -stride;
804 
805  // Each part of the relation union will provide independent contribution.
806  while (r != NULL) {
807  part = NULL;
808 
809  // Separate the bounding constraints (bound) which are impacted by the
810  // stride from others (notbound) which will be reinjected later.
811  clan_relation_extract_bounding(r, &bound, &notbound, depth, lower);
812 
813  // Change the bounding constraints to a set of linear expressions
814  // to make it easy to manipulate them through existing functions.
815  clan_relation_to_expressions(bound, depth);
816 
817  // Each bound constraint contributes along with the stride.
818  for (i = 0; i < bound->nb_rows; i++) {
819  // -1. Extract the contributing constraint c.
820  constraint = clan_relation_extract_constraint(bound, i);
821 
822  // -2. For every constaint before c, ensure the comparison at step 3
823  // will be strictly greater, by adding 1: since the different
824  // sets must be disjoint, we don't want a >= b then b >= a but
825  // a >= b then b > a to avoid a == b to be in both sets.
826  // (Resp. adding -1 for the upper case.)
827  if (i > 0) {
828  if (lower) {
829  osl_int_add_si(precision,
830  &bound->m[i - 1][bound->nb_columns - 1],
831  bound->m[i - 1][bound->nb_columns - 1], 1);
832  } else {
833  osl_int_add_si(precision,
834  &bound->m[i - 1][bound->nb_columns - 1],
835  bound->m[i - 1][bound->nb_columns - 1], -1);
836  }
837  }
838 
839  // -3. Compute c > a && c > b && c >= c && c >= d ...
840  // We remove the c >= c row which corresponds to a trivial 0 >= 0.
841  // (Resp. c < a && c <b && c <= c && c <=d ... for the upper case.)
842  if (lower)
843  contribution = clan_relation_greater(constraint, bound, 0);
844  else
845  contribution = clan_relation_greater(bound, constraint, 0);
846  osl_relation_remove_row(contribution, i);
847 
848  // -4. The iterator i of the current depth is i >= c (i.e., i - c >= 0).
849  // (Resp. i <= c, i.e., -i + c >= 0, for the upper case.)
850  // * 4.1 Put c at the end of the constraint set.
851  osl_relation_insert_constraints(contribution, constraint, -1);
852  // * 4.2 Oppose so we have -c.
853  // (Resp. do nothing so we have c for the upper case.)
854  if (lower) {
855  clan_relation_oppose_row(contribution, contribution->nb_rows - 1);
856  }
857  // * 4.3 Put the loop iterator so we have i - c.
858  // (Resp. -i + c for the upper case.)
859  if (lower) {
860  osl_int_set_si(precision,
861  &contribution->m[contribution->nb_rows - 1][depth], 1);
862  } else {
863  osl_int_set_si(precision,
864  &contribution->m[contribution->nb_rows - 1][depth], -1);
865  }
866  // * 4.4 Set the inequality marker so we have i - c >= 0.
867  // (Resp. -i + c >= 0 for the upper case.)
868  osl_int_set_si(precision,
869  &contribution->m[contribution->nb_rows - 1][0], 1);
870 
871  // -5. Add the contribution of the stride (same for lower and upper).
872  // * 5.1 Put c at the end of the constraint set.
873  osl_relation_insert_constraints(contribution, constraint, -1);
874  // * 5.2 Put the opposed loop iterator so we have -i + c.
875  osl_int_set_si(precision,
876  &contribution->m[contribution->nb_rows - 1][depth], -1);
877  // * 5.3 Put stride * local dimension so we have -i + c + stride*ld.
878  // The equality marker is set so we have i == c + stride*ld.
879  osl_int_set_si(precision,
880  &contribution->m[contribution->nb_rows - 1]
881  [CLAN_MAX_DEPTH + 1 + clan_parser_nb_ld()], stride);
882 
883  osl_relation_free(constraint);
884  osl_relation_add(&part, contribution);
885  }
886 
887  // Re-inject notbound constraints
888  clan_relation_and(notbound, part);
889  osl_relation_free(bound);
890  osl_relation_free(part);
891  osl_relation_add(&full, notbound);
892  r = r->next;
893  }
895 
896  return full;
897 }
898 
899 
913 static
914 void clan_relation_gaussian_elimination(osl_relation_p relation,
915  int pivot_row, int pivot_column) {
916  int i, j, same_sign, precision, identical;
917  osl_int_p temp, pivot_coef, current_coef;
918 
919  if (relation == NULL)
920  return;
921 
922  precision = relation->precision;
923 
924  if (relation->next != NULL)
925  OSL_debug("gaussian elimination works only on the first part of unions");
926 
927  if ((pivot_row >= relation->nb_rows) || (pivot_row < 0) ||
928  (pivot_column >= relation->nb_columns) || (pivot_column < 0))
929  OSL_error("bad pivot position");
930 
931  if (osl_int_zero(precision, relation->m[pivot_row][pivot_column]))
932  OSL_error("pivot value is 0");
933 
934  if (!osl_int_zero(precision, relation->m[pivot_row][0]))
935  OSL_warning("pivot not in an equality: non equivalent simplified relation");
936 
937  // Achieve the gaussian elimination.
938  // TODO: (ndCedric) investigate the impact of converting i > 0 to i - 1 >= 0.
939  // When we multiply with some coefficients, like here, we may run into
940  // trouble. For instance, let us suppose we want to simplify N > i
941  // knowing that 2i = N. If we keep the >, we end up with N > 0. If we
942  // translate to >=, we end up with N >= 2 which is not quite the same.
943  temp = osl_int_malloc(precision);
944  pivot_coef = osl_int_malloc(precision);
945  current_coef = osl_int_malloc(precision);
946  for (i = 0; i < relation->nb_rows; i++) {
947  // Do not eliminate if:
948  // - The current element to eliminate is the pivot,
949  // - The current element to eliminate is already zero,
950  // - The pivot lies in an inequality and the element in an equality,
951  // - The pivot and the current element are described with inequalities and
952  // their coefficients have the same sign (impossible to eliminate).
953  same_sign = (osl_int_neg(precision, relation->m[pivot_row][pivot_column])&&
954  osl_int_neg(precision, relation->m[i][pivot_column])) ||
955  (osl_int_pos(precision, relation->m[pivot_row][pivot_column])&&
956  osl_int_pos(precision, relation->m[i][pivot_column]));
957  if ((i != pivot_row) &&
958  (!osl_int_zero(precision, relation->m[i][pivot_column])) &&
959  (osl_int_zero(precision, relation->m[pivot_row][0]) ||
960  !osl_int_zero(precision, relation->m[i][0]))) {
961  if (osl_int_zero(precision, relation->m[pivot_row][0]) ||
962  osl_int_zero(precision, relation->m[i][0]) || !same_sign) {
963  // Set the values of coefficients for the pivot and the current rows:
964  // - if the pivot and the current element do not have the same sign,
965  // ensure that only an equality can be multiplied by a negative coef,
966  // - if the signs are different, use positive coefficients.
967  osl_int_assign(precision,
968  pivot_coef, relation->m[pivot_row][pivot_column]);
969  osl_int_assign(precision,
970  current_coef, relation->m[i][pivot_column]);
971  if (same_sign) {
972  if (osl_int_zero(precision, relation->m[pivot_row][0])) {
973  osl_int_oppose(precision, current_coef, *current_coef);
974  } else {
975  osl_int_oppose(precision, pivot_coef, *pivot_coef);
976  }
977  } else {
978  osl_int_abs(precision, pivot_coef, *pivot_coef);
979  osl_int_abs(precision, current_coef, *current_coef);
980  }
981 
982  // element = pivot_coef * element + current_coef * pivot_row_element
983  for (j = 1; j < relation->nb_columns; j++) {
984  osl_int_mul(precision,
985  temp, *current_coef, relation->m[pivot_row][j]);
986  osl_int_mul(precision,
987  &relation->m[i][j], *pivot_coef, relation->m[i][j]);
988  osl_int_add(precision,
989  &relation->m[i][j], relation->m[i][j], *temp);
990  }
991  } else {
992  // In the case of two inequalities of the same sign, check whether they
993  // are identical and if yes, zero the current row.
994  identical = 1;
995  for (j = 1; j < relation->nb_columns; j++) {
996  if (osl_int_ne(precision,
997  relation->m[i][j], relation->m[pivot_row][j])) {
998  identical = 0;
999  break;
1000  }
1001  }
1002  if (identical) {
1003  for (j = 1; j < relation->nb_columns; j++)
1004  osl_int_sub(precision, &relation->m[i][j],
1005  relation->m[i][j], relation->m[i][j]);
1006  }
1007  }
1008  }
1009  }
1010  osl_int_free(precision, temp);
1011  osl_int_free(precision, pivot_coef);
1012  osl_int_free(precision, current_coef);
1013 }
1014 
1015 
1023 static
1024 void clan_relation_simplify_parts(osl_relation_p relation) {
1025  osl_relation_p test, temp;
1026 
1027  test = relation->next;
1028  while (relation != NULL) {
1029  while (test != NULL) {
1030  if (osl_relation_part_equal(relation, test)) {
1031  temp = test;
1032  test = test->next;
1033  if (relation->next == temp)
1034  relation->next = test;
1035  temp->next = NULL;
1036  osl_relation_free(temp);
1037  } else {
1038  test = test->next;
1039  }
1040  }
1041  relation = relation->next;
1042  }
1043 }
1044 
1045 
1054 void clan_relation_simplify(osl_relation_p relation) {
1055  int i, j, k, to_eliminate, offset;
1056  osl_relation_p gauss, reference_gauss, reference = relation;
1057 
1058  gauss = osl_relation_clone(relation);
1059  reference_gauss = gauss;
1060  while (relation != NULL) {
1061  // First, try to eliminate columns elements by pivoting.
1062  for (j = 1; j < gauss->nb_columns; j++) {
1063  // Try to find a pivot, hence such that:
1064  // - the pivot is not 0,
1065  // - the constraint including the pivot is an equality,
1066  // - there is no non-zero element in the row before the pivot.
1067 
1068  //printf("j = %d\n", j);
1069  //osl_relation_dump(stdout, gauss);
1070  for (i = 0; i < gauss->nb_rows; i++) {
1071  if (!osl_int_zero(gauss->precision, gauss->m[i][j]) &&
1072  osl_int_zero(gauss->precision, gauss->m[i][0])) {
1073  to_eliminate = 1;
1074  for (k = 1; k < j; k++)
1075  if (!osl_int_zero(gauss->precision, gauss->m[i][k]))
1076  to_eliminate = 0;
1077  if (to_eliminate)
1079  }
1080  }
1081  //osl_relation_dump(stdout, gauss);
1082  }
1083 
1084  // Second, remove trivially duplicated rows.
1085  for (i = 0; i < gauss->nb_rows; i++) {
1086  for (k = i + 1; k < gauss->nb_rows; k++) {
1087  to_eliminate = 1;
1088  for (j = 1; j < gauss->nb_columns; j++) {
1089  if (osl_int_ne(gauss->precision, gauss->m[i][j], gauss->m[k][j])) {
1090  to_eliminate = 0;
1091  break;
1092  }
1093  }
1094  if (to_eliminate) {
1095  for (j = 1; j < gauss->nb_columns; j++)
1096  osl_int_sub(gauss->precision, &gauss->m[k][j],
1097  gauss->m[k][j], gauss->m[k][j]);
1098  }
1099  }
1100  }
1101 
1102  // Third, remove positive constant >= 0 constraints (e.g., 42 >= 0)
1103  for (i = 0; i < gauss->nb_rows; i++) {
1104  if (osl_int_pos(gauss->precision, gauss->m[i][gauss->nb_columns - 1]) &&
1105  !osl_int_zero(gauss->precision, gauss->m[i][0])) {
1106  to_eliminate = 1;
1107  for (j = 1; j < gauss->nb_columns - 1; j++) {
1108  if (!osl_int_zero(gauss->precision, gauss->m[i][j])) {
1109  to_eliminate = 0;
1110  break;
1111  }
1112  }
1113  if (to_eliminate)
1114  osl_int_sub(gauss->precision,
1115  &gauss->m[i][gauss->nb_columns - 1],
1116  gauss->m[i][gauss->nb_columns - 1],
1117  gauss->m[i][gauss->nb_columns - 1]);
1118  }
1119  }
1120 
1121  // Remove the rows in the original relation which correspond to
1122  // zero-rows in the gauss relation since they are redundant.
1123  offset = 0;
1124  for (i = 0; i < gauss->nb_rows; i++) {
1125  to_eliminate = 1;
1126  for (j = 1; j < gauss->nb_columns; j++) {
1127  if (!osl_int_zero(gauss->precision, gauss->m[i][j])) {
1128  to_eliminate = 0;
1129  break;
1130  }
1131  }
1132  if (to_eliminate) {
1133  osl_relation_remove_row(relation, i - offset);
1134  offset++;
1135  }
1136  }
1137 
1138  gauss = gauss->next;
1139  relation = relation->next;
1140  }
1141  osl_relation_free(reference_gauss);
1142  clan_relation_simplify_parts(reference);
1143 }
1144 
1145 
1162 void clan_relation_loop_context(osl_relation_p condition,
1163  osl_relation_p initialization,
1164  int depth) {
1165  int i, j;
1166  osl_relation_p contextual = NULL, temp, first_condition, new_condition;
1167 
1168  if ((condition == NULL) || (initialization == NULL))
1169  return;
1170 
1171  if (initialization->next != NULL)
1172  OSL_error("cannot compute the loop context for an initialization union");
1173 
1174  if (initialization->nb_columns != condition->nb_columns)
1175  OSL_error("imcompatible number of columns");
1176 
1177  for (i = 0; i < initialization->nb_rows; i++)
1178  if (osl_int_zero(initialization->precision, initialization->m[i][0]))
1179  OSL_error("no equality is allowed in the initialization relation");
1180 
1181  first_condition = condition;
1182  // For each possible initial value (e.g., in the case of a max):
1183  for (i = 0; i < initialization->nb_rows; i++) {
1184  condition = first_condition;
1185  // For each union part of the condition
1186  while (condition != NULL) {
1187  // Build the loop context (i.e. the loop condition where the
1188  // iterator is replaced by its initial value).
1189  temp = osl_relation_nclone(condition, 1);
1190  osl_relation_insert_blank_row(temp, 0);
1191  for (j = 0; j < temp->nb_columns; j++)
1192  osl_int_assign(temp->precision,
1193  &temp->m[0][j], initialization->m[i][j]);
1194  clan_relation_tag_equality(temp, 0);
1195  clan_relation_gaussian_elimination(temp, 0, depth);
1196  osl_relation_remove_row(temp, 0);
1197 
1198  // Intersect the union part of the condition with its loop context.
1199  new_condition = osl_relation_nclone(condition, 1);
1200  osl_relation_insert_constraints(new_condition, temp, -1);
1201 
1202  osl_relation_free(temp);
1203  osl_relation_add(&contextual, new_condition);
1204  condition = condition->next;
1205  }
1206  }
1207 
1208  condition = first_condition;
1209  osl_relation_free_inside(condition);
1210  osl_relation_free(condition->next);
1211 
1212  // Replace the inside of condition.
1213  condition->nb_rows = contextual->nb_rows;
1214  condition->m = contextual->m;
1215  condition->next = contextual->next;
1216 
1217  // Free the contextual "shell".
1218  free(contextual);
1219 }
static void clan_relation_gaussian_elimination(osl_relation_p relation, int pivot_row, int pivot_column)
Definition: relation.c:914
static void clan_relation_tag_inequality(osl_relation_p relation, int row)
Definition: relation.c:475
osl_relation_p clan_relation_greater(osl_relation_p min, osl_relation_p max, int strict)
Definition: relation.c:332
static void clan_relation_negate_inequality(osl_relation_p relation, int row)
Definition: relation.c:405
osl_relation_p clan_relation_stride(osl_relation_p r, int depth, int stride)
Definition: relation.c:788
void clan_parser_add_ld(void)
static void clan_relation_to_expressions(osl_relation_p r, int depth)
Definition: relation.c:754
int bounded_context
Definition: options.h:66
static void clan_relation_tag_equality(osl_relation_p relation, int row)
Definition: relation.c:492
osl_relation_p clan_relation_not(osl_relation_p relation)
Definition: relation.c:545
void clan_relation_tag_array(osl_relation_p relation, int array)
Definition: relation.c:71
static void clan_relation_extract_bounding(osl_relation_p r, osl_relation_p *bound, osl_relation_p *notbound, int depth, int lower)
Definition: relation.c:676
void clan_relation_and(osl_relation_p dest, osl_relation_p src)
Definition: relation.c:580
int clan_parser_nb_ld(void)
void clan_relation_new_output_scalar(osl_relation_p relation, int scalar)
Definition: relation.c:220
static osl_relation_p clan_relation_extract_constraint(osl_relation_p relation, int row)
Definition: relation.c:430
void clan_relation_new_output_vector(osl_relation_p relation, osl_vector_p vector)
Definition: relation.c:175
osl_relation_p clan_relation_scattering(int *vector, int depth, int precision)
Definition: relation.c:133
static void clan_relation_simplify_parts(osl_relation_p relation)
Definition: relation.c:1024
static int clan_relation_is_equality(osl_relation_p relation, int row)
Definition: relation.c:459
osl_relation_p clan_relation_build_context(int nb_parameters, clan_options_p options)
Definition: relation.c:93
void clan_relation_oppose_row(osl_relation_p r, int row)
Definition: relation.c:647
void clan_relation_compact(osl_relation_p relation, int nb_parameters)
Definition: relation.c:253
void clan_relation_simplify(osl_relation_p relation)
Definition: relation.c:1054
void clan_relation_loop_context(osl_relation_p condition, osl_relation_p initialization, int depth)
Definition: relation.c:1162
int clan_relation_existential(osl_relation_p relation)
Definition: relation.c:621
int precision
Definition: options.h:65
static osl_relation_p clan_relation_constraint_not(osl_relation_p relation, int row)
Definition: relation.c:508