PIPS
transformer_list.c
Go to the documentation of this file.
1 /*
2 
3  $Id: transformer_list.c 23120 2016-06-29 16:30:17Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 /* Functions to deal with transformer lists.
25  *
26  * Tansformer lists are used to delay convex hulls and to refine the
27  * precondition computation of loops by putting aside the identity
28  * transformer.
29  *
30  * If there is an identity transformer in the list, it is supposed to
31  * be the first one in the list.
32  *
33  * However, some control paths are almost identity transformers
34  * because the store is apparently unchanged. However, they contain
35  * predicates on the possible values. Although they have no arguments,
36  * and hence, the store is left unchanged, they are different from the
37  * identity transformer bebcause the relation is smaller.
38  *
39  * So it should be up to the function using the transformer list to
40  * decide how to cope with transformers that restrict the identity
41  * transition.
42  */
43 #ifdef HAVE_CONFIG_H
44  #include "pips_config.h"
45 #endif
46 
47 #include <stdio.h>
48 
49 #include "boolean.h"
50 #include "vecteur.h"
51 #include "contrainte.h"
52 #include "sc.h"
53 
54 #include "genC.h"
55 #include "linear.h"
56 #include "ri.h"
57 #include "ri-util.h"
58 #include "properties.h"
59 
60 #include "misc.h"
61 /* Must not be used, beware of library cycles: #include "semantics.h" */
62 
63 #include "transformer.h"
64 
65 /* Union of two lists
66 
67  If the list includes the identity transformer, it must be the first
68  in the list and be nowehere else
69 
70  It is not clear if transformer lists will be stored in hash
71  tables... Hence I do not know if the input list should be freed,
72  reused or left unshared. To be conservative, no alias is created.
73  */
75 {
76  list ntl = NIL;
77  list ntl1 = NIL;
78  list ntl2 = NIL;
79 
80  if(ENDP(tl1))
81  ntl = gen_full_copy_list(tl2);
82  else if(ENDP(tl2))
83  ntl = gen_full_copy_list(tl1);
84  else {
85  /* Do we have to worry about different bases in transformers? */
86  transformer t1 = TRANSFORMER(CAR(tl1));
87  transformer t2 = TRANSFORMER(CAR(tl2));
88 
89  /* Too much information is sometimes lost with this
90  simplification */
91  /*
92  if(ENDP(transformer_arguments(t1))) {
93  free_transformer(t1);
94  t1 = transformer_identity();
95  }
96 
97  if(ENDP(transformer_arguments(t2))) {
98  free_transformer(t2);
99  t2 = transformer_identity();
100  }
101  */
102 
105  }
106  if(transformer_identity_p(t1))
107  ntl1 = gen_full_copy_list(CDR(tl1));
108  else
109  ntl1 = gen_full_copy_list(tl1);
110  if(transformer_identity_p(t2))
111  ntl2 = gen_full_copy_list(CDR(tl2));
112  else
113  ntl2 = gen_full_copy_list(tl2);
114  ntl1 = gen_nconc(ntl1, ntl2);
115  ntl = gen_nconc(ntl, ntl1);
116  }
117 
118  ifdebug(1) {
119  int ntll = gen_length(ntl);
120  int tl1l = gen_length(tl1);
121  int tl2l = gen_length(tl2);
122  pips_assert("The new list is about the sum of the input lists.\n",
123  ntll>=tl1l+tl2l-1 && ntll<=tl1l+tl2l);
124  pips_assert("The new transformer list is legal",
126  }
127  return ntl;
128 }
129 
130 
131 /* What do we want to impose?
132  *
133  * 1. Only one identity transformer
134  *
135  * 2. Common basis?
136  *
137  * 3. No empty transformer
138  *
139  */
141 {
142  bool identity_p = false;
143  // unused: bool one_p = false; // useless for the time being
144 
145  if(ENDP(tl)) {
146  /* The empty transformer list is used to represent the empty
147  transformer... */
148  ;
149  }
150  else {
151  FOREACH(TRANSFORMER, tf, tl) {
152  if(transformer_identity_p(tf)) {
153  if(identity_p) {
154  pips_internal_error("Two identity transformers in one list.");
155  }
156  else {
157  identity_p = true;
158  }
159  }
160  }
161  if(identity_p) {
162  /* It must be the first one */
164  pips_internal_error("The identity transformer is not the list header.");
165  }
166 
167  FOREACH(TRANSFORMER, tf, tl) {
168  if(transformer_empty_p(tf))
169  pips_internal_error("An empty transformer has been found.");
170  }
171  }
172 
173  return true;
174 }
175 
176 /* each transformer of tl1 must be combined with a transformer of
177  tl2, including the identity transformer. If an identity
178  transformer is generated and if identity transformers are always
179  first in the list, it will again be first in the returned list. */
181 {
182  list ntl = NIL;
183  int n1 = gen_length(tl1);
184  int n2 = gen_length(tl2);
185  int en = 0;
186  int nn = -1;
187 
188  pips_assert("tl1 is OK\n", check_transformer_list(tl1));
189  pips_assert("tl2 is OK\n", check_transformer_list(tl2));
190 
191  FOREACH(TRANSFORMER, t1, tl1) {
192  FOREACH(TRANSFORMER, t2, tl2) {
194 
195  // transformer_empty_p() is not strong enough currently
196  // It does not detect that k<= 2 && k>=3 is empty...
197  nt = transformer_normalize(nt, 2);
198  if(!transformer_empty_p(nt))
199  ntl = CONS(TRANSFORMER, nt, ntl);
200  else
201  en++;
202  }
203  }
204  ntl = gen_nreverse(ntl);
205 
206  nn = gen_length(ntl);
207  pips_assert("ntl is OK\n", check_transformer_list(ntl));
208  pips_assert("nn is n1*n2-en", nn==n1*n2-en);
209 
210  return ntl;
211 }
212 
213 /* each transformer of tl1 must be applied to each precondition of
214  tl2, including the identity transformer. If an identity
215  transformer is generated and if identity transformers are always
216  first in the list, it will again be first in the returned
217  list. Empty preconditions are not preserved in the returned
218  list. An empty list is unfeasible.
219 
220  if exclude_p==false, return U_i1 U_i2 apply(t_i1, p_i2);
221  else return U_i1 U_i2!=i1 apply(t_i1, p_i2);
222  */
224 {
225  list ntl = NIL;
226  int n1 = gen_length(tl1);
227  int n2 = gen_length(tl2);
228  int en = 0; // number of empty preconditions generated
229  int sn = 0; // number of excluded/skipped preconditions
230  int nn = -1; // number of preconditions in the result
231  int i1 = 0;
232 
233  // FI: not true is option keep_p has been used to maintain
234  //|tl_1|==|tl_2| which is useful when exclude_p is TRUE
235  if(!exclude_p) {
236  pips_assert("tl1 is OK\n", check_transformer_list(tl1));
237  pips_assert("tl2 is OK\n", check_transformer_list(tl2));
238  }
239 
240  FOREACH(TRANSFORMER, t1, tl1) {
241  int i2 = 0;
242  i1++;
243  FOREACH(TRANSFORMER, t2, tl2) {
244  i2++;
245  if(i1!=i2 && exclude_p) {
246  transformer nt = transformer_apply(t1, t2);
247 
248  if(!transformer_empty_p(nt))
249  ntl = CONS(TRANSFORMER, nt, ntl);
250  else
251  en++;
252  }
253  else if(exclude_p)
254  sn++;
255  }
256  }
257  ntl = gen_nreverse(ntl);
258 
259  nn = gen_length(ntl);
260  pips_assert("nn is n1*n2-en", nn==n1*n2-en-sn);
261  //FI: there is no guarantee here that the identity transformer is
262  //not returned multiple times... although it would make sense if the
263  //input lists are properly sorted.
264  pips_assert("ntl is OK\n", check_transformer_list(ntl));
265 
266  return ntl;
267 }
268 
270 {
271  return apply_transformer_lists_generic(tl1, tl2, false);
272 }
273 
275 {
276  return apply_transformer_lists_generic(tl1, tl2, true);
277 }
278 
279 /* Eliminate empty transformers and keep at most one identity
280  * transformer, placed as first list element.
281  *
282  * check_transformer_list(ntfl) should be TRUE.
283  *
284  * tfl is fully destroyed (to avoid memory leaks and nightmares); to
285  * be more efficient, the transformers moved from the input list into
286  * the output list should be detached from the input list and then the
287  * input list could be fully destroyed without having to copy any
288  * transformers; but FOREACH operates at too high a level for this.
289  */
291 {
292  list ntfl = NIL;
293  bool identity_p = false;
294 
295  FOREACH(TRANSFORMER, tf, tfl) {
296  bool tf_identity_p = transformer_identity_p(tf);
297  if(!tf_identity_p && !transformer_empty_p(tf))
298  ntfl = CONS(TRANSFORMER, copy_transformer(tf), ntfl);
299  identity_p = identity_p || tf_identity_p;
300  }
301  gen_full_free_list(tfl);
302  ntfl = gen_nreverse(ntfl);
303  if(identity_p)
304  ntfl = CONS(TRANSFORMER, transformer_identity(), ntfl);
305  return ntfl;
306 }
307 
308 /* Transformer two transformers into a correct transformer list
309  *
310  * Could be generalized to any number of transformers using a
311  * varargs... and more thinking.
312  *
313  * Two transformers are obtained for loops that may be skipped or
314  * entered and for tests whose condition is not statically decidable.
315  */
317 {
318  list tl = NIL;
319  if(transformer_empty_p(t1)) {
320  if(transformer_empty_p(t2)) {
321  tl = NIL;
322  }
323  else {
324  tl = CONS(TRANSFORMER, t2, NIL);
325  }
326  }
327  else {
328  if(transformer_empty_p(t2)) {
329  tl = CONS(TRANSFORMER, t1, NIL);
330  }
331  else {
332 
333  /* This is a very dangerous step that should not always be
334  taken. It is useful to ease the detection of identity
335  paths, but it looses a lot of information. So almost
336  identity path might simply be better identified elsewhere */
337  /*
338  if(ENDP(transformer_arguments(t1))) {
339  free_transformer(t1);
340  t1 = transformer_identity();
341  }
342 
343  if(ENDP(transformer_arguments(t2))) {
344  free_transformer(t2);
345  t2 = transformer_identity();
346  }
347  */
348 
349  if(transformer_identity_p(t1)) {
350  if(transformer_identity_p(t2)) {
351  tl = CONS(TRANSFORMER, t1, NIL);
352  free_transformer(t2);
353  }
354  else {
355  tl = CONS(TRANSFORMER, t1,
356  CONS(TRANSFORMER, t2, NIL));
357  }
358  }
359  else {
360  if(transformer_identity_p(t2)) {
361  tl = CONS(TRANSFORMER, t2,
362  CONS(TRANSFORMER, t1, NIL));
363  }
364  else {
365  tl = CONS(TRANSFORMER, t1,
366  CONS(TRANSFORMER, t2, NIL));
367  }
368  }
369  }
370  }
371  return tl;
372 }
373 
374 /* Reduce the transformer list with the convex hull operator.
375  *
376  * If active_p is true, skip transformers that do not update the
377  * state. Beyond the identity transformer, any transformer without
378  * arguments does not really update the state, although it may
379  * restrict it.
380  *
381  * A new transformer is always allocated. The transformers in the
382  * transformer list ltl are freed.
383  */
385 {
386  transformer ltf = transformer_undefined; // list transformer
387 
388  if(ENDP(ltl))
389  ltf = transformer_empty();
390  else {
391  list ctl = ltl;
392  /* Look for the first useful transformer in the list */
393  FOREACH(TRANSFORMER, tf, ltl) {
394  if(!active_p || !ENDP(transformer_arguments(tf))) {
395  ltf = copy_transformer(tf);
396  free_transformer(tf);
397  POP(ctl);
398  break;
399  }
400  POP(ctl);
401  }
402  if(ENDP(ctl)) {
403  if(transformer_undefined_p(ltf))
404  /* Only range conditions have been found: the store is
405  restricted but not changed. */
406  ltf = transformer_identity();
407  }
408  else {
409  /* Take care of the following useful transformers */
410  while(!ENDP(ctl)) {
411  /* Look for the next useful transformer in the list */
412  FOREACH(TRANSFORMER, tf, ctl) {
413  if(!active_p || !ENDP(transformer_arguments(tf))) {
414  transformer ntf = copy_transformer(tf);
415  transformer ptf = ltf;
416  ltf = transformer_convex_hull(ptf, ntf);
417  free_transformer(ntf);
418  free_transformer(ptf);
419  POP(ctl);
420  break;
421  }
422  POP(ctl);
423  }
424  }
425  }
426  }
427 
428  return ltf;
429 }
430 
431 /* Reduce the transformer list ltl to one transformer using the convex
432  * hull operator.
433  */
435 {
436  return generic_transformer_list_to_transformer(ltl, false);
437 }
438 
439 /* Reduce the sublist of active transformers in the transformer list
440  * ltl to one transformer using the convex hull operator. An active
441  * transformer is a transformer with argument(s): at least one value
442  * is changed.
443  *
444  * Note: a hidden identity transformer such as T(i) {i==i#init} is not
445  * detected.
446  */
448 {
449  return generic_transformer_list_to_transformer(ltl, true);
450 }
451 
452 // Remove all inactive transformers from ltl and generate a new list
453 // with copied elements
455 {
456  list atl = NIL;
457 
458  FOREACH(TRANSFORMER, tf, tl) {
459  if(!ENDP(transformer_arguments(tf)))
460  atl = CONS(TRANSFORMER, copy_transformer(tf), atl);
461  }
462 
463  atl = gen_nreverse(atl);
464 
465  return atl;
466 }
467 
468 ␌
469 /* Compute the precondition of a loop whose body transformers T_i are
470  * in transformer list tl and whose condition is modelized by
471  * transformer c_t. The precondition of iteration 0 is p_0.
472  *
473  * We need a developped formulae for P*=(U_i T_i)^*P_0... to postpone
474  * the convex hulls as much as possible
475  *
476  * For instance, and this is a heuristics:
477  *
478  * P_0 is known as pre_init
479  *
480  * P_1 = U_i T_i(P_0)
481  *
482  * P_2 = U_i U_j T_i(T_j(P_0))
483  *
484  * P_3^s = U_i T_i^+(P_0) --- only one path is used
485  *
486  * P_3^+ = U_i U_j!=i T^+_i(T_j(T^*(P_1))) --- at least two
487  * paths are used
488  *
489  * which would make more sense when i and j are in
490  * [0..1]. Note that in P_3, T_j and T^+_i could be recomputed
491  * wrt P_1 instead of pre_fuzzy... which is not provided
492  *
493  * Maybe T^*=(U_i T_i)^* could/should be computed as (U_i T_i*)* but
494  * it is not clear how all the useful conditions could be taken into
495  * account.
496  *
497  * A more accurate approach would use several developped formulae for
498  * P* and an intersection of their results.
499  */
500 static transformer
502  transformer c_t,
503  transformer p_0)
504 {
506 
507  list p_1_l = transformers_apply(ntl, p_0);
509 
510  list t_2_l = combine_transformer_lists(ntl, ntl);
511  list p_2_l = transformers_apply(t_2_l, p_0);
513 
514  list itcl = transformers_derivative_fix_point(ntl); // individual
515  // transformer closures
516  itcl = transformers_combine(itcl, c_t);
517  list itcl_plus = gen_full_copy_list(itcl); // to preserve ictl
518  itcl_plus = one_to_one_transformers_combine(itcl_plus, ntl);
519  list p_3_l = transformers_apply(itcl_plus, p_0);
521 
523  if(!get_bool_property("SEMANTICS_USE_DERIVATIVE_LIST")) {
524  // Not satisfying: works only for the whole space, not for subpaces
525  // left untouched
527  }
528  else
530  transformer p_4_1 = transformer_apply(t_star, p_1); // one + * iteration
531  list p_4_2_l = transformers_apply_and_keep_all(ntl, p_4_1); // another iteration
532  pips_assert("itcl_plus and p_4_2_l have the same numer of elements",
533  gen_length(itcl_plus)==gen_length(p_4_2_l));
534  list p_4_3_l = apply_transformer_lists_with_exclusion(itcl_plus, p_4_2_l);
536 
538 
539  ifdebug(8) {
540  pips_debug(8, "p_0:\n");
541  print_transformer(p_0);
542  pips_debug(8, "p_1:\n");
543  print_transformer(p_1);
544  pips_debug(8, "p_2:\n");
545  print_transformer(p_2);
546  pips_debug(8, "p_3:\n");
547  print_transformer(p_3);
548  pips_debug(8, "p_4:\n");
549  print_transformer(p_4);
550  }
551 
552  // reduce p_0, p_1, p_2, p_3 and p_4 to p_star
553  transformer p_01 = transformer_convex_hull(p_0, p_1);
554  transformer p_012 = transformer_convex_hull(p_01, p_2);
555  transformer p_0123 = transformer_convex_hull(p_012, p_3);
556  p_star = transformer_convex_hull(p_0123, p_4);
557 
558  ifdebug(8) {
559  pips_debug(8, "p_star:\n");
560  print_transformer(p_star);
561  }
562 
563  // Clean up all intermediate variables
564  gen_full_free_list(ntl);
565  //gen_full_free_list(p_1_l);
566  free_transformer(p_1);
567  //gen_full_free_list(t_2_l);
568  //gen_full_free_list(p_2_l);
569  free_transformer(p_2);
570  //gen_full_free_list(itcl);
571  gen_full_free_list(itcl_plus);
572  //gen_full_free_list(p_3_l);
573  free_transformer(p_3);
574  free_transformer(t_star);
575  free_transformer(p_4_1);
576  gen_full_free_list(p_4_2_l);
577  //gen_full_free_list(p_4_3_l);
578  free_transformer(p_4);
579  free_transformer(p_01);
580  free_transformer(p_012);
581  free_transformer(p_0123);
582  pips_assert("p_star is consistent", transformer_consistency_p(p_star));
583  return p_star;
584 }
585 
586 /* Compute the precondition of a loop whose body transformers T_i are
587  * in transformer list tl and whose condition is modelized by
588  * transformer c_t. The precondition of iteration 0 is p_0.
589  *
590  * We need a developped formulae for P*=(U_i T_i)^*P_0... to postpone
591  * the convex hulls as much as possible
592  *
593  * For instance, and this is a heuristics:
594  *
595  * P_0 is known as pre_init
596  *
597  * P_l = U_i T_i(P_0)
598  *
599  * P_2 = U_i U_j T_i(T_j(P_0))
600  *
601  * P_3^s = U_i T_i^+(P_0) --- only one path is used
602  *
603  * P_3^+ = U_i U_j!=i T^+_i(T_j(T^*(P_1))) --- at least two
604  * paths are used
605  *
606  * which would make more sense when i and j are in
607  * [0..1]. Note that in P_3, T_j and T^+_i could be recomputed
608  * wrt P_1 instead of pre_fuzzy... which is not provided
609  *
610  * Maybe T^*=(U_i T_i)^* could/should be computed as (U_i T_i*)* but
611  * it is not clear how all the useful conditions could be taken into
612  * account.
613  *
614  * A more accurate approach would use several developped formulae for
615  * P* and an intersection of their results.
616  */
617 static transformer
619  transformer c_t,
620  transformer p_0)
621 {
623  //pips_assert("ntl is OK", check_transformer_list(ntl));
624 
625  list p_1_l = transformers_apply(ntl, p_0);
627 
628  list t_2_l = combine_transformer_lists(ntl, ntl);
629  list p_2_l = transformers_apply(t_2_l, p_0);
631 
632  list itcl = transformers_derivative_fix_point(ntl); // individual
633  // transformer closures
634  itcl = transformers_combine(itcl, c_t);
635  list itcl_plus = gen_full_copy_list(itcl); // to preserve ictl
636  itcl_plus = one_to_one_transformers_combine(itcl_plus, ntl);
637  list p_3_l = transformers_apply(itcl_plus, p_0);
639 
641  if(!get_bool_property("SEMANTICS_USE_DERIVATIVE_LIST")) {
642  // Not satisfying: works only for the whole space, not for subpaces
643  // left untouched
645  }
646  else
648  transformer p_4_1 = transformer_apply(t_star, p_1); // one + * iteration
649  list p_4_2_l = transformers_apply_and_keep_all(ntl, p_4_1); // another iteration
650  pips_assert("itcl_plus and p_4_2_l have the same numer of elements",
651  gen_length(itcl_plus)==gen_length(p_4_2_l));
652  list p_4_3_l = apply_transformer_lists_with_exclusion(itcl_plus, p_4_2_l);
654 
656 
657  ifdebug(8) {
658  pips_debug(8, "p_0:\n");
659  print_transformer(p_0);
660  pips_debug(8, "p_1:\n");
661  print_transformer(p_1);
662  pips_debug(8, "p_2:\n");
663  print_transformer(p_2);
664  pips_debug(8, "p_3:\n");
665  print_transformer(p_3);
666  pips_debug(8, "p_4:\n");
667  print_transformer(p_4);
668  }
669 
670  // reduce p_0, p_1, p_2, p_3 and p_4 to p_star
671  transformer p_01 = transformer_convex_hull(p_0, p_1);
672  transformer p_012 = transformer_convex_hull(p_01, p_2);
673  transformer p_0123 = transformer_convex_hull(p_012, p_3);
674  p_star = transformer_convex_hull(p_0123, p_4);
675 
676  ifdebug(8) {
677  pips_debug(8, "p_star:\n");
678  print_transformer(p_star);
679  }
680 
681  // Clean up all intermediate variables
682  gen_full_free_list(ntl);
683  //gen_full_free_list(p_1_l);
684  free_transformer(p_1);
685  //gen_full_free_list(t_2_l);
686  //gen_full_free_list(p_2_l);
687  free_transformer(p_2);
688  //gen_full_free_list(itcl);
689  gen_full_free_list(itcl_plus);
690  //gen_full_free_list(p_3_l);
691  free_transformer(p_3);
692  free_transformer(t_star);
693  free_transformer(p_4_1);
694  gen_full_free_list(p_4_2_l);
695  //gen_full_free_list(p_4_3_l);
696  free_transformer(p_4);
697  free_transformer(p_01);
698  free_transformer(p_012);
699  free_transformer(p_0123);
700 
701  return p_star;
702 }
703 
704 /* Relay to select a heuristic */
706  transformer c_t,
707  transformer p_0)
708 {
710  const char* h = get_string_property("SEMANTICS_LIST_FIX_POINT_OPERATOR");
711 
712  if(strcmp(h, "depth_two")) {
714  }
715  else if(strcmp(h, "max_depth")) {
717  }
718  else
719  pips_user_error("Unknown value \"%s\" for property "
720  "\"SEMANTICS_LIST_FIX_POINT_OPERATOR\"", h);
721  pips_assert("prec is consistent", transformer_consistency_p(p_star));
722  return p_star;
723 }
724 ␌
725 /* Returns a new list of newly allocated projected transformers. If a
726  * value of a variable in list proj appears in t of tl, it is
727  * projected. New transformers are allocated to build the projection
728  * list.
729  */
731 {
732  list ptl = NIL;
733  FOREACH(TRANSFORMER, t, tl) {
734  list apl = NIL; // actual projection list
736  FOREACH(ENTITY, v, proj) {
738  entity ov = entity_to_old_value(v);
739  apl = CONS(ENTITY, ov, apl);
740  }
741  apl = CONS(ENTITY, v, apl);
742  }
743  nt = safe_transformer_projection(nt, apl);
744  ptl = CONS(TRANSFORMER, nt, ptl);
745  gen_free_list(apl);
746  }
747  ptl = gen_nreverse(ptl);
748  return ptl;
749 }
750 ␌
751 /* Returns the list of variables modified by at least one transformer
752  in tl */
754 {
755  list vl = NIL;
756 
757  FOREACH(TRANSFORMER, t, tl) {
759  if(!gen_in_list_p(v, vl))
760  vl = CONS(ENTITY, v, vl);
761  }
762  }
763 
764  vl = gen_nreverse(vl);
765 
766  return vl;
767 }
768 
769 /* build a sublist sl of the transformer list tl with transformers that
770  modify the value of variable v */
772 {
773  list sl = NIL;
774 
775  FOREACH(TRANSFORMER, t, tl){
777  sl = CONS(TRANSFORMER, t, sl);
778  }
779  sl = gen_nreverse(sl);
780  return sl;
781 }
782 
783 /* returns the list of variables in vl which are not modified by
784  transformers belonging to tl-tl_v. tl_v is assumed to be a subset
785  of tl. */
787 {
788  list pvl = NIL;
789 
790  FOREACH(ENTITY, v, vl) {
791  bool found_p = false;
792  FOREACH(TRANSFORMER, t, tl) {
793  if(!gen_in_list_p(t, tl_v)) {
795  found_p = true;
796  break;
797  }
798  }
799  }
800  if(!found_p) {
801  pvl = CONS(ENTITY, v, pvl);
802  }
803  }
804 
805  pvl = gen_nreverse(pvl);
806 
807  return pvl;
808 }
809 ␌
810 /* When some variables are not modified by some transformers, use
811  projections on subsets to increase the number of identity
812  transformers and to increase the accuracy of the loop precondition.
813 
814  The preconditions obtained with the different projections are
815  intersected.
816 
817  FI: this may be useless when derivatives are computed before the
818  convex union. No. This was due to a bug in the computation of list
819  of derivatives.
820 
821  FI: this should be mathematically useless but it useful when a
822  heuristic is used to compute the invariant. The number of
823  transitions is reduced and hence a limited number of combinations
824  is more likely to end up with a precise result.
825  */
827  transformer c_t,
828  transformer p_0)
829 {
831 
832  if(get_bool_property("SEMANTICS_USE_LIST_PROJECTION")) {
833  list al = transformer_arguments(prec);
834  list vl = transformer_list_to_argument(tl); // list of modified
835  // variables
836  // FI: this is too strong vl must only be included in transformer_arguments(prec)
837  //pips_assert("all modified variables are argument of the global precondition",
838  //arguments_equal_p(vl, transformer_arguments(prec)));
839  FOREACH(ENTITY, v, vl) {
840  // FI: the same projection could be obtained for different
841  // variables v and the computation should not be performed again
842  // but I choose not to memoize past lists tl_v
843  list tl_v = transformer_list_with_effect(tl, v);
844 
845  if(gen_length(tl_v)<gen_length(tl)) {
846  list keep_v = transformer_list_preserved_variables(vl, tl, tl_v);
847  list proj_v = arguments_difference(vl, keep_v);
848  list ptl_v = transformer_list_safe_variables_projection(tl_v, proj_v);
849  transformer p_0_v
851  transformer c_t_v
853  transformer prec_v
854  = transformer_list_closure_to_precondition(ptl_v, c_t_v, p_0_v);
855  if(arguments_subset_p(transformer_arguments(prec_v), al)) {
856  // FI: this generates an inconsistent transformer if
857  // transformer_arguments(prec_v) is not a subset of al...
858  transformer_arguments(prec_v) = gen_copy_seq(al); // memory leak
859  }
860  else {
861  transformer n_prec_v = transformer_range(prec_v);
862  free_transformer(prec_v);
863  prec_v = n_prec_v;
864  transformer_arguments(prec_v) = gen_copy_seq(al);
865  }
866  prec = transformer_intersection(prec, prec_v); // memory leak
867  // transformer_intersection() returns an inconsistent transformer
868  // The argument list is empty but an old value is used in the conditions
869  // prec = transformer_range(prec); // memory leak
870  pips_assert("prec is consistent", transformer_consistent_p(prec));
871 
872  free_transformer(prec_v);
873  free_transformer(c_t_v);
874  free_transformer(p_0_v);
875  gen_full_free_list(ptl_v);
876  gen_free_list(keep_v);
877  }
878  gen_free_list(tl_v);
879  }
880 
881  gen_free_list(vl);
882  }
883  pips_assert("prec is consistent", transformer_consistency_p(prec));
884  return prec;
885 }
886 
887 /* Allocate a new constraint system sc(dx) with dx=x'-x and t(x,x')
888  *
889  * FI: this function should/might be located in fix_point.c
890  */
892 {
894  /* sc is going to be modified and returned */
895  /* Do not handle variable which do not appear explicitly in constraints! */
896  Pbase b = sc_to_minimal_basis(sc);
897  Pbase bv = BASE_NULLE; /* basis vector */
898 
899  /* Compute constraints with difference equations */
900 
901  for(bv = b; !BASE_NULLE_P(bv); bv = bv->succ) {
902  entity oldv = (entity) vecteur_var(bv);
903 
904  /* Only generate difference equations if the old value is used */
905  if(old_value_entity_p(oldv)) {
906  entity var = value_to_variable(oldv);
907  entity newv = entity_to_new_value(var);
909  Pvecteur diff = VECTEUR_NUL;
911 
912  diff = vect_make(diff,
913  (Variable) diffv, VALUE_ONE,
914  (Variable) newv, VALUE_MONE,
915  (Variable) oldv, VALUE_ONE,
916  TCST, VALUE_ZERO);
917 
918  eq = contrainte_make(diff);
919  sc = sc_equation_add(sc, eq);
920  }
921  }
922 
923  ifdebug(8) {
924  pips_debug(8, "with difference equations=\n");
925  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
926  }
927 
928  /* Project all variables but differences to get T' */
929 
930  sc = sc_projection_ofl_along_variables(sc, b);
931 
932  ifdebug(8) {
933  pips_debug(8, "Non-homogeneous constraints on derivatives=\n");
934  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
935  }
936 
937  return sc;
938 }
939 ␌
940 /* Computation of an upper approximation of a transitive closure using
941  * constraints on the discrete derivative for a list of
942  * transformers. Each transformer is used to compute its derivative
943  * and the derivatives are unioned by convex hull.
944  *
945  * The reason for doing this is D(T1) U D(T2) == D(T1 U T2) but the
946  * complexity is lower
947  *
948  * See http://www.cri.ensmp.fr/classement/doc/A-429.pdf
949  *
950  * Implicit equations, n#new - n#old = 0, are added because they are
951  * necessary for the convex hull.
952  *
953  * Intermediate values are used to encode the differences. For instance,
954  * i#int = i#new - i#old
955  */
956 /* This code was cut-and-pasted from
957  transformer_derivative_fix_point() but is more general and subsume
958  it */
959 /* transformer transformer_derivative_fix_point(transformer tf)*/
961 {
963 
964  ifdebug(8) {
965  pips_debug(8, "Begin for transformer list %p:\n", tfl);
966  print_transformers(tfl);
967  }
968 
969  if(ENDP(tfl)) {
970  if(star_p) {
971  /* Since we compute the * transitive closure and not the +
972  transitive closure, the fix point is the identity. */
973  tc_tf = transformer_identity();
974  }
975  else {
976  tc_tf = transformer_empty();
977  }
978  }
979  else {
980  // Pbase ib = base_dup(sc_base(sc)); /* initial and final basis */
981  Pbase ib = BASE_NULLE;
982  Pbase diffb = BASE_NULLE; /* basis of difference vectors */
983  Pbase bv = BASE_NULLE;
984  Pbase b = BASE_NULLE;
985 
986  /* Compute the global argument list and the global base b */
987  list gal = NIL;
988  FOREACH(TRANSFORMER, t, tfl) {
989  list al = transformer_arguments(t);
990  /* Cannot use arguments_union() because a new list is allocated */
991  FOREACH(ENTITY, e, al)
992  gal = arguments_add_entity(gal, e);
993 
994  // FI: this copy is almost entirely memory leaked
996  // redundant with call to transformer_derivative_constraints(t)
997  Pbase tb = sc_to_minimal_basis(sc);
998  Pbase nb = base_union(b, tb);
999  base_rm(b); // base_union() allocates a new base
1000  b = nb;
1001  }
1002 
1003  /* For each transformer t in list tl
1004  *
1005  * compute its derivative constraint system
1006  *
1007  * add the equations for the unchanged variables
1008  *
1009  * compute its convex hull with the current value of sc if sc is
1010  * already defined
1011  */
1012  Psysteme sc = SC_UNDEFINED;
1013  FOREACH(TRANSFORMER, t, tfl) {
1015  FOREACH(ENTITY,e,gal) {
1017  /* Add corresponding equation */
1019  Pvecteur diff = VECTEUR_NUL;
1021 
1022  diff = vect_make(diff,
1023  (Variable) diffv, VALUE_ONE,
1024  TCST, VALUE_ZERO);
1025 
1026  eq = contrainte_make(diff);
1027  tsc = sc_equation_add(tsc, eq);
1028  }
1029  }
1030  if(SC_UNDEFINED_P(sc))
1031  sc = tsc;
1032  else {
1033  /* This could be optimized by using the convex hull of a
1034  Psystemes list and by keeping the dual representation of
1035  the result instead of converting it several time back
1036  and forth. */
1037  Psysteme nsc = cute_convex_union(sc, tsc);
1038  sc_free(sc);
1039  sc = nsc;
1040  }
1041  }
1042 
1043  /* Multiply the constant terms by the iteration number ik and add a
1044  positivity constraint for the iteration number ik and then
1045  eliminate the iteration number ik to get T*(dx). */
1047  //Psysteme sc_t_prime_k = sc_dup(sc);
1048  //sc_t_prime_k = sc_multiply_constant_terms(sc_t_prime_k, (Variable) ik);
1049  sc = sc_multiply_constant_terms(sc, (Variable) ik, star_p);
1050  //Psysteme sc_t_prime_star = sc_projection_ofl(sc_t_prime_k, (Variable) ik);
1051  sc = sc_projection_ofl(sc, (Variable) ik);
1052  if(SC_EMPTY_P(sc)) {
1053  sc = sc_empty(BASE_NULLE);
1054  }
1055  else {
1056  sc->base = base_remove_variable(sc->base, (Variable) ik);
1057  sc->dimension--;
1058  // FI: I do not remember nor find how to get rid of local values...
1059  //sc_rm(sc);
1060  //sc = sc_t_prime_star;
1061  }
1062 
1063  ifdebug(8) {
1064  pips_debug(8, "All invariants on derivatives=\n");
1065  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1066  }
1067 
1068  /* Difference variables must substituted back to differences
1069  * between old and new values.
1070  */
1071 
1072  for(bv = b; !BASE_NULLE_P(bv); bv = bv->succ) {
1073  entity oldv = (entity) vecteur_var(bv);
1074 
1075  /* Only generate difference equations if the old value is used */
1076  if(old_value_entity_p(oldv)) {
1077  entity var = value_to_variable(oldv);
1078  entity newv = entity_to_new_value(var);
1079  entity diffv = entity_to_intermediate_value(var);
1080  Pvecteur diff = VECTEUR_NUL;
1082 
1083  diff = vect_make(diff,
1084  (Variable) diffv, VALUE_ONE,
1085  (Variable) newv, VALUE_MONE,
1086  (Variable) oldv, VALUE_ONE,
1087  TCST, VALUE_ZERO);
1088 
1089  eq = contrainte_make(diff);
1090  sc = sc_equation_add(sc, eq);
1091  diffb = base_add_variable(diffb, (Variable) diffv);
1092  ib = base_add_variable(ib, (Variable) oldv);
1093  ib = base_add_variable(ib, (Variable) newv);
1094  }
1095  }
1096 
1097  ifdebug(8) {
1098  pips_debug(8,
1099  "All invariants on derivatives with difference variables=\n");
1100  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1101  }
1102 
1103  /* Project all difference variables */
1104 
1105  sc = sc_projection_ofl_along_variables(sc, diffb);
1106 
1107  ifdebug(8) {
1108  pips_debug(8, "All invariants on differences=\n");
1109  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1110  }
1111 
1112  /* The full basis must be used again */
1113  base_rm(sc_base(sc)), sc_base(sc) = BASE_NULLE;
1114  sc_base(sc) = ib;
1115  sc_dimension(sc) = vect_size(ib);
1116  base_rm(b), b = BASE_NULLE;
1117 
1118  ifdebug(8) {
1119  pips_debug(8, "All invariants with proper basis =\n");
1120  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1121  }
1122 
1123  /* Plug sc back into tc_tf */
1125  transformer_arguments(tc_tf) = gal;
1126 
1127  }
1128  /* That's all! */
1129 
1130  ifdebug(8) {
1131  pips_debug(8, "Transitive closure tc_tf=\n");
1134  pips_debug(8, "end\n");
1135  }
1136 
1137  return tc_tf;
1138 }
1139 
1140 /* Compute (U tfl)* */
1142 {
1144 }
1145 
1146 /* Compute (U tfl)+ */
1148 {
1150 }
1151 ␌
1152 /* Internal recursive function. Should be used as
1153  * transformer_list_combination(). As long as n is not zero, choose
1154  * all unused transformation numbers in past and call yourself
1155  * recursively after updating past and ct. past is a bit field. Each
1156  * bit of past is set to 1 initially because no transformer has been
1157  * used yet. It is reset to 0 when the transformation has been
1158  * used. The selected transformer is combined to ct.
1159  *
1160  * @param tn is the number of transformers that can be chosen to be
1161  * combined
1162  *
1163  * @param ta[tn] is an array containing the tn transformers to combine
1164  *
1165  * @param n is the number of combinations to perform. It is less than
1166  * tn.
1167  *
1168  * @param ct is the current combination of past transformers
1169  *
1170  * @param past is a bit field used to keep track of transformers
1171  * alreasy used to build ct
1172  *
1173  * @return the list of all non-empty combinations of n transformers
1174  */
1176  transformer ta[tn],
1177  int n,
1178  transformer ct,
1179  int past)
1180 {
1181  list cl = NIL;
1182 
1183  if(n>0) {
1184  int k = 1; // to select a non-zero bit in past
1185  int ti; // transformation index
1186  bool found_p = false;
1187  for(ti=0; ti<n;ti++) {
1188  if(k&past) {
1189  // this transformation is selectable, because it has not been
1190  // selected yet
1191  int npast = past ^ k; // mark it as selected
1192  transformer t = ta[ti]; // to ease debugging
1194  // Necessary before checking emptiness
1195  nct = transformer_normalize(nct, 2);
1196  // Check the sequence feasability
1197  if(!transformer_empty_p(nct)) {
1198  list nl = transformer_list_add_combination(tn, ta, n-1, nct, npast);
1199  cl = gen_nconc(cl, nl);
1200  }
1201  found_p = true;
1202  free_transformer(nct);
1203  }
1204  k <<= 1;
1205  }
1206  pips_assert("At least one transformation has been found", found_p);
1207  }
1208  else {
1209  // The recursion is over, ct contains the right number of
1210  // transformer combinations
1211  cl = CONS(TRANSFORMER, ct, NIL);
1212  }
1213  return cl;
1214 }
1215 
1216 /* compute all combinations of n different transformers t from
1217  * transformer list tl. No check is performed on the content of list
1218  * tl. Empty transformers and identity transformers should have been
1219  * removed before this call.
1220  *
1221  * @param tl: a non-empty list of transformers
1222  *
1223  * int n: a strictly positive integer, smaller than the length of tl
1224  *
1225 */
1226 static list __attribute__ ((unused)) transformer_list_combination(list tl, int n)
1227 {
1228  list cl = NIL;
1229  int tn = gen_length(tl);
1230 
1231  pips_assert("n is smaller than the number of transformers",
1232  n <= tn && n>=1 && n<=31);
1233 
1234  transformer ta[tn]; // build a transformer array
1235  int r = 0;
1236 
1237  FOREACH(TRANSFORMER, t, tl) {
1238  ta[r++] = t;
1239  }
1240 
1241  // Initialize recurrence
1243  cl = transformer_list_add_combination(tn, ta, n, ct, -1);
1244  free_transformer(ct);
1245 
1246  return cl;
1247 }
void free_transformer(transformer p)
Definition: ri.c:2616
bool transformer_consistent_p(transformer p)
Definition: ri.c:2622
transformer copy_transformer(transformer p)
TRANSFORMER.
Definition: ri.c:2613
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
cons * arguments_add_entity(cons *a, entity e)
Definition: arguments.c:85
bool arguments_subset_p(list a1, list a2)
Check if a1 is a subset of a2.
Definition: arguments.c:204
cons * arguments_difference(cons *a1, cons *a2)
set difference: a1 - a2 ; similar to set intersection
Definition: arguments.c:233
#define VALUE_ZERO
#define VALUE_MONE
#define VALUE_ONE
Pbase base_add_variable(Pbase b, Variable var)
Pbase base_add_variable(Pbase b, Variable v): add variable v as a new dimension to basis b at the end...
Definition: base.c:88
Pbase base_remove_variable(Pbase b, Variable v)
Pbase base_remove_variable(b, v): remove basis vector relative to v from b; abort if v is not in b;.
Definition: base.c:122
Pbase base_union(Pbase b1, Pbase b2)
Pbase base_union(Pbase b1, Pbase b2): compute a new basis containing all elements of b1 and all eleme...
Definition: base.c:428
bool transformer_identity_p(transformer t)
Check that t is an identity function.
Definition: basic.c:154
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
bool transformer_consistency_p(transformer t)
FI: I do not know if this procedure should always return or fail when an inconsistency is found.
Definition: basic.c:612
transformer transformer_empty()
Allocate an empty transformer.
Definition: basic.c:120
#define CONTRAINTE_UNDEFINED
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
char * get_string_property(const char *)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
list transformers_derivative_fix_point(list tl)
Definition: fix_point.c:1262
Psysteme sc_multiply_constant_terms(Psysteme sc, Variable ik, bool star_p)
Specific for the derivative fix point: each constant term in the constraints is multiplied by ik whic...
Definition: fix_point.c:1013
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define pips_user_error
Definition: misc-local.h:147
transformer fprint_transformer(FILE *fd, transformer tf, get_variable_name_t value_name)
Definition: io.c:69
list print_transformers(list tl)
Definition: io.c:62
#define print_transformer(t)
Definition: print.c:357
Psysteme cute_convex_union(Psysteme s1, Psysteme s2)
debug messages before calling the version in polyedre.
Definition: convex_hull.c:41
#define transformer_undefined
Definition: ri.h:2847
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define TRANSFORMER(x)
TRANSFORMER.
Definition: ri.h:2841
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define transformer_relation(x)
Definition: ri.h:2873
#define transformer_arguments(x)
Definition: ri.h:2871
#define predicate_system(x)
Definition: ri.h:2069
Psysteme sc_empty(Pbase b)
Psysteme sc_empty(Pbase b): build a Psysteme with one unfeasible constraint to define the empty subsp...
Definition: sc_alloc.c:319
Pbase sc_to_minimal_basis(Psysteme ps)
creation d'une base contenant toutes les variables apparaissant avec des coefficients non-nuls dans l...
Definition: sc_alloc.c:76
Psysteme sc_copy(Psysteme ps)
Psysteme sc_copy(Psysteme ps): duplication d'un systeme (allocation et copie complete des champs sans...
Definition: sc_alloc.c:230
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
Psysteme sc_equation_add(Psysteme sc, Pcontrainte c)
The basis of the constraint system is updated.
Definition: sc_insert_eq.c:101
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
Psysteme sc_free(Psysteme in_ps)
Psysteme sc_free( in_ps ) AL 30/05/94 Free of in_ps.
Definition: sc_list.c:112
#define ifdebug(n)
Definition: sg.c:47
Pbase base
Definition: sc-local.h:75
int dimension
Definition: sc-local.h:74
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
transformer transformer_convex_hull(transformer t1, transformer t2)
transformer transformer_convex_hull(t1, t2): compute convex hull for t1 and t2; t1 and t2 are slightl...
Definition: convex_hull.c:216
list one_to_one_transformers_combine(list tl1, list tl2)
Combine each transformer of transformer list tl1 with the corresponding transformer in transformer li...
Definition: transformer.c:476
transformer transformer_normalize(transformer t, int level)
Eliminate (some) rational or integer redundancy.
Definition: transformer.c:932
transformer safe_transformer_projection(transformer t, list args)
t may be undefined, args may contain values unrelated to t
Definition: transformer.c:1187
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455
list transformers_combine(list tl1, transformer t2)
Combine each transformer of transformer list tl1 with t2.
Definition: transformer.c:454
list transformers_apply(list tl, transformer pre)
Same as previous one, but with a more normalized name.
Definition: transformer.c:1616
transformer transformer_combine(volatile transformer t1, transformer t2)
transformer transformer_combine(transformer t1, transformer t2): compute the composition of transform...
Definition: transformer.c:238
transformer transformer_apply(transformer tf, transformer pre)
transformer transformer_apply(transformer tf, transformer pre): apply transformer tf on precondition ...
Definition: transformer.c:1559
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714
transformer transformer_intersection(transformer t1, transformer t2)
tf is a new transformer that receives the constraints in t1 and t2.
Definition: transformer.c:600
list transformers_apply_and_keep_all(list tl, transformer pre)
Same as previous one, but with a more normalized name.
Definition: transformer.c:1622
const char * external_value_name(entity)
Definition: value.c:753
bool old_value_entity_p(entity)
Definition: value.c:936
entity entity_to_intermediate_value(entity)
Definition: value.c:879
entity entity_to_new_value(entity)
Definition: value.c:859
entity make_local_temporary_integer_value_entity(void)
Definition: value.c:629
entity entity_to_old_value(entity)
Definition: value.c:869
entity value_to_variable(entity)
Get the primitive variable associated to any value involved in a transformer.
Definition: value.c:1624
list merge_transformer_lists(list tl1, list tl2)
Functions to deal with transformer lists.
static list transformer_list_add_combination(int tn, transformer ta[tn], int n, transformer ct, int past)
Internal recursive function.
list transformer_list_with_effect(list tl, entity v)
build a sublist sl of the transformer list tl with transformers that modify the value of variable v
list clean_up_transformer_list(list tfl)
Eliminate empty transformers and keep at most one identity transformer, placed as first list element.
transformer transformer_list_transitive_closure_plus(list tfl)
Compute (U tfl)+.
transformer transformer_list_closure_to_precondition(list tl, transformer c_t, transformer p_0)
Relay to select a heuristic.
transformer transformer_list_to_transformer(list ltl)
Reduce the transformer list ltl to one transformer using the convex hull operator.
static transformer transformer_list_closure_to_precondition_max_depth(list tl, transformer c_t, transformer p_0)
Compute the precondition of a loop whose body transformers T_i are in transformer list tl and whose c...
transformer generic_transformer_list_to_transformer(list ltl, bool active_p)
Reduce the transformer list with the convex hull operator.
static list __attribute__((unused))
compute all combinations of n different transformers t from transformer list tl.
list apply_transformer_lists_generic(list tl1, list tl2, bool exclude_p)
each transformer of tl1 must be applied to each precondition of tl2, including the identity transform...
transformer transformer_list_transitive_closure(list tfl)
Compute (U tfl)*.
transformer transformer_list_generic_transitive_closure(list tfl, bool star_p)
Computation of an upper approximation of a transitive closure using constraints on the discrete deriv...
transformer transformer_list_multiple_closure_to_precondition(list tl, transformer c_t, transformer p_0)
When some variables are not modified by some transformers, use projections on subsets to increase the...
list transformer_list_to_active_transformer_list(list tl)
bool check_transformer_list(list tl)
What do we want to impose?
static transformer transformer_list_closure_to_precondition_depth_two(list tl, transformer c_t, transformer p_0)
Compute the precondition of a loop whose body transformers T_i are in transformer list tl and whose c...
list apply_transformer_lists_with_exclusion(list tl1, list tl2)
list apply_transformer_lists(list tl1, list tl2)
list combine_transformer_lists(list tl1, list tl2)
each transformer of tl1 must be combined with a transformer of tl2, including the identity transforme...
list transformer_list_to_argument(list tl)
Returns the list of variables modified by at least one transformer in tl.
list transformer_list_preserved_variables(list vl, list tl, list tl_v)
returns the list of variables in vl which are not modified by transformers belonging to tl-tl_v.
Psysteme transformer_derivative_constraints(transformer t)
Allocate a new constraint system sc(dx) with dx=x'-x and t(x,x')
list transformer_list_safe_variables_projection(list tl, list proj)
Returns a new list of newly allocated projected transformers.
transformer active_transformer_list_to_transformer(list ltl)
Reduce the sublist of active transformers in the transformer list ltl to one transformer using the co...
list two_transformers_to_list(transformer t1, transformer t2)
Transformer two transformers into a correct transformer list.
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
#define base_rm(b)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
#define BASE_NULLE
MACROS SUR LES BASES.
#define BASE_NULLE_P(b)
Pvecteur vect_make(Pvecteur v, Variable var, Value val,...)
Pvecteur vect_make(v, [var, val,]* 0, val) Pvecteur v; // may be NULL, use assigne anyway Variable va...
Definition: alloc.c:165