PIPS
fix_point.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "misc.h"
#include "boolean.h"
#include "vecteur.h"
#include "contrainte.h"
#include "sc.h"
#include "ray_dte.h"
#include "sommet.h"
#include "sg.h"
#include "polyedre.h"
#include "matrice.h"
#include "transformer.h"
+ Include dependency graph for fix_point.c:

Go to the source code of this file.

Functions

transformer transformer_halbwachs_fix_point (transformer tf)
 
static void build_transfer_matrix (matrice *, Pcontrainte, int, Pbase)
 Must be declared explicity to keep a logical order in this C file. More...
 
transformer transformer_equality_fix_point (transformer tf)
 Let A be the affine loop transfert function. More...
 
void build_transfer_equations (Pcontrainte leq, Pcontrainte *plteq, Pbase *pb_new)
 
bool transfer_equation_p (Pvecteur eq)
 A transfer equation is an explicit equation giving one new value as a function of old values and a constant term. More...
 
entity new_value_in_transfer_equation (Pvecteur eq)
 
bool sub_basis_p (Pbase b1, Pbase b2)
 FI: should be moved in base.c. More...
 
void equations_to_bases (Pcontrainte lteq, Pbase *pb_new, Pbase *pb_old)
 
transformer transformer_pattern_fix_point (transformer tf)
 This fixpoint function was developped to present a talk at FORMA. More...
 
Pvecteur look_for_the_best_counter (Pcontrainte egs)
 Try to identify a loop counter among the equation egs. More...
 
Psysteme sc_eliminate_constant_terms (Psysteme sc, Pvecteur v)
 Eliminate all constant terms in sc using v. More...
 
Pcontrainte constraints_eliminate_constant_terms (Pcontrainte lc, Pvecteur v)
 
Psysteme sc_keep_invariants_only (Psysteme sc)
 This function cannot be moved into the Linear library. More...
 
Pcontrainte constraints_keep_invariants_only (Pcontrainte lc)
 
bool invariant_vector_p (Pvecteur v)
 A vector (in fact, a constraint) represents an invariant if it is a sum of delta for each variable. More...
 
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 which is not in sc's basis, and ik is added to the basis is necessary. More...
 
transformer transformer_derivative_fix_point (transformer tf)
 Computation of a transitive closure using constraints on the discrete derivative. More...
 
list transformers_derivative_fix_point (list tl)
 
transformer transformer_basic_fix_point (transformer tf)
 Computation of a fix point: drop all constraints, remember which variables are changed. More...
 
transformer any_transformer_to_k_closure (transformer t_init, transformer t_enter, transformer t_next, transformer t_body, transformer post_init, int k, bool assume_previous_iteration_p)
 Derived from any_loop_to_k_transformer() More...
 

Variables

transformer(* transformer_fix_point_operator )(transformer)
 transformer package - fix-point or transitive closure computations More...
 

Function Documentation

◆ any_transformer_to_k_closure()

transformer any_transformer_to_k_closure ( transformer  t_init,
transformer  t_enter,
transformer  t_next,
transformer  t_body,
transformer  post_init,
int  k,
bool  assume_previous_iteration_p 
)

Derived from any_loop_to_k_transformer()

The recursive computation of the loop transformer is not performed here.

Complete the body transformer with t_next (t_body is modified by side effects into t_fbody)

Compute the fix point

Compute t_body_star = t_init ; t_enter

and add the continuation condition, pre_iteration improved with knowledge about the body, npre_iteration. Note that pre_iteration would also provide correct results, although less accurate.

FI: this is a very strong normalization

obvious redundancy like 0<=x, x<=y, 0<=y is detected

Integer redundancy elimination is aso used and leads potentially to larger coefficients and ultimately to an accuracy reduction when a convex hull is performed.

Any transformer or other data structure to free?

Parameters
t_init_init
t_enter_enter
t_next_next
t_body_body
post_initost_init
assume_previous_iteration_pssume_previous_iteration_p

Definition at line 1304 of file fix_point.c.

1320 {
1321  transformer t_fbody = transformer_undefined; // t_body; t_next
1322  transformer t_fbody_star = transformer_undefined; // t_fbody*
1323  transformer t_body_star = transformer_undefined; // t_init ; t_enter ; tfbodystar
1324  transformer post_enter = transformer_apply(t_enter, post_init);
1325  transformer enter_condition = transformer_range(post_enter);
1326  transformer next_condition = transformer_range(t_next);
1327  transformer post_next = transformer_undefined;
1328  //transformer pre_iteration = transformer_convex_hull(enter_condition, next_condition);
1329  transformer npre_iteration = transformer_undefined;
1330  transformer post_loop_star = transformer_undefined;
1331  transformer post_loop_plus = transformer_undefined;
1332  transformer post_loop = transformer_undefined;
1333  transformer t_next_star = transformer_undefined;
1334  transformer t_fbody_k = transformer_undefined;
1335  int ck; // used to unroll k-1 times the loop body
1336 
1337  ifdebug(8) {
1338  fprintf(stderr, "t_init:\n");
1339  print_transformer(t_init);
1340  fprintf(stderr, "t_enter:\n");
1341  print_transformer(t_enter);
1342  fprintf(stderr, "t_next:\n");
1343  print_transformer(t_next);
1344  fprintf(stderr, "t_body:\n");
1345  print_transformer(t_body);
1346  fprintf(stderr, "post_init:\n");
1347  print_transformer(post_init);
1348  }
1349 
1350  if(assume_previous_iteration_p)
1351  t_body = transformer_intersect_range_with_domain(t_body);
1352 
1353  /* Complete the body transformer with t_next (t_body is modified by
1354  side effects into t_fbody) */
1355  t_fbody = transformer_combine(t_body, t_next);
1356 
1357  /* Compute the fix point */
1358  t_fbody_k = copy_transformer(t_fbody);
1359  for(ck=2; ck<=k; ck++)
1360  t_fbody_k = transformer_combine(t_fbody_k, t_fbody);
1361  t_fbody_star = (* transformer_fix_point_operator)(t_fbody_k);
1362  free_transformer(t_fbody_k);
1363 
1364  /* Compute t_body_star = t_init ; t_enter */
1365  t_body_star = transformer_combine(transformer_dup(t_init), t_enter);
1366  t_body_star = transformer_combine(t_body_star, t_fbody_star);
1367 
1368  /* and add the continuation condition, pre_iteration improved with
1369  knowledge about the body, npre_iteration. Note that pre_iteration
1370  would also provide correct results, although less accurate. */
1371  post_loop_star = transformer_apply(t_fbody_star, enter_condition);
1372  post_loop_plus = transformer_apply(t_fbody, post_loop_star);
1373  post_loop = transformer_range(post_loop_plus);
1374  npre_iteration = transformer_convex_hull(enter_condition, post_loop);
1375  if(k==2) { // Should be a loop over k
1376  transformer post_loop_plus_plus = transformer_apply(t_fbody, post_loop_plus);
1377  transformer old_npre_iteration = npre_iteration;
1378  post_loop = transformer_range(post_loop_plus_plus);
1379  npre_iteration = transformer_convex_hull(npre_iteration, post_loop);
1380  free_transformer(post_loop_plus_plus);
1381  free_transformer(old_npre_iteration);
1382  }
1383  t_body_star = transformer_combine(t_body_star, npre_iteration);
1384  /* FI: this is a very strong normalization
1385  *
1386  * obvious redundancy like 0<=x, x<=y, 0<=y is detected
1387  *
1388  * Integer redundancy elimination is aso used and leads potentially
1389  * to larger coefficients and ultimately to an accuracy reduction
1390  * when a convex hull is performed.
1391  */
1392  // FI: I remove it for the time being because it slows down PIPS a lot
1393  // according to measurements for NSAD2014, nested01-09.c
1394  // t_body_star = transformer_normalize(t_body_star, 0);
1395  // Not sufficient for the simple case in Semantics-New/do01
1396  // t_body_star = transformer_normalize(t_body_star, 2);
1397 
1398  /* Any transformer or other data structure to free? */
1399  //free_transformer(t_body); transformed into t_fbody
1400  free_transformer(t_fbody);
1401  free_transformer(t_fbody_star);
1402  free_transformer(post_next);
1403  //free_transformer(t_effects);
1404  free_transformer(post_enter);
1405  free_transformer(enter_condition);
1406  free_transformer(next_condition);
1407  free_transformer(npre_iteration);
1408  free_transformer(post_loop_star);
1409  free_transformer(post_loop_plus);
1410  free_transformer(post_loop);
1411  free_transformer(t_next_star);
1412 
1413  ifdebug(8) {
1414  fprintf(stderr, "t_body_star:\n");
1415  print_transformer(t_body_star);
1416  }
1417 
1418  return t_body_star;
1419 }
void free_transformer(transformer p)
Definition: ri.c:2616
transformer copy_transformer(transformer p)
TRANSFORMER.
Definition: ri.c:2613
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
#define print_transformer(t)
Definition: print.c:357
#define transformer_undefined
Definition: ri.h:2847
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define ifdebug(n)
Definition: sg.c:47
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
transformer transformer_intersect_range_with_domain(transformer tf)
When tf is used repeatedly in a loop, the range is part of the domain from iteration 2 to the end.
Definition: transformer.c:845
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

References copy_transformer(), fprintf(), free_transformer(), ifdebug, print_transformer, transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_intersect_range_with_domain(), transformer_range(), and transformer_undefined.

Referenced by any_loop_to_k_transformer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ build_transfer_equations()

void build_transfer_equations ( Pcontrainte  leq,
Pcontrainte plteq,
Pbase pb_new 
)

FI: this is the simplest version; It would be possible to build a larger set of transfer equations by adding indirect transfer equations using a new basis till the set is stable, and then by removing equations containing old values which are not defined, again till the result is stable

I guess that these new equations would not change the fix-point and/or the preconditions.

derive the new basis and the old basis

check that the old basis is included in the new basis (else no fix-point!)

Remove equations as long b_old is not included in b_new

could be avoided by using only lteq...

Parameters
leqeq
plteqlteq
pb_newb_new

Definition at line 433 of file fix_point.c.

436 {
438  Pbase b_new = BASE_NULLE;
439  Pbase b_old = BASE_NULLE;
440  Pbase b_diff = BASE_NULLE;
442 
443  ifdebug(8) {
444  pips_debug(8, "begin\ninput equations:\n");
445  egalites_fprint(stderr, leq, (char * (*)(Variable)) external_value_name);
446  }
447 
448  /* FI: this is the simplest version;
449  * It would be possible to build a larger set of transfer equations
450  * by adding indirect transfer equations using a new basis
451  * till the set is stable, and then by removing equations containing
452  * old values which are not defined, again till the result is stable
453  *
454  * I guess that these new equations would not change the fix-point
455  * and/or the preconditions.
456  */
457  for(eq = leq; !CONTRAINTE_UNDEFINED_P(eq); eq = eq->succ) {
460 
461  neq->succ = lteq;
462  lteq = neq;
463  }
464  }
465 
466  ifdebug(8) {
467  pips_debug(8, "preliminary transfer equations:\n");
468  egalites_fprint(stderr, lteq,
469  (char * (*)(Variable)) external_value_name);
470  }
471 
472  /* derive the new basis and the old basis */
473  equations_to_bases(lteq, &b_new, &b_old);
474 
475  /* check that the old basis is included in the new basis (else no
476  fix-point!) */
477  ifdebug(8) {
478  pips_debug(8, "old basis:\n");
479  base_fprint(stderr, b_old, (char * (*)(Variable)) external_value_name);
480  pips_debug(8, "new basis:\n");
481  base_fprint(stderr, b_new, (char * (*)(Variable)) external_value_name);
482  }
483 
484  /* Remove equations as long b_old is not included in b_new */
485  b_diff = base_difference(b_old, b_new);
486  while(!BASE_NULLE_P(b_diff)) {
489 
490  for(eq = lteq; !CONTRAINTE_UNDEFINED_P(eq); eq = next_eq) {
491  bool preserve = true;
493  for(t = contrainte_vecteur(eq);
494  !VECTEUR_UNDEFINED_P(t) && preserve;
495  t = t->succ) {
496  entity e = (entity) vecteur_var(t);
497 
498  preserve = base_contains_variable_p(b_diff, (Variable) e);
499  }
500  next_eq = eq->succ;
501  if(preserve) {
502  eq->succ = n_lteq;
503  n_lteq = eq;
504  }
505  else {
506  contrainte_rm(eq);
507  }
508  }
509  lteq = n_lteq; /* could be avoided by using only lteq... */
510  equations_to_bases(lteq, &b_new, &b_old);
511  b_diff = base_difference(b_old, b_new);
512  }
513 
514  ifdebug(8) {
515  pips_debug(8, "final transfer equations:\n");
516  egalites_fprint(stderr, lteq,
517  (char * (*)(Variable)) external_value_name);
518  pips_debug(8, "old basis:\n");
519  base_fprint(stderr, b_old, (char * (*)(Variable)) external_value_name);
520  pips_debug(8, "new basis:\n");
521  base_fprint(stderr, b_new, (char * (*)(Variable)) external_value_name);
522  }
523 
524  if(!sub_basis_p(b_old, b_new)) {
525  pips_internal_error("Old basis is too large");
526  }
527  base_rm(b_old);
528  b_old = BASE_UNDEFINED;
529  *plteq = lteq;
530  *pb_new = b_new;
531 
532  ifdebug(8) {
533  pips_debug(8, "results\ntransfer equations:\n");
534  egalites_fprint(stderr, lteq, (char * (*)(Variable)) external_value_name);
535  pips_debug(8, "results\ntransfer basis:\n");
536  base_fprint(stderr, b_new, (char * (*)(Variable)) external_value_name);
537  pips_debug(8, "end\n");
538  }
539 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
Pbase base_difference(Pbase b1, Pbase b2)
Pbase base_difference(Pbase b1, Pbase b2): allocate b; b = b1 - b2 – with the set meaning return b;.
Definition: base.c:621
bool base_contains_variable_p(Pbase b, Variable v)
bool base_contains_variable_p(Pbase b, Variable v): returns true if variable v is one of b's elements...
Definition: base.c:136
#define CONTRAINTE_UNDEFINED_P(c)
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
#define CONTRAINTE_UNDEFINED
#define contrainte_rm(c)
the standard xxx_rm does not return a value
Pcontrainte contrainte_dup(Pcontrainte c_in)
Pcontrainte contrainte_dup(Pcontrainte c_in): allocation d'une contrainte c_out prenant la valeur de ...
Definition: alloc.c:132
void egalites_fprint(FILE *, Pcontrainte, char *(*)(Variable))
bool transfer_equation_p(Pvecteur eq)
A transfer equation is an explicit equation giving one new value as a function of old values and a co...
Definition: fix_point.c:552
void equations_to_bases(Pcontrainte lteq, Pbase *pb_new, Pbase *pb_old)
Definition: fix_point.c:660
bool sub_basis_p(Pbase b1, Pbase b2)
FI: should be moved in base.c.
Definition: fix_point.c:648
void base_fprint(FILE *f, Pbase b, get_variable_name_t variable_name)
void base_fprint(FILE * f, Pbase b, char * (*variable_name)()): impression d'une base sur le fichier ...
Definition: io.c:342
#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_internal_error
Definition: misc-local.h:149
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
struct Scontrainte * succ
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
const char * external_value_name(entity)
Definition: value.c:753
#define vecteur_var(v)
#define VECTEUR_UNDEFINED
#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_UNDEFINED
#define BASE_NULLE
MACROS SUR LES BASES.
#define BASE_NULLE_P(b)
#define VECTEUR_UNDEFINED_P(v)

References base_contains_variable_p(), base_difference(), base_fprint(), BASE_NULLE, BASE_NULLE_P, base_rm, BASE_UNDEFINED, contrainte_dup(), contrainte_rm, CONTRAINTE_UNDEFINED, CONTRAINTE_UNDEFINED_P, contrainte_vecteur, egalites_fprint(), eq, equations_to_bases(), external_value_name(), ifdebug, pips_debug, pips_internal_error, sub_basis_p(), Scontrainte::succ, Svecteur::succ, transfer_equation_p(), VECTEUR_UNDEFINED, VECTEUR_UNDEFINED_P, and vecteur_var.

Referenced by transformer_equality_fix_point().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ build_transfer_matrix()

static void build_transfer_matrix ( matrice pa,
Pcontrainte  lteq,
int  n_eq,
Pbase  b_new 
)
static

Must be declared explicity to keep a logical order in this C file.

Also, the matrice type is now obsolete and should not appear in transformer.h. Hence buil_transfer_matrix() must be static.

add the homogeneous coordinate

Definition at line 601 of file fix_point.c.

605 {
606  matrice a = matrice_new(n_eq, n_eq);
608 
609  matrice_nulle(a, n_eq, n_eq);
610 
611  for(eq = lteq; !CONTRAINTE_UNDEFINED_P(eq); eq = eq->succ) {
614  int nv_rank = rank_of_variable(b_new, (Variable) nv);
615 
616  for( ; !VECTEUR_UNDEFINED_P(t); t = t->succ) {
617  entity e = (entity) vecteur_var(t);
618 
619  if( e != (entity) TCST ) {
620  if(new_value_entity_p(e)) {
621  pips_assert("Coefficient must be one",
623  }
624  else {
626  int ov_rank = rank_of_variable(b_new, (Variable) ov);
627  pips_debug(8, "nv_rank=%d, ov_rank=%d\n",
628  nv_rank, ov_rank);
629  ACCESS(a, n_eq, nv_rank, ov_rank) =
631  }
632  }
633  else {
634  ACCESS(a, n_eq, nv_rank, n_eq) =
636  }
637  }
638  }
639  /* add the homogeneous coordinate */
640  ACCESS(a, n_eq, n_eq, n_eq) = VALUE_ONE;
641 
642  *pa = a;
643 }
#define value_uminus(val)
unary operators on values
#define value_one_p(val)
#define VALUE_ONE
int rank_of_variable(Pbase base, Variable var)
this function returns the rank of the variable var in the base 0 encodes TCST, but I do not know why,...
Definition: base.c:497
entity new_value_in_transfer_equation(Pvecteur eq)
Definition: fix_point.c:570
#define ACCESS(matrix, column, i, j)
Macros d'acces aux elements d'une matrice.
Definition: matrice-local.h:86
#define matrice_new(n, m)
Allocation et desallocation d'une matrice.
Definition: matrice-local.h:77
Value * matrice
package matrice
Definition: matrice-local.h:71
void matrice_nulle(matrice Z, int n, int m)
void matrice_nulle(matrice Z, int n, int m): Initialisation de la matrice Z a la valeur matrice nulle
Definition: matrice.c:311
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
entity old_value_to_new_value(entity)
Definition: value.c:1698
bool new_value_entity_p(entity)
the following three functions are directly or indirectly relative to the current module and its value...
Definition: value.c:925
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)

References ACCESS, CONTRAINTE_UNDEFINED, CONTRAINTE_UNDEFINED_P, contrainte_vecteur, eq, matrice_new, matrice_nulle(), new_value_entity_p(), new_value_in_transfer_equation(), old_value_to_new_value(), pips_assert, pips_debug, rank_of_variable(), Scontrainte::succ, Svecteur::succ, TCST, VALUE_ONE, value_one_p, value_uminus, VECTEUR_UNDEFINED_P, vecteur_val, and vecteur_var.

Referenced by transformer_equality_fix_point().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ constraints_eliminate_constant_terms()

Pcontrainte constraints_eliminate_constant_terms ( Pcontrainte  lc,
Pvecteur  v 
)

cv may now be the null vector

Parameters
lcc

Definition at line 865 of file fix_point.c.

866 {
867  Value c1 = vect_coeff(TCST, v);
869 
870  if(c1==0) {
871  abort();
872  }
873 
874  for(cc = lc; !CONTRAINTE_UNDEFINED_P(cc); cc = contrainte_succ(cc)) {
875  Pvecteur cv = contrainte_vecteur(cc);
876  Value c2;
877 
878  if((c2 = vect_coeff(TCST, cv))!=0) {
879  cv = vect_multiply(cv, c1);
880  cv = vect_cl(cv, -c2, v);
881  }
882 
883  /* cv may now be the null vector */
884  contrainte_vecteur(cc) = cv;
885  }
886 
887  return lc;
888 }
int Value
#define contrainte_succ(c)
#define abort()
Definition: misc-local.h:53
Pvecteur vect_multiply(Pvecteur v, Value x)
Pvecteur vect_multiply(Pvecteur v, Value x): multiplication du vecteur v par le scalaire x,...
Definition: scalaires.c:123
Pvecteur vect_cl(Pvecteur v, Value lambda, Pvecteur u)
Definition: binaires.c:181
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228

References abort, contrainte_succ, CONTRAINTE_UNDEFINED, CONTRAINTE_UNDEFINED_P, contrainte_vecteur, TCST, vect_cl(), vect_coeff(), and vect_multiply().

Referenced by sc_eliminate_constant_terms().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ constraints_keep_invariants_only()

Pcontrainte constraints_keep_invariants_only ( Pcontrainte  lc)
Parameters
lcc

Definition at line 910 of file fix_point.c.

911 {
912  Pcontrainte cc;
913 
914  for(cc = lc; !CONTRAINTE_UNDEFINED_P(cc); cc = contrainte_succ(cc)) {
915  Pvecteur cv = contrainte_vecteur(cc);
916  if(!invariant_vector_p(cv)) {
917  vect_rm(cv);
919  }
920  }
921 
922  return lc;
923 }
bool invariant_vector_p(Pvecteur v)
A vector (in fact, a constraint) represents an invariant if it is a sum of delta for each variable.
Definition: fix_point.c:934
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78

References contrainte_succ, CONTRAINTE_UNDEFINED_P, contrainte_vecteur, invariant_vector_p(), vect_rm(), and VECTEUR_NUL.

Referenced by sc_keep_invariants_only().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ equations_to_bases()

void equations_to_bases ( Pcontrainte  lteq,
Pbase pb_new,
Pbase pb_old 
)
Parameters
lteqteq
pb_newb_new
pb_oldb_old

Definition at line 660 of file fix_point.c.

661 {
662  Pbase b_new = BASE_UNDEFINED;
663  Pbase b_old = BASE_UNDEFINED;
665 
666  for(eq = lteq; !CONTRAINTE_UNDEFINED_P(eq); eq = eq->succ) {
667  Pvecteur t;
668 
669  for(t=contrainte_vecteur(eq); !VECTEUR_UNDEFINED_P(t); t = t->succ) {
670  entity e = (entity) vecteur_var(t);
671 
672  if( e != (entity) TCST ) {
673  if(new_value_entity_p(e)) {
674  b_new = vect_add_variable(b_new, (Variable) e);
675  }
676  else {
677  b_old = vect_add_variable(b_old,
679  }
680  }
681  }
682  }
683 
684  *pb_new = b_new;
685  *pb_old = b_old;
686 }
Pbase vect_add_variable(Pbase b, Variable v)
package vecteur - routines sur les bases
Definition: base.c:61

References BASE_UNDEFINED, CONTRAINTE_UNDEFINED, CONTRAINTE_UNDEFINED_P, contrainte_vecteur, eq, new_value_entity_p(), old_value_to_new_value(), Scontrainte::succ, Svecteur::succ, TCST, vect_add_variable(), VECTEUR_UNDEFINED_P, and vecteur_var.

Referenced by build_transfer_equations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ invariant_vector_p()

bool invariant_vector_p ( Pvecteur  v)

A vector (in fact, a constraint) represents an invariant if it is a sum of delta for each variable.

Let di = i::new - i::old. If v = sigma (di) = 0, v can be used to build a loop invariant.

It is assumed that constant terms have been substituted earlier using a loop counter.

OK, you could argue for invariant = false, but this would not help my debugging!

if v_sum is non zero, you might try to bound it wrt the loop precondition?

Definition at line 934 of file fix_point.c.

935 {
936  bool invariant = true;
938  Pvecteur v_old = VECTEUR_NUL;
939  Pvecteur v_new = VECTEUR_NUL;
940  Pvecteur v_sum = VECTEUR_UNDEFINED;
941 
942  ifdebug(8) {
943  pips_debug(8, "begin for vector: ");
944  vect_fprint(stderr, v, (char * (*)(Variable)) external_value_name);
945  }
946 
947  for(cv=v; !VECTEUR_UNDEFINED_P(cv); cv = vecteur_succ(cv)) {
948  if(vecteur_var(cv)==TCST) {
949  /* OK, you could argue for invariant = false,
950  * but this would not help my debugging!
951  */
952  pips_internal_error("Constant term in a potential invariant vector!");
953  }
954  else {
955  entity e = (entity) vecteur_var(cv);
956  entity var = value_to_variable(e);
957 
958 
959  if(old_value_entity_p(e)) {
960  vect_add_elem(&v_old, (Variable) var, vecteur_val(cv));
961  }
962  else if(new_value_entity_p(e)) {
963  vect_add_elem(&v_new, (Variable) var, vecteur_val(cv));
964  }
965  else {
966  pips_internal_error("Non value entity %s in invariant vector",
967  entity_name(e));
968  }
969  }
970  }
971 
972  v_sum = vect_add(v_new, v_old);
973 
974  ifdebug(8) {
975  pips_debug(8, "vector v_new: ");
976  vect_fprint(stderr, v_new, (char * (*)(Variable)) external_value_name);
977  pips_debug(8, "vector v_old: ");
978  vect_fprint(stderr, v_old, (char * (*)(Variable)) external_value_name);
979  pips_debug(8, "vector v_sum: ");
980  vect_fprint(stderr, v_sum, (char * (*)(Variable)) external_value_name);
981  }
982 
983  if(VECTEUR_NUL_P(v_sum)) {
984  invariant = true;
985  }
986  else {
987  /* if v_sum is non zero, you might try to bound it
988  * wrt the loop precondition?
989  */
990  invariant = false;
991  vect_rm(v_sum);
992  }
993 
994  vect_rm(v_new);
995  vect_rm(v_old);
996 
997  pips_debug(8, "end invariant=%s\n",
998  bool_to_string(invariant));
999 
1000  return invariant;
1001 }
void vect_fprint(FILE *f, Pvecteur v, get_variable_name_t variable_name)
void vect_fprint(FILE * f, Pvecteur v, char * (*variable_name)()): impression d'un vecteur creux v su...
Definition: io.c:124
string bool_to_string(bool)
Definition: string.c:243
#define entity_name(x)
Definition: ri.h:2790
bool old_value_entity_p(entity)
Definition: value.c:936
entity value_to_variable(entity)
Get the primitive variable associated to any value involved in a transformer.
Definition: value.c:1624
#define vecteur_succ(v)
#define VECTEUR_NUL_P(v)
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72

References bool_to_string(), entity_name, external_value_name(), ifdebug, new_value_entity_p(), old_value_entity_p(), pips_debug, pips_internal_error, TCST, value_to_variable(), vect_add(), vect_add_elem(), vect_fprint(), vect_rm(), VECTEUR_NUL, VECTEUR_NUL_P, vecteur_succ, VECTEUR_UNDEFINED, VECTEUR_UNDEFINED_P, vecteur_val, and vecteur_var.

Referenced by constraints_keep_invariants_only().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ look_for_the_best_counter()

Pvecteur look_for_the_best_counter ( Pcontrainte  egs)

Try to identify a loop counter among the equation egs.

If the transformer has been build naively, a loop counter should have a transformer equation like i::new = i::old + K_i where K_i is a numerical constant.

Since the loop counter is later used to eliminate constant terms in other constraints, variable i with the minimal absolute value K_i shuold be chosen.

Parameters
egsgs

Definition at line 797 of file fix_point.c.

798 {
799  Pvecteur v_inc = VECTEUR_UNDEFINED;
801  int inc = 0;
802 
803  for(leq = egs;
805  leq = contrainte_succ(leq)) {
806 
807  Pvecteur v = contrainte_vecteur(leq);
808  int c_inc = 0;
809 
810  if(vect_size(v)==3) {
811  entity p_old_index = entity_undefined;
812  entity p_new_index = entity_undefined;
814  bool failed = false;
815  for(lv = v; !VECTEUR_UNDEFINED_P(lv) && !failed; lv = vecteur_succ(lv)) {
816  if(vecteur_var(lv) == TCST) {
817  c_inc = (int) vecteur_val(lv);
818  }
819  else if(old_value_entity_p((entity) vecteur_var(lv))) {
820  if(entity_undefined_p(p_old_index))
821  p_old_index = (entity) vecteur_var(lv);
822  else
823  failed = true;
824  }
825  else if(new_value_entity_p((entity) vecteur_var(lv))) {
826  if(entity_undefined_p(p_new_index))
827  p_new_index = (entity) vecteur_var(lv);
828  else
829  failed = true;
830  }
831  else {
832  pips_internal_error("Unexpected value entity %s",
834  }
835  }
836  if(!failed && value_to_variable(p_old_index) == value_to_variable(p_new_index)) {
837  if(ABS(c_inc) < ABS(inc) || c_inc == 1) {
838  inc = c_inc;
839  v_inc = v;
840  }
841  }
842  }
843  }
844 
845  return v_inc;
846 }
void const char const char const int
#define ABS(x)
was: #define value_mult(v,w) value_direct_multiply(v,w) #define value_product(v,w) value_direct_produ...
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761

References ABS, contrainte_succ, CONTRAINTE_UNDEFINED, CONTRAINTE_UNDEFINED_P, contrainte_vecteur, entity_local_name(), entity_undefined, entity_undefined_p, int, new_value_entity_p(), old_value_entity_p(), pips_internal_error, TCST, value_to_variable(), vect_size(), vecteur_succ, VECTEUR_UNDEFINED, VECTEUR_UNDEFINED_P, vecteur_val, and vecteur_var.

Referenced by transformer_pattern_fix_point().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ new_value_in_transfer_equation()

entity new_value_in_transfer_equation ( Pvecteur  eq)

for gcc

Parameters
eqq

Definition at line 570 of file fix_point.c.

571 {
572  Pvecteur t;
573  int n_new = 0;
574  Value coeff = VALUE_ZERO; /* for gcc */
575  entity new_value = entity_undefined;
576 
577  for(t=eq; !VECTEUR_UNDEFINED_P(t) && n_new <= 1; t = t->succ) {
578  entity e = (entity) vecteur_var(t);
579 
580  if( e != (entity) TCST && new_value_entity_p(e) &&
582  new_value = e;
583  coeff = vecteur_val(t);
584  n_new++;
585  }
586  }
587 
588  if(value_mone_p(coeff)) {
589  for(t=eq; !VECTEUR_UNDEFINED_P(t) && n_new <= 1; t = t->succ) {
591  }
592  }
593 
594  pips_assert("n_new==1", n_new==1);
595 
596  return new_value;
597 }
#define VALUE_ZERO
#define value_mone_p(val)
#define value_oppose(ref)

References entity_undefined, eq, new_value_entity_p(), pips_assert, Svecteur::succ, TCST, value_mone_p, value_one_p, value_oppose, VALUE_ZERO, VECTEUR_UNDEFINED_P, vecteur_val, and vecteur_var.

Referenced by build_transfer_matrix().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sc_eliminate_constant_terms()

Psysteme sc_eliminate_constant_terms ( Psysteme  sc,
Pvecteur  v 
)

Eliminate all constant terms in sc using v.

No sharing between sc and v is assumed as sc is updated!

This function should be located in Linear/sc

Parameters
scc

Definition at line 853 of file fix_point.c.

854 {
855  int cv = vect_coeff(TCST, v);
856 
857  assert(cv!=0);
858 
859  sc_egalites(sc) = constraints_eliminate_constant_terms(sc_egalites(sc), v);
860  sc_inegalites(sc) = constraints_eliminate_constant_terms(sc_inegalites(sc), v);
861 
862  return sc;
863 }
Pcontrainte constraints_eliminate_constant_terms(Pcontrainte lc, Pvecteur v)
Definition: fix_point.c:865
#define assert(ex)
Definition: newgen_assert.h:41

References assert, constraints_eliminate_constant_terms(), TCST, and vect_coeff().

Referenced by transformer_pattern_fix_point().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sc_keep_invariants_only()

Psysteme sc_keep_invariants_only ( Psysteme  sc)

This function cannot be moved into the Linear library.

It relies on the concepts of old and new values.

It could be improved by using an approximate initial fix-point to evaluate v_sum (see invariant_vector_p) and to degrade equations into inequalities or to relax inequalities.

For instance, p = p + a won't generate an invariant. However, if the lousy fix-point is sufficient to prove a >= 0, it is possible to derive p::new >= p::old. Or even better if a's value turns out to be known.

Parameters
scc

Definition at line 902 of file fix_point.c.

903 {
904  sc_egalites(sc) = constraints_keep_invariants_only(sc_egalites(sc));
905  sc_inegalites(sc) = constraints_keep_invariants_only(sc_inegalites(sc));
906  return sc;
907 }
Pcontrainte constraints_keep_invariants_only(Pcontrainte lc)
Definition: fix_point.c:910

References constraints_keep_invariants_only().

Referenced by transformer_pattern_fix_point().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sc_multiply_constant_terms()

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 which is not in sc's basis, and ik is added to the basis is necessary.

This possible only if ik is positive. Constraint ik>=0 is added if star_p is true because the function is used to compute T*. Else, contraint ik>=1 is added because the function is used to compute T+.

Also used in transformer_list.c

add constraint ik >= 0 to compute T*. Would be ik>=1 if T+ were sought.

Parameters
scc
ikk
star_ptar_p

Definition at line 1013 of file fix_point.c.

1014 {
1015  Pcontrainte c;
1016 
1017  pips_assert("sc is defined", !SC_UNDEFINED_P(sc));
1018  pips_assert("ik is not in sc's basis",
1019  !base_contains_variable_p(sc->base, ik));
1020 
1021  for(c = sc->egalites; !CONTRAINTE_UNDEFINED_P(c); c = c->succ) {
1022  Pvecteur v = c->vecteur;
1023  for(;!VECTEUR_NUL_P(v); v = v->succ) {
1024  Variable var = var_of(v);
1025  if(var==TCST) {
1026  var_of(v) = ik;
1027  break;
1028  }
1029  }
1030  }
1031 
1032  for(c = sc->inegalites; !CONTRAINTE_UNDEFINED_P(c); c = c->succ) {
1033  Pvecteur v = c->vecteur;
1034  for(;!VECTEUR_NUL_P(v); v = v->succ) {
1035  Variable var = var_of(v);
1036  if(var==TCST) {
1037  var_of(v) = ik;
1038  break;
1039  }
1040  }
1041  }
1042 
1043  /* add constraint ik >= 0 to compute T*. Would be ik>=1 if T+ were
1044  sought. */
1045  Pvecteur v = vect_new(ik, VALUE_MONE);
1046  if(!star_p) {
1047  // add the constant term for T+
1049  }
1050  c = contrainte_make(v);
1051  sc_add_inegalite(sc, c);
1052  base_add_dimension(&(sc->base), ik);
1053  sc->dimension++;
1054 
1055  return sc;
1056 }
#define VALUE_MONE
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
void sc_add_inegalite(Psysteme p, Pcontrainte i)
void sc_add_inegalite(Psysteme p, Pcontrainte i): macro ajoutant une inegalite i a un systeme p; la b...
Definition: sc_alloc.c:406
Pvecteur vecteur
Pcontrainte inegalites
Definition: sc-local.h:71
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
int dimension
Definition: sc-local.h:74
#define var_of(varval)
#define base_add_dimension(b, v)
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110

References Ssysteme::base, base_add_dimension, base_contains_variable_p(), contrainte_make(), CONTRAINTE_UNDEFINED_P, Ssysteme::dimension, Ssysteme::egalites, Ssysteme::inegalites, pips_assert, sc_add_inegalite(), Scontrainte::succ, Svecteur::succ, TCST, VALUE_MONE, VALUE_ONE, var_of, vect_add_elem(), vect_new(), Scontrainte::vecteur, and VECTEUR_NUL_P.

Referenced by transformer_derivative_fix_point(), and transformer_list_generic_transitive_closure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sub_basis_p()

bool sub_basis_p ( Pbase  b1,
Pbase  b2 
)

FI: should be moved in base.c.

sub_basis_p(Pbase b1, Pbase b2): check if b1 is included in b2

Parameters
b11
b22

Definition at line 648 of file fix_point.c.

649 {
650  bool is_a_sub_basis = true;
651  Pbase t;
652 
653  for(t=b1; !VECTEUR_UNDEFINED_P(t) && is_a_sub_basis; t = t->succ) {
654  is_a_sub_basis = base_contains_variable_p(b2, vecteur_var(t));
655  }
656 
657  return is_a_sub_basis;
658 }
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105

References b1, b2, base_contains_variable_p(), Svecteur::succ, VECTEUR_UNDEFINED_P, and vecteur_var.

Referenced by build_transfer_equations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transfer_equation_p()

bool transfer_equation_p ( Pvecteur  eq)

A transfer equation is an explicit equation giving one new value as a function of old values and a constant term.

Because we are using diophantine equations, the coefficient of the new value must one or minus one. We assume that the equation is reduced (i.e. gcd(coeffs) == 1).

FI: Non-unary coefficients may appear because equations were combined, for instance by a previous internal fix-point as in KINETI of mdg-fi.f (Perfect Club). Maybe, something could be done for these nested fix-points.

Parameters
eqq

Definition at line 552 of file fix_point.c.

553 {
554  Pvecteur t;
555  int n_new = 0;
556  Value coeff = VALUE_ZERO;
557 
558  for(t=eq; !VECTEUR_UNDEFINED_P(t) && n_new <= 1; t = t->succ) {
559  entity e = (entity) vecteur_var(t);
560 
561  if( e != (entity) TCST && new_value_entity_p(e)) {
562  coeff = vecteur_val(t);
563  n_new++;
564  }
565  }
566 
567  return (n_new==1) && (value_one_p(coeff) || value_mone_p(coeff));
568 }

References eq, new_value_entity_p(), Svecteur::succ, TCST, value_mone_p, value_one_p, VALUE_ZERO, VECTEUR_UNDEFINED_P, vecteur_val, and vecteur_var.

Referenced by build_transfer_equations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformer_basic_fix_point()

transformer transformer_basic_fix_point ( transformer  tf)

Computation of a fix point: drop all constraints, remember which variables are changed.

Except if the transformer is syntactically empty since its fix point is easy to compute. Without normalization, mathematically empty transformers are lost.

get rid of equalities and inequalities but keep the basis

Parameters
tff

Definition at line 1280 of file fix_point.c.

1281 {
1282  transformer fix_tf = copy_transformer(tf);
1283 
1284  if(!transformer_empty_p(tf)) {
1285  /* get rid of equalities and inequalities but keep the basis */
1287  Pcontrainte eq = sc_egalites(sc);
1288  Pcontrainte ineq = sc_inegalites(sc);
1290  contraintes_free(ineq);
1291  sc_egalites(sc) = CONTRAINTE_UNDEFINED;
1292  sc_inegalites(sc) = CONTRAINTE_UNDEFINED;
1293  sc_nbre_egalites(sc) = 0;
1294  sc_nbre_inegalites(sc) = 0;
1295  }
1296 
1297  return fix_tf;
1298 }
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
#define transformer_relation(x)
Definition: ri.h:2873
#define predicate_system(x)
Definition: ri.h:2069
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455

References CONTRAINTE_UNDEFINED, contraintes_free(), copy_transformer(), eq, predicate_system, transformer_empty_p(), and transformer_relation.

Referenced by select_fix_point_operator().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformer_derivative_fix_point()

transformer transformer_derivative_fix_point ( transformer  tf)

Computation of a transitive closure using constraints on the discrete derivative.

See http://www.cri.ensmp.fr/classement/doc/A-429.pdf

Implicit equations, n::new - n::old = 0, are not added. Instead, invariant constraints in tf are obtained by projection and added.

Intermediate values are used to encode the differences. For instance, i::int = i::new - i::old

I tried to use the standard procedure but arguments are not removed when the transformer tf is not feasible. Since we compute the * fix point and not the + fix point, the fix point is the identity.

sc is going to be modified and destroyed and eventually replaced in fix_tf

Do not handle variable which do not appear explicitly in constraints!

initial and final basis

basis vector

basis of difference vectors

Compute constraints with difference equations

Only generate difference equations if the old value is used

Project all variables but differences to get T'

Multiply the constant terms by the iteration number ik and add a positivity constraint for the iteration number ik and then eliminate the iteration number ik to get T*(dx).

Difference variables must substituted back to differences between old and new values.

Only generate difference equations if the old value is used

Project all difference variables

The full basis must be used again

Plug sc back into fix_tf

Add constraints about invariant variables. This could be avoided if implicit equalities were added before the derivative are processed: each invariant variable would generate an implicit null difference.

Such invariant constraints do not exist in general. We have them when array references are trusted.

This is wrong because we compute f* and not f+ and this is not true for the initial store.

What can be done instead is to refine fix_tf as :

dom(tf) U tf(fix_tf(dom(tf)))

But this fails because tf loops back to the beginning of the next iteration. Hence, the domain of tf implies two iterations instead of one. For instance, "i<n" becomes "i<=n-2" for a while loop such as "while(i<n) i++;".

So this refinement should be performed at a higher level where t_init and t_enter are know... so as to have:

dom_tf = transformer_range(t_enter(t_init)).

That's all!

Parameters
tff

Definition at line 1067 of file fix_point.c.

1068 {
1069  transformer fix_tf = transformer_dup(tf);
1070 
1071  ifdebug(8) {
1072  pips_debug(8, "Begin for transformer %p:\n", tf);
1074  }
1075 
1076  if(transformer_empty_p(tf)) {
1077  /* I tried to use the standard procedure but arguments are not removed
1078  when the transformer tf is not feasible. Since we compute the * fix
1079  point and not the + fix point, the fix point is the identity. */
1080  free_transformer(fix_tf);
1081  fix_tf = transformer_identity();
1082  }
1083  else {
1084  //transformer inv_tf = transformer_undefined; /* invariant constraints of tf */
1085  /* sc is going to be modified and destroyed and eventually
1086  replaced in fix_tf */
1088  /* Do not handle variable which do not appear explicitly in constraints! */
1089  Pbase b = sc_to_minimal_basis(sc);
1090  Pbase ib = base_dup(sc_base(sc)); /* initial and final basis */
1091  Pbase bv = BASE_NULLE; /* basis vector */
1092  Pbase diffb = BASE_NULLE; /* basis of difference vectors */
1093 
1094  /* Compute constraints with difference equations */
1095 
1096  for(bv = b; !BASE_NULLE_P(bv); bv = bv->succ) {
1097  entity oldv = (entity) vecteur_var(bv);
1098 
1099  /* Only generate difference equations if the old value is used */
1100  if(old_value_entity_p(oldv)) {
1101  entity var = value_to_variable(oldv);
1102  entity newv = entity_to_new_value(var);
1103  entity diffv = entity_to_intermediate_value(var);
1104  Pvecteur diff = VECTEUR_NUL;
1106 
1107  diff = vect_make(diff,
1108  (Variable) diffv, VALUE_ONE,
1109  (Variable) newv, VALUE_MONE,
1110  (Variable) oldv, VALUE_ONE,
1111  TCST, VALUE_ZERO);
1112 
1113  eq = contrainte_make(diff);
1114  sc = sc_equation_add(sc, eq);
1115  }
1116  }
1117 
1118  ifdebug(8) {
1119  pips_debug(8, "with difference equations=\n");
1120  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1121  }
1122 
1123  /* Project all variables but differences to get T' */
1124 
1125  sc = sc_projection_ofl_along_variables(sc, b);
1126 
1127  ifdebug(8) {
1128  pips_debug(8, "Non-homogeneous constraints on derivatives=\n");
1129  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1130  }
1131 
1132  /* Multiply the constant terms by the iteration number ik and add a
1133  positivity constraint for the iteration number ik and then
1134  eliminate the iteration number ik to get T*(dx). */
1136  //Psysteme sc_t_prime_k = sc_dup(sc);
1137  //sc_t_prime_k = sc_multiply_constant_terms(sc_t_prime_k, (Variable) ik);
1138  sc = sc_multiply_constant_terms(sc, (Variable) ik, true);
1139  //Psysteme sc_t_prime_star = sc_projection_ofl(sc_t_prime_k, (Variable) ik);
1140  sc = sc_projection_ofl(sc, (Variable) ik);
1141  sc->base = base_remove_variable(sc->base, (Variable) ik);
1142  sc->dimension--;
1143  // FI: I do not remember nor find how to get rid of local values...
1144  //sc_rm(sc);
1145  //sc = sc_t_prime_star;
1146 
1147  ifdebug(8) {
1148  pips_debug(8, "All invariants on derivatives=\n");
1149  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1150  }
1151 
1152  /* Difference variables must substituted back to differences
1153  * between old and new values.
1154  */
1155 
1156  for(bv = b; !BASE_NULLE_P(bv); bv = bv->succ) {
1157  entity oldv = (entity) vecteur_var(bv);
1158 
1159  /* Only generate difference equations if the old value is used */
1160  if(old_value_entity_p(oldv)) {
1161  entity var = value_to_variable(oldv);
1162  entity newv = entity_to_new_value(var);
1163  entity diffv = entity_to_intermediate_value(var);
1164  Pvecteur diff = VECTEUR_NUL;
1166 
1167  diff = vect_make(diff,
1168  (Variable) diffv, VALUE_ONE,
1169  (Variable) newv, VALUE_MONE,
1170  (Variable) oldv, VALUE_ONE,
1171  TCST, VALUE_ZERO);
1172 
1173  eq = contrainte_make(diff);
1174  sc = sc_equation_add(sc, eq);
1175  diffb = base_add_variable(diffb, (Variable) diffv);
1176  }
1177  }
1178 
1179  ifdebug(8) {
1180  pips_debug(8,
1181  "All invariants on derivatives with difference variables=\n");
1182  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1183  }
1184 
1185  /* Project all difference variables */
1186 
1187  sc = sc_projection_ofl_along_variables(sc, diffb);
1188 
1189  ifdebug(8) {
1190  pips_debug(8, "All invariants on differences=\n");
1191  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1192  }
1193 
1194  /* The full basis must be used again */
1195  base_rm(sc_base(sc)), sc_base(sc) = BASE_NULLE;
1196  sc_base(sc) = ib;
1197  sc_dimension(sc) = vect_size(ib);
1198  base_rm(b), b = BASE_NULLE;
1199 
1200  ifdebug(8) {
1201  pips_debug(8, "All invariants with proper basis =\n");
1202  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
1203  }
1204 
1205  /* Plug sc back into fix_tf */
1206  predicate_system(transformer_relation(fix_tf)) = sc;
1207 
1208  /* Add constraints about invariant variables. This could be avoided if
1209  implicit equalities were added before the derivative are processed:
1210  each invariant variable would generate an implicit null
1211  difference.
1212 
1213  Such invariant constraints do not exist in general. We have them when
1214  array references are trusted.
1215 
1216  This is wrong because we compute f* and not f+ and this is not true
1217  for the initial store.
1218 
1219  */
1220  /*
1221  inv_tf = transformer_arguments_projection(transformer_dup(tf));
1222  fix_tf = transformer_image_intersection(fix_tf, inv_tf);
1223  free_transformer(inv_tf);
1224  */
1225 
1226  /* What can be done instead is to refine fix_tf as :
1227  *
1228  * dom(tf) U tf(fix_tf(dom(tf)))
1229  *
1230  * But this fails because tf loops back to the beginning of the
1231  * next iteration. Hence, the domain of tf implies *two*
1232  * iterations instead of one. For instance, "i<n" becomes "i<=n-2"
1233  * for a while loop such as "while(i<n) i++;".
1234  *
1235  * So this refinement should be performed at a higher level where
1236  * t_init and t_enter are know... so as to have:
1237  *
1238  * dom_tf = transformer_range(t_enter(t_init)).
1239  */
1240  /*
1241  transformer dom_tf = transformer_to_domain(tf);
1242  transformer tf_plus = transformer_combine(copy_transformer(dom_tf), fix_tf);
1243  tf_plus = transformer_combine(tf_plus, tf);
1244  free_transformer(fix_tf);
1245  fix_tf = transformer_convex_hull(dom_tf, tf_plus);
1246  free_transformer(dom_tf);
1247  free_transformer(tf_plus);
1248  */
1249  }
1250  /* That's all! */
1251 
1252  ifdebug(8) {
1253  pips_debug(8, "fix-point fix_tf=\n");
1255  transformer_consistency_p(fix_tf);
1256  pips_debug(8, "end\n");
1257  }
1258 
1259  return fix_tf;
1260 }
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
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
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
transformer fprint_transformer(FILE *fd, transformer tf, get_variable_name_t value_name)
Definition: io.c:69
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_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
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
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
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
Pbase base_dup(Pbase b)
Pbase base_dup(Pbase b) Note: this function changes the value of the pointer.
Definition: alloc.c:268

References Ssysteme::base, base_add_variable(), base_dup(), BASE_NULLE, BASE_NULLE_P, base_remove_variable(), base_rm, contrainte_make(), CONTRAINTE_UNDEFINED, Ssysteme::dimension, entity_to_intermediate_value(), entity_to_new_value(), eq, external_value_name(), fprint_transformer(), free_transformer(), ifdebug, make_local_temporary_integer_value_entity(), old_value_entity_p(), pips_debug, predicate_system, sc_equation_add(), sc_fprint(), sc_multiply_constant_terms(), sc_to_minimal_basis(), Svecteur::succ, TCST, transformer_consistency_p(), transformer_dup(), transformer_empty_p(), transformer_identity(), transformer_relation, VALUE_MONE, VALUE_ONE, value_to_variable(), VALUE_ZERO, vect_make(), vect_size(), VECTEUR_NUL, and vecteur_var.

Referenced by invariant_wrt_transformer(), select_fix_point_operator(), and transformers_derivative_fix_point().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformer_equality_fix_point()

transformer transformer_equality_fix_point ( transformer  tf)

Let A be the affine loop transfert function.

The affine transfer fix-point T is such that T(A-I) = 0

T A = 0 also gives a fix-point when merged with the initial state. It can only be used to compute preconditions.

Algorithm (let H be A's Smith normal form):

A = A - I (if necessary) H = P A Q A = P^-1 H Q^-1 T A = T P^-1 H Q^-1 = 0 T P^-1 H = 0 (by multipliying by Q)

Soit X t.q. X H = 0 A basis for all solutions is given by X chosen such that X is a rectangular matrix (0 I) selecting the zero submatrix of H

T P^-1 = X T = X P

Note: I (FI) believe this functions is wrong because it does not return the appropriate arguments. The fix point transformer should modify as many variables as the input tf. A new basis should not be recomputed according to the transition matrix. This problem seems to be fixed in the callers, see loop_to_transformer() and whileloop_to_transformer().

result

do not modify an input argument

number of transfer equalities plus the homogeneous constraint which states that 1 == 1

use a matrix a to store these equalities in a dense form

Pbase t = BASE_UNDEFINED;

If the input transformer is not feasible, so is not its fixpoint because the number of iterations may be zero which implies identity.

fix_tf = transformer_identity();

find or build explicit transfer equations: v::new = f(v1::old, v2::old,...) and the corresponding sub-basis

FI: for each constant variable, whose constance is implictly implied by not having it in the argument field, an equation should be added...

lieq = build_implicit_equalities(tf); lieq->succ = leq; leq = lieq;

build matrix a from lteq and b_new: this should be moved in a function

Subtract the identity matrix

Compute the Smith normal form: H = P A Q

Find out the number of invariants n_inv

Convert p's last n_inv rows into constraints

FI: maybe I should retrieve fix_tf system...

is it a non-trivial invariant?

Set fix_tf's argument list

Fix the basis and the dimension

get rid of dense matrices

Parameters
tff

Definition at line 266 of file fix_point.c.

267 {
268  /* result */
270 
271  /* do not modify an input argument */
272  transformer tf_copy = transformer_dup(tf);
273 
274  /* number of transfer equalities plus the homogeneous constraint which
275  states that 1 == 1 */
276  int n_eq = 1;
277  /* use a matrix a to store these equalities in a dense form */
282  Pbase b_new = BASE_NULLE;
284  Pcontrainte leq = sc_egalites((Psysteme) predicate_system(transformer_relation(tf_copy)));
285 
286  Psysteme sc_inv = SC_UNDEFINED;
287  int n_inv = 0;
288 
289  int i = 0;
290  /* Pbase t = BASE_UNDEFINED; */
291 
292  ifdebug(8) {
293  pips_debug(8, "begin for transformer %p\n", tf);
294  fprint_transformer(stderr, tf,
296  }
297 
298  /* If the input transformer is not feasible, so is not its fixpoint
299  * because the number of iterations may be zero which implies identity.
300  */
301  if(transformer_empty_p(tf)) {
302  /* fix_tf = transformer_identity(); */
303  ifdebug(8) {
304  pips_debug(8, "fix-point fix_tf=\n");
305  fprint_transformer(stderr, fix_tf,
307  pips_debug(8, "end\n");
308  }
309  return fix_tf;
310  }
311 
312  /* find or build explicit transfer equations: v#new = f(v1#old, v2#old,...)
313  * and the corresponding sub-basis
314  *
315  * FI: for each constant variable, whose constance is implictly
316  * implied by not having it in the argument field, an equation
317  * should be added...
318  *
319  * lieq = build_implicit_equalities(tf);
320  * lieq->succ = leq;
321  * leq = lieq;
322  */
323  build_transfer_equations(leq, &lteq, &b_new);
324 
325  /* build matrix a from lteq and b_new: this should be moved in a function */
326  n_eq = base_dimension(b_new)+1;
327  build_transfer_matrix(&a , lteq, n_eq, b_new);
328  ifdebug(8) {
329  pips_debug(8, "transfer matrix:\n");
330  matrice_fprint(stderr, a, n_eq, n_eq);
331  }
332 
333  /* Subtract the identity matrix */
334  for(i=1; i<= n_eq; i++) {
335  value_substract(ACCESS(a, n_eq, i, i),VALUE_ONE);
336  }
337 
338  /* Compute the Smith normal form: H = P A Q */
339  h = matrice_new(n_eq, n_eq);
340  p = matrice_new(n_eq, n_eq);
341  q = matrice_new(n_eq, n_eq);
342  DENOMINATOR(h) = VALUE_ONE;
343  DENOMINATOR(p) = VALUE_ONE;
344  DENOMINATOR(q) = VALUE_ONE;
345  matrice_smith(a, n_eq, n_eq, p, h, q);
346 
347  ifdebug(8) {
348  pips_debug(8, "smith matrix h=p.a.q:\n");
349  matrice_fprint(stderr, h, n_eq, n_eq);
350  pips_debug(8, "p matrix:\n");
351  matrice_fprint(stderr, p, n_eq, n_eq);
352  pips_debug(8, "q matrix:\n");
353  matrice_fprint(stderr, q, n_eq, n_eq);
354  }
355 
356  /* Find out the number of invariants n_inv */
357  for(i=1; i <= n_eq &&
358  value_notzero_p(ACCESS(h, n_eq, i, i)) ; i++)
359  ;
360  n_inv = n_eq - i + 1;
361  pips_debug(8, "number of useful invariants: %d\n", n_inv-1);
362  pips_assert("n_inv>=1", n_inv >= 1);
363 
364  /* Convert p's last n_inv rows into constraints */
365  /* FI: maybe I should retrieve fix_tf system... */
366  sc_inv = sc_new();
367 
368  for(i = n_eq - n_inv + 1 ; i <= n_eq; i++) {
369  int j;
370  /* is it a non-trivial invariant? */
371  for(j=1; j<= n_eq-1 && value_zero_p(ACCESS(p, n_eq, i, j)); j++)
372  ;
373  if( j != n_eq) {
374  Pvecteur v_inv = VECTEUR_NUL;
376 
377  for(j = 1; j<= n_eq; j++) {
378  Value coeff = ACCESS(p, n_eq, i, j);
379 
380  if(value_notzero_p(coeff)) {
381  entity n_eb = (entity) variable_of_rank(b_new, j);
382  entity o_eb = new_value_to_old_value(n_eb);
383 
384  vect_add_elem(&v_inv, (Variable)n_eb, coeff);
385  vect_add_elem(&v_inv, (Variable)o_eb, value_uminus(coeff));
386  }
387  }
388  c_inv = contrainte_make(v_inv);
389  sc_add_egalite(sc_inv, c_inv);
390  }
391  }
392 
393  sc_creer_base(sc_inv);
394 
395  ifdebug(8) {
396  pips_debug(8, "fix-point sc_inv=\n");
397  sc_fprint(stderr, sc_inv, (char * (*)(Variable)) external_value_name);
398  pips_debug(8, "end\n");
399  }
400 
401  /* Set fix_tf's argument list */
402  /*
403  for(t = b_new; !BASE_NULLE_P(t); t = t->succ) {
404  I should use a conversion function from value_to_variable()
405  entity arg = (entity) vecteur_var(t);
406 
407  transformer_arguments(fix_tf) = arguments_add_entity(transformer_arguments(fix_tf), arg);
408  }
409  */
411  /* Fix the basis and the dimension */
412  sc_base(sc_inv) = base_dup(sc_base(predicate_system(transformer_relation(tf))));
413  sc_dimension(sc_inv) = sc_dimension(predicate_system(transformer_relation(tf)));
414  transformer_relation(fix_tf) = make_predicate(sc_inv);
415 
416  /* get rid of dense matrices */
417  matrice_free(a);
418  matrice_free(h);
419  matrice_free(p);
420  matrice_free(q);
421 
422  free_transformer(tf_copy);
423 
424  ifdebug(8) {
425  pips_debug(8, "fix-point fix_tf=\n");
427  pips_debug(8, "end\n");
428  }
429 
430  return fix_tf;
431 }
predicate make_predicate(Psysteme a1)
Definition: ri.c:1820
cons * dup_arguments(cons *args)
Definition: arguments.c:225
#define value_notzero_p(val)
#define value_zero_p(val)
#define value_substract(ref, val)
void build_transfer_equations(Pcontrainte leq, Pcontrainte *plteq, Pbase *pb_new)
Definition: fix_point.c:433
static void build_transfer_matrix(matrice *, Pcontrainte, int, Pbase)
Must be declared explicity to keep a logical order in this C file.
Definition: fix_point.c:601
#define DENOMINATOR(matrix)
int DENOMINATEUR(matrix): acces au denominateur global d'une matrice matrix La combinaison *(&()) est...
Definition: matrice-local.h:93
#define matrice_free(m)
Definition: matrice-local.h:78
#define MATRICE_UNDEFINED
Definition: matrice-local.h:73
void matrice_smith(matrice, int, int, matrice, matrice, matrice)
smith.c
Definition: smith.c:68
void matrice_fprint(FILE *, matrice, int, int)
matrice_io.c
Definition: matrice_io.c:62
#define transformer_arguments(x)
Definition: ri.h:2871
void sc_creer_base(Psysteme ps)
void sc_creer_base(Psysteme ps): initialisation des parametres dimension et base d'un systeme lineair...
Definition: sc_alloc.c:129
void sc_add_egalite(Psysteme p, Pcontrainte e)
void sc_add_egalite(Psysteme p, Pcontrainte e): macro ajoutant une egalite e a un systeme p; la base ...
Definition: sc_alloc.c:389
Psysteme sc_new(void)
Psysteme sc_new(): alloue un systeme vide, initialise tous les champs avec des valeurs nulles,...
Definition: sc_alloc.c:55
Variable variable_of_rank()
entity new_value_to_old_value(entity)
Definition: value.c:1710
#define base_dimension(b)

References ACCESS, base_dimension, base_dup(), BASE_NULLE, build_transfer_equations(), build_transfer_matrix(), contrainte_make(), CONTRAINTE_UNDEFINED, DENOMINATOR, dup_arguments(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, make_predicate(), matrice_fprint(), matrice_free, matrice_new, matrice_smith(), MATRICE_UNDEFINED, new_value_to_old_value(), pips_assert, pips_debug, predicate_system, sc_add_egalite(), sc_creer_base(), sc_fprint(), sc_new(), transformer_arguments, transformer_dup(), transformer_empty_p(), transformer_identity(), transformer_relation, value_notzero_p, VALUE_ONE, value_substract, value_uminus, value_zero_p, variable_of_rank(), vect_add_elem(), and VECTEUR_NUL.

Referenced by select_fix_point_operator(), and standard_whileloop_to_transformer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformer_halbwachs_fix_point()

transformer transformer_halbwachs_fix_point ( transformer  tf)

THIS FUNCTION WAS NEVER CORRECT AND HAS NOT BEEN REWRITTEN FOR THE NEW VALUE PACKAGE

simple fix-point for inductive variables: loop bounds are ignored

cons * args = effects_to_arguments(e);

tf1: transformer for one loop iteration

tf2: transformer for two loop iterations

tf12: transformer for one or two loop iterations

tf23: transformer for two or three loop iterations

tf_star: transformer for one, two, three,... loop iterations should be called tf_plus by I do not use the one_trip flag

preserve transformer of loop body s

temporarily commented out

duplicate tf1 because transformer_combine might not be able to use twice the same argument

input/output relation for one or two iteration of the loop

apply one iteration on tf12

fix-point

should be done again based on Chenikova

tf_star = transformer_fix_point(tf12, tf23);

free useless transformers

Parameters
tff

Definition at line 143 of file fix_point.c.

144 {
145  /* THIS FUNCTION WAS NEVER CORRECT AND HAS NOT BEEN REWRITTEN FOR
146  THE NEW VALUE PACKAGE */
147 
148  /* simple fix-point for inductive variables: loop bounds are
149  ignored */
150 
151  /* cons * args = effects_to_arguments(e); */
152  /* tf1: transformer for one loop iteration */
153  transformer tf1;
154  /* tf2: transformer for two loop iterations */
155  transformer tf2;
156  /* tf12: transformer for one or two loop iterations */
157  transformer tf12;
158  /* tf23: transformer for two or three loop iterations */
159  transformer tf23;
160  /* tf_star: transformer for one, two, three,... loop iterations
161  should be called tf_plus by I do not use the one_trip flag */
163 
164  pips_internal_error("not implemented");
165 
166  /* preserve transformer of loop body s */
167  /* temporarily commented out */
168  /*
169  tf1 = transformer_rename(transformer_dup(tf), args);
170  */
171  tf1 = transformer_dup(tf);
172 
173  ifdebug(8) {
174  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer",
175  "tf1 after renaming =");
176  (void) print_transformer(tf1);
177  }
178 
179  ifdebug(8) {
180  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer", "tf1 =");
181  (void) print_transformer(tf1);
182  }
183 
184  /* duplicate tf1 because transformer_combine might not be able
185  to use twice the same argument */
186  tf2 = transformer_dup(tf1);
187  tf2 = transformer_combine(tf2, tf1);
188 
189  ifdebug(8) {
190  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer", "tf2 =");
191  (void) print_transformer(tf2);
192  }
193 
194  /* input/output relation for one or two iteration of the loop */
195  tf12 = transformer_convex_hull(tf1, tf2);
196 
197  ifdebug(8) {
198  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer", "tf12 =");
199  (void) print_transformer(tf12);
200  }
201 
202  /* apply one iteration on tf12 */
203  tf23 = transformer_combine(tf12, tf1);
204 
205  ifdebug(8) {
206  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer", "tf23 =");
207  (void) print_transformer(tf23);
208  }
209 
210  /* fix-point */
211  /* should be done again based on Chenikova */
212  /* tf_star = transformer_fix_point(tf12, tf23); */
213 
214  ifdebug(8) {
215  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer", "tf_star =");
216  (void) print_transformer(tf_star);
217  }
218 
219  /* free useless transformers */
220  transformer_free(tf1);
221  transformer_free(tf2);
222  transformer_free(tf12);
223  transformer_free(tf23);
224 
225  tf = tf_star;
226 
227  return tf;
228 }
void transformer_free(transformer t)
Definition: basic.c:68

References fprintf(), ifdebug, pips_internal_error, print_transformer, transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_free(), and transformer_undefined.

Referenced by standard_whileloop_to_transformer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformer_pattern_fix_point()

transformer transformer_pattern_fix_point ( transformer  tf)

This fixpoint function was developped to present a talk at FORMA.

I used examples published by Pugh and I realized that the fixpoint constraints were obvious in the loop body transformer. You just had to identify them. This is not a clever algorithm. It certainly would not resist any messing up with the constraints, i.e. a change of basis. But it provides very good result for a class of applications.

Algorithm:

  1. Find a loop counter
  2. Use it to eliminate all constant terms
  3. Look for invariant constraints

Let d_i = i::new - i::old. An invariant constraint is a sum of d_i which is equal to zero or greater than zero. Such a constraint is its own fixpoint: if you combine it with itself after renaming i::new as i::int on one hand and i::old as i::int on the other, the global sum for and equation or its sign for an inequality is unchanged.

result

Look for the best loop counter: the smallest increment is chosen

eliminate sharing between v_inc and fix_sc

Replace constant terms in equalities and inequalities by loop counter differences

Remove all constraints to build the invariant transformer

Parameters
tff

Definition at line 709 of file fix_point.c.

710 {
711  /* result */
712  transformer fix_tf = transformer_dup(tf);
714  Pvecteur v_inc = VECTEUR_UNDEFINED;
715 
716  ifdebug(8) {
717  pips_debug(8, "Begin for transformer %p:\n", tf);
718  fprint_transformer(stderr, tf,
720  }
721 
722  /* Look for the best loop counter: the smallest increment is chosen */
723  v_inc = look_for_the_best_counter(sc_egalites(fix_sc));
724 
725  if(!VECTEUR_UNDEFINED_P(v_inc)) {
726 
727  ifdebug(8) {
728  pips_debug(8, "incrementation vector=\n");
729  vect_fprint(stderr, v_inc, (char * (*)(Variable)) external_value_name);
730  }
731 
732  /* eliminate sharing between v_inc and fix_sc */
733  v_inc = vect_dup(v_inc);
734 
735  /* Replace constant terms in equalities and inequalities by
736  * loop counter differences
737  */
738  fix_sc = sc_eliminate_constant_terms(fix_sc, v_inc);
739 
740  ifdebug(8) {
741  pips_debug(8, "after constant term elimination=\n");
742  sc_fprint(stderr, fix_sc, (char * (*)(Variable)) external_value_name);
743  }
744 
745  fix_sc = sc_elim_redund(fix_sc);
746 
747  ifdebug(8) {
748  pips_debug(8, "after normalization=\n");
749  sc_fprint(stderr, fix_sc, (char * (*)(Variable)) external_value_name);
750  }
751 
752  fix_sc = sc_keep_invariants_only(fix_sc);
753 
754  ifdebug(8) {
755  pips_debug(8, "after non-invariant elimination=\n");
756  sc_fprint(stderr, fix_sc, (char * (*)(Variable)) external_value_name);
757  }
758 
759  fix_sc = sc_elim_redund(fix_sc);
760 
761  ifdebug(8) {
762  pips_debug(8, "after 2nd normalization=\n");
763  sc_fprint(stderr, fix_sc, (char * (*)(Variable)) external_value_name);
764  }
765  }
766  else {
767  pips_debug(8, "No counter found\n");
768  /* Remove all constraints to build the invariant transformer */
769  contraintes_free(sc_egalites(fix_sc));
770  sc_egalites(fix_sc) = CONTRAINTE_UNDEFINED;
771  sc_nbre_egalites(fix_sc) = 0;
772  contraintes_free(sc_inegalites(fix_sc));
773  sc_inegalites(fix_sc) = CONTRAINTE_UNDEFINED;
774  sc_nbre_inegalites(fix_sc) = 0;
775  }
776 
777  ifdebug(8) {
778  pips_debug(8, "fix-point fix_tf=\n");
780  pips_debug(8, "end\n");
781  }
782 
783  return fix_tf;
784 }
Pvecteur look_for_the_best_counter(Pcontrainte egs)
Try to identify a loop counter among the equation egs.
Definition: fix_point.c:797
Psysteme sc_keep_invariants_only(Psysteme sc)
This function cannot be moved into the Linear library.
Definition: fix_point.c:902
Psysteme sc_eliminate_constant_terms(Psysteme sc, Pvecteur v)
Eliminate all constant terms in sc using v.
Definition: fix_point.c:853
struct Ssysteme * Psysteme
Psysteme sc_elim_redund(Psysteme ps)
Psysteme sc_elim_redund(Psysteme ps): elimination des contraintes lineaires redondantes dans le syste...
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51

References CONTRAINTE_UNDEFINED, contraintes_free(), external_value_name(), fprint_transformer(), ifdebug, look_for_the_best_counter(), pips_debug, predicate_system, sc_elim_redund(), sc_eliminate_constant_terms(), sc_fprint(), sc_keep_invariants_only(), transformer_dup(), transformer_relation, vect_dup(), vect_fprint(), VECTEUR_UNDEFINED, and VECTEUR_UNDEFINED_P.

Referenced by select_fix_point_operator().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ transformers_derivative_fix_point()

list transformers_derivative_fix_point ( list  tl)
Parameters
tll

Definition at line 1262 of file fix_point.c.

1263 {
1264  list ntl = NIL;
1265  FOREACH(TRANSFORMER, tf, tl) {
1267  ntl = CONS(TRANSFORMER, fix_tf, ntl);
1268  }
1269  ntl = gen_nreverse(ntl);
1270  return ntl;
1271 }
transformer transformer_derivative_fix_point(transformer tf)
Computation of a transitive closure using constraints on the discrete derivative.
Definition: fix_point.c:1067
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#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 TRANSFORMER(x)
TRANSFORMER.
Definition: ri.h:2841
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References CONS, FOREACH, gen_nreverse(), NIL, TRANSFORMER, and transformer_derivative_fix_point().

Referenced by transformer_list_closure_to_precondition_depth_two(), and transformer_list_closure_to_precondition_max_depth().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ transformer_fix_point_operator

transformer(* transformer_fix_point_operator) (transformer) ( transformer  )

transformer package - fix-point or transitive closure computations

fix_point.c

Interface between the untyped database manager and clean code and between pipsmake and clean code.

Several algorithms are available:

  • two untested versions using Halwachs approach; sc_elarg() was found to be very slow in an earlier implementation by Malik; experimentally, we did not find scientific Frotran programs that required such an algorithm.
  • a fix point algorithm based on the transfer matrix linking the new values to the old values; this is sufficient for induction variables but only equations can be found.
  • a fix point algorithm based on pattern matching which was developped experimentally for examples presented at FORMA; once the constant terms are eliminated using a loop counter, the constraints which are their own fixpoints are easy to pattern match; equations and inequalities can both be found.
  • a fix point algorithm combining the last two algorithms above. This algorithm adds difference variables d_i = i::new - i::old for each variable i. All non d_i variables are thn projected. If the projection algorithm is sophisticated enough, the projection ordering will be "good". Left over inequalities are invariant or useless. Let N be the strictly positive iteration count:

    sum ai di <= -k implies N sum ai di <= -Nk <= -k (OK)

    sum ai di <= k implies N sum ai di <= Nk <= infinity (useless unless k == 0)

    Left over equations can stay equations if the constant term is 0, or be degraded into an inequation if not. The nw inequation depends on the sign of the constant:

    sum ai di == -k implies N sum ai di == -Nk <= -k

    sum ai di == k implies N sum ai di == Nk >= k

    sum ai di == 0 implies N sum ai di == 0

    In a second step, the constant terms are eliminated to obtain new constraints leading to new invariants, using the same rules as above.

    This algorithm was designed for while loops such as:

    WHILE( I > 0 ) J = J + I I = I - 1

    to find as loop transformer T(I,J) {I::new <= I::old - 1, J::new >= J::old + 1, I::new+J::new >= I::old + J::old}

    Note that the second constraint is redundant with the other two, but the last one cannot be found before the constant terms are eliminated.

The current algorithm, the derivative version, is published and describes in NSAD 2010, A/426/CRI. See also A/429/CRI: http://www.cri.ensmp.fr/classement/doc/A-429.pdf

Francois Irigoin, 21 April 1990 The fixpoint operator is selected according to properties

Definition at line 114 of file fix_point.c.

Referenced by select_fix_point_operator(), and standard_whileloop_to_transformer().